Adding and reporting on permissions for Azure AD Security groups in Exchange Online

Some of you are probably well aware of the fact that Azure AD is the directory behind Office 365. Azure AD stores all the user and group objects and their relevant properties. Some of the different workloads constituting Office 365 have their own directory stores, such as EXODS for Exchange Online, SPODS for SharePoint Online and so on. A copy of any Azure AD object relevant to Exchange Online is kept inside EXODS, and its properties are “extended” with many Exchange-only attributes. It simply doesn’t make sense to store all this information in the “general” Azure AD directory, as no other workload can consume it. Similarly, some object types only exist in EXODS and are never synced to Azure AD.

The opposite scenario is also observed, for examples (non mail-enabled) Azure AD security groups do not have any representation in EXODS. This includes security groups you have synchronized from on-premises or the ones created directly in the cloud. As they are not mail-enabled and take no part in the mail flow process, Exchange doesn’t care about them. Thus, when you try to use any of the familiar Exchange cmdlets against such a security group, you will run into the “object could not be found” exception. As it should be, right?

Let’s dig a bit deeper. It’s easy enough to list all such non mail-enabled, Azure AD only security groups. For example, to do this via the MSOnline module, one can use:

Get-MsolGroup -GroupType Security | select DisplayName,GroupType,ProxyAddresses,ObjectId

DisplayName                            GroupType ProxyAddresses ObjectId
-----------                            --------- -------------- --------
test                                    Security {}             a1813eff-a80b-4ac9-bbdc-8e0821b76809
Group                                   Security {}             80cc841e-e4fd-4351-94d6-bd2f4398191b
FIMSyncAdmins                           Security {}             8595ff15-45fa-4fef-bf51-cf3878a085ef
WinRMRemoteWMIUsers__                   Security {}             5a3cdc21-85c0-41b2-8f29-a8b4850ddff2

In the above output, we can clearly see some groups that have been synchronized from on-premises AD (who in their right mind will intentionally name a group “WinRMRemoteWMIUsers__”), as well as some cloud-created ones. The newer Azure AD PowerShell module can also be used:

Get-AzureADMSGroup -Filter "SecurityEnabled eq true and MailEnabled eq false" | select DisplayName,MailNickName,MailEnabled,ProxyAddresses

DisplayName                     MailNickname                    MailEnabled ProxyAddresses
-----------                     ------------                    ----------- --------------
ADSyncBrowse                    ADSyncBrowse                          False {}
ADSyncOperators                 ADSyncOperators                       False {}
Exchange Install Domain Servers Exchange_Install_Domain_Servers       False {}
Exchange Trusted Subsystem      Exchange_Trusted_Subsystem            False {}
ADSyncPasswordSet               ADSyncPasswordSet                     False {}

The above example is from a different tenant, one that has Exchange on-premises installed, and so some of the default Exchange groups are visible in the output. It’s interesting to note that although all these groups are not mail-enabled, all of them have their alias/MailNickName attribute populated.

Another option to report on such groups is the Get-AzureADMSGroup cmdlet. To spice up things a bit, this example uses yet another tenant, one in which the synchronization process has been initiated from several different on-premises ADs:

Get-AzureADMSGroup -SearchString ADSync | ft DisplayName,MailNickName,*Enabled,Id

DisplayName       MailNickname      OnPremisesSyncEnabled MailEnabled SecurityEnabled Id
-----------       ------------      --------------------- ----------- --------------- --
ADSyncAdmins      ADSyncAdmins                                  False            True bf526ee3-f6c7-4960-bd9b-cc90bbed718c
ADSyncAdmins      ADSyncAdmins                                  False            True 445e01a0-b7e4-41ca-b269-311e473c7e6f
ADSyncAdmins      ADSyncAdmins      True                        False            True 7abcceed-2e6a-48c2-9601-d281fd567e77
ADSyncBrowse      ADSyncBrowse                                  False            True c56aff52-d7e5-4a54-93d7-ffce3ad40f98
ADSyncBrowse      ADSyncBrowse                                  False            True d0f96187-cce8-4666-9bb7-5a167a4ed914
ADSyncBrowse      ADSyncBrowse      True                        False            True e063d094-65f8-4aa9-a89b-30bf6e30aef3

