Skip to content

Identity and Access

First PublishedByAtif Alam

Identity in Azure is handled by Microsoft Entra ID (formerly Azure Active Directory / Azure AD). It’s different from AWS IAM — Entra ID is a full identity provider (SSO, MFA, directory services) while Azure RBAC handles authorization on resources.

┌──────────────────────────────────────────────┐
│ Entra ID Tenant │
│ (your organization's identity directory) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │ Users │ │ Groups │ │ App │ │
│ │ (people) │ │ (teams) │ │ Registrations│ │
│ └────┬─────┘ └────┬─────┘ └──────┬─────┘ │
│ └──────┬───────┘ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────────┐ │
│ │ Azure RBAC │ │
│ │ (role assignments on resources) │ │
│ │ "Reader on subscription X" │ │
│ │ "Contributor on resource group Y" │ │
│ └──────────────────────────────────────┘ │
└──────────────────────────────────────────────┘
ConceptWhat It Is
TenantAn Entra ID instance representing your organization. Contains all users, groups, and app registrations.
UserA person or account in the directory. Can sign in with email/password, SSO, or MFA.
GroupA collection of users. Assign roles to groups instead of individual users.
Service principalAn identity for an application or service (like an AWS IAM role for an app).
Managed identityAn Azure-managed service principal for Azure resources — no credentials to manage.
App registrationRegisters an application with Entra ID for authentication (OAuth2, OIDC).
Azure (Entra ID + RBAC)AWS (IAM)
IdentityEntra ID (full directory: SSO, MFA, federation)IAM users (basic, no directory)
AuthorizationAzure RBAC (role assignments on scopes)IAM policies (JSON, attached to identities)
Service identityManaged identity / service principalIAM role (instance profile)
GroupsEntra ID groupsIAM groups
SSOBuilt-in (SAML, OIDC, WS-Fed)External (Okta, etc. via federation)
MFABuilt-inBuilt-in (simpler)

RBAC controls what users and services can do with Azure resources.

A role assignment has three parts:

WHO (security principal) + WHAT (role) + WHERE (scope) = access
PartExamples
Security principalUser, group, service principal, managed identity
RoleReader, Contributor, Owner, custom roles
ScopeManagement group, subscription, resource group, or single resource
RolePermissions
OwnerFull access + can assign roles to others
ContributorFull access except role assignments
ReaderRead-only access
User Access AdministratorManage role assignments only

There are also hundreds of service-specific roles:

RoleScope
Virtual Machine ContributorManage VMs but not access the network or storage
Storage Blob Data ReaderRead blob data (not the storage account itself)
AKS Cluster AdminFull access to AKS clusters
Key Vault Secrets UserRead secrets from Key Vault
SQL DB ContributorManage SQL databases
Terminal window
# Assign "Contributor" to a user on a resource group
az role assignment create \
--assignee [email protected] \
--role Contributor \
--resource-group myapp-prod-rg
# Assign "Reader" to a group on a subscription
az role assignment create \
--assignee-object-id <group-object-id> \
--role Reader \
--scope /subscriptions/<subscription-id>
# List role assignments
az role assignment list --resource-group myapp-prod-rg --output table

Roles assigned at a higher scope are inherited by lower scopes:

Management Group ──► Subscription ──► Resource Group ──► Resource
(broadest) (narrowest)

A “Contributor” role on a subscription applies to all resource groups and resources within it.

Terminal window
az role definition create --role-definition '{
"Name": "VM Operator",
"Description": "Can start and stop VMs but not create or delete them",
"Actions": [
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/powerOff/action",
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Compute/virtualMachines/read"
],
"NotActions": [],
"AssignableScopes": ["/subscriptions/<subscription-id>"]
}'

A service principal is an identity for an application, script, or CI/CD pipeline. It has its own credentials (secret or certificate) and RBAC role assignments.

Terminal window
# Create with a secret (returns appId, password, tenant)
az ad sp create-for-rbac \
--name "myapp-cicd" \
--role Contributor \
--scopes /subscriptions/<sub-id>/resourceGroups/myapp-prod-rg
# Output:
# {
# "appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
# "displayName": "myapp-cicd",
# "password": "generated-secret",
# "tenant": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# }
Terminal window
# Login as the service principal
az login --service-principal \
--username <appId> \
--password <password> \
--tenant <tenant>

In CI/CD, store these credentials as pipeline secrets (or better, use federated credentials with OIDC — no secrets to manage).

Like AWS OIDC for GitHub Actions — no secrets needed:

Terminal window
# Create federated credential for GitHub Actions
az ad app federated-credential create \
--id <app-object-id> \
--parameters '{
"name": "github-main",
"issuer": "https://token.actions.githubusercontent.com",
"subject": "repo:myorg/myrepo:ref:refs/heads/main",
"audiences": ["api://AzureADTokenExchange"]
}'

Managed identities are the recommended way for Azure resources to authenticate to other Azure services — no credentials to store or rotate.

TypeWhat It IsUse Case
System-assignedTied to one resource. Created and deleted with the resource.VM, App Service, Function, AKS pod
User-assignedStandalone identity. Can be shared across resources.Multiple VMs/services needing the same access
Terminal window
# Enable system-assigned identity on a VM
az vm identity assign --resource-group myapp-rg --name my-vm
# Enable on an App Service
az webapp identity assign --resource-group myapp-rg --name my-webapp
Terminal window
# Get the managed identity's principal ID
PRINCIPAL_ID=$(az vm identity show --resource-group myapp-rg --name my-vm --query principalId -o tsv)
# Grant it "Storage Blob Data Reader" on a storage account
az role assignment create \
--assignee $PRINCIPAL_ID \
--role "Storage Blob Data Reader" \
--scope /subscriptions/<sub>/resourceGroups/myapp-rg/providers/Microsoft.Storage/storageAccounts/mystorage

The Azure SDKs automatically detect managed identities — no credentials in code:

from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient
# DefaultAzureCredential automatically uses managed identity when running on Azure
credential = DefaultAzureCredential()
blob_service = BlobServiceClient(
account_url="https://mystorage.blob.core.windows.net",
credential=credential
)

DefaultAzureCredential tries multiple methods in order: environment variables → managed identity → Azure CLI → Visual Studio Code → Interactive browser. It works both locally (CLI) and in production (managed identity).

Conditional access policies add context-aware rules to authentication:

User attempts sign-in
Entra ID evaluates conditions:
├── User/group membership
├── Location (IP range, country)
├── Device state (compliant, managed)
├── Application being accessed
└── Risk level (sign-in risk, user risk)
Apply controls:
├── Allow (with MFA)
├── Block
├── Require compliant device
└── Require approved app

Examples:

  • Require MFA for all users accessing Azure portal.
  • Block sign-ins from countries where you don’t operate.
  • Require a compliant device for accessing sensitive apps.
  • Force password change when sign-in risk is high.

Key Vault is Azure’s secrets management service (like AWS Secrets Manager + KMS):

Terminal window
# Create a Key Vault
az keyvault create --name myapp-vault --resource-group myapp-rg --location eastus
# Store a secret
az keyvault secret set --vault-name myapp-vault --name db-password --value 'S3cure!Pass'
# Retrieve a secret
az keyvault secret show --vault-name myapp-vault --name db-password --query value -o tsv

Key Vault stores three types of objects:

TypeWhat It Stores
SecretsConnection strings, passwords, API keys
KeysEncryption keys (RSA, EC) — can be HSM-backed
CertificatesTLS/SSL certificates with auto-renewal

Access is controlled via RBAC or vault access policies. Use managed identities to access Key Vault from your applications.

PracticeWhy
Use groups for role assignmentsEasier to manage than per-user assignments
Use managed identities for Azure resourcesNo credentials to manage or rotate
Use service principals with OIDC for CI/CDNo secrets in pipelines
Apply least privilegeUse narrow roles (e.g. “Storage Blob Data Reader” not “Contributor”)
Assign roles at the narrowest scopeResource group or resource level, not subscription
Enable MFA for all usersProtects against credential theft
Use conditional accessContext-aware security (location, device, risk)
Store secrets in Key VaultNever in code, config files, or environment variables
Review access with access reviewsPeriodic review of who has what access
  • Entra ID (Azure AD) is the identity provider — users, groups, SSO, MFA. Azure RBAC controls what identities can do on resources.
  • RBAC = WHO (principal) + WHAT (role) + WHERE (scope). Roles inherit down the scope hierarchy.
  • Managed identities are the preferred way for Azure resources to authenticate — no secrets needed.
  • Service principals are for external applications and CI/CD. Use federated credentials (OIDC) to avoid storing secrets.
  • Key Vault stores secrets, encryption keys, and certificates. Access it via managed identity.
  • Conditional access adds context-aware rules to sign-in (MFA, device compliance, location).