Sécurité DevOps - Avancé
🎯 Objectifs
- Gérer les secrets avec HashiCorp Vault
- Comprendre et appliquer la supply chain security (SBOM, cosign, SLSA)
- Sécuriser un cluster Kubernetes (RBAC, NetworkPolicies, Pod Security Standards)
- Modéliser les menaces avec STRIDE
- Implémenter la compliance as code avec Open Policy Agent
📋 Prérequis
- Sécurité DevOps - Intermédiaire terminé
- Kubernetes : bases (pods, deployments, namespaces)
- Terraform ou infrastructure as code
🤔 Pourquoi aller plus loin ?
Les bases et les outils CI/CD protègent ton code. Mais les attaques modernes ciblent autre chose :
- La supply chain : empoisonner une dépendance open-source pour toucher des milliers de projets (SolarWinds, log4shell)
- L'infrastructure : un pod Kubernetes compromis qui pivote vers toute la plateforme
- Les secrets à long terme : des tokens qui ne tournent jamais et finissent par fuiter
Ce module couvre les pratiques que les équipes de sécurité expérimentées utilisent en production.
🏛️ HashiCorp Vault : gestion des secrets en production
Pourquoi pas juste GitHub Secrets ?
GitHub Secrets convient parfaitement pour les workflows CI/CD. Mais il a des limites :
| Critère | GitHub Secrets | HashiCorp Vault |
|---|---|---|
| Rotation automatique | ❌ | ✅ |
| Secrets dynamiques | ❌ | ✅ |
| Audit trail complet | Partiel | ✅ |
| Multi-cloud / multi-env | Limité | ✅ |
| Accès programmatique | Via API GitHub | API + SDK + CLI |
L'analogie
GitHub Secrets, c'est un coffre-fort fixe avec un seul jeu de clés. Vault, c'est un coffre-fort qui génère un nouveau jeu de clés à chaque utilisation, qui expire après un délai, et qui enregistre qui a pris quoi et quand.
Architecture Vault
Application → Vault Agent → Vault Server → Backend (AWS, DB, PKI…)
↑
s'authentifie
(Kubernetes, AWS IAM, AppRole…)Secrets dynamiques : le concept clé
Au lieu de stocker un mot de passe fixe pour la base de données, Vault génère un utilisateur temporaire à chaque demande.
# Vault génère des credentials PostgreSQL temporaires
vault read database/creds/mon-role
# Résultat :
# Key Value
# --- -----
# lease_duration 1h ← expire dans 1 heure
# username v-token-abc123
# password A1-XyZqRsT...Avantage : si les credentials fuient, ils expirent rapidement. La base de données n'a pas de mot de passe permanent.
Intégration Kubernetes avec Vault Agent
# Annotation sur un pod pour injecter les secrets automatiquement
apiVersion: v1
kind: Pod
metadata:
name: mon-app
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "mon-app-role"
# Vault Agent monte le secret dans /vault/secrets/config
vault.hashicorp.com/agent-inject-secret-config: "secret/data/mon-app/config"
spec:
containers:
- name: mon-app
image: mon-app:latest📚 Documentation officielle : developer.hashicorp.com/vault
📦 Supply Chain Security
Le problème de la chaîne d'approvisionnement
Ton application n'est pas que ton code. C'est :
- Des dépendances open-source (npm, pip, go modules)
- Des images de base Docker
- Des actions GitHub
- Des outils de build
Chaque maillon peut être compromis. L'attaque SolarWinds a touché 18 000 organisations via un outil de monitoring légitime infecté lors du build.
SBOM : l'inventaire de ton application
Un SBOM (Software Bill of Materials) est la liste exhaustive de tous les composants de ton application, avec leurs versions et licences. C'est le "sommaire d'ingrédients" de ton logiciel.
# Générer un SBOM avec Trivy (format CycloneDX)
trivy image --format cyclonedx --output sbom.json mon-app:latest
# Générer avec Syft (autre outil populaire)
syft mon-app:latest -o cyclonedx-json > sbom.json
# Analyser le SBOM pour détecter des vulnérabilités
grype sbom:./sbom.jsonIntégration dans GitHub Actions :
- name: Generate SBOM
uses: anchore/sbom-action@v0.17.0
with:
image: mon-app:${{ github.sha }}
artifact-name: sbom.spdx.json
output-file: ./sbom.spdx.json
- name: Scan SBOM for vulnerabilities
uses: anchore/scan-action@v4
with:
sbom: ./sbom.spdx.json
fail-build: true
severity-cutoff: criticalSigner les images avec cosign
cosign (projet Sigstore) permet de signer cryptographiquement une image Docker, prouvant son origine et son intégrité.
# Installer cosign
brew install cosign # macOS
# Signer une image (sans clé - via OIDC GitHub Actions)
cosign sign --yes mon-registry/mon-app:latest
# Vérifier la signature
cosign verify \
--certificate-identity https://github.com/mon-org/mon-repo/.github/workflows/release.yml@refs/heads/main \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
mon-registry/mon-app:latestSigner dans GitHub Actions (sans gérer de clé) :
- name: Sign the Docker image
env:
DIGEST: ${{ steps.build.outputs.digest }}
run: cosign sign --yes mon-registry/mon-app@${DIGEST}Niveaux SLSA : framework de provenance
SLSA (Supply-chain Levels for Software Artifacts) est un framework qui définit des niveaux de confiance sur l'origine d'un artefact.
| Niveau | Exigences | Protège contre |
|---|---|---|
| SLSA 1 | Build scripté, provenance générée | Documentation de base |
| SLSA 2 | Build service versionné, provenance signée | Modification post-build |
| SLSA 3 | Build isolé, non influençable | Compromission du build |
| SLSA 4 | Build hermétique, revue two-party | Modification du build service |
GitHub Actions génère automatiquement des attestations SLSA 3 via l'action officielle :
- name: Build with SLSA provenance
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
with:
image: mon-registry/mon-app
digest: ${{ steps.build.outputs.digest }}☸️ Sécurité Kubernetes
RBAC : qui peut faire quoi
RBAC (Role-Based Access Control) définit précisément quelles actions chaque utilisateur ou service peut effectuer.
# Rôle : lecture seule sur les pods dans le namespace "production"
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"] # pas de create, delete, update
---
# Lier ce rôle à un ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: production
subjects:
- kind: ServiceAccount
name: monitoring-agent
namespace: production
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io💡 Principe du moindre privilège : donne uniquement les permissions strictement nécessaires.
Vérifier les droits d'un ServiceAccount :
# Peut-il créer des pods ?
kubectl auth can-i create pods --as=system:serviceaccount:production:monitoring-agent -n production
# no
# Peut-il lire des pods ?
kubectl auth can-i get pods --as=system:serviceaccount:production:monitoring-agent -n production
# yesNetworkPolicies : isoler les pods
Par défaut dans Kubernetes, tous les pods communiquent entre eux. Les NetworkPolicies permettent de restreindre ce trafic.
# Politique "deny all" : bloquer tout trafic entrant et sortant par défaut
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: production
spec:
podSelector: {} # s'applique à tous les pods du namespace
policyTypes:
- Ingress
- Egress
---
# Autoriser uniquement les requêtes du frontend vers le backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend # s'applique aux pods "backend"
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend # uniquement depuis les pods "frontend"
ports:
- port: 3000Pod Security Standards
Les PSS remplacent les PodSecurityPolicies (dépréciées depuis Kubernetes 1.25). Ils définissent trois profils :
| Profil | Usage | Ce qu'il restreint |
|---|---|---|
| Privileged | Nœuds système | Rien (tout autorisé) |
| Baseline | Applications générales | Conteneurs privileged, hostPath, hostNetwork |
| Restricted | Applications critiques | + runAsNonRoot, readOnlyRootFilesystem |
# Appliquer le profil "restricted" sur un namespace
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/warn: restricted🎯 Threat Modeling avec STRIDE
Qu'est-ce que le threat modeling ?
C'est l'exercice qui consiste à se demander : "Comment mon système pourrait-il être attaqué ?" avant que ça arrive.
Le framework STRIDE
Chaque lettre est une catégorie de menace :
| Lettre | Menace | Exemple |
|---|---|---|
| Spoofing | Se faire passer pour quelqu'un d'autre | Faux token JWT |
| Tampering | Modifier des données | Modifier un SBOM en transit |
| Repudiation | Nier avoir effectué une action | Logs insuffisants pour prouver qui a supprimé des données |
| Information Disclosure | Exposer des données sensibles | Logs qui affichent des secrets |
| Denial of Service | Rendre le service indisponible | Saturation de l'API |
| Elevation of Privilege | Obtenir plus de droits que prévu | Pod qui accède aux secrets d'autres namespaces |
Exemple pratique : modéliser un pipeline CI/CD
Développeur → GitHub → GitHub Actions → Registry → Kubernetes| Flux | Menace STRIDE | Contrôle |
|---|---|---|
| Développeur → GitHub | S: usurpation d'identité | 2FA + commit signing |
| GitHub → Actions | T: injection dans le workflow | Actions pinnées + permissions minimales |
| Actions → Registry | T: image compromise | Trivy + cosign signature |
| Registry → Kubernetes | S: image non vérifiée | Admission controller + vérification cosign |
📜 Compliance as Code avec Open Policy Agent
Le problème
Comment s'assurer que toutes les ressources déployées respectent les politiques de sécurité de ton organisation ?
Exemple : "Tous les conteneurs doivent tourner en non-root."
Sans automation, c'est une règle dans un document PDF que personne ne lit.
OPA : un moteur de règles universel
OPA (Open Policy Agent) est un moteur de règles qui évalue des politiques écrites en langage Rego.
Gatekeeper est l'intégration OPA pour Kubernetes : il intercepte chaque création/modification de ressource et l'évalue contre tes règles.
# ConstraintTemplate : définit une règle réutilisable
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("Labels manquants : %v", [missing])
}
---
# Constraint : applique la règle sur les namespaces de prod
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-team-label
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
parameters:
labels: ["team", "environment"]Tester une politique OPA en local :
# Installer opa
brew install opa
# Tester une règle
opa eval --input input.json --data policy.rego "data.k8srequiredlabels.violation"📊 Récapitulatif
| Domaine | Outil | Ce qu'il apporte |
|---|---|---|
| Secrets dynamiques | HashiCorp Vault | Rotation automatique, audit trail complet |
| Inventaire logiciel | Trivy / Syft (SBOM) | Visibilité sur tous les composants |
| Signature d'image | cosign (Sigstore) | Garantie d'origine et d'intégrité |
| Provenance build | SLSA / slsa-github-generator | Preuve du process de build |
| Accès Kubernetes | RBAC | Moindre privilège par ServiceAccount |
| Réseau Kubernetes | NetworkPolicy | Isolation entre pods et namespaces |
| Sécurité des pods | Pod Security Standards | Prévention de l'escalade de privilèges |
| Analyse des menaces | STRIDE | Identification proactive des risques |
| Règles de sécurité | OPA / Gatekeeper | Enforcement automatique des politiques |
✅ Checklist Sécurité Avancé
- Vault déployé avec secrets dynamiques pour la base de données
- SBOM généré à chaque build et archivé
- Images signées avec cosign avant le déploiement
- Attestation SLSA générée pour les releases
- RBAC Kubernetes : chaque service a un ServiceAccount dédié
- NetworkPolicies : deny-all par défaut + allow explicites
- Pod Security Standards : profil
restrictedsur les namespaces de production - Threat model documenté pour les flux critiques
- OPA/Gatekeeper en place avec les politiques obligatoires
📚 Ressources
- HashiCorp Vault
- Sigstore / cosign
- SLSA Framework
- Syft (SBOM)
- OPA Documentation
- Kubernetes RBAC
- STRIDE threat modeling - Microsoft
🚀 Prochaines Étapes
Tu maîtrises maintenant la sécurité DevOps de bout en bout.
- 👉 Sécuriser ses pipelines (DevSecOps) - Synthèse des bonnes pratiques
- 👉 Terraform - Avancé - Infrastructure as code en production
- 👉 Kubernetes - Avancé - Production-grade Kubernetes