Kubernetes — scan d'images avec Trivy et admission de vulnérabilités
Analyse de vulnérabilités des images conteneur avec Trivy : scan en CI, scan des charges en cluster avec trivy-operator et blocage des images critiques à l'admission.
Analyse des vulnérabilités des images conteneur avec Trivy, en intégration continue et au sein du cluster.
Contexte
Les images conteneur embarquent des bibliothèques système et applicatives dont les CVE s’accumulent entre deux reconstructions. Sans scan systématique, des images vulnérables atteignent la production. Trivy analyse les couches d’image, le système de fichiers et les manifestes ; couplé à un contrôleur d’admission, il bloque le déploiement d’images au-delà d’un seuil de sévérité.
Détection
Scan d’une image avec seuil de sévérité et code de sortie exploitable en CI :
trivy image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed registry.exemple.fr/web:1.4.2
trivy image --format json --output rapport.json registry.exemple.fr/web:1.4.2
jq -r '.Results[].Vulnerabilities[]? | "\(.Severity) \(.VulnerabilityID) \(.PkgName)"' rapport.json | sort | uniq -c
Scan des charges déjà déployées dans le cluster via trivy-operator (rapports VulnerabilityReport) :
kubectl get vulnerabilityreports -A -o wide
kubectl get vulnerabilityreports -A -o json | jq -r '.items[] | "\(.metadata.namespace)/\(.report.artifact.repository) CRIT=\(.report.summary.criticalCount)"' | grep -v 'CRIT=0'
Détection de secrets et de mauvaises configurations dans les manifestes :
trivy fs --scanners secret,misconfig ./deploy/
Durcissement
Intégration du scan bloquant dans le pipeline de build (échec si CVE corrigeable de sévérité élevée) :
scan-image:
stage: test
script:
- trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 "$IMAGE:$TAG"
- trivy config --severity HIGH,CRITICAL --exit-code 1 ./deploy/
Déploiement de trivy-operator pour le scan continu en cluster :
helm install trivy-operator aquasecurity/trivy-operator \
--namespace trivy-system --create-namespace \
--set trivy.severity=HIGH\,CRITICAL \
--set operator.scannerReportTTL=24h
Application d’un fichier .trivyignore versionné pour les CVE acceptées avec justification documentée, plutôt que la désactivation globale du scan :
# CVE-XXXX-YYYY : composant non exposé, exception validée jusqu'au prochain rebuild
CVE-XXXX-YYYY
Politique d’admission bloquant les images non scannées ou critiques, via les rapports trivy-operator interrogés par une policy (Kyverno) :
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: block-critical-cve
spec:
validationFailureAction: Enforce
rules:
- name: require-clean-scan
match:
any:
- resources:
kinds: [Pod]
context:
- name: report
apiCall:
urlPath: "/apis/aquasecurity.github.io/v1alpha1/namespaces/{{request.namespace}}/vulnerabilityreports"
validate:
message: "Image avec CVE critiques non autorisee"
deny:
conditions:
any:
- key: "{{ report.items[].report.summary.criticalCount || `0` }}"
operator: GreaterThan
value: 0
Vérification
Confirmation que le scan bloque une image volontairement vulnérable et passe sur une image saine :
trivy image --severity CRITICAL --exit-code 1 --ignore-unfixed registry.exemple.fr/web:1.4.2; echo "code=$?"
Vérification de l’absence de rapports critiques en cluster :
kubectl get vulnerabilityreports -A -o json | jq '[.items[].report.summary.criticalCount] | add'
Un code de sortie non nul sur l’image vulnérable et une somme de criticalCount à 0 en cluster confirment la chaîne de contrôle.
Vous avez un projet sur ces sujets ?
Nous contacter →