📍 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
- 🔝 Retour au pilier : CKS — guide pratique 2026
- Trivy : aquasecurity.github.io/trivy
- Cosign et Sigstore : docs.sigstore.dev/cosign/overview
- Distroless images : github.com/GoogleContainerTools/distroless
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-actionen 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 :
- Builder l’image localement avec
push: false(ouload: true). - Scanner l’image locale ou le tarball avec Trivy.
- 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.
Lien d affiliation. Si vous achetez via ce lien, le blog reçoit une petite commission sans surcoût pour vous.