Policy as Code pour le CI/CD : Appliquer des Gates de Sécurité avec OPA et Rego

Introduction : Pourquoi les Revues de Sécurité Manuelles ne Passent pas à l’Échelle

Chaque équipe d’ingénierie finit par se heurter au même mur : les revues de sécurité qui dépendent de l’œil humain ne peuvent pas suivre le rythme des pipelines CI/CD modernes. Lorsque les équipes déploient des dizaines ou des centaines de fois par jour, demander à un ingénieur sécurité de vérifier manuellement chaque plan Terraform, chaque manifeste Kubernetes ou chaque Dockerfile devient un goulot d’étranglement qui soit ralentit la livraison à un rythme d’escargot, soit est tout simplement contourné.

Les conséquences sont prévisibles. Des erreurs de configuration passent entre les mailles du filet. Des conteneurs s’exécutent en tant que root. Les images de base dérivent vers des versions non corrigées. Terraform provisionne des buckets S3 accessibles publiquement. Il ne s’agit pas de vulnérabilités zero-day exotiques — ce sont des schémas connus comme problématiques qui pourraient être détectés automatiquement si nous disposions d’un moyen systématique d’exprimer et d’appliquer des règles de sécurité.

C’est là que le Policy as Code entre en jeu. Au lieu d’intégrer des vérifications de sécurité sous forme de scripts shell fragiles dispersés dans les définitions de pipelines, le Policy as Code traite les règles de sécurité comme des artefacts de première classe : déclaratifs, versionnés, testables et applicables à chaque étape du cycle de vie CI/CD.

Dans ce guide, nous allons explorer comment utiliser l’Open Policy Agent (OPA) et son langage de politiques Rego pour construire des gates de sécurité automatisés et auditables dans vos pipelines CI/CD — des gates qui évoluent avec votre cadence de déploiement plutôt que contre elle.

Qu’est-ce que le Policy as Code ?

Le Policy as Code est une méthodologie pour définir, gérer et appliquer des règles en utilisant du code plutôt que des processus manuels ou des scripts ad-hoc. En son cœur, il s’agit d’écrire des règles déclaratives qui sont évaluées par rapport à des données structurées pour produire des décisions — autoriser, refuser ou avertir.

Concepts Fondamentaux

  • Règles déclaratives évaluées par rapport à des données structurées : Les politiques décrivent ce qui doit être vrai, et non comment le vérifier. Un moteur de politiques reçoit une entrée structurée (JSON, YAML) et évalue les règles par rapport à celle-ci pour produire une décision.
  • Séparation de la politique et de la logique du pipeline : Les politiques vivent dans leurs propres dépôts, maintenues par les équipes sécurité ou plateforme. Les définitions de pipelines référencent les politiques mais ne les contiennent pas. Cette séparation des préoccupations signifie que les changements de politique ne nécessitent pas de changements de pipeline, et vice versa.
  • Versionné, testable, révisable : Parce que les politiques sont du code, elles suivent le même cycle de vie que le code applicatif — pull requests, revues de code, tests automatisés et releases versionnées.
  • Auditable par conception : Chaque évaluation de politique produit une décision avec une trace claire de ce qui a été évalué, quelles règles ont correspondu et pourquoi. C’est essentiel pour la conformité et la réponse aux incidents.

En Quoi Cela Diffère des Vérifications par Script Shell

Beaucoup d’équipes commencent avec des scripts shell dans leurs pipelines — un grep pour « latest » dans un Dockerfile, une requête jq sur un plan Terraform. Cela fonctionne au début mais s’effondre rapidement :

  • Les scripts shell sont impératifs et fragiles — un changement mineur de format les casse.
  • Ils manquent de composabilité — combiner plusieurs vérifications nécessite une logique d’orchestration.
  • Ils produisent une sortie incohérente — pas de format standard pour les violations ou les avertissements.
  • Ils sont difficiles à tester de manière isolée.
  • Ils ne peuvent pas être facilement partagés entre équipes ou pipelines.

