Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Set up identity bindings on your Azure Kubernetes Service (AKS) clusters to map a user-assigned managed identity (UAMI) across multiple clusters while using a single federated identity credential (FIC). This setup helps you scale Microsoft Entra authentication for workloads without hitting FIC limits.
Prerequisites
- Review Identity bindings concepts to understand how identity bindings work.
- Azure CLI version 2.73.0 or later. To check your version, use the
az versioncommand. To install or update the Azure CLI, see Install the Azure CLI. - The Azure CLI
aks-previewextension version18.0.0b26or later installed. - The
IdentityBindingPreviewfeature flag enabled for your subscription. - You need the following Azure permissions on the identity and cluster scope:
Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/writeandMicrosoft.ContainerService/managedClusters/write. - You need Kubernetes cluster admin (or equivalent) permissions to create
ClusterRoleandClusterRoleBindingresources.
Install or update the aks-preview extension
Install or update the Azure CLI
aks-previewextension to the latest version using theaz extension addoraz extension updatecommand:# Install the aks-preview extension az extension add --name aks-preview # Update to the latest version if already installed az extension update --name aks-preview
Enable the IdentityBindingPreview feature flag
Register the
IdentityBindingPreviewfeature flag on your Azure subscription using theaz feature registercommand.az feature register --namespace Microsoft.ContainerService --name IdentityBindingPreviewFeature registration can take up to 15 minutes to complete.
Wait for the feature to finish registering using the
az feature showcommand.az feature show --namespace Microsoft.ContainerService --name IdentityBindingPreviewOnce the feature shows as
Registered, refresh the provider registration using theaz provider registercommand.az provider register --namespace Microsoft.ContainerService
Create test resources
Create an Azure resource group using the
az group createcommand.export RESOURCE_GROUP="ib-test" export LOCATION="chinanorth3" az group create --name $RESOURCE_GROUP --location $LOCATIONCreate an AKS cluster with workload identity and OIDC issuer enabled using the
az aks createcommand with the--enable-workload-identityand--enable-oidc-issuerflags.export CLUSTER_NAME="ib-test-cluster" az aks create --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --location $LOCATION --no-ssh-key --enable-workload-identity --enable-oidc-issuerCreate a user-assigned managed identity (UAMI) using the
az identity createcommand.export MI_NAME="ib-test-mi" az identity create --resource-group $RESOURCE_GROUP --name $MI_NAME
Verify the workload identity webhook version
Identity binding requires the preview version of the workload identity webhook. Verify the installed webhook version using the following
kubectl get podscommand:kubectl -n kube-system get pods -l azure-workload-identity.io/system=true -o yaml | grep v1.6.0The output should show
v1.6.0-alpha.1in the image tag, which confirms the correct version is installed.
Get the UAMI IDs
Get the resource, principal, client, and tenant IDs of the UAMI and set them as environment variables using the following
az identity showcommands:export MI_RESOURCE_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $MI_NAME --query id --output tsv) export MI_PRINCIPAL_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $MI_NAME --query principalId --output tsv) export MI_CLIENT_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $MI_NAME --query clientId --output tsv) export MI_TENANT_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $MI_NAME --query tenantId --output tsv)
Create an identity binding
Map the UAMI to the AKS cluster with an identity binding using the
az aks identity-binding createcommand.az aks identity-binding create --resource-group $RESOURCE_GROUP --cluster-name $CLUSTER_NAME --name "${MI_NAME}-ib" --managed-identity-resource-id $MI_RESOURCE_IDNote
When you create an identity binding, AKS automatically creates a federated identity credential (FIC) named
aks-identity-bindingunder the UAMI. This credential is managed by AKS. Don't modify or delete it while identity bindings are in use. The FIC created for identity bindings is shared across all identity bindings referencing the same UAMI.
Get the OIDC issuer URL for the UAMI
Get the OIDC issuer URL associated with the UAMI by inspecting the identity binding using the
az aks identity-binding showcommand.az aks identity-binding show --resource-group $RESOURCE_GROUP --cluster-name $CLUSTER_NAME --name "${MI_NAME}-ib"Condensed example output:
{ "oidcIssuer": { "oidcIssuerUrl": "https://ib.oic.prod-aks.azure.com/<MI-tenant-id>/<MI-client-id>" } }
Connect to the AKS cluster
Get the AKS cluster credentials using the
az aks get-credentialscommand and save them to a separate kubeconfig file:az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME -a -f "${CLUSTER_NAME}.kubeconfig"Set the
KUBECONFIGenvironment variable to point to the new kubeconfig file:export KUBECONFIG="$(pwd)/${CLUSTER_NAME}.kubeconfig"
Authorize namespaces and service accounts
Configure role-based access control (RBAC) to grant specific subjects the permission to use the managed identity via identity binding by applying the following manifest using with the following
kubectl applycommand.Note
The following example explicitly refers to the
demoservice account in thedemonamespace. While explicitly referring to a specific service account is one option, it's also possible to refer to a collection of service accounts undersubjects. For more information, see Referring to subjects in the Kubernetes documentation.kubectl apply -f - <<EOF apiVersion: v1 kind: Namespace metadata: name: demo --- apiVersion: v1 kind: ServiceAccount metadata: name: demo namespace: demo --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: use-mi-${MI_CLIENT_ID} rules: - verbs: ["use-managed-identity"] apiGroups: ["cid.wi.aks.azure.com"] resources: ["${MI_CLIENT_ID}"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: use-mi-${MI_CLIENT_ID} roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: use-mi-${MI_CLIENT_ID} subjects: - kind: ServiceAccount name: demo namespace: demo EOF
Create a key vault with purge protection and Azure RBAC authorization
Create a key vault with purge protection and Azure RBAC authorization enabled using the
az keyvault createcommand with the--enable-purge-protectionand--enable-rbac-authorizationflags. You can also use an existing key vault if it's configured for both purge protection and Azure RBAC authorization.export KEY_VAULT_NAME="ib-test" az keyvault create \ --name $KEY_VAULT_NAME \ --resource-group $RESOURCE_GROUP \ --location $LOCATION \ --enable-purge-protection \ --enable-rbac-authorization
Get the key vault resource ID and URL
Get the resource ID of the key vault using the
az keyvault showcommand and set it as an environment variable:export KEY_VAULT_RESOURCE_ID=$(az keyvault show --resource-group $RESOURCE_GROUP \ --name $KEY_VAULT_NAME \ --query id \ --output tsv)Get the key vault URL using the
az keyvault showcommand and set it as an environment variable:export KEYVAULT_URL="$(az keyvault show \ --resource-group $RESOURCE_GROUP \ --name $KEY_VAULT_NAME \ --query properties.vaultUri \ --output tsv)"
Configure key vault access and create secret
The following steps show how to access secrets, keys, or certificates in Azure Key Vault from the pod. The examples in this section configure access to secrets in the key vault for the workload identity, but you can perform similar steps to configure access to keys or certificates.
The following example shows how to use the Azure RBAC permission model to grant the pod access to the key vault. For more information about the Azure RBAC permission model for Azure Key Vault, see Grant permission to applications to access Azure Key Vault using Azure RBAC.
Get the object ID of the signed-in user using the
az ad signed-in-user showcommand and set it as an environment variable:export CALLER_OBJECT_ID=$(az ad signed-in-user show --query id --output tsv)Assign yourself the Azure RBAC Key Vault Secrets Officer role on the key vault using the
az role assignment createcommand.az role assignment create --assignee $CALLER_OBJECT_ID \ --role "Key Vault Secrets Officer" \ --scope $KEY_VAULT_RESOURCE_IDCreate a secret in the key vault using the
az keyvault secret setcommand.export KEY_VAULT_SECRET_NAME="my-secret" az keyvault secret set \ --vault-name $KEY_VAULT_NAME \ --name $KEY_VAULT_SECRET_NAME \ --value "Hello\!"Assign the Key Vault Secrets User role to the UAMI using the
az role assignment createcommand.az role assignment create \ --assignee-object-id $MI_PRINCIPAL_ID \ --role "Key Vault Secrets User" \ --scope $KEY_VAULT_RESOURCE_ID \ --assignee-principal-type ServicePrincipal
Annotate service account
Annotate the service account with the managed identity tenant ID using the
kubectl annotatecommand.kubectl annotate sa demo -n demo azure.workload.identity/tenant-id=$MI_TENANT_IDAnnotate the service account with the managed identity client ID using the
kubectl annotatecommand.kubectl annotate sa demo -n demo azure.workload.identity/client-id=$MI_CLIENT_ID
Deploy sample application
Deploy the sample pod that uses identity binding to obtain an access token for the managed identity to access Azure Key Vault using the following
kubectl applycommand:kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: demo namespace: demo labels: azure.workload.identity/use: "true" annotations: azure.workload.identity/use-identity-binding: "true" spec: serviceAccount: demo containers: - name: azure-sdk # source code: https://github.com/Azure/azure-workload-identity/blob/feature/custom-token-endpoint/examples/identitybinding-msal-go/main.go image: ghcr.io/bahe-msft/azure-workload-identity/identitybinding-msal-go:latest-linux-amd64 env: - name: KEYVAULT_URL value: ${KEYVAULT_URL} - name: SECRET_NAME value: ${KEYVAULT_SECRET_NAME} restartPolicy: Never EOF
Verify access to key vault from sample application
Describe the pod and confirm environment variables and projected token volume mounts are present using the
kubectl describe podcommand.kubectl describe pod demo -n demoExpected output should contain values for
AZURE_CLIENT_ID,AZURE_TENANT_ID,AZURE_FEDERATED_TOKEN_FILE,AZURE_AUTHORITY_HOST,AZURE_KUBERNETES_TOKEN_PROXY.AZURE_KUBERNETES_SNI_NAME, andAZURE_KUBERNETES_CA_FILE.Verify the pod can get a token and access the resource using the
kubectl logscommand.kubectl logs demo -n demoIf successful, the output should be similar to the following example:
I1107 20:03:42.865180 1 main.go:77] "successfully got secret" secret="Hello!"
Scale identity bindings across multiple clusters
Identity bindings allow mapping multiple AKS clusters to the same UAMI while still using a single FIC. To scale identity bindings across multiple clusters, you can repeat the steps from Create an identity binding through verify access to key vault from sample application for each extra cluster you want to map to the same UAMI (creating a new identity binding per cluster).
Clean up resources
If you no longer need the resources you created in this article, you can clean them up to avoid incurring future costs.
Delete the pod using the
kubectl delete podcommand.kubectl delete pod demo -n demoDelete the namespace using the
kubectl delete nscommand.kubectl delete ns demoDelete the resource group and all related resources using the
az group deletecommand.az group delete --name $RESOURCE_GROUP --yes --no-wait