Friday, 30 October 2026

What is Managed Identity, and why do we use it?

Managed Identity

A managed identity is an identity in Microsoft Entra ID that Azure creates and manages for an Azure resource (an App Service, Function App, VM, Container App, AKS workload, and so on). The resource uses it to authenticate to other Azure services without any credentials in your code or config. Azure handles the credential behind the scenes: it creates it, stores it, and rotates it automatically, and you never see or handle the secret.

The problem it solves

Normally, to call something like Key Vault, SQL, or Storage, your app needs a credential: a connection string, API key, or client secret. That creates a chain of problems:

  • The credential has to be stored somewhere (config, CI variables, a vault).
  • It can leak through source control, logs, or screenshots.
  • It expires and needs rotation, which often causes outages when someone forgets.
  • To read the secret from Key Vault, you need another credential (the "secret zero" problem).

Managed identity removes the credential from the picture entirely. The identity is the resource, and access is granted through RBAC.

How it works

  1. You enable a managed identity on the resource.
  2. Azure registers a service principal for it in Entra ID.
  3. You grant that identity a role on the target resource (e.g., Key Vault Secrets User, Storage Blob Data Reader).
  4. At runtime, your code asks a local token endpoint on the host (the Instance Metadata Service, or the App Service identity endpoint) for an access token for the target resource.
  5. Azure issues a short-lived token, and your code presents it to the target service, which checks the RBAC assignment.

The token request is only possible from code running on that resource, which is why no secret is needed. The Azure SDKs do all of this for you:

var credential = new DefaultAzureCredential();

var blobs = new BlobServiceClient(
    new Uri("https://mystorage.blob.core.windows.net"), credential);

DefaultAzureCredential uses the managed identity when running in Azure, and falls back to your az login or Visual Studio sign-in locally, so the same code works in both places.

Two types

System-assigned User-assigned
Lifecycle Tied to the resource; deleted with it Standalone resource with its own lifecycle
Sharing One resource only Can be attached to many resources
Best for Simple, single-resource scenarios Sharing one identity across apps, pre-provisioning access before deployment, or keeping access stable when you recreate resources

When using a user-assigned identity, tell the SDK which one to use, since a resource can have several:

var credential = new DefaultAzureCredential(
    new DefaultAzureCredentialOptions { ManagedIdentityClientId = "<client-id>" });

Setting it up

# System-assigned
az webapp identity assign --name my-app --resource-group my-rg

# User-assigned
az identity create --name my-identity --resource-group my-rg
az webapp identity assign --name my-app --resource-group my-rg \
  --identities <identity-resource-id>

# Grant access
az role assignment create \
  --assignee <principalId> \
  --role "Storage Blob Data Reader" \
  --scope <storage-account-resource-id>

Why use it

  • No secrets to manage: nothing to store, leak, or rotate by hand.
  • Better security posture: short-lived tokens, and access governed by RBAC with least privilege and a clear audit trail in Entra ID and Azure Monitor.
  • Less operational risk: no expired-credential outages.
  • Simpler code and pipelines: no secret plumbing between environments.
  • Free: there's no extra charge for managed identities.

Limitations to know about

  • It only works for Azure resources (and Azure Arc-enabled servers). Code running on-premises or on a laptop can't use one directly; use DefaultAzureCredential fallbacks, workload identity federation, or service principals there.
  • The target service must support Entra authentication. Most Azure services do (Key Vault, Storage, Service Bus, SQL, Cosmos DB, Event Hubs), but some third-party services or older features still need keys.
  • Role assignments take a few minutes to propagate, and tokens are cached, so changes aren't always instant.
  • It authenticates the resource, not an end user. If you need per-user access, you need user sign-in (OAuth/OIDC) instead.
  • For Azure SQL, you also have to create a database user for the identity (CREATE USER [my-app] FROM EXTERNAL PROVIDER) and grant it database roles.

Related: workload identity

For apps outside Azure (GitHub Actions, Kubernetes on other clouds), workload identity federation gives a similar credential-free experience by trusting tokens from an external identity provider. It's what the azure/login@v2 OIDC setup in a GitHub Actions workflow uses.


No comments:

Post a Comment

Note: only a member of this blog may post a comment.