Use PowerShell and RBAC to Control Access to Exchange Server Cmdlets

Summary: Microsoft PFE, Bhargav Shukla, shows how to use Windows PowerShell and RBAC to control access to Exchange cmdlets.

Microsoft Scripting Guy, Ed Wilson, is here. We are joined today by guest blogger Bhargav Shukla.

Bhargav Shukla is a senior premier field engineer—unified communications, with his primary focus on the Exchange Server platform. Bhargav has been in IT since the beginning of his career 14 years ago. Before joining Microsoft, he managed to work on almost any technology an IT consultant would be required to know, including Active Directory, Exchange, RSA Security, VMware, Citrix, and Cisco. He also holds industry certifications such as Microsoft Certified Master: Exchange Server 2010, VMware Certified Professional, Citrix CCEA, RSA: CSE, and Cisco CCNA/CCDA. He started working on scripting with small DOS batch scripts in his early career, and he learned to be a better scripter with new scripting languages. From batch files to VBScript and on to Windows PowerShell, he has written many scripts to address specific needs and reusable functions for repetitive code. When he is not working with customers, Bhargav leads the Philadelphia Area Exchange Server User Group, shares his knowledge on his blog and twitter, plays chess, and flies model airplanes.

Bhargav’s contact information:
Blog: Random thoughts of an Exchange PFE Blog
Twitter: bhargavs

RBAC and the principle of least privilege

The principle of least privilege is an important design consideration in enhancing the protection of data and functionality from unintentional and/or malicious behavior.

Exchange Server 2010 aids such implementation of roles by using role-based access control (RBAC). However, in my professional experience, I have noticed that many deployments are not actually thought out to utilize the full potential of what RBAC has to offer. Most often, I see deployments where built-in RBAC roles are utilized and rarely customized to match the actual job roles of administrators. This mostly results in having too much access for the role.

In this blog, I will try to explain a technique that will enable you to understand and apply the principle of least privilege with RBAC, especially when the administrators in question may not even be familiar with Exchange Server cmdlets, and you only want them to run a predefined sequence or a script that meets your requirements and aligns with business workflow.

Let’s take an example of a requirement to update the mailbox properties of users calling the Help Desk. You are required to provide tools so the Help Desk can carry out the necessary operations. You are also required to ensure that the business process workflow is followed. Giving access to appropriate cmdlets and parameters is relatively easy, but you don’t want to provide direct access to cmdlets because it may enable Help Desk users to run cmdlets outside of the confines of the workflow, and that could result in an undesired configuration of objects.

You decide to create a script that adheres to business process workflow. You do not want to distribute the script to Help Desk users because that can enable curious Help Desk users to edit the script as they desire.

By now, you may be asking, “How are we going to do this if we aren’t providing user access to cmdlets or script?” This is where the RBAC unscoped roles come in!

Let’s start with the business logic for a new user creation:

  • User must be created on given database.  For this exercise, we will use “Mailbox Database 0489489499.”
  • User must be created in a given organizational unit (OU). For this exercise, we will use “Fabrikam Users” OU.

Although this is very basic and simple logic, the process that we are going to follow can be applied to much more complex business cases, and this is merely an illustration of how you can do it.

The script looks like this:

## This script accepts a single parameter Name

param([string]$Name=$(Throw “Parameter missing: -name Name”))

$UPNSuffix = “”

$MDB = “Mailbox Database 0489489499”

$OU = “Fabrikam Users”

$Password = ConvertTo-SecureString ‘MyPassword123’ -AsPlainText -Force

New-Mailbox $Name -UserPrincipalName $Name$UPNSuffix -Database $MDB -Password $Password -OrganizationalUnit $OU

Let’s call the script New-CustomMailbox.ps1.

First step is to copy the script to all servers running Exchange Server 2010 that the Help Desk has the ability to connect to (usually all internal server’s roles except Edge). We will copy the script to the RemoteScripts folder (usually located at “C:Program FilesMicrosoftExchange ServerV14RemoteScripts”).

Next, we need to assign “Organization Management” group ability to create the unscoped roles. This is a protective measure because creating unscoped roles could be potentially dangerous. Due to the potentially dangerous nature of unscoped roles by default, no one in a given Exchange Server 2010 organization is assigned this role. This can be verified by running:

Get-ManagementRoleAssignment *unscoped* | fl *

The output would result in exactly one entry that looks similar to the following:


Identity                     : UnScoped Role Management-Organization Management-Delegating


RoleAssignmentDelegationType : DelegatingOrgWide



It is important to note RoleAssignmentDelegationType. It reads “DelegatingOrgWide” and not “Regular.” It is the “Regular” assignment that actually allows the assignee the ability to execute given cmdlets or parameters.

A simpler way to verify this is to try running the following:

New-ManagementRole –Un<TAB>

If you are familiar with Windows PowerShell syntax, this should result in auto completion of the parameter –UnScopedTopLevel…that is, if you have access to it. Until the administrator assigns this access (see the following script) or has assigned the access already, you will not be able to tab complete or run this cmdlet with the –UnScopedTopLevel parameter.

By running the following, we will assign “Organization Management” group ability to create unscoped roles:

New-ManagementRoleAssignment “Unscoped Role Management-Organization Management” -Role “Unscoped Role Management” -SecurityGroup “Organization Management”

Now that the ability to create unscoped roles has been assigned to the administrator, let’s create a new management role that Help Desk users will eventually use. You will need to establish a new Windows PowerShell session before doing this, because changes made by the cmdlet won’t be effective until then.

New-ManagementRole “Helpdesk Provisioning Script” –UnScopedTopLevel

This cmdlet will create an empty top-level unscoped role. It is important to understand a bit about top-level and unscoped. If you are aware of RBAC basics, you know that each new management role that you create must use a built-in role as a parent—except unscoped roles, which do not have any parent. Due to it’s nature as a top-level role, it doesn’t have any scope assigned either. You will need to manage the scope of impact from the script that you are going to assign to the role. You also need to control who has access to the server running Exchange Server 2010 and the script location to avoid unauthorized access and modifications.

Now that we have the unscoped role in place, we need to add the management role entry (the script we created above). To do this, use the command that follows.

Add-ManagementRoleEntry “Helpdesk Provisioning ScriptNew-CustomMailbox.ps1” -Parameters Name –UnScopedTopLevel

The next step is to create a role group with members (Help Desk members in our example) that will have access to the unscoped role we just created. Here is the command to accomplish that.

New-RoleGroup -Name “Helpdesk Provisioning” -Roles “Helpdesk Provisioning Script”

Finally, assign users to the role group that we just created (in our example, helpdesk1 is the user who will have access to the role). Use the Add-RoleGroupMember cmdlet to accomplish that task.

Add-RoleGroupMember -Identity “Helpdesk Provisioning” -Member helpdesk1

Help Desk user, helpdesk1, can now connect to the Exchange Management Shell. If a Help Desk user runs Get-ExCommand from the Exchange Management Shell, there is only one cmdlet available.

Note: Get-ExCommand is not available in a remote connection using Windows PowerShell, it is only available in the Exchange Management Shell.

The following cmdlet will be available to the Help Desk user:

[PS] C:>get-excommand

CommandType     Name                                                Definition

———–     —-                      ———-

Function        New-CustomMailbox.ps1    …

Now the Help Desk user can execute the following to create the user as defined by script:

[PS] C:>New-CustomMailbox.ps1 -Name user1

By now, you have probably picked up the fact that although the user is running a script that in turn runs the New-Mailbox cmdlet, the user doesn’t have direct access to the cmdlet that script is running. This prevents the user from directly creating new mailboxes while bypassing business logic that must be applied when creating a new mailbox.

Isn’t that some power in your hands? Isn’t that a feature that the Exchange Server team deserves kudos for?


Thank you, Bhargav, for a great blog. Join me tomorrow for the Weekend Scripter.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Comments (3)

  1. Charles Derber says:

    It is very much informative…!

  2. dblind1 says:

    Quick question about using Write-Host in the PS1 file. We are trying to check a lot of various attributes for a user. We have a nice script written that does the queries and then outputs to the screen using Write-Host commands. It works great when you
    run the script outside of RBAC, but inside of RBAC, you don’t see any output. Any ideas? I’m assuming because of the remote connections, and the Write-host is more of a local display output.

  3. John says:

    I tried this for "group mailbox" provisioning and in testing am getting errors when getting to a part of the script where we are trying to use the following cmdlets:

    Set-User with -DomainController parameter fails:

    Invoke-Command : A parameter cannot be found that matches parameter name ‘Manager’.

    + CategoryInfo : InvalidArgument: (:) [Set-User], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Set-User