Durcir les services cloud, les données & l'IaC
Objectifs pédagogiques
- Étendre le durcissement au-delà des conteneurs : stockage, bases, sauvegardes, certificats, réseau cloud
- Configurer un stockage objet minimal, chiffré, versionné et verrouillé
- Concevoir des sauvegardes qui survivent à un rançongiciel
- Gérer des certificats internes automatiquement avec cert-manager
- Valider une infrastructure cloud décrite en Terraform avant tout déploiement
- Suivre la conformité en continu
Au-delà des conteneurs
La surface oubliée
- Bucket ouvert en lecture publique, base de données exposée sur Internet, groupe de sécurité ouvert à
0.0.0.0/0 - Sauvegardes stockées là où l'attaquant peut les supprimer
- Certificat expiré qui coupe un service un dimanche
- Clé d'accès unique partagée par toutes les applications
- Ces erreurs ne viennent pas d'une faille logicielle mais d'une configuration, et elles se détectent dans le code d'infrastructure
La responsabilité partagée
| Le fournisseur sécurise | Vous sécurisez |
| Les centres de données et le matériel | La configuration de chaque service |
| L'hyperviseur et le réseau physique | Les identités, les rôles et les clés |
| La disponibilité du service managé | Le chiffrement, l'exposition, les sauvegardes |
- Un service managé n'est pas sécurisé par défaut : il est configurable de façon sécurisée
- La configuration se décrit en code, se revoit en MR et se teste avant d'être appliquée
Stockage objet
Les règles de base
- Aucun accès public : blocage explicite au niveau du compte et du bucket
- Accès minimal par usage : une identité et une clé par application, limitées à leurs buckets et à leurs actions
- Chiffrement au repos, idéalement avec une clé gérée par l'entreprise (KMS)
- Transport chiffré imposé par la politique du bucket
- Versioning : un objet écrasé ou supprimé reste récupérable
- Journalisation des accès pour l'audit
Le verrouillage d'objets (WORM)
- Une version verrouillée ne peut être ni modifiée ni supprimée avant sa date de rétention
- Mode governance : des identités privilégiées peuvent lever le verrou
- Mode compliance : personne ne le peut, pas même l'administrateur
- Une rétention par défaut s'applique à chaque nouvel objet du bucket
- Une suppression simple pose un marqueur de suppression : l'objet semble disparu, la version reste
- Selon le moteur, le verrouillage doit être activé à la création du bucket
Quel moteur S3 en lab ?
| Moteur | Versioning | Verrouillage d'objets | Remarque |
| MinIO Community Edition | oui | oui | archivé en amont depuis avril 2026 |
| Garage | non | non | en cours de développement, non publié |
| SeaweedFS | oui | oui | governance et compliance, vérifié en test |
- Pour des sauvegardes immuables, le choix se fait sur le verrouillage d'objets, pas sur la simplicité
- En production cloud, le stockage objet du fournisseur offre ces garanties nativement
Vérifier le verrou
aws --endpoint-url "$S3_URL" s3api create-bucket \
--bucket sauvegardes --object-lock-enabled-for-bucket
aws --endpoint-url "$S3_URL" s3api put-object-lock-configuration --bucket sauvegardes \
--object-lock-configuration \
'{"ObjectLockEnabled":"Enabled","Rule":{"DefaultRetention":{"Mode":"COMPLIANCE","Days":7}}}'
# Supprimer une version verrouillée
aws --endpoint-url "$S3_URL" s3api delete-object \
--bucket sauvegardes --key velero/backup.tar --version-id "$VERSION"
# AccessDenied
- Constaté sur SeaweedFS : versioning activé automatiquement, suppression de la version refusée, marqueur de suppression sans perte de données
Sauvegardes anti-rançongiciel
La règle 3-2-1-1-0
- 3 copies des données
- sur 2 supports différents
- dont 1 hors site
- dont 1 immuable ou déconnectée
- 0 erreur constatée lors des tests de restauration
- Une sauvegarde accessible et supprimable avec les identifiants de production n'est pas une protection contre un attaquant qui les détient
Velero : ce que contient une sauvegarde
- Les manifests Kubernetes du périmètre, Secrets compris, déposés tels quels dans le bucket
- Les volumes, par instantané ou par sauvegarde de fichiers (Kopia)
- Par défaut, Velero chiffre les dépôts Kopia avec une clé statique commune : quiconque accède au bucket peut lire les données
- Conséquences :
- définir sa propre clé de dépôt et la ranger dans le coffre ;
- chiffrer le bucket au repos ;
- restreindre strictement l'accès au bucket
Velero et le verrouillage
- Les sauvegardes vont dans un bucket verrouillé en mode compliance
- L'identité de Velero écrit et lit, mais ne peut pas supprimer une version verrouillée
- La durée de vie des sauvegardes (
--ttl) doit être supérieure ou égale à la rétention du verrou, sinon le nettoyage des sauvegardes expirées se heurte au verrou - Le stockage vit hors du cluster qu'il protège : la perte du cluster ne doit pas emporter ses sauvegardes
- La restauration se teste régulièrement et se chronomètre (voir le Security Chaos Engineering)
Certificats & TLS interne
cert-manager
- Gère les certificats comme des objets Kubernetes :
Issuer, ClusterIssuer, Certificate - Émetteurs : autosigné (amorçage), autorité interne (CA), ACME (Let's Encrypt), coffre (PKI d'OpenBao)
- Émet, stocke dans un Secret, renouvelle avant expiration
- Réémet automatiquement un certificat dont le Secret a disparu (constaté en une seconde)
- Expose des métriques d'expiration et d'état à surveiller
Une autorité de certification interne
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata: {name: selfsigned}
spec: {selfSigned: {}}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata: {name: securepay-ca, namespace: cert-manager}
spec:
isCA: true
commonName: SecurePay Internal CA
secretName: securepay-ca
issuerRef: {name: selfsigned, kind: ClusterIssuer}
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata: {name: securepay-ca}
spec: {ca: {secretName: securepay-ca}}
TLS sur OpenBao
global:
tlsDisable: false
server:
extraVolumes:
- type: secret
name: openbao-prod-tls # monté dans /openbao/userconfig/openbao-prod-tls/
standalone:
config: |
listener "tcp" {
address = "[::]:8200"
cluster_address = "[::]:8201"
tls_cert_file = "/openbao/userconfig/openbao-prod-tls/tls.crt"
tls_key_file = "/openbao/userconfig/openbao-prod-tls/tls.key"
}
- Le Secret
openbao-prod-tls est produit par un Certificate signé par l'autorité interne - Les clients (External Secrets, CLI) font confiance à cette autorité
IaC cloud validée avant apply
Le principe
- La cible cloud est décrite en Terraform : bucket, base de données, réseau, clés
- Comme le SAST pour le code, l'analyse d'IaC détecte les erreurs avant qu'elles n'existent
- Trois niveaux complémentaires :
- Trivy et Checkov : règles génériques issues des benchmarks ;
- conftest : règles propres à la PSSI de l'entreprise, écrites en Rego
- Le tout bloque la MR, comme une Quality Gate
Trivy et Checkov
trivy config --severity HIGH,CRITICAL --exit-code 1 iac/terraform
checkov -d iac/terraform --framework terraform --compact --quiet
- Constaté sur un module volontairement fautif : 7 constats HIGH pour Trivy 0.76.0, 18 contrôles en échec pour Checkov 3.4.3
- Les identifiants Trivy ont changé de forme :
AWS-0080, et non plus AVD-AWS-0080 - Exception justifiée, au plus près de la ressource :
#trivy:ignore:AWS-0180
resource "aws_db_instance" "paiements" {
#checkov:skip=CKV_AWS_17:base exposée sur un réseau privé de rebond, voir ADR-0007
...
}
conftest : la PSSI en Rego
package main
import rego.v1
# conftest représente chaque bloc Terraform par une liste : d'où le [_]
deny contains msg if {
some name
db := input.resource.aws_db_instance[name][_]
not db.storage_encrypted == true
msg := sprintf("PSSI-CHIF-01 : la base %s doit être chiffrée au repos", [name])
}
deny contains msg if {
some name
db := input.resource.aws_db_instance[name][_]
db.publicly_accessible == true
msg := sprintf("PSSI-RES-02 : la base %s ne doit pas être exposée publiquement", [name])
}
- Sans le
[_], la seconde règle ne se déclenche jamais : piège constaté en test
Dans la pipeline
iac:validate:
image: hashicorp/terraform:<version>
script:
- terraform -chdir=iac/terraform init -backend=false
- terraform -chdir=iac/terraform validate
iac:trivy:
image: {name: aquasec/trivy:0.76.0, entrypoint: [""]}
script: [trivy config --severity HIGH,CRITICAL --exit-code 1 iac/terraform]
iac:checkov:
image: {name: bridgecrew/checkov:<version>, entrypoint: [""]}
script: [checkov -d iac/terraform --framework terraform --compact --quiet]
iac:conftest:
image: {name: openpolicyagent/conftest:<version>, entrypoint: [""]}
script: [conftest test --policy iac/policy iac/terraform/*.tf]
- Images épinglées, jobs en parallèle, aucun
terraform apply dans ce TP
Mesurer en continu, pas une fois par an
- Kyverno : rapports de politiques (
PolicyReport) sur l'existant, pas seulement à l'admission - Trivy Operator : vulnérabilités, audits de configuration et rapports de conformité générés en continu dans le cluster
- Kubescape : score de conformité selon plusieurs référentiels
- Cloud : scanners de compte comme Prowler pour l'infrastructure déployée
- Les écarts alimentent la matrice de conformité et DefectDojo, avec leur responsable
Anti-patterns à proscrire
- Un bucket de sauvegarde dans le même compte et avec les mêmes identifiants que la production
- Des sauvegardes jamais restaurées
- La clé de dépôt par défaut de Velero en production
- Des certificats suivis dans un tableur
- Des exceptions de scanner sans justification ni date de réexamen
- Valider l'IaC après le
terraform apply
À retenir
- Les services managés ne sont pas sécurisés par défaut : leur configuration se décrit, se revoit et se teste
- Stockage objet : privé, minimal, chiffré, versionné ; et verrouillé pour les sauvegardes
- Une sauvegarde utile contre un rançongiciel est immuable, hors du cluster, chiffrée avec votre propre clé, et restaurée régulièrement
- cert-manager supprime les expirations oubliées, à condition de surveiller ses métriques
- Trivy, Checkov et conftest bloquent les mauvaises configurations avant qu'elles n'existent
Pour aller plus loin