Managing Azure AD Recommendations via the Graph API

Azure Active Directory Recommendations is a nifty feature that highlights potential improvements you can act on in order to improve your tenant’s security posture and overall health. The feature has been available for a while now, and can be also thought of as a trimmed down version of the Security scope/Identity secure score recommendations. In this article, we will go over the recently introduced Graph API endpoint to list and manage Azure AD recommendations.

As usual with anything Graph, you will need the necessary permissions first. For this feature, they come in two shapes: DirectoryRecommendations.Read.All and DirectoryRecommendations.ReadWrite.All with the first one being “read-only”, whereas the second one allowing for “edit” operations. Both delegation and application permissions are supported. Should you choose to use delegate permissions, you will also need to have an admin role assigned, with sufficient permissions to read or manage the recommendations. The least privileged “read” role is Security Reader (or Reports reader, depending on what your criteria is), whereas the least privileged “edit” role is Cloud application administrator. I’m not entirely sure what application roles have to do with Azure AD Recommendations, but that’s what the documentation reads. You can also use the Security operator role.

Once you have the permissions granted, you can query the set of Azure AD recommendations via the /directory/recommendations endpoint. An example using the Graph explorer tool is shown below. You might notice that the set of recommendations returned by the Graph API differs from the ones displayed in the Azure AD UI. The reason is that the UI seems to only show “incomplete” recommendations, for which the maxScore property does not match the (rounded up) currentScore (not reflective of the actual status property).

GET https://graph.microsoft.com/beta/directory/recommendations

AADRecommendationsTo get the details on specific recommendation object, you can also use the /directory/recommendations/{id} endpoint, though for getting the insanely convoluted id value, you’d still have to run the LIST method first. An alternative approach would be to use a $filter query based on category, featureAreas or recommendationType value. Refer to the official documentation for more info on those.

The set of actions you can take against a recommendation object include Dismiss, Postpone, Complete, and Reactivate. The Dismiss action (POST against /directory/recommendations/{recommendationId}/dismiss) basically disables the recommendation as not applicable, and you can provide the dismissReason as justification. The Postpone action (POST against /directory/recommendations/{recommendationId}/postpone) tells the service to stop bothering you about the given recommendation until the designated postponeUntilDateTime date. The Complete action (POST against /directory/recommendations/{recommendationId}/complete) informs the service that the recommended steps were manually applied by you (or another admin). Lastly, the Reactivate action (POST agains /directory/recommendations/{recommendationId}/reactivate) undoes any of the previous three and sets the status of a given recommendation to “active”.

The most interesting part of the recommendation object is the associated set of impacted resources, represented via the impactedResource resource type. To list the set of impacted resources, use a GET request against the /directory/recommendations/{id}/impactedResources endpoint. Note that not every recommendation will return such a list, even if the description/insights property ensures you you have at least one object of interest.

GET https://graph.microsoft.com/beta/directory/recommendations/icrosoft.Identity.IAM.Insights.TurnOffPerUserMFA

AADRecommendations1In case the query does return a list of impacted objects, you can issue additional queries against each of them, via the /directory/recommendations/{recommendationId}/impactedResources/{impactedResourceId} endpoint, where you also have to provide the impacted object’s ID value (matches the actual directory object ID). You’re probably better off querying the getByIds endpoint instead.

GET https://graph.microsoft.com/beta/directory/recommendations/923712ba-352a-4eda-bece-09d0684d0cfb_Microsoft.Identity.IAM.Insights.StaleApps/impactedResources/9dd50c8b-0eb9-47e9-af9e-80d200b11505

AADRecommendations2Instead of listing the set of impacted resources one by one, you can also include them in the /recommendation query, by using the following syntax:

GET https://graph.microsoft.com/beta/directory/recommendations?$expand=impactedResources

For each impacted resource object, you can use the same four operations we described above: Postpone, Dismiss, Complete and Reactivate. They serve the exact same purpose as above, so I will not repeat them. Instead, we can perform the Dismiss action as an example. As this is an edit operation, so we will need the DirectoryRecommendations.ReadWrite.All permission! Here’s the corresponding request:

POST https://graph.microsoft.com/beta/directory/recommendations/923712ba-352a-4eda-bece-09d0684d0cfb_Microsoft.Identity.IAM.Insights.StaleApps/impactedResources/9dd50c8b-0eb9-47e9-af9e-80d200b11505/dismiss

AADRecommendations3Do note that updating the status of the impacted resource to Dismissed will not cause it to disappear from the list of impactedResources. The change in status should however be immediately visible in both the Graph API output and the UI. This is contrast to the regular processing of Azure AD recommendation objects, which happens once per day.

And that’s it in a nutshell. The Azure AD recommendations feature is quite straightforward to use and does not offer much in terms of customizability or actions to perform, thus the corresponding Graph API endpoints are on the light side. They are however important for automation scenarios, especially when you want to run things at scale across multiple tenants. Not only you can easily obtain a set of recommendations, along with their corresponding sets of impacted resources, suggested actions and additional insights, but you can quickly and in bulk dismiss, postpone or complete recommendations as needed, or reactivate the to bring back the attention of the tenant’s admins. Overall, a good functionality to have!

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.