Le Policy as Code résout tous ces problèmes en fournissant un cadre structuré et déclaratif avec un moteur d’évaluation dédié.

Fondamentaux d’OPA et Rego

L’Open Policy Agent (OPA) est un moteur de politiques open-source et généraliste maintenu par la Cloud Native Computing Foundation (CNCF). Il découple la politique des services qui doivent l’appliquer, fournissant un cadre unique pour la politique à travers toute la stack — du contrôle d’admission Kubernetes aux gates CI/CD en passant par l’autorisation des API.

Comment Fonctionne OPA

OPA suit un modèle simple : entrée → politique → décision.

  • Entrée : Des données structurées (JSON) représentant l’élément évalué — un manifeste Kubernetes, un plan Terraform, un arbre d’analyse de Dockerfile ou une configuration de pipeline.
  • Politique : Un ou plusieurs fichiers Rego définissant des règles qui évaluent l’entrée.
  • Décision : Un résultat JSON indiquant si l’entrée est conforme, et sinon, pourquoi.

Syntaxe de Base de Rego

Rego est le langage de politique conçu spécifiquement pour OPA. Il est déclaratif, ce qui signifie que vous décrivez des conditions plutôt que d’écrire une logique pas à pas. Les éléments clés incluent :

  • Packages : Organisent les politiques de manière logique dans des espaces de noms (ex. package cicd.docker).
  • Règles : Expressions nommées qui s’évaluent à vrai ou produisent des valeurs.
  • Imports : Référencent des données depuis l’entrée ou des sources de données externes.

Un Exemple Simple : Refuser le Tag « latest »

Commençons par une règle de sécurité courante : refuser tout déploiement Kubernetes qui utilise le tag d’image latest, car cela rend les builds non reproductibles et masque la version réelle exécutée en production.

# policy/k8s/deny_latest_tag.rego
package k8s.images

deny[msg] {
    container := input.spec.template.spec.containers[_]
    endswith(container.image, ":latest")
    msg := sprintf("Container '%s' uses the 'latest' tag — pin to a specific version", [container.name])
}

deny[msg] {
    container := input.spec.template.spec.containers[_]
    not contains(container.image, ":")
    msg := sprintf("Container '%s' has no tag specified (defaults to 'latest') — pin to a specific version", [container.name])
}

Cette politique itère sur tous les conteneurs dans une spec de déploiement Kubernetes et génère un message de refus si l’image utilise :latest ou n’a aucun tag spécifié.

Exécuter OPA Localement

Vous pouvez évaluer cette politique localement avec le CLI OPA :

# Sauvegarder un exemple d'entrée
cat > input.json <<'EOF'
{
  "spec": {
    "template": {
      "spec": {
        "containers": [
          {"name": "app", "image": "myregistry/app:latest"},
          {"name": "sidecar", "image": "envoyproxy/envoy:v1.28.0"}
        ]
      }
    }
  }
}
EOF

# Évaluer la politique
opa eval --input input.json --data policy/ "data.k8s.images.deny"

La sortie inclura le message de refus pour le conteneur app utilisant :latest, tandis que le conteneur sidecar avec une version épinglée passe sans problème.

Cas d'Usage CI/CD pour OPA

OPA ne se limite pas à Kubernetes. Sa conception agnostique par rapport aux entrées le rend utile partout où vous devez valider des données structurées par rapport à des règles. Voici les cas d'usage CI/CD les plus impactants.

Valider les Manifestes Kubernetes Avant le Déploiement

Détectez les erreurs de configuration avant qu'elles n'atteignent le cluster : limites de ressources manquantes, conteneurs privilégiés, accès au réseau hôte, contextes de sécurité manquants ou labels non conformes.

# policy/k8s/deny_privileged.rego
package k8s.security

deny[msg] {
    container := input.spec.template.spec.containers[_]
    container.securityContext.privileged == true
    msg := sprintf("Container '%s' must not run in privileged mode", [container.name])
}

