Estimated Duration: 60 minutes
NOTE: You need to fulfill these requirements and AKS Basic Cluster to complete this exercise.
In this lab we will complete the following tasks:
- Enable the cluster for Entra Workload Identity
- Create the Entra cluster identities
- Configure an Entra enabled target for testing
- Write the code to test your Workload Identity setup
- Deploy the application to your AKS cluster and demonstrate its operation
For more information see: Workload Identity Overview
Workloads deployed on an Azure Kubernetes Services (AKS) cluster require Microsoft Entra application credentials or managed identities to access Microsoft Entra protected resources. Microsoft Entra Workload ID integrates with the capabilities native to Kubernetes to federate with external identity providers.
In this security model, the AKS cluster acts as the token issuer. Microsoft Entra ID uses OpenID Connect to discover public signing keys and verify the authenticity of the service account token before exchanging it for a Microsoft Entra token. Your workload can exchange a service account token projected to its volume for a Microsoft Entra token using the Azure Identity client library.
In a terminal, export variables required for this lab (if not already exported):
INITIALS=abc
CLUSTER_NAME=aks-$INITIALS
RG=aks-$INITIALS-rg
If not already connected, connect to the cluster from your local client machine.
az aks get-credentials --name $CLUSTER_NAME -g $RG
Enable the Azure Workload Identity managed add-on and OIDC issuer on the target cluster.
az aks update -g $RG -n $CLUSTER_NAME \
--enable-oidc-issuer \
--enable-workload-identity
Now that the cluster is enabled with the OIDC Issuer and Azure Workload Identity, we can create our Managed Identity and Service Account and then federate those identities.
Retrieve the OIDC Issuer URL
export AKS_OIDC_ISSUER="$(az aks show -n $CLUSTER_NAME -g $RG --query "oidcIssuerProfile.issuerUrl" -o tsv)"
Create the managed identity
MANAGED_IDENTITY_NAME=testmi
az identity create --name $MANAGED_IDENTITY_NAME --resource-group $RG
Get identity client ID
export USER_ASSIGNED_CLIENT_ID=$(az identity show --resource-group $RG --name $MANAGED_IDENTITY_NAME --query 'clientId' -o tsv)
Create the kubernetes namespace
NAMESPACE=workload-identity-test
kubectl create ns $NAMESPACE
Create a service account with Workload Identity enabled and specifying the client id:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
azure.workload.identity/client-id: ${USER_ASSIGNED_CLIENT_ID}
labels:
azure.workload.identity/use: "true"
name: ${MANAGED_IDENTITY_NAME}-sa
namespace: ${NAMESPACE}
EOF
Create the federated identity credential between the managed identity, the service account issuer, and the subject
az identity federated-credential create \
--name $MANAGED_IDENTITY_NAME-federated-id \
--identity-name $MANAGED_IDENTITY_NAME \
--resource-group $RG \
--issuer ${AKS_OIDC_ISSUER} \
--subject system:serviceaccount:$NAMESPACE:$MANAGED_IDENTITY_NAME-sa
For the purposes of this test, one of the best and easiest sample targets is Azure Key Vault. Create an Azure Key Vault and a Secret that we can try to access from our cluster. The key vault name must be unique:
KEY_VAULT_NAME=$INITIALS-kv
Create a key vault for testing:
az keyvault create --name $KEY_VAULT_NAME --resource-group $RG --enable-rbac-authorization
Assign yourself the RBAC Key Vault Secrets Officer role so that you can create a secret in the new key vault:
export KEYVAULT_RESOURCE_ID=$(az keyvault show --resource-group "$RG" \
--name "$KEY_VAULT_NAME" \
--query id \
--output tsv)
USER_EMAIL=$(az ad signed-in-user show --query userPrincipalName --output tsv)
az role assignment create --assignee "$USER_EMAIL" \
--role "Key Vault Secrets Officer" \
--scope $KEYVAULT_RESOURCE_ID
Create a Key Vault secret:
az keyvault secret set --vault-name $KEY_VAULT_NAME --name "Secret" --value "Hello from key vault"
Assign the Key Vault Secrets User role to the user-assigned managed identity that you created previously. This step gives the managed identity permission to read secrets from the key vault:
export IDENTITY_PRINCIPAL_ID=$(az identity show \
--name "$MANAGED_IDENTITY_NAME" \
--resource-group "${RG}" \
--query principalId --output tsv)
az role assignment create \
--assignee-object-id "${IDENTITY_PRINCIPAL_ID}" \
--role "Key Vault Secrets User" \
--scope "$KEYVAULT_RESOURCE_ID" \
--assignee-principal-type ServicePrincipal
Now we have our cluster setup properly and have created a test target for an Entra authenticated call. Let's deploy an app to call the key vault. In this case we'll use a dotnet application, but you can use any language you prefer that is supported by the Microsoft Authentication Libraries.
cd src/keyvault-console-app
We need to get this app into a container, so we need to build the image. You can do this locally, but to be safe from any cpu architecture mismatches, lets use the Azure Container Registry to build. You should have an existing registry from the AKS Basic Cluster.
ACR_NAME=$(az acr list --resource-group $RG --query '[0].name' -o tsv)
IMAGE_NAME=wi-kv-test
Build the image. This uploads the source code and builds the image remotely using ACR:
az acr build -t $IMAGE_NAME -r $ACR_NAME .
Get the ACR FQDN for later use:
ACR_FQDN=$(az acr show -n $ACR_NAME -o tsv --query loginServer)
Now we need to do is create a pod that uses the service account with workload identity enabled:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: wi-kv-test
namespace: ${NAMESPACE}
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: ${MANAGED_IDENTITY_NAME}-sa
containers:
- image: ${ACR_FQDN}/${IMAGE_NAME}
name: wi-kv-test
env:
- name: KEY_VAULT_NAME
value: ${KEY_VAULT_NAME}
- name: SECRET_NAME
value: Secret
nodeSelector:
kubernetes.io/os: linux
EOF
Check the pod status and confirm pod is Running:
kubectl get pods -n $NAMESPACE
Now check the logs
kubectl logs -f wi-kv-test -n $NAMESPACE
Sample Output:
Retrieving your secret from abc-kv.
Your secret is 'Hello from key vault'.
You now have a cluster enabled with the OIDC Issuer and the Azure Workload Identity managed add-on with a deployed application using a Kubernetes Service Account that has been federated to an Azure Managed Identity to access a secret in an Azure Key Vault!
Before moving to the next lab, do not forget to delete namespace:
kubectl delete ns $NAMESPACE
Only uf you are done with all labs, then clean up by deleting the resource group, otherwise delete individual resources below.
az group delete --name $RG --yes --no-wait
Delete key vault (only delete if not planning on doing other labs):
az keyvault delete -n $KEY_VAULT_NAME -g $RG
Delete managed identity:
az identity delete -n $MANAGED_IDENTITY_NAME -g $RG
This command is included for reference, however we recommend keeping workload identity for subsequent labs (unless explicitly recommended to be removed in a subsequent lab).
az aks update --resource-group "${RG}" --name "${CLUSTER_NAME}" --disable-workload-identity