Aller au contenu principal

Plan d'identité et de politiques : guide d'exploitation

Ce guide couvre Keycloak (A-03), SPIFFE/SPIRE (A-04), OpenFGA (A-05), OPA et les bundles signés (A-06, A-07), la gestion des clés KMS et HSM (A-08). Les preuves sont des tests qui démarrent les vrais composants, issus des versions officielles téléchargées par tools/iam/fetch.sh (versions épinglées, empreintes sha256 vérifiées) dans /tmp/toolchains.

ComposantVersionLicenceTest
Keycloak26.8.1Apache-2.0tests/test_iam_keycloak_real.py
SPIRE server et agent1.15.5Apache-2.0tests/test_iam_spire_real.py
OpenFGA1.22.1Apache-2.0tests/test_iam_openfga_real.py
OPA1.21.4Apache-2.0tests/test_iam_opa_bundles_real.py, tests/test_iam_fail_closed.py
SoftHSM2 (compilé depuis les sources)2.7.0BSD-2-Clausetests/test_iam_kms.py

Keycloak (OIDC, SAML, MFA)​

  • Le realm deploy/keycloak/realm-enterprise-ai.json est importé tel quel (la fédération LDAP est retirée en test, faute d'annuaire). Le flux code d'autorisation avec PKCE S256 est joué en HTTP, le jeton est accepté par le Control Plane (EAI_OIDC_ISSUER, JWKS découvert), renouvelé, puis la déconnexion révoque le refresh token (invalid_grant) et la session (userinfo 401).
  • MFA : l'administrateur plateforme porte l'action requise CONFIGURE_TOTP ; à la connexion suivante le mot de passe seul ne termine pas la connexion, un code faux est refusé, un code TOTP valide (HmacSHA1, 6 chiffres, 30 s, codes non réutilisables) passe.
  • SAML : le client https://<apps-host>/saml/metadata (assertions signées RSA-SHA256, POST) est déclaré dans le realm ; le descripteur IdP /realms/enterprise-ai/protocol/saml/descriptor est validé (SSO POST, SLO, certificat RSA 2048 bits minimum). Une connexion SAML complète par navigateur n'est pas jouée par les tests.
  • Identité résolue : GET /v1/identity/whoami.

SPIFFE et SPIRE​

  • Attestation de nœud par join token, attestation de workload unix (chemin du binaire), une entrée d'enregistrement par workload, SVID X.509 récupérés par la Workload API.
  • eai.domains.identity.spiffe : contexte TLS 1.3 qui exige le certificat du pair chaîné au bundle, puis autorise l'identifiant SPIFFE contre une liste blanche (refus par défaut). Un SVID valide mais hors liste, l'absence de certificat client ou un serveur inattendu sont refusés.
  • L'identifiant vérifié est résolu par le Control Plane (X-SPIFFE-ID derrière le proxy maillé, EAI_AUTH_SPIFFE) vers l'identité de service enregistrée ; un SVID inconnu reçoit 401 unknown_spiffe_id.

OpenFGA​

  • Modèle deploy/policies/openfga/model.fga, tuples écrits par /v1/authz/tuples et par la création des ressources, contrôles par document et par action (can_read, editor, owner, can_use), tuples contextuels (contextual_tuples de POST /v1/authz/check, jamais stockés), isolation des tenants par préfixe d'objet.
  • Panne : require_relation et /v1/authz/check répondent 502 authz_backend_error et l'audit enregistre un refus avec la raison backend_unavailable.

OPA et bundles versionnés​

  • EAI_OPA_DELIVERY=bundle : POST /v1/policies/bundles empaquette les politiques engine=opa (actives, et en brouillon pour les bibliothèques comme eai.lib) avec un .manifest qui porte la révision et les racines, signé RS256 comme opa build --signing-key. OPA interroge GET /v1/policies/bundles/current/bundle.tar.gz avec une clé API auditeur et vérifie la signature avec la clé publique déclarée sous keys.
  • Configuration OPA type : services.cp.url = https://<control-plane>/v1/policies/bundles, bundles.eai.resource = current/bundle.tar.gz, bundles.eai.signing.keyid = <EAI_POLICY_BUNDLE_KEY_ID>.
  • GET /v1/policies/engines lit la révision réellement chargée dans OPA (/v1/data/system/bundles) et indique in_sync. Un bundle signé par une autre clé est refusé par OPA, qui garde la révision précédente : in_sync passe à false.
  • Décisions : refus, autorisation, obligations (dlp masquage, approval) remontées par le PEP /v1/policies/evaluate.

Refus par défaut et fail closed​

  • OPA arrêté : l'action sensible (appel d'outil) est refusée en 403 policy_denied avec la raison policy engine unavailable: <politique>, la décision est enregistrée et auditée.
  • OpenFGA arrêté : 502 authz_backend_error, refus audité.
  • Stockage d'audit indisponible : l'écriture d'audit fait partie de la transaction de la mutation, donc la délégation de droits et la publication de politique échouent sans rien laisser ; les lectures non auditées (liste des politiques) continuent de répondre.

Simulateur et historique​

  • Chaque création, modification et suppression ajoute une révision immuable (GET /v1/policies/{id}/revisions, .../revisions/diff).
  • POST /v1/policies/simulate compare, entrée par entrée et sur les N dernières décisions enregistrées, les politiques actives et le même ensemble avec la candidate ; rien n'est modifié, l'exécution est auditée.

Séparation des rôles​

Matrice testée (tests/test_iam_role_matrix.py) : seul platform_admin crée un tenant ; tenant_admin et security_officer écrivent les politiques, les relations et les identités de service ; auditor lit l'audit, les décisions et l'état des moteurs sans rien modifier ; developer simule et lit l'historique sans publier ; viewer n'a accès à rien de tout cela. Le demandeur d'une approbation ne peut jamais la décider (separation_of_duties), l'auditeur non plus.

Rôles de l'architecture de référence​

Quinze rôles (eai.auth.ROLES, rôles de royaume Keycloak, migration V161). Les sept rôles métiers ajoutés :

RôleCapacitésJamais
soc_analystalertes, détections, incidents, investigations, réponses permises par le garde de proportionnalitéécriture de politiques, clés, administration du tenant
ai_governance_officermodèles, agents, risques, évaluations, validationinfrastructure, secrets
data_stewardsources, classification, quarantaine RAG, lignage, rétention (métadonnées)contenu des documents dont il n'est pas lecteur
application_owneragents et applications dont il est propriétaire (relation owner)ressources des autres
ai_platform_engineerfournisseurs, routes, déploiements, passerelle, runtimeIAM, export d'audit
business_ownerapprobation et validation des cas d'usageadministration
support_engineerdiagnostics, santé, SLO, opérations en lectureécritures

Les administrateurs techniques (platform_admin, tenant_admin) n'ont aucun accès implicite au contenu métier : documents, recherche RAG et mémoires dépendent de l'ACL de la ressource, et le refus est audité. Preuve : services/control-plane/tests/test_iam_role_matrix.py.

KMS et HSM : ce que le client doit fournir​

EAI_KMS_PROVIDER=openbao utilise OpenBao Transit. EAI_KMS_PROVIDER=pkcs11 utilise le HSM du client par python-pkcs11 (MIT). À négocier avec le client :

  1. La bibliothèque PKCS#11 du fabricant, montée dans le conteneur (EAI_KMS_PKCS11_MODULE).
  2. Le libellé du token ou de la partition (EAI_KMS_PKCS11_TOKEN_LABEL).
  3. Une référence au PIN utilisateur : un fichier monté depuis un secret (EAI_KMS_PKCS11_PIN_FILE), jamais le PIN dans l'environnement.
  4. Les clés, créées par le client, non extractibles et sensibles : une clé AES-256 <libellé> (CKM_AES_CBC_PAD), un secret générique <libellé>.mac (CKM_SHA256_HMAC, chiffrement puis MAC), une paire EC P-256 de signature (CKM_ECDSA_SHA256).
  5. La vérification que ces mécanismes sont autorisés sur la partition (certains HSM restreignent CBC ou exigent GCM : à valider avant la mise en service).

Toute erreur du HSM lève KmsError (code kms_unavailable) : l'appelant échoue fermé. Le chemin PKCS#11 est prouvé contre un vrai token SoftHSM2.