DISA : sécuriser les images conteneurisées selon le guide officiel

Exemples, Dockerfile durci et checklist pour durcir et prouver la sécurité de vos images (digest, SBOM, cosign), contrôles CI/CD et politiques runtime Kubernetes.

Un bureau informatique avec des écrans montrant des éléments de sécurité et de stockage de données.

Table des matières :

  1. DISA, STIG et « images conteneurisées » : périmètre et pièges fréquents
  2. Risques spécifiques de la supply chain d’images : ce que le guide DISA cherche à casser
  3. Construire une image « STIG-friendly » : Dockerfile/Containerfile durci (exemple PHP-FPM pour PrestaShop)
  4. Contrôles automatisés en CI/CD : vulnérabilités, SBOM, signature, provenance (SLSA)
  5. À l’exécution : politiques Kubernetes/Compose, restrictions kernel, secrets, observabilité et réponse à incident

DISA, STIG et « images conteneurisées » : périmètre et pièges fréquents

Quand on parle de DISA (Defense Information Systems Agency) dans le contexte « container », on parle en pratique des référentiels STIG (Security Technical Implementation Guides) et parfois des SRG (Security Requirements Guides). La DISA résume l’objectif sans ambiguïté : « Security Technical Implementation Guides (STIGs) provide security guidance for the configuration of DoD information systems. » (DISA, portail STIG). Traduction opérationnelle côté build : l’image n’est qu’un artefact dans une chaîne (registre → orchestrateur → runtime). Le guide officiel ne « sécurise » pas magiquement votre Dockerfile ; il impose des exigences vérifiables (durcissement, traçabilité, séparation des rôles, réduction de surface, gestion des vulnérabilités) qu’il faut mapper à vos outils.

Dans un audit « STIG-like », le sujet n’est pas seulement ce que vous faites, mais comment vous le démontrez. Concrètement, préparez dès le départ un périmètre clair, sinon vous vous retrouvez avec des « contrôles fantômes » impossibles à rattacher à une couche technique :

  • Build : Dockerfile/Containerfile, dépendances, secrets, reproductibilité, SBOM.
  • Registre : contrôle d’accès, immutabilité des tags, rétention, scans, signatures.
  • Orchestrateur / plateforme : politiques d’admission, RBAC, segmentation réseau, limites ressources.
  • Nœuds / OS hôte : patching, configuration du runtime (containerd, Docker), journaux, restrictions kernel.
  • Run / ops : rotation des secrets, observabilité, réponse à incident, gestion des exceptions.

Le premier piège, c’est de confondre image et conteneur en exécution. Une image « propre » peut être lancée avec --privileged, des montages en écriture, des capabilities kernel inutiles, ou un daemon Docker exposé ; à l’inverse, un runtime bien verrouillé ne compensera pas une image qui embarque un gestionnaire de paquets, des binaires SUID, ou des dépendances non patchées. Le référentiel DISA pousse justement vers cette séparation : contrôles de build (ce qui est dans l’image) et contrôles de plateforme (ce qui entoure l’image).

Un réflexe utile (et très « audit-friendly ») : raisonner en preuves plutôt qu’en intentions. Exemple concret : si quelqu’un vous demande « quelle version exacte tourne en prod ? », répondre « php:8.3-fpm » est insuffisant (tag mutable). Une réponse exploitable, c’est : le digest exact (SHA256) déployé, associé à un SBOM et à une signature, avec la trace du pipeline ayant produit cet artefact.

Le deuxième piège, très courant en e-commerce, c’est l’illusion « on a dockerisé donc c’est isolé ». NIST est explicite dans NIST SP 800-190 : « Containers are not a panacea and should not be considered a complete security solution. » Pour une stack PrestaShop (typiquement PrestaShop 8/9 + PHP-FPM 8.2/8.3 + Nginx/Apache + Redis/ES), l’isolation process ne vous protège ni d’une supply chain compromise, ni d’un secret qui fuit dans une layer, ni d’un conteneur lancé en root. Avant de parler conformité, clarifiez votre objectif : réduire le risque exploitable et pouvoir le prouver (audit).

