Over the past few years, the number of Azure AD administrative roles has nearly doubled as new roles have been added to support workloads such as Microsoft Teams, Flow and PowerApps, Kaizala, etc. Another group of roles has been made available to address scenarios where certain functionality required the highly privileged Global administrator role. Removing the dependencies on Global admins is of course a good thing, but the increased number of roles also has its downsides. Just keeping track of what a given role allows a user to do can be a challenge, even when looking at the detailed documentation Microsoft publishes. Overall, a total of 56 different roles exist now in Azure AD (58 if we count the default “User” and “Guest” ones). The Office 365 Admin Center lists 34 of those.
Keeping track of privileged roles assignments in your organization is of course a must, but having to go over each of the roles manually, either via the Azure AD Roles and administrators blade or the newly introduced Roles tab in the Office 365 Admin Center can be time consuming and frankly, quite annoying. Instead, one can use a programmatic method, such as the cmdlets exposed via the MSOnline or the Azure AD PowerShell modules. Here’s a quick example of doing this via the MSOnline module:
We use the Get-MsolRole cmdlet to list all admin roles in the tenant, then for each of the roles we invoke the Get-MsolRoleMember cmdlet to get the assigned users or service principals. In a fresh demo tenant, the resulting output is a list of 5 users, each assigned the Company administrator role. You cannot actually see the role from the above output, which illustrates that simple one-liners might not be sufficient to address this issue. So, let’s look into building a more comprehensive solution.
We will use the Azure AD PowerShell module, which offers two benefits. First, the Get-AzureADDirectoryRole cmdlet only returns a list of “activated” roles, so instead of cycling against all 56 admin roles, we immediately get a list of just the ones that are in use in the tenant. Second, the output of the Get-AzureADDirectoryRoleMember cmdlet returns the full object, meaning we can get all its properties right away. In contrast, the Get-MsolRoleMember cmdlet returns a set of only 10 properties, which might not include all the information you want to expose in the report.
The script itself will simply call the Get-AzureADDirectoryRoleMember cmdlet against each of the “activated” roles and report the assigned objects. Some added logic handles the list of properties included in the output, as well as ensures that objects with multiple role assignments are reported only once. Lastly, the script outputs the report to the console and optionally saves it to a CSV file. Here’s a sample output from a tenant that has some non-user objects with role assignments, as well as users with multiple roles:
As mentioned above, service principal objects can also be assigned to any of the admin roles and this is what we see on the first line in the above output. The GUID returned in the UserPrincipalName column corresponds to the applicationID of the service principal object, which you can then look up to get additional information about the application, it’s owner and purpose. If needed, you can expose other attributes as well by modifying the corresponding section of the script. Speaking of which, you can get your copy of the script from the TechNet Gallery or GitHub.
Now, it’s very important to understand that this script only covers Azure AD admin roles. Apart from these, there are numerous workload-specific roles that can be granted across Office 365, such as the Exchange Online Roles and assignments, Roles in the Security and Compliance Center, site collection permissions in SharePoint Online, and so on. Just because a given user doesn’t appear in the admin role report, it doesn’t mean that he cannot have other permissions granted! We will be addressing some of those in the next article in the series.
In addition, one should make sure to cover any applications that have been granted permissions to execute operations against your tenant. Such permissions can range from being able to read directory data to full access to user’s messages and files, so it’s very important to keep track on them. We published an article that can get you started with a sample script a while back.
If the user does appear in the report generated with the above script, make sure to protect his account with Azure MFA and/or additional controls enforced via Conditional Access. The recently announced baseline policies are a good start, although they do not cover all admin roles. In addition, you are strongly encouraged to consider evaluating and enabling Privileged Access Management so that you can minimize the number of users with standing access to admin roles. Make sure to also utilize workload-specific controls where possible, such as the authentication policies for Exchange Online or the Privileged Access Management feature, both of which we have already covered on our blog over at practical365.com.