Sécurité

Open Policy Agent (OPA)

Policy engine CNCF Graduated - langage Rego déclaratif pour APIs, microservices, K8s (via Gatekeeper), Terraform et tout système distribué.

Open Policy Agent (OPA) est un moteur de policies généraliste, projet CNCF Graduated depuis février 2021. Son principe est de découpler la prise de décision de policies de son application : OPA expose une API REST qui évalue des règles écrites en Rego (langage déclaratif propre à OPA) et retourne une décision. Il n'est pas limité à Kubernetes - OPA est utilisé pour l'autorisation d'APIs REST, l'accès aux données, la validation d'infrastructure Terraform, ou comme moteur de policies dans les service meshes (Envoy/Istio).

Dans Kubernetes, OPA s'utilise le plus souvent via Gatekeeper (admission controller), mais peut aussi être déployé en sidecar ou service autonome.


Informations essentielles

Origine : Styra → CNCF  ·  Licence : Apache 2.0  ·  Architectures : x86_64, ARM64

Liens : Site officiel  ·  Documentation  ·  GitHub  ·  Releases

Support : CNCF Graduated depuis février 2021. Releases fréquentes.

Stack par défaut

ComposantValeur
LangageRego (déclaratif, inspiré de Datalog)
InterfaceAPI REST (/v1/data, /v1/query) ou bibliothèque embarquée
DeploymentBinaire standalone, sidecar, ou bibliothèque Go
BundlesPolicies et données distribuées en bundle OCI/HTTP
Decision logAudit de toutes les décisions prises

Concepts clés

ConceptDescription
PolicyFichier .rego définissant des règles avec allow/deny/violation
DataDonnées contextuelles (JSON) chargées pour évaluer les policies
InputDonnées de la requête courante (ex: token JWT, manifest K8s)
BundleArchive de policies + data distribuée via HTTP ou OCI
Decision LogJournal de toutes les décisions OPA (audit trail)
Rego PlaygroundInterface web pour tester les policies en ligne

Prérequis

RessourceValeur
OSLinux, macOS, Windows
Mémoire128 Mi minimum (selon la taille des policies/data)
RéseauAccès HTTP pour charger les bundles (si utilisé)

Installation

CLI OPA (pour développement et tests)

# Linux amd64
curl -Lo opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64_static
chmod +x opa
sudo mv opa /usr/local/bin/

opa version

OPA comme service REST

# Démarrer OPA en mode serveur avec une policy
opa run --server \
  --addr 0.0.0.0:8181 \
  --log-level info \
  my-policies/

# Tester
curl http://localhost:8181/v1/data/

OPA dans Kubernetes (sidecar ou Deployment)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-with-opa
spec:
  template:
    spec:
      containers:
      - name: my-app
        image: my-app:latest
      # OPA comme sidecar d'autorisation
      - name: opa
        image: openpolicyagent/opa:latest-static
        args:
        - run
        - --server
        - --addr=localhost:8181
        - --config-file=/etc/opa/config.yaml
        volumeMounts:
        - name: opa-policies
          mountPath: /etc/opa/policies
      volumes:
      - name: opa-policies
        configMap:
          name: opa-policies

Vérification de l'installation

# 1. Version
opa version
# OPA x.y.z (et Go version)

# 2. Évaluer une policy simple
echo '{"input": {"user": "alice", "action": "read"}}' | \
  opa eval -d - 'data.example.allow' --format pretty

# 3. Démarrer le serveur et tester le health check
opa run --server &
curl http://localhost:8181/health
# {"status": "ok"}

# 4. Test d'une policy via API REST
curl -s http://localhost:8181/v1/data/system/main \
  -H "Content-Type: application/json" \
  -d '{"input": {"method": "GET", "path": "/api/data"}}'

Écrire des policies en Rego

Structure de base

# authz.rego
package authz

# Par défaut, refuser
default allow := false

# Autoriser si l'utilisateur a le bon rôle
allow if {
    some role in input.user.roles
    role == "admin"
}

