Query Details

Graph Activity From First Party Apps

Query

// Get a list of first party apps with activity to Microsoft Graph and enriched classification
let SensitiveMsGraphPermissions = externaldata(AppId: guid, AppRoleId: guid, AppRoleDisplayName: string, Category: string, EAMTierLevelName: string, EAMTierLevelTagValue: string)["https://raw.githubusercontent.com/Cloud-Architekt/AzurePrivilegedIAM/main/Classification/Classification_AppRoles.json"] with (format='multijson')
    | where isnotempty(EAMTierLevelName)
    // Optional: Filtering for Control Plane only
    //| where EAMTierLevelName == "ControlPlane"    
    | distinct AppRoleDisplayName;
_GetWatchlist('WorkloadIdentityInfo')
| where IsFirstPartyApp == "True"
| extend Identity = tostring(ServicePrincipalObjectId)
| join kind=inner (
    MicrosoftGraphActivityLogs
    | where TimeGenerated >ago(365d)
    | where Roles has_any (SensitiveMsGraphPermissions)
    | extend Roles = split(Roles, ' ')
    | extend Identity = ServicePrincipalId
) on Identity
| summarize make_set( Roles ) by AppDisplayName, ServicePrincipalObjectId

Explanation

This query retrieves a list of first-party apps that have activity to Microsoft Graph and enriched classification. It uses external data to get sensitive Microsoft Graph permissions and filters for apps with a non-empty tier level name. It then joins this data with the 'WorkloadIdentityInfo' watchlist and filters for first-party apps. Finally, it retrieves Microsoft Graph activity logs for the past year and summarizes the roles for each app and service principal.

Details

Thomas Naunheim profile picture

Thomas Naunheim

Released: February 16, 2024

Tables

_GetWatchlistMicrosoftGraphActivityLogs

Keywords

Devices,Intune,User,MicrosoftGraph,enrichedclassification,firstpartyapps,activity,AppId,AppRoleId,AppRoleDisplayName,Category,EAMTierLevelName,EAMTierLevelTagValue,WorkloadIdentityInfo,IsFirstPartyApp,Identity,ServicePrincipalObjectId,MicrosoftGraphActivityLogs,TimeGenerated,Roles,AppDisplayName

Operators

externaldatawithwhereisnotemptydistinctextendjoinkindwhereTimeGeneratedagohas_anysplitsummarizeby

Actions