Query Details

Unified Identity Info

Query

id: 94a61b2d-bf7e-4255-8003-c9722ce1d6c9
Function:
  Title: Parser for to get a list of all non-privileged and privileged users but also workload identities
  Version: '1.0.0'
  LastUpdated: '2023-11-11'
Category: Microsoft Sentinel Parser
FunctionName: UnifiedIdentityInfo
FunctionAlias: UnifiedIdentityInfo
FunctionQuery: |
    // Function to get a list of all non-privileged and privileged users but also workload identities
    let SensitiveEntraDirectoryRoles = externaldata(RoleName: string, RoleId: string, isPrivileged: bool, Classification: dynamic)["https://raw.githubusercontent.com/Cloud-Architekt/AzurePrivilegedIAM/main/Classification/Classification_EntraIdDirectoryRoles.json"] with(format='multijson')
    | where Classification.EAMTierLevelName != "Unclassified"
    | project RoleName, isPrivileged, Classification;
    let SensitiveUsers = IdentityInfo
    | where TimeGenerated > ago(14d)
    | summarize arg_max(TimeGenerated, *) by AccountObjectId
    | mv-expand AssignedRoles
    | extend RoleName = tostring(AssignedRoles)
    | join kind=inner ( SensitiveEntraDirectoryRoles ) on RoleName
    | extend AadDirectoryRoleTierLevels = parse_json(Classification.EAMTierLevelName)
    | extend Classification = iif((AadDirectoryRoleTierLevels contains "ControlPlane"), "ControlPlane", "Unclassified")
    | extend Classification = iif((Classification == "Unclassified" and (AadDirectoryRoleTierLevels contains "ManagementPlane")), "ManagementPlane", Classification)
    | extend Classification = iif((Classification == "Unclassified" and (AadDirectoryRoleTierLevels contains "WorkloadPlane")), "WorkloadPlane", Classification)
    | extend Classification = iif((Classification == "Unclassified" and (AadDirectoryRoleTierLevels contains "UserAccess")), "UserAccess", Classification)
    | summarize RoleAssignments = make_set(RoleName) by AccountObjectId, AccountDisplayName, AccountUPN, OnPremisesAccountObjectId, DeletedDateTime, Classification;
    let PrivilegedUsers = SensitiveUsers
    | extend OnPremSynchronized = iff(isnotempty(OnPremisesAccountObjectId), "true", "false")
    | extend IsDeleted =  iff(isnotempty(DeletedDateTime), "true", "false")    
    | project
        ObjectId = tostring(AccountObjectId),
        ObjectType = "User",
        ObjectDisplayName = AccountDisplayName,
        UserPrincipalName = AccountUPN,
        OnPremSynchronized,
        IsDeleted,
        tostring(Classification),
        EntraIdRoles = RoleAssignments;
    let AllUsers = IdentityInfo
    | where TimeGenerated > ago(14d)
    | summarize arg_max(TimeGenerated, *) by AccountObjectId
    | extend ObjectId = tostring(AccountObjectId)
    | join kind=leftanti ( PrivilegedUsers ) on ObjectId
    | extend DefaultPermissionClassification = "UserAccess"
    | extend OnPremSynchronized = iff(isnotempty(OnPremisesAccountObjectId), "true", "false")
    | extend IsDeleted =  iff(isnotempty(DeletedDateTime), "true", "false")
    | project
        ObjectId,
        ObjectType = "User",
        ObjectDisplayName = AccountDisplayName,
        OnPremSynchronized,
        IsDeleted,
        Classification = DefaultPermissionClassification;
    let PrivilegedWorkloads = PrivilegedWorkloadIdentityInfo
    | where isnotempty(EntraIdRoles) or isnotempty(AppRolePermissions)
    | project
        ObjectId = tostring(ServicePrincipalObjectId),
        ObjectType = WorkloadIdentityType,
        ObjectDisplayName = WorkloadIdentityName,
        OnPremSynchronized = "false",
        Classification = tostring(EnterpriseAccessModelTiering),
        EntraIdRoles = EntraIdRoles,
        AppRoles = AppRolePermissions;
    union AllUsers, PrivilegedUsers, PrivilegedWorkloads

Explanation

This query is designed to create a comprehensive list of users and workload identities in a Microsoft environment, categorizing them based on their privilege levels and roles. Here's a simplified breakdown of what the query does:

  1. Sensitive Entra Directory Roles: It retrieves a list of directory roles from an external JSON source, filtering out any roles that are "Unclassified". It identifies whether these roles are privileged or not.

  2. Sensitive Users: It gathers information about users from the IdentityInfo table, focusing on data from the last 14 days. It identifies users with assigned roles, joins this data with the sensitive roles list, and classifies users based on their role's tier level (e.g., ControlPlane, ManagementPlane, WorkloadPlane, UserAccess). It summarizes the role assignments for each user.

  3. Privileged Users: From the list of sensitive users, it extracts details about users with privileged roles, noting whether their accounts are synchronized with on-premises directories and if they are deleted.

  4. All Users: It compiles a list of all users from the IdentityInfo table, excluding those already identified as privileged. It assigns a default classification of "UserAccess" to these users and notes their synchronization and deletion status.

  5. Privileged Workloads: It identifies workload identities (like service principals) with privileged roles or app role permissions, classifying them based on their enterprise access model tiering.

  6. Union of Results: Finally, it combines the lists of all users, privileged users, and privileged workloads into a single comprehensive list. This list includes both privileged and non-privileged users, as well as workload identities, providing a complete overview of identities in the environment.

Details

Thomas Naunheim profile picture

Thomas Naunheim

Released: December 17, 2023

Tables

IdentityInfoPrivilegedWorkloadIdentityInfo

Keywords

MicrosoftSentinelParserUsersWorkloadIdentitiesRolesClassification

Operators

externaldatawithwhereprojectsummarizearg_maxmv-expandextendtostringjoinkindparse_jsoniifcontainsmake_setiffisnotemptyleftantiunion

Actions

GitHub