Azure Managed Identity Explained: Secure Access Simplified

Azure Managed Identity explained: Streamline secure access to Azure resources from your applications without managing secrets. Boost security and reduce operati

Murat Doğan

11 min read
0

/

Azure Managed Identity Explained: Secure Access Simplified

Most teams hardcode connection strings or store secrets in configuration files for application-to-resource communication. But this approach quickly leads to secret sprawl, complex rotation schedules, and elevated security risks at scale, creating significant operational overhead that impacts both security posture and developer productivity.


TL;DR

  • Azure Managed Identity eliminates the need for managing application secrets by providing an Azure AD identity.
  • It simplifies secure access for Azure resources to other Azure services, enhancing your overall security posture.
  • Two types exist: System-Assigned, tied to a resource's lifecycle, and User-Assigned, managed independently for broader use.
  • Implementing Managed Identity involves granting specific Azure RBAC permissions to interact with target services.
  • Leveraging Managed Identity reduces operational burden and mitigates risks associated with credential exposure.


The Problem with Traditional Secret Management


In production environments, applications frequently need to interact with various Azure services like Azure Key Vault, Storage Accounts, or Cosmos DB. Traditionally, this involved managing secrets such as connection strings, API keys, or certificates. Storing these credentials in application configurations, environment variables, or even within CI/CD pipelines introduces a critical attack vector and an undeniable operational burden. Teams commonly report 30–50% of security incidents stemming from credential exposure or mismanagement.


The effort involved in rotating secrets, distributing them securely, and ensuring their revocation upon compromise drains engineering cycles better spent on core business logic. Furthermore, auditing which application uses which secret to access what resource becomes an increasingly complex and error-prone task as the system grows. This traditional model is brittle, unscalable, and fundamentally increases the attack surface for any distributed system operating within Azure.


How Azure Managed Identity Works


What is Azure Managed Identity?


Azure Managed Identity provides an identity for your applications to use when connecting to resources that support Azure Active Directory (Azure AD) authentication, all without requiring you to manage any credentials. It acts as an abstraction layer over service principals, automatically handling their creation, certificate rotation, and lifecycle management within Azure AD. This mechanism allows Azure services to authenticate to other Azure services securely and directly, leveraging Azure AD's robust authentication and authorization framework.


There are two distinct types of Managed Identities, each suited for different architectural patterns and operational needs:


Managed Identity Types


System-Assigned Managed Identity


A System-Assigned Managed Identity is created directly on an Azure resource, such as a Virtual Machine, App Service, or Azure Kubernetes Service (AKS) cluster. Its lifecycle is intrinsically tied to that of the parent resource; when the resource is deleted, the identity is automatically deleted as well. This simplicity makes it ideal for single-resource scenarios where the identity's scope and purpose are confined to that specific instance. It cannot be shared with other resources.


User-Assigned Managed Identity


A User-Assigned Managed Identity is a standalone Azure resource, created independently of any compute resource. This identity can then be assigned to multiple Azure services, allowing for a centralized management approach. Because it has its own lifecycle, it can persist even if the resources it's assigned to are deleted. This makes User-Assigned Managed Identities particularly valuable in complex deployments, such as AKS, where multiple pods or services might require the same set of permissions, or when you need to share an identity across different Azure services for consistent access patterns.


When an Azure resource is configured with a Managed Identity, the Azure instance metadata service (IMDS) within that resource’s VM provides a REST endpoint. Your application can then query this endpoint to obtain an access token. This token, issued by Azure AD, represents the Managed Identity and can be used to authenticate against any Azure service that supports Azure AD authentication. The entire process happens behind the scenes, abstracting away token acquisition and refreshing complexities from your application code.


Step-by-Step Implementation: Secure Access for AKS Pods with Managed Identity


Let's walk through a concrete scenario: an application deployed on Azure Kubernetes Service (AKS) needs to securely retrieve secrets from Azure Key Vault without embedding any credentials in its deployment. We will use a User-Assigned Managed Identity and Azure AD Workload Identity (formerly Azure AD Pod Identity) to achieve this. This demonstrates a robust approach to secure Azure AD authentication for containerized applications.


Prerequisites:

  • An existing AKS cluster running Kubernetes 1.25 or newer with Azure AD Workload Identity enabled.
  • Azure CLI installed and configured.


1. Create a User-Assigned Managed Identity (UAMI)