deny[msg] {
    not input.spec.template.spec.containers[_].resources.limits
    msg := "All containers must define resource limits"
}

Appliquer les Bonnes Pratiques Dockerfile

En utilisant des outils comme conftest avec un parseur de Dockerfile (comme la sortie JSON de hadolint ou dockerfile-json), vous pouvez appliquer des règles comme l'interdiction d'exécution en tant que root et l'épinglage des images de base :

# policy/docker/best_practices.rego
package docker

deny[msg] {
    input.stages[_].commands[i].cmd == "user"
    input.stages[_].commands[i].value == "root"
    msg := "Dockerfile must not explicitly set USER to root"
}

deny[msg] {
    stage := input.stages[_]
    stage.base_image
    not contains(stage.base_image, "@sha256:")
    not regex.match(`:.+$`, stage.base_image)
    msg := sprintf("Base image '%s' must be pinned to a tag or digest", [stage.base_image])
}

Vérifier les Plans Terraform pour les Violations de Sécurité

Convertissez un plan Terraform en JSON avec terraform show -json tfplan, puis validez-le par rapport aux politiques de sécurité :

# policy/terraform/aws_security.rego
package terraform.aws

deny[msg] {
    resource := input.resource_changes[_]
    resource.type == "aws_s3_bucket"
    resource.change.after.acl == "public-read"
    msg := sprintf("S3 bucket '%s' must not be publicly readable", [resource.address])
}

deny[msg] {
    resource := input.resource_changes[_]
    resource.type == "aws_security_group_rule"
    resource.change.after.cidr_blocks[_] == "0.0.0.0/0"
    resource.change.after.type == "ingress"
    msg := sprintf("Security group rule '%s' must not allow ingress from 0.0.0.0/0", [resource.address])
}

Valider les Configurations de Pipeline

Vous pouvez même appliquer des règles sur les définitions de pipeline elles-mêmes — en vous assurant que chaque pipeline inclut les étapes requises comme le scan SAST, la détection de secrets ou la signature d'images :

# policy/pipeline/required_steps.rego
package pipeline

required_jobs := {"sast-scan", "secret-detection", "image-sign"}

missing_jobs[job] {
    job := required_jobs[_]
    not job_exists(job)
}

job_exists(name) {
    input.jobs[name]
}

deny[msg] {
    count(missing_jobs) > 0
    msg := sprintf("Pipeline is missing required security jobs: %v", [missing_jobs])
}

Appliquer la Protection des Branches et les Politiques d'Approbation

Validez que les modifications vers les branches de production sont accompagnées des approbations requises et passent les vérifications obligatoires avant le merge. OPA peut évaluer les payloads de webhooks GitHub ou GitLab ou les réponses d'API pour appliquer ces politiques de manière programmatique.

Intégrer OPA dans les Pipelines CI/CD

La manière la plus ergonomique d'intégrer OPA dans le CI/CD est via Conftest, un outil de test construit au-dessus d'OPA et spécifiquement conçu pour valider des fichiers de configuration structurés. Il comprend nativement YAML, JSON, HCL, Dockerfile et de nombreux autres formats.

GitHub Actions : OPA avec Conftest

# .github/workflows/policy-check.yml
name: Policy Checks

on:
  pull_request:
    branches: [main]

