Vos conteneurs tournent en production, mais sont-ils vraiment sécurisés ? Ce guide vous explique les risques spécifiques aux conteneurs et comment les mitiger à chaque étape : build, deploy et runtime. Vous apprendrez à scanner vos images, durcir vos configurations Kubernetes et détecter les comportements anormaux. Résultat : une stratégie de sécurité conteneurs complète, de la CI/CD à la production.
Pourquoi les conteneurs sont-ils une cible ?
Section intitulée « Pourquoi les conteneurs sont-ils une cible ? »Les conteneurs ont révolutionné le déploiement d'applications, mais ils introduisent des surfaces d'attaque spécifiques que les approches de sécurité traditionnelles ne couvrent pas.
Le problème fondamental : les conteneurs partagent le noyau de l'hôte. Contrairement à une VM qui a son propre kernel, un conteneur n'est qu'un processus isolé. Si un attaquant exploite une vulnérabilité kernel depuis un conteneur, il peut potentiellement compromettre tout le nœud, et par extension, tous les autres conteneurs qui y tournent.
Les 5 surfaces d'attaque principales
Section intitulée « Les 5 surfaces d'attaque principales »Comprendre où se situent les risques est la première étape pour les mitiger. Les conteneurs présentent des vulnérabilités à plusieurs niveaux :
| Surface d'attaque | Risque | Exemple concret |
|---|---|---|
| Images vulnérables | CVE dans les dépendances, base image obsolète | Log4Shell présent dans une image Java non mise à jour |
| Configurations permissives | Conteneurs root, capabilities excessives | Un conteneur avec CAP_SYS_ADMIN peut modifier le système hôte |
| Secrets exposés | Variables d'environnement en clair, ConfigMaps accessibles | Mot de passe BDD visible via kubectl describe pod |
| Réseau ouvert | Absence de Network Policies, trafic est-ouest libre | Un pod compromis peut scanner tout le cluster |
| Supply chain | Images tierces non vérifiées, registres publics | Image Docker Hub contenant un cryptominer caché |
Ces risques ne sont pas théoriques. En analysant 250 000 images publiques de Docker Hub, les chercheurs de Sysdig en ont identifié 1 652 malveillantes : cryptomineurs, secrets embarqués utilisables comme portes dérobées, détournements DNS. Une image tirée d'un registre public n'est pas auditée par quiconque avant d'atterrir sur vos nœuds.
Qui doit sécuriser quoi ?
Section intitulée « Qui doit sécuriser quoi ? »La sécurité des conteneurs est une responsabilité partagée. Chaque profil a un rôle spécifique, et la collaboration est essentielle pour couvrir toutes les surfaces d'attaque.
| Profil | Responsabilité principale | Actions concrètes |
|---|---|---|
| Développeur | Construire des images sécurisées | Utiliser des images de base minimales, ne pas embarquer de secrets, définir un USER non-root |
| Ops / SRE | Durcir l'infrastructure | Appliquer les Pod Security Standards, configurer les Network Policies, gérer les mises à jour |
| DevSecOps | Automatiser les contrôles | Intégrer Trivy dans la CI, bloquer les déploiements non conformes, alerter sur les dérives |
| RSSI / Compliance | Garantir la conformité | Auditer selon CIS Benchmarks, documenter les exceptions, préparer les certifications |
La stratégie de défense en profondeur
Section intitulée « La stratégie de défense en profondeur »La sécurité des conteneurs ne repose pas sur un seul outil ou une seule étape. Elle s'articule autour de trois phases qui se complètent : Build, Deploy et Runtime. Si une couche échoue, les autres limitent l'impact.
Phase 1 : Build, sécuriser les images
Section intitulée « Phase 1 : Build, sécuriser les images »C'est le moment le plus efficace pour détecter les problèmes. Une image vulnérable ne devrait jamais atteindre la production.
Bonnes pratiques :
-
Images de base minimales : Préférez
distrolessoualpineàubuntu. Moins de paquets = moins de CVE potentielles. Sur une machine de test,gcr.io/distroless/python3-debian12pèse 80 Mo là oùpython:3.11en pèse 1,6 Go : tout ce qui disparaît (shell, gestionnaire de paquets, compilateurs) est autant de surface d'attaque et de CVE en moins à traiter. -
Scanner systématiquement : Intégrez un scanner (Trivy, Grype) dans votre CI. Bloquez le pipeline si une CVE critique est détectée.
-
Ne jamais tourner en root : Ajoutez
USER 1000dans votre Dockerfile. Un conteneur root compromis peut modifier l'hôte. -
Signer vos images : Utilisez Cosign pour prouver l'origine et l'intégrité de vos images. Le cluster peut refuser les images non signées.
Le multi-stage build ci-dessous compile les dépendances dans une image complète, puis ne recopie que le résultat dans une image distroless qui ne contient ni shell ni pip. Le point qui fait échouer la plupart des tentatives : pip install écrit dans site-packages, pas dans /app. Sans --target et sans PYTHONPATH, l'image se construit sans erreur mais l'application meurt au démarrage sur un ModuleNotFoundError.
# Exemple de Dockerfile sécuriséFROM python:3.11-slim AS builderWORKDIR /appCOPY requirements.txt .RUN pip install --no-cache-dir --target=/app/deps -r requirements.txt
FROM gcr.io/distroless/python3-debian12:latest@sha256:2fdb05402a2cf21cf78fdb3ba4c5db167241e9e498140f5bf689d7efb773731fWORKDIR /appENV PYTHONPATH=/app/depsCOPY --from=builder /app/deps /app/depsCOPY app.py .USER 1000CMD ["app.py"]Vérifiez toujours l'image finale en l'exécutant réellement (docker run --rm mon-image) : un docker build qui réussit ne prouve rien sur la présence des dépendances.
Phase 2 : Deploy, durcir les configurations
Section intitulée « Phase 2 : Deploy, durcir les configurations »Même une image sécurisée peut être déployée de manière dangereuse. Kubernetes offre de nombreuses options de sécurité, mais elles sont souvent désactivées par défaut.
Bonnes pratiques :
- Pod Security Standards : Appliquez le niveau
restricted(ou au minimumbaseline) sur vos namespaces. Cela interdit les conteneurs root, les capabilities dangereuses et les montages de volumes sensibles.
apiVersion: v1kind: Namespacemetadata: name: production labels: pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/warn: restricted- Network Policies : Par défaut, tous les pods peuvent communiquer entre eux. Définissez des règles explicites pour n'autoriser que le trafic nécessaire.
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: deny-all-ingress namespace: productionspec: podSelector: {} policyTypes: - Ingress-
ResourceQuota et LimitRange : Empêchez un pod compromis de consommer toutes les ressources du nœud (déni de service).
-
RBAC strict : Appliquez le principe du moindre privilège. Un ServiceAccount ne devrait avoir que les permissions strictement nécessaires.
Phase 3 : Runtime, détecter et bloquer
Section intitulée « Phase 3 : Runtime, détecter et bloquer »Les phases Build et Deploy ne suffisent pas. De nouvelles CVE sont découvertes quotidiennement, et un attaquant peut exploiter une faille zero-day. La protection runtime surveille les conteneurs en cours d'exécution.
Ce que surveille une solution runtime :
| Signal | Ce qu'il détecte | Outil |
|---|---|---|
| Syscalls anormaux | Exécution de shell dans un conteneur, modification de fichiers système | Falco |
| Connexions réseau | Trafic vers des IPs suspectes, scan de ports | NeuVector, Cilium |
| Processus inattendus | Cryptominer, reverse shell | Falco, Sysdig |
| Dérive de configuration | Modification des fichiers par rapport à l'image d'origine | NeuVector |
Scénario : intégrer la sécurité dans votre pipeline
Section intitulée « Scénario : intégrer la sécurité dans votre pipeline »Voyons comment une équipe DevSecOps intègre ces trois phases dans un pipeline CI/CD réel. L'objectif : qu'aucune image vulnérable ou mal configurée n'atteigne la production.
-
Build : scanner l'image
Dans la CI (GitLab CI, GitHub Actions, Jenkins), Trivy analyse l'image après le build. Si une CVE critique (score CVSS ≥ 9) est détectée, le pipeline échoue.
.gitlab-ci.yml scan-image:stage: testscript:- trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -
Registry : signer l'image
Avant de pousser l'image vers le registre, elle est signée avec Cosign. La signature prouve qu'elle vient bien de votre CI et n'a pas été modifiée.
Fenêtre de terminal cosign sign --key cosign.key $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -
Admission : valider les manifests
Au moment du déploiement, un admission controller (Kyverno, OPA Gatekeeper) vérifie que les manifests respectent les politiques de sécurité : pas de conteneur root, ressources définies, etc.
# ValidatingPolicy Kyverno : interdire les conteneurs rootapiVersion: policies.kyverno.io/v1kind: ValidatingPolicymetadata:name: require-non-rootspec:validationActions: [Deny]matchConstraints:resourceRules:- apiGroups: [""]apiVersions: ["v1"]operations: ["CREATE", "UPDATE"]resources: ["pods"]validations:- expression: >-object.spec.containers.all(c,has(c.securityContext) &&has(c.securityContext.runAsNonRoot) &&c.securityContext.runAsNonRoot == true)message: "Les conteneurs doivent tourner en non-root (runAsNonRoot: true)." -
Runtime : surveiller en production
NeuVector ou Falco surveille les conteneurs déployés. Une alerte est déclenchée si un comportement anormal est détecté (shell interactif, connexion sortante suspecte).
Résultat : une vulnérabilité Log4Shell est détectée dans une dépendance Java lors du scan CI. Le pipeline échoue, le développeur est notifié, et l'image n'atteint jamais la production. Temps de détection : 45 secondes au lieu de plusieurs jours (ou jamais) sans scan.
Pièges courants à éviter
Section intitulée « Pièges courants à éviter »Même avec les bons outils, certaines erreurs reviennent fréquemment. Voici les pièges les plus courants et comment les éviter :
Outils recommandés
Section intitulée « Outils recommandés »Chaque phase a sa famille d'outils, et un outil de la phase Build ne remplace jamais un outil de la phase Runtime. Les trois tableaux qui suivent se lisent par la colonne Quand l'utiliser : elle indique le contexte de déclenchement, pas une préférence de qualité. Deux outils de la même ligne ne se cumulent pas, ils se remplacent.
Scanner de vulnérabilités
Section intitulée « Scanner de vulnérabilités »Un scanner de vulnérabilités compare les paquets présents dans une image aux bases de CVE publiques. Son résultat dépend donc entièrement de la fraîcheur de sa base : un scan lancé sur une image inchangée peut remonter dix vulnérabilités de plus qu'hier. Regardez surtout la colonne Forces pour savoir si l'outil couvre autre chose que les images (dépôts Git, manifests IaC), car c'est ce qui décide si vous en installez un seul ou plusieurs.
| Outil | Forces | Quand l'utiliser |
|---|---|---|
| Trivy | Rapide, gratuit, multi-cibles (images, repos, IaC) | Premier choix pour la CI/CD |
| Grype | Léger, intégration Anchore | Alternative à Trivy |
| Snyk | Base de données CVE enrichie, remédiation guidée | Si vous avez un budget sécurité |
Conformité et audit
Section intitulée « Conformité et audit »Ces outils ne cherchent pas de CVE : ils comparent la configuration réelle de votre cluster à un référentiel (CIS Benchmark, recommandations NSA). Ils répondent à la question « ma configuration est-elle conforme », pas « mes images sont-elles vulnérables ». Choisissez selon le référentiel que votre organisation doit prouver, car c'est ce référentiel qui sera exigé lors d'un audit externe.
| Outil | Forces | Quand l'utiliser |
|---|---|---|
| Kubescape | CIS Benchmarks, NSA guidelines, gratuit | Audit initial et continu |
| kube-bench | CIS Kubernetes Benchmark officiel | Audit de conformité formel |
| Polaris | Best practices Kubernetes, simple | Premiers pas en sécurité K8s |
Protection runtime
Section intitulée « Protection runtime »La protection runtime observe les appels système et le trafic des conteneurs déjà démarrés. Contrairement aux deux familles précédentes, elle produit des alertes en continu et non un rapport ponctuel : prévoyez qui les reçoit et qui y répond avant de la déployer. Un outil runtime installé sans destinataire d'alerte ne protège personne.
| Outil | Forces | Quand l'utiliser |
|---|---|---|
| Falco | Open source, basé sur eBPF/syscalls | Détection d'intrusion |
| NeuVector | Protection complète (réseau + runtime), pare-feu L7 | Sécurité enterprise |
| Sysdig Secure | Observabilité + sécurité intégrées | Si vous utilisez déjà Sysdig |
Guides détaillés
Section intitulée « Guides détaillés »Les pages ci-dessous reprennent chacun de ces outils en mode pratique : installation, première exécution et lecture du rapport. Si vous partez de zéro, commencez par Trivy (un scan d'image se lance en une commande et donne un résultat immédiat), puis Kubescape pour mesurer l'écart de votre cluster aux CIS Benchmarks. NeuVector et Cosign supposent un cluster déjà en place et une chaîne de build maîtrisée.
À retenir
Section intitulée « À retenir »-
Les conteneurs partagent le kernel : une vulnérabilité exploitée peut compromettre tout le nœud, pas juste le conteneur.
-
Défense en profondeur : Build (scan d'images) + Deploy (durcissement K8s) + Runtime (détection) = trois couches qui se complètent.
-
Shift-left : détectez les problèmes dans la CI, pas en production. Un scan prend 30 secondes, une remédiation d'incident prend des jours.
-
Pod Security Standards : appliquez au minimum le niveau
baseline, visezrestricteden production. -
Network Policies obligatoires : sans elles, le trafic est-ouest est grand ouvert. Un pod compromis peut attaquer tout le cluster.
-
Scan continu : les CVE sont découvertes quotidiennement. Scannez aussi les images déjà déployées.
Checklist sécurité conteneurs
Section intitulée « Checklist sécurité conteneurs »Cette checklist sert de revue avant une mise en production, pas de liste de courses à cocher d'un bloc. Traitez-la dans l'ordre Build, Deploy, Runtime : chaque bloc suppose le précédent acquis. Une case laissée vide n'est pas forcément un blocage, mais elle doit être une exception documentée, avec un nom en face.
Ce bloc se joue entièrement dans le dépôt et dans la CI, avant qu'aucune image n'atteigne un registre. C'est le moment le moins coûteux : une correction ici est un commit, la même correction en production est un incident. Le point le plus souvent oublié reste la signature des images, parce qu'elle demande de gérer une clé.
- Images de base minimales (distroless, alpine)
- Scanner intégré dans la CI (Trivy, Grype)
- Pipeline bloqué si CVE critique détectée
- Pas de secrets dans les images
- Dockerfile avec
USERnon-root - Images signées (Cosign)
Ces contrôles se posent sur le namespace et sur le cluster, pas sur l'image. Ils protègent même contre une image que vous n'avez pas construite, ce qui en fait le dernier filet quand une dépendance tierce arrive dans votre chaîne. Vérifiez chaque case sur un namespace réel : un label Pod Security mal orthographié est ignoré silencieusement par l'API server, sans le moindre message d'erreur.
- Pod Security Standards appliqués (baseline ou restricted)
- Network Policies définies (deny by default)
- RBAC avec moindre privilège
- ResourceQuota et LimitRange configurés
- Secrets dans des Secret K8s (pas en variables d'environnement)
Le bloc runtime est celui qui se dégrade le plus vite : un agent déployé une fois et jamais relu finit par alerter dans le vide. Les deux cases qui comptent réellement sont la destination des alertes et la procédure de réponse, car un détecteur sans destinataire ne change rien au délai de réaction.
- Outil de détection déployé (Falco, NeuVector)
- Alertes configurées pour les comportements anormaux
- Scan régulier des images en production
- Procédure de réponse aux incidents documentée