Cloud

Azure ACR et AKS : contenir un digest d'image vulnérable avant de redéployer

Un runbook de production pour relier un signal de vulnérabilité ACR aux pods AKS, geler la promotion, revenir à un digest connu, valider le rollout puis conserver ou supprimer l'image suspecte.

08 août 2026 azureacrakscontainerssecurityimage-digestvulnerabilitysupply-chainkubernetesrunbookrollbackproduction

Une analyse de vulnérabilité signale un digest dans Azure Container Registry. Le même dépôt contient plusieurs tags, des pods AKS tournent déjà et le pipeline peut encore promouvoir l’image. Supprimer immédiatement le manifest paraît prudent. Cette action ne remplace pourtant pas les conteneurs en cours et peut rendre leur prochain redémarrage impossible avant qu’un digest sain soit prêt.

Le cas d’usage est un service déployé dans plusieurs namespaces AKS depuis une image ACR. L’équipe doit déterminer où le digest suspect s’exécute, stopper sa propagation, revenir vers un artefact connu et prouver que le cluster ne le relance plus. La sortie du runbook est une décision explicite : conserver temporairement le manifest pour l’investigation, le supprimer du registre ou isoler le workload faute de version sûre.

Fixer l’incident au digest

Un tag décrit une intention de publication ; un digest identifie le manifest réellement exécuté. Un même digest peut porter plusieurs tags, et un tag mutable peut désormais pointer vers une autre image. Le dossier d’incident doit commencer par le digest complet, le dépôt, le registre et la preuve qui a déclenché l’alerte.

yaml container-image-incident.yml
incident: inc-container-2026-08-08-01
registry: acrprodweu
repository: payments/api
suspect_digest: sha256:<digest-suspect>
finding:
source: approved-vulnerability-assessment
severity: <severity>
affected_component: <package-or-layer>
exploitable_context: under-review
scope:
clusters: [aks-prod-weu, aks-prod-neu]
environments: [production]
containment_owner: platform-oncall
application_owner: payments-team
known_good_digest: sha256:<digest-known-good>
deletion_authorized: false

Ne transformez pas automatiquement une sévérité élevée en suppression immédiate. Confirmez que le finding concerne ce digest, que le composant vulnérable est présent dans le chemin d’exécution et que l’image n’est pas seulement un parent utilisé pendant le build. Cette qualification ajuste l’urgence ; elle ne doit pas retarder le gel de promotion.

Relier le manifest ACR aux workloads AKS

Commencez par inventorier les métadonnées du manifest et les tags attachés. Cette lecture est non destructive.

bash 01-inspect-acr-digest.sh
ACR="acrprodweu"
REPOSITORY="payments/api"
SUSPECT_DIGEST="sha256:<digest-suspect>"

az acr manifest list-metadata --registry "$ACR" --name "$REPOSITORY" --query "[?digest=='$SUSPECT_DIGEST']" --output json

Interrogez ensuite les pods pour lire l’image demandée et l’identifiant résolu par le runtime. Le champ image peut encore montrer un tag alors que imageID expose le digest effectivement tiré.

bash 02-find-running-digest.sh
kubectl get pods --all-namespaces -o json | jq -r '
.items[] as $pod
| ($pod.status.containerStatuses // [])[]
| select(.imageID | contains("sha256:<digest-suspect>"))
| [
    $pod.metadata.namespace,
    $pod.metadata.name,
    .name,
    .image,
    .imageID,
    (.ready | tostring),
    (.restartCount | tostring)
  ]
| @tsv'

Répétez l’inventaire sur chaque cluster du périmètre. Associez chaque pod à son contrôleur, puis au dépôt GitOps ou à la release qui porte l’état désiré. Modifier un pod isolé ne tient pas : Deployment, StatefulSet, DaemonSet ou opérateur le recréera depuis sa propre référence.

Conservez aussi les workloads à zéro replica et les CronJobs. Ils ne produisent aucun pod au moment du diagnostic, mais peuvent relancer le digest lors du prochain scale-out ou de la prochaine planification.

Geler la propagation sans effacer la preuve

Le premier changement doit empêcher une nouvelle promotion, pas détruire l’artefact étudié. Suspendez le job qui déplace les tags de release, bloquez le digest dans la politique de déploiement et interdisez les relances automatiques non nécessaires. Gardez les lectures ACR et la collecte de logs disponibles.

yaml digest-containment-decision.yml
blocked:
- promote suspect digest to an environment tag
- create a new workload revision with suspect digest
- restart or scale out affected workloads without approval
- rebuild from an unpinned base image

still_allowed:
- read registry metadata and vulnerability evidence
- export manifests, SBOM and deployment history
- build and scan a remediation candidate
- deploy the approved known-good digest to a canary

exit_conditions:
- every desired-state reference is known
- a deployable safe digest is selected
- rollback and isolation paths are assigned
- validation commands are ready before rollout

Un tag déplacé n’assainit pas les pods existants. Une suppression ACR ne les arrête pas non plus. Le confinement est complet seulement quand le pipeline refuse le digest et que l’état désiré des contrôleurs ne peut plus le recréer.

Choisir un retour sûr, pas seulement une image plus ancienne

Le candidat de retour doit être identifié par digest et requalifié avec les données disponibles au moment de l’incident. « Revenir à la version précédente » ne suffit pas si cette version partage la même couche vulnérable ou n’est plus compatible avec une migration de schéma déjà appliquée.

Vérifiez au minimum la provenance du build, le résultat de scan, la compatibilité de configuration, les dépendances externes, les migrations irréversibles et la capacité de l’image à démarrer avec l’état courant. Si aucun digest précédent n’est défendable, construisez une image corrigée depuis une base épinglée ou isolez le service. Ne remettez pas le digest suspect en production uniquement parce que le nouveau rollout échoue.

text remediation-choice.txt
Retour vers un digest connu
digest rescanné et provenance vérifiée
compatible avec le schéma et la configuration actuels
probe de démarrage disponible
autre version sûre prête en cas de régression

Construire un digest corrigé
aucune version précédente compatible
patch de dépendance ou base image nécessaire
pipeline reproductible et attestations disponibles

Isoler le workload
exploitation active ou impact élevé confirmé
aucun digest sûr immédiatement déployable
exposition réseau ou action métier peut être suspendue
restauration soumise à une nouvelle validation

Redéployer par digest et commencer par un canary

Modifiez la source de vérité, pas seulement le cluster. La référence par digest garantit que tous les nouveaux pods demandent le même manifest, même si un tag est déplacé ensuite.

yaml deployment-known-good.patch.yml
spec:
template:
  metadata:
    annotations:
      naxaya.com/image-incident: inc-container-2026-08-08-01
  spec:
    containers:
    - name: api
      image: acrprodweu.azurecr.io/payments/api@sha256:<digest-known-good>
      imagePullPolicy: IfNotPresent

Appliquez d’abord ce changement à une replica ou à un segment de trafic borné. Vérifiez le démarrage, la readiness, les erreurs applicatives, les dépendances et un parcours métier réversible. Étendez ensuite par palier. L’objectif n’est pas uniquement d’obtenir un Deployment Available, mais de prouver que le digest attendu traite correctement le trafic réel.

bash 03-validate-rollout.sh
NAMESPACE="payments"
DEPLOYMENT="payments-api"

kubectl rollout status --namespace "$NAMESPACE" deployment/"$DEPLOYMENT" --timeout=10m

kubectl get pods --namespace "$NAMESPACE" -l app=payments-api -o custom-columns='POD:.metadata.name,IMAGE:.spec.containers[*].image,IMAGE_ID:.status.containerStatuses[*].imageID,READY:.status.containerStatuses[*].ready'

Une fois le rollout terminé, relancez l’inventaire global du digest suspect. Le résultat attendu est vide pour les pods en cours, les nouveaux pods et les jobs déclenchés pendant la fenêtre. Contrôlez également que les manifests GitOps, CronJobs et workloads suspendus ne le référencent plus.

Décider quoi faire du manifest suspect

Supprimer par digest dans ACR retire le manifest et tous les tags qui le référencent. L’opération est destructive. Elle empêche de nouveaux pulls depuis ce registre, mais n’arrête pas les conteneurs lancés et peut faire échouer un redémarrage encore configuré sur ce digest.

Avant suppression, exigez trois preuves : aucun état désiré approuvé ne référence le digest, aucune dépendance de restauration ne l’utilise et les éléments d’investigation nécessaires ont été conservés selon la politique de l’organisation. Affichez d’abord la cible exacte, puis faites autoriser l’action.

bash 04-delete-suspect-manifest-after-approval.sh
ACR="acrprodweu"
REPOSITORY="payments/api"
SUSPECT_DIGEST="sha256:<digest-suspect>"

az acr manifest list-metadata --registry "$ACR" --name "$REPOSITORY" --query "[?digest=='$SUSPECT_DIGEST'].[digest,tags,lastUpdateTime]" --output table

# Exécuter uniquement après validation formelle de la cible.
az acr repository delete --name "$ACR" --image "$REPOSITORY@$SUSPECT_DIGEST" --yes

Si l’investigation impose de conserver l’artefact, ne laissez pas cette conservation devenir une possibilité de promotion. Maintenez le blocage dans le pipeline et la politique d’admission, limitez les droits d’écriture et documentez une date de réévaluation.

Valider le confinement et préparer le rollback

Le rollback du rollout ne doit jamais signifier « remettre le digest suspect ». Préparez deux chemins : revenir vers un second digest sûr si la version choisie régresse, ou isoler le workload si aucune image saine ne fonctionne avec l’état courant.

Clôturez seulement lorsque le digest suspect n’est plus exécuté, aucune source de vérité ne le référence, une tentative de promotion est refusée, le digest de remplacement est observé dans chaque cluster, les probes restent conformes et la décision de conservation ou suppression est tracée.

Après suppression, testez un pull contrôlé du digest suspect depuis un environnement sans cache : il doit échouer. Testez ensuite un rescheduling du canary sain sur un nœud qui ne possède pas déjà ses couches. Cette seconde vérification prouve que le digest de remplacement reste réellement récupérable depuis ACR.

Conclusion

Un finding sur une image conteneur devient exploitable quand il est relié à un digest, aux pods qui l’exécutent et aux contrôleurs capables de le recréer. Le bon ordre est de geler la promotion, inventorier, sélectionner un digest sûr, redéployer par digest, valider le comportement puis décider du sort du manifest suspect.

La décision finale doit prouver trois propriétés différentes : le digest vulnérable ne s’exécute plus, il ne peut plus être promu et le service dispose d’un chemin de retour qui ne réintroduit pas le risque.