Risques spécifiques de la supply chain d’images : ce que le guide DISA cherche à casser

Le point dur des images conteneurisées, ce n’est pas « Docker vs VM ». C’est la supply chain : base image → dépendances OS → dépendances applicatives → outil de build → registry → déploiement. La plupart des incidents réels viennent de là : tags « latest » remplacés silencieusement, image publique typosquattée, CI compromise, ou artefacts non signés acceptés en production. DISA pousse implicitement vers des mécanismes de preuve : provenance, immutabilité, traçabilité, et contrôle d’admission.

Sur un projet PrestaShop, on retrouve des erreurs récurrentes :

  • FROM php:8.3-fpm sans digest (vous acceptez les rebuilds upstream sans contrôle) ;
  • apt-get install qui laisse caches, outils de compilation, curl, git, voire ssh dans l’image runtime ;
  • modules Composer/NPM installés en production, sans verrouillage strict (lockfile), donc surface et dérive ;
  • .env, tokens, clés d’API copiés dans l’image (ils restent récupérables via l’historique des layers).

Ajoutez deux « pièges » très fréquents en production e-commerce :

  • tags réutilisés (ex. :prod, :stable) : si le tag pointe vers des digests différents au fil du temps, vous perdez la capacité à reconstituer « qui a tourné quand » ;
  • build non déterministe : si composer install ou npm ci n’est pas strictement verrouillé (ou si les registres/proxies changent), vous pouvez reconstruire « la même version » avec un contenu différent.

Le lien avec DISA est direct : tout ce qui augmente la surface augmente le nombre de findings et surtout la probabilité d’exploit. Les métriques à suivre sont simples et auditables : nombre de CVE Critical/High par image, âge des vulnérabilités (mean time to remediate), taux d’images non signées déployées, et ratio d’images exécutées en non-root. Si vous ne mesurez pas ça dans votre pipeline, votre « conformité » se limite à des PDF.

Pour éviter les débats abstraits, voici une mini-grille « preuve / contrôle » qui aide beaucoup en revue de sécurité :

Risque supply chain Contre-mesure pratique Preuve attendue en audit
Tag mutable (ex. :latest) Déployer par digest, verrouiller tags critiques, activer l’immutabilité côté registry Manifest/helm chart avec @sha256:..., politique d’admission qui refuse les tags
Dépendances non maîtrisées Lockfiles, dépôt proxy/miroir, builds reproductibles composer.lock/package-lock.json, logs de build, SBOM
Image runtime trop « riche » Multi-stage, suppression des outils, base minimale Scan montrant baisse de paquets, absence d’outils de build dans runtime
CI compromise / artefact substitué Signature + provenance + contrôle d’admission Signature (cosign), attestation de provenance, logs de policy enforcement

Dernier point : l’image doit être considérée comme un artefact applicatif. La même rigueur que pour vos dépôts PrestaShop s’applique (contrôle des sources, branches protégées, etc.). Sur ce sujet, le rappel « anti-forks / vérification des dépôts » est pertinent, même si vous n’êtes pas sur le cœur PrestaShop : voir PrestaShop GitHub : dépôts officiels, vérification et sécurité anti-forks.

Construire une image « STIG-friendly » : Dockerfile/Containerfile durci (exemple PHP-FPM pour PrestaShop)

Objectif : une image qui passe mieux les contrôles type DISA/CIS (réduction surface, exécution non-root, limites, pas de secrets, traçabilité). On part ici d’un cas concret : PrestaShop 9 en PHP-FPM. Versioning : exemples valables avec Docker Engine/BuildKit récents (2025–2026) et PHP 8.2/8.3 ; adaptez si vous êtes contraints par une version PHP spécifique (voir PrestaShop 9 : versions PHP recommandées et incohérences de documentation). Pré-requis : registry privée ou au minimum contrôle d’accès, et une CI capable de builder en multi-stage.

Les décisions qui font réellement baisser le risque (et améliorent vos chances face à un audit STIG-like) :

