Few years back, Microsoft released a set of new policy objects, allowing us to impose restrictions on the credentials used for service principal and application objects. In a nutshell, an application management policy can be used to control the type of credentials that can be configured for any given SP/application object, their maximum lifetime, and in the case of certificate credentials, the list of trusted certificate authorities. One could configure a tenant-wide policy, or additional custom policies scoped to specific objects. If you need additional details, we covered said application management policies here and here.
Now, the Graph API changelog reveals some new additions to the resource, as well as a general reorganization of its overall structure, so it is time to take another look at application management policies. Unfortunately, since last time we covered this functionality, there are some bad news. Namely, the licensing requirements for using application management policies have changed – they now require the Workload Identities SKU, which is quite the bummer.
So, if you are interested in playing with Application management policies, the first thing you need to do is ensure your tenant meets the updated licensing requirements. Without it, you cannot even toggle the default (tenant-wide) policy object… great example of Microsoft’s priorities. But I digress.
As mentioned above, there has been some reorganization of the corresponding Graph API resources. Most of the changes are straightforward and do not deserve a separate mention. However, you might notice some interesting new additions as well. You can find the full list of changes below:
- Added the appManagementApplicationConfiguration resource.
- Added the appManagementServicePrincipalConfiguration resource.
- Added the customAppManagementApplicationConfiguration resource.
- Added the customAppManagementConfiguration resource.
- Updated the return type for the restrictions property of the appManagementPolicy resource from appManagementConfiguration to customAppManagementConfiguration.
- Updated the return type for the applicationRestrictions property of the tenantAppManagementPolicy resource from appManagementConfiguration to appManagementApplicationConfiguration.
- Updated the return type for the servicePrincipalRestrictions property of the tenantAppManagementPolicy resource from appManagementConfiguration to appManagementServicePrincipalConfiguration.
- Added the identifierUris property to the appManagementApplicationConfiguration resource.
- Added the identifierUriConfiguration resource.
- Added the identifierUriRestriction resource.
Again, most of these are irrelevant, as you don’t care about the type of resource when providing the JSON payload to update the policy (or create a new one). In other words, the process hasn’t really changed. You still issue a PATCH request against the /beta/policies/defaultAppManagementPolicy endpoint, with the desired payload (and make sure you have the required Policy.ReadWrite.ApplicationConfiguration permissions). For example, the request below will enforce a 90 day limit on the maximum credential lifetime for client secrets and certificate credentials on application objects:
PATCH https://graph.microsoft.com/beta/policies/defaultAppManagementPolicy { "isEnabled": true, "applicationRestrictions": { "passwordCredentials": [ { "restrictionType": "passwordLifetime", "maxLifetime": "P90D", "restrictForAppsCreatedAfterDateTime": "2024-01-01T00:00:00Z" } ], "keyCredentials": [ { "restrictionType": "asymmetricKeyLifetime", "maxLifetime": "P90D", "restrictForAppsCreatedAfterDateTime": "2024-01-01T00:00:00Z" } ] } }
Do note that we have not configured all the relevant properties in the example above, the idea is to simply illustrate that the process remains virtually unchanged. For real-life scenarios, you’d definitely want to leverage some of the other properties!
Moving on, let’s talk about the newly introduced identifierUriRestriction resource. As the name suggest, we can use this to restrict the values that can be used when configuring the Identifier URIs for application objects. This is also known as the Application ID URI, and should not be confused with the Reply/Redirect URIs.
Configuring this restriction will prevent the addition of custom Identifier URI values and enforces the default format, which matches the application ID in the form api://{appId}. This ensures a globally unique value and can potentially prevent some spoof-like scenario. As part of the identifierUriRestriction resource, four optional settings can be configured:
- state – Optional, indicates whether to evaluate Identifier URI restrictions. Possible values are: enabled, disabled or the beloved unknownFutureValue.
- excludeAppsReceivingV2Tokens – Optional, indicates whether the restriction are enforced for applications that are configured to receive V2 tokens. Boolean, so possible values are true/false.
- excludeSaml – Optional, indicates whether the restriction are enforced for SAML applications. Boolean, true/false.
- restrictForAppsCreatedAfterDateTime – as with all the other restrictions, you can use this value to enforce the policy to newly created objects only, or retroactively apply it to existing ones. Optional Datetime value.
The example below shows how you can configure identifierUriRestriction on the default application management policy. As with all other restrictions within a policy, you don’t really need to know how the corresponding resource is named, simply provide a JSON with the desired values. You do not need to specify any of the four optional settings we listed above, unless you want to.
PATCH https://graph.microsoft.com/beta/policies/defaultAppManagementPolicy { "applicationRestrictions": { "identifierUris": { "nonDefaultUriAddition": { "restrictForAppsCreatedAfterDateTime": "2024-01-01T00:00:00Z" } } } }
To see the newly configured restrictions in action, head over to the Entra portal and select any application registration object you have. Under Expose an API, look for the Application ID URI on top and hit the Add button. You will be presented with the default value, which as we mentioned above is in the format api://{appId}. If you try to make any changes to said value now, you will be presented with an error like the one shown below:
There you have it – similar to other restrictions we can apply via application management policy, the attempted change was blocked due to policy violation. The error message will also give you the application management policy id, and if you look at the audit logs, you will also notice a Microsoft.Online.Workflows.ApplicationManagementPolicyValidationException type of error being logged.
Speaking of the audit log, I don’t believe we covered that in our previous articles on Application management policies. Not that there is much to cover here – as expected any CRUD event will be diligently logged in, along with the corresponding list of modified properties. It all falls down under the Core Directory service and the Policy category, whereas any application management policy violation events will be logged under the ApplicationManagement category.
Before I forget, I need to mention something important. When providing the JSON payload for any PATCH operation, make sure to include any already configured restrictions under the corresponding node (servicePrincipalRestrictions and/or applicationRestrictions). Failing to do so, such as in the examples we used below, will override the existing values, which is probably not what you desire. Please treat the examples above as just that, examples, and not a full fledged solution.
Lastly, if you take a closer look at the applicationRestrictions resource as returned in GET requests, you will likely notice the audiences subresource. This one however is not yet documented, so at this point is unclear what exactly it is used for. If I were to make an educated guess, it is likely intended to set restrictions on the signInAudience property, i.e. restrict app creation to only single-tenant apps. We shall see.
And with that, we can close this short update on the application management policies in Entra ID. It’s good to see Microsoft adding additional controls to this feature, and we can also get glimpses of future updates, too. On the other hand, the fact that Microsoft now enforces a Workload Identity SKU requirement greatly diminishes the usefulness of these policies.