Business Digital

Trivy, Cosign et supply chain security Kubernetes CKS 2026

11 min de lecture

📍 Article principal du cluster : CKS Certified Kubernetes Security Specialist — guide pratique 2026

Ce tutoriel fait partie du cluster certification CKS. Pour la vue d’ensemble, lisez d’abord le pilier.

Introduction

Le domaine 5 « Supply Chain Security » pèse 20 % de l’examen CKS. Il teste votre capacité à sécuriser tout le pipeline qui amène une image conteneur en production : minimisation de l’image de base, scan de vulnérabilités, signature cryptographique, et validation à l’admission. Ce tutoriel pratique Trivy (le scanner de référence en 2026 (informations vérifiées en avril 2026, susceptibles d’évoluer ; vérifier la source officielle avant toute décision technique)), Cosign (signature Sigstore keyless), et l’intégration des deux dans une pipeline CI/CD GitHub Actions ou GitLab CI. Toutes les commandes sont testées sur un cluster kind 1.34.

Prérequis

  • Cluster kind récent avec image de nœud Kubernetes v1.34 (par exemple kindest/node:v1.34.x)
  • Docker installé localement
  • Tutoriels CKS précédents terminés
  • 40 minutes

Étape 1 — Installer Trivy et scanner une première image

Trivy est un scanner open-source d’Aqua Security. Détecte les CVE dans les couches d’images, les secrets accidentels, les misconfigurations Kubernetes, les licences problématiques. Le largement adopté.

curl -fsSL https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor -o /usr/share/keyrings/trivy.gpg
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" > /etc/apt/sources.list.d/trivy.list
apt update && apt install -y trivy
trivy --version

# Scanner nginx classique — beaucoup de CVE attendues
trivy image nginx:1.27 --severity HIGH,CRITICAL | head -30

La sortie liste chaque CVE avec son ID, son score CVSS, le package vulnérable, la version installée, et la version corrigée. Un Une image officielle comme nginx:1.27 affiche en général un certain nombre de CVE résiduelles (le chiffre exact varie avec la date du scan, l’architecture, le tag d’image et la base de vulnérabilités Trivy), principalement dans les libs glibc, openssl, libxml2.

Étape 2 — Comparer images standard vs distroless

Une stratégie clé pour réduire la surface d’attaque : utiliser des images distroless (Google) ou scratch qui ne contiennent que le binaire applicatif et ses dépendances strictement nécessaires.

trivy image --severity HIGH,CRITICAL gcr.io/distroless/python3-debian12 2>&1 | tail -5

trivy image --severity HIGH,CRITICAL python:3.13-slim 2>&1 | tail -5

L’image distroless affiche typiquement 0-3 CVE, alors que python:3.13-slim peut contenir un nombre plus important de CVE résiduelles selon la version Debian sous-jacente et la date du scan. La différence est massive. La règle d’or : pour la production, partez d’un Dockerfile multi-stage qui compile dans une image build complète puis copie le binaire dans une distroless.

Étape 3 — Dockerfile multi-stage avec distroless

Démonstration du pattern recommandé pour réduire drastiquement la surface d’attaque. Application Go simple en exemple.

mkdir -p /tmp/secure-app
cat > /tmp/secure-app/main.go <<'EOF'
package main
import ("fmt"; "net/http")
func main() {
  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello secure world")
  })
  http.ListenAndServe(":8080", nil)
}
EOF

cat > /tmp/secure-app/Dockerfile <<'EOF'
FROM golang:1.23 AS build
WORKDIR /src
COPY main.go .
RUN go mod init app && CGO_ENABLED=0 go build -o /out/app main.go

FROM gcr.io/distroless/static-debian12
COPY --from=build /out/app /app
USER nonroot
EXPOSE 8080
ENTRYPOINT ["/app"]
EOF

docker build -t secure-app:v1 /tmp/secure-app
trivy image secure-app:v1 --severity HIGH,CRITICAL

La nouvelle image affiche typiquement très peu de CVE (mais ce nombre n’est pas garanti — il dépend de la date et des vulnérabilités nouvellement publiées) — l’image distroless ne contient pas de kernel (le kernel est fourni par l’hôte ; les conteneurs partagent le noyau Linux de la machine hôte). Elle contient uniquement le binaire applicatif et les dépendances runtime nécessaires (certaines bibliothèques système, certificats CA selon l’image choisie). C’est exactement la posture recommandée par les benchmarks SLSA et NIST SSDF.

Étape 4 — Trivy en mode Kubernetes — scanner les manifests

Trivy peut scanner non seulement les images mais aussi les manifests Kubernetes pour détecter les misconfigurations (privileged: true, hostNetwork, capabilities excessives).

cat > /tmp/bad-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: dangerous-pod
spec:
  hostPID: true
  hostNetwork: true
  containers:
  - name: app
    image: nginx:1.27
    securityContext:
      privileged: true
      runAsUser: 0
EOF

trivy config /tmp/bad-pod.yaml | head -30

La sortie liste toutes les misconfigurations : hostPID, hostNetwork, privileged, runAsUser=0. Trivy catégorise ces problèmes par sévérité ; selon les règles utilisées, privileged et hostNetwork sont généralement signalés en HIGH (pas CRITICAL). Cette commande tombe directement à l’examen — savoir lire un manifest Kubernetes pour identifier les anti-patterns sécurité.

Étape 5 — Installer Cosign pour la signature d’images

Cosign est l’outil de signature de Sigstore. Permet de signer une image (ou un manifest) avec une clé privée — ou en mode keyless avec un OIDC token (GitHub, Google, GitLab).

curl -L https://github.com/sigstore/cosign/releases/download/v2.5.0/cosign-linux-amd64 -o /usr/local/bin/cosign
chmod +x /usr/local/bin/cosign
cosign version

# Générer une keypair locale
cd /tmp
cosign generate-key-pair  # mot de passe demandé
ls cosign.key cosign.pub

Vous avez maintenant une clé privée (cosign.key, à ne JAMAIS commit) et une clé publique (cosign.pub, à distribuer). En production, on préfère le mode keyless basé sur OIDC pour éviter la gestion manuelle des clés.

Étape 6 — Signer une image et la vérifier

La signature s’attache à l’image via OCI artifact. La vérification consulte le registry pour récupérer la signature et la valider contre la clé publique.

# Tag l'image vers un registry local kind
docker tag secure-app:v1 localhost:5001/secure-app:v1

# Pour un registry interne kind
docker run -d -p 5001:5000 --restart=always --name registry registry:2
docker push localhost:5001/secure-app:v1

# Signer
COSIGN_PASSWORD="" cosign sign --key /tmp/cosign.key localhost:5001/secure-app:v1

# Vérifier
cosign verify --key /tmp/cosign.pub localhost:5001/secure-app:v1

La vérification doit retourner « Verified OK ». Toute modification de l’image après signature invalide cette vérification — c’est ce qui garantit l’intégrité.

Étape 7 — Gatekeeper policy pour exiger des images signées

Couplé à Gatekeeper, cosign devient un outil d’admission : on bloque toute image qui ne fournit pas une signature valide.

# Cosign policy controller installation
kubectl apply -f https://github.com/sigstore/policy-controller/releases/download/v0.13.0/policy-controller.yaml
sleep 30

cat > /tmp/cluster-image-policy.yaml <<'EOF'
apiVersion: policy.sigstore.dev/v1alpha1
kind: ClusterImagePolicy
metadata:
  name: signed-images-only
spec:
  images:
  - glob: "localhost:5001/**"
  authorities:
  - key:
      data: |
        -----BEGIN PUBLIC KEY-----
        # Coller ici le contenu de /tmp/cosign.pub
        -----END PUBLIC KEY-----
EOF

kubectl apply -f /tmp/cluster-image-policy.yaml

Une fois la policy active, tout Pod qui demande une image non-signée est rejeté à l’admission. C’est exactement la posture supply chain end-to-end qu’attend la CKS.

Étape 8 — Pipeline GitHub Actions sécurisée

Pour clôturer le tutoriel, voici un workflow GitHub Actions qui scan + sign automatiquement à chaque commit. C’est le pattern standard 2026.

name: secure-build
on: push

jobs:
  build:
    runs-on: ubuntu-24.04
    permissions:
      contents: read
      id-token: write
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/build-push-action@v6
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
      - uses: aquasecurity/trivy-action@0.35.0  # ou pinner par commit SHA — voir incident sécurité mars 2026
        with:
          image-ref: ghcr.io/${{ github.repository }}:${{ github.sha }}
          severity: HIGH,CRITICAL
          exit-code: 1
      - uses: sigstore/cosign-installer@v4
      - run: cosign sign --yes ghcr.io/${{ github.repository }}:${{ github.sha }}

Ce workflow refuse de pousser une image avec des CVE HIGH/CRITICAL non patchées (`exit-code: 1`), et signe en keyless via le token OIDC GitHub. C’est la posture de référence en 2026 chez les pure players cloud.

Comprendre la différence keyless vs keyed signing

Cosign supporte deux modes. Keyed : vous générez une keypair, signez avec la privée, vérifiez avec la publique. Simple mais demande une gestion sécurisée de la clé privée. Keyless : pas de clé persistante. Cosign utilise un OIDC token (GitHub Actions, Google Cloud, GitLab) pour s’identifier auprès de Sigstore Fulcio qui émet un certificat éphémère valide quelques minutes. La signature est attachée à cette identité OIDC. Avantages : aucune clé à protéger, audit centralisé via Sigstore Rekor (transparency log).

