Manage Azure Identities & Governance (AZ-104)

IntermediateTopic55 min11 min read26 Apr 2026Azure

AZ-104 — Manage Azure Identities and Governance. Microsoft Entra ID (Azure AD), RBAC, Azure Policy, Management Groups, locks, and PIM — with step-by-step labs.

What you'll learn

  • Create and manage users, groups, and guests in Microsoft Entra ID
  • Assign Azure RBAC roles and create custom roles
  • Design Management Group and subscription hierarchies
  • Enforce compliance with Azure Policy
  • Protect resources with resource locks
  • Use Privileged Identity Management for just-in-time access

Relevant for certifications

AZ-104

Microsoft Entra ID (formerly Azure Active Directory)

Microsoft Entra ID is Azure's identity and access management service — the central identity provider for Azure, Microsoft 365, and thousands of SaaS applications.

Microsoft Entra ID (Tenant)
├── Users (employees, admins, service accounts)
├── Groups (security, Microsoft 365)
├── Applications (enterprise apps, app registrations)
├── Devices (Entra joined, registered)
└── External identities (B2B guests, B2C customers)

Entra ID vs Active Directory Domain Services

Microsoft Entra IDAD DS (on-premises)
ProtocolREST/OAuth/SAMLKerberos/LDAP/NTLM
StructureFlat (no OUs)Hierarchical (OUs, GPOs)
ManagementCloud-nativeOn-premises or IaaS
MFABuilt-inThird-party required
Device joinEntra JoinDomain join

Users and Groups

Create a user

# Create a new user
az ad user create \
  --display-name "Jane Smith" \
  --user-principal-name jane.smith@company.onmicrosoft.com \
  --password "TempP@ss123" \
  --force-change-password-next-sign-in true

# Create a guest user (B2B invite)
az ad user invite \
  --user-principal-name contractor@external.com \
  --display-name "External Contractor" \
  --invited-user-email contractor@external.com \
  --invite-redirect-url https://portal.azure.com

Create and manage groups

# Create a security group
az ad group create \
  --display-name "Network Admins" \
  --mail-nickname NetworkAdmins \
  --description "Team responsible for VNet management"

# Add a member
az ad group member add \
  --group "Network Admins" \
  --member-id $(az ad user show --id jane.smith@company.onmicrosoft.com --query id -o tsv)

# Create dynamic group (auto-membership based on attributes)
# Done in portal: Groups → New Group → Membership type: Dynamic User
# Rule: user.department -eq "Engineering"

Dynamic groups

Dynamic groups automatically add/remove members based on user attributes — no manual management:

Rule syntax:
user.department -eq "Engineering"            → all Engineering dept users
user.jobTitle -contains "Manager"            → all managers
user.userPrincipalName -endsWith "@corp.com" → all corp.com email users
(user.department -eq "IT") -and (user.accountEnabled -eq true)

Bulk operations

# Bulk create users from CSV
az ad user list --output csv > users-export.csv
# Edit CSV, then use portal: Users → Bulk create → Upload CSV

Azure Role-Based Access Control (RBAC)

RBAC controls who can do what on which Azure resource.

Role assignment = Security Principal + Role Definition + Scope

Who: Jane Smith (user)
Can do what: Virtual Machine Contributor (role)
On what: Resource Group "prod-rg" (scope)

Built-in roles

RoleDescription
OwnerFull access + manage access
ContributorFull access, cannot manage access
ReaderRead-only
User Access AdministratorManage user access (not resources)
Virtual Machine ContributorManage VMs (not networking/storage)
Network ContributorManage networking
Storage Account ContributorManage storage accounts

Assign a role

# Assign Contributor to a user at resource group scope
az role assignment create \
  --assignee jane.smith@company.onmicrosoft.com \
  --role "Contributor" \
  --scope /subscriptions/<sub-id>/resourceGroups/prod-rg

