This guide demonstrates how to access Azure Key Vault secrets from a Python app running in AKS, using a System Assigned Managed Identity (SAMI) assigned to the AKS cluster.
- Uses SAMI assigned to AKS
- Secure access to Azure Key Vault using
DefaultAzureCredential - No secrets in environment variables
- Simple setup with no annotations or federated identity
- Azure CLI
- Docker
- Kubernetes CLI (
kubectl) - Azure subscription with sufficient privileges
cat <<EOF > env.sh
export LOCATION="southeastasia"
export RESOURCE_GROUP="aks-sami-demo-rg"
export AKS_NAME="akssami$(openssl rand -hex 3 | tr -dc 'a-z0-9' | cut -c1-10)"
export KEYVAULT_NAME="kv$(openssl rand -hex 3 | tr -dc 'a-z0-9' | cut -c1-20)"
export SECRET_NAME="DemoSecret"
export SECRET_VALUE="SuperSecret123"
export APP_NAME="kv-reader"
export IMAGE_NAME="kv-reader"
export ACR_NAME="acr$(openssl rand -hex 3 | tr -dc 'a-z0-9' | cut -c1-20)"
EOF
source env.shaz group create --name $RESOURCE_GROUP --location $LOCATIONaz aks create \
--resource-group $RESOURCE_GROUP \
--name $AKS_NAME \
--enable-managed-identity \
--node-count 1 \
--generate-ssh-keys
az aks get-credentials --name $AKS_NAME --resource-group $RESOURCE_GROUPaz keyvault create \
--name $KEYVAULT_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--enable-rbac-authorization true
az keyvault secret set \
--vault-name $KEYVAULT_NAME \
--name $SECRET_NAME \
--value "$SECRET_VALUE"AKS_MI_PRINCIPAL_ID=$(az aks show --name $AKS_NAME --resource-group $RESOURCE_GROUP --query identity.principalId -o tsv)
az role assignment create \
--assignee-object-id $AKS_MI_PRINCIPAL_ID \
--role "Key Vault Secrets User" \
--scope $(az keyvault show --name $KEYVAULT_NAME --query id -o tsv)from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
import os
import time
vault_name = os.getenv("KEY_VAULT_NAME")
secret_name = os.getenv("SECRET_NAME")
vault_url = f"https://{vault_name}.vault.azure.net"
credential = DefaultAzureCredential()
client = SecretClient(vault_url=vault_url, credential=credential)
retrieved = client.get_secret(secret_name)
print(f"Secret value: {retrieved.value}")
# Wait indefinitely
print("App is running. Press Ctrl+C to exit.")
while True:
time.sleep(60)FROM python:3.10-slim
WORKDIR /app
COPY app.py .
RUN pip install azure-identity azure-keyvault-secrets
CMD ["python", "app.py"]az acr create --resource-group $RESOURCE_GROUP --name $ACR_NAME --sku Basic
az aks update -n $AKS_NAME -g $RESOURCE_GROUP --attach-acr $ACR_NAME
az acr login --name $ACR_NAME
docker build -t $ACR_NAME.azurecr.io/$IMAGE_NAME:v1 .
docker push $ACR_NAME.azurecr.io/$IMAGE_NAME:v1apiVersion: apps/v1
kind: Deployment
metadata:
name: kv-reader
spec:
replicas: 1
selector:
matchLabels:
app: kv-reader
template:
metadata:
labels:
app: kv-reader
spec:
containers:
- name: kv-reader
image: <ACR_NAME>.azurecr.io/kv-reader:v1
env:
- name: KEY_VAULT_NAME
value: "<KEYVAULT_NAME>"
- name: SECRET_NAME
value: "<SECRET_NAME>"sed "s|<ACR_NAME>|$ACR_NAME|g; s|<KEYVAULT_NAME>|$KEYVAULT_NAME|g; s|<SECRET_NAME>|$SECRET_NAME|g" deployment.yaml > deployment.generated.yaml
kubectl apply -f deployment.generated.yamlkubectl get pods
kubectl logs $(kubectl get pods -l app=kv-reader -o jsonpath="{.items[0].metadata.name}")Expected output:
Secret value: SuperSecret123
az group delete --name $RESOURCE_GROUP --yes --no-waitYou have now successfully set up AKS to access Azure Key Vault using a System Assigned Managed Identity and Python SDK.