Continuing the Journey to Explore the SDK
Recently, I’ve been looking at how to use the Microsoft Graph SDK for PowerShell. As you might recall, the SDK cmdlets essentially act as wrappers around Graph API calls. Microsoft’s hope is that the SDK will make it easier for developers and administrators to embrace and use the Graph through familiar PowerShell.
So far, I’ve explored the practical aspects of using the SDK by explaining how to remove individual service plans from Office 365 licenses, how to create a licensing report for a tenant, and how to send email from Exchange Online. I’ve also pointed out some considerations administrators and developers should understand when using the SDK. In this article, we’ll look at accessing Azure AD sign-in information. Specifically, how to report the last sign-in for accounts.
Why Review Account Sign-in Data
Azure AD sign-in data is available for the last 30 days. You can access the data interactively through the Azure AD admin center, where you can filter the data and download whatever you want (in CSV or JSON format). The data is also available through the Get-AzureADAuditSignInLogs cmdlet.
Why pay any attention to sign-in data? For tenant accounts, the lack of any sign-in activity might point to unused accounts which might hold valuable licenses. There are good reasons why an account might be inactive for a period, such as extended leave. Even so, it’s good to know if accounts are inactive.
Guest accounts don’t generate any cost for a tenant unless you use premium Azure AD features like conditional access or dynamic Microsoft 365 groups. The older method of licensing operates on the basis that the tenant needs to buy premium licenses based on a 1:5 ratio (five guests for each Azure AD premium license. Since September 2020, Microsoft has advocated a newer monthly active user (MAU) model where tenants pay only if they exceed a 50,000 monthly active user threshold for premium features.
Even if guest accounts don’t incur a big licensing overhead, that’s no reason to ignore guest account sign-ins. For instance, it’s good to know if any guest accounts come from competitor domains or other organizations that you’d prefer not to share information with (an Azure B2B collaboration policy can stop people adding new guest accounts for blacklisted domains).
Coding a Report
The script (downloadable from GitHub) is straightforward. Here are the major steps:
- Connect to the Microsoft Graph, specifying that the Auditlog.Read.All permission is required. If the service principal for the SDK doesn’t already have consent for this permission, it prompts to receive administrative approval.
- Find all accounts using the Get-MgUser cmdlet.
- For each account, use the Get-MgAuditLogSignIn cmdlet to see if we can retrieve the most recent sign-in record. Some applications (like Teams) generate many sign-in records over a day. We’re only interested in knowing the last time an account signed in, so use the Top parameter to specify that the Graph should return 1 record. Given that the Graph returns the most recent data first, the first record is the latest.
- Extract information for reporting from the sign-in data, including calculating the number of days since the last sign-in.
- Report what’s been found and generate a CSV file containing the results. Also display the data using Out-GridView (Figure 1).
A Usable SDK
In this instance, switching from Azure AD to SDK cmdlets doesn’t pose any great challenge, and the experience of working with SDK cmdlets as documented in this series of articles show that the SDK is more than usable. Any issues that exist with the Microsoft Graph SDK for PowerShell are in other areas, like the poor documentation and permissions creep for the service principal if scripts are run interactively. Documentation will improve over time, and you can run Graph-based scripts in the background using certificate-based authentication.
The point is that the Graph SDK is a project still in the early stages of development. It will get better as Microsoft removes the rough edges. For now, developers might prefer to call Graph APIs direct without using the SDK. In a year’s time, who knows?