First, we create a UAMI that our AKS pods will use. This identity will hold the necessary permissions to access Key Vault.

$ AZURERESOURCEGROUP="my-aks-rg"

$ AZURE_LOCATION="eastus"

$ UAMI_NAME="my-aks-kv-uami-2026"


Create the User-Assigned Managed Identity

$ az identity create \

--resource-group "$AZURERESOURCEGROUP" \

--name "$UAMI_NAME" \

--location "$AZURE_LOCATION"


Capture the Client ID and Resource ID for later use

$ UAMICLIENTID=$(az identity show \

--resource-group "$AZURERESOURCEGROUP" \

--name "$UAMI_NAME" \

--query "clientId" -o tsv)

$ UAMIRESOURCEID=$(az identity show \

--resource-group "$AZURERESOURCEGROUP" \

--name "$UAMI_NAME" \

--query "id" -o tsv)


echo "UAMI Client ID: $UAMICLIENTID"

echo "UAMI Resource ID: $UAMIRESOURCEID"

Expected Output: A JSON object detailing the created identity, followed by the echoed UAMI Client ID and UAMI Resource ID.

{

"clientId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",

"id": "/subscriptions/.../resourceGroups/my-aks-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-aks-kv-uami-2026",

"location": "eastus",

"name": "my-aks-kv-uami-2026",

"principalId": "b1c2d3e4-f5a6-7890-1234-567890fedcba",

"resourceGroup": "my-aks-rg",

"tags": {},

"tenantId": "...",

"type": "Microsoft.ManagedIdentity/userAssignedIdentities"

}

UAMI Client ID: a1b2c3d4-e5f6-7890-1234-567890abcdef

UAMI Resource ID: /subscriptions/.../resourceGroups/my-aks-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-aks-kv-uami-2026


2. Create an Azure Key Vault and a Secret

We need a Key Vault to store our secret and then add a sample secret.

$ KEYVAULT_NAME="mykeyvault2026md" # Must be globally unique

$ SECRET_NAME="my-app-secret"

$ SECRET_VALUE="SuperSecureValue!2026"


Create Azure Key Vault

$ az keyvault create \

--name "$KEYVAULT_NAME" \

--resource-group "$AZURERESOURCEGROUP" \

--location "$AZURE_LOCATION" \

--sku standard


Add a secret to the Key Vault

$ az keyvault secret set \

--vault-name "$KEYVAULT_NAME" \

--name "$SECRET_NAME" \

--value "$SECRET_VALUE"

Expected Output: JSON detailing the Key Vault creation and then the secret creation.


3. Grant Key Vault Permissions to the UAMI

The UAMI needs explicit permissions to get secrets from the Key Vault. We'll assign the "Key Vault Secret User" role, which is part of the robust identity lifecycle management for Azure resources.

Get your subscription ID

$ SUBSCRIPTION_ID=$(az account show --query id -o tsv)


Grant the UAMI permissions to get secrets from Key Vault

Role: Key Vault Secret User (built-in role)

$ az role assignment create \

--role "Key Vault Secret User" \

--assignee "$UAMICLIENTID" \

--scope "/subscriptions/$SUBSCRIPTIONID/resourceGroups/$AZURERESOURCEGROUP/providers/Microsoft.KeyVault/vaults/$KEYVAULTNAME"

Expected Output: A JSON object confirming the role assignment.

{

"canDelegate": null,

"id": "/subscriptions/.../resourceGroups/my-aks-rg/providers/Microsoft.KeyVault/vaults/mykeyvault2026md/providers/Microsoft.Authorization/roleAssignments/...",

"name": "...",

"principalId": "b1c2d3e4-f5a6-7890-1234-567890fedcba",

"principalType": "ServicePrincipal",

"resourceGroup": "my-aks-rg",

"roleDefinitionId": "/subscriptions/.../providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6",

"scope": "/subscriptions/.../resourceGroups/my-aks-rg/providers/Microsoft.KeyVault/vaults/mykeyvault2026md",

"type": "Microsoft.Authorization/roleAssignments"

}


Common mistake: Forgetting to assign the necessary RBAC role. Without this, the application will receive 403 Forbidden errors when attempting to access Key Vault, even if Workload Identity is configured correctly. Always verify RBAC assignments at the target resource level.


