Aller au contenu
Conteneurs & Orchestration medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Supply Chain Security Kubernetes - Sécuriser la chaîne d'approvisionnement

14 min de lecture

La supply chain security représente 20% du CKS et couvre la réduction de l’empreinte des images, la compréhension de la chaîne d’approvisionnement, la sécurisation des artefacts et l’analyse statique des workloads et images. Ce guide se concentre sur cinq pratiques concrètes : images minimales, scan de vulnérabilités, SBOM, signature d’images et contrôle d’admission.

Ces cinq pratiques couvrent le socle, mais elles doivent s’insérer dans une chaîne plus large incluant le CI/CD, le stockage d’artefacts et les contrôles d’admission.

  • Cluster Kubernetes fonctionnel avec accès cluster-admin
  • Bases Docker/conteneurs (build d’images)
  • kubectl configuré
  • Notions de sécurité (CVE, vulnérabilités)

La chaîne d’approvisionnement d’une image conteneur couvre tout le cycle de vie avant déploiement :

Chaîne d'approvisionnement d'une image conteneur — étapes et contrôles de sécurité

Une attaque supply chain compromet n’importe quel maillon : une dépendance malveillante, un build piraté, une image modifiée en transit, ou une registry non authentifiée.

Règle d’or : ne jamais faire confiance à une image simplement parce qu’elle “fonctionne”. Une image qui fonctionne peut quand même contenir des CVE critiques ou avoir été altérée.

Pourquoi les images légères réduisent la surface d’attaque

Section intitulée « Pourquoi les images légères réduisent la surface d’attaque »

Une image contenant apt, bash, curl et des outils système offre à un attaquant de nombreux leviers s’il parvient à s’exécuter dans le conteneur. Une image distroless ne contient que le runtime et votre binaire.

Type d’imageTailleSurface d’attaqueCas d’usage
ubuntu:22.04~70 MoÉlevée (shell, apt, utils)Développement
alpine:3.19~7 MoModérée (shell BusyBox)Usage général
gcr.io/distroless/static~2 MoMinimale (pas de shell)Go, binaires statiques
gcr.io/distroless/base~20 MoTrès faible (glibc seulement)C, C++, Java
scratch0 MoMinimale côté base image (la sécurité dépend toujours du binaire embarqué)Binaires entièrement statiques

Build multi-stage : compiler sans embarquer les outils

Section intitulée « Build multi-stage : compiler sans embarquer les outils »

Le build multi-stage permet de compiler dans une image “build” complète et de ne copier que le binaire final dans une image minimale :

