Query Details

Az ADSPI Enriched By Entra Ops

Query

id: 571107c2-5abe-49ff-9867-445805502add
Function:
  Title: Parser for AzADServicePrincipalInsights with enriched classification of EntraOps
  Version: '1.0.0'
  LastUpdated: '2023-11-11'
Category: Microsoft Sentinel Parser
FunctionName: PrivilegedAzADSPI
FunctionAlias: PrivilegedAzADSPI
FunctionQuery: |
    let SensitiveMsGraphPermissions = externaldata(EAMTierLevelName: string, Category: string, AppRoleDisplayName: string)["https://raw.githubusercontent.com/Cloud-Architekt/AzurePrivilegedIAM/main/Classification/Classification_AppRoles.json"] with(format='multijson');
    let SensitiveAadDirectoryRoles = externaldata(Classification: string, RolePermissions: string, Category: string, RoleId: string)["https://raw.githubusercontent.com/Cloud-Architekt/AzurePrivilegedIAM/main/Classification/Classification_EntraIdDirectoryRoles.json"] with(format='multijson') | mv-expand parse_json(RolePermissions)
    | summarize Category = make_list(RolePermissions.Category) by AadDirectoryRoleId = RoleId, AadDirectoryRoleTierLevel = tostring(parse_json(Classification).EAMTierLevelName);
    let SpWithAppRole = AzADServicePrincipalInsights_CL
    | where TimeGenerated > ago(14d)
    | summarize arg_max(TimeGenerated, *) by ObjectId
    | mv-expand parse_json(SPAppRoleAssignments)
    | mv-expand SPAppRoleAssignments.AppRolePermission
    | extend AppRolePermission = tostring(SPAppRoleAssignments_AppRolePermission) 
    | extend SPObjectId = tostring(parse_json(SP)[0].SPObjectId)
    | join kind=leftouter(
        SensitiveMsGraphPermissions | project AppRolePermissionTierLevel = EAMTierLevelName, AppRolePermission = AppRoleDisplayName, Category
        ) on AppRolePermission
    | where isnotempty(AppRolePermission)
    | summarize AppRolePermissions = make_set(AppRolePermission), AppRolePermissionTierLevels = make_set(AppRolePermissionTierLevel) by SPObjectId;
    let SpWithDirectoryRole = AzADServicePrincipalInsights_CL
    | where TimeGenerated > ago(14d)
    | summarize arg_max(TimeGenerated, *) by ObjectId
    | mv-expand parse_json(SPAADRoleAssignments)
    | mv-expand SPAADRoleAssignments.roleDefinitionName, SPAADRoleAssignments.roleDefinitionId
    | extend AadDirectoryRoleId = tostring(SPAADRoleAssignments_roleDefinitionId)
    | extend AadDirectoryRoleName = tostring(SPAADRoleAssignments_roleDefinitionName)
    | extend SPObjectId = tostring(parse_json(SP)[0].SPObjectId)
    | join kind=leftouter(
        SensitiveAadDirectoryRoles
        ) on AadDirectoryRoleId
    | where isnotempty(AadDirectoryRoleName)
    | summarize AadDirectoryRoles = make_set(AadDirectoryRoleName), AadDirectoryRoleTierLevels = make_set(AadDirectoryRoleTierLevel) by SPObjectId;
    AzADServicePrincipalInsights_CL
    | where TimeGenerated > ago(14d)
    | summarize arg_max(TimeGenerated, *) by ObjectId
    | extend AppObjectId = tostring(parse_json(APP)[0].APPObjectId)
    | extend SPObjectId = tostring(parse_json(SP)[0].SPObjectId)
    | join kind=leftouter (
        union SpWithAppRole, SpWithDirectoryRole
        | summarize AppRolePermissions = make_set(AppRolePermissions), AppRolePermissionTierLevels = make_set(AppRolePermissionTierLevels), AadDirectoryRoles = make_set(AadDirectoryRoles), AadDirectoryRoleTierLevels = make_set(AadDirectoryRoleTierLevels) by SPObjectId
        ) on SPObjectId
    | extend Classification = iif((AppRolePermissionTierLevels contains "ControlPlane" or AadDirectoryRoleTierLevels contains "ControlPlane"), "ControlPlane", "Unclassified")
    | extend Classification = iif((Classification == "Unclassified" and (AppRolePermissionTierLevels contains "ManagementPlane" or AadDirectoryRoleTierLevels contains "ManagementPlane")), "ManagementPlane", Classification)
    | extend Classification = iif((Classification == "Unclassified" and (AppRolePermissionTierLevels contains "WorkloadPlane" or AadDirectoryRoleTierLevels contains "WorkloadPlane")), "WorkloadPlane", Classification)
    | extend Classification = iif((Classification == "Unclassified" and (AppRolePermissionTierLevels contains "UserAccess" or AadDirectoryRoleTierLevels contains "UserAccess")), "UserAccess", Classification)
    | extend WorkloadIdentityType = iff(ObjectType contains "SP MI", "ManagedIdentity", "Application")
    | project 
        WorkloadIdentityName = tostring(parse_json(SP)[0].SPDisplayName),
        WorkloadIdentityType,
        ServicePrincipalObjectId = SPObjectId,
        ServicePrincipalOwners = SPOwners,
        ServicePrincipalType = ObjectType,
        ApplicationObjectId = AppObjectId,
        ApplicationId = tostring(parse_json(SP)[0].SPAppId),
        ApplicationOwners = APPAppOwners,
        EntraIdRoles = AadDirectoryRoles,
        EntraGroupMemberships = APPAppOwners,
        AppRolePermissions,
        AzureRoles = SPAzureRoleAssignments,
        EnterpriseAccessModelTiering = Classification

Explanation

The query is used to parse and classify Azure Active Directory (AAD) service principal insights. It retrieves sensitive Microsoft Graph permissions and sensitive AAD directory roles from external data sources. It then joins the service principal insights with the retrieved data to determine the app role permissions, AAD directory roles, and their respective tier levels. Finally, it assigns a classification to the service principal based on the app role permission and AAD directory role tier levels, and returns various attributes of the service principal, including its workload identity name, type, object ID, owners, application ID, and more.

Details

Thomas Naunheim profile picture

Thomas Naunheim

Released: November 11, 2023

Tables

AzADServicePrincipalInsights_CL

Keywords

Devices,Intune,User,Azure,App,Classification

Operators

externaldatawithsummarizemv-expandparse_jsonextendjoinprojectwhereisnotemptymake_setunioniififf

Actions