Potentially More Flexibility and Control Available in Entra ID
On December 1, 2021 Microsoft announced the preview of Entra ID Custom Security Attributes. In a nutshell, tenants with Entra ID P1 or P2 licenses can use custom security attributes to store business-specific information for user accounts, security principals, and managed identities. The requirement for premium licenses reflects the targeting of large enterprises for this capability. In their FY22 Q1 results, Microsoft said that the Enterprise Mobility and Security suite, which includes Entra ID premium, has 196 million users, or roughly 60% of the Office 365 user base. With those numbers in mind, the requirement for premium licenses should not be an impediment to the adoption of Entra ID custom security attributes.
Microsoft’s announcement positions custom security attributes as part of their roll-out of Attribute Based Access Control to give organizations the ability to control access to resources like Azure storage at a fine-grained level. Worthy as that effort is, I think many organizations will find practical use for custom security attributes to replace Exchange custom mailbox attributes to store important or sensitive corporate information about users. This is one of the scenarios called out by Microsoft in their announcement and it’s the one I explore here.
Allowing Organizations to Define Their Own Attributes
The problem with standard software is that it’s standard. Being able to customize how software works means that different customers can make software more useful in terms of their operations.
Although an organization can store what they want in Exchange custom attributes, they can’t change the names of the attributes or their number. Things are very different with Entra ID. Custom security attributes are defined in attribute sets, managed collections of key-value pairs. Azure roles allow organizations to control who can define attribute sets and individual attributes and who can view the data stored in the attributes. A tenant can create up to 500 custom security attributes. You can scope an attribute set so that it is managed tenant-wide or managed by specific users. For instance, an administrator located in Germany might control attributes specific to accounts belonging to that country.
Overall, the key differences between Exchange custom attributes and custom security attributes are:
- Organizations can decide how many custom security attributes they want and how to organize those attributes in attribute sets. They can assign their own names to the attributes.
- Custom security attributes can be strings, integers, or Booleans, and accept single or multiple values. Fifteen of the Exchange custom attributes are single value (all treated as strings) while five are multi-value and can hold up to 1,300 values each.
- Custom security attributes can be prepopulated and limited to a set of acceptable values.
- Management of and access to attribute sets can be scoped to different users. By comparison, any global or Exchange administrator can manage and access the data held in mailbox attributes.
- Exchange Online custom attributes are available for all mail-enabled objects, including Microsoft 365 group mailboxes. Custom attributes are available for user accounts (member and guests).
- Adaptive scopes for user retention policies is an example of how Microsoft exploits values written into Exchange custom attributes. For custom attributes, Microsoft’s focus is likely to be on security, with the first use being as conditions in conditional access policies (due soon).
Like the Exchange custom attributes, Entra ID custom security attributes are accessible programmatically using PowerShell and the Microsoft Graph (through the beta endpoint for the Users API). The PowerShell cmdlets and parameters show their Graph heritage and are not as easy to work with as the Exchange custom attributes are, but once you get used to what’s required, it’s reasonably plain sailing to set attributes. As explained later, retrieving values from custom security attributes using PowerShell is a tad more complicated, but not if you use the Graph API.
Creating New Custom Security Attributes
The documentation for creating a new attribute set and populating it with attributes is clear and doesn’t need repeating. The big thing is to make sure that the account you sign into the Entra admin center holds the Attribute Definition Administrator role. Even if your account is a global administrator, it won’t have the role unless you go ahead and assign it. After assigning the role, wait a few minutes for the change to percolate through Entra ID and refresh the browser to pick up the change.
Before creating anything, it’s a good idea to write down the names and characteristics of the custom security attributes you plan to use. The basic structure of each attribute is:
- Name (up to 32 characters but can’t contain spaces or special characters).
- Description (up to 128 characters of your best prose).
- Data type (string, integer, or Boolean). Given the widespread storage of dates (hire date, last promotion, last review) in personal data, it’s curious that Microsoft did not include a date type.
- Allow multiple values to be assigned (yes/no).
- Only allow predefined values to be assigned (yes/no). If you choose yes, you must edit the attribute after creation to add the predefined values.
Apart from predefined values, you can’t add validation or formatting instructions for data held in custom security attributes. For instance, you can’t say that an integer attribute must be within 1 and 1000. However, the lack of formatting and validation for Exchange custom attributes has not restricted their usefulness over the last fifteen years because, in most cases, code is written to validate and format data before updating an attribute.
When you create a new attribute set, you’re asked how many attributes will be in it. The default is 25, but you don’t have to create this many. It is a maximum, not a target to aim for.
I created a new attribute set called Employees to hold the kind of information often used by HR and then started on the attributes. Figure 1 shows the creation of an attribute called TaxIdentifier, intended to store information like U.S. social security numbers.
Figure 2 shows a custom security attribute called LegalEntity being edited to add predefined values. In addition, the settings for the attribute allow only values from the predefined set.
Note that you cannot delete an attribute. If you make a mistake, you can deactivate an attribute to remove it from the current set, but the old attribute remains in place until Microsoft provides a way to remove it.
Eventually, you build out all the custom security attributes for the set (Figure 3) and are ready to populate some data.
This is when you get the chance for a coffee break. When I set things up in two different tenants, it took several hours for Entra ID to recognize that a new set of custom security attributes is available to be populated. Microsoft says that new attributes should show up faster. It could be that the slowness I experienced is just a preview glitch.
In any case, you’ll know when things are ready when the Custom security attributes (preview) option in the Users blade of the Entra admin center is no longer greyed out. If the option stays greyed out after a couple of hours, it might be a chance to have a mild panic. Or just wait a bit longer and check the troubleshooting hints again.
Populating Entra ID Custom Security Attributes
Adding custom security attributes to Entra ID is nice; being able to store some user data in those attributes is even better. The basic approach is to edit user properties in the Entra admin center and choose Custom security attributes from the Manage menu. You can then select attributes to add from the available attribute sets (Figure 4).
The Entra admin center GUI for custom attributes could never be considered user friendly. Then again, neither is the GUI available for custom attributes in the new Exchange Online admin center (Figure 5). Both are passable, but only because it’s likely that code will write data into both types of custom attributes most often.
Because Entra ID indexes custom security attributes, they can be used to filter user accounts. Add a filter in the normal manner and select custom security attribute as the filter, then the attribute set and attribute to use, the operator, and the value (Figure 6).
Using PowerShell to Transfer Custom Attributes from Exchange Online to Entra ID
Speaking of PowerShell, if we want to move data from Exchange Online to Entra ID, we need to write some code. The PowerShell code below requires the Exchange Online management module to read the mailbox information and version 2.0.2.138 of the AzureAD preview module to update the user accounts. The code is very simple:
- Find user mailboxes in the tenant.
- If CustomAttribute8 holds a value, use it to update the JobCode custom security attribute for the user account.
- If CustomAttribute12 holds a value, use it to update the LegalEntity custom security attribute for the user account.
No error checking or validation of the data held in the Exchange custom attributes occurs. I’ll leave those pieces to your imagination. Here’s the code:
[array]$Mbx = Get-ExoMailbox -RecipientTypeDetails UserMailbox -ResultSize Unlimited -Properties CustomAttribute8, CustomAttribute12 If (!($Mbx)) { Write-Host "No mailboxes found - exiting"; break} ForEach ($M in $Mbx) { If (!([string]::IsNullOrWhiteSpace($M.CustomAttribute8))) { # Update the JobCode in Entra ID $JobCodeInfo = @{ Employees = @{ "@odata.type" = "#Microsoft.DirectoryServices.CustomSecurityAttributeValue" JobCode = "$($M.CustomAttribute8)" } } Write-Host ("Updating account {0} job title to {1}" -f $M.DisplayName, $M.CustomAttribute8) Set-AzureADMSUser -Id $M.ExternalDirectoryObjectId -CustomSecurityAttributes $JobCodeInfo } # End if If (!([string]::IsNullOrWhiteSpace($M.CustomAttribute12))) { # Update Legal Entity in Entra ID $LegalEntityInfo = @{ Employees = @{ "@odata.type" = "#Microsoft.DirectoryServices.CustomSecurityAttributeValue" LegalEntity = "$($M.CustomAttribute12)" } } Write-Host ("Updating account {0} legacy entity to {1}" -f $M.DisplayName, $M.CustomAttribute12) Set-AzureADMSUser -Id $M.ExternalDirectoryObjectId -CustomSecurityAttributes $LegalEntityInfo } # End if } # End ForEach
To remove the sensitive user information from Exchange Online, you could use the Set-Mailbox cmdlet to overwrite the custom attributes. However, before you put all your custom attribute eggs in the Entra ID basket, read the notes about retrieving information below.
Further details of how to manage custom security attributes with PowerShell or the Microsoft Graph are available here.
Searching and Retrieving Information
And now some bad news. Transferring information from Exchange Online to Entra ID using PowerShell is straightforward. Accessing it afterwards is more challenging. As described above, you can use the Entra admin center to filter objects based on custom security attributes, but it’s likely that you’ll also want to access the data in scripts.
For Exchange custom attributes, the task is straightforward because you can use a server-side filter. For example:
Get-Recipient -Filter {CustomAttribute12 -eq "United States"}
The matching objects are found by the server and returned to the workstation in an array ready to be processed in whatever way the scripter wishes.
The PowerShell implementation for fetching custom security attributes is poor and requires too much effort to find and extract data. First, you can’t run Get-AzureADUser to filter against values in custom security attributes. Instead, you need to check accounts individually by running the Get-AzureADMSUser cmdlet:
$Attributes = Get-AzureADMSUser -Id Brian.Weakliam@Office365itpros.com -Select CustomSecurityAttributes
The returned object is a MsUser type (rather than standard PowerShell object). To see the actual values, we need to examine the CustomSecurityAttributes property, which is a JObject type, to see:
$Attributes.CustomSecurityAttributes Type : Object HasValues : True First : {} Last : {} Count : 4 Parent : {"@odata.type": "#microsoft.graph.customSecurityAttributeValue" "JobCode": "OpsMgr" "LegalEntity": "RA Ireland" "EmployeeNumber": 150823} Root : {Employees} Next : Previous : Path : Employees LineNumber : 0 LinePosition : 0 IsReadOnly : False AllowNew : True AllowEdit : True AllowRemove : True SupportsChangeNotification : True SupportsSearching : False SupportsSorting : False IsSorted : False SortProperty : SortDirection : Ascending IsFixedSize : False SyncRoot : System.Object IsSynchronized : False Keys : {@odata.type, JobCode, LegalEntity, EmployeeNumber}
The information we need to access is there, but it’s hard (and slow) to get at it.
Microsoft’s answer is to use the Graph API. For instance, an example in their documentation shows how to fetch data by filtering users using an equal match against a custom security attribute. The query looks for objects with the value Canada in the custom attribute AppCountry in the Marketing attribute set:
https://graph.microsoft.com/beta/users?$count=true&$select=id,displayName,customSecurityAttributes&$filter=customSecurityAttributes/Marketing/AppCountry%20eq%20'Canada'
Although it’s not hard to include Graph API queries in PowerShell scripts, extra code and effort is needed. I understand why Microsoft would concentrate on the Graph API for programmatic access to date, especially for preview releases, but it’s a pity that simple (and fast) PowerShell querying capability against custom security attributes is unavailable.
Extensible Directories
Being able to extend the information held about user accounts is a nice feature to have. Microsoft has made a solid start in the preview of Entra ID custom security attributes, and the capability will become stronger when they add support for custom security attributes in conditional access policies. The lack of good PowerShell support might create an adoption barrier in some cases; in other circumstances, the Graph rules supreme and this isn’t an issue.
All in all, Entra ID custom security attributes are worth investigating to discover if they can solve business problems for your Microsoft 365 tenant.
Do you know if Custom Security Attributes or Extension Properties Attributes can be populated with Azure AD Connect?
Thanks for a really good article!
Custom Security Attributes, no… but extension attributes should carry across because they are also available in Active Directory.
Hello, thanks for the article! I have two questions. 1. Can these new AAD Custom Security Attributes be mapped to a AAD Enterprise Application relationship for syncing? 2. Do you know if the Exchange Custom Attributes are visible to users at large or only sys admins in backend?
Custom security attributes are currently only assignable to Azure AD user objects and security principals.
Exchange custom attributes are not exposed by any client that I know of.
Great article. How can the Custom Security Attributes be accessed for SAML claims or expressions? Are they part of the user object or are they part of another object? I created a Custom Security Attribute and assigned it to a user but it doesn’t appear in the drop down of available attributes within the user object (user.CustomSecurityAttribute)
Did you have any success with this?
I really appreciate this article. Microsoft’s help documentation on Powershell for Custom Security Attributes is lacking right now and the examples they provided for Powershell weren’t working for me. (There’s a line “Project@odata.type” = “#Collection(String)” which it didn’t seem to like.) I saw your code and it set me on the right path. Thanks!
Documentation often needs time to catch up with the active use of new technology in the wild…
Good article. How do these differ from Graph Schema Extensions and Graph Open Extensions? I feel like there’s no simple english or best practice examples for these….
The Azure AD security attributes are defined for use by any tenants. Any extensions are, by definition, organization specific.