infra / docker
Sécurité de la chaîne d'approvisionnement : SBOM et signature
Explication
Ce que vous allez apprendre
- Générer un SBOM (inventaire exhaustif des composants d'une image) avec
syft - Comprendre pourquoi la chaîne d'approvisionnement d'une image est aussi forte que son maillon le plus faible
- Signer une image avec
cosignpour prouver son origine et son intégrité - Distinguer la signature classique par clé de la signature "keyless" basée sur une identité OIDC
- Comprendre comment un cluster de production peut vérifier automatiquement signature et SBOM avant déploiement
Dans quel contexte ?
Une faille critique est annoncée sur une version précise d'OpenSSL. L'équipe sécurité doit déterminer en urgence lesquelles, parmi des dizaines d'images en production, embarquent cette version vulnérable. Sans SBOM généré à l'avance, il faudrait ouvrir chaque image une par une pour vérifier. Avec un SBOM déjà attaché à chaque image via cosign attach sbom, un simple grep sur les fichiers SPDX déjà générés répond à la question en quelques secondes pour l'ensemble du parc.
Au-delà du scan : savoir précisément ce qui compose une image
La leçon sur la sécurité des conteneurs a introduit le scan de vulnérabilités, qui compare le contenu d'une image à une base de failles connues. Mais pour réagir vite lorsqu'une nouvelle faille critique est annoncée sur UNE dépendance précise (par exemple une version particulière d'OpenSSL), il faut d'abord savoir avec certitude quelles versions exactes de quels composants une image contient. C'est le rôle du SBOM (Software Bill of Materials, littéralement "nomenclature logicielle") : un inventaire exhaustif et structuré de tout ce qui compose une image, un peu comme la liste des ingrédients sur un emballage alimentaire.
| Outil | Répond à la question |
|---|---|
SBOM (syft) | Qu'est-ce qu'il y a exactement dans cette image ? |
Scan de vulnérabilités (grype, trivy) | Ces composants ont-ils des failles connues ? |
Signature (cosign) | Cette image vient-elle vraiment de la source annoncée ? |
Prérequis
Cette leçon suppose que tu es à l'aise avec le scan de vulnérabilités (trivy) vu dans la leçon sur la sécurité des conteneurs : le SBOM et la signature vont plus loin, en amont du scan lui-même.
La chaîne d'approvisionnement : un maillon faible peut suffire
Une image finale dépend d'une longue chaîne : l'image de base choisie, les paquets système installés, les dépendances applicatives téléchargées, et le pipeline qui a construit et publié l'image elle-même. Un attaquant n'a besoin de compromettre qu'un SEUL maillon de cette chaîne (une dépendance piégée, un registre compromis, un pipeline CI infiltré) pour affecter l'image finale, même si le code de l'application elle-même est irréprochable.
Prouver l'origine avec la signature
Un SBOM répond à "qu'est-ce qu'il y a dedans ?", mais pas à "cette image vient-elle vraiment de l'endroit annoncé, et n'a-t-elle pas été altérée depuis ?". C'est le rôle de la signature cryptographique (avec un outil comme cosign) : elle prouve à la fois l'identité de qui a publié l'image et garantit qu'aucun octet n'a été modifié depuis la signature. Le mode "keyless", basé sur l'identité d'un compte plutôt que sur une clé privée à protéger et à ne jamais perdre, simplifie considérablement la gestion par rapport à une signature classique par clé.
La confiance, vérifiée automatiquement
L'objectif final de ces mécanismes est de permettre à un cluster de production de vérifier automatiquement, avant même d'accepter de déployer une image, qu'elle est bien signée par une source de confiance et accompagnée d'un SBOM à jour — une vérification qu'aucun humain ne pourrait raisonnablement faire manuellement à chaque déploiement.
Commandes & code
Sécurité de la chaîne d'approvisionnement : SBOM et signature
# La "supply chain" d'une image Docker = tout ce qui la compose : image de base, paquets
# système, dépendances applicatives, ET le pipeline qui l'a construite et publiée.
# Un attaquant qui compromet UN maillon (dépendance, registre, pipeline CI) compromet l'image finale.# --- SBOM (Software Bill of Materials) : inventaire exhaustif du contenu d'une image ---
docker sbom mon-api:1.0 # intégré à Docker Desktop/CLI récent (via syft)
syft mon-api:1.0 -o table # même outil en standalone, plus de formats de sortie
syft mon-api:1.0 -o spdx-json > sbom.spdx.json # format SPDX, standard industrie
syft mon-api:1.0 -o cyclonedx-json > sbom.cdx.json # format CycloneDX, autre standard répandu
# Un SBOM répond à : "quelle version EXACTE de openssl/libc/requests tourne dans cette image ?"
# -> indispensable pour réagir vite à une CVE annoncée sur UNE dépendance précise
grep -i "openssl" sbom.spdx.json | head -5
# --- Croiser un SBOM avec une base de vulnérabilités ---
grype sbom:sbom.spdx.json # scanne un SBOM déjà généré (rapide, pas de re-pull)
grype mon-api:1.0 # ou directement sur l'image# --- Signature d'image avec cosign (Sigstore) : prouve QUI a publié l'image, et qu'elle n'a pas changé ---
cosign generate-key-pair # génère cosign.key (privée) et cosign.pub (publique)
cosign sign --key cosign.key registry.exemple.com/equipe/mon-api:1.0
# La signature est stockée dans le REGISTRE lui-même, à côté de l'image (pas de service externe requis)
# Vérifier une signature avant de déployer (à intégrer dans un admission controller en prod)
cosign verify --key cosign.pub registry.exemple.com/equipe/mon-api:1.0
# --- Signature "keyless" (recommandée) : identité liée à un compte OIDC (GitHub Actions, Google...) ---
cosign sign registry.exemple.com/equipe/mon-api:1.0 # ouvre un flux OIDC, pas de clé à gérer/stocker
cosign verify --certificate-identity-regexp ".*@exemple\.com" \
--certificate-oidc-issuer https://accounts.google.com \
registry.exemple.com/equipe/mon-api:1.0# --- Intégration CI : signer automatiquement chaque image publiée depuis main ---
sign:
stage: push
script:
- cosign sign --key "$COSIGN_KEY" $IMAGE:$CI_COMMIT_SHORT_SHA
- syft $IMAGE:$CI_COMMIT_SHORT_SHA -o spdx-json > sbom.json
- cosign attach sbom --sbom sbom.json $IMAGE:$CI_COMMIT_SHORT_SHA
only: [main]# --- Attestations : lier un SBOM ou un rapport de scan directement à l'image, de façon vérifiable ---
cosign attest --key cosign.key --predicate sbom.json --type spdxjson \
registry.exemple.com/equipe/mon-api:1.0
cosign verify-attestation --key cosign.pub --type spdxjson \
registry.exemple.com/equipe/mon-api:1.0
# --- Provenance de build (SLSA) : prouve QUEL pipeline CI, avec QUEL commit, a produit l'image ---
# Généré automatiquement par certaines plateformes CI (GitHub Actions avec l'action officielle,
# GitLab avec le SLSA provenance generator) -> répond à "cette image vient-elle VRAIMENT de mon repo ?"
# --- Bloquer un déploiement si l'image n'est pas signée (politique côté cluster) ---
# Kubernetes : un admission controller (ex: Kyverno, Sigstore Policy Controller) refuse
# tout Pod dont l'image n'a pas de signature cosign valide avant même sa créationRésumé
- Un SBOM (
syft, formats SPDX/CycloneDX) liste précisément chaque composant d'une image — la base pour réagir vite à une CVE ciblée. cosign sign/verifyprouve l'origine et l'intégrité d'une image ; le mode "keyless" (OIDC) évite de gérer une clé privée à protéger.- Signature + SBOM + attestations forment la chaîne de confiance qu'un cluster peut vérifier avant d'accepter de déployer une image.
Exercices pratiques
Mission : répondre en urgence à une faille critique découverte sur OpenSSL
Objectif : Utiliser un SBOM déjà généré pour identifier rapidement les images affectées, et sécuriser la chaîne de publication avec une signature.
Contexte
Une faille critique est annoncée sur une version précise d'OpenSSL. L'équipe sécurité doit déterminer en urgence lesquelles, parmi des dizaines d'images en production, embarquent cette version vulnérable — sans ouvrir chaque image une par une.