Dockerfile
# Étape 1 : compilation (image complète)
FROM golang:1.23 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o myapp .
# Étape 2 : image finale minimale (distroless)
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/myapp /myapp
USER nonroot:nonroot
ENTRYPOINT ["/myapp"]
  • PIN les versions : nginx:1.25.3 plutôt que nginx:latest — une mise à jour peut introduire des CVE
  • Utiliser le digest SHA256 pour garantir l’immuabilité : nginx@sha256:abc123...
  • Ne pas installer de debuggers dans les images de production (gdb, strace, tcpdump)
  • Nettoyer le cache dans le même RUN : apt-get install -y curl && rm -rf /var/lib/apt/lists/*
# ✅ Image avec digest fixé (immuable)
FROM nginx@sha256:67f9a4f10d147a6e04629340e6493c9703300ca23a2f7f3aa56fe615d75d31ca
# ❌ Latest non reproductible
FROM nginx:latest

Avant toute chose : scanner vos images pour détecter les CVE (Common Vulnerabilities and Exposures) connues.

Je le privilégie pour son intégration avec Syft, son accent sur EPSS, KEV, risk scoring et OpenVEX, et sa capacité à scanner images, file systems et SBOMs indifféremment.

Fenêtre de terminal
# Installation (lab / poste de test — en production, préférez un binaire versionné et vérifié)
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
# Scanner une image
grype nginx:1.25.3
# Scanner avec seuil de sévérité (fail si CRITICAL détecté)
grype nginx:1.25.3 --fail-on critical
# Format JSON pour CI/CD
grype nginx:1.25.3 -o json > results.json
Fenêtre de terminal
# Scanner une image
trivy image nginx:1.25.3
# Ignorer les CVE non fixées
trivy image --ignore-unfixed nginx:1.25.3
# Format pour CI/CD
trivy image --exit-code 1 --severity CRITICAL nginx:1.25.3

Pour approfondir le scanning et comprendre les scores CVE : Comprendre les CVE, CVSS et EPSS.

Un SBOM (Software Bill of Materials) est l’inventaire exhaustif de tous les composants d’une image : packages OS, bibliothèques, versions, licences. C’est la liste d’ingrédients de votre logiciel.

Fenêtre de terminal
# Générer un SBOM avec Syft
syft nginx:1.25.3 -o cyclonedx-json > nginx-sbom.json
# Utiliser le SBOM pour scanner avec Grype
grype sbom:nginx-sbom.json
# Générer et scanner en une commande
syft nginx:1.25.3 | grype

Voir le guide SBOM complet pour les formats SPDX/CycloneDX et l’intégration CI/CD.

La signature d’images garantit l’authenticité (l’image provient bien du build attendu) et l’intégrité (elle n’a pas été modifiée). Cosign de Sigstore est l’outil standard.

Fenêtre de terminal
# Installation Cosign
curl -LO https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign-linux-amd64 && sudo mv cosign-linux-amd64 /usr/local/bin/cosign
# Générer une paire de clés
cosign generate-key-pair
# → cosign.key (privée), cosign.pub (publique)
# Signer par digest (recommandé — le tag peut être réaffecté)
cosign sign --key cosign.key registry.example.com/myapp@sha256:abc123...
# Signer par tag (acceptable mais moins robuste)
cosign sign --key cosign.key registry.example.com/myapp:1.0.0
# Vérifier la signature
cosign verify --key cosign.pub registry.example.com/myapp:1.0.0

Vérification dans Kubernetes avec ImagePolicyWebhook

Section intitulée « Vérification dans Kubernetes avec ImagePolicyWebhook »

L’ImagePolicyWebhook est un admission controller historique, désactivé par défaut, qui délègue la décision d’autorisation à un backend webhook externe. Il reste documenté et utile pour comprendre les mécanismes de contrôle d’images, mais sur les clusters récents on rencontre davantage des admission webhooks génériques (ValidatingAdmissionWebhook) ou des moteurs de policy comme Kyverno.

audit-policy.yaml
# Configuration du webhook dans kube-apiserver
--enable-admission-plugins=...,ImagePolicyWebhook
--admission-control-config-file=/etc/kubernetes/admission/admission-config.yaml
/etc/kubernetes/admission/admission-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: ImagePolicyWebhook
configuration:
imagePolicy:
kubeConfigFile: /etc/kubernetes/admission/webhook-kubeconfig.yaml
allowTTL: 50
denyTTL: 50
retryBackoff: 500
defaultAllow: false # Bloquer si le webhook est inaccessible

Pour aller plus loin sur la signature : Guide Cosign complet.

En plus de la signature, on peut restreindre Kubernetes pour n’accepter que des images venant de registries approuvées. C’est la voie moderne et recommandée : les controllers de policy comme Kyverno ou Gatekeeper sont activés par défaut et offrent plus de flexibilité qu’ImagePolicyWebhook.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-registries
spec:
validationFailureAction: Enforce
rules:
- name: allowed-registries
match:
any:
- resources:
kinds: ["Pod"]
validate:
message: "Seules les images de registry.example.com sont autorisées"
pattern:
spec:
containers:
- image: "registry.example.com/*"
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
name: allowed-repos
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
repos:
- "registry.example.com/"
- "gcr.io/distroless/"

→ Voir Guide Kyverno et Guide Gatekeeper.

En production et pour le CKS, voici le cycle recommandé :

  1. Build avec une image de base minimale (distroless/alpine) et build multi-stage

  2. Scanner l’image avant le push : grype myapp:1.0.0 --fail-on high

  3. Générer le SBOM et l’attacher à l’image : syft myapp:1.0.0 -o cyclonedx-json

  4. Pinner par digest : référencer l’image par son SHA256 pour garantir l’immuabilité

  5. Signer par digest : cosign sign --key cosign.key registry/myapp@sha256:abc123...

  6. Pousser vers un artifact repository privé et contrôlé (registry interne approuvée)

  7. Vérifier à l’admission : politique Kyverno/Gatekeeper ou ImagePolicyWebhook

SymptômeCause probableSolution
Pod bloqué par ImagePolicyWebhookWebhook inaccessible avec defaultAllow: falseVérifier la disponibilité du webhook
Signature non vérifiéeMauvaise clé publique ou image re-taguéeRe-signer ou utiliser le digest SHA256
CVE CRITICAL non bloquantesSeuil pas configuréAjouter --fail-on critical dans le CI/CD
Images latest en productionConvention de tag permissivePolitique Kyverno pour interdire latest

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

10 questions
8 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  • Images minimales : distroless > alpine > ubuntu, build multi-stage ; scratch réduit l’empreinte base mais la sécurité dépend du binaire embarqué
  • Scanner avant push : Grype (mon choix prod — EPSS, KEV, OpenVEX) ou Trivy (culture écosystème)
  • Le scan ne suffit pas : une image sans CVE peut rester malveillante ou compromise — compléter avec signature et admission
  • SBOM : inventaire exhaustif avec Syft, re-scannable séparément sans rebuild
  • Signature : Cosign, de préférence par digest et keyless en production
  • Contrôle admission : Kyverno/Gatekeeper comme voie moderne ; ImagePolicyWebhook comme mécanisme historique
  • Registries : restreindre aux sources de confiance, préférer un artifact repository interne
  • CI/CD : évitez les installations d’outils à la volée depuis Internet en production

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn