Blog Post

Exchange Team Blog
9 MIN READ

Securing resources by tailoring Exchange Online RBAC (Part 1)

The_Exchange_Team's avatar
Mar 26, 2024

EHLO, folks!

Here’s a story from my work with customers, that’s coming out as a blog post series. One of my banking customers raised a request regarding RBAC (Role Based Access Control) permissions for their Service Desk Team. Upon analysis, it came to our attention they had lots of unwanted RBAC permissions granted to their Service Desk team.

The problem: giving too many RBAC permissions to users can result in accidental modifications of accounts. The way to deal with this is to customize the Role Groups and Management Roles.

I’ll begin with an overview of how RBAC works. It is a method of regulating access to resources based on the roles of individual users within an organization. RBAC enables you to control what tasks users can perform and what resources they can access within the organization. This is done by assigning roles to users, which define their permissions and access levels.

Exchange Online includes a large set of predefined permissions, based on the RBAC permissions model. These RBAC permissions are based on management roles i.e., inside every RBAC Role you’ll find one or many management roles. The cmdlet that’ll give you all the role groups is Get-RoleGroup.

These predefined role groups (aka, RBAC Roles) have management roles inside them that give permissions to perform tasks to administrators and users by making cmdlets available to those who are assigned the roles. The cmdlet that’ll give you all management roles is Get-ManagementRole.

When talking about RBAC, you’ll find the below terminology, so let’s get you all familiarized with these terms (in a nutshell).

  • Role Group: a group of Management Roles.
  • Management Role: a group of permissions or rights.
  • Management Role Entries: a group of cmdlets and their parameters behind a management role.
  • RBAC Scope: a collection of resources in a virtual segment that the members of the role group can manage (more in part 2 of this blog post)
  • RBAC Member: the user (admin) who is going to get the permissions.

The above overview is taken from Understanding Role Based Access Control: Exchange 2013 Help. For more information on RBAC and management roles, refer to Permissions in Exchange Online.

Back to the customer story – I would categorize the requests in two parts:

  • Minimize the chance of granting more permissions than necessary.
  • Ensure the team only accesses the resources to which they are authorized (this is in part 2 of this blog post)

Minimize the chance of granting more permissions than necessary

In our evaluation, we discovered the customer used the predefined role groups and management roles for their L1/ Service Desk team, which is not considered a good practice from a security perspective.

To address this, you would have to create your own customized version of Role Group(s) and Management Role(s).

Here are the phases of how you might want to go about doing this:

  • Phase 1: Find the tasks performed by L1/ Service Desk team and their respective cmdlets.
  • Phase 2: Create your own management role (a Child Management Role).
  • Phase 3: Create a new Role Group, add members & Child Management Role.

Please note that these phases should only be used as a reference. It is recommended to perform these in a test environment first and replicate in production only when you see desired results.

What you will need:

  • You must connect using Exchange Online Module (Connect-ExchangeOnline) to complete this task.
  • You must be a Global Admin or have an admin role for the specific workload / service to perform these changes.
  • For PowerShell to show all details, use $FormatEnumerationLimit =-1 in the start of the activity.

Phase 1: Find the tasks performed by L1/ Service Desk team and their respective cmdlets.

  1. Verify and collate a list of activities/ tasks being performed by Service Desk/ L1 or L2 Teams. For example: enforce MFA, add/remove delegates, create or modify Transport Rules and so on.
  2. Based on the activities/tasks from step 1, find out the corresponding PowerShell cmdlets
  • For example, the cmdlet to force Managed Folder Assistant (MRM) is: Start-ManagedFolderAssistant

Phase 2: Create your own Management Roles (aka, Child Management Role)

To create your own Management Roles, you must create a child management role and link it to a default management role which will act as its “parent”. This will allow the child management role to inherit the existing permissions (or, cmdlets). This is done because you can’t modify the default management roles in Exchange Online.

Now, let’s find the default management role that’ll act as “parent”. Here’s how you can find the default management role for any cmdlet (for example, Start-ManagedFolderAssistant).

Get-ManagementRole -Cmdlet Start-ManagedFolderAssistant

There can be multiple Management Roles for a single cmdlet, please choose the most restrictive one.

The above specifies that the cmdlet “Start-ManagedFolderAssistant” is part of default management role called “Retention Management”. This default management role will act as our “parent”. Once you have found the parent management role, it’s time to create the child management role:

  • Parent Management Role (Default): Retention Management
  • Child Management Role (Customized): SD Restrict - Retention Management
New-ManagementRole -Name "SD Restrict - Retention Management" -Description "Grants SD Team to enforce MFA" -Parent "Retention Management"

Note: The child management role will inherit all the permissions from parent management role, after which you can customize it. For more refer, New-ManagementRole (ExchangePowerShell) | Microsoft Learn.

Now that your child management role has been created, you must customize it (because right now, it is just a copy of what you already determined grants too many permissions). You can add or remove any cmdlet/ parameter to customize.

To see all the “Get-” cmdlets are part of child management role, run:

Get-ManagementRoleEntry -identity "SD Restrict - Retention Management\Get-*"

Run the same cmdlet for other verbs, like Set–*, Add-*, Remove-* and so on to find and review all permissions:

Get-ManagementRoleEntry -identity "SD Restrict - Retention Management\Set-*"
Get-ManagementRoleEntry -identity "SD Restrict - Retention Management\Disable-*"
Get-ManagementRoleEntry -identity "SD Restrict - Retention Management\Add-*"
Get-ManagementRoleEntry -identity "SD Restrict - Retention Management\Remove-*"
Get-ManagementRoleEntry -identity "SD Restrict - Retention Management\New-*"

There’s a fair chance of missing some verbs while reviewing. To deal with this, I would suggest running the below cmdlet to fetch all role entries (root cmdlets) that are part of this child management role.

Get-ManagementRoleEntry -identity "SD Restrict - Retention Management\*"

Or pipe it to view in [Grid View]

Get-ManagementRoleEntry -identity "SD Restrict - Retention Management\*" | Out-GridView

Once you filter out the cmdlets, start removing them. There are two ways to achieve this – either remove them one-by-one manually or remove all at once except the “GET-” cmdlets (if that is appropriate for the role you are creating). I’ll share examples for both.

Manual removal

For instance, if you want to restrict your Service Desk Team from creating any new Retention Policy:

Remove-ManagementRoleEntry -identity "SD Restrict - Retention Management\New-RetentionPolicy" -Confirm:$false

This will remove the rights to create any new Retention Policy from this child management role.

Another example, if you want to restrict your Service Desk Team from performing any changes on Mail Users.

Remove-ManagementRoleEntry -identity "SD Restrict - Retention Management\Set-MailUser" -Confirm:$false

Continue to perform the same for rest of the cmdlets depending on what rights you want to restrict.

Remove all at once (except Get-*)

We knew from the initial assessment that my customer wanted to grant only one task i.e., to enforce the managed folder assistant (Start-ManagedFolderAssistant) using this child management role. Instead of removing the root cmdlets one-by-one; we applied a different approach of removing all the cmdlets at once except [Get-*].

Get-ManagementRoleEntry -Identity "SD Restrict - Retention Management\*" | Where-Object {$_.Name -notlike 'Get-*'} | foreach {Remove-ManagementRoleEntry -Confirm:$false -Identity "$($_.id)\$($_.name)"}

The above will remove all the role entries that don’t have the verb [Get-] on the “SD Restrict - Retention Management” role by piping the output of the Get-ManagementRoleEntry cmdlet to the Where-Object cmdlet which specifies the verb filter, and then these results are piped to the Remove-ManagementRoleEntry cmdlet. For more information refer to - Remove-ManagementRoleEntry (ExchangePowerShell) | Microsoft Learn.

How do you know this worked? Run this cmdlet again to compare the results:

Get-ManagementRoleEntry -identity "SD Restrict - Retention Management\*" | Out-GridView

Once you are done removing all the unnecessary root cmdlets, add the desired one by running:

Add-ManagementRoleEntry -Identity "SD Restrict - Retention Management\Start-ManagedFolderAssistant"

When you remove or add a root cmdlet from a child management role, all its associated parameters will also be automatically removed or added accordingly. You can only add those cmdlets (functions/ parameters) back to child management role which are under its scope.

Bonus!

Here is another common situation that you might come across. The customer decided to add a new task for their Service Desk/ L1 team, which is to adjust the “Recipient Rate Limit” for user mailboxes.

The challenge here is that the root cmdlet (Set-Mailbox) has many other parameters defined in it which are not necessary for this team. We would have to ensure to eliminate all other parameters except what’s desired to perform the task.

Let's go over the process from the beginning leveraging Phase 1 and Phase 2 as mentioned above:

Find out the corresponding PowerShell cmdlet for this task.

Set-Mailbox -identity <user> -RecipientLimits 200

Determine the default (built-in) management role for this cmdlet. You would also need to ensure that the parameter <RecipientLimits> is also part of the default management role.

Get-ManagementRole -Cmdlet Set-Mailbox -CmdletParameters RecipientLimits

In my case, both the cmdlet and the parameter are part of “Mail Recipients”, so I’ll leverage it as my “Parent” and create a child management role. Always pick the most restrictive default management role.

Now, let’s create a child management role:

New-ManagementRole -Name "SD Restrict – Mail Recipients" -Description "Grants SD Team to adjust Recipient Rate Limit" -Parent "Mail Recipients"

Remove all the root cmdlets at once from this newly created child management role (SD Restrict – Mail Recipients) except [Get-*]

Get-ManagementRoleEntry -Identity "SD Restrict – Mail Recipients\*" | Where-Object {$_.Name -notlike 'Get-*'} | foreach {Remove-ManagementRoleEntry -Confirm:$false -Identity "$($_.id)\$($_.name)"}

Now, let’s add the root cmdlet and the parameter back in the child management role.

Add-ManagementRoleEntry -Identity "SD Restrict - Mail Recipients\Set-Mailbox" -Parameters RecipientLimits, Confirm, Force, WhatIf

I’ve observed that the parameter "Confirm”, and "Force" need to be included in order to perform any task using the new Exchange Online Admin Centre (EAC). However, these parameters don't give any additional permissions or rights.

Phase 3 – Create a Role Group, add members & Child Management Role

So far, we have been dealing with PowerShell instead of GUI. That’s because creating or managing a child management role isn’t possible via GUI – you must use the Exchange Online PowerShell module.

The only remaining tasks are to create Role Groups and add members and the child management role (created in Phase 2). These can be done either from Exchange Admin Center GUI or Exchange Online PowerShell Module. Just for the sake of leveraging both, I’m using Modern EAC (GUI) now.

To create an RBAC Role Group from New EAC (GUI), go to EAC > Roles > Admin Roles > Add Role Group:

Fill in Name and Description. You can leave Write Scope as “Default”. We’ll talk more about the “Write Scope” in part 2 of this blog post.

Add the Child Management Roles that you just created in the Permissions tab.

Add the desired administrators under Members tab.

Review and Finish by clicking Add Role Group.

Please wait about 60 mins for this to take effect.

This should create a new Role Group (RBAC) with the following details:

  • Name – SD Restrict
  • Permissions (Child Management Roles):
    • SD Restrict – Mail Recipients
    • SD Restrict – Retention Management
  • Admins - SD Test

Review using PowerShell:

Review it using EAC > Roles > Admin Roles > Click on “SD Restrict”. Go to Admin roles > General Tab.

Admin roles > Assigned Tab

Admin roles > Permissions

What is the behavior if your Service Desk Team tries to perform any task that’s beyond the defined scope of Child Management Role?

  • Let’s say, someone from that team tries to convert a User mailbox to a Shared mailbox from Exchange Admin Center GUI? There should be no Save button.
  • And for the same task from Exchange Online PowerShell V3 – see the error: The “’Type’ parameter isn’t found” as it’s not part of the management role entry of child management role.

This brings us to the end of this first part of the RBAC customization series. See you again in part 2!

Additional references:

Special thanks to all that reviewed this blog series - Nino Bilic, Mithun Rathinam and Nick Elder

Kshitij Gulati
Cloud Solution Architect

Updated Mar 28, 2024
Version 3.0
  • IczerSigma215's avatar
    IczerSigma215
    Copper Contributor

    KshitijGulatithanks for the reply! We have created many custom roles over the past decade in both Exchange On prem and Exchange Online, and we really appreciate the ability to go with a least privileged model. Which is why we were taken aback on the guidance from MSFT to NOT create child roles in Exchange Online as they may or may not work as expected. If this is still true, then I think it makes sense to either call that out or detail which roles shouldn't be made into pruned child roles in this blog post. This would be beneficial not only to your customers but also to your support staff. As my team wasted dozen of our own and MSFT supports' work hours troubleshooting why our child RBAC role wasn't working.

  • IczerSigma215's avatar
    IczerSigma215
    Copper Contributor

    This blog post on creating child RBAC roles with commands removed runs counter to the information I was told by Exchange Online support back in December of 2023. At that time, I was trying to create a custom RBAC role to just allow all methods of running and downloading message trace reports for our helpdesk support staff without granting access to more cmdlets then needed. No matter what we tried, our support staff could run extended message traces but received a HTTP 403 error when downloading them via any method. In contacting MSFT support I was told the following:

    • Ideally, Historical Search and Message tracking Role should allow users to download the reports but there is a product limitation role assigned via a group are not correctly propagated to all EXO parts, the message trace report being one of them. 
    • This is not a bug - this is a work item for a potential future feature which Microsoft currently have significant technical barriers to implementing. There is no ETA provided for the implication. 
    • We do not suggest you divide the role group "View-Only Recipients" as it will not work as expected to download the reports. 
    • For on-premises servers we have more flexibility to create custom role group to full fill our requirements.  

    Does this blog post mean that removing commands from Child Management roles is now working as expected?

     

  • IczerSigma215 The ability to create and customize child management roles has been there. It must be specific to a use-case in which it did not work as expected. Per your comment, I can see engineering/ support did acknowledge the behaviour and has confirmed that it's not a bug rather a work item to be taken as a potential future feature. If you happen to have other use-cases, please feel free to test the customization and let us know in the comments if you face any challenges.