Automation
Azure DevOps : diagnostiquer un secret Key Vault après rotation avant de relancer la production
Un runbook de production pour qualifier un secret Azure Key Vault consommé par Azure Pipelines via variable group, isoler version, mapping, identité, réseau et précédence, puis valider ou rollbacker sans exposer la valeur.
Une rotation de secret peut réussir dans Azure Key Vault et casser le déploiement qui suit. Le pipeline voit une variable vide, reçoit un 401, ou échoue avant même le premier script. La réaction rapide consiste souvent à relancer le job, recréer le secret ou élargir les droits du service connection. Ces actions mélangent pourtant plusieurs problèmes possibles : version désactivée, nom absent du variable group, autorisation de lecture, chemin réseau, collision de variables ou application qui utilise encore l’ancienne valeur.
Le cas d’usage est un pipeline Azure DevOps qui déploie payments-api-prod. Il consomme payments-api-key depuis Key Vault via le variable group vg-payments-prod. Une rotation a eu lieu à 08:30 UTC ; le déploiement suivant échoue à l’étape de smoke test. L’objectif du runbook est de décider s’il faut corriger la liaison Azure DevOps, restaurer temporairement l’ancienne version, réparer le consommateur ou bloquer la relance tant que la preuve manque.
Figer le contrat de rotation
Avant de toucher au vault ou au pipeline, rassemblez les identifiants qui relient la rotation à l’échec. La valeur du secret n’en fait jamais partie.
incident:
pipeline: payments-api-prod
run_id: 18452
stage: deploy_westeurope
variable_group: vg-payments-prod
key_vault: kv-payments-prod
secret_name: payments-api-key
rotation_time_utc: 2026-08-07T08:30:00Z
first_failed_run_utc: 2026-08-07T08:42:00Z
evidence_without_secret_value:
- pipeline commit and template version
- variable group identifier and authorization
- service connection principal identifier
- secret version, enabled state and dates
- agent pool and network path
- failing task and downstream HTTP status
decisions:
- repair mapping or authorization
- deploy with current version
- restore previous version temporarily
- stop and correct the application contract Ce contrat empêche un faux diagnostic fréquent : attribuer au secret une erreur apparue dans le même créneau, alors que le pipeline a aussi changé de template, de pool ou de variable group.
Séparer le nom, la valeur et le consommateur
Un variable group lié à Key Vault conserve une sélection de noms de secrets. Les valeurs sont récupérées au moment de l’exécution. Une nouvelle version sous un nom déjà sélectionné peut donc être disponible sans modifier le groupe. En revanche, ajouter un nouveau nom ou supprimer l’ancien dans Key Vault ne met pas automatiquement la sélection à jour.
Le diagnostic doit suivre trois objets distincts :
- le nom sélectionné dans
vg-payments-prod; - la version courante que Key Vault retourne pour ce nom ;
- la variable effectivement injectée dans la tâche qui lance le smoke test.
Un 401 applicatif prouve seulement que la valeur utilisée n’est pas acceptée. Il ne dit pas si Azure DevOps a lu la mauvaise version, si une autre variable a pris la priorité ou si le service cible n’accepte pas encore la nouvelle clé.
Inspecter les versions sans lire la valeur
Commencez par les métadonnées du secret. La version la plus récente doit être activée, dans sa fenêtre de validité, créée au moment attendu et identifiable dans le journal de changement.
SUBSCRIPTION="00000000-0000-0000-0000-000000000000"
VAULT="kv-payments-prod"
SECRET="payments-api-key"
az account set --subscription "$SUBSCRIPTION"
az keyvault secret list-versions --vault-name "$VAULT" --name "$SECRET" --query "[].{version:id,enabled:attributes.enabled,created:attributes.created,updated:attributes.updated,notBefore:attributes.notBefore,expires:attributes.expires}" --output table Conservez l’identifiant de version, mais pas le résultat de az keyvault secret show --query value. Le pipeline doit prouver la présence et l’usage du secret sans l’imprimer, le copier dans un artefact ou le passer dans un paramètre de ligne de commande visible.
Si la dernière version est désactivée ou expirée, la relance ne corrigera rien. Si elle est valide, poursuivez vers la liaison et l’identité avant de recréer une version supplémentaire.
Vérifier la liaison, l’identité et le chemin
Le variable group doit être autorisé pour le pipeline et lié au bon vault avec le bon nom de secret. Le principal porté par le service connection doit disposer des droits de lecture nécessaires selon le modèle d’autorisation du vault. Notez son identifiant d’objet : le nom affiché du service connection n’est pas une preuve d’identité.
Variable group
Group: vg-payments-prod
Type: AzureKeyVault
Vault: kv-payments-prod
Selected name: payments-api-key
Pipeline permission: payments-api-prod authorized
Service connection
Connection used by the variable group recorded
Tenant and subscription match production
Principal object ID recorded
Get/List or equivalent RBAC access proven
Execution path
Microsoft-hosted or self-hosted agent identified
Vault firewall and public/private access model recorded
DNS and TCP/TLS path tested from the actual self-hosted pool when applicable
No temporary broad firewall opening kept after diagnosis Un vault privé change le chemin d’exploitation. Une tâche AzureKeyVault@2 exécutée sur un agent auto-hébergé dans le réseau autorisé peut être adaptée quand le variable group ne peut pas joindre le vault selon son mode d’accès. Ce changement doit être traité comme une décision d’architecture testée, pas comme un contournement ajouté pendant l’incident.
Écarter la collision de variables
Une valeur correcte peut être remplacée après sa récupération. Azure Pipelines applique une précédence entre variables définies à la mise en file, dans le YAML et dans les variable groups. Deux groupes contenant le même nom dans le même scope rendent le résultat difficile à expliquer.
Inspectez le YAML final après expansion des templates et recherchez toutes les définitions de payments-api-key ou de son alias. Préférez un nom explicite et mappez le secret vers une variable d’environnement uniquement dans la tâche qui en a besoin.
variables:
- group: vg-payments-prod
steps:
- bash: |
set -euo pipefail
if [ -z "$PAYMENTS_API_KEY" ]; then
echo "Secret injection failed: PAYMENTS_API_KEY is empty"
exit 20
fi
echo "Secret injection present; value intentionally not logged"
displayName: Validate secret injection
env:
PAYMENTS_API_KEY: $(payments-api-key) Cette vérification distingue une variable absente d’un secret rejeté par le service cible. Elle ne prouve pas encore que la valeur est la bonne ; le test fonctionnel borné s’en charge.
Construire une relance contrôlée
Ne relancez pas directement le déploiement complet. Créez une étape de préflight qui utilise les mêmes template, variable group, service connection et pool que la production, mais ne modifie aucune ressource. Elle doit vérifier l’injection, puis appeler un endpoint de validation non destructif ou un contrôle d’authentification prévu par le service.
stages:
- stage: secret_preflight
variables:
- group: vg-payments-prod
jobs:
- job: validate_rotated_secret
pool: prod-private-agents
steps:
- bash: |
set -euo pipefail
test -n "$PAYMENTS_API_KEY"
status=$(curl --silent --show-error --output /dev/null --write-out "%{http_code}" --connect-timeout 5 --max-time 15 --header "Authorization: Bearer $PAYMENTS_API_KEY" "https://payments.internal.example.com/auth/check")
test "$status" = "204"
displayName: Validate current secret against bounded endpoint
env:
PAYMENTS_API_KEY: $(payments-api-key) Adaptez l’endpoint et le schéma d’authentification au service réel. Le principe stable est d’utiliser la même voie de récupération que la production, de ne provoquer aucune écriture métier et de fixer un timeout court. Un préflight vert autorise la suite ; il ne déclenche pas automatiquement le déploiement.
Corréler la rotation et les exécutions
La timeline doit montrer quelle exécution a consommé quelle génération logique du secret sans stocker sa valeur. Enregistrez un identifiant de rotation fourni par le processus, l’identifiant de version Key Vault côté contrôle, le run Azure DevOps et le résultat du préflight dans le ticket ou la télémétrie de changement.
{
"rotationId": "rot-payments-20260807-0830",
"vault": "kv-payments-prod",
"secretName": "payments-api-key",
"secretVersionId": "version-id-without-value",
"variableGroup": "vg-payments-prod",
"pipelineRunId": 18452,
"preflightRunId": 18457,
"injectionCheck": "present",
"boundedAuthCheck": "passed",
"productionDeploymentApproved": false,
"rollbackVersionId": "previous-version-id"
} Ne calculez pas un hash du secret dans les logs pour tenter de le reconnaître : cela crée une donnée dérivée sensible et n’établit pas que le consommateur accepte la valeur. Un identifiant de version et un test fonctionnel suffisent.
Décider validation ou rollback
La fin du runbook doit produire une décision explicite.
Valider la rotation
Le nom est sélectionné dans le variable group
La dernière version est active et dans sa fenêtre de validité
L'identité et le chemin d'accès sont prouvés
Aucune variable de priorité supérieure ne remplace le secret
Le préflight non destructif passe depuis le pool de production
Le déploiement reste soumis à son approbation normale
Réparer puis retester
Le nouveau nom manque dans le variable group
Le pipeline ou le groupe n'est pas autorisé
Le service connection pointe vers le mauvais principal ou abonnement
Le réseau empêche la récupération depuis le chemin réel
Une collision YAML remplace la variable
Rollbacker la rotation
Le consommateur n'accepte pas la nouvelle valeur
La correction applicative ne tient pas dans la fenêtre d'incident
L'ancienne version est encore autorisée par la politique de sécurité
Sa réactivation est bornée, approuvée et suivie d'un nouveau préflight
Arrêter la relance
La version consommée ne peut pas être identifiée
La valeur a été exposée dans les logs ou un artefact
Le rollback n'est pas défini
Plusieurs changements concurrents empêchent d'attribuer le résultat Un bon rollback ne consiste pas à remettre l’ancienne valeur dans le YAML. Il restaure temporairement une version maîtrisée dans Key Vault, conserve la même voie de consommation et fixe une échéance de nouvelle rotation. Une fois le préflight vert, la production peut être relancée avec une preuve claire : nom sélectionné, version active, identité correcte, chemin accessible et consommateur compatible.