How to Audit User Permissions in Azure: A Step-by-Step Guide

Managing who has access to what in your Azure environment is crucial for security. For IT administrators, security teams, and Azure subscription owners, regular permission audits help prevent unauthorized access and maintain compliance.
This guide walks you through auditing Azure permissions using both the Azure Portal and PowerShell, and shows you how to analyze results to fix potential security gaps.
Understanding Azure Permissions Fundamentals
Key Azure Identity Management Concepts
When you’re diving into Azure permissions, you need to grasp a few core concepts first. Your Azure environment relies on these fundamental building blocks:
- Principals: These are the “who” – users, groups, service principals, or managed identities that need access to resources
- Scopes: These define the “where” – management groups, subscriptions, resource groups, or resources that can be accessed
- Roles: These determine the “what” – collections of permissions that specify allowed actions
Think of it like keys to different rooms in a building. Some people get master keys, others only access specific areas. Your identity in Azure works the same way – it determines which doors open for you.
Role-Based Access Control (RBAC) Explained
RBAC is your permission system in Azure. It’s how you control who can do what with your resources. Here’s how it works:
- You assign roles to users at specific scopes
- Each role contains permissions that allow certain actions
- Azure checks these permissions whenever someone tries to access a resource
Azure offers built-in roles like Owner, Contributor, and Reader. The Owner can do anything, the Contributor can create and manage resources but can’t grant access to others, while the Reader can only view resources.
You can also create custom roles when the built-in options don’t quite fit your needs. This gives you fine-grained control over exactly what actions your team members can perform.
Azure Active Directory Integration
Azure AD is your identity backbone. It’s where you manage all users, groups, and applications that need access to your Azure resources. When you connect RBAC with Azure AD, you get a powerful security system.
With Azure AD, you can:
- Create and manage user accounts and groups
- Set up multi-factor authentication
- Enable conditional access policies
- Implement single sign-on
Azure AD handles authentication (proving who you are), while RBAC handles authorization (determining what you can do). Together, they form a comprehensive security framework for your cloud resources.
Common Permission Security Risks
Watch out for these permission pitfalls that could leave your Azure environment vulnerable:
- Over-privileged accounts: Giving users more permissions than they need creates unnecessary risk
- Stale access: Former employees or contractors who still have access
- Permission creep: Users accumulating more access over time than their role requires
- Lack of regular reviews: Not checking who has what access on a consistent schedule
- Missing approval workflows: Allowing permission changes without proper oversight
The principle of least privilege should be your guide – only give users the minimum access they need to do their jobs. Regular permission audits help you spot and fix these issues before they become security problems.
Preparing for an Azure Permissions Audit
A. Defining Audit Scope and Objectives
Before diving into an Azure permissions audit, you need to clearly define what you’re looking for. Start by asking yourself these key questions:
- Which subscriptions, resource groups, or specific resources will you audit?
- Are you focusing on specific user groups or all users with access?
- Do you need to check just current permissions or historical access too?
Setting specific objectives helps you stay focused. Maybe you’re preparing for compliance certification, responding to a security incident, or just doing routine maintenance. Whatever your reason, write it down and use it to guide your audit.
B. Required Permissions for Auditing
To effectively audit permissions in Azure, you’ll need some permissions yourself:
- Reader role at minimum across the scopes you’re auditing
- Global Reader or Security Reader for broader access reviews
- User Access Administrator if you plan to make changes during your audit
Pro tip: Create a dedicated audit account rather than using your daily credentials. This keeps your audit activities separate and creates a clean audit trail.
C. Gathering Documentation
Pull together these essential documents before starting:
- Your organization’s access control policies
- Compliance requirements relevant to your industry
- Previous audit reports and remediation plans
- An up-to-date organizational chart
- Documentation of approved access exceptions
These resources give you context for evaluating whether the permissions you find are appropriate or problematic.
D. Setting Up Audit Tools and Environment
Prepare your toolkit for an efficient audit:
- Set up Azure PowerShell or Azure CLI on your workstation
- Install Azure AD PowerShell modules if reviewing identity permissions
- Prepare your Azure Portal favorites with relevant pages (IAM, Azure AD)
- Create a secure location to store audit findings
- Set up a spreadsheet or database to track discovered permissions
Consider using specialized tools like Azure Policy or Microsoft Defender for Cloud to automate parts of your audit.
E. Creating an Audit Timeline
Break your audit into manageable phases:
- Discovery phase (1-2 days): Initial scan to understand the environment
- Deep analysis (3-5 days): Detailed review of permissions
- Documentation (2-3 days): Recording findings and evidence
- Reporting (1-2 days): Summarizing results for stakeholders
Factor in time for follow-up questions and clarifications. Permission structures can be complex, and you’ll likely need to consult with system owners about why certain permissions exist.
Using Azure Portal for Permission Auditing
A. Navigating to Access Control (IAM)
The Azure Portal offers the easiest way to check who has access to what in your cloud environment. To start auditing permissions, sign in to the Azure Portal (portal.azure.com) using an account with sufficient rights.
Once you’re in, you can access the IAM settings from multiple places:
- At the subscription level
- Inside resource groups
- For individual resources
Look for “Access control (IAM)” in the left sidebar menu of any resource, resource group, or subscription page. This is your gateway to permission management. The interface is consistent across different levels, making it easy to jump between checking permissions at different scopes.
B. Reviewing Role Assignments
When you open the Access Control (IAM) section, you’ll see the “Role assignments” tab already selected. This view shows you all users, groups, and service principals that have been assigned roles at that particular scope.
You can filter this list in several ways:
- By role type (Owner, Contributor, Reader, etc.)
- By name of the user or group
- By assignment type (direct or inherited)
The power move here is using the “Check access” feature at the top of the screen. Enter a specific user’s email or name to see exactly what permissions they have at this scope, including which roles grant those permissions.
C. Checking Subscription-Level Permissions
Subscription permissions affect everything within that subscription, so you need to check these first. Navigate to your subscription list from the Azure Portal homepage, select the subscription you want to audit, then click on “Access control (IAM)”.
Pay special attention to users with Owner or User Access Administrator roles at this level – they have the keys to the kingdom. They can grant permissions to others and potentially create security risks if not monitored closely.
You can also download the role assignments as a CSV file by clicking the “Download” button. This gives you an offline record you can analyze or share with your security team.
D. Analyzing Resource Group Permissions
Resource groups are where the real action happens in your Azure environment. Checking permissions at this level helps you understand who can deploy, modify, or delete resources.
Navigate to the resource group you want to audit and click “Access control (IAM)” in the left menu. Look for any surprising assignments that might not follow your governance policies.
The “Deny assignments” tab is especially useful here – it shows you explicitly blocked permissions that override role assignments. Many organizations overlook deny assignments, but they’re critical for proper security boundaries.
Remember that permissions flow downward – if someone has Contributor access at the resource group level, they’ll have that same access to all resources inside it unless specifically denied.
Leveraging Azure PowerShell for Advanced Auditing
A. Essential PowerShell Commands for Permission Auditing
When you’re serious about auditing permissions in Azure, PowerShell becomes your best friend. Start with these must-know commands:
# Get all role assignments in a subscription
Get-AzRoleAssignment
# Check permissions for a specific user
Get-AzRoleAssignment -SignInName user@domain.com
# List all custom roles
Get-AzRoleDefinition | Where-Object {$_.IsCustom -eq $true}
These commands give you the raw data you need. Want to dig deeper? Try this command to find users with Owner permissions:
Get-AzRoleAssignment | Where-Object {$_.RoleDefinitionName -eq "Owner"} | Format-Table DisplayName, SignInName, Scope
B. Creating Custom Permission Reports
Don’t settle for basic outputs. Create reports that actually tell you something useful:
$permissions = Get-AzRoleAssignment
$permissions | Export-Csv -Path "AzurePermissions.csv" -NoTypeInformation
For more detailed insights, build a custom report format:
$report = Get-AzRoleAssignment | Select-Object DisplayName, SignInName, RoleDefinitionName, Scope |
Sort-Object DisplayName
$report | ConvertTo-Html -Property DisplayName, SignInName, RoleDefinitionName, Scope -Title "Azure Permissions Report" |
Out-File AzurePermissions.html
This gives you a clean HTML report you can share with stakeholders or keep for your records.
C. Filtering and Sorting Permissions Data
Raw permission data can be overwhelming. Break it down into manageable chunks:
# Find all Global Admins
Get-AzRoleAssignment | Where-Object {$_.RoleDefinitionName -eq "Global Administrator"}
# Check resource-specific permissions
Get-AzRoleAssignment -ResourceGroupName "Finance-RG" |
Sort-Object RoleDefinitionName
For nested resources, try:
Get-AzRoleAssignment -ResourceGroupName "Production-RG" -ResourceType "Microsoft.Compute/virtualMachines"
These filters help you zoom in on exactly what matters for your audit.
D. Automating Recurring Permission Checks
Why do manually what PowerShell can do automatically? Set up scheduled permission audits:
# Create a runbook script
$script = @'
Connect-AzAccount -Identity
$date = Get-Date -Format "yyyy-MM-dd"
$permissions = Get-AzRoleAssignment
$permissions | Export-Csv -Path "D:\Reports\AzurePermissions-$date.csv" -NoTypeInformation
'@
# Save the script and schedule with Task Scheduler or Azure Automation
For change detection, compare current permissions against a baseline:
$baseline = Import-Csv "BaselinePermissions.csv"
$current = Get-AzRoleAssignment | Select-Object DisplayName, SignInName, RoleDefinitionName, Scope
$differences = Compare-Object -ReferenceObject $baseline -DifferenceObject $current -Property SignInName, RoleDefinitionName
This tells you exactly what changed since your last audit – perfect for continuous security monitoring.
Azure CLI Techniques for Permission Analysis