1) Pinner la base image (digest SHA256, pas juste un tag).
2) Multi-stage : build avec outils (composer, node, build deps) → runtime minimal.
3) Non-root par défaut, UID/GID fixes, répertoires explicitement chown.
4) Aucune donnée sensible dans l’image : secrets injectés au runtime.
5) Nettoyage systématique : caches APT, build deps, artefacts.

Deux compléments qui font souvent la différence en revue sécurité (sans « complexifier pour complexifier ») :

  • .dockerignore strict : pour éviter d’embarquer par accident .env, dumps, clés, ou dossiers CI (c’est une source d’incidents très banale, et ça se voit rarement tant qu’on ne déplie pas l’image).
  • labels OCI (traçabilité) : au minimum org.opencontainers.image.source, org.opencontainers.image.revision, org.opencontainers.image.created. Ça aide à relier un digest à un commit et à un pipeline, y compris après plusieurs mois.

Exemple de Dockerfile (à adapter à votre arborescence PrestaShop et votre méthode de build). L’idée n’est pas « parfait DISA » en 30 lignes, mais un socle durci, reproductible, diffable :

# syntax=docker/dockerfile:1.7

ARG PHP_IMAGE=php:8.3-fpm-bookworm

# 1) Stage build : dépendances et vendor
FROM ${PHP_IMAGE} AS build

# Pinning recommandé : remplacer par un digest dans la vraie vie
# FROM php@sha256:<digest> AS build

RUN set -eux; \
  apt-get update; \
  apt-get install -y --no-install-recommends \
    git unzip libzip-dev; \
  docker-php-ext-install zip; \
  rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Composer en build uniquement
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
COPY composer.json composer.lock ./
RUN set -eux; composer install --no-dev --prefer-dist --no-interaction --no-progress

# Code applicatif
COPY . .

# 2) Stage runtime : minimal, non-root
FROM ${PHP_IMAGE} AS runtime

# Crée un user non-root stable
RUN set -eux; \
  groupadd -g 10001 app; \
  useradd -u 10001 -g app -s /usr/sbin/nologin -m app

WORKDIR /var/www/html

# Copie uniquement le nécessaire depuis le build
COPY --from=build /app /var/www/html

# Permissions minimales (adapter au besoin de PrestaShop : cache, uploads…)
RUN set -eux; \
  chown -R app:app /var/www/html; \
  find /var/www/html -type f -name "*.sh" -exec chmod 0750 {} \;; \
  true

USER app

# Santé applicative : évite les conteneurs zombies
HEALTHCHECK --interval=30s --timeout=3s \
  CMD php -v >/dev/null || exit 1

# Important : config PHP/FPM à monter via ConfigMap/volume, pas baked-in si vous devez varier par env
CMD ["php-fpm", "-F"]

Quelques points d’attention « PrestaShop réel » (et donc audit réel) :

  • Écritures nécessaires : si vous activez readOnlyRootFilesystem (fortement recommandé au runtime), vous devrez prévoir des volumes/emptyDir pour les zones d’écriture (cache, sessions, uploads). L’objectif n’est pas d’interdire l’écriture, mais de la circonscrire.
  • Install/upgrade : l’installation ou la mise à jour de modules ne doit pas forcer à exécuter le conteneur en root. Une approche propre consiste à séparer :
  • un conteneur runtime « strict » (prod),
  • et un job/outil d’administration (maintenance) exécuté de façon contrôlée, avec des droits et un périmètre limités.
  • Paquets résiduels : si votre image runtime contient apt, curl, git, etc., vous augmentez la surface et vous facilitez les post-exploitation (téléchargement, compilation, pivot). Multi-stage + nettoyage est un gain simple.

Checklist express de revue Dockerfile (utile en PR, et très facile à transformer en règles CI) :

  • [ ] FROM …@sha256: (digest) ou preuve d’équivalence contrôlée
  • [ ] multi-stage et absence d’outils de build dans l’étape runtime
  • [ ] USER non-root + UID/GID fixés (pas d’UID aléatoire non documenté)
  • [ ] aucun secret dans l’historique des layers (pas de ARG/ENV sensible)
  • [ ] suppression des caches (/var/lib/apt/lists/*, caches composer/node si pertinents)
  • [ ] présence d’une stratégie de logs et healthcheck (même minimal)

Limites à connaître (et à documenter) : PrestaShop a historiquement des besoins d’écriture (cache, img/, parfois var/) et certains modules « legacy » supposent l’exécution en root lors d’installations ou de tâches CRON mal conçues. Le choix « non-root strict » peut donc casser du code ; c’est précisément le type de problème que DISA force à mettre au jour. Ne compensez pas en repassant tout en root : corrigez la permission, isolez les volumes, ou séparez les tâches d’administration dans un conteneur job dédié.

Contrôles automatisés en CI/CD : vulnérabilités, SBOM, signature, provenance (SLSA)

DISA n’est pas un framework CI/CD, mais un audit STIG moderne finit toujours par poser la même question : comment prouvez-vous que l’image déployée est celle qui a été validée, et qu’elle respecte un niveau de sécurité minimal ? Si votre réponse tient dans « on build sur la machine du dev », vous êtes hors-jeu. La base, c’est : scan CVE, génération SBOM, signature, et politiques bloquantes.

Sur le scan vulnérabilités, l’écueil classique est le « scan décoratif » (rapport ignoré). Il faut un seuil : par exemple 0 Critical et 0 High au-delà d’un délai (SLA interne), avec une liste d’exceptions expirables. Outillage courant : Trivy (Aqua), Grype (Anchore). Côté SBOM, Syft + CycloneDX est une combo standard. Le SBOM n’est pas un gadget conformité : il réduit le temps de réponse quand une CVE tombe sur une lib indirecte.

Une façon pragmatique de rendre ça exploitable (et pas seulement « conforme ») :

  • Séparer les niveaux : vulnérabilités OS packages vs dépendances applicatives (PHP/Composer). Les deux comptent, mais les plans de remédiation diffèrent.
  • Suivre l’âge des vulnérabilités : un backlog de High « vieux de 90 jours » est souvent plus risqué qu’un pic temporaire (et c’est un indicateur facile à expliquer à une direction).
  • Garder les artefacts : stocker SBOM + rapport de scan liés au digest. Sans ça, vous avez un rapport… mais pas la preuve qu’il correspond à ce qui tourne.

Sur l’intégrité/provenance, évitez les solutions « maison ». Le minimum robuste en 2026 :

  • signer l’image (cosign / Sigstore) ;
  • enregistrer le digest exact déployé ;
  • attester la provenance (SLSA), a minima niveau 2/3 selon vos contraintes.

À noter (important en audit) : la signature ne sert pas seulement à « faire joli ». Elle sert à bloquer l’exécution d’artefacts non approuvés. Sans contrôle d’admission en face (cf. section runtime), la signature reste un mécanisme théorique.

Exemple de pipeline (pseudo GitHub Actions) :

- name: Build (with provenance)
  run: |
    docker buildx build \
      --provenance=true \
      --sbom=true \
      -t registry.example.com/prestashop:${GIT_SHA} \
      --push .

- name: Scan CVE
  run: trivy image --exit-code 1 --severity CRITICAL,HIGH registry.example.com/prestashop:${GIT_SHA}

- name: Sign
  run: cosign sign registry.example.com/prestashop:${GIT_SHA}

Pour cadrer la discussion côté organisation, une matrice « livrable → utilité → preuve » évite beaucoup de malentendus :

Livrable CI/CD À quoi ça sert réellement À conserver / fournir
Digest d’image Identifier exactement ce qui tourne digest + date + environnement
SBOM (CycloneDX) Impact analysis (CVE, dépendances indirectes) SBOM lié au digest
Rapport de scan Décider / bloquer / tracer les exceptions rapport versionné + règles de seuil
Signature + attestation Prouver provenance et empêcher substitution signature vérifiée à l’admission

Si vous cherchez des parallèles « applicatifs », la logique est la même que pour sécuriser des clés d’accès ou limiter les dégâts d’une compromission : vous automatisez, vous journalisez, vous rendez l’état prouvable. Sur la partie secrets/rotation côté applicatif, voir API : sécuriser apikey, limiter le débit et renforcer la conformité.

À l’exécution : politiques Kubernetes/Compose, restrictions kernel, secrets, observabilité et réponse à incident

Même une image « nickel » peut être ruinée au runtime. Le durcissement DISA-like au déploiement se joue sur : exécution non-root, capabilities minimales, seccomp/AppArmor/SELinux, filesystem en lecture seule, pas de privilege escalation, et limites ressources. En Kubernetes, ça se traduit dans securityContext. Exemple (extrait) :

securityContext:
  runAsNonRoot: true
  runAsUser: 10001
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities:
    drop: ["ALL"]
  seccompProfile:
    type: RuntimeDefault

Pour industrialiser ce type d’exigences, alignez-vous sur un standard compréhensible et outillable. Kubernetes documente les Pod Security Standards (Baseline/Restricted), qui servent souvent de socle aux politiques (admission).

Dans la vraie vie PrestaShop, readOnlyRootFilesystem: true est faisable, mais implique de prévoir explicitement des points d’écriture. Mini-schéma classique :

  • root FS en lecture seule,
  • volumes dédiés pour var/ (cache), img/ (uploads), éventuellement /tmp,
  • droits cadrés via fsGroup ou initContainer qui prépare les permissions (plutôt que de repasser en root dans l’app).

Le point central « DISA moderne » est l’admission control : refuser en cluster ce qui ne respecte pas votre politique (image non signée, tag mutable, conteneur privileged, etc.). Typiquement via Gatekeeper/OPA ou Kyverno. Si vous ne bloquez rien, vous n’avez pas de contrôle : vous avez un wiki. Ajoutez un contrôle de signature (cosign) et exigez l’usage de digests (image: repo@sha256:...) ; ça neutralise une classe entière d’attaques basées sur la substitution de tag.

Même hors Kubernetes, vous pouvez appliquer une partie des restrictions avec Docker Compose (utile en PME/ETI). Exemples de leviers concrets :

  • read_only: true + tmpfs: /tmp (réduit l’écriture inattendue),
  • cap_drop: ["ALL"] (et ré-autoriser au cas par cas),
  • security_opt: ["no-new-privileges:true"],
  • limites CPU/RAM pour éviter qu’un conteneur compromis ne dégrade tout le service.

Enfin, le guide officiel ne remplace pas l’exploitation : gestion des secrets, logs, et réponse à incident. Pour les secrets Kubernetes, éviter de « docker secret » bricolé ou des variables d’environnement versionnées en clair ; un opérateur de synchronisation (Vault/OKMS/Secrets Manager) est plus propre, par exemple via External Secrets Operator : synchroniser les secrets Kubernetes avec OVHcloud OKMS. Et si vous pensez « on verra en cas de problème », vous allez perdre du temps quand ça compte : préparez un runbook, des artefacts (digest de l’image, SBOM, logs), et un plan de containment ; sur l’écosystème e-commerce/PrestaShop, voir Sécurité PrestaShop : plan de réponse à incident et containment immédiat.

Un point souvent sous-estimé en réponse à incident sur conteneurs : savoir quoi collecter avant de « tout redéployer ». Une checklist opérationnelle (simple, mais décisive) :

  • digest(s) exact(s) des images déployées au moment de l’incident,
  • SBOM correspondant et rapports de scan associés,
  • événements d’admission/policy (rejets/acceptations),
  • logs applicatifs + logs ingress/reverse-proxy + logs runtime (selon stack),
  • empreinte de config (values Helm / manifests) pour reproduire le contexte.

Pour être clair : sécuriser des images « selon DISA » n’est pas une case à cocher, c’est un système. Vous durcissez le build, vous imposez des preuves (SBOM + signatures + digests), et vous verrouillez l’exécution. Le reste (hébergement, isolation réseau, WAF, monitoring) relève de l’architecture globale — et si vous partez d’une infra sous-dimensionnée ou instable, vous finirez par contourner vos propres garde-fous. Point de départ pragmatique si vous êtes en phase de sizing : VPS pour Docker : critères techniques et ressources recommandées.


À lire aussi