As a result, we have several copies of the same security group object, each with different ObjectID, but with matching names and alias/MailNickName attributes. Now, if you look at cloud-created groups, another interesting observation can be made for the MailNickName attribute. Namely, for all such groups, the value of this attribute is set to “BposMailNickName”, regardless of which method they were created by (PowerShell, O365 portal, Azure AD portal). In turn, this allows us to easily filter them out:

Get-AzureADMSGroup -SearchString BposMailNickName

Id                                   DisplayName           Description
--                                   -----------           -----------
a1813eff-a80b-4ac9-bbdc-8e0821b76809 test
a32a3a02-095a-4a7d-86e8-98f63fc002b2 CreatedFromO365Portal
84b18857-3c01-48be-b707-492019c57142 CloudSecGrp
b6b27af5-7b64-4bd5-9dc5-8886974dcb51 All Users
5641f280-8cf7-4a3b-a559-470b16451730 AllGuests
492075a7-3b42-41b6-884e-f19966134422 TestEXO

So, why am I showing you all this? It turns out, we can actually use such groups to delegate permissions in Exchange Online. Or at least we can try to, the permissions don’t actually work as we will see later on. To demonstrate this, we select a random, cloud-created, non mail-enabled security group, say “TestEXO” from the above list. We have the group’s objectID from the above example, so lets check what Exchange Online knows about it:

Get-Recipient 492075a7-3b42-41b6-884e-f19966134422
The operation couldn't be performed because object '492075a7-3b42-41b6-884e-f19966134422' couldn't be found on 'VI1PR03A001DC01.EURPR03A001.prod.outlook.com'.

Get-Group 492075a7-3b42-41b6-884e-f19966134422
The operation couldn't be performed because object '492075a7-3b42-41b6-884e-f19966134422' couldn't be found on 'VI1PR03A001DC01.EURPR03A001.prod.outlook.com'.

Get-SecurityPrincipal 492075a7-3b42-41b6-884e-f19966134422
The operation couldn't be performed because object '492075a7-3b42-41b6-884e-f19966134422' couldn't be found on 'VI1PR03A001DC01.EURPR03A001.prod.outlook.com'.

Judging by the above, Exchange Online is totally oblivious about the existence of this group, as far as its concerned it does not exist and definitely cannot be used to delegate permissions (not recognized as security principal). Yet, any permissions-related cmdlet happily accepts the group as a valid delegate:

Add-MailboxPermission sharednew -User 492075a7-3b42-41b6-884e-f19966134422 -AccessRights FullAccess -AutoMapping $false

Identity             User                 AccessRights
--------             ----                 ------------
sharednew            EURPR03A001\Bpos5... {FullAccess}

Yes, the Full Access permissions were successfully granted, which we can confirm via:

Get-MailboxPermission sharednew -User 492075a7-3b42-41b6-884e-f19966134422 | fl

AccessRights    : {FullAccess}
Deny            : False
InheritanceType : All
User            : BposMailNickName_4343c935f8
Identity        : sharednew
IsInherited     : False
IsValid         : True

So, contrary to our initial expectations, the Azure AD security group does seem to exist in EXODS and can be used to delegate permissions. Some permissions at least: Full Access and Send As can be granted, while folder-level permissions cannot and neither can Send on behalf of permissions. Even though Full Access permissions can be granted, they do not actually work, as can be confirmed by trying to access the shared mailbox from the above example via the account of any member of the TestEXO group:

What is the explanation behind all this? There is no official documentation from Microsoft that says Azure AD Security groups can be used to delegate permissions. At least not yet. So two options exists here: either the observed behavior is a bug, or we are simply seeing the initial stages of a feature that is intended to provide support for such permissions. Some additional facts increase the possibility that the latter scenario is valid – recently a new recipient type was introduced in Exchange Online. More specifically, the Get-Recipient cmdlet lists “ExchangeSecurityGroup” as valid recipient type (RecipientTypeDetails), which is a nice fit for the above scenario.

The actual parameter doesn’t work yet, and it might never work for us as end-users, but we have already seen similar behavior on several other occasions. Most recently, such behavior was observed with the Supervisory mailboxes used by the Supervisory review feature, which are very well hidden from the admin tools. Their corresponding recipient type, SupervisoryReviewPolicyMailbox, is also listed as available for Get-Recipient, however only the permissions-related cmdlets work with such objects.

Another example of similar behavior is the use of built-in administrative groups and security principals. When you review the permissions of any mailbox in Office 365, you will note entries such as “EURPRD03\Domain Admins” or “NT AUTHORITY\SYSTEM”. Those entries are usually ignored by us, and there’s hardly any information we can get on them, but they are of vital importance to Microsoft’s ability to run the service. If you are adventurous enough, there are some workarounds that allow you to play with such objects, as described here.

While Supervisory mailboxes can be thought of “backend” for a particular feature and in general are not very interesting to work with, the situation with Azure AD security groups is different. We can create, synchronize and manage such groups and in most organizations the number of such objects can be comparable to or even surpassing the number of users. Thus, if some part of the service has support for security groups, it’s natural to expect that all the familiar tools work as expected. More importantly, permissions are usually a sensitive matter for which often times periodic reports are being generated end examined. For example, it’s a common practice to review which resources a give user has prior to him leaving the company, etc.

And therein lies the problem – we simply cannot rely on any known method to report on permission entries granted via such groups. If you run the Get-MailboxPermission cmdlet to get the list of permissions for a given object, such as in the above example, the only bit of information you can get about the delegate is a string value containing something like “BposMailNickName_4343c935f8”. None of the cmdlets in either Exchange Online or Azure AD work against this entry however, as shown on the below image:

The above example illustrates the scenario for cloud-created Azure AD security groups, which get the generic “BposMailNickName” value. For synchronized ones, the MailNickName attribute matches the display name and is easier to reuse. None of the Exchange cmdlets will accept this value, but you can use it against Get-MsolGroup or Get-AzureADGroup to find a match. However, remember that example we show above with several groups having the same display name? Here’s how permissions looks like when all three instances of the ADSyncAdmins group are present, and how the User entry is mapped across the different cmdlets:

In other words, there is no reliable way to report on such permissions unless you check against each Azure AD Security group. Here’s an example on how to generate such report:

foreach ($group in (Get-MsolGroup -GroupType Security)) {Get-MailboxPermission shared -User $group.ObjectId.Guid | select @{n="AADGroup";e={$Group.ObjectId.Guid}},User,AccessRights }

AADGroup                             User                    AccessRights
--------                             ----                    ------------
bf526ee3-f6c7-4960-bd9b-cc90bbed718c ADSyncAdmins_034fadd801 {FullAccess}
445e01a0-b7e4-41ca-b269-311e473c7e6f ADSyncAdmins            {FullAccess}
7abcceed-2e6a-48c2-9601-d281fd567e77 ADSyncAdmins_e4e371a4b9 {FullAccess}

Of course, if you want to cover all mailboxes, a proper full-blown script should be used instead.

In summary, when you report on (or grant) permissions in Exchange Online, you should be aware that Azure AD Security group entries can eventually pop up. To handle such entries, you cannot use the Exchange cmdlets, as the corresponding objects are “hidden” from them. The only reliable method I’ve found is to use the objectID of the group against the User parameter of the Get-MailboxPermission cmdlet, which unfortunately means you will have to cycle over each security group in your Azure AD instance. Hopefully, Microsoft will improve the handling of such entries in the future!

This entry was posted in Exchange Online, Office 365, PowerShell. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *