Infrastructure

Azure Key Vault : diagnostiquer les références de secrets avant une rotation

Un runbook de production pour qualifier une panne de référence Key Vault avec identité managée, RBAC, version de secret, diagnostics, KQL, validation et rollback avant de tourner ou élargir les accès.

05 juil. 2026 azurekey-vaultmanaged-identityrbacsecretsobservabilitykqlsecurityrunbookrollbackproduction

Une application peut tomber en production sans que le secret lui-même ait disparu. Une référence Key Vault peut pointer vers une version désactivée, une identité managée peut avoir changé, un rôle RBAC peut ne pas encore être propagé, une règle réseau peut bloquer le coffre, ou une rotation peut avoir remplacé la valeur sans que le runtime recharge sa configuration. Le symptôme est souvent un 403, une valeur vide, un secret périmé ou un redémarrage en boucle. Le mauvais réflexe consiste à tourner le secret encore une fois ou à donner un rôle plus large.

Le cas d’usage est une API Azure App Service ou Azure Functions qui lit des secrets depuis Key Vault via références d’application, SDK ou configuration d’automatisation. Après un déploiement, une rotation ou une correction d’identité, l’application ne récupère plus la bonne valeur. Le but du runbook est de décider s’il faut corriger la référence, restaurer une version, réparer l’identité, attendre une propagation, rollbacker la configuration ou bloquer la rotation.

Figer le contrat secret-runtime

Commencez par décrire le contrat attendu. Un secret de production n’est pas seulement une valeur : c’est un nom, une version, un consommateur, une identité d’exécution, une méthode de lecture, une fenêtre de rotation et un plan de retour.

text key-vault-secret-contract.txt
Contrat secret-runtime
Application: api-billing-prod
Coffre: kv-prod-platform
Secret: billing-db-password
Version attendue: latest ou version explicite
Consommateur: App Service, Function, worker, pipeline ou runbook
Methode de lecture: Key Vault reference, SDK, variable injectee ou automation
Identite d'execution: managed identity system-assigned ou user-assigned
Derniere rotation connue
Derniere version valide
Rollback: version precedente, slot precedent, configuration precedente ou secret secondaire

Questions avant action
Quelle identite lit vraiment le secret ?
La reference pointe-t-elle vers latest ou vers une version pinnee ?
La version courante est-elle active et non expiree ?
Le coffre a-t-il recu une requete depuis le runtime ?
Les droits, le reseau et le cache runtime sont-ils separes ?

Si l’équipe ne peut pas nommer l’identité réelle et la version attendue, une nouvelle rotation ajoute de la dérive au lieu de résoudre l’incident.

Séparer référence, identité et réseau

Trois familles de panne se ressemblent côté application. Une référence mal formée ne demande jamais le secret. Une identité sans droit reçoit un refus. Un chemin réseau bloqué ne produit pas la même preuve côté Key Vault. Il faut donc éviter de corriger toutes les couches en même temps.

bash 01-key-vault-reference-snapshot.sh
APP_RG="rg-prod-app"
APP_NAME="app-billing-prod"
VAULT_NAME="kv-prod-platform"
SECRET_NAME="billing-db-password"

az webapp config appsettings list --resource-group "$APP_RG" --name "$APP_NAME" --query "[?contains(value, '@Microsoft.KeyVault')].{name:name,value:value}" --output table

az keyvault secret show --vault-name "$VAULT_NAME" --name "$SECRET_NAME" --query "{id:id,enabled:attributes.enabled,expires:attributes.expires,created:attributes.created,updated:attributes.updated}" --output json

az webapp identity show --resource-group "$APP_RG" --name "$APP_NAME" --output json

Pour Functions, Container Apps ou un worker, adaptez la commande au runtime. Le point important est de capturer la référence, le secret et l’identité au même moment.

Vérifier la version avant de tourner

Une référence Key Vault peut cibler SecretUri sans version, ou une version explicite. Les deux modes sont légitimes, mais ils ne se diagnostiquent pas pareil. Avec une version pinnee, une rotation ne sera pas consommée tant que la référence ne change pas. Avec latest, une version désactivée, expirée ou invalide peut casser le runtime.

bash 02-secret-version-check.sh
VAULT_NAME="kv-prod-platform"
SECRET_NAME="billing-db-password"

az keyvault secret list-versions --vault-name "$VAULT_NAME" --name "$SECRET_NAME" --query "[].{id:id,enabled:attributes.enabled,expires:attributes.expires,created:attributes.created,updated:attributes.updated}" --output table

az keyvault secret show --vault-name "$VAULT_NAME" --name "$SECRET_NAME" --query "{id:id,valuePresent:value != null,enabled:attributes.enabled,expires:attributes.expires}" --output json

Ne lisez pas la valeur en clair pour prouver l’incident. La preuve utile est l’état de la version, son identifiant, sa date et son accessibilité par l’identité de production.

Corréler les logs Key Vault et runtime

Le coffre doit dire si la requête arrive, qui l’envoie et pourquoi elle échoue. Côté application, les logs doivent dire si la configuration est résolue, mise en cache, expirée ou absente.

kusto 03-key-vault-secret-evidence.kql
let StartTime = datetime(2026-07-05T08:00:00Z);
let EndTime = datetime(2026-07-05T09:00:00Z);
let VaultName = "kv-prod-platform";
let SecretName = "billing-db-password";
AzureDiagnostics
| where TimeGenerated between (StartTime .. EndTime)
| where ResourceProvider == "MICROSOFT.KEYVAULT"
| where Resource has VaultName
| where OperationName has_any ("SecretGet", "SecretList")
| extend secretName = tostring(parse_url(tostring(id_s)).Path)
| where id_s has SecretName or requestUri_s has SecretName
| project TimeGenerated,
        OperationName,
        ResultType,
        ResultSignature,
        CallerIPAddress,
        identity_claim_appid_g,
        identity_claim_oid_g,
        requestUri_s,
        CorrelationId
| order by TimeGenerated asc

Si aucun événement Key Vault ne correspond au runtime, cherchez d’abord la référence, le cache, le réseau ou la variable d’environnement. Si le coffre retourne Forbidden, concentrez-vous sur l’identité, RBAC ou access policy. Si le coffre retourne NotFound, contrôlez le nom, la version et l’environnement.

Tester avec l’identité réelle

Un test depuis le poste d’un administrateur ne valide pas le chemin de production. Il faut reproduire la lecture avec l’identité qui exécute l’application ou avec une preuve équivalente dans les logs.

text runtime-identity-checklist.txt
Controles d'identite
L'identite system-assigned ou user-assigned attendue est active
Le client ID configure correspond a l'identite utilisee par le runtime
Le role Key Vault Secrets User ou l'access policy couvre le bon coffre
La propagation RBAC a eu le temps necessaire
Aucun changement recent n'a remplace l'identite du slot, de la Function ou du worker
Les logs Key Vault montrent le meme object ID que le runtime

Bloquer l'elargissement des droits quand
L'identite reelle n'est pas connue
Le test a ete fait avec un compte humain
Plusieurs identites sont attachees mais aucune n'est explicitement selectionnee
Le coffre ne recoit aucune requete du runtime
Le role demande depasse la lecture du secret requis

L’objectif est d’éviter le rôle large qui marche par hasard. Le bon correctif donne seulement la lecture nécessaire au consommateur attendu.

Valider cache, redémarrage et slot

Même quand Key Vault est sain, l’application peut garder une ancienne valeur. Les références App Service, les variables injectées, les slots et certains workers ne rechargent pas tous les secrets au même moment. La décision doit intégrer ce comportement au lieu de multiplier les rotations.

yaml secret-refresh-validation.yml
validation:
target: api-billing-prod
secret: billing-db-password
expected_version: latest_valid_version
checks:
  - key_vault_logs_show_secret_get_from_runtime_identity
  - runtime_logs_show_configuration_refresh_or_restart
  - application_health_check_passes_with_correlation_id
  - no_new_forbidden_or_notfound_errors
  - previous_secret_version_still_available_for_rollback
controlled_actions:
  - refresh_configuration_if_supported
  - restart_one_instance_or_slot_if_required
  - swap_back_only_if validation_fails
stop_when:
  - new version breaks dependency authentication
  - runtime still reads old version after documented refresh
  - Key Vault denies production identity
  - rollback version is disabled or expired

Pour un slot bleu/vert, validez le slot qui recevra le trafic. Une référence correcte sur le slot de staging ne prouve pas que la production consommera la même identité ou la même version après swap.

Décider correction, rollback ou rotation différée

La décision doit rester limitée au défaut prouvé. Une panne de référence n’est pas toujours un problème de secret.

text key-vault-secret-decision.txt
Corriger la reference
Le nom de secret, le coffre ou la version cible est faux
La reference pointe vers une version desactivee ou obsolete
Le slot de production ne porte pas la meme configuration que le slot valide

Reparer l'identite ou RBAC
Key Vault recoit la requete du runtime
ResultType montre Forbidden ou equivalent
L'object ID correspond a une identite attendue mais sans droit suffisant
Le role cible reste limite a la lecture de secret

Attendre ou forcer un refresh controle
Le secret est lisible par l'identite de production
La reference est correcte
Le runtime garde une valeur cachee
Le redemarrage ou refresh est teste sur un perimetre borne

Rollbacker
La nouvelle version casse la dependance aval
Une rotation a retire la derniere version fonctionnelle trop tot
Le changement d'identite ou de slot a casse plusieurs consommateurs
La configuration precedente restaure le service et reste auditable

Differer la rotation
L'identite reelle n'est pas prouvee
Les logs Key Vault sont indisponibles
Le rollback secret n'est pas valide
Le consommateur aval ne peut pas confirmer l'acceptation de la nouvelle valeur

Une rotation réussie n’est pas celle qui crée une nouvelle valeur. C’est celle qui prouve que les consommateurs attendus lisent la bonne version et que l’ancienne peut être retirée sans casser le service.

Conclusion

Diagnostiquer une référence Key Vault demande de traiter le secret comme une dépendance de production complète : référence, version, identité, droits, réseau, cache runtime, logs et rollback. Tant que ces éléments ne sont pas séparés, tourner le secret ou élargir les accès masque la cause.

La décision fiable consiste à corriger la couche prouvée, valider avec l’identité réelle, conserver une version de retour et retirer les accès temporaires. Le coffre reste alors un contrôle de sécurité, pas une boîte noire qui casse les déploiements au mauvais moment.