Introduction
Entra ID offers a feature called Administrative Units that act as containers for Entra ID resources, allowing you to group together users, groups, and other resources. This is particularly useful for larger organizations that require a way to delegate administrative tasks to different departments or teams. An enhanced version of Administrative Units, known as Restricted Management Administrative Units, provides an additional layer of security for privileged accounts by restricting who can manage these accounts.
In this blog post, we will explore the use of Kusto Query Language (KQL) to interact with these Administrative Units, specifically focusing on Restricted Management Administrative Units.
KQL Queries for Administrative Units
Here are several KQL examples that you can use to interact with Administrative Units:
List all AdministrativeUnit Category Events
//List all AdministrativeUnit Category Events
AuditLogs | where Category == "AdministrativeUnit"
This query lists all events that fall under the “AdministrativeUnit” category.
List all AdministrativeUnit Category where OperationName equals Add administrative unit
AuditLogs | where Category == "AdministrativeUnit" and OperationName == "Add administrative unit"
This query lists all events where an administrative unit was added.
List all AdministrativeUnit Category where OperationName equals Delete administrative unit
AuditLogs | where Category == "AdministrativeUnit" and OperationName == "Delete administrative unit"
This query lists all events where an administrative unit was deleted.
List all AdministrativeUnit Category where OperationName equals Add administrative unit with additional details
AuditLogs | where Category == "AdministrativeUnit" and OperationName == "Add administrative unit"
| extend DisplayName=extractjson("$.[0].displayName",tostring(TargetResources))
| mv-expand Description=parse_json(tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[0].newValue))
| extend IsMemberManagementRestricted=iff(tostring(parse_json(tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[2].newValue))) contains "true","Yes","No")
| extend UserPrincipalName=extractjson("$.user.userPrincipalName",tostring(InitiatedBy))
| project TimeGenerated,DisplayName,Description,IsMemberManagementRestricted,UserPrincipalName,OperationName
This query lists all events where an administrative unit was added, along with additional details such as the display name, description, whether member management is restricted, the user principal name, and the operation name.
List all AdministrativeUnit Category where OperationName equals Delete administrative unit with additional details
//List all AdministrativeUnit Category where OperationName equals Delete administrative unit
AuditLogs | where Category == "AdministrativeUnit" and OperationName == "Delete administrative unit"
| extend DisplayName=extractjson("$.[0].displayName",tostring(TargetResources))
| extend IsMemberManagementRestricted=iff(tostring(parse_json(tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[2].newValue))) contains "true","Yes","No")
| extend UserPrincipalName=extractjson("$.user.userPrincipalName",tostring(InitiatedBy))
| project TimeGenerated,DisplayName,IsMemberManagementRestricted,UserPrincipalName,OperationName
This query lists all events where an administrative unit was deleted, along with additional details such as the display name, whether member management is restricted, the user principal name, and the operation name.
List all AdministrativeUnit Category Events where OperationName equals Add member to restricted management administrative unit
//List all AdministrativeUnit Category Events where OperatationName equals Add member to restricted management administrative unit
//This query lists the object type that was added to the Administrative Unit
AuditLogs | where Category == "AdministrativeUnit" and OperationName == "Add member to restricted management administrative unit"
| extend InitiatedBy=extractjson("$.user.userPrincipalName",tostring(InitiatedBy))
| extend Type = tostring(parse_json(tostring(parse_json(tostring(TargetResources[0])).type)))
| extend ["Target Object"] = case(
Type == "User", tostring(parse_json(tostring(parse_json(tostring(TargetResources[0])).userPrincipalName))),
Type == "Device", tostring(parse_json(tostring(parse_json(tostring(TargetResources[0])).displayName))),
Type == "Group", tostring(parse_json(tostring(parse_json(tostring(TargetResources[0])).displayName))),
"N/A"
)
| project TimeGenerated,InitiatedBy,Type,['Target Object'],OperationName
This query lists all events where a member was added to a restricted management administrative unit, along with the type of object that was added.
List all AdministrativeUnit Category Events where OperationName equals Remove member from restricted management administrative unit
//List all AdministrativeUnit Category Events where OperatationName equals Remove member from restricted management administrative unit
//This query lists the object type that was removed from the Administrative Unit
AuditLogs | where Category == "AdministrativeUnit" and OperationName == "Remove member from restricted management administrative unit"
| extend InitiatedBy=extractjson("$.user.userPrincipalName",tostring(InitiatedBy))
| extend Type = tostring(parse_json(tostring(parse_json(tostring(TargetResources[0])).type)))
| extend ["Target Object"] = case(
Type == "User", tostring(parse_json(tostring(parse_json(tostring(TargetResources[0])).userPrincipalName))),
Type == "Device", tostring(parse_json(tostring(parse_json(tostring(TargetResources[0])).displayName))),
Type == "Group", tostring(parse_json(tostring(parse_json(tostring(TargetResources[0])).displayName))),
"N/A"
)
| project TimeGenerated,InitiatedBy,Type,['Target Object'],OperationName
This query lists all events where a member was removed from a restricted management administrative unit, along with the type of object that was removed.
List RoleManagement Category and Add eligible member to role in PIM requested (permanent) OperationName events
//List RoleManagement Category and Add eligible member to role in PIM requested (permanent) OperationName events
//This query lists the assigned role and the administrative unit that the role was asssigned
AuditLogs | where OperationName == "Add eligible member to role in PIM requested (permanent)" and Category == "RoleManagement"
| extend InitiatedBy=extractjson("$.user.userPrincipalName",tostring(InitiatedBy))
| extend ["Object Type"] = tostring(parse_json(tostring(parse_json(tostring(TargetResources[2])).type)))
| extend ["Display Name"] = tostring(parse_json(tostring(parse_json(tostring(TargetResources[2])).displayName)))
| extend ["Administrative Unit"] = tostring(parse_json(tostring(parse_json(tostring(TargetResources[5])).displayName)))
| extend ["Delegated Role"] = tostring(parse_json(tostring(parse_json(tostring(TargetResources[0])).displayName)))
| project TimeGenerated,InitiatedBy,['Object Type'], ['Display Name'], ['Administrative Unit'], ['Delegated Role']
This query lists all events where an eligible member was added to a role in Privileged Identity Management (PIM), along with details about the object type, display name, administrative unit, and delegated role.
List RoleManagement Category and Remove eligible member from role in PIM completed (permanent) OperationName events
//List RoleManagement Category and Remove eligible member from role in PIM completed (permanent) OperationName events
//This query lists the assigned role and the administrative unit that the role was removed
AuditLogs | where OperationName == "Remove eligible member from role in PIM completed (permanent)" and Category == "RoleManagement"
| extend InitiatedBy=extractjson("$.user.userPrincipalName",tostring(InitiatedBy))
| extend ["Object Type"] = tostring(parse_json(tostring(parse_json(tostring(TargetResources[2])).type)))
| extend ["Display Name"] = tostring(parse_json(tostring(parse_json(tostring(TargetResources[2])).displayName)))
| extend ["Administrative Unit"] = tostring(parse_json(tostring(parse_json(tostring(TargetResources[5])).displayName)))
| extend ["Delegated Role"] = tostring(parse_json(tostring(parse_json(tostring(TargetResources[0])).displayName)))
| project TimeGenerated,InitiatedBy,['Object Type'], ['Display Name'], ['Administrative Unit'], ['Delegated Role']
This query lists all events where an eligible member was removed from a role in Privileged Identity Management (PIM), along with details about the object type, display name, administrative unit, and delegated role.
Conclusion
These KQL examples provide a easy way to interact with Restricted Management Administrative Units in Entra ID. They allow you to list all events related to these units, add or remove members, and even manage roles within the units. By understanding and leveraging these queries, you can manage your Entra ID environment and ensure the security of your privileged accounts.