Azure AD & RBAC Guide
Understand Azure Active Directory, role-based access control, and identity management patterns.
Prerequisites
- Azure subscription with Azure AD access
- Basic understanding of identity management concepts
Understanding Azure Active Directory & Role-Based Access Control
Azure Active Directory (Azure AD, now Microsoft Entra ID) is the backbone of identity and access management in Azure. Combined with Role-Based Access Control (RBAC), it provides a powerful framework for managing who can do what within your Azure environment. Identity is the new security perimeter in cloud computing; network-based controls alone are insufficient when resources are accessed from anywhere, by anyone, on any device. This guide covers the core concepts, best practices, and practical implementation patterns you need to secure your cloud resources effectively.
Whether you are a cloud architect designing a multi-subscription governance model, a security engineer hardening your identity posture, or a DevOps engineer automating access provisioning, understanding how Azure AD and RBAC work together is foundational to every Azure deployment. We will walk through tenant configuration, identity object types, RBAC mechanics, Conditional Access policies, Privileged Identity Management, and monitoring, with practical code examples you can adapt for your own environment.
Microsoft Entra ID Rebrand
As of July 2023, Azure Active Directory was rebranded to Microsoft Entra ID. The underlying technology, APIs, and PowerShell modules remain the same; only the branding has changed. Throughout this guide, we use both names interchangeably, but be aware that newer Azure portal interfaces, documentation, and CLI commands will reference Entra ID. The Azure CLI still uses az ad commands, and the Microsoft Graph API endpoints remain unchanged.
Azure AD Tenant Architecture
An Azure AD tenant is a dedicated instance of the directory service that an organization receives when it signs up for a Microsoft cloud service (Azure, Microsoft 365, Dynamics 365). Each tenant is a fully isolated identity boundary; user accounts, groups, app registrations, and policies in one tenant are completely separate from those in another.
Every Azure subscription is associated with exactly one Azure AD tenant, but a single tenant can have many subscriptions associated with it. This one-to-many relationship is important because it means you can centralize identity management across multiple subscriptions, environments, and even business units.
Single-Tenant vs Multi-Tenant Strategies
Most organizations should use a single Azure AD tenant for all their Azure subscriptions. A single tenant provides unified identity, simplified conditional access policies, and consistent governance. Multi-tenant configurations are typically reserved for organizations that have hard regulatory boundaries between business units (for example, a holding company with subsidiaries that must maintain complete data separation).
| Strategy | When to Use | Advantages | Challenges |
|---|---|---|---|
| Single Tenant | Most organizations | Unified identity, simple governance, single pane of glass | Requires careful RBAC design for multi-team isolation |
| Multi-Tenant | Regulatory separation, M&A isolation | Hard security boundary between units | Duplicate policies, complex B2B collaboration, higher admin cost |
| B2B Collaboration | Partner and vendor access | Guest users access your resources without separate accounts | Must manage guest lifecycle, Conditional Access for guests |
# View current tenant information
az account show --query '{TenantId:tenantId, SubscriptionName:name, SubscriptionId:id}' --output table
# List all subscriptions in the current tenant
az account list --query "[].{Name:name, Id:id, State:state, TenantId:tenantId}" --output table
# List all Azure AD users in the tenant (first 100)
az ad user list --query "[].{DisplayName:displayName, UPN:userPrincipalName, ObjectId:id}" --output table --top 100
# Check the tenant's verified domains
az rest --method GET --uri "https://graph.microsoft.com/v1.0/organization" \
--query "value[0].verifiedDomains[].{Name:name, Default:isDefault, Initial:isInitial}" --output tableAzure AD Core Identity Objects
Azure AD manages several types of identity objects, each serving a distinct purpose in the authentication and authorization ecosystem. Understanding these object types and when to use each one is fundamental to designing a secure identity architecture.
Users
User objects represent individual people in your organization. Users can be cloud-only (created directly in Azure AD) or synced from on-premises Active Directory via Azure AD Connect or the newer Azure AD Cloud Sync. Each user has a User Principal Name (UPN) that serves as their sign-in identifier, typically in the format user@domain.com.
Cloud-only users are best for organizations that are fully cloud-native or for accounts that don't correspond to on-premises identities (break-glass admin accounts, external collaborators). Synced users maintain a link to the on-premises AD object, and password changes, group memberships, and attribute updates flow from on-premises to the cloud (or bidirectionally with password writeback).
Groups
Groups are collections of users, devices, service principals, or other groups. Azure AD supports two primary group types:
- Security Groups: Used for RBAC role assignments, access control, and Conditional Access policy targeting. These are the groups you will use most often for Azure resource management.
- Microsoft 365 Groups: Used for collaboration features (shared mailbox, SharePoint site, Teams channel). While they can be used for RBAC, security groups are preferred for resource access control.
Groups can have assigned membership (manually managed) or dynamic membership (based on user or device attributes). Dynamic groups are particularly powerful for automating RBAC: for example, a dynamic group that includes all users with the department attribute set to “Engineering” can automatically receive Contributor access to development subscriptions.
# Create a dynamic security group for all engineering department members
az ad group create \
--display-name "Engineering Team" \
--mail-nickname "engineering-team" \
--group-types "DynamicMembership" \
--membership-rule "(user.department -eq \"Engineering\")" \
--membership-rule-processing-state "On"
# Create a static security group for infrastructure admins
az ad group create \
--display-name "Infra Admins" \
--mail-nickname "infra-admins"
# Add a user to the static group
az ad group member add \
--group "Infra Admins" \
--member-id <user-object-id>
# List group members
az ad group member list \
--group "Infra Admins" \
--query "[].{Name:displayName, UPN:userPrincipalName}" \
--output tableService Principals and App Registrations
When an application needs to authenticate to Azure AD, you create an App Registration (the global definition of the app) and a Service Principal (the local instance of the app in your tenant). The app registration defines the app's identity, permissions, and authentication settings. The service principal is the security identity that Azure AD uses for authorization.
Service principals authenticate using client secrets (passwords), certificates, or federated identity credentials (for workload identity federation with external identity providers like GitHub Actions or Terraform Cloud). Client secrets have a maximum lifetime and must be rotated. Certificates are preferred for production workloads because they are harder to accidentally expose.
Managed Identities
Managed identities are a special type of service principal that Azure manages automatically. They completely eliminate the need to handle credentials in your code, configuration, or deployment pipelines. Azure handles the creation, rotation, and deletion of the underlying credentials.
| Feature | System-Assigned | User-Assigned |
|---|---|---|
| Lifecycle | Tied to the Azure resource (created/deleted with it) | Independent lifecycle (create once, assign to many) |
| Sharing | Cannot be shared between resources | Can be assigned to multiple resources |
| Use case | Single resource needing unique identity | Multiple resources needing the same permissions |
| Cleanup | Automatic when resource is deleted | Must be deleted manually |
| RBAC assignment | Per resource (can be many assignments) | One identity, shared across resources |
Always Prefer Managed Identities
Whenever a service supports managed identities, use them instead of service principals with client secrets or certificates. Managed identities eliminate credential management, provide automatic rotation, and reduce the risk of credential leakage. Services that support managed identities include App Service, Functions, AKS, VMs, Logic Apps, Data Factory, and many more. Use user-assigned managed identities when multiple resources need the same set of permissions to avoid duplicating RBAC assignments.
# Enable system-assigned managed identity
az webapp identity assign \
--name my-web-app \
--resource-group myRG
# Create a user-assigned managed identity
az identity create \
--name my-shared-identity \
--resource-group myRG \
--location eastus2
# Assign the user-assigned identity to an App Service
az webapp identity assign \
--name my-web-app \
--resource-group myRG \
--identities /subscriptions/<sub-id>/resourceGroups/myRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-shared-identity
# Grant the managed identity access to Key Vault
az role assignment create \
--assignee $(az webapp identity show --name my-web-app -g myRG --query principalId -o tsv) \
--role "Key Vault Secrets User" \
--scope $(az keyvault show --name myapp-kv --query id -o tsv)
# Grant the managed identity access to a Storage Account
az role assignment create \
--assignee $(az webapp identity show --name my-web-app -g myRG --query principalId -o tsv) \
--role "Storage Blob Data Reader" \
--scope $(az storage account show --name mystorageacct --query id -o tsv)RBAC Fundamentals
Azure RBAC is an authorization system built on Azure Resource Manager that provides fine-grained access management for Azure resources. Unlike traditional all-or-nothing admin models, RBAC follows the principle of least privilege by allowing you to grant only the specific permissions users need, at the precise scope where they need them. This dramatically reduces the blast radius of compromised accounts and limits the potential for accidental misconfiguration.
An RBAC assignment consists of three elements that together answer the question: “Who can do what, and where?”
| Element | Description | Example |
|---|---|---|
| Security Principal | Who is getting access | User, group, service principal, or managed identity |
| Role Definition | What permissions are granted | Reader, Contributor, Owner, or a custom role |
| Scope | Where the permissions apply | Management group, subscription, resource group, or resource |
RBAC Scope Hierarchy
Azure RBAC supports a hierarchical scope model. Permissions assigned at a higher scope are inherited by all child scopes. Understanding this inheritance is critical for designing an effective access model.
Management Group (e.g., "Contoso")
└── Subscription (e.g., "Production")
└── Resource Group (e.g., "prod-web-rg")
└── Resource (e.g., "prod-web-app")
Inheritance flows downward:
- Owner at Management Group → Owner on ALL subscriptions, RGs, and resources below
- Contributor at Subscription → Contributor on ALL resource groups and resources
- Reader at Resource Group → Reader on ALL resources in that group
- "Storage Blob Data Reader" at Resource → Only that specific storage account
Best practice: Assign at the NARROWEST scope that meets the need.Avoid Subscription-Level Owner Assignments
Granting the Owner role at the subscription level gives unrestricted access to every resource in the subscription, including the ability to assign roles to others. This is one of the highest-risk RBAC assignments. Limit Owner to a small number of break-glass accounts and use Privileged Identity Management (PIM) for time-bound elevation. For everyday administration, Contributor is sufficient for resource management without the ability to modify access.
Built-in Roles
Azure provides over 300 built-in roles covering every Azure service. The four fundamental roles form the foundation of most RBAC designs:
| Role | Permissions | Key Limitation | Use Case |
|---|---|---|---|
| Owner | Full access including assigning roles to others | Cannot manage Azure Blueprints or share image galleries | Subscription administrators, break-glass accounts |
| Contributor | Full access except role assignment and Blueprint management | Cannot grant access to others | Developers who need to create and manage resources |
| Reader | View all resources, no modifications | Cannot see secrets, keys, or connection strings | Auditors, stakeholders needing visibility |
| User Access Administrator | Manage user access to resources (role assignments only) | Cannot create, modify, or delete resources | Delegated access management without full Owner |
Service-Specific Roles
Beyond the fundamental roles, Azure provides granular, service-specific roles that follow least-privilege principles more closely. Some commonly used service-specific roles include:
- Storage Blob Data Contributor: Read, write, and delete blob data (data plane only, not management plane)
- Key Vault Secrets User: Read secret contents (not manage the vault itself)
- AcrPull: Pull container images from Azure Container Registry
- Cosmos DB Account Reader Role: Read Cosmos DB account metadata
- Network Contributor: Manage networking resources without full subscription access
- Monitoring Contributor: Read monitoring data and edit monitoring settings
Implementing Custom RBAC Roles
When built-in roles are too broad or too narrow for your requirements, create custom roles. Custom roles are defined using JSON and can be scoped to one or more subscriptions or management groups. They provide fine-grained control that aligns permissions precisely with job functions, following the principle of least privilege.
A custom role definition specifies Actions (management plane operations the role can perform), NotActions (operations to exclude), DataActions(data plane operations like reading blob data), and NotDataActions (data plane exclusions). The distinction between management plane and data plane is important: management plane controls the resource itself (create, delete, configure), while data plane controls the data within the resource (read blobs, query databases, get secrets).
{
"Name": "VM Operator",
"IsCustom": true,
"Description": "Can start, stop, restart, and monitor VMs but cannot create, delete, or resize them.",
"Actions": [
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/powerOff/action",
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Compute/virtualMachines/read",
"Microsoft.Compute/virtualMachines/instanceView/read",
"Microsoft.Network/networkInterfaces/read",
"Microsoft.Network/publicIPAddresses/read",
"Microsoft.Resources/subscriptions/resourceGroups/read",
"Microsoft.Insights/metrics/read",
"Microsoft.Insights/diagnosticSettings/read"
],
"NotActions": [],
"DataActions": [],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
]
}# Create the custom role from a JSON definition
az role definition create --role-definition custom-vm-operator-role.json
# List all custom roles in the subscription
az role definition list --custom-role-only true --output table
# Assign the custom role to a security group at resource group scope
az role assignment create \
--assignee-object-id <group-object-id> \
--assignee-principal-type Group \
--role "VM Operator" \
--scope /subscriptions/<sub-id>/resourceGroups/production-vms
# Verify the assignment
az role assignment list \
--assignee <group-object-id> \
--scope /subscriptions/<sub-id>/resourceGroups/production-vms \
--output table
# Update an existing custom role (modify the JSON, then update)
az role definition update --role-definition updated-vm-operator-role.json
# Delete a custom role (must remove all assignments first)
az role definition delete --name "VM Operator"Custom Role Limits and Propagation
Each Azure AD tenant can have up to 5,000 custom roles. Custom roles can take up to 10 minutes to propagate after creation or modification. Always test custom roles in a non-production environment first, and document the intended purpose of each custom role. Use a naming convention that indicates the custom nature (e.g., prefix with your organization name) to distinguish custom roles from built-in ones.
Custom Role Design Patterns
When designing custom roles, follow these patterns for maintainability:
- Start from a built-in role and subtract: Find the closest built-in role, copy its definition, and use
NotActionsto remove unneeded permissions. This is easier than building from scratch. - Use wildcards carefully:
Microsoft.Compute/virtualMachines/*grants all VM operations. This is convenient but may grant more than intended as Azure adds new operations. Prefer explicit action lists for production roles. - Separate management and data plane roles: A role that manages a storage account (management plane) should not also have blob data access (data plane). Create separate roles for each concern.
- Version control role definitions: Store custom role JSON files in your IaC repository alongside Bicep/Terraform templates. Deploy role definitions through your CI/CD pipeline to ensure consistency across environments.
Conditional Access Policies
Conditional Access is Azure AD's signal-based policy engine. It evaluates signals like user identity, device state, location, application, real-time risk level, and session context to enforce access decisions. Think of it as “if-then” statements for authentication: if a user meets certain conditions, then enforce specific controls.
Conditional Access requires Azure AD Premium P1 or P2 licensing. P1 covers basic policy creation, while P2 adds risk-based policies (using Identity Protection signals) and more advanced conditions.
Policy Components
Every Conditional Access policy has three sections:
- Assignments (Who and What): Which users, groups, or workload identities does the policy apply to? Which cloud apps or actions are targeted? What conditions must be true (platform, location, device state, risk level)?
- Access Controls (Then Do What): Grant access (with or without conditions like MFA, compliant device, or approved app) or block access entirely.
- Session Controls: Additional constraints on the authenticated session, such as sign-in frequency, persistent browser sessions, or Conditional Access App Control (integration with Microsoft Defender for Cloud Apps).
Essential Conditional Access Policies
Microsoft recommends a baseline set of Conditional Access policies that every organization should implement:
| Policy | Target | Control | Why It Matters |
|---|---|---|---|
| Require MFA for admins | All directory roles (Global Admin, User Admin, etc.) | Require MFA | Admin accounts are highest-value targets |
| Require MFA for all users | All users (exclude break-glass accounts) | Require MFA | MFA blocks 99.9% of account compromise attacks |
| Block legacy authentication | All users, all cloud apps | Block (condition: client apps = other clients) | Legacy protocols (IMAP, POP3) cannot enforce MFA |
| Require compliant devices for Office 365 | All users, Office 365 apps | Require compliant device (Intune) | Prevents data access from unmanaged devices |
| Block high-risk sign-ins | All users (P2 required) | Block (condition: sign-in risk = high) | Automatically blocks compromised credentials |
| Require password change for high-risk users | All users (P2 required) | Require password change + MFA | Forces remediation when user account is likely compromised |
Start with Report-Only Mode
Always deploy new Conditional Access policies in report-only mode first. This lets you see which sign-ins would be affected without actually blocking users. Review the sign-in logs for at least one to two weeks before switching to enforcement mode. Use the Conditional Access insights and reporting workbook in Azure Monitor for visual analysis of policy impact.
Named Locations and IP-Based Policies
Named locations allow you to define trusted network ranges (office IP addresses, VPN egress points) and use them as conditions in Conditional Access policies. This enables scenarios like “require MFA only when signing in from outside the corporate network” or “block all sign-ins from high-risk countries.”
# Create a named location for your corporate network
az rest --method POST \
--uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/namedLocations" \
--headers "Content-Type=application/json" \
--body '{
"@odata.type": "#microsoft.graph.ipNamedLocation",
"displayName": "Corporate Network",
"isTrusted": true,
"ipRanges": [
{"@odata.type": "#microsoft.graph.iPv4CidrRange", "cidrAddress": "203.0.113.0/24"},
{"@odata.type": "#microsoft.graph.iPv4CidrRange", "cidrAddress": "198.51.100.0/24"}
]
}'
# Create a Conditional Access policy requiring MFA for admins
az rest --method POST \
--uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" \
--headers "Content-Type=application/json" \
--body '{
"displayName": "Require MFA for admin roles",
"state": "enabledForReportingButNotEnforced",
"conditions": {
"users": {
"includeRoles": [
"62e90394-69f5-4237-9190-012177145e10",
"194ae4cb-b126-40b2-bd5b-6091b380977d",
"f28a1f50-f6e7-4571-818b-6a12f2af6b6c"
]
},
"applications": {
"includeApplications": ["All"]
}
},
"grantControls": {
"operator": "OR",
"builtInControls": ["mfa"]
}
}'Privileged Identity Management (PIM)
Privileged Identity Management (PIM) is an Azure AD Premium P2 feature that provides just-in-time (JIT) and time-bound access to privileged roles. Instead of having permanent (standing) access to sensitive roles, users are made “eligible” for a role and must activate it when needed, with a defined maximum duration.
PIM addresses one of the most critical security risks in cloud environments: over-provisioned permanent access. Studies show that most privileged access is used less than 5% of the time, yet the accounts remain permanently elevated, creating an unnecessary attack surface.
PIM Workflow
The typical PIM workflow follows these steps:
- Eligible assignment: An administrator makes a user eligible for a role (no standing access)
- Activation request: The user requests activation when they need the role, providing a justification
- Approval (optional): A designated approver reviews and approves the request
- Time-bound activation: The role is activated for a defined period (e.g., 4 hours, 8 hours)
- Automatic deactivation: The role assignment is automatically removed when the time expires
- Audit trail: Every activation, approval, and deactivation is logged for audit
# List eligible role assignments for a user
az rest --method GET \
--uri "https://management.azure.com/subscriptions/<sub-id>/providers/Microsoft.Authorization/roleEligibilityScheduleInstances?api-version=2020-10-01" \
--query "value[].{Role:properties.expandedProperties.roleDefinition.displayName, Scope:properties.expandedProperties.scope.displayName}"
# Activate an eligible role (just-in-time access)
az rest --method PUT \
--uri "https://management.azure.com/subscriptions/<sub-id>/providers/Microsoft.Authorization/roleAssignmentScheduleRequests/<request-id>?api-version=2020-10-01" \
--body '{
"properties": {
"principalId": "<user-object-id>",
"roleDefinitionId": "/subscriptions/<sub-id>/providers/Microsoft.Authorization/roleDefinitions/<role-id>",
"requestType": "SelfActivate",
"scheduleInfo": {
"expiration": {
"type": "AfterDuration",
"duration": "PT4H"
}
},
"justification": "Deploying hotfix to production - Incident INC-4521"
}
}'
# List active PIM role assignments
az rest --method GET \
--uri "https://management.azure.com/subscriptions/<sub-id>/providers/Microsoft.Authorization/roleAssignmentScheduleInstances?api-version=2020-10-01" \
--query "value[].{Role:properties.expandedProperties.roleDefinition.displayName, Principal:properties.expandedProperties.principal.displayName, End:properties.endDateTime}"PIM for Azure Resources vs Azure AD Roles
PIM manages two separate domains: Azure AD directory roles (Global Administrator, User Administrator, etc.) and Azure resource roles (Owner, Contributor, custom roles). Both use the same JIT workflow but are configured separately. Make sure you enable PIM for both domains to fully protect your environment. Directory roles are managed in the Azure AD portal, while Azure resource roles are managed in the PIM blade under Azure Resources.
Workload Identity Federation
Workload identity federation allows external identity providers (GitHub Actions, GitLab CI, Terraform Cloud, AWS, Google Cloud) to authenticate to Azure AD without storing secrets. Instead of creating a client secret or certificate for your CI/CD pipeline, you configure a trust relationship between Azure AD and the external identity provider using OpenID Connect (OIDC) federation.
This is a significant security improvement for DevOps workflows. Previously, deploying to Azure from GitHub Actions required storing a service principal client secret in GitHub Secrets, a credential that could be exfiltrated and had to be manually rotated. With workload identity federation, no secrets are stored anywhere.
# Create an app registration for GitHub Actions
az ad app create --display-name "github-actions-deploy"
# Get the app's object ID
APP_OBJECT_ID=$(az ad app list --display-name "github-actions-deploy" --query "[0].id" -o tsv)
APP_CLIENT_ID=$(az ad app list --display-name "github-actions-deploy" --query "[0].appId" -o tsv)
# Create a federated identity credential for the main branch
az ad app federated-credential create \
--id $APP_OBJECT_ID \
--parameters '{
"name": "github-main-branch",
"issuer": "https://token.actions.githubusercontent.com",
"subject": "repo:myorg/myrepo:ref:refs/heads/main",
"audiences": ["api://AzureADTokenExchange"],
"description": "GitHub Actions deployment from main branch"
}'
# Create a service principal for the app
az ad sp create --id $APP_CLIENT_ID
# Grant Contributor access to the target resource group
az role assignment create \
--assignee $APP_CLIENT_ID \
--role Contributor \
--scope /subscriptions/<sub-id>/resourceGroups/production-rgUse Federated Credentials for All CI/CD
Workload identity federation is available for GitHub Actions, GitLab CI/CD, Terraform Cloud, and any OIDC-compliant identity provider. Migrate all your deployment pipelines away from client secrets to federated credentials. This eliminates the most common source of leaked Azure credentials in CI/CD pipelines.
Azure AD Security Monitoring and Auditing
Comprehensive monitoring of your identity infrastructure is essential for detecting threats, investigating incidents, and maintaining compliance. Azure AD provides multiple log types that should be collected, analyzed, and alerted on.
Log Types
| Log Type | What It Captures | Retention (Free) | Key Alerts to Configure |
|---|---|---|---|
| Sign-in Logs | Every authentication attempt (success and failure) | 7 days | Failed MFA, sign-ins from unusual locations, impossible travel |
| Audit Logs | Directory changes (user/group/role modifications) | 7 days | Role assignment changes, app registration modifications |
| Provisioning Logs | User provisioning to SaaS apps | 7 days | Provisioning failures, unexpected deprovisioning |
| Risk Detections | Identity Protection risk events (P2) | 90 days | Leaked credentials, anonymous IP, malware-linked IPs |
| Managed Identity Logs | Token issuance for managed identities | In Activity Log | Unexpected managed identity usage patterns |
Forwarding Logs to Log Analytics
The free 7-day retention for sign-in and audit logs is insufficient for most organizations. Forward these logs to a Log Analytics workspace for long-term retention, advanced querying with Kusto Query Language (KQL), and integration with Microsoft Sentinel for SIEM capabilities.
# Create a Log Analytics workspace for security logs
az monitor log-analytics workspace create \
--resource-group security-rg \
--workspace-name identity-logs-workspace \
--location eastus2 \
--retention-time 365
# Configure Azure AD diagnostic settings to forward to Log Analytics
az monitor diagnostic-settings create \
--name "azure-ad-logs" \
--resource "/providers/Microsoft.aadiam/diagnosticSettings" \
--workspace /subscriptions/<sub-id>/resourceGroups/security-rg/providers/Microsoft.OperationalInsights/workspaces/identity-logs-workspace \
--logs '[
{"category": "SignInLogs", "enabled": true, "retentionPolicy": {"enabled": true, "days": 365}},
{"category": "AuditLogs", "enabled": true, "retentionPolicy": {"enabled": true, "days": 365}},
{"category": "NonInteractiveUserSignInLogs", "enabled": true, "retentionPolicy": {"enabled": true, "days": 365}},
{"category": "ServicePrincipalSignInLogs", "enabled": true, "retentionPolicy": {"enabled": true, "days": 365}},
{"category": "ManagedIdentitySignInLogs", "enabled": true, "retentionPolicy": {"enabled": true, "days": 365}},
{"category": "RiskyUsers", "enabled": true, "retentionPolicy": {"enabled": true, "days": 365}},
{"category": "UserRiskEvents", "enabled": true, "retentionPolicy": {"enabled": true, "days": 365}}
]'// Find all Owner role assignments created in the last 7 days
AzureActivity
| where OperationNameValue == "Microsoft.Authorization/roleAssignments/write"
| where Properties_d contains "Owner"
| project TimeGenerated, Caller, ResourceGroup, Properties_d
| order by TimeGenerated desc
// Detect failed sign-ins followed by success (potential brute force)
SigninLogs
| where TimeGenerated > ago(24h)
| summarize FailedCount=countif(ResultType != "0"),
SuccessCount=countif(ResultType == "0")
by UserPrincipalName, IPAddress, bin(TimeGenerated, 1h)
| where FailedCount > 10 and SuccessCount > 0
| order by FailedCount desc
// Find service principal sign-ins from unexpected locations
AADServicePrincipalSignInLogs
| where TimeGenerated > ago(7d)
| where Location !in ("US", "GB", "DE")
| project TimeGenerated, ServicePrincipalName, IPAddress, Location, ResourceDisplayName
| order by TimeGenerated descAudit Everything
Every RBAC assignment and Conditional Access policy change is logged in the Azure AD Audit Log. Set up alerts for changes to Owner and User Access Administrator assignments, especially at the subscription level. These are high-impact changes that could indicate privilege escalation. Also alert on new app registrations, federated credential additions, and changes to Conditional Access policies, as these are common attack vectors in compromised tenant scenarios.
Best Practices for Azure AD & RBAC
Follow these best practices to build a secure and manageable identity posture. These recommendations are drawn from the Microsoft Cloud Adoption Framework, Azure Security Benchmark, and real-world operational experience.
Identity Governance
- Use groups for role assignments, not individual users. Assign RBAC roles to Azure AD security groups and manage membership in the group. This scales better, simplifies auditing, and makes it easy to grant or revoke access by adding or removing group members.
- Apply the principle of least privilege everywhere. Start with the most restrictive role that allows the task. Elevate temporarily using PIM for just-in-time access. Resist the temptation to grant Contributor or Owner “just in case” ; it is always easier to add permissions than to clean up over-privileged accounts.
- Scope assignments as narrowly as possible. Prefer resource-group or resource-level assignments over subscription-level. Avoid management-group-level assignments unless they apply to truly global capabilities (like security auditing).
- Implement Privileged Identity Management for all privileged roles. PIM provides time-bound, approval-based activation for privileged roles, reducing standing access and improving auditability. At minimum, put Owner, Contributor, and User Access Administrator behind PIM at the subscription level.
- Review access regularly with Azure AD Access Reviews. Use Access Reviews to periodically verify that role assignments are still appropriate. Set up quarterly reviews for sensitive roles and annual reviews for standard access. Access Reviews can automatically remove access if a reviewer doesn't respond.
Authentication Security
- Require MFA for all users, no exceptions. Multi-factor authentication blocks 99.9% of identity attacks. Use phishing-resistant methods (FIDO2 security keys, Windows Hello, Microsoft Authenticator passkeys) for the highest security.
- Block legacy authentication protocols. IMAP, POP3, SMTP AUTH, and older Office clients cannot enforce MFA. Block them with Conditional Access to eliminate a major attack vector.
- Maintain at least two break-glass accounts. These are cloud-only Global Administrator accounts that are excluded from Conditional Access policies. They use extremely long, complex passwords stored in a physical safe and are only used when normal admin access fails. Monitor their usage with alerts.
- Use managed identities for all Azure service-to-service authentication.Eliminate stored credentials wherever possible. For external identity providers (CI/CD pipelines), use workload identity federation.
Operational Practices
- Forward all Azure AD logs to a central Log Analytics workspace. Set retention to meet your compliance requirements (typically 1 year minimum). Build alert rules for high-risk events.
- Use Azure Policy to enforce RBAC governance. Create policies that deny certain role assignments (e.g., prevent Owner assignment at subscription scope) or require specific conditions for privileged operations.
- Document your RBAC model. Maintain a living document that maps job functions to Azure AD groups, roles, and scopes. This is essential for onboarding new team members and for audit responses.
- Automate access provisioning. Use Azure AD entitlement management (access packages) or Infrastructure as Code to provision RBAC assignments. Manual, ad-hoc role assignments inevitably lead to permission sprawl.
Common Pitfalls and How to Avoid Them
Even experienced Azure administrators make these mistakes. Awareness of common pitfalls can save significant troubleshooting time and prevent security incidents.
| Pitfall | Impact | Solution |
|---|---|---|
| Assigning roles to individual users instead of groups | Permission sprawl, impossible to audit at scale | Create security groups for each role/scope combination |
| Using Owner where Contributor would suffice | Users can modify RBAC, creating privilege escalation paths | Default to Contributor; only use Owner with PIM |
| Service principals with non-expiring secrets | Leaked secrets remain valid indefinitely | Use managed identities or federated credentials; set max secret lifetime |
| Not testing Conditional Access in report-only mode | Accidental lockout of users or administrators | Always deploy in report-only first; verify for 1-2 weeks |
| Forgetting to exclude break-glass accounts from CA policies | Complete lockout from the tenant | Exclude break-glass accounts from all Conditional Access policies |
| Orphaned service principals after app decommissioning | Stale credentials with active permissions remain exploitable | Include service principal cleanup in decommissioning checklists |
Break-Glass Account Safety
Your break-glass accounts are the last line of defense against tenant lockout. They should be cloud-only accounts (not synced from on-premises), excluded from ALL Conditional Access policies, have no MFA requirement (or use a FIDO2 key stored in a safe), use extremely long random passwords, and have their sign-in activity monitored with immediate alerts. Test break-glass access quarterly to ensure it still works.
Multi-Cloud Identity Considerations
Organizations operating across Azure, AWS, and GCP face the challenge of maintaining consistent identity governance across fundamentally different IAM systems. Azure AD can serve as the centralized identity provider across all three clouds using federation.
- AWS: Federate Azure AD with AWS IAM Identity Center (formerly AWS SSO) to provide Azure AD users with SSO access to AWS accounts and roles.
- GCP: Configure Workforce Identity Federation to allow Azure AD users to authenticate to Google Cloud resources using their Azure AD credentials.
- Consistent governance: Use Azure AD as the source of truth for identity lifecycle. When a user is disabled in Azure AD, their federated access to AWS and GCP should be revoked automatically.
Key Takeaways
- 1Azure AD (now Entra ID) is the central identity provider for all Azure resources.
- 2RBAC assignments combine a principal, role definition, and scope.
- 3Use managed identities for service-to-service authentication, eliminating credentials to manage.
- 4Conditional Access policies enforce MFA, device compliance, and location restrictions.
- 5Privileged Identity Management provides just-in-time access to reduce standing permissions.
- 6Always assign roles to groups, not individual users, for scalable access management.
Frequently Asked Questions
What is the difference between Azure AD and Azure RBAC?
What is the difference between Owner and Contributor roles?
Should I use Azure AD groups for role assignments?
What is Privileged Identity Management (PIM)?
What are managed identities in Azure?
How do I audit role assignments in Azure?
Written by CloudToolStack Team
Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.
Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.