Guide de développement de politiques
English version: ../../en/guides/policy-development.md
Ce guide montre comment écrire, tester, enregistrer, simuler, activer, publier, versionner et retirer une politique
d'autorisation (Rego OPA ou règles intégrées) et un modèle de relations (OpenFGA). Écrire une politique demande
tenant_admin ou security_officer ; un developer peut simuler et lire les révisions.
Concept
Le Control Plane est le point de décision des politiques de la plateforme : chaque action sensible (exécuter un agent,
appeler un outil, synchroniser un connecteur, charger une skill) demande une décision par le Policy Contract
(contracts/v1/policy-contract.schema.json) et reçoit allow, reasons et obligations
(contracts/v1/policy-decision.schema.json). Deux types de politiques coexistent :
- Politiques d'attributs, moteur
builtin(règles JSON) ouopa(Rego), conservées dans le registre des politiques avec une révision immuable à chaque modification. - Contrôles de relations (ReBAC), répondus par OpenFGA à partir de tuples comme
owner,editor,vieweroucan_invokesur un objet.
Une politique est draft, active ou disabled ; seules les politiques active participent aux décisions, dans
l'ordre de priority.
Champs de la politique
Le corps de POST /v1/policies :
| Champ | Type | Défaut | Description |
|---|---|---|---|
name | chaîne | obligatoire | ^[a-z0-9][a-z0-9_.-]{0,99}$. |
description | chaîne | "" | Ce que la politique impose. |
version | chaîne | 1.0.0 | Étiquette de version de la politique. |
engine | énumération | builtin | builtin ou opa. |
rego | chaîne | aucun | Module Rego, obligatoire pour opa. |
rules | tableau | [] | Règles d'une politique builtin (table ci-dessous). |
priority | entier | 100 | Ordre d'évaluation, la plus basse d'abord. |
status | énumération | active | draft, active ou disabled. |
Chaque règle intégrée :
| Champ | Type | Défaut | Description |
|---|---|---|---|
id | chaîne | aucun | Identifiant de la règle, cité dans reasons. |
effect | énumération | allow | allow ou deny. |
actions | tableau | ["*"] | Actions concernées, comme agent.run. |
resource_types | tableau | [] | Types de ressources, comme agent ou connector. |
conditions | objet | {} | Conditions sur le sujet, la ressource et le contexte. |
obligations | tableau | [] | Chaque élément : type et params. |
reason | chaîne | aucun | Explication renvoyée avec la décision. |
Rego et OpenFGA
Le modèle sdks/python/src/enterprise_ai/templates/policy-pack contient des politiques Rego avec leurs tests et un modèle OpenFGA avec model.fga.yaml ; les politiques de la plateforme sont dans deploy/policies/opa et le modèle de relations dans deploy/policies/openfga/model.fga.
Une règle decision Rego renvoie allow, reasons, obligations et, pour un paquet produit (eai.rag_agent, eai.compliance...), applies : false quand l'action n'est pas de son ressort (audit.record, knowledge.query...). Le Control Plane ignore alors cette politique au lieu de lire son allow: false fermé par défaut comme un refus ; sans applies, le paquet décide de toutes les actions du locataire.
enterprise-ai create policy residency
cd residency
enterprise-ai test authz
Étapes
-
Créer le projet de politiques. Le modèle
policy-packécritpolicies/*.regoavec leurs_test.rego, un modèle OpenFGAauthz/model.fgaavec ses testsauthz/model.fga.yaml, et une requête d'exempleinputs/tool-invoke.json.enterprise-ai create policy residencyRésultat attendu : les fichiers sont listés et le projet est valide.
En cas d'échec : code de sortie 1 avec « exists » ; ajoutez
--force. -
Écrire les règles. Écrivez du Rego pour le moteur
opa, ou une liste de règles JSON pour le moteurbuiltin. Dans le portail : Studio développeur > Studio de politiques > Nouveau ; l'éditeur vérifie le JSON des règles pendant la saisie.Résultat attendu : chaque règle a un test qui autorise et un test qui refuse.
En cas d'échec : une règle sans test de refus autorise en général trop ; ajoutez le cas.
-
Tester en local.
test authzlanceopa testsur les politiques etfga model testsur chaque*.fga.yaml. Un binaireopaoufgaabsent est une erreur, jamais un succès silencieux.cd residencyenterprise-ai test authzRésultat attendu : chaque suite est déclarée PASS.
En cas d'échec : le code de sortie 1 nomme la suite en échec, ou le binaire absent.
-
Enregistrer la politique en brouillon. POST /v1/policies conserve la politique et crée la révision 1. Enregistrez-la avec
status: draftpour qu'elle ne participe pas encore aux décisions. Dans le portail : Créer.policy = client.policies.create({"name": "residency", "engine": "opa", "rego": open("policies/residency.rego").read(), "status": "draft"})Résultat attendu : 201 avec l'identifiant de la politique.
En cas d'échec : 422
validation_error(rego is required for engine opa), 503policy_engine_unavailablequand OPA refuse le module. -
Évaluer et simuler. POST /v1/policies/evaluate donne la décision des politiques actives pour une requête. POST /v1/policies/simulate compare, entrée par entrée, l'ensemble actif avec le même ensemble plus la candidate, sans aucune modification ;
recordedrejoue aussi les dernières décisions enregistrées (0 à 500). Dans le portail : Requête de test > Évaluer avec les politiques actives et Simuler la politique modifiée.client.policies.evaluate({"action": "tool.invoke", "resource": {"type": "tool", "id": "crm-search"}})client.policies.simulate({"name": "residency", "rules": []}, policy_id="<policy-id>", inputs=[{"action": "tool.invoke"}])<policy-id>: identifiant de la politique que la candidate remplace ; sans lui la candidate est ajoutée.Résultat attendu : la simulation compte
changed,allow_to_denyetdeny_to_allow.En cas d'échec : 422
simulation_engine_unsupported(seules les candidatesbuiltinsont simulées ; testez le Rego avecopa test), 422validation_errorquand niinputsnirecordedn'est fourni. -
Activer. PUT /v1/policies/{policy_id} avec
status: activecrée une nouvelle révision. Avec la livraison par défautEAI_OPA_DELIVERY=push, une politiqueopaest envoyée à OPA à l'écriture.Résultat attendu : GET /v1/policies/decisions montre les nouvelles décisions avec leurs
reasons.En cas d'échec : 503
policy_engine_unavailable; vérifiezEAI_OPA_URLet le service OPA. -
Publier un bundle signé. Avec
EAI_OPA_DELIVERY=bundle, OPA interroge plutôt des bundles signés : POST /v1/policies/bundles publie une nouvelle révision, signée avec la clé deEAI_POLICY_BUNDLE_SIGNING_KEY_FILE, et OPA télécharge GET /v1/policies/bundles/{revision}/bundle.tar.gz. GET /v1/policies/engines montre la version que chaque moteur exécute réellement.Résultat attendu : les moteurs indiquent la révision publiée.
En cas d'échec : 409
policy_bundle_empty, 503policy_bundle_signing_unavailable(pas de clé de signature). -
Versionner et comparer. Chaque PUT ajoute une révision. GET /v1/policies/{policy_id}/revisions les liste et GET /v1/policies/{policy_id}/revisions/diff en compare deux (par défaut la précédente avec la dernière). Dans le portail : Studio de politiques > Révisions > Comparer les décisions des deux révisions.
Résultat attendu : les champs modifiés et les décisions qui changent.
En cas d'échec : 404
not_foundpour une révision inconnue. -
Désactiver ou supprimer. PUT avec
status: disabledretire la politique des décisions et la conserve ; DELETE /v1/policies/{policy_id} la supprime (ainsi que le module dans OPA en mode push).Résultat attendu : la politique n'apparaît plus dans les
reasonsdes nouvelles décisions.En cas d'échec : 503
policy_engine_unavailableà la suppression ; la politique est conservée, réessayez.
Désactiver une politique de refus peut ouvrir un accès immédiatement. Simulez sur les décisions enregistrées avant de la désactiver en production.
Gouvernance
POST /v1/policies crée une politique, POST /v1/policies/simulate simule une révision candidate, POST /v1/policies/evaluate évalue une requête, POST /v1/policies/bundles publie un bundle OPA signé, POST /v1/authz/check vérifie une relation.
client.policies.simulate({"rules": []}, policy_id="<policy-id>", recorded=True)
client.policies.diff("<policy-id>", from_revision=1, to_revision=2)
Les relations se gèrent avec POST /v1/authz/tuples, GET /v1/authz/tuples et DELETE /v1/authz/tuples, et se vérifient avec POST /v1/authz/check. Dans le portail : Sécurité et gouvernance > Permissions (ReBAC) et Simulateur de politiques.
Dépannage
| Symptôme | Cause | Correction |
|---|---|---|
422 validation_error sur rego | Moteur opa sans module Rego. | Envoyez rego, ou utilisez le moteur builtin. |
422 validation_error sur inputs | Simulation sans inputs et sans recorded. | Donnez des requêtes d'exemple ou un nombre de décisions enregistrées. |
422 validation_error avec contract: policy-contract | La requête évaluée ne respecte pas le Policy Contract. | Vérifiez-la selon contracts/v1/policy-contract.schema.json. |
422 simulation_engine_unsupported | La candidate utilise le moteur opa. | Testez le Rego avec enterprise-ai test authz ; ne simulez que des règles builtin. |
503 policy_engine_unavailable | OPA a refusé ou n'a pas répondu. | Vérifiez OPA et EAI_OPA_URL ; lisez reason. |
409 policy_bundle_empty | Aucune politique à mettre dans le bundle. | Créez ou activez d'abord une politique. |
503 policy_bundle_signing_unavailable | Pas de clé de signature des bundles. | Réglez EAI_POLICY_BUNDLE_SIGNING_KEY_FILE. |
404 not_found | Identifiant de politique (un UUID) ou révision inconnu. | Listez les politiques avec enterprise-ai get policies. |
| 403 sur POST /v1/policies | L'appelant n'a ni tenant_admin ni security_officer. | Demandez le rôle ; un developer peut seulement simuler. |
Étapes suivantes
- Contexte d'action et contexte d'exécution : les attributs que voit une politique.
- Guide de développement des packs pour les politiques d'un pack.
- Guide des tests et guide de référence de l'API.