4. Configure Azure AD Workload Identity for your AKS Pod

Azure AD Workload Identity allows Kubernetes pods to impersonate an Azure AD identity. We configure a Kubernetes Service Account to trust our UAMI. This establishes the trust relationship crucial for secure Azure access.

$ AKSRESOURCEGROUP="my-aks-rg" # Your AKS cluster's resource group

$ AKS_NAME="myakscluster" # Your AKS cluster name

$ AKSOIDCISSUER=$(az aks show \

--resource-group "$AKSRESOURCEGROUP" \

--name "$AKS_NAME" \

--query "oidcIssuerProfile.issuerUrl" -o tsv)


echo "AKS OIDC Issuer: $AKSOIDCISSUER"


Create the federated identity credential between the UAMI and the Service Account

Subject format: system:serviceaccount:<namespace>:<service-account-name>

$ az identity federated-credential create \

--name "my-aks-fed-cred-2026" \

--identity-name "$UAMI_NAME" \

--resource-group "$AZURERESOURCEGROUP" \

--issuer "$AKSOIDCISSUER" \

--subject "system:serviceaccount:default:my-app-service-account"

Expected Output: A JSON object describing the federated credential.

{

"audiences": [

"api://AzureADTokenExchange"

],

"id": "/subscriptions/.../resourceGroups/my-aks-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-aks-kv-uami-2026/federatedIdentityCredentials/my-aks-fed-cred-2026",

"issuer": "https://eastus.oic.azure.com/...",

"name": "my-aks-fed-cred-2026",

"resourceGroup": "my-aks-rg",

"subject": "system:serviceaccount:default:my-app-service-account",

"tenantId": "...",

"type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials"

}


5. Deploy a Sample Application to AKS

Now, deploy an application that uses the Service Account configured with Workload Identity to fetch the secret. We'll generate the YAML dynamically to ensure it uses the correct values.

Create a temporary file with replaced values for Kubernetes deployment

cat <<EOF > deployment-final.yaml

apiVersion: v1

kind: ServiceAccount

metadata:

name: my-app-service-account

annotations:

# Associate this Service Account with the User-Assigned Managed Identity's Client ID

azure.workload.identity/client-id: "$UAMICLIENTID"

WRITTEN BY

Murat Doğan

Microsoft Azure MVP, 6 years in the Microsoft ecosystem. Computer Engineering graduate, Yıldız Technical University. Contributes to Azure, AKS and DevOps content.Read more

Responses (0)

    Hottest authors

    View all

    Ahmet Çelik

    Lead Writer · ex-AWS Solutions Architect, 8 yrs · AWS, Terraform, K8s

    Alp Karahan

    Contributor · MongoDB certified, NoSQL specialist · MongoDB, DynamoDB

    Ayşe Tunç

    Lead Writer · Engineering Manager, ex-Meta, Google · System Design, Interviews

    Berk Avcı

    Lead Writer · Principal Backend Eng., API design · REST, GraphQL, gRPC

    Burak Arslan

    Managing Editor · Content strategy, developer marketing

    Cansu Yılmaz

    Lead Writer · Database Architect, 9 yrs Postgres · PostgreSQL, Indexing, Perf

    Popular posts

    View all
    Sercan Öztürk
    ·

    # GitHub Actions Tutorial: Step-by-Step CI/CD Workflows

    # GitHub Actions Tutorial: Step-by-Step CI/CD Workflows
    Murat Doğan
    ·

    <h1 class="text-3xl font-bold mb-4">Azure DevOps Pipelines: Serverless Functions CI/CD</h1>

    <h1 class="text-3xl font-bold mb-4">Azure DevOps Pipelines: Serverless Functions CI/CD</h1>
    Ahmet Çelik
    ·

    S3 Intelligent-Tiering vs Glacier: A Cost Analysis

    S3 Intelligent-Tiering vs Glacier: A Cost Analysis
    Elif Demir
    ·

    Docker Tutorial for Beginners 2025: Production Basics

    Docker Tutorial for Beginners 2025: Production Basics
    Ahmet Çelik
    ·

    AWS VPC Peering vs Transit Gateway vs PrivateLink

    AWS VPC Peering vs Transit Gateway vs PrivateLink
    Elif Demir
    ·

    Docker Compose vs Kubernetes: Production Orchestration

    Docker Compose vs Kubernetes: Production Orchestration