- AKS cluster should exist
- Enable OIDC issuer and workload identity (WI deploys pod in kube-system namespace)
- Enable secret store provider (Creates pod in kube-system namespace)
- Create UAMI for accessing Key Vault
- Create namespace in Kubernetes
- Create federation with Kubernetes namespace and service account (Refer to service YAML file)
- Create Key Vault and assign role to created UAMI
- Create dummy secret
- Deploy service account YAML
- Deploy secret provider YAML
- Deploy pods
- Execute in pod and validate the mounted credentials or environment variable secrets
- Volume mount is mandatory in pod for Kubernetes secrets to be created
The approach would be to have Key Vault for each application deployed in Kubernetes and store their respective secrets in Key Vault, for example, MySQL DB connection string required for PHP app. This approach is being used only for PHP based as there is no native Azure SDK available as of today. For other languages for e.g python, nodejs, we can use native workload identity to access Azure services. To test follow the below steps in order
resourceGroup="aks-cluster"
clusterName="san360-vnet"
location="northeurope"
export SUBSCRIPTION="$(az account show --query id --output tsv)"
az account set --subscription "${SUBSCRIPTION}"
az aks update --resource-group $resourceGroup --name $clusterName --enable-oidc-issuer --enable-workload-identity
az aks enable-addons --addons azure-keyvault-secrets-provider --name $clusterName --resource-group $resourceGroup
export AKS_OIDC_ISSUER="$(az aks show -n $clusterName -g $resourceGroup --query "oidcIssuerProfile.issuerUrl" -o tsv)"
az identity create --name keyvaultaccessapp1 --resource-group $resourceGroup --location $location --subscription "${SUBSCRIPTION}"
az identity create --name keyvaultaccessapp2 --resource-group $resourceGroup --location $location --subscription "${SUBSCRIPTION}"
az identity show --resource-group $resourceGroup --name keyvaultaccessapp1 --query 'clientId' -o tsv
az identity show --resource-group $resourceGroup --name keyvaultaccessapp2 --query 'clientId' -o tsv
kubectl create ns accessapp1
kubectl create ns accessapp2
az identity federated-credential create --name accessapp1 --identity-name keyvaultaccessapp1 --resource-group $resourceGroup --issuer "${AKS_OIDC_ISSUER}" --subject system:serviceaccount:accessapp1:accessapp1 --audience api://AzureADTokenExchange
az identity federated-credential create --name accessapp2 --identity-name keyvaultaccessapp2 --resource-group $resourceGroup --issuer "${AKS_OIDC_ISSUER}" --subject system:serviceaccount:accessapp2:accessapp2 --audience api://AzureADTokenExchange
az keyvault create -n accessapp1vault -g $resourceGroup -l $location --enable-rbac-authorization
az keyvault create -n accessapp2vault -g $resourceGroup -l $location --enable-rbac-authorization
export accessapp1uami="$(az identity show --resource-group $resourceGroup --name keyvaultaccessapp1 --query 'clientId' -o tsv)"
export accesapp1keyvault="$(az keyvault show --name accessapp1vault --query id -o tsv)"
az role assignment create --role "Key Vault Secrets User" --assignee $accessapp1uami --scope $accesapp1keyvault --subscription "${SUBSCRIPTION}"
export accessapp2uami="$(az identity show --resource-group $resourceGroup --name keyvaultaccessapp2 --query 'clientId' -o tsv)"
export accesapp2keyvault="$(az keyvault show --name accessapp2vault --query id -o tsv)"
az role assignment create --role "Key Vault Secrets User" --assignee $accessapp2uami --scope $accesapp2keyvault --subscription "${SUBSCRIPTION}"
az keyvault secret set --vault-name accessapp1vault -n ExampleSecret --value MyAKSExampleSecret
az keyvault secret set --vault-name accessapp2vault -n ExampleSecret --value MyAKSExampleSecret
kubectl apply -f kube-service-account.yaml
kubectl apply -f secret-prodvider.yaml
kubectl apply -f kube-pods.yaml