Exercise 5: Workload Identity
Task 1: Enable Workload Identity
Use the Azure CLI to enable Workload Identity on your AKS cluster.
az aks update -g $RESOURCE_GROUP -n $AKS_NAME --enable-oidc-issuer --enable-workload-identity
az aks update -g $RESOURCE_GROUP -n $AKS_NAME --enable-oidc-issuer --enable-workload-identity
This operation may take 5-10 minutes to complete.
Task 1: Create Identity Resources
Create a managed identity for our application to use:
$IDENTITY_NAME = "workload-identity-demo" az identity create -g $RESOURCE_GROUP -n $IDENTITY_NAME
IDENTITY_NAME="workload-identity-demo" az identity create -g $RESOURCE_GROUP -n $IDENTITY_NAME
Get the details of the managed identity:
$IDENTITY_CLIENT_ID = (az identity show -g $RESOURCE_GROUP -n $IDENTITY_NAME --query clientId -o tsv) $IDENTITY_RESOURCE_ID = (az identity show -g $RESOURCE_GROUP -n $IDENTITY_NAME --query id -o tsv)
IDENTITY_CLIENT_ID=$(az identity show -g $RESOURCE_GROUP -n $IDENTITY_NAME --query clientId -o tsv) IDENTITY_RESOURCE_ID=$(az identity show -g $RESOURCE_GROUP -n $IDENTITY_NAME --query id -o tsv)
Create a namespace for our workload identity demo:
kubectl create namespace workload-identity-demo
kubectl create namespace workload-identity-demo
Create a service account and annotate it with the managed identity’s client ID:
$serviceAccountYaml = @" apiVersion: v1 kind: ServiceAccount metadata: annotations: azure.workload.identity/client-id: $IDENTITY_CLIENT_ID name: workload-identity-sa namespace: workload-identity-demo "@ $serviceAccountYaml | kubectl apply -f -
cat << EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: annotations: azure.workload.identity/client-id: $IDENTITY_CLIENT_ID name: workload-identity-sa namespace: workload-identity-demo EOF
Create a federated identity credential to establish trust between the managed identity and the service account:
$AKS_OIDC_ISSUER = (az aks show -g $RESOURCE_GROUP -n $AKS_NAME --query "oidcIssuerProfile.issuerUrl" -o tsv) az identity federated-credential create ` --name "kubernetes-federated-credential" ` --identity-name $IDENTITY_NAME ` --resource-group $RESOURCE_GROUP ` --issuer $AKS_OIDC_ISSUER ` --audience api://AzureADTokenExchange ` --subject system:serviceaccount:workload-identity-demo:workload-identity-sa
AKS_OIDC_ISSUER=$(az aks show -g $RESOURCE_GROUP -n $AKS_NAME --query "oidcIssuerProfile.issuerUrl" -o tsv) az identity federated-credential create \ --name "kubernetes-federated-credential" \ --identity-name $IDENTITY_NAME \ --resource-group $RESOURCE_GROUP \ --issuer $AKS_OIDC_ISSUER \ --audience api://AzureADTokenExchange \ --subject system:serviceaccount:workload-identity-demo:workload-identity-sa
Task 2: Create a Storage Account
Create an Azure Storage account to test the identity:
$STORAGE_ACCOUNT_NAME = "widemostorage$((New-Guid).ToString().Substring(0,8))" az storage account create ` --name $STORAGE_ACCOUNT_NAME ` --resource-group $RESOURCE_GROUP ` --location $LOCATION ` --sku Standard_LRS
STORAGE_ACCOUNT_NAME="widemostorage$(openssl rand -hex 4)" az storage account create \ --name $STORAGE_ACCOUNT_NAME \ --resource-group $RESOURCE_GROUP \ --location $LOCATION \ --sku Standard_LRS
Assign the reader role to the managed identity for the storage account:
$STORAGE_ACCOUNT_ID = (az storage account show --name $STORAGE_ACCOUNT_NAME --resource-group $RESOURCE_GROUP --query id -o tsv) az role assignment create ` --role "Reader" ` --assignee $IDENTITY_CLIENT_ID ` --scope $STORAGE_ACCOUNT_ID
STORAGE_ACCOUNT_ID=$(az storage account show --name $STORAGE_ACCOUNT_NAME --resource-group $RESOURCE_GROUP --query id -o tsv) az role assignment create \ --role "Reader" \ --assignee $IDENTITY_CLIENT_ID \ --scope $STORAGE_ACCOUNT_ID
Task 3: Validate Workload Identity
Deploy a pod that uses the workload identity to access the storage account, note the use of the
azure.workload.identity/use
label:$workloadIdentityPodYaml = @" apiVersion: v1 kind: Pod metadata: labels: azure.workload.identity/use: "true" name: workload-identity-test namespace: workload-identity-demo spec: serviceAccountName: workload-identity-sa containers: - image: k8sonazureworkshoppublic.azurecr.io/mcr.microsoft.com/azure-cli name: azure-cli command: - "/bin/bash" - "-c" - "az login --service-principal -u $IDENTITY_CLIENT_ID --tenant `$(printenv AZURE_TENANT_ID) --federated-token `$(cat `$AZURE_FEDERATED_TOKEN_FILE) && echo 'Login successful' && sleep infinity" nodeSelector: kubernetes.io/os: linux "@ $workloadIdentityPodYaml | kubectl apply -f -
cat << EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: labels: azure.workload.identity/use: "true" name: workload-identity-test namespace: workload-identity-demo spec: serviceAccountName: workload-identity-sa containers: - image: k8sonazureworkshoppublic.azurecr.io/mcr.microsoft.com/azure-cli name: azure-cli command: - "/bin/bash" - "-c" - "az login --service-principal -u $IDENTITY_CLIENT_ID --tenant \$(printenv AZURE_TENANT_ID) --federated-token \$(cat \$AZURE_FEDERATED_TOKEN_FILE) && echo 'Login successful' && sleep infinity" nodeSelector: kubernetes.io/os: linux EOF
Wait for the pod to be running:
kubectl wait --for=condition=Ready pod/workload-identity-test -n workload-identity-demo
kubectl wait --for=condition=Ready pod/workload-identity-test -n workload-identity-demo
Test the workload identity by accessing the storage account:
# First check that the pod is still running kubectl get pod workload-identity-test -n workload-identity-demo # Create a container in the storage account kubectl exec -it workload-identity-test -n workload-identity-demo -- bash -c "az storage account list"
# First check that the pod is still running kubectl get pod workload-identity-test -n workload-identity-demo # Create a container in the storage account kubectl exec -it workload-identity-test -n workload-identity-demo -- bash -c "az storage account list"
This should get the details of the storage account without requiring you to provide credentials, demonstrating that the workload identity is working correctly.
Task 4: Clean Up
Clean up the workload identity resources:
kubectl delete namespace workload-identity-demo
kubectl delete namespace workload-identity-demo
Clean up the managed identity and storage account:
az identity delete --name $IDENTITY_NAME --resource-group $RESOURCE_GROUP az storage account delete --name $STORAGE_ACCOUNT_NAME --resource-group $RESOURCE_GROUP --yes
az identity delete --name $IDENTITY_NAME --resource-group $RESOURCE_GROUP az storage account delete --name $STORAGE_ACCOUNT_NAME --resource-group $RESOURCE_GROUP --yes