Le Policy as Code (PaC) est une approche DevSecOps où les politiques de sécurité, de conformité et de gouvernance sont exprimées sous forme de code versionné, testable et automatiquement appliqué — au lieu de documents PDF interprétés manuellement. Le code policy est stocké dans Git, revu via pull requests, testé avec des cas unitaires, et évalué par un moteur dédié au runtime ou en amont des déploiements. Les 4 moteurs dominants en 2026 : OPA (Open Policy Agent, CNCF graduated 2021, langage Rego, général-purpose), Kyverno (Nirmata, CNCF graduated 2023, Kubernetes-natif YAML), HashiCorp Sentinel (Terraform Enterprise/Cloud, langage propriétaire), AWS Cedar (open-source 2023, authorization engine). Les 6 cas d'usage principaux : Kubernetes admission control (Kyverno ou OPA Gatekeeper), Infrastructure as Code pre-apply (Conftest, Sentinel, Checkov custom), CI/CD pipeline gates, API authorization fine-grained ABAC, cloud governance continue (AWS Config, Azure Policy, GCP Organization Policy), data governance. Le PaC est devenu un levier majeur de conformité réglementaire depuis 2023-2024, accéléré par NIS 2 (directive UE 2022/2555 transposée octobre 2024), DORA (règlement UE 2022/2554 applicable janvier 2025), Cyber Resilience Act UE (applicable décembre 2027), PCI-DSS v4.0, SOC 2 Type II — les auditeurs demandent désormais des artefacts PaC plutôt que des captures d'écran. Zeroday Cyber Academy recommande de commencer par Kyverno (Kubernetes-natif, courbe plate) puis de progresser vers OPA Rego (flexibilité maximale), avec focus testing et déploiement progressif audit puis enforce. Cet article détaille la définition, les 4 moteurs avec leurs spécificités, les 6 cas d'usage, du code hands-on Rego plus Kyverno plus Cedar, les pratiques de testing et notre bilan factuel.
1. Définition et intérêt structurel du Policy as Code
Définition opérationnelle : le Policy as Code transforme des règles de sécurité précédemment exprimées en documents écrits (PDF policy, Word procedures, wiki) en code exécutable qui :
- Est versionné dans Git comme n'importe quel code applicatif.
- Est testé avec des cas unitaires et d'intégration.
- Est revu via pull requests avec approbation.
- Est évalué automatiquement par un moteur (OPA, Kyverno, Sentinel, Cedar) au runtime ou en pre-deployment.
- Produit des logs d'évaluation exploitables pour audit et debugging.
Contraste avec l'approche document
| Aspect | Policy document (PDF, Word) | Policy as Code |
|---|---|---|
| Expression | Langage naturel | Code versionné |
| Enforcement | Manuel, interprétable | Automatique, déterministe |
| Test | Revue humaine | Tests unitaires et intégration |
| Versioning | Dates de révision | Git history complète |
| Audit | Capture d'écran | Logs d'évaluation temps réel |
| Temps de détection déviation | Audit annuel ou trimestriel | Immédiat à chaque déploiement |
| Scalabilité | Limitée équipe humaine | Massive, automatisée |
2. Les quatre moteurs Policy as Code dominants en 2026
| Moteur | Éditeur | Langage | Contexte optimal | Positionnement |
|---|---|---|---|---|
| OPA (Open Policy Agent) | CNCF (graduated 2021) | Rego (custom, déclaratif) | Multi-contexte : K8s, IaC, API, cloud | Général-purpose, flexible |
| Kyverno | Nirmata, CNCF graduated 2023 | YAML (K8s-native) | Kubernetes-only | Courbe d'apprentissage plate |
| HashiCorp Sentinel | HashiCorp (commercial TF Enterprise/Cloud) | Sentinel (propriétaire) | Terraform pre-apply | Verrou HashiCorp mais puissant |
| AWS Cedar | AWS (open-source 2023) | Cedar (custom, ABAC) | Authorization APIs | Modern, formellement vérifié |
Recommandation 2026 selon contexte
- Stack Kubernetes dominante → Kyverno en premier, OPA Gatekeeper en complément si cas avancés.
- Stack multi-contexte (K8s + Terraform + API) → OPA comme socle, Conftest pour Terraform.
- Contexte HashiCorp Terraform Enterprise ou Cloud → Sentinel natif, intégration transparente.
- Authorization API complexe avec ABAC → AWS Cedar (open-source 2023), CASBIN alternative.
Outils complémentaires : Conftest (OPA pour Terraform via CLI), Regula (Fugue, scan IaC avec OPA), Styra DAS (commercial OPA management at scale), Gatekeeper Policy Library (bibliothèque de policies K8s prêtes à l'emploi).
3. OPA et Rego — le moteur général-purpose
OPA (Open Policy Agent) est un moteur de policy général-purpose écrit en Go, graduated CNCF 2021. Il évalue des policies Rego contre des données JSON structurées et retourne une décision (allow/deny/mutate).
Architecture OPA
- Policy : fichier Rego avec règles logiques.
- Data : données de contexte (attributs utilisateur, état cluster, configuration).
- Query : requête exécutée par l'application cliente.
- Decision : résultat booléen ou objet.
Langage Rego — propriétés :
- Déclaratif et fonctionnel.
- Inspiré de Datalog (famille Prolog).
- Pas de mutation d'état, pas de boucles impératives classiques (utilise compréhensions).
- Courbe d'apprentissage notoirement raide (2-4 semaines pour maîtrise basique).
Exemple Rego — policy refusant les Pods Kubernetes privilégiés (exploitable en portfolio GitHub) :
# kubernetes-deny-privileged-pods.rego
# Policy OPA Rego refusant les Pods Kubernetes privilegies.
# Utilisable avec OPA Gatekeeper en ConstraintTemplate.
package kubernetes.admission
import rego.v1
# Metadata de la policy
metadata := {
"title": "Deny Privileged Pods",
"description": "Refuse les Pods avec securityContext.privileged = true",
"cwe": "CWE-250 Execution with Unnecessary Privileges",
"severity": "high"
}
# Exception pour namespaces systeme (CNI, CSI drivers)
allowed_namespaces := {"kube-system", "gatekeeper-system"}
# Regle principale : deny si containers privilegies
deny contains msg if {
input.request.kind.kind == "Pod"
namespace := input.request.namespace
not namespace in allowed_namespaces
some container in input.request.object.spec.containers
container.securityContext.privileged == true
msg := sprintf(
"Pod '%s' in namespace '%s' utilise un container privilegie '%s' (refuse par policy).",
[input.request.object.metadata.name, namespace, container.name]
)
}
# Meme regle pour initContainers
deny contains msg if {
input.request.kind.kind == "Pod"
namespace := input.request.namespace
not namespace in allowed_namespaces
some container in input.request.object.spec.initContainers
container.securityContext.privileged == true
msg := sprintf(
"Pod '%s' in namespace '%s' utilise un initContainer privilegie '%s' (refuse par policy).",
[input.request.object.metadata.name, namespace, container.name]
)
}
# Tests unitaires (fichier kubernetes-deny-privileged-pods_test.rego)
# package kubernetes.admission
#
# test_privileged_pod_denied if {
# deny[_] with input as {
# "request": {
# "kind": {"kind": "Pod"},
# "namespace": "production",
# "object": {
# "metadata": {"name": "bad-pod"},
# "spec": {
# "containers": [{
# "name": "app",
# "securityContext": {"privileged": true}
# }]
# }
# }
# }
# }
# }
#
# test_non_privileged_pod_allowed if {
# count(deny) == 0 with input as {
# "request": {
# "kind": {"kind": "Pod"},
# "namespace": "production",
# "object": {
# "metadata": {"name": "good-pod"},
# "spec": {
# "containers": [{
# "name": "app",
# "securityContext": {"privileged": false}
# }]
# }
# }
# }
# }
# }Commandes OPA :
# Tests unitaires
opa test kubernetes-deny-privileged-pods.rego kubernetes-deny-privileged-pods_test.rego
# Evaluation manuelle
opa eval -d kubernetes-deny-privileged-pods.rego \
-i sample-pod.json \
"data.kubernetes.admission.deny"
# Integration avec kube-mgmt pour OPA Gatekeeper
kubectl apply -f constraint-template.yaml
kubectl apply -f constraint.yaml4. Kyverno — le moteur Kubernetes-natif
Kyverno est un moteur Policy as Code Kubernetes-natif, graduated CNCF 2023. Il utilise YAML pour exprimer les policies avec une syntaxe similaire aux manifests K8s, rendant l'adoption triviale pour les équipes familières avec Kubernetes.
Points forts vs OPA Gatekeeper
- Courbe plate : un dev K8s peut écrire sa première policy Kyverno en 30 minutes.
- Mutation facile : ajout automatique de labels, annotations, sidecars.
- Génération de ressources : création automatique de NetworkPolicy par défaut dans chaque namespace.
- Cluster policies : scope cluster-wide natif.
- Image verification : intégration Sigstore Cosign native.
Points faibles vs OPA
- Limité à Kubernetes.
- Moins flexible pour logique complexe (expressions, boucles).
- Écosystème plus jeune (2020+) que OPA (2016+).
Exemple Kyverno — policy équivalente à la Rego précédente, en YAML :
# kyverno-deny-privileged-containers.yaml
# Policy Kyverno refusant les containers privilegies.
# Pattern recommande Pod Security Standards Baseline.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged-containers
annotations:
policies.kyverno.io/title: "Disallow Privileged Containers"
policies.kyverno.io/category: "Pod Security Standards (Baseline)"
policies.kyverno.io/severity: "high"
policies.kyverno.io/description: >-
Un container privilegie equivaut a un acces root sur le node hote.
Refuse systematiquement en production. Mapping CWE-250 Execution
with Unnecessary Privileges.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: disallow-privileged-containers
match:
any:
- resources:
kinds: ["Pod"]
exclude:
any:
- resources:
namespaces: ["kube-system", "kyverno", "gatekeeper-system"]
validate:
message: >-
Les containers privilegies sont interdits. Un container privilegie
equivaut a root sur le node. Justifier via exemption namespace si
besoin legitime (CSI driver, CNI plugin).
pattern:
spec:
=(initContainers):
- =(securityContext):
=(privileged): "false"
containers:
- =(securityContext):
=(privileged): "false"
---
# kyverno-require-network-policy.yaml
# Policy Kyverno generant NetworkPolicy deny-all par defaut.
# Secure-by-default network segmentation.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-default-network-policy
spec:
rules:
- name: generate-default-deny-all
match:
any:
- resources:
kinds: ["Namespace"]
exclude:
any:
- resources:
names: ["kube-system", "kyverno", "default"]
generate:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
name: default-deny-all
namespace: "{{request.object.metadata.name}}"
synchronize: true
data:
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# kyverno-verify-images-cosign.yaml
# Policy Kyverno exigeant signature Cosign pour images production.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures-production
spec:
validationFailureAction: Enforce
background: false
webhookTimeoutSeconds: 30
rules:
- name: verify-signed-images-production
match:
any:
- resources:
kinds: ["Pod"]
namespaces: ["production"]
verifyImages:
- imageReferences:
- "ghcr.io/mycompany/*"
attestors:
- entries:
- keyless:
subject: "https://github.com/mycompany/*"
issuer: "https://token.actions.githubusercontent.com"
rekor:
url: "https://rekor.sigstore.dev"Commandes Kyverno :
# Application de policies
kubectl apply -f kyverno-deny-privileged-containers.yaml
kubectl apply -f kyverno-require-network-policy.yaml
# Tests locaux avant deploiement
kyverno test ./policies/
# Audit mode vs Enforce mode
# audit : les violations sont loggees mais le Pod est admis
# enforce : les violations bloquent l'admission
# Visualisation des violations
kubectl get policyreport -A
kubectl get clusterpolicyreport5. HashiCorp Sentinel — Terraform pre-apply policies
Sentinel est le moteur Policy as Code de HashiCorp, intégré nativement à Terraform Enterprise et Terraform Cloud. Il évalue les policies contre les plans Terraform avant l'apply, bloquant les déploiements non-conformes.
Positionnement : verrou HashiCorp (commercial uniquement en Terraform Enterprise ou Cloud payant), mais intégration workflow Terraform inégalée. Pour alternative open-source, utiliser OPA + Conftest.
Exemple Sentinel — policy refusant les Security Groups AWS avec port 22 SSH ouvert sur 0.0.0.0/0 :
# aws-restrict-ssh-security-groups.sentinel
# Policy HashiCorp Sentinel pour Terraform Enterprise/Cloud.
# Refuse les Security Groups AWS avec SSH 22 ouvert a 0.0.0.0/0.
import "tfplan/v2" as tfplan
# Recuperer toutes les ressources aws_security_group_rule du plan
security_group_rules = filter tfplan.resource_changes as _, rc {
rc.type is "aws_security_group_rule" and
rc.mode is "managed" and
(rc.change.actions contains "create" or
rc.change.actions contains "update")
}
# Regle : refuser SSH 22 ouvert au monde
main = rule {
all security_group_rules as _, rule {
not (
rule.change.after.type is "ingress" and
rule.change.after.from_port is 22 and
rule.change.after.to_port is 22 and
rule.change.after.cidr_blocks contains "0.0.0.0/0"
)
}
}
# Sortie en cas de violation
if main is false {
print("FAIL: detected SSH 22 opened to 0.0.0.0/0 in Security Group rules")
print("This is a critical security issue - use VPN or bastion host instead")
}6. AWS Cedar — authorization engine formellement vérifié
AWS Cedar est un moteur d'authorization open-source publié par AWS en 2023, utilisé en interne pour AWS Verified Permissions. Spécificité : langage formellement vérifié avec garanties mathématiques de correction (théorème de consistance), support ABAC (Attribute-Based Access Control) et RBAC natif.
Positionnement : excellent pour authorization API fine-grained avec des règles complexes basées sur attributs utilisateur, ressource et contexte. Alternative à Casbin, OPA pour API authorization.
Exemple Cedar — policy autorisant un utilisateur à accéder à un document si membre de son organisation :
// authorization-document-access.cedar
// Policy Cedar pour authorization API fine-grained.
// Accord d'acces a un document uniquement si membre de l'organisation proprietaire.
permit (
principal in Group::"employees",
action == Action::"readDocument",
resource is Document
)
when {
resource.organization == principal.organization &&
resource.classification in ["public", "internal"]
};
// Interdire acces explicite aux documents confidentiels sauf role specifique
forbid (
principal,
action == Action::"readDocument",
resource is Document
)
when {
resource.classification == "confidential" &&
!(principal in Group::"legal" || principal in Group::"executives")
};
// Autoriser modification uniquement au proprietaire ou editors du document
permit (
principal,
action == Action::"writeDocument",
resource is Document
)
when {
principal == resource.owner ||
principal in resource.editors
};Cedar est intégrable dans toute API via le SDK Cedar (Rust, Java, Python, JavaScript) ou via AWS Verified Permissions managed service.
7. Testing des policies — pratique obligatoire 2026
Le PaC sans tests reproduit les mêmes erreurs que le code applicatif sans tests. Trois pratiques obligatoires.
1. Tests unitaires policies
- OPA : framework natif
opa testavec fichiers*_test.rego. - Kyverno :
kyverno testavec fichiers YAML fixtures. - Sentinel : framework de tests intégré à Terraform Enterprise.
- Cedar :
cedar testavec entities JSON et test cases.
Objectif : chaque règle a au moins 2 tests — un input conforme qui passe, un input non-conforme qui échoue.
2. Tests d'intégration
Exécuter les policies contre un ensemble de manifests réels (K8s), plans Terraform (IaC), requêtes API. Conftest est l'outil standard pour integration testing avec OPA.
# Integration testing avec Conftest
conftest verify --policy ./policies/ kubernetes-manifests.yaml
conftest test --policy ./policies/ --all-namespaces ./k8s/3. Déploiement progressif audit puis enforce
Pattern recommandé obligatoire pour éviter les incidents production.
- Semaine 1-2 : déploiement en audit mode (warn, no block). Les violations sont loguées mais ne bloquent pas.
- Analyse : typiquement 20-30 % des policies initiales nécessitent ajustement après phase audit — faux positifs, cas légitimes non-prévus.
- Semaine 3 : bascule en enforce mode sur 10-20 % du périmètre (canary).
- Semaine 4 : enforce mode sur 100 % du périmètre.
8. Contribution à la conformité NIS 2, DORA, CRA
Le PaC est devenu un levier majeur de conformité réglementaire depuis 2023-2024.
| Régulation | Apport PaC | Exemples policies |
|---|---|---|
| NIS 2 (UE 2022/2555, transposée octobre 2024) | Article 21 mesures techniques automatisées et vérifiables | MFA obligatoire IAM privilégiés, segmentation réseau, chiffrement at-rest, rétention logs |
| DORA (UE 2022/2554, applicable janvier 2025) | Contrôles TIC auditables, tests de résilience | Backup obligatoire workloads critiques, redondance multi-AZ, rotation credentials TIC critiques |
| Cyber Resilience Act UE (règlement 2024/2847, applicable décembre 2027) | Gestion vulnérabilités continue, SBOM obligatoire | Policy exigeant SBOM signé à chaque image production, blocage images avec CVE critical actives |
| PCI-DSS v4.0 | Contrôles cartes de paiement | Chiffrement TLS obligatoire, segmentation réseau, logging événements sécurité |
| SOC 2 Type II | Trust Service Criteria Security | MFA, logging, encryption, access controls tous en PaC |
| ISO 27001 Annexe A (2022) | Contrôles automatisables | Traçabilité modifications, contrôles accès, cryptographie |
Bénéfice audit : l'auditeur ne demande plus une capture d'écran d'une configuration, mais consulte les logs d'évaluation PaC sur la période d'audit. Preuve automatisée et traçable — typiquement 50-70 % de réduction du temps d'audit sur les contrôles techniques.
Exemple de traduction exigence réglementaire → policy Kyverno :
Exigence NIS 2 article 21.2.e : « gestion des actifs de sécurité des systèmes d'information incluant la cryptographie et, le cas échéant, le chiffrement ».
Policy Kyverno équivalente : exiger chiffrement at-rest pour tous les Pods (via admission controller refusant les Volumes non-chiffrés) plus policy Terraform refusant les buckets S3 sans SSE-KMS, les RDS sans encryption at rest, les EBS sans encryption.
9. Pour aller plus loin
- Devenir DevSecOps sans expérience : trajectoire DevSecOps complète.
- Compétences DevSecOps à apprendre : cartographie des 7 piliers dont PaC.
- Roadmap DevSecOps : roadmap technique structurée.
- Roadmap Cloud Security : spécialisation Cloud Security Engineer.
- Qu'est-ce qu'un SBOM : complément supply chain security avec PaC.
- Secrets management pour développeurs : sujet connexe DevSecOps.
10. Points clés à retenir
- Policy as Code (PaC) : politiques de sécurité exprimées en code versionné, testable, automatiquement appliqué.
- 4 moteurs dominants 2026 : OPA (Rego, général-purpose, CNCF graduated 2021), Kyverno (YAML K8s-natif, CNCF graduated 2023), HashiCorp Sentinel (Terraform Enterprise), AWS Cedar (open-source 2023, formellement vérifié).
- 6 cas d'usage principaux : K8s admission, IaC pre-apply, CI/CD gates, API authorization ABAC, cloud governance, data governance.
- Recommandation Kyverno d'abord pour Kubernetes-only (courbe plate), puis OPA Rego pour multi-contexte.
- Testing obligatoire : tests unitaires (opa test, kyverno test), tests intégration (Conftest), déploiement progressif audit puis enforce.
- Jamais de déploiement enforce direct : audit mode 7-14 jours minimum avant enforce sur tout nouveau policy.
- Apport conformité NIS 2, DORA, CRA UE, PCI-DSS v4.0, SOC 2, ISO 27001 : preuve automatisée via logs d'évaluation, réduction 50-70 % temps audit contrôles techniques.
- CNCF écosystème : OPA graduated 2021, Kyverno graduated 2023 — signal maturité écosystème.
- PaC ne remplace pas les documents policy : traduction code des exigences, les deux couches coexistent et se synchronisent.
- Profils PaC rares : salariés 10-15 % au-dessus médiane DevSecOps en 2026 grâce à la pénurie.
Le bootcamp DevSecOps Zeroday Cyber Academy inclut un module approfondi Policy as Code avec 20+ policies Kyverno hands-on (Pod Security Standards Baseline et Restricted, image verification Cosign, génération NetworkPolicy), 10+ policies OPA Rego avec tests unitaires, intégration Conftest Terraform, déploiement progressif audit puis enforce, et préparation aux certifications CKS (Certified Kubernetes Security Specialist) plus AWS Certified Security Specialty.







