Identity is the new perimeter. In the cloud, there’s no firewall protecting your data center – authentication and authorization are your first line of defense. Every Azure resource access starts with “who are you?” and “what are you allowed to do?”
From the field: I have implemented identity governance across organisations ranging from 50 to 5,000 users. The concepts here are not theoretical — they are the exact policies I configure in production Azure AD (now Entra ID) environments. Getting identity right is the foundation of everything else in cloud security.
This post covers the 20-25% of AZ-104 that deals with identity and governance. Microsoft Entra ID (formerly Azure AD), Role-Based Access Control, subscriptions, management groups, and Azure Policy. Get this wrong, and you have security holes. Get it right, and you have a foundation for everything else.
Career Impact
Why this matters: Identity and governance skills are essential for any cloud role. Security teams, compliance auditors, and architects all need someone who understands RBAC and policy.
Resume value: “Implemented RBAC model for 200+ user Azure environment” or “Deployed Azure Policy initiatives achieving 95% compliance”
What You’ll Learn
- Microsoft Entra ID (Azure AD) concepts
- Users, groups, and external identities
- Role-Based Access Control (RBAC)
- Management groups and subscriptions
- Azure Policy and compliance
Quick Reference
| Concept | What It Is | Key Point |
|---|---|---|
| Entra ID | Identity provider | Not the same as on-prem AD |
| Tenant | Entra ID instance | One per organization |
| RBAC | Permission system | Role + Scope = Access |
| Management Group | Subscription container | Hierarchical organization |
| Azure Policy | Compliance enforcement | Deny, audit, or modify |
| Initiative | Policy collection | Group related policies |
Microsoft Entra ID (Azure AD)
What It Is (and Isn’t)
Entra ID is NOT on-premises Active Directory in the cloud.
| Feature | Active Directory | Entra ID |
|---|---|---|
| Protocol | LDAP, Kerberos | SAML, OAuth, OIDC |
| Structure | OUs, Forests | Flat directory |
| Group Policy | Yes | No (use Intune) |
| Join | Domain join | Azure AD join |
| Purpose | On-prem resources | Cloud/SaaS apps |
They can work together (hybrid identity), but they’re different systems.
Tenant Basics
Every Azure subscription is associated with an Entra ID tenant:
# Azure CLI - View current tenant
az account show --query tenantId
# Azure CLI - List all tenants you have access to
az account tenant list
# Azure PowerShell - View current tenant
(Get-AzContext).Tenant.Id
# Azure PowerShell - List all tenants
Get-AzTenant
One tenant per organization is typical. Multiple tenants create complexity.
Users
# Azure CLI - Create user
az ad user create \
--display-name "John Smith" \
--user-principal-name [email protected] \
--password "TempP@ss123!" \
--force-change-password-next-sign-in true
# Azure PowerShell - Create user
New-AzADUser -DisplayName "John Smith" `
-UserPrincipalName "[email protected]" `
-Password (ConvertTo-SecureString "TempP@ss123!" -AsPlainText -Force) `
-ForceChangePasswordNextLogin
User types:
- Member – Full organization member
- Guest – External user (B2B)
Groups
Two group types:
Security Groups – For RBAC assignments
# Azure CLI - Create security group
az ad group create --display-name "VM-Admins" --mail-nickname "vm-admins"
# Azure CLI - Add member to group
az ad group member add --group "VM-Admins" --member-id <user-object-id>
# Azure PowerShell - Create security group
New-AzADGroup -DisplayName "VM-Admins" -MailNickname "vm-admins"
# Azure PowerShell - Add member to group
Add-AzADGroupMember -TargetGroupDisplayName "VM-Admins" -MemberObjectId <user-object-id>
Microsoft 365 Groups – For collaboration (Teams, SharePoint)
Membership types:
- Assigned – Manual membership
- Dynamic User – Rule-based membership
- Dynamic Device – Rule-based for devices
Dynamic group example:
(user.department -eq "IT") and (user.jobTitle -contains "Engineer")
External Identities (B2B)
Invite external users without creating accounts:
# Azure CLI - Invite guest user
az ad user invite \
--invited-user-email-address [email protected] \
--invite-redirect-url https://portal.azure.com
# Azure PowerShell - Invite guest user
New-AzADUser -InvitedUserEmailAddress "[email protected]" `
-InviteRedirectUrl "https://portal.azure.com" `
-SendInvitationMessage $true
Guest users appear in your directory but authenticate against their home tenant.
Role-Based Access Control (RBAC)
The RBAC Model
RBAC has three components:
Security Principal (WHO) + Role Definition (WHAT) + Scope (WHERE) = Access
Security Principal: User, group, service principal, managed identity
Role Definition: Collection of permissions (actions)
Scope: Resource, resource group, subscription, or management group
Built-in Roles
Common roles:
| Role | Description | Use Case |
|---|---|---|
| Owner | Full access + can delegate | Account admins |
| Contributor | Full access, no delegation | Developers, operators |
| Reader | Read-only | Auditors, viewers |
| User Access Administrator | Manage user access only | Delegated access management |
Resource-specific roles:
- Virtual Machine Contributor
- Storage Account Contributor
- Network Contributor
- SQL Server Contributor
Assigning Roles
Portal: Resource → Access control (IAM) → Add role assignment
# Azure CLI - Assign Contributor role to user at resource group scope
az role assignment create \
--assignee [email protected] \
--role "Contributor" \
--scope /subscriptions/<sub-id>/resourceGroups/myResourceGroup
# Azure PowerShell - Assign Contributor role
New-AzRoleAssignment `
-SignInName "[email protected]" `
-RoleDefinitionName "Contributor" `
-ResourceGroupName "myResourceGroup"
Scope Hierarchy
Permissions inherit downward:
Management Group
└── Subscription
└── Resource Group
└── Resource
Assign at the highest appropriate level – not higher. Reader at subscription = Reader on everything in subscription.
Custom Roles
When built-in roles don’t fit:
{
"Name": "VM Restart Operator",
"Description": "Can restart VMs but not create or delete",
"Actions": [
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Compute/virtualMachines/read"
],
"NotActions": [],
"AssignableScopes": [
"/subscriptions/<subscription-id>"
]
}
# Azure CLI - Create custom role
az role definition create --role-definition custom-role.json
# Azure PowerShell - Create custom role
New-AzRoleDefinition -InputFile "custom-role.json"
Deny Assignments
Block specific actions even if a role allows them:
- Can only be created via Azure Blueprints
- Useful for compliance enforcement
- Deny trumps allow
Management Groups
Hierarchy Structure
Root Management Group
├── Production MG
│ ├── Production Subscription 1
│ └── Production Subscription 2
├── Development MG
│ └── Dev Subscription
└── Sandbox MG
└── Personal Subscriptions
# Azure CLI - Create management group
az account management-group create --name "Production"
# Azure CLI - Move subscription under management group
az account management-group subscription add \
--name "Production" \
--subscription "Production-Sub-001"
# Azure PowerShell - Create management group
New-AzManagementGroup -GroupName "Production"
# Azure PowerShell - Move subscription under management group
New-AzManagementGroupSubscription -GroupName "Production" -SubscriptionId "<sub-id>"
Why Use Management Groups?
- RBAC at scale – Assign roles to management group, inherit to all subscriptions
- Policy at scale – Apply policy once, enforce everywhere
- Compliance – Organizational boundaries
- Cost management – Group related subscriptions
Azure Policy
What Policy Does
Azure Policy evaluates resources against rules and takes action:
- Deny – Block non-compliant resources from being created
- Audit – Log non-compliance, don’t block
- Append – Add tags or properties
- Modify – Change resource properties
- DeployIfNotExists – Deploy related resource if missing
Built-in Policies
Hundreds available out of the box:
# Azure CLI - List built-in policies
az policy definition list --query "[?policyType=='BuiltIn'].{Name:displayName}" -o table
# Azure PowerShell - List built-in policies
Get-AzPolicyDefinition | Where-Object { $_.Properties.PolicyType -eq "BuiltIn" } | Select-Object -Property DisplayName
Common policies:
- Allowed locations
- Allowed VM SKUs
- Require tags on resources
- Configure Azure Backup
- Allowed storage account SKUs
Assigning Policy
# Azure CLI - Assign policy to resource group
az policy assignment create \
--name "require-tag" \
--display-name "Require Environment Tag" \
--policy "/providers/Microsoft.Authorization/policyDefinitions/1e30110a-5ceb-460c-a204-c1c3969c6d62" \
--scope /subscriptions/<sub-id>/resourceGroups/myResourceGroup \
--params '{"tagName": {"value": "Environment"}}'
# Azure PowerShell - Assign policy to resource group
$ResourceGroup = Get-AzResourceGroup -Name "myResourceGroup"
$Policy = Get-AzPolicyDefinition -Id "/providers/Microsoft.Authorization/policyDefinitions/1e30110a-5ceb-460c-a204-c1c3969c6d62"
New-AzPolicyAssignment -Name "require-tag" -DisplayName "Require Environment Tag" `
-Scope $ResourceGroup.ResourceId -PolicyDefinition $Policy `
-PolicyParameterObject @{"tagName"="Environment"}
Custom Policies
Define your own rules:
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
{
"field": "Microsoft.Compute/virtualMachines/storageProfile.osDisk.diskSizeGB",
"greater": 128
}
]
},
"then": {
"effect": "deny"
}
}
}
This denies VMs with OS disks larger than 128GB.
Policy Initiatives
Group related policies:
Built-in initiatives:
- Azure Security Benchmark
- CIS Microsoft Azure Foundations
- ISO 27001:2013
- NIST SP 800-53
Compliance Dashboard
View compliance status:
Portal: Policy → Compliance
Shows:
- Overall compliance percentage
- Non-compliant resources
- Policy assignments
- Remediation status
Cost Management
Budgets
Set spending limits with alerts:
# Azure CLI - Create budget
az consumption budget create \
--budget-name "monthly-budget" \
--amount 1000 \
--time-grain Monthly \
--category Cost \
--notifications '{ "threshold": 80, "contactEmails": ["[email protected]"] }'
# Azure PowerShell - Create budget (via REST API or Portal recommended)
# Budget creation is typically done via Portal: Cost Management > Budgets
Cost Analysis
Portal: Cost Management → Cost analysis
Filter by:
- Resource group
- Tag
- Service name
- Time period
Recommendations
Azure Advisor provides cost recommendations:
- Right-size VMs
- Delete unused resources
- Reserve instances
- Use spot VMs
Practice Lab
Lab 1: Set Up Management Groups and RBAC
# Azure CLI - Create management groups
az account management-group create --name "Production"
az account management-group create --name "Development"
# Create security group for developers
az ad group create --display-name "Azure-Developers" --mail-nickname "azure-developers"
# Assign Contributor at Development management group
az role assignment create \
--assignee-object-id $(az ad group show -g "Azure-Developers" --query id -o tsv) \
--role "Contributor" \
--scope /providers/Microsoft.Management/managementGroups/Development
# Azure PowerShell - Create management groups
New-AzManagementGroup -GroupName "Production"
New-AzManagementGroup -GroupName "Development"
# Create security group for developers
$Group = New-AzADGroup -DisplayName "Azure-Developers" -MailNickname "azure-developers"
# Assign Contributor at Development management group
New-AzRoleAssignment -ObjectId $Group.Id -RoleDefinitionName "Contributor" `
-Scope "/providers/Microsoft.Management/managementGroups/Development"
Lab 2: Implement Azure Policy
# Azure CLI - Assign "Require tag" policy to resource group
az policy assignment create \
--name "require-environment-tag" \
--display-name "Require Environment Tag" \
--policy "/providers/Microsoft.Authorization/policyDefinitions/1e30110a-5ceb-460c-a204-c1c3969c6d62" \
--scope /subscriptions/<sub-id>/resourceGroups/az104-labs \
--params '{"tagName": {"value": "Environment"}}'
# Try to create a resource without the tag (should fail)
az storage account create \
--name testpolicy$RANDOM \
--resource-group az104-labs \
--location uksouth \
--sku Standard_LRS
# Try with the tag (should succeed)
az storage account create \
--name testpolicy$RANDOM \
--resource-group az104-labs \
--location uksouth \
--sku Standard_LRS \
--tags Environment=Development
# Azure PowerShell - Assign policy
$ResourceGroup = Get-AzResourceGroup -Name "az104-labs"
$Policy = Get-AzPolicyDefinition -Id "/providers/Microsoft.Authorization/policyDefinitions/1e30110a-5ceb-460c-a204-c1c3969c6d62"
New-AzPolicyAssignment -Name "require-environment-tag" `
-DisplayName "Require Environment Tag" `
-Scope $ResourceGroup.ResourceId `
-PolicyDefinition $Policy `
-PolicyParameterObject @{"tagName"="Environment"}
# Try to create without tag (should fail)
New-AzStorageAccount -ResourceGroupName "az104-labs" -Name "testpolicy$(Get-Random)" `
-Location "uksouth" -SkuName "Standard_LRS"
# Try with tag (should succeed)
New-AzStorageAccount -ResourceGroupName "az104-labs" -Name "testpolicy$(Get-Random)" `
-Location "uksouth" -SkuName "Standard_LRS" -Tag @{Environment="Development"}
Interview Questions
Q1: “Explain the difference between Azure AD and on-premises AD.”
Good Answer: “They serve different purposes and use different protocols. On-premises AD uses LDAP and Kerberos for domain-joined Windows machines and supports Group Policy. Azure AD – now Entra ID – uses modern web protocols like SAML and OAuth for cloud and SaaS applications. They can work together through Azure AD Connect for hybrid identity, but they’re not the same system. You can’t just ‘move’ AD to the cloud – you sync or federate between them.”
Q2: “How would you implement least-privilege access in Azure?”
Good Answer: “Start with no access – users get nothing by default. Use built-in RBAC roles when possible because they’re tested and documented. Assign at the narrowest scope that makes sense – if someone needs access to one resource group, don’t give subscription access. Use groups instead of individual assignments for easier management. Review access regularly with access reviews. For privileged operations, consider Privileged Identity Management for just-in-time elevation rather than permanent assignments.”
Q3: “A team keeps creating VMs that are too expensive. How would you prevent this?”
Good Answer: “Azure Policy. I’d create or use a built-in policy that restricts allowed VM SKUs to approved sizes. Assign it with ‘Deny’ effect at the subscription or management group level. Before deployment, the policy evaluates the request – if someone tries to create a D64 VM and it’s not in the allowed list, the deployment fails. Combine with budgets and cost alerts for visibility. This gives governance without manual approval processes.”
Key Exam Points
- Entra ID is identity only – No OUs, no GPO
- RBAC = Role + Scope – Know built-in roles
- Deny trumps allow – For deny assignments
- Policy effects matter – Deny vs Audit vs Append
- Inheritance flows down – Management group → Subscription → Resource Group → Resource
- Custom roles need AssignableScopes – Can’t be broader than original scope
Career Application
On your resume:
- “Implemented RBAC model for 200+ user Azure environment”
- “Designed management group hierarchy for multi-subscription governance”
- “Deployed Azure Policy initiatives achieving 95% compliance”
Demonstrate:
- Understanding of least-privilege
- Policy vs RBAC distinction
- Practical governance experience
- Compliance awareness
Next Steps
Next in series: Azure Virtual Networks – Networking fundamentals
Related: Active Directory Essentials – On-prem AD comparison
Lab: Create a management group structure and assign policies
Identity and governance aren’t exciting, but they’re foundational. Get them right once, and everything else is easier. Get them wrong, and you’ll spend months fixing security holes.
This guide is part of the Azure AZ-104 Study Series. See the full series for more guides like this.
Related Guides
If you found this useful, these guides continue the journey:
- Azure AZ-104 Series — the full certification study path
- Azure Virtual Networks — networking fundamentals for your Azure environment
- Azure Storage — the next module in the AZ-104 path
- Learn Azure for Free — get hands-on without spending money

ReadTheManual is run, written and curated by Eric Lonsdale.
Eric has over 20 years of professional experience in IT infrastructure, cloud architecture, and cybersecurity, but started with PCs long before that.
He built his first machine from parts bought off tables at the local college campus, hoping they worked. He learned on BBC Micros and Atari units in the early 90s, and has built almost every PC he’s used between 1995 and now.
From helpdesk to infrastructure architect, Eric has worked across enterprise datacentres, Azure environments, and security operations. He’s managed teams, trained engineers, and spent two decades solving the problems this site teaches you to solve.
ReadTheManual exists because Eric believes the best way to learn IT is to build things, break things, and actually read the manual. Every guide on this site runs on infrastructure he owns and maintains.
Enjoyed this guide?
New articles on Linux, homelab, cloud, and automation every 2 days. No spam, unsubscribe anytime.