A. Installing and Configuring Azure CLI
Getting started with Azure CLI is easier than you might think. First, download and install it from Microsoft’s official site or use your package manager:
# For Windows
winget install -e --id Microsoft.AzureCLI
# For macOS
brew install azure-cli
# For Ubuntu/Debian
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
After installation, sign in to your Azure account:
az login
A browser window will open—just sign in with your Azure credentials. If you’re working on a remote machine without a browser, use:
az login --use-device-code
Need to switch between multiple subscriptions? No problem:
# List your subscriptions
az account list --output table
# Set your active subscription
az account set --subscription "Your-Subscription-Name"
B. Key Commands for Auditing Permissions
Now for the good stuff—commands that help you audit permissions:
# List all role assignments in a subscription
az role assignment list --output table
# Filter role assignments by scope
az role assignment list --scope /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName} --output table
# Check who has owner permissions
az role assignment list --role "Owner" --output table
# See all custom roles
az role definition list --custom-role-only true --output table
Want to check a specific user’s permissions? Try this:
# List assignments for a specific user
az role assignment list --assignee user@example.com --output table
C. Exporting Permissions Data for Analysis
Ready to dig deeper? Export your permissions data for proper analysis:
# Export all role assignments to a JSON file
az role assignment list --output json > azure_permissions.json
# Export with filtering (e.g., only a specific resource group)
az role assignment list --scope /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName} --output json > resource_group_permissions.json
For CSV format (better for spreadsheet analysis):
az role assignment list --output tsv > azure_permissions.tsv
You can automate this process with a simple script:
#!/bin/bash
DATE=$(date +%Y-%m-%d)
az role assignment list --output json > azure_permissions_$DATE.json
echo "Permissions exported to azure_permissions_$DATE.json"
Schedule this script weekly, and you’ll build a historical record of permission changes—perfect for security audits and compliance requirements.
Implementing Microsoft Graph API for Comprehensive Audits
A. Setting Up Graph API Access
When you need to dig deeper into Azure permissions than the standard tools allow, Microsoft Graph API becomes your secret weapon. To get started with Graph API:
- Register a new application in Azure AD:
- Go to your Azure portal
- Navigate to Azure Active Directory > App registrations > New registration
- Give your app a name and configure the redirect URI
- Grant your application the right permissions:
- Select API permissions > Add a permission > Microsoft Graph
- Add these permissions at minimum:
- Directory.Read.All
- Group.Read.All
- User.Read.All
- RoleManagement.Read.All
- Create a client secret:
- Go to Certificates & secrets
- Add a new client secret with an appropriate expiration
- Note down these crucial details:
- Application (client) ID
- Directory (tenant) ID
- Client secret value
# Sample authentication code
$clientId = "your-app-id"
$tenantId = "your-tenant-id"
$clientSecret = "your-client-secret"
$tokenBody = @{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
Client_Id = $clientId
Client_Secret = $clientSecret
}
$tokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -Method POST -Body $tokenBody
$headers = @{
"Authorization" = "Bearer $($tokenResponse.access_token)"
"Content-Type" = "application/json"
}
B. Querying User and Group Permissions
Once you’ve set up Graph API access, you can pull detailed information about users and groups:
To retrieve all users in your tenant:
$users = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/users" -Headers $headers
To get group memberships for a specific user:
$userId = "user-object-id"
$userGroups = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/users/$userId/memberOf" -Headers $headers
You can also query groups directly:
$groups = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/groups" -Headers $headers
And check group members:
$groupId = "group-object-id"
$groupMembers = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/groups/$groupId/members" -Headers $headers
The data returned contains rich information that standard Azure tools don’t expose, giving you greater visibility into permission structures.
C. Analyzing Directory Role Assignments
Directory roles in Azure AD grant powerful permissions across your tenant. Using Graph API, you can audit these critical assignments:
To list all directory roles:
$directoryRoles = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/directoryRoles" -Headers $headers
To see who has been assigned to a specific role:
$roleId = "role-object-id"
$roleMembers = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/directoryRoles/$roleId/members" -Headers $headers
You might want to pay special attention to highly privileged roles:
- Global Administrator
- Privileged Role Administrator
- Security Administrator
- Exchange Administrator
Create a report by processing the results:
$report = @()
foreach ($role in $directoryRoles.value) {
$members = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/directoryRoles/$($role.id)/members" -Headers $headers
foreach ($member in $members.value) {
$report += [PSCustomObject]@{
RoleName = $role.displayName
MemberName = $member.displayName
MemberType = $member.'@odata.type' -replace "#microsoft.graph."
ObjectId = $member.id
}
}
}
$report | Export-Csv -Path "DirectoryRoleReport.csv" -NoTypeInformation
D. Building Custom Audit Solutions with Graph API
Why stick with off-the-shelf tools when you can build exactly what you need? With Graph API, you can create custom audit solutions tailored to your organization:
- Develop recurring permission scans:
- Schedule weekly audits of critical role assignments
- Track changes over time to identify permission creep
- Set up alerts for unauthorized permission changes
- Create specialized reports:
# Example: Find all guest users with high privileges
$guests = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/users?`$filter=userType eq 'Guest'" -Headers $headers
foreach ($guest in $guests.value) {
$memberOf = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/users/$($guest.id)/memberOf" -Headers $headers
if ($memberOf.value.Count -gt 0) {
Write-Output "Guest user $($guest.displayName) is a member of $($memberOf.value.Count) groups/roles"
}
}
- Combine with other data sources:
- Merge Azure RBAC data with Azure AD role information
- Correlate permission data with security logs
- Build comprehensive dashboards that visualize your security posture
- Implement remediation workflows:
- Flag excessive permissions
- Generate approval requests for maintaining privileged access
- Create automated cleanup processes for unused permissions
The beauty of custom solutions is they grow with your needs and security requirements, giving you full control over your audit processes.
Analyzing Audit Results and Identifying Issues
A. Detecting Over-Privileged Accounts
After running your Azure permission audit, you’ll likely find accounts with excessive privileges. Look for:
- Users with Global Administrator or Owner roles who don’t need them
- Service principals with broad scopes (subscription-level access)
- Accounts with multiple high-privilege roles across resources
Pay special attention to accounts with permanent admin roles instead of using Privileged Identity Management (PIM) for just-in-time access. Flag any service accounts with Owner permissions—these are prime targets for attackers.
B. Identifying Stale or Unused Permissions
Unused permissions create unnecessary risk. When analyzing your audit results:
- Check sign-in logs for accounts that haven’t logged in for 30+ days but retain permissions
- Look for service principals with valid credentials but no API calls in recent months
- Identify project-based roles still active after projects have concluded
- Review guest accounts with lingering access after collaborations end
These zombie permissions are easy to overlook but create serious security gaps in your environment.
C. Recognizing Privilege Escalation Risks
Some permission combinations can enable privilege escalation even when individual permissions seem harmless. Watch for:
- Accounts with both Contributor roles and User Access Administrator at different scopes
- Custom roles with permission to create/manage app registrations and service principals
- Nested group memberships that result in unintended permission inheritance
- Management group-level permissions that cascade down to multiple subscriptions
These subtle permission combinations often slip through standard reviews but create paths for attackers to elevate privileges.
D. Documenting Compliance Violations
Map your audit findings to your compliance requirements:
- Flag role assignments violating separation of duties principles
- Identify permissions that breach least-privilege policies
- Document missing approval workflows for sensitive role assignments
- Note any role assignments lacking proper expiration dates
Create a report linking each violation to specific compliance requirements from your governance framework. This makes remediation more straightforward and helps justify changes to stakeholders.
E. Prioritizing Security Findings
Not all permission issues carry equal risk. Prioritize your findings using:
| Priority Level | Characteristics | Response Timeframe |
|---|---|---|
| Critical | Over-privileged admin accounts, broad subscription access | Immediate (24-48 hours) |
| High | Stale admin accounts, potential privilege escalation paths | Within 1 week |
| Medium | Excessive project permissions, outdated guest access | Within 2-4 weeks |
| Low | Minor policy violations, excessive read-only access | Next review cycle |
Focus your immediate remediation efforts on issues that could lead to widespread compromise. Address critical findings first, then work down your priority list methodically.
Implementing Remediation Strategies
A. Applying Least Privilege Principles
After discovering excessive permissions in your Azure environment, your first step is to implement the least privilege principle. This means giving users only the permissions they absolutely need to do their jobs – nothing more.
Start by downgrading global admin accounts. You probably don’t need ten people with god-mode access to your entire Azure environment.
For each overprivileged user, ask yourself: “What do they actually need to accomplish?” Then swap out those broad Owner roles for more specific ones like Reader, Contributor, or custom roles that match their actual responsibilities.
Custom roles are your best friend here. Build roles that precisely match job functions rather than relying solely on Azure’s built-in options. For example, create a “VM Operator” role that can restart VMs but can’t delete them or modify their configurations.
B. Implementing Just-In-Time Access
Standing privileges are risky. Instead, set up just-in-time (JIT) access using Azure Privileged Identity Management (PIM). This approach transforms standing permissions into eligible assignments that require activation when needed.
With PIM, you can:
- Set time limits on elevated permissions (4 hours is often plenty)
- Require approval workflows for sensitive access
- Mandate reason documentation for each activation
- Force MFA for privilege elevation
This dramatically reduces your attack surface – a compromised account is much less dangerous if its admin privileges aren’t constantly active.
C. Establishing Permission Review Processes
One-time permission cleanup isn’t enough. You need ongoing hygiene:
- Schedule quarterly role reviews with resource owners
- Implement automated alerts for suspicious permission changes
- Create a formal access request process (no more “just give me admin for a minute”)
- Review service principal permissions regularly (they’re often overlooked)
Use Azure AD access reviews to periodically validate all role assignments. Assign reviewers who actually understand what access each team member needs.
D. Documenting Changes for Compliance
Every permission change should leave a trail. This isn’t just good practice – it’s often a regulatory requirement.
Keep detailed records of:
- Who approved each permission change
- Why the change was necessary
- When the change was implemented
- Previous and new permission levels
Azure’s activity logs capture these changes automatically, but you should export and preserve them in a dedicated audit repository. Set up regular reports showing permission modifications with PowerShell scripts or Logic Apps.
For regulated industries, maintain documentation showing your permission governance processes align with compliance frameworks like SOC 2, HIPAA, or PCI DSS. When auditors come knocking, you’ll be ready with evidence of your systematic approach.
Regularly auditing user permissions in Azure is essential for maintaining a secure cloud environment and ensuring compliance with organizational policies.
By following the step-by-step approaches outlined in this guide, from using the Azure Portal for basic reviews to implementing advanced techniques with PowerShell, CLI, and Microsoft Graph API, you can effectively identify and address permission issues before they become security vulnerabilities.
Take time to thoroughly analyze your audit results and implement appropriate remediation strategies based on the principle of least privilege.
Remember that permission auditing isn’t a one-time task but an ongoing process that should be integrated into your regular security practices.
Start with small, manageable audits and gradually expand your scope to build a comprehensive permissions management system that keeps your Azure environment secure and compliant.
I’ve built a platform that shows you how you can build the right cybersecurity skills to help businesses achieve their cloud security goals while you’re also building the career you love. Check it out here and start working on projects that get you hired.