# Assign Virtual Machine Contributor at subscription scope
az role assignment create \
  --assignee $(az ad group show --group "VM Admins" --query id -o tsv) \
  --role "Virtual Machine Contributor" \
  --scope /subscriptions/<sub-id>

# Assign Reader at management group scope
az role assignment create \
  --assignee jane.smith@company.onmicrosoft.com \
  --role "Reader" \
  --scope /providers/Microsoft.Management/managementGroups/mg-prod

Scope hierarchy

Management Group
└── Subscription
    └── Resource Group
        └── Individual Resource

Roles assigned higher in hierarchy are inherited downward.
A role at subscription scope applies to ALL resource groups and resources within.

Custom roles

Create a role with exactly the permissions you need:

# Create a custom role (start from JSON definition)
cat > custom-vm-operator.json << 'EOF'
{
  "Name": "VM Operator",
  "Description": "Can start, stop, and restart VMs, read all resources",
  "Actions": [
    "Microsoft.Compute/virtualMachines/start/action",
    "Microsoft.Compute/virtualMachines/powerOff/action",
    "Microsoft.Compute/virtualMachines/restart/action",
    "Microsoft.Compute/virtualMachines/read",
    "Microsoft.Resources/subscriptions/resourceGroups/read"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": ["/subscriptions/<sub-id>"]
}
EOF

az role definition create --role-definition @custom-vm-operator.json

# Assign the custom role
az role assignment create \
  --assignee ops-team@company.com \
  --role "VM Operator" \
  --scope /subscriptions/<sub-id>/resourceGroups/prod-rg

Check effective permissions

# What can this user do?
az role assignment list --assignee jane.smith@company.onmicrosoft.com --all

# Check if a specific action is allowed
az role assignment list \
  --scope /subscriptions/<sub-id>/resourceGroups/prod-rg \
  --query "[?principalName=='jane.smith@company.onmicrosoft.com']"

Management Groups

Management groups sit above subscriptions — group subscriptions for policy and RBAC application at scale.

Tenant Root Group
├── Platform MG
│   ├── Connectivity subscription (Hub VNet, ExpressRoute)
│   └── Identity subscription (AD DS, Azure AD Connect)
├── Production MG
│   ├── Prod-App-1 subscription
│   └── Prod-App-2 subscription
├── Non-Production MG
│   ├── Dev subscription
│   └── Test subscription
└── Sandbox MG
    └── Experimentation subscription
# Create a management group
az account management-group create \
  --name "mg-production" \
  --display-name "Production"

# Move a subscription to a management group
az account management-group subscription add \
  --name "mg-production" \
  --subscription <subscription-id>

Azure Policy

Azure Policy enforces organisational standards and assesses compliance across Azure resources.

Policy effects

EffectDescription
DenyBlocks non-compliant resource creation/update
AuditLogs non-compliant resources, doesn't block
DeployIfNotExistsDeploys a resource if missing (e.g., add diagnostics)
AuditIfNotExistsAudits if a related resource doesn't exist
AppendAdds fields to the resource (e.g., tags)
ModifyModify tags on resources
DisabledPolicy is inactive

Apply a built-in policy

# Enforce allowed VM SKUs
POLICY_ID=$(az policy definition list \
  --query "[?displayName=='Allowed virtual machine size SKUs'].id" -o tsv)

az policy assignment create \
  --name "allowed-vm-skus" \
  --policy $POLICY_ID \
  --scope /subscriptions/<sub-id>/resourceGroups/prod-rg \
  --params '{"listOfAllowedSKUs": {"value": ["Standard_D2s_v3", "Standard_D4s_v3"]}}'

Create a custom policy

# Policy: Require a CostCenter tag on all resources
cat > require-tag-policy.json << 'EOF'
{
  "mode": "All",
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "notIn": ["Microsoft.Resources/subscriptions/resourceGroups"]
        },
        {
          "field": "tags['CostCenter']",
          "exists": "false"
        }
      ]
    },
    "then": {
      "effect": "Deny"
    }
  }
}
EOF

az policy definition create \
  --name "require-costcenter-tag" \
  --display-name "Require CostCenter tag" \
  --rules @require-tag-policy.json

az policy assignment create \
  --name "enforce-costcenter-tag" \
  --policy require-costcenter-tag \
  --scope /subscriptions/<sub-id>

Policy Initiatives (Policy Sets)

Group multiple policies into a single assignment:

# Create initiative from multiple policies
az policy set-definition create \
  --name "security-baseline" \
  --display-name "Security Baseline" \
  --policy-definitions '[
    {"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/1e30110a-5ceb-460c-a204-c1c3969c6d62"},
    {"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/4da35fc9-c9e7-4960-aec9-797fe7d9051d"}
  ]'

# Assign the initiative
az policy assignment create \
  --name "security-baseline-assignment" \
  --policy-set-definition security-baseline \
  --scope /subscriptions/<sub-id>

Remediation tasks

For DeployIfNotExists and Modify policies, create a remediation task to fix existing non-compliant resources:

az policy remediation create \
  --name "add-diagnostics-remediation" \
  --policy-assignment /subscriptions/<sub-id>/providers/Microsoft.Authorization/policyAssignments/add-vm-diagnostics \
  --resource-discovery-mode ReEvaluateCompliance

Resource Locks

Resource locks prevent accidental deletion or modification — they apply to all users regardless of RBAC role.

Lock typePrevents
CanNotDeleteDelete (read and modify still allowed)
ReadOnlyBoth modification AND deletion
# Lock a resource group (children inherit the lock)
az lock create \
  --name "prod-rg-lock" \
  --resource-group prod-rg \
  --lock-type CanNotDelete \
  --notes "Production resource group — do not delete"

# Lock an individual resource
az lock create \
  --name "vnet-lock" \
  --resource-group prod-rg \
  --resource-type Microsoft.Network/virtualNetworks \
  --resource-name prod-vnet \
  --lock-type CanNotDelete

# List locks
az lock list --resource-group prod-rg

# Delete a lock (must be done before deleting the resource)
az lock delete --name "vnet-lock" --resource-group prod-rg

Warning

ReadOnly locks can cause unexpected failures — for example, an App Service with ReadOnly lock may fail to start because starting requires a write operation to update the LastModified timestamp.


Managed Identities

Managed identities provide an Azure AD identity for Azure resources to authenticate to other Azure services — no credentials to manage.

TypeDescription
System-assignedTied to the resource lifecycle — deleted with the resource
User-assignedIndependent resource — can be assigned to multiple resources
# Enable system-assigned managed identity on a VM
az vm identity assign \
  --resource-group myRG \
  --name myVM

# Create a user-assigned managed identity
az identity create \
  --resource-group myRG \
  --name myManagedIdentity

# Assign the identity to a VM
az vm identity assign \
  --resource-group myRG \
  --name myVM \
  --identities /subscriptions/<sub-id>/resourceGroups/myRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myManagedIdentity

# Grant the identity access to Key Vault secrets
az role assignment create \
  --assignee $(az identity show --name myManagedIdentity --resource-group myRG --query principalId -o tsv) \
  --role "Key Vault Secrets User" \
  --scope /subscriptions/<sub-id>/resourceGroups/myRG/providers/Microsoft.KeyVault/vaults/myKV

On the VM, the app can now call Key Vault without any stored credentials — it gets a token from the IMDS endpoint automatically.


Privileged Identity Management (PIM)

PIM provides just-in-time (JIT) privileged access — users only have elevated roles when they need them.

Key concepts

ConceptDescription
Eligible assignmentUser can activate the role, but it's not active by default
Active assignmentRole is permanently active
ActivationUser requests access for a limited time (hours)
ApprovalActivation can require manager approval
Access reviewsPeriodic review of who has access

Configure PIM for a role

Azure AD → Privileged Identity Management → Azure Resources → Subscriptions
→ Select subscription → Roles → Owner
→ Settings:
  - Maximum activation duration: 4 hours
  - Require MFA on activation: Yes
  - Require justification: Yes
  - Require approval: Yes (approver: security-team@company.com)
→ Assignments → Add assignments (Eligible):
  - Member: Jane Smith
  - Assignment type: Eligible

Activate a role (end user)

PIM → My roles → Azure Resource roles
→ Owner → Activate
→ Activation duration: 2 hours
→ Justification: "Deploying production infrastructure for project X"
→ Submit → Wait for approval → Role activates

Administrative Units

Administrative units (AUs) allow delegation of administration to subsets of users within a tenant — useful for large organisations with regional IT teams:

Example:
  AU: UK-Staff
    Members: all UK-based users
    Scoped admin: UK IT team has User Administrator for UK-Staff AU only
                  (cannot see or manage users outside the AU)
# Create an administrative unit
az ad administrative-unit create --display-name "UK-Staff"

# Add a user to the AU
az ad administrative-unit member add \
  --administrative-unit-id <au-id> \
  --member-id <user-object-id>

# Assign scoped admin role (done in portal: AU → Roles and administrators)

Hands-on: Governance Setup for a New Project

Goal: Set up governance for a new production project with least-privilege access.

1. Create resource group
   az group create -n "ecom-prod-rg" -l eastus

2. Apply resource lock
   az lock create -n "no-delete" -g ecom-prod-rg --lock-type CanNotDelete

3. Create Azure Policy assignment
   # Require Environment tag
   az policy assignment create \
     --name "require-environment-tag" \
     --policy "require-tag-policy" \
     --scope /subscriptions/<sub-id>/resourceGroups/ecom-prod-rg

4. Create Security Group
   az ad group create --display-name "EcomProd-Developers"

5. Assign Contributor role (RBAC)
   az role assignment create \
     --assignee <group-object-id> \
     --role "Contributor" \
     --scope /subscriptions/<sub-id>/resourceGroups/ecom-prod-rg

6. Create managed identity for app
   az identity create -n ecom-app-identity -g ecom-prod-rg
   # Grant Key Vault Secrets User role to the identity

7. Enable PIM for Owner role on the subscription
   # Set: eligible assignment for on-call team
   # Require approval + MFA for activation
   # Max 4-hour activation duration

8. Check compliance
   az policy state list -g ecom-prod-rg
   # All resources should be compliant with tag policy

Common AZ-104 Exam Questions

Q: A user has Contributor on a resource group but still can't delete a VM. Why? A resource lock (CanNotDelete or ReadOnly) is applied to the resource or resource group. Locks override RBAC — even Owners and Contributors cannot delete locked resources without first removing the lock.

Q: You need to allow a team to start/stop VMs but not create or delete them. What do you use? Create a custom RBAC role with only Microsoft.Compute/virtualMachines/start/action, Microsoft.Compute/virtualMachines/powerOff/action, and read permissions. Assign it to the team's security group at the resource group scope.

Q: How do you prevent all subscriptions in an organisation from deploying resources to restricted regions? Apply an Azure Policy (Deny effect) at the Management Group level — it inherits to all subscriptions. Or apply an SCP if using Azure landing zones with specific governance frameworks.

Q: What's the difference between a system-assigned and user-assigned managed identity? System-assigned is created per-resource and deleted with it — one-to-one. User-assigned is a standalone resource that can be assigned to multiple resources — useful when multiple services need the same identity and permissions.


What to Learn Next

  1. Managing Subscriptions — subscription organisation and cost management
  2. Azure Monitor (AZ-104) — monitor compliance and resource health
  3. Azure Governance Cheatsheet — quick reference for policy and RBAC

More in Microsoft Azure