Pour la CKS v1.34, attendez-vous à des questions sur les deux modes. Le keyless est de plus en plus la norme pour les workflows CI/CD modernes.

Erreurs fréquentes

Erreur Cause Solution
Trivy scan trop lent Cache vulnerability DB pas à jour `trivy image –download-db-only` une fois par jour en CI
Distroless image refuse de démarrer Binaire pas statiquement compilé `CGO_ENABLED=0 go build` ou Dockerfile multi-stage avec scratch
Cosign verify fail Mauvaise clé publique ou registry inaccessible Vérifier que cosign.pub correspond à la clé qui a signé
ClusterImagePolicy ignorée policy-controller pas démarré `kubectl get pods -n cosign-system` doit lister policy-controller en Running
Trivy false positive CVE déjà patchée mais base de données obsolète `.trivyignore` pour les CVE acceptées avec justification documentée

Spécificités ouest-africaines à connaître

Pour les startups dakaroises et abidjanaises qui montent leur premier pipeline CI/CD sécurisé, le combo Trivy + Cosign keyless est gratuit et opérationnel en quelques heures. GitHub Actions est gratuit jusqu’à 2 000 minutes/mois pour les comptes individuels — largement suffisant pour 5-10 services applicatifs en CI. Pour les équipes plus matures qui ont besoin d’un registry privé, Harbor self-hosté sur Hostinger Cloud Startup à 9,99 USD/mois fait le travail. L’investissement total pour atteindre une supply chain conforme aux bonnes pratiques industrielles : moins de 30 USD/mois.

Tutoriels frères

Pour explorer plus loin

FAQ

Trivy ou Grype, lequel choisir ?
Les deux scanners sont valides. Trivy est dans le syllabus officiel CKS et c’est le standard de l’industrie. Grype (Anchore) est une alternative open-source rapide.

Cosign keyless est-il sécurisé sans clé persistante ?
Oui, parce que la chaîne de confiance se déplace vers le provider OIDC (GitHub, Google) et le transparency log Sigstore Rekor. Toutes les signatures sont publiquement auditables.

Mots-clés secondaires : trivy cks, cosign sigstore, image signing kubernetes, distroless dockerfile, supply chain security, sbom kubernetes

Notes de version vérifiées — avril 2026

  • CKS est actuellement basé sur Kubernetes v1.34 selon la Linux Foundation. Le domaine « Supply Chain Security » représente 20 % de l’examen.
  • Kubernetes 1.34 est en série active (patch 1.34.6 publié le 19 mars 2026).
  • Trivy Action : utiliser une version 0.35.0 minimum, ou pinner par commit SHA vérifié. Un incident de sécurité a touché certaines versions/tags de aquasecurity/trivy-action en mars 2026 — éviter les tags mutables en production.
  • Cosign : pour Cosign v3, utiliser sigstore/cosign-installer@v4. La v3.x du installer ne peut pas installer Cosign v3.x.
  • Distroless : ne contient pas de kernel (les conteneurs partagent le kernel de l’hôte). Contient uniquement le binaire applicatif et ses dépendances runtime.
  • Nombres de CVE : les chiffres affichés dans ce tutoriel sont indicatifs. Ils varient selon la date du scan, l’architecture, le tag exact, la base de données Trivy et les vulnérabilités nouvellement publiées. Toujours rescanner au moment de la mise en production.

Policy controller Sigstore — opt-in par namespace

Une fois le policy-controller installé, il faut opter explicitement chaque namespace à valider, via un label :

kubectl label namespace default policy.sigstore.dev/include=true
kubectl label namespace my-secure-namespace policy.sigstore.dev/include=true

Sans ce label, la ClusterImagePolicy ne s’applique pas au namespace ciblé et les Pods non signés ne seront pas rejetés.

Workflow GitHub Actions : scanner avant de pousser

Précision importante. Si le workflow utilise docker/build-push-action@v6 avec push: true puis lance Trivy après, l’image est déjà publiée au moment du scan. Le workflow ne « refuse pas le push » — il échoue après publication, ce qui laisse une image potentiellement vulnérable accessible.

Pour réellement bloquer le push avant publication :

  1. Builder l’image localement avec push: false (ou load: true).
  2. Scanner l’image locale ou le tarball avec Trivy.
  3. Ne pousser qu’après validation du scan (étape conditionnelle).

Pour appliquer ce tutoriel sur un vrai serveur

Hostinger reste l’option la plus simple pour démarrer. Lien partenaire — votre achat soutient le blog sans surcoût.

Réserver un VPS Hostinger →

Lien d affiliation. Si vous achetez via ce lien, le blog reçoit une petite commission sans surcoût pour vous.

Partager