Get-MgAuditLogSignIn – Office 365 for IT Pros https://office365itpros.com Mastering Office 365 and Microsoft 365 Sat, 24 Aug 2024 11:37:09 +0000 en-US hourly 1 https://i0.wp.com/office365itpros.com/wp-content/uploads/2024/06/cropped-Office-365-for-IT-Pros-2025-Edition-500-px.jpg?fit=32%2C32&ssl=1 Get-MgAuditLogSignIn – Office 365 for IT Pros https://office365itpros.com 32 32 150103932 Finding Non-Compliant Shared Mailboxes https://office365itpros.com/2024/08/26/shared-mailbox-signin/?utm_source=rss&utm_medium=rss&utm_campaign=shared-mailbox-signin https://office365itpros.com/2024/08/26/shared-mailbox-signin/#comments Mon, 26 Aug 2024 07:00:00 +0000 https://office365itpros.com/?p=66097

Identify Problematic Shared Mailboxes using Sign-in Logs

Exchange Online shared mailboxes have Entra ID accounts. The accounts have passwords and people can sign-into the account and start a mail client that’s connected to the shared mailbox to process email. Is this a problem? Absolutely!

Shared mailboxes don’t require Exchange Online or any other licenses unless the mailboxes have an archive, need more than 50 GB quota, use litigation hold, or are subject to Purview retention policies. As stated in the Microsoft service description:

To access a shared mailbox, a user must have an Exchange Online license, but the shared mailbox doesn’t require a separate license.”

No Need Exists to Sign Into Shared Mailboxes

Shared mailboxes are intended for joint access by multiple users whose connections are controlled by permissions managed by Exchange Online. Full Access permission allows a user full control over all mailbox folders and items while Send As or Send on Behalf Of allows them to send email from the mailbox. No need exists to sign into the Entra ID accounts for shared mailboxes, and if you sign into an unlicensed shared mailbox, you violate Microsoft licensing terms.

One reason I have heard advanced to justify signing into a shared mailbox is after someone leaves the organization and their mailbox is converted to a shared mailbox. If the mailbox includes some information that’s important to the organization, another user might need to sign into the mailbox to retrieve the data. I don’t buy this logic. Granting Full Access permission to the mailbox is sufficient to review the items stored there. I prefer to use inactive mailboxes to preserve ex-employee content instead. It’s just a cleaner solution.

Microsoft documentation says:

“A shared mailbox is a type of user mailbox that doesn’t have its own username and password. As a result, users can’t log into them directly.”

This is factually incorrect. Every shared mailbox has an ExternalDirectoryObjectId property that points to its Entra ID account. This PowerShell snippet uses the property to report the user principal names for the accounts:

$Mbx = Get-ExoMailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited | Sort-Object DisplayName
ForEach ($M in $Mbx) {
    $User = Get-MgUser -UserId $M.ExternalDirectoryObjectId
    Write-Output ("Mailbox {0} has Entra ID account {1}" -f $M.DisplayName, $User.UserPrincipalName)
}
Mailbox Admin-RA-Shared has Entra ID account admin-ra-shared@office365itpros.com
Mailbox Azure Management Account has Entra ID account Azure.Management.Account@office365itpros.com

Changing the password and enabling the accounts to allow users to sign into the accounts is easy. If you don’t want to use PowerShell, you can select the account in the Microsoft 365 admin center and perform the actions there (Figure 1).

Figure 1: Unblocking a shared mailbox account in the Microsoft 365 admin center

Checking for Illegal Shared Mailboxes

Life isn’t perfect and people make mistakes. It’s possible that a tenant has some shared mailboxes that fall in a technically illegal state because people sign into the mailbox instead of connecting using mailbox permissions. To detect these situations, we can use the Get-MgAuditLogSignIn cmdlet to check if any sign-in records exist for the mailbox accounts. The account running the script must have an Entra ID P1 license to access the audit log records.

To illustrate the point, I wrote a script (downloadable from GitHub) to find shared mailboxes and check if they’ve been signed into. If so, a further check establishes if the mailbox’s account is licensed with Exchange Online Plan 1 or Plan 2. The output is shown in Figure 2.

Reporting Shared mailbox sign-in detections
Figure 2: Reporting mailbox sign-ins

Fortunately, the two mailboxes with detected sign-in records both have Exchange Online Plan 2 licenses, so they’re in compliance.

Other Checks

Microsoft doesn’t check shared mailboxes where other license requirements arise, like those with archive mailboxes or those on litigation hold. If you want to scan for those conditions, the necessary code is covered in this article. It wouldn’t take much to combine the two scripts to have one script that checks everything. I’ll leave that as an exercise for the reader.


Learn more about how the Office 365 applications really work on an ongoing basis by subscribing to the Office 365 for IT Pros eBook. Our monthly updates keep subscribers informed about what’s important across the Office 365 ecosystem.

]]>
https://office365itpros.com/2024/08/26/shared-mailbox-signin/feed/ 2 66097
How to Block User Access to Microsoft 365 PowerShell Modules https://office365itpros.com/2023/10/12/block-powershell-m365/?utm_source=rss&utm_medium=rss&utm_campaign=block-powershell-m365 https://office365itpros.com/2023/10/12/block-powershell-m365/#comments Thu, 12 Oct 2023 01:00:00 +0000 https://office365itpros.com/?p=61922

Use Enterprise Applications to Block PowerShell Modules

A question arose about the best way to block Microsoft 365 user accounts from being able to run PowerShell. It seemed like a worthy problem to consider. In some cases an obvious answer exists, like stopping Exchange Online users from accessing PowerShell, but that’s a technique that only works for Exchange, and the block needs to be imposed for every new mailbox. We need something more generic that works across Microsoft 365.

Microsoft documents a process to block access to PowerShell for EDU tenants. The script to block PowerShell uses cmdlets from the Azure AD module, which Microsoft is deprecating with retirement scheduled for March 30, 2024. A replacement script using Microsoft Graph PowerShell SDK cmdlets is needed. Fortunately, I’ve been down this path with an article covering secure access to the SDK and can reuse many of the concepts explained there.

Update August 23, 2024: Microsoft now documents how to use the EXOModuleEnabled setting for accounts to control access to Exchange Online PowerShell. The technique described here works for other PowerShell modules.

Key Steps to Block PowerShell Modules

Every application that authenticates against Entra ID is known to the directory. Some applications are created within a tenant (registered apps). Others are created by companies like Microsoft as multi-tenant applications that can run anywhere. These are enterprise applications. The PowerShell modules that connect to Microsoft 365 endpoints like Exchange or Teams authenticate using enterprise applications created by Microsoft. The Microsoft Graph PowerShell SDK is the most obvious of these applications, but other applications exist for the Exchange Online management module, SharePoint Online management module, and the Microsoft Teams module.

Most administrators are unaware that these PowerShell enterprise applications exist. The applications don’t show up in the Entra ID admin center because normally they do not have a service principal. Applications use service principals to store permissions, like the Graph permissions used by the Microsoft Graph PowerShell SDK. Applications without service principals use roles instead.

For instance, when you run the Connect-ExchangeOnline cmdlet to connect to Exchange Online, the ability to work with Exchange data is gated by the roles possessed by the signed-in user account. If the account holds the Exchange administrator or Global administrator role, they can manage all aspects of Exchange Online (this also applies to Azure Automation accounts). If not, they can manage their own mailbox.

The key steps to restrict access to a PowerShell module are:

  • Find the application identifier for the module. We’ll get to doing that in a minute.
  • Create a service principal for the application.
  • Update the service principal so that it uses application role assignments.
  • Create a security group to manage assignments of permission to use the module.
  • Add the security group as an assignment to the service principal.

Finding Application Identifiers for PowerShell Modules

The first step is to find the application identifiers. The easiest way to do this is to check the Entra ID sign-in logs for events when people connect using a PowerShell module. Figure 1 shows an example of a sign-in event logged when an administrator connected with the SharePoint Online management module. We can see that the application identifier is 9bc3ab49-b65d-410a-85ad-de819febfddc.

Finding the application identifier for a PowerShell module from an Entra ID sign-in event

Block PowerShell access
Figure 1: Finding the application identifier for a PowerShell module from an Entra ID sign-in event

Application identifiers for other modules include:

  • Exchange Online management: fb78d390-0c51-40cd-8e17-fdbfab77341b (covers both regular Exchange and the compliance endpoint).
  • Microsoft Teams: 12128f48-ec9e-42f0-b203-ea49fb6af367
  • Azure: 1950a258-227b-4e31-a9cf-717495945fc2
  • Microsoft Graph PowerShell SDK: 14d82eec-204b-4c2f-b7e8-296a70dab67e

Example: Block Access to Exchange Online PowerShell

Now that we know the application identifiers, we can go ahead and create the service principal for the modules to block. Here are the PowerShell commands to connect an interactive Graph session and create a block for Exchange Online:

# Connect to the Grph
Connect-MgGraph -Scopes Directory.ReadWrite.All, Group.ReadWrite.All, Application.ReadWrite.All

# Create security group to control access to Exchange Online PowerShell
$Group = New-MgGroup -DisplayName "Allow access to EXO PowerShell" -MailEnabled:$False -SecurityEnabled:$True -MailNickName 'EXO.PowerShell'

# Create the service principal for the Exchange Online PowerShell app
$ServicePrincipal = New-MgServicePrincipal -Appid 'fb78d390-0c51-40cd-8e17-fdbfab77341b'

# Check that the Service Principal exists
Get-MgServicePrincipal -ServicePrincipalId $ServicePrincipal.Id | Format-Table DisplayName, Id, AppId

DisplayName                                  Id                                   AppId
-----------                                  --                                   -----
Microsoft Exchange REST API Based PowerShell 8d32ebd2-7295-4236-a3da-7c45be69a0b3 fb78d390-0c51-40cd-8e17-fdbfab77341b

# Update the Service Principal so that it requires application role assignments
Update-MgServicePrincipal -ServicePrincipalId $ServicePrincipal.Id -AppRoleAssignmentRequired:$True

# Add the security group as an assignment to the service principal
New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $ServicePrincipal.Id -AppRoleId ([Guid]::Empty.ToString()) -ResourceId $ServicePrincipal.Id -PrincipalId $Group.Id

After running these commands, no one can run the Connect-ExchangeOnline cmdlet to connect to Exchange unless they are added to the security group (Figure 2).

Members of the security group permitted to run Exchange Online PowerShell
Figure 2: Members of the security group permitted to run Exchange Online PowerShell

Entra ID rejects connection attempts from unauthorized accounts with an AADSTS50105 error (Figure 3). The “Microsoft Exchange REST API Based PowerShell” name is assigned to the enterprise application by Microsoft.

Error when attempting to run the Exchange Online PowerShell module
Figure 3: Error when attempting to run the Exchange Online PowerShell module

Discovering Who Accesses PowerShell

Often it’s simple to know who should be allowed to be members of the security group controlling access to a module. The tenant administrator, any administrators for a workload (like Teams service administrators), break glass accounts, service accounts such as those used by Azure Automation, and so on. But to be definite, we should review the Entra ID sign-in logs to see who uses a module.

This command retrieves the last 5,000 sign-in records and filters them for any sign-in for the Exchange Online application:

[array]$AuditRecords = Get-MgAuditLogSignIn -Top 5000 -Sort "createdDateTime DESC" -Filter "AppId eq 'fb78d390-0c51-40cd-8e17-fdbfab77341b'"

A simple Group-Object command gives the answer:

$AuditRecords | Group-Object UserPrincipalName -NoElement | Sort-Object Count -Descending| Select-Object Name, Count

Name                               Count
----                               -----
tony.redmond@office365itpros.com      10
EXOAdmin@office365itpros.com           7
James.Atkinson@office365itpros.com     3

You can then decide if any or all of the people who have accessed the module should be added to the security group. To check another module, replace the application identifier in the Get-MgAuditLogSignIn command.

Should My Tenant Block PowerShell?

The factors driving the decision to block PowerShell access for user accounts will differ from organization to organization. At least now you know the best way to block the most common PowerShell modules used with Microsoft 365 and how to find out who’s using the modules.


Support the work of the Office 365 for IT Pros team by subscribing to the Office 365 for IT Pros eBook. Your support pays for the time we need to track, analyze, and document the changing world of Microsoft 365 and Office 365.

]]>
https://office365itpros.com/2023/10/12/block-powershell-m365/feed/ 16 61922
Track User Access to Teams Shared Channels with Entra ID Sign-In Logs https://office365itpros.com/2022/03/31/teams-shared-channels-access/?utm_source=rss&utm_medium=rss&utm_campaign=teams-shared-channels-access https://office365itpros.com/2022/03/31/teams-shared-channels-access/#comments Thu, 31 Mar 2022 01:00:00 +0000 https://office365itpros.com/?p=54326

Know Who’s Collaborating in Teams Shared Channels From Outside Your Tenant

Updated 4 March 2024

When Microsoft launched Teams shared channels into public preview (according to MC390413, shared channels will GA in mid-July 2022) the rubber hit the road as tenant administrators tried to figure out the complexities of managing shared channels in production use. It’s true that Microsoft conducted a long private preview with many customers to get shared channels to the point where they squashed obvious bugs and delivered usable software. However, once software is exposed to the kind of examination that an application with 270 million monthly active users can create, other questions bubble to the surface.

Which brings me to the topic of controlling user access to shared channels. The cross-tenant access settings in the External identities section of the Entra admin center control which tenants your organization can access using Entra ID B2B Direct Connect. This is the underlying authentication mechanism for Teams shared channels. It allows users to authenticate in their home tenant and use that authentication, including MFA and device state claims, to access resources in other tenants, if permitted by other tenants.

Entra ID Sign-Ins Track Cross-Tenant Access

Microsoft’s guidance for cross-tenant access settings advises that you can use Entra ID sign in logs to figure out user access to other tenants. It’s true that you can use the PowerShell snippet provided there, but I think we can do better.

The code uses the Get-MgBetaAuditLogSignIn cmdlet from the Microsoft Graph PowerShell SDK to look for sign in records where the resource tenant identifier (the organization delivering a resource like Teams) is not the same as the home tenant identifier (the organization hosting the sign in logs).

$TenantId = (Get-MgOrganization).Id
Get-MgBetaAuditLogSignIn -Filter "ResourceTenantId ne '$TenantId'" -All:$True

The code works (the All switch doesn’t need $True), but the result of the query is a set of sign-in records for both Entra ID B2B Collaboration (guest accounts) and Entra ID B2B Direct Connect. This is a better filter if you want to focus on access to Teams shared channels:

Get-MgBetaAuditLogSignIn -Filter "ResourceTenantId ne '$TenantId' and CrossTenantAccessType eq 'b2bDirectConnect'" -All

Next, although you might recognize the identifier for your tenant, it’s unlikely that you’ll know the identifiers for other tenants (like 22e90715-3da6-4a78-9ec6-b3282389492b). To translate these identifiers into human-friendly tenant names, we need another method.

We’re already connected to the Microsoft Graph, so we can use a Graph query to resolve the identifier into a tenant name.

Finding Tenant Names

Fortunately, a beta query called findTenantInformationByTenantId does the trick. There’s little documentation available, but by running it through the Invoke-MgGraphRequest cmdlet (runs any Graph query when an SDK cmdlet is unavailable), we can retrieve tenant data:

$ExternalTenantId = $Record.ResourceTenantId
$Uri = "https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByTenantId(tenantId='$ExternalTenantId')"
$ExternalTenantData = Invoke-MgGraphRequest -Uri $Uri -Method Get

The tenant information returned is:

Name                           Value
----                           -----
@odata.context                 https://graph.microsoft.com/beta/$metadata#microsoft.graph.tenantInformation
tenantId                       22e90715-3da6-4a78-9ec6-b3282389492b
displayName                    o365maestros
federationBrandName
defaultDomainName              o365maestros.onmicrosoft.com

I assume this web site, which can return the identifier of any Microsoft 365 tenant, uses a similar API.

Flow of the Script

The flow of the PowerShell script to analyze sign-in data is therefore:

  • Find sign-in records for Entra ID Direct Connect activity. If you want to process records for Azure B2B Collaboration, change the filter to remove the check against the CrossTenantAccessType property.
  • Extract data from each record, including resolving external tenant identifiers to tenant names.
  • Report.

In normal circumstances, the sign-in data will feature just a few tenants. It would be slow to run a query to resolve the tenant identifier for every record. To ensure performance, the script resolves a tenant name the first time it is encountered and stores the tenant name identifier and name in a hash table. When the script processes subsequent records for the same tenant, it reads the information from the hash table.

You can download the script from GitHub. Normal warnings apply: use at your peril, etc. and please fix my bugs…

Script Outputs

The output of the script is a PowerShell list containing details of sign-ins which use cross-tenant access to connect to Teams shared channels in external tenants (Figure 1).

Viewing information about user connects to Teams shared channels
Figure 1: Viewing information about user connects to Teams shared channels

The data can be parsed to reveal statistics like which tenants use cross-tenant access:

$Report | Group TenantName | Sort Count -Descending | Format-Table Name, Count

Or to reveal the names of the users who connect to external tenants:

$Report | Group User | Sort Count -Descending | Format-Table Name, Count

Name       Count
----       -----
Sean Landy     4
James Ryan     3
Ken Bowers     3

And so on. I’m sure you’ll find other ways to use the information to track what’s happening with Teams shared channels. The point is that the data is there if you need it. All that’s required is a little massaging of the information.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

]]>
https://office365itpros.com/2022/03/31/teams-shared-channels-access/feed/ 10 54326
Creating an Authentication Method Report for Entra IAccounts https://office365itpros.com/2022/03/03/azure-ad-accounts-authentication/?utm_source=rss&utm_medium=rss&utm_campaign=azure-ad-accounts-authentication https://office365itpros.com/2022/03/03/azure-ad-accounts-authentication/#comments Thu, 03 Mar 2022 01:00:00 +0000 https://office365itpros.com/?p=53754

Moving from Old Modules to the Microsoft Graph SDK for PowerShell

Update: This article describes a script to generate a report showing the MFA status for accounts and highlights administrative accounts that aren’t MFA-enabled.

Microsoft 365 tenants often create reports to understand the health of their Azure AD accounts. In June 2021, Microsoft announced that they are moving away from the Microsoft Online Services (MSOL) and Azure AD PowerShell modules and would deprecate the Azure AD Graph API at the end of June 2022. Customer feedback convinced Microsoft to push the deprecation date out to the end of 2022, and then to March 2024. However, the writing is on the wall for the Azure AD Graph API and it’s time to move to Graph-based interfaces.

Their future focus for PowerShell access to Entra ID data is the Microsoft Graph SDK for PowerShell. The only definite drop-dead date affecting the older modules is June 30, 2022, when Microsoft moves to a new license management platform. At this point, any cmdlet which retrieves license information for user accounts will cease working. Any scripts used for tenant license management that haven’t been updated now require urgent attention.

I have an MFA status script written in 2018. The script uses the MSOL cmdlets to check and report the “strong authentication methods” for each user account. The state of multi-factor authentication has moved on since 2018 to accommodate new methods like FIDO2 keys and passwordless authentication. These methods aren’t handled by the MSOL cmdlets. It’s therefore time to take a different approach.

Given Microsoft’s direction to use the Microsoft Graph SDK for PowerShell for Azure AD access, it seems like this is the right path to follow. I’ve done a reasonable amount with the SDK and have written several articles to report my progress. For example, here’s how to generate a licensing report for a tenant.

Not a Perfect SDK

The SDK is not perfect. Essentially, its cmdlets are wrappers around Graph API queries. If you’re used to dealing with Graph APIs, the SDK cmdlets will be second nature. If not, it will take time to become familiar.

Getting acquainted isn’t helped by the poor state of the documentation for the SDK cmdlets. Microsoft uses automatic text generation tools to create the documentation from source code. The result is often as useful as a snowball in a desert, especially in terms of practical examples and explanations about inputs. Again, if you know the Graph APIs, you probably won’t be surprised at what you find in the documentation, but the current state of the documentation is no credit to Microsoft and a barrier to adoption.

Steps in the Creation of the Report

The aim is to create a report showing the authentication methods used by Azure AD accounts and highlight accounts which might attention (hopefully, by enabling multi-factor authentication). According to a recent Microsoft report, only 22% of Microsoft 365 accounts use multi-factor authentication. Although this marks an improvement over the past, it’s still far too low a percentage. Perhaps people don’t know about recent improvements Microsoft has made in MFA processing to make it easier for people to use.

The script I wrote to create the report does the following:

  • Connects to the Graph endpoint with the following permissions: UserAuthenticationMethod.Read.All, Directory.Read.All, User.Read.All, Auditlog.Read.All. If the service principal for the SDK doesn’t have administrat9or consent of any permission, it must be granted at this point.
  • Set the Graph profile to beta to make sure that we have access to all the user account data.
  • Call the Get-MgUser cmdlet to fetch the set of Azure AD member accounts. The set returned excludes guest accounts but includes the accounts used for shared and resource mailboxes. To focus solely on licensed member accounts, you could apply a filter to look for accounts with at least one assigned license.
  • Loop through each account to check its authentication methods. To ensure that only active accounts are checked, the script calls the Get-MgAuditLogSignIn cmdlet to look for a sign-in record. This check can only go back 30 days.
  • For each active account, call the Get-MgUserAuthenticationMethod cmdlet to return the authentication methods used by the account. An account can use all the valid authentication methods from passwordless to the Microsoft authenticator app. The first time an account uses a method, Azure AD adds it to the list used by the account.
  • For each method, retrieve some information.
  • Report the results of checking each method.
  • After processing all user accounts, create a list of users for which an authentication method is available and check each account to see if one of the strong (MFA) methods is noted.
  • Create a final report and output it to a CSV file.

Figure 1 shows an example of the kind of output generated.

Azure AD Accounts and authentication methods
Figure 1: Authentication methods report for Azure AD accounts

You can download the script from GitHub. As always, the code is intended to illustrate a principal rather than being a fully-baked solution.

Automating the Check

A script like this is a good candidate for execution by an Azure Automation runbook. It can be run on a schedule and the results emailed to administrators for action. Getting a weekly or monthly reminder to improve the security posture of the organization by increasing the percentage of well-protected accounts can only be a good thing, can’t it?


Learn how to exploit the data available to Microsoft 365 tenant administrators through the Office 365 for IT Pros eBook. We love figuring out how things work.

]]>
https://office365itpros.com/2022/03/03/azure-ad-accounts-authentication/feed/ 9 53754