jobs:
  validate-kubernetes:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Install Conftest
        run: |
          LATEST=$(wget -qO- "https://api.github.com/repos/open-policy-agent/conftest/releases/latest" | jq -r '.tag_name' | sed 's/v//')
          wget -q "https://github.com/open-policy-agent/conftest/releases/download/v${LATEST}/conftest_${LATEST}_Linux_x86_64.tar.gz"
          tar xzf conftest_${LATEST}_Linux_x86_64.tar.gz
          sudo mv conftest /usr/local/bin/

      - name: Validate Kubernetes manifests
        run: |
          conftest test k8s/*.yaml \
            --policy policy/k8s/ \
            --output json \
            --all-namespaces

  validate-terraform:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3

      - name: Install Conftest
        run: |
          LATEST=$(wget -qO- "https://api.github.com/repos/open-policy-agent/conftest/releases/latest" | jq -r '.tag_name' | sed 's/v//')
          wget -q "https://github.com/open-policy-agent/conftest/releases/download/v${LATEST}/conftest_${LATEST}_Linux_x86_64.tar.gz"
          tar xzf conftest_${LATEST}_Linux_x86_64.tar.gz
          sudo mv conftest /usr/local/bin/

      - name: Generate Terraform plan JSON
        run: |
          cd terraform/
          terraform init
          terraform plan -out=tfplan
          terraform show -json tfplan > tfplan.json

      - name: Validate Terraform plan
        run: |
          conftest test terraform/tfplan.json \
            --policy policy/terraform/ \
            --output json

GitLab CI : Conftest dans un Job CI

# .gitlab-ci.yml
stages:
  - validate
  - build
  - deploy

policy-check-k8s:
  stage: validate
  image: openpolicyagent/conftest:latest
  script:
    - conftest test k8s/*.yaml
        --policy policy/k8s/
        --output json
        --all-namespaces
  rules:
    - changes:
        - k8s/**/*
        - policy/k8s/**/*

policy-check-terraform:
  stage: validate
  image:
    name: hashicorp/terraform:latest
    entrypoint: [""]
  before_script:
    - apk add --no-cache wget
    - wget -q https://github.com/open-policy-agent/conftest/releases/download/v0.50.0/conftest_0.50.0_Linux_x86_64.tar.gz
    - tar xzf conftest_0.50.0_Linux_x86_64.tar.gz
    - mv conftest /usr/local/bin/
  script:
    - cd terraform/
    - terraform init
    - terraform plan -out=tfplan
    - terraform show -json tfplan > tfplan.json
    - conftest test tfplan.json --policy ../policy/terraform/
  rules:
    - changes:
        - terraform/**/*
        - policy/terraform/**/*

Conftest vs CLI OPA Brut : Quand Utiliser Lequel

  • Utilisez Conftest quand : Vous validez des fichiers de configuration (YAML, JSON, HCL, Dockerfiles) dans le CI/CD. Conftest gère le parsing des fichiers, fournit des formats de sortie structurés, supporte plusieurs types de fichiers et suit les conventions établies (règles deny, warn, violation).
  • Utilisez le CLI OPA brut quand : Vous devez évaluer des politiques par rapport à une entrée JSON personnalisée, intégrer OPA en tant que sidecar ou daemon pour des décisions en temps réel, travailler avec des bundles OPA ou avez besoin de l'API OPA complète (évaluation partielle, profilage, etc.).

Pour la plupart des cas d'usage de gates de sécurité CI/CD, Conftest est le bon choix. Il réduit le boilerplate et s'intègre proprement dans les étapes de pipeline.

Écrire des Politiques Rego Efficaces

Écrire des politiques Rego maintenables, déboguables et utiles en pratique nécessite de suivre des patterns et conventions établis.

Deny-by-Default vs Allow-by-Default

Il existe deux approches fondamentales :

  • Deny-by-default : Tout est autorisé sauf si une règle deny correspond. C'est la convention standard de Conftest et cela fonctionne bien pour les gates CI/CD où vous voulez détecter des schémas spécifiques connus comme problématiques.
  • Allow-by-default avec refus explicites : Identique au précédent — c'est le pattern le plus courant pour les cas d'usage CI/CD.

Pour une sécurité maximale, certaines organisations utilisent un modèle strict deny-by-default où l'entrée doit correspondre explicitement à une règle allow sinon elle est rejetée. Ceci est plus approprié pour le contrôle d'admission que pour les gates CI/CD.

# Deny-by-default (courant pour le CI/CD — détecte les violations spécifiques)
package k8s.images

deny[msg] {
    # Refuser explicitement les schémas connus comme problématiques
    container := input.spec.template.spec.containers[_]
    endswith(container.image, ":latest")
    msg := sprintf("Container '%s' uses ':latest' tag", [container.name])
}

# Strict allow-only (tout ce qui n'est pas explicitement autorisé est refusé)
package k8s.registries

allowed_registries := {
    "gcr.io/my-project",
    "us-docker.pkg.dev/my-project",
}

deny[msg] {
    container := input.spec.template.spec.containers[_]
    image := container.image
    not image_from_allowed_registry(image)
    msg := sprintf("Container '%s' uses image '%s' from a non-approved registry", [container.name, image])
}

image_from_allowed_registry(image) {
    some registry in allowed_registries
    startswith(image, registry)
}

Générer des Messages de Violation Significatifs

Une politique qui dit « violation détectée » est quasiment inutile. De bons messages de violation doivent indiquer à l'ingénieur ce qui ne va pas, dans la configuration cela se produit, et idéalement comment y remédier :

deny[msg] {
    container := input.spec.template.spec.containers[_]
    not container.securityContext.runAsNonRoot
    msg := sprintf(
        "Container '%s' must set securityContext.runAsNonRoot to true. "
        "See: https://wiki.internal/policies/container-security#non-root",
        [container.name]
    )
}

Test des Politiques avec opa test

Les politiques Rego doivent être testées comme le code applicatif. OPA inclut un framework de test intégré :

# policy/k8s/deny_latest_tag_test.rego
package k8s.images

test_deny_latest_tag {
    result := deny with input as {
        "spec": {"template": {"spec": {"containers": [
            {"name": "app", "image": "nginx:latest"}
        ]}}}
    }
    count(result) == 1
    contains(result[_], "latest")
}

test_allow_pinned_tag {
    result := deny with input as {
        "spec": {"template": {"spec": {"containers": [
            {"name": "app", "image": "nginx:1.25.3"}
        ]}}}
    }
    count(result) == 0
}

test_deny_no_tag {
    result := deny with input as {
        "spec": {"template": {"spec": {"containers": [
            {"name": "app", "image": "nginx"}
        ]}}}
    }
    count(result) == 1
}

Exécutez les tests avec :

opa test policy/ -v

Organiser les Politiques par Domaine

Une structure de dépôt de politiques propre rend les politiques découvrables et maintenables :

policy/
├── k8s/
│   ├── deny_latest_tag.rego
│   ├── deny_latest_tag_test.rego
│   ├── deny_privileged.rego
│   ├── deny_privileged_test.rego
│   ├── require_labels.rego
│   └── require_labels_test.rego
├── terraform/
│   ├── aws_security.rego
│   ├── aws_security_test.rego
│   ├── gcp_security.rego
│   └── gcp_security_test.rego
├── docker/
│   ├── best_practices.rego
│   └── best_practices_test.rego
└── pipeline/
    ├── required_steps.rego
    └── required_steps_test.rego

Gérer les Bundles de Politiques

Pour les organisations comptant de nombreuses équipes, la distribution des politiques sous forme de bundles OPA est l'approche recommandée. Les bundles sont des archives tar versionnées de fichiers Rego et de données pouvant être hébergées sur n'importe quel serveur HTTP, registre OCI ou stockage cloud :

# Construire un bundle
opa build -b policy/ -o bundle.tar.gz

# Pousser vers un registre OCI
conftest push myregistry.io/policies/security:v1.2.0

# Récupérer et utiliser dans un pipeline
conftest pull myregistry.io/policies/security:v1.2.0
conftest test k8s/*.yaml --policy policy/

Cette approche permet aux équipes sécurité de publier des politiques de manière centralisée tandis que les équipes applicatives consomment des versions spécifiques, et permet un déploiement contrôlé des nouvelles versions de politiques.

Faire Échouer les Pipelines de Manière Sûre et Explicite

Appliquer des politiques dans le CI/CD est autant un défi d'ingénierie que de sécurité. Déployer des échecs stricts dès le premier jour créera le chaos. Une approche mesurée est essentielle.

Gates Strictes vs Gates Souples

Conftest supporte deux types de règles qui correspondent parfaitement à cette distinction :

  • Règles deny : Gates strictes. Le pipeline échoue si une règle deny correspond.
  • Règles warn : Gates souples. Le pipeline enregistre l'avertissement mais continue. C'est inestimable pour le déploiement de nouvelles politiques.
# Commencer avec warn, promouvoir en deny une fois que les équipes se sont adaptées
warn[msg] {
    container := input.spec.template.spec.containers[_]
    not container.resources.requests
    msg := sprintf("[WARN] Container '%s' should define resource requests", [container.name])
}

Exceptions et Dérogations de Politique

Aucune politique ne peut couvrir chaque cas légitime particulier. Vous avez besoin d'un mécanisme d'exceptions qui soit auditable et ne contourne pas entièrement le système :

# policy/k8s/exceptions.rego
package k8s.images

import data.exceptions

deny[msg] {
    container := input.spec.template.spec.containers[_]
    endswith(container.image, ":latest")
    not exception_exists(input.metadata.name, container.name)
    msg := sprintf("Container '%s' uses the 'latest' tag", [container.name])
}

exception_exists(deployment, container) {
    exception := exceptions.approved[_]
    exception.deployment == deployment
    exception.container == container
    exception.policy == "deny-latest-tag"
    time.now_ns() < exception.expires_ns
}

Le fichier de données d'exceptions est également versionné et nécessite une approbation :

# data/exceptions.json
{
  "approved": [
    {
      "deployment": "legacy-app",
      "container": "app",
      "policy": "deny-latest-tag",
      "reason": "Legacy build system cannot produce tagged images — migration tracked in JIRA-1234",
      "approved_by": "security-team",
      "expires_ns": 1735689600000000000
    }
  ]
}

Rapporter les Résultats de Politique aux Tableaux de Bord

Conftest et OPA supportent tous deux la sortie JSON, ce qui facilite l'envoi des résultats vers des plateformes d'observabilité. Dans votre pipeline, capturez la sortie et envoyez-la à votre SIEM, plateforme de logging ou tableau de bord personnalisé :

# Capturer les résultats en JSON
conftest test k8s/*.yaml --policy policy/k8s/ --output json > policy-results.json

# Envoyer à votre plateforme de logging
curl -X POST https://logging.internal/api/v1/policy-results \
  -H "Content-Type: application/json" \
  -d @policy-results.json

Cela crée une piste d'audit indépendante des logs CI/CD — essentielle pour la conformité et l'analyse des tendances.

Déploiement Progressif : Mode Audit Avant Mode Application

La stratégie de déploiement recommandée pour toute nouvelle politique suit cette progression :

  1. Mode audit : Exécutez la politique sous forme de règles warn. Collectez des données sur le nombre de pipelines qui échoueraient. Partagez les rapports avec les équipes.
  2. Application souple : Gardez les règles warn mais ajoutez des notifications — alertes Slack, tickets Jira — pour que les équipes soient informées et puissent remédier.
  3. Application stricte : Promouvez les règles de warn à deny après une date limite communiquée. Assurez-vous que le processus d'exception est en place.
  4. Ajustement continu : Surveillez les faux positifs, ajustez les politiques, ajoutez de nouvelles règles basées sur les incidents et les renseignements sur les menaces.

Cette approche respecte les workflows d'ingénierie tout en élevant progressivement le niveau de sécurité.

Limitations et Compromis

Le Policy as Code avec OPA est puissant, mais comporte des compromis. Être honnête sur les limitations vous aide à prendre des décisions éclairées.

La Courbe d'Apprentissage de Rego

Rego est un langage conçu dans un but précis avec un modèle d'évaluation unique. Il n'est pas impératif — il n'y a pas de boucles ni de variables mutables au sens traditionnel. Les ingénieurs habitués à Python, Go ou Bash auront besoin de temps pour internaliser l'approche déclarative et basée sur les ensembles de Rego. Investissez dans la formation d'équipe, la programmation en binôme sur les premières politiques et une bibliothèque d'exemples de politiques bien commentés.

Performance avec des Entrées Volumineuses

OPA évalue les politiques en mémoire. Pour la plupart des cas d'usage CI/CD — manifestes Kubernetes, plans Terraform, Dockerfiles — les tailles d'entrée sont petites et l'évaluation est quasi instantanée. Cependant, des plans Terraform très volumineux (des milliers de ressources) ou des politiques complexes avec une récursion profonde peuvent causer une latence notable. Profilez les politiques avec opa eval --profile si la performance devient une préoccupation.

OPA vs Autres Outils de Politique

OPA n'est pas la seule option. Considérez les alternatives en fonction de votre stack :

  • Kyverno : Moteur de politique natif Kubernetes. Si vos politiques concernent exclusivement les ressources Kubernetes et que vous préférez des politiques en YAML plutôt qu'en Rego, Kyverno est une excellente alternative.
  • HashiCorp Sentinel : Étroitement intégré avec Terraform Cloud/Enterprise. Si votre organisation est standardisée sur les outils HashiCorp et que vous avez besoin de politiques principalement pour Terraform, Sentinel peut être plus naturel.
  • AWS Cedar : Conçu pour l'autorisation au niveau applicatif. Ce n'est pas un concurrent direct pour les cas d'usage de politique CI/CD, mais c'est pertinent si vous construisez une autorisation fine pour votre plateforme.

La force d'OPA est sa généralité. Il fonctionne avec Kubernetes, Terraform, Docker, les configurations de pipeline et toute autre donnée structurée. Si vous avez besoin de politiques sur plusieurs domaines, OPA évite la prolifération d'outils.

Dérive des Politiques et Maintenance

Les politiques sont des artefacts vivants. Elles nécessitent une maintenance continue :

  • Les nouveaux types de ressources et versions d'API nécessitent de nouvelles règles.
  • Les faux positifs érodent la confiance et doivent être traités rapidement.
  • Les exceptions s'accumulent et nécessitent une revue périodique.
  • Le turnover des équipes signifie que la connaissance de l'intention des politiques peut être perdue.

Traitez votre dépôt de politiques avec la même rigueur que votre code applicatif : assignez des propriétaires, planifiez des revues, suivez la couverture et dépréciez les règles obsolètes.

Conclusion : Le Policy as Code Est de l'Infrastructure

Le Policy as Code n'est pas un luxe ni une case à cocher pour la conformité. C'est de l'infrastructure — au même titre que votre pipeline CI/CD, votre orchestrateur de conteneurs et les API de votre fournisseur cloud sont de l'infrastructure. Cela mérite la même discipline d'ingénierie.

La voie à suivre est claire :

  1. Commencez petit. Choisissez une politique à fort impact — refuser les tags latest, exiger des limites de ressources, bloquer les buckets S3 publics — et implémentez-la avec Conftest dans un seul pipeline.
  2. Développez le réflexe. Écrivez des tests pour vos politiques. Mettez en place un dépôt de politiques avec du CI. Familiarisez l'équipe avec Rego.
  3. Étendez systématiquement. Ajoutez des politiques par domaine (Kubernetes, Terraform, Docker, configuration de pipeline). Déployez d'abord en mode audit.
  4. Opérationnalisez. Construisez des tableaux de bord. Définissez le processus d'exception. Intégrez avec votre workflow de réponse aux incidents.

Traitez vos politiques comme du code : testez-les, révisez-les, versionnez-les, déployez-les. Le résultat est une posture de sécurité qui évolue avec votre cadence de livraison — applicable, auditable et automatisée du premier commit à la production.