CKS - Supply Chain Security
🎯 Objectifs
Tu vas sécuriser le cycle complet de tes images :
- ✅ Signer les images avec cosign
- ✅ Vérifier les signatures au déploiement
- ✅ Implémenter des image policies dans le cluster
- ✅ Utiliser les admission controllers pour valider les images
- ✅ Scanner les images pour les vulnerabilités
- ✅ Gérer les registries privées de manière sécurisée
🖼️ Image Scanning
Pourquoi ?
Une image peut contenir des milliers de dépendances. Certaines ont des vulnerabilités connues. Le scanning détecte les CVEs (Common Vulnerabilities and Exposures).
Outils populaires
Trivy (Aqua Security) : fast, complet, gratuit
# Scanner une image locale
trivy image myapp:latest
# Résultat : liste des vulnerabilités par sévérité
# CRITICAL, HIGH, MEDIUM, LOW, UNKNOWNÀ faire :
- Installe trivy :
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin - Scanne une image publique :
trivy image alpine:latest - Note les CRITICAL vulnerabilities
✍️ Image Signing avec Cosign
Pourquoi ?
Tu peux modifier une image à tout moment. Comment sais-tu que l'image que tu déploies est vraiment celle que tu as testée ?
cosign : outil pour signer cryptographiquement les images (par Sigstore/Linux Foundation).
Workflow
1. Tu builds ton image
2. Tu la signes avec cosign : signature attestée avec clé privée
3. Tu la pushes au registry
4. Au déploiement : Kubernetes vérifie la signature avec la clé publique
5. Si invalide : REJET du déploiementInstallation et setup
# Installe cosign
curl -L https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 -o cosign
chmod +x cosign
# Génère une paire de clés (interactive)
./cosign generate-key-pair
# Résultat : cosign.key (privé) et cosign.pub (public)
# Stocke-les en sécurité!Signer une image
# Build et push ton image
docker build -t myregistry.azurecr.io/myapp:v1.0.0 .
docker push myregistry.azurecr.io/myapp:v1.0.0
# Signe l'image
./cosign sign --key cosign.key myregistry.azurecr.io/myapp:v1.0.0
# L'outil demande la passphrase de ta clé privéeVérifier la signature
./cosign verify --key cosign.pub myregistry.azurecr.io/myapp:v1.0.0
# Output : métadonnées de signature si OK
# Error si signature invalideÀ faire :
- Génère une paire de clés cosign
- Signe une image publique (tu peux bricoler!)
- Vérifie avec la clé publique
🔐 Image Policies avec Admission Controllers
Pourquoi ?
Tu peux interdire au cluster de déployer des images non-signées, non-scannées, ou depuis un registry non-approuvé.
Kyverno : Policy Engine pour Kubernetes
Kyverno : admission controller qui valide les images (et bien plus).
# Installe Kyverno
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno --namespace kyverno --create-namespaceExemple : Politique "Image doit être signée"
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-signed-images
spec:
validationFailureAction: enforce # Rejette les violations (enforce) ou log seulement (audit)
rules:
- name: check-image-signature
match:
resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "*.azurecr.io/*" # Toutes les images de ce registry
attestors:
- count: 1
entries:
- keys:
publicKeys: |
-----BEGIN PUBLIC KEY-----
<ta-clé-publique-cosign>
-----END PUBLIC KEY-----
signatureAlgorithm: sha256Exemple : Politique "Image depuis registry approuvé uniquement"
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: allowed-registries
spec:
validationFailureAction: enforce
rules:
- name: validate-registry
match:
resources:
kinds:
- Pod
validate:
message: "Only images from myregistry.azurecr.io are allowed"
pattern:
spec:
containers:
- image: "myregistry.azurecr.io/*"À faire :
- Installe Kyverno
- Crée une policy restrictive sur les registries
- Essaie de déployer depuis docker.io (devrait échouer)
- Essaie de déployer depuis ton registry (succès)
🛡️ Registries Privées et Pull Secrets
Pourquoi ?
Tu ne veux pas que n'importe qui puisse pull tes images privées.
Authentification basique
# Crée un secret pour l'authentification
kubectl create secret docker-registry myregistry \
--docker-server=myregistry.azurecr.io \
--docker-username=<username> \
--docker-password=<token> \
--docker-email=admin@company.comUtiliser le secret dans un Pod
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
imagePullSecrets:
- name: myregistry
containers:
- name: app
image: myregistry.azurecr.io/private-app:latestConfiguration avancée
# Authentification par certificat client TLS
kubectl create secret tls registry-client-cert \
--cert=client-cert.crt \
--key=client-key.keyÀ faire :
- Crée un secret registry privé
- Déploie un pod avec ce secret
- Essaie sans le secret (ImagePullBackOff)
- Ajoute le secret (succès)
📊 Supply Chain Example : De la source au déploiement
1. Développeur push le code → GitHub
2. CI pipeline (GitHub Actions)
- Build image
- Scanner avec Trivy
- Signe l'image avec cosign
- Push vers registry privé
3. GitOps (ArgoCD) détecte le commit
4. Kyverno vérifie la signature
5. Pod est déployé seulement si signature valide + pas de CVE CRITICAL
6. Audit logs enregistrent qui a pushé quoi📝 Checklist Supply Chain Security
- Image scanning : Trivy intégré au CI/CD
- Image signing : cosign configuré avec clé privée sécurisée
- Image verification : admission controller valide les signatures
- Registry policies : Kyverno enforce les registries approuvées
- Pull secrets : authentification configurée pour registries privées
- Audit : chaque déploiement est loggé
- Rotation : clés de signature rotées régulièrement
- SBOM : Software Bill of Materials généré et stocké