How to Report Membership of Microsoft 365 Compliance Role Groups

The Looming End for the Security and Compliance Center

A reader asked how to create a report of the membership of Microsoft 365 role groups. Although this sounds like a straightforward question, the answer is complex. Here’s why.

Originally, compliance functionality was workload-based. Exchange Online had its own features as did SharePoint Online. In 2016, Microsoft introduced the Office 365 Security and Compliance Center (SCC) to bring together functionality which applied across all workloads. Permissions for the SCC follow the Exchange Online Role-Based Access Control (RBAC) model. Users receive permissions to perform actions through membership of role groups. If your account is a member of the right role group, you can perform a compliance action, like running a content search or managing an eDiscovery case. If it’s not, you won’t see the options to perform those actions displayed in the SCC.

Here’s where the situation becomes complicated. We are in the middle of a transition from the SCC to the Microsoft 365 compliance center, which Microsoft launched in 2018. Three years and a lot of confusion later, an April 15 blog post warns that Microsoft will soon start to redirect users automatically from the SCC to the Microsoft 365 compliance center. Message center notification MC256030 posted on May 12 confirms that a new permissions management page in the Microsoft 365 compliance center will make role management easier (Microsoft 365 roadmap item 72239).

New Permissions Management Page

The new permissions page in the Microsoft 365 compliance center
Figure 1: The new permissions page in the Microsoft 365 compliance center

The new permissions management page (Figure 1) allows management for both Azure AD roles and compliance center roles (more correctly, role groups). The differences between the two are:

  • Azure AD roles allow performance of directory-related tasks. The full set of Azure AD roles is visible by running the Get-AzureADDirectoryRole cmdlet or through the Roles and administrators section of the Azure AD admin center. Azure AD roles support advanced role management functionality like Privileged Identity Management to assign roles to users for limited periods.
  • Compliance center role groups allow performance of compliance tasks like eDiscovery. Each role group contains one or more roles, which is how accounts gain permission. The 43 compliance role groups (my tenant has 44 because I created a specific role group to handle certain processing) have no other function except to control access to different compliance features. The SCC was the previous location to manage these roles. To update the set of users who receive permissions through membership of a compliance role group, an account must be a global administrator or assigned the Role Management role (a role assigned only to the Organization Management role group).

The permission management page shows Azure AD roles used to performance compliance tasks. Currently, the page lists nine Azure AD roles like compliance administrator and compliance data administrator. Other Azure AD roles like Teams Administrator don’t appear because they are not associated with compliance management.

Reporting Who Holds Compliance Roles

Returning to the original question of how to generate a report about the holders of different compliance roles, the answer depends on if you want to report the membership of compliance role groups or Azure AD roles. Given that more functionality is governed by the latter type at present, the following code is a solution.

The steps to create the report are:

  • Uses the Connect-IPPSSession cmdlet (in the Exchange Online management module) to connect to the Compliance endpoint. You’ll need to use a tenant administrator account or one holding the compliance Organization Management role.
  • Fetches the list of known role groups.
  • Parses the set of members for each role group by converting the odd values used to represent members Exchange Hosted Organizations/ into mailbox display names (the last part of the name is the Azure AD object identifier for the account).
  • Writes details out into a PowerShell list and displays the results using the Out-GridView cmdlet.

Here’s the code:


$RoleGroups = Get-RoleGroup
$Report = [System.Collections.Generic.List[Object]]::new()
ForEach ($RoleGroup in $RoleGroups) {
    $Members = $RoleGroup.Members
    $MemberNames = [System.Collections.Generic.List[Object]]::new()

    ForEach ($Member in $Members) {
       $MemberName = (Get-ExoMailbox -Identity $Member.SubString(($Member.IndexOf("")+16),36) -Erroraction SilentlyContinue).DisplayName 
    $MemberNames = $MemberNames -join ", "

    $ReportLine = [PSCustomObject][Ordered]@{  
       "Role Group"           = $RoleGroup.DisplayName 
       "Members"              = $MemberNames
       "Last Updated"         = Get-Date($RoleGroup.WhenChanged)   }
} #End ForEach $RoleGroup

$Report | Sort "Role Group" | Out-GridView

Figure 2 shows what the report looks like. A simple Export-CSV command will write the details out to a CSV file if you want to manipulate the data in Excel.

Reporting membership of compliance role groups
Figure 2: Reporting membership of compliance role groups

The same approach works to create a report for the Azure AD roles. In this case, you use the Get-AzureADDirectoryRole cmdlet to find the set of roles and Get-AzureADDirectoryRoleMember cmdlet to process each role (here’s an example of using these cmdlets to report on Microsoft 365 admin accounts which aren’t protected by multi-factor authentication).

$RoleGroups = Get-AzureADDirectoryRole
$Report = [System.Collections.Generic.List[Object]]::new()
ForEach ($RoleGroup in $RoleGroups) {
  $Members = Get-AzureADDirectoryRoleMember -ObjectId $RoleGroup.ObjectId | Select -ExpandProperty DisplayName
  $MemberNames = $Members -join (", ")

  $ReportLine = [PSCustomObject][Ordered]@{  
       "Role Group"          = $RoleGroup.DisplayName 
       "Members"             = $MemberNames
       "Description"         = $RoleGroup.Description  }
} #End ForEach $RoleGroup
$Report | Sort "Role Group" | Out-GridView

Simple questions often have complex answers. In this case, it’s a matter of deciding what kind of role holders you want to report. Once you know that, the PowerShell to generate the report is relatively straightforward.

Learn lots more about how different parts of Office 365 work by subscribing to the Office 365 for IT Pros eBook. We go where other writing teams don’t, and we keep our book refreshed with monthly updates.

15 Replies to “How to Report Membership of Microsoft 365 Compliance Role Groups”

  1. the first script does not work fine , in the “$MemberName = (Get-ExoMailbox -Identity $Member.SubString(($Member.IndexOf(“”)+16),36) -Erroraction SilentlyContinue).DisplayName ” can’t make the subsrick

    1. obviously something doesn’t work as well as it did in my environment when it’s in your environment, so it’s an opportunity to debug. Did you check what the $Member variable contained?

  2. Hey Tony,

    Stupid question, how can i connect both Connect-IPPSession and Connect-ExchangeOnline Cmdlets? Are you saying if run your script it will connect both of them at the same time? I have not had much luck getting Connect-IppSession to work in conjunction with any other modules.


    1. Run Connect-ExchangeOnline to connect to the Exchange Online management endpoint, and then run Connect-IPPSsession to connect to the compliance endpoint. You’ll then be able to use the Exchange Online and compliance cmdlets.

      1. Hey Tony, I will give that a try. But i swear i did that at least 3xs. Maybe just the wrong order.


  3. It ran successfully. But it doesnt report for example my admin user account which is part of the Compliance Administrator group (In the security and compliance center). I also tried using Get-ExoRecipient which seemed to work better but didnt quite get the job done.

      1. Hey Tony,

        A fair point. I was able to work around it by using Get-Recipient. That seemed to work better. It sometimes shows system.object[0] but when checking that seems only to occur for blank spaces in the repport line (For example, username1, , username2) shows the system object value.

        but the data is correct.


  4. For some reason the output does not seem to match the membership displayed in the Compliance center.

  5. Hi, Tony, and thanks for the code.

    It worked fine a couple of times, but now I’m facing an exception for the “SubString” method, at the command:

    $MemberName = (Get-ExoMailbox -Identity $Member.SubString(($Member.IndexOf(“”)+16),36) -Erroraction SilentlyContinue).DisplayName

    Error is:

    Exception calling “Substring” with “2” argument(s): “startIndex cannot be larger than length of string.
    Parameter name: startIndex”

    I tried to change the values for the command $Member.IndexOf…. but I can’t get through.
    I also changed the command into this below, not having the error but with useless results (empty Roles column and “SystemObject[]” in the Members column)

    $MemberName = (Get-ExoMailbox -Identity $Member.SubString(0,($Member.lenght))).DisplayName

    What can I do to solve this?

    Thank you in advance.

    1. It’s PowerShell, so you will have to debug it based on what results you see from your tenant. It looks as if the $Member variable is not populated with a value. I’d start by checking there.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.