Small demo that reads secrets from Azure Key Vault via the Secrets Store CSI driver and injects them into a Java app.
Features
- Uses Secrets Store CSI driver + SecretProviderClass to sync Key Vault secrets into a Kubernetes Secret
- Image entrypoint reads files from
/mnt/secrets-storeand exports them as environment variables - Local development supported via an embedded
.env(not for production)
- Build the image:
cd app
docker build -t aro-key-vault-app:local .- Run locally (uses
./app/.env):
docker run --rm -v /mnt/secrets-store:/mnt/secrets-store aro-key-vault-app:local- CI / ACR push (example)
# tag
docker tag aro-key-vault-app:local <ACR_HOST>/aro-key-vault-app:latest
# login then push
docker push <ACR_HOST>/aro-key-vault-app:latestRecommended sequence for ACR push and Key Vault setup
Prerequisites
- Install and login with Azure CLI:
az login - Have access to an Azure Container Registry (ACR) and an Azure Key Vault
- Build, tag and push image to ACR (local Docker)
# build locally
cd app
docker build -t aro-key-vault-app:latest .
# tag for your ACR (replace <ACR_LOGIN_SERVER> e.g. myacr.azurecr.io)
docker tag aro-key-vault-app:latest <ACR_LOGIN_SERVER>/aro-key-vault-app:latest
# login to ACR (option A: az acr login)
az acr login --name <ACR_NAME>
# push
docker push <ACR_LOGIN_SERVER>/aro-key-vault-app:latestAlternatively build in cloud using ACR Tasks:
az acr build --registry <ACR_NAME> --image aro-key-vault-app:latest ./app- (Optional) Create a service principal for CI to push to ACR and access Key Vault
# create SP and allow pushing images to ACR
az ad sp create-for-rbac --name "ci-acr-sp" --role AcrPush --scopes /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RG>/providers/Microsoft.ContainerRegistry/registries/<ACR_NAME>
# the command prints appId (CLIENT_ID) and password (CLIENT_SECRET)- Grant the service principal access to Key Vault secrets (so it can read or the pod can use SP credentials)
# grant get/list on secrets to the SP
az keyvault set-policy --name <KV_NAME> --spn <CLIENT_ID> --secret-permissions get list- Set Key Vault secrets (example)
az keyvault secret set --vault-name <KV_NAME> --name ENV-TYPE --value "dev"
az keyvault secret set --vault-name <KV_NAME> --name AZURE-TENANT-ID --value "<TENANT_ID>"
az keyvault secret set --vault-name <KV_NAME> --name AZURE-CLIENT-ID --value "<CLIENT_ID>"
az keyvault secret set --vault-name <KV_NAME> --name AZURE-CLIENT-SECRET --value "<CLIENT_SECRET>"
az keyvault secret set --vault-name <KV_NAME> --name PG-SERVER --value "<PG_HOST>"
az keyvault secret set --vault-name <KV_NAME> --name PG-DATABASE --value "<DB_NAME>"
az keyvault secret set --vault-name <KV_NAME> --name PG-USER --value "<DB_USER>"- Update
secret-provider.yaml(if using service principal auth) withtenantId, and ensurekeyvaultNamematches<KV_NAME>; then apply manifests:
kubectl apply -f secret-provider.yaml
kubectl apply -f app.yamlNotes
- Use Azure Managed Identities where possible instead of storing client secrets.
- For automation (CI), store sensitive values in CI secrets (GitHub Actions Secrets, Azure DevOps library) and inject them during the pipeline — do not hardcode secrets in repository files.
Set Key Vault secrets (example):
az keyvault secret set --vault-name <KV_NAME> --name ENV-TYPE --value "dev"
az keyvault secret set --vault-name <KV_NAME> --name AZURE-TENANT-ID --value "<tenant-id>"
az keyvault secret set --vault-name <KV_NAME> --name AZURE-CLIENT-ID --value "<client-id>"
az keyvault secret set --vault-name <KV_NAME> --name AZURE-CLIENT-SECRET --value "<client-secret>"
az keyvault secret set --vault-name <KV_NAME> --name PG-SERVER --value "<pg-host>"
az keyvault secret set --vault-name <KV_NAME> --name PG-DATABASE --value "<db-name>"
az keyvault secret set --vault-name <KV_NAME> --name PG-USER --value "<db-user>"- Ensure Secrets Store CSI driver and provider are installed on the cluster.
- Create
SecretProviderClass(example:secret-provider.yaml) pointing at your Key Vault. - Apply the pod manifest:
oc apply -f app.yaml(orkubectl apply -f app.yaml).
- The container entrypoint (
app/entrypoint.sh) will read allowed files from/mnt/secrets-storeand export them as environment variables (hyphens converted to underscores). In local runs the application falls back to.envusing dotenv.
- MIT