P20 - DevSecOps : la sécurité dans toute la chaîne

Objectif

Comprendre l’approche DevSecOps (la sécurité intégrée à chaque étape, pas à la fin), savoir lire un score CVSS, produire une SBOM et scanner une image Docker avec Trivy et Dockle, puis durcir un Dockerfile.

Source

Fiche rédigée à partir de cours de lidstah (module et 3 TP de lidstah).


1. Le scénario de départ

Une application est livrée. Elle contient : ton code, des centaines de dépendances (npm, pip…), des secrets (mots de passe de BDD, clés API), des images de conteneurs (avec tout un système Debian ou Alpine dedans) et des fichiers IaC (Terraform, Ansible). Quelques jours après, la base de données fuit. Où chercher ? Partout. DevSecOps, c’est vérifier tout ça automatiquement, à chaque modification, pour ne pas en arriver là.

2. Les 5 familles de tests automatiques

TestCe qu’il chercheOutils
SAST (Static)Failles dans ton code source (injection SQL…)Semgrep, SonarQube, Bandit (Python)
SCA (Software Composition Analysis)Failles connues dans les dépendancesTrivy, osv-scanner, pip-audit
Scan IaCMauvaises configurations Terraform, Ansible, KubernetesTrivy config, Checkov, tfsec
DAST (Dynamic)Failles visibles quand l’application tourneOWASP ZAP
Secrets scanningMots de passe, clés API écrits en durGitleaks, TruffleHog

3. Le pipeline sécurisé

flowchart LR
  P["git push"] --> S1["SAST<br/>(code)"] --> S2["SCA<br/>(dépendances)"] --> S3["Scan IaC"] --> B["Build de l'image"] --> S4["Scan image<br/>(Trivy, Dockle)"] --> R["Registre<br/>(Harbor)"] --> PR["Production<br/>+ supervision"]
  S1 & S2 & S3 & S4 -.->|"faille critique"| X["⛔ build arrêté"]

Les 3 règles :

  1. Bloquer le critique (exécution de code à distance, secret en dur).
  2. Alerter sans bloquer pour le reste.
  3. Jamais de secrets en dur : HashiCorp Vault, Ansible Vault, SOPS, ou au minimum un fichier chiffré GPG.

4. Vocabulaire

TermeSignification
CVEIdentifiant public d’une vulnérabilité connue (ex. CVE-2024-3094, la porte dérobée de xz)
CVSSScore de gravité de 0 à 10 : 0,1-3,9 faible · 4-6,9 moyen · 7-8,9 élevé · 9-10 critique
SBOMSoftware Bill Of Materials : la liste des ingrédients d’un logiciel (fournisseur, composant, version, dépendances, date). Ce n’est pas un scanner, mais un scanner peut la lire
Supply chainChaîne d’approvisionnement : d’où vient chaque composant, est-il signé, par qui
Security by designMoindre privilège (pas de root), défense en profondeur (chaque couche protégée), sécurisé par défaut (seuls les ports utiles ouverts)
Analyse de risquesMenaces (qui ?) × vulnérabilités (par où ?) × impact (combien ça coûte ?) → on protège d’abord ce qui compte le plus

Les 5 métriques DevSecOps : MTTD (temps moyen pour détecter, viser < 24 h), MTTR (temps moyen pour corriger, viser < 7 jours), taux de détection avant la production, taux de faux positifs (trop de bruit = alertes ignorées), couverture des scans.

5. TP : scanner une image

sudo apt install docker.io
# SBOM avec Syft (liste des paquets de l'image)
docker run --rm anchore/syft wordpress:6.9.1-php8.4-apache
# vulnérabilités avec Trivy
mkdir -p trivycache
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v ./trivycache:/root/.cache/ \
  aquasec/trivy image --severity HIGH,CRITICAL wordpress:6.9.1-php8.4-apache
# mauvaises pratiques du Dockerfile / de l'image avec Dockle
dockle wordpress:6.9.1-php8.4-apache
# scanner des fichiers Terraform / Kubernetes / Dockerfile
docker run --rm -v ./mon-projet:/projet aquasec/trivy config /projet

À comparer : la même application sur une base debian:trixie, alpine ou une image distroless : moins il y a de paquets, moins il y a de CVE.

Harbor (registre d’images, installé par Helm sur K3s) fait tout ça automatiquement à chaque docker push : SBOM + scan Trivy intégré + blocage des images trop vulnérables.

6. Durcir un Dockerfile

L’exemple « à ne pas faire » du TP :

FROM alpine:latest
RUN apk update
RUN apk upgrade
RUN apk add git nginx
RUN git clone https://github.com/... /usr/share/nginx/html
COPY ./default.conf /etc/nginx/http.d/default.conf

Problèmes : tag latest (pas reproductible), tourne en root, git reste dans l’image finale, cache des paquets conservé, plusieurs couches inutiles.

Version durcie :

# étape 1 : récupérer le contenu (git ne sera PAS dans l'image finale)
FROM alpine:3.22 AS source
RUN apk add --no-cache git \
 && git clone --depth 1 https://github.com/Werkstattl/quick-dungeon-crawler-rpg-od /site
 
# étape 2 : image finale minimale, nginx sans root
FROM nginxinc/nginx-unprivileged:1.27-alpine
COPY --from=source --chown=101:101 /site /usr/share/nginx/html
USER 101
EXPOSE 8080
HEALTHCHECK CMD wget -qO- http://127.0.0.1:8080/ || exit 1

Exercices

  1. Une CVE a un score CVSS de 9,8 dans une bibliothèque que ton application utilise. Que fait le pipeline ?
  2. Pourquoi une SBOM est-elle utile le jour où une nouvelle faille est publiée ?
  3. Cite trois améliorations de sécurité d’un Dockerfile.

Voir aussi