# Autoriser la lecture pour les viewers
allow if {
    input.action == "read"
    some role in input.user.roles
    role in {"viewer", "editor", "admin"}
}

Tester une policy

# Évaluer avec un input JSON
opa eval \
  --data authz.rego \
  --input '{"user": {"roles": ["viewer"]}, "action": "read"}' \
  'data.authz.allow'
# true

opa eval \
  --data authz.rego \
  --input '{"user": {"roles": ["viewer"]}, "action": "write"}' \
  'data.authz.allow'
# false

Policy pour API REST (exemple Express/Envoy)

package api.authz

default allow := false

allow if {
    is_authenticated
    has_permission
}

is_authenticated if {
    input.token != ""
    # Décoder et vérifier le JWT ici
}

has_permission if {
    permission := sprintf("%s:%s", [input.method, input.path])
    permission in data.roles[input.user.role].permissions
}

Utiliser les bundles OPA

Les bundles permettent de distribuer policies et données sans redémarrer OPA :

# opa-config.yaml
services:
- name: bundle-server
  url: https://my-bundle-server.example.com

bundles:
  main:
    service: bundle-server
    resource: /bundles/policies.tar.gz
    polling:
      min_delay_seconds: 60
      max_delay_seconds: 120

decision_logs:
  console: true
opa run --server --config-file=opa-config.yaml

OPA pour Kubernetes avec Conftest

Conftest permet d'utiliser OPA pour valider des manifests K8s dans les pipelines CI/CD, sans Gatekeeper :

# Installer Conftest
curl -Lo conftest.tar.gz \
  https://github.com/open-policy-agent/conftest/releases/latest/download/conftest_Linux_x86_64.tar.gz
tar xzf conftest.tar.gz && sudo mv conftest /usr/local/bin/

# Policy de validation (policy/k8s.rego)
cat > policy/k8s.rego <<'EOF'
package main

deny[msg] {
  input.kind == "Deployment"
  not input.spec.template.spec.securityContext.runAsNonRoot
  msg := sprintf("Deployment '%s' doit avoir runAsNonRoot=true", [input.metadata.name])
}
EOF

# Valider un manifest
conftest test deployment.yaml
# FAIL - Deployment 'my-app' doit avoir runAsNonRoot=true

Mise à jour

# Mettre à jour le binaire
curl -Lo opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64_static
chmod +x opa && sudo mv opa /usr/local/bin/

# Mettre à jour l'image Docker
docker pull openpolicyagent/opa:latest-static

# Dans K8s
kubectl set image deployment/opa opa=openpolicyagent/opa:latest-static -n <namespace>

Troubleshooting

# Mode REPL interactif pour déboguer
opa run --stdin-input -d authz.rego
> data.authz.allow with input as {"user": {"roles": ["admin"]}, "action": "write"}

# Tracer l'évaluation d'une règle
opa eval --data authz.rego --input input.json 'data.authz.allow' --explain notes

# Vérifier la syntaxe d'une policy
opa check authz.rego

# Profiler les performances
opa eval --data authz.rego --input input.json 'data.authz.allow' --profile

Policy qui retourne toujours false

# Utiliser explain pour voir pourquoi une règle ne matche pas
opa eval --data authz.rego --input input.json 'data.authz.allow' \
  --explain full 2>&1 | head -50

Commandes utiles

opa version                              # Version OPA
opa check <fichier.rego>                # Vérifier la syntaxe
opa eval -d <policy.rego> '<query>'     # Évaluer une règle
opa test <policy.rego> <test.rego>      # Exécuter les tests unitaires
opa run --server                        # Démarrer en mode serveur REST
opa build <policy.rego>                 # Compiler en bundle OCI
opa bench <policy.rego>                 # Benchmarker une policy

Ressources

Newsletter · 2 000+ abonnés

Reste au courant de ce qui bouge en prod

RudeOps veille devops hebdo, droit au but.

Gratuit · Sans spam · Désinscription en un clic