Accueil Blog Workload Identity sur AKS : accéder à Azure Key Vault sans aucun secret stocké
Kubernetes

Workload Identity sur AKS : accéder à Azure Key Vault sans aucun secret stocké

Le secret le plus dangereux d'un cluster, c'est celui qui donne accès au coffre. Workload Identity le supprime : un ServiceAccount Kubernetes échange son token OIDC contre un token Entra ID, et lit Azure Key Vault sans clé stockée.

Le paradoxe classique de la gestion des secrets : vous centralisez vos mots de passe dans Azure Key Vault… mais pour y accéder depuis Kubernetes, il faut un credential. Et ce credential-là, où le stockez-vous ?

Workload Identity supprime le problème à la racine. Le cluster AKS signe des tokens OIDC pour ses ServiceAccounts ; Microsoft Entra ID apprend à leur faire confiance ; le pod échange son token contre un token Entra ID — et accède au Key Vault. Aucune clé, aucun certificat, aucun secret d’amorçage stocké dans le cluster.

Cet article déroule le montage complet, tel que nous l’avons industrialisé dans une démo publiqueExternal Secrets Operator (ESO) synchronise des mots de passe PostgreSQL depuis trois coffres (Key Vault, HashiCorp Vault, AWS Secrets Manager).

Le concept : échanger un token Kubernetes contre un token Entra ID

Deux options du cluster AKS font tout le travail :

az aks create -g $RG -n $AKS \
  --enable-oidc-issuer \
  --enable-workload-identity \
  ...
  • --enable-oidc-issuer expose un issuer OIDC public : une URL qui publie les clés de signature des tokens de ServiceAccounts du cluster ;
  • --enable-workload-identity injecte dans les pods concernés un token projeté et les variables d’environnement attendues par les SDK Azure.

À partir de là, un token de ServiceAccount devient une preuve d’identité vérifiable de l’extérieur : Entra ID peut valider sa signature en interrogeant l’issuer, comme n’importe quel fournisseur OIDC.

C’est exactement le même principe qu’IRSA côté AWS — nous l’avons d’ailleurs appliqué à AWS Secrets Manager depuis ce même cluster AKS.

L’identité managée : une identité dédiée, pas un compte partagé

On crée une User Assigned Managed Identity dédiée au besoin (ici : la lecture des secrets par ESO) :

az identity create -g $RG -n id-eso-demo
UAMI_CLIENT_ID=$(az identity show -g $RG -n id-eso-demo --query clientId -o tsv)
UAMI_PRINCIPAL_ID=$(az identity show -g $RG -n id-eso-demo --query principalId -o tsv)

Deux identifiants qu’on confond souvent :

  • clientId — l’identifiant d’application, celui qu’on annote sur le ServiceAccount ;
  • principalId — l’identifiant du service principal, celui qu’on utilise pour les attributions RBAC.

Une identité dédiée par usage : c’est ce qui permet un périmètre de droits minimal et un audit lisible.

Le RBAC Key Vault : lecture seule, sur le bon scope

az role assignment create \
  --assignee-object-id $UAMI_PRINCIPAL_ID --assignee-principal-type ServicePrincipal \
  --role "Key Vault Secrets User" \
  --scope $(az keyvault show -g $RG -n $KV --query id -o tsv)
  • « Key Vault Secrets User » : lecture seule des secrets (plan données) — c’est tout ce dont ESO a besoin ;
  • « Key Vault Secrets Officer » : lecture/écriture — réservé à l’humain (ou au pipeline) qui pousse les secrets.

Le scope est le vault lui-même, pas le resource group : moindre privilège, toujours.

Le federated credential : la ligne de confiance

C’est la pièce centrale du montage — la déclaration qui dit à Entra ID « ce ServiceAccount Kubernetes est cette identité managée » :

az identity federated-credential create \
  --name fc-eso --identity-name id-eso-demo -g $RG \
  --issuer $(az aks show -g $RG -n $AKS --query oidcIssuerProfile.issuerUrl -o tsv) \
  --subject "system:serviceaccount:eso-demo:eso-sa" \
  --audience api://AzureADTokenExchange

Trois paramètres, trois verrous :

  • issuer : seul ce cluster peut émettre les tokens acceptés ;
  • subject : seul le ServiceAccount eso-sa du namespace eso-demo est reconnu — pas un autre SA, pas un autre namespace ;
  • audience : api://AzureADTokenExchange, l’audience dédiée à l’échange de tokens.

Le moindre écart sur le subject (faute de frappe, mauvais namespace) produit une erreur AADSTS70021: No matching federated identity record found — c’est le premier endroit à vérifier en cas de panne.

Côté cluster : un ServiceAccount annoté, et c’est tout

apiVersion: v1
kind: ServiceAccount
metadata:
  name: eso-sa
  namespace: eso-demo
  annotations:
    azure.workload.identity/client-id: "<clientId de l'identité managée>"
  labels:
    azure.workload.identity/use: "true"

Le SecretStore d’External Secrets Operator référence ce SA et déclare l’authentification Workload Identity :

apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: azure-store
  namespace: eso-demo
spec:
  provider:
    azurekv:
      authType: WorkloadIdentity
      vaultUrl: "https://kv-eso-demo.vault.azure.net/"
      tenantId: "<tenant-id>"
      serviceAccountRef:
        name: eso-sa

À partir de là, chaque ExternalSecret adossé à ce store lit le Key Vault et matérialise un Secret Kubernetes — templable (type basic-auth, URL de connexion, etc.), resynchronisé périodiquement, rotation comprise : changez le mot de passe dans le coffre, ESO propage.

Déboguer : les trois pannes classiques

Symptôme Cause probable
AADSTS70021: No matching federated identity record le subject du federated credential ne correspond pas à system:serviceaccount:<ns>:<sa>, ou mauvais issuer
403 Forbidden sur le Key Vault rôle « Key Vault Secrets User » absent, mauvais scope, ou vault resté en access policies au lieu de RBAC
Token non injecté dans le pod label azure.workload.identity/use: "true" absent du SA (ou du pod), ou add-on Workload Identity non activé

Le réflexe : kubectl describe secretstore puis kubectl describe externalsecret — les conditions et events d’ESO pointent presque toujours la brique fautive.

Ce qu’il faut retenir

Brique Rôle
OIDC issuer AKS rend les tokens de SA vérifiables de l’extérieur
Identité managée dédiée porte les droits, un usage = une identité
Rôle « Key Vault Secrets User » lecture seule, scope réduit au vault
Federated credential la confiance issuer + subject + audience
SA annoté + SecretStore le câblage côté cluster, sans aucun secret

Le montage tient en une vingtaine de lignes de CLI et deux manifests — l’intégralité est rejouable depuis la démo eso-aks-demo (script mise run azure-setup, idempotent). Et si votre plateforme parle aussi à AWS, le même principe s’applique à Secrets Manager — avec quelques pièges spécifiques que nous avons documentés.

Pour aller plus loin sur la trajectoire plateforme, voir aussi Kubernetes pour l’entreprise.

Vos secrets Kubernetes méritent mieux qu'un fichier .env

Doveaia industrialise la gestion des secrets sur AKS : Workload Identity, External Secrets, rotation et gouvernance — sans friction pour vos équipes.

Sécuriser vos secrets Kubernetes