Query Details
AuditLogs
| where Category == "ApplicationManagement" and LoggedByService == "Core Directory" and OperationName in ("Add delegated permission grant", "Add app role assignment to service principal")
| mv-expand TargetResource = TargetResources
//| where tostring(TargetResource["displayName"]) == "Microsoft Graph"
| mv-expand modifiedProperty = TargetResource["modifiedProperties"]
| where tostring(modifiedProperty["displayName"]) in ("AppRole.Value", "DelegatedPermissionGrant.Scope")
| extend PermissionGrant = trim(@'[\"\s]+', tostring(modifiedProperty["newValue"]))
| where PermissionGrant has "RoleManagement.ReadWrite.Directory"
| mv-apply modifiedProperty = TargetResource["modifiedProperties"] on (
summarize modifiedProperties = make_bag(
pack(tostring(modifiedProperty["displayName"]),
pack("oldValue", trim(@'[\"\s]+', tostring(modifiedProperty["oldValue"])),
"newValue", trim(@'[\"\s]+', tostring(modifiedProperty["newValue"])))))
)
| project
TimeGenerated,
OperationName,
Result,
PermissionGrant,
//AppDisplayName for operation "Add delegated permission grant" will be in operation "Consent to application" (usually same CorrelationId)
AppDisplayName = tostring(modifiedProperties["ServicePrincipal.DisplayName"]["newValue"]),
AppServicePrincipalId = tostring(modifiedProperties["ServicePrincipal.ObjectID"]["newValue"]),
Initiator = iif(isnotempty(InitiatedBy["app"]), tostring(InitiatedBy["app"]["displayName"]), tostring(InitiatedBy["user"]["userPrincipalName"])),
InitiatorId = iif(isnotempty(InitiatedBy["app"]), tostring(InitiatedBy["app"]["servicePrincipalId"]), tostring(InitiatedBy["user"]["id"])),
InitiatedBy,
TargetResources,
AdditionalDetails,
CorrelationId
This query is looking at audit logs where the category is "ApplicationManagement", the service that logged the event is "Core Directory", and the operation name is either "Add delegated permission grant" or "Add app role assignment to service principal".
It then expands the target resources and modified properties fields. It filters the results to only include those where the modified property display name is either "AppRole.Value" or "DelegatedPermissionGrant.Scope".
The query then trims any extra spaces or quotation marks from the new value of the modified property and assigns it to a new field called "PermissionGrant". It further filters the results to only include those where the permission grant includes "RoleManagement.ReadWrite.Directory".
The query then summarizes the modified properties by creating a bag that includes the display name, old value, and new value of the modified property.
Finally, the query projects several fields including the time the event was generated, the operation name, the result, the permission grant, the display name of the app, the ID of the app's service principal, the initiator of the event, the ID of the initiator, the resources targeted by the event, any additional details, and the correlation ID.
In simple terms, this query is looking at specific types of changes made to app permissions and roles in the audit logs, and provides detailed information about these changes.

Jose Sebastián Canós
Released: January 4, 2023
Tables
Keywords
Operators