I’ve blogged previously about the fact that “plain” Azure AD Security groups are synced to EXODS and can in fact be used to assign permissions or added as members of Exchange groups. Similar observations were then made about “non-recipient” Azure AD user objects, although these were easily discoverable in the output of Get-User. What I failed to cover back in the day is the way these object types are exposed/utilized by the corresponding cmdlets within the Security and Compliance PowerShell module, so let’s take a look at them now.
Let’s start with user objects, where we should not expect to see a big difference. Or should we? Here’s the result we get out of the Get-User cmdlet when using the SCC variant:
Get-User | group RecipientType | select Count,Name Count Name ----- ---- 55 User 1 MailUser
and here is the same via the ExO one:
Get-User | group RecipientType | select Count,Name Count Name ----- ---- 35 UserMailbox 16 MailUser 8 User
OK, that’s a bit strange. Not only the total count is off, but the breakdown by recipient type looks suspicious. Let’s take a look at the breakdown by RecipientTypeDetails instead:
Get-User | group RecipientTypeDetails | select Count,Name Count Name ----- ---- 55 User 1 RemoteUserMailbox
Hm… So all of them fall in the same type according to the SCC cmdlet, with a single exception (a user mailbox of all things). Here’s what the ExO cmdlet reported in turn:
Get-User | group RecipientTypeDetails | select Count,Name Count Name ----- ---- 2 DiscoveryMailbox 15 UserMailbox 3 RoomMailbox 11 SharedMailbox 1 TeamMailbox 12 GuestMailUser 8 User 2 SchedulingMailbox 1 EquipmentMailbox 4 MailUser
So which are the missing objects? In my particular scenario, the two DiscoveryMailbox objects as well as one of the Scheduling mailboxes. While one might expect this for the case of Discovery mailboxes, which are not represented in Azure AD and thus have no value for the ExternalDirectoryObjectId attribute, why only a single one of my Scheduling mailboxes is missing is a bit of a mystery. A closer look at its attributes reveals some empty values, on parameters such as MicrosoftOnlineServicesID, whereas they are populated on the other Scheduling mailbox entry. Incidentally, the former one is older, created two years earlier, so the provisioning workflow for such objects seems to have changed in the meantime (remember back when Microsoft changed the object type for Group mailboxes?).
But enough about users. It’s the group object type that’s showing bigger discrepancies, as shown below:
Get-Group | group RecipientType | select Count,Name Count Name ----- ---- 116 Group 17 MailUniversalSecurityGroup Get-Group | group RecipientTypeDetails | select Count,Name Count Name ----- ---- 55 UniversalSecurityGroup 61 RoleGroup 5 MailUniversalSecurityGroup 12 RemoteGroupMailbox
Now compare this against the output of Get-Group in ExO:
Get-Group | group RecipientType | select Count,Name Count Name ----- ---- 21 Group 26 MailUniversalDistributionGroup 5 MailUniversalSecurityGroup Get-Group | group RecipientTypeDetails | select Count,Name Count Name ----- ---- 21 RoleGroup 9 MailUniversalDistributionGroup 5 MailUniversalSecurityGroup 2 RoomList 15 GroupMailbox
That’s more than twice the number of objects returned from the SCC cmdlet (133) vs the ExO one (52). Now, the title of the post has probably already given away the answer here – the difference is that the SCC cmdlet returns “plain” Azure AD Security group objects, whereas the ExO cmdlet does not. Even though some ExO cmdlet will happily accept such objects, as shown in previous articles.
Let’s focus on the 55 UniversalSecurityGroup objects. None of these should be returned in the output of Get-Group within ExO, as such objects correspond to Azure AD Security groups and/or Azure AD Role groups (or their representation within the SCC). In my tenant, 37 out of the 55 objects map to Azure AD security groups (as checked via Get-MsolGroup/Get-AzureADGroup) and the remaining represent admin roles such as “SharePoint Service Administrator” or the legacy “Partner Tier1 Support”. One interesting observation here is that the latter set of groups compliment the list of “default” admin role “mapped” groups returned by Get-RoleGroup, such as the TenantAdmins one, or GlobalReaders. While we can see some of these “default” entries within ExO as well, roles such as “SharePoint Service Administrator” do not have a representation there. This of course makes sense, as the SCC is a cross-workload console.
The important part to note here is that such groups are actually supported for assigning permissions to different functionalities within the SCC. As an example, we can assign a Azure AD security group to the Records Management Role Group by using:
Add-RoleGroupMember RecordsManagement -Member 2903dd42-9643-40ee-9df6-88f18c155fe1
Confirming the changes are in effect can be a big confusing, as the Get-RoleGroupMember will display the ExchangeObjectId/Guid value instead of the ExternalDirectoryObjectId:
Get-RoleGroupMember RecordsManagement Name RecipientType ---- ------------- 47dc4a7a-c85d-4eaa-ac87-11501200f928 Group
The real confusing part is that the Get-Group cmdlet will only show the relevant entry when used with the ExternalDirectoryObjectId value:
Get-Group 2903dd42-9643-40ee-9df6-88f18c155fe1 Name DisplayName SamAccountName GroupType ---- ----------- -------------- --------- 47dc4a7a-c85d-4eaa-ac87-11501200f928 new Universal, SecurityEnabled
If you try passing the ExchangeObjectId or any other non-existing GUID value for that matter, the full set of group objects will be returned!? The Get-User cmdlet seems to exhibit the same behavior within the SCC, whereas their ExO equivalents behave “as expected” and return an error message instead.
Putting the output discrepancies aside, the important thing is that one can indeed use Azure AD security groups to assign permissions to SCC features and more importantly, these actually work. After a 30 mins or so replication time, the members of the group we added to the RecordsManagement Role Group above were able to access the corresponding pages within the SCC.
Another thing to note is that the Permissions UI still does not recognize Azure AD security groups as valid object for assigning permissions. If you assign the permissions via the PowerShell cmdlet though, the corresponding entries will be visible and can be removed via the UI as well. Adding an Azure AD security group will not be possible however. And while we are on the subject of limitations, the SCC (and its sister Compliance/Security centers) still lacks proper RBAC controls, such as managing assignments directly, configuring scopes, and so on. Role Groups remain the only RBAC bit available.
OK, so what about the remaining objects? 61 of those represent Role Groups within the SCC, versus 21 for the EAC ones. There are zero (0) MailUniversalDistributionGroup returned by the Get-Group cmdlet in the SCC, as it doesnt seem to particularly care about non-security enabled objects. Interestingly, such entries are readily returned when queried for by name. Closer examination shows that such objects show GroupType value of “Universal”, whereas all the other groups have a value of “Universal, SecurityEnabled”. In effect, the SCC Get-Group cmdlet filters out non-security enabled groups it seems.
And whereas GroupMailbox objects are returned as MailUniversalDistributionGroup type within the EAC, the SCC cmdlet designates them as MailUniversalSecurityGroup. What’s even more interesting is that some Microsoft 365 groups aren’t returned by default, suggesting some discrepancy in their properties. In my tenant two such objects were found, both with GroupType value set to “Universal”, similarly to the case of “traditional” distribution groups described above. The conclusion we can draw here is that the Get-Group cmdlet behaves quite differently in the case of SCC, so you probably shouldn’t be comparing its output directly with the ExO counterpart.
To close this article, I want to re-iterate that Azure AD security groups can successfully be used to assign (some types of) permissions across Exchange Online and the Security and Compliance Center functionalities. The only bit that’s new here is the fact that such groups are now readily returned in the output of Get-Group cmdlet as part of the SCC module, which in turn allows you to more easily enumerate and assign them as needed.