How to Audit Azure RBAC Role Assignments
Permission creep is silent. A contractor finishes a project and their access remains. Someone moves team and their old role stays attached. An admin grants Owner at subscription scope because it was faster than working out the minimum. None of this is malicious. All of it is how 80% of cloud breaches happen.
Auditing Azure RBAC role assignments is how you find the creep before it becomes the headline. This guide covers the three tools that matter: Activity Logs for tracking changes, the Azure CLI and PowerShell for enumerating what actually exists, and Privileged Identity Management for the high-risk roles that need more than a quarterly review.
Use Azure Activity Logs to track changes
Every role assignment change in Azure is logged in the Activity Log. Grants, revocations, and custom role modifications all appear there, timestamped and attributed to the caller who made the change.
To surface RBAC-specific events, navigate to Monitor > Activity Log in the portal. Set the Event Category filter to Administrative and narrow the Operation field to the events that matter:
Create role assignment(new permissions granted)Delete role assignment(permissions revoked)Create or update custom role definition(role scope modified)
For tighter focus, filter the Resource Provider field to Microsoft.Authorization. This strips out unrelated admin events and leaves you with a clean RBAC audit trail.
Each log entry carries several fields worth reading carefully. The authorization:action field shows what operation occurred. The authorization:scope field shows where: subscription level, resource group, or a specific resource. The caller field identifies who made the change. Cross-reference against your change management records. An authorised change looks different from an unexplained one. The correlationId ties related operations together if you need to reconstruct a sequence.
Activity Logs retain data for 90 days. For longer retention, route them to a Log Analytics workspace or a storage account. Regulated businesses often need to hold access logs for 12 months or more under FCA, PCI DSS, or UK GDPR requirements. Configure the retention period to match your obligations before you need the history, not after.
Enumerate role assignments with Azure CLI and PowerShell
Activity Logs show changes. The CLI shows the current state: every role assignment that exists right now across your subscription.
The core command is:
az role assignment list --all --output json \
--query '[].{principalName:principalName, roleDefinitionName:roleDefinitionName, scope:scope}'
The --all flag captures assignments across the subscription and all child resources. Without it you only see assignments at the subscription level and miss everything scoped below.
For a specific user:
az role assignment list --all --assignee user@company.com \
--output json --include-inherited
For group-based assignments, add --include-groups. This captures roles assigned through Microsoft Entra ID group membership, not just direct assignments. Groups are where inherited permissions live, and direct commands miss them unless you ask explicitly.
Nested group membership is where most audits fall short. If User A is in Group B, and Group B is in Group C, and Group C has Contributor at a resource group, User A has Contributor. The default CLI commands show the group assignment; they do not recursively follow the chain to the individual. PowerShell handles this properly:
function Get-NestedGroupMembers {
param([string]$GroupId)
$members = Get-AzADGroupMember -GroupObjectId $GroupId
foreach ($member in $members) {
if ($member.OdataType -eq '#microsoft.graph.group') {
Get-NestedGroupMembers -GroupId $member.Id
} else {
$member
}
}
}
Run this recursively across your top-level groups to surface every user who has permissions, however many layers deep.
Export the results to CSV for comparison across audit cycles:
Get-AzRoleAssignment | Select-Object RoleDefinitionName, DisplayName, SignInName, Scope |
Export-Csv -Path "rbac-audit-$(Get-Date -Format 'yyyy-MM-dd').csv" -NoTypeInformation
Keep monthly snapshots. The comparison between this month and last month is where you find the changes that should not have happened.
Use Privileged Identity Management for high-risk roles
Activity Logs and CLI give you visibility. Privileged Identity Management (PIM) changes how high-risk roles are structured so they are safer by default.
PIM replaces standing admin assignments with just-in-time access. Instead of having a permanent Owner or Global Administrator assignment, a user has an eligible assignment. When they need the role, they activate it: they provide a justification, optionally a ticket reference, and the role activates for a defined window (typically 1 to 8 hours) before expiring automatically. No standing access means no standing target.
Configure PIM for each sensitive role by setting activation requirements that match the risk level. For Global Administrator, require MFA and manager approval. For Contributor at subscription scope, MFA and a business justification is usually sufficient. The activation duration should be the shortest practical window for the work. For production break-glass access, 1 to 2 hours is usually right.
PIM Access Reviews run on a schedule you define. Quarterly works for most organisations; regulated businesses in financial services often run them monthly. The review interface presents each role assignment and asks the reviewer (often the user's direct manager): does this person still need this access? Yes proceeds, no removes it automatically after the review closes. The review itself produces a log of who approved what, which is exactly the evidence an auditor asks for.
Route PIM audit logs to Azure Monitor via Log Analytics. The default 30-day retention in PIM is not sufficient for GDPR, FCA, or PCI DSS purposes. Log Analytics lets you set longer retention and query across PIM events alongside your other security signals. Alert on critical patterns: non-PIM role assignments on sensitive roles, MFA bypass on activation, bulk activations outside business hours.
Build a repeatable audit schedule
A one-off audit is a snapshot. A repeatable schedule is a control.
The minimum viable cadence for most organisations is a quarterly full review: enumerate all role assignments via CLI, export to CSV, compare to the previous quarter's export, and investigate any new assignments at sensitive scopes. Owner and Contributor at subscription level get reviewed regardless of whether they changed. Service principals with broad permissions need the same scrutiny as human accounts.
Before each review, run the nested group membership export. Groups change between audits, and a group that previously contained three people now containing thirty is something you want to catch systematically rather than stumble on during an incident.
Document every audit finding and every action taken. This is not administrative overhead; it is the evidence that demonstrates your access controls are maintained, which is what regulators and auditors ask for. A spreadsheet with date, finding, action taken, and who approved the action satisfies most audit requirements without needing specialist tooling.
For businesses scaling into multi-subscription environments, Azure Policy can enforce RBAC governance automatically: deny Owner assignments at subscription scope except from a designated break-glass process, require justification tags on assignments above a certain scope, and alert when privileged assignments are made outside PIM. Policy-enforced governance is more reliable than review-only governance because it catches violations at creation rather than after the fact.
Where Critical Cloud comes in
Auditing RBAC correctly, running PIM access reviews on schedule, and producing the evidence that regulated businesses need for FCA, PCI DSS, and GDPR audits is part of how we operate Azure for clients across financial services, insurance, and healthcare. As the world's first Powered by Datadog accredited partner, we surface access and identity signals in the same observability layer as infrastructure and application data, so anomalous access patterns appear in the same place as the operational events they precede. If keeping Azure access under control is pulling your team away from building, see how Critical Support works.