Identité & délégation
Toute la chaîne d’attribution repose sur une distinction : un journal qui remonte à « marie.dupont » sans pouvoir établir que c’était bien elle ne prouve rien.
Prouvée ou déclarée
Section intitulée « Prouvée ou déclarée »| Prouvée (OIDC) | Déclarée (--insecure-declared-identity) | |
|---|---|---|
principal_issuer dans le journal | l’émetteur réel | cli://declared |
| Expiration | issue du claim exp | aucune |
| Vérifié | signature, iss, aud, exp, nbf | rien |
| Usage | production | développement uniquement |
Le mode déclaré exige un drapeau dont le nom dit ce qu’il est, et sans aucune configuration d’identité la passerelle refuse de démarrer, sans repli silencieux vers un mode anonyme.
Quatre choix de conception à connaître :
- Aucun appel réseau. Le JWKS vit à l’intérieur d’un bundle d’identité signé, distribué par le plan de contrôle aux côtés du bundle de politiques. La passerelle reste déployable en air-gap et n’ajoute aucune surface sortante.
- Le bundle d’identité est signé lui aussi. Qui peut écrire ce fichier peut se forger une identité : la même menace qu’un fichier de règles non signé, méritant la même réponse.
- L’algorithme vient du JWKS, jamais de l’en-tête du jeton. La faille JWT
classique, qui consiste à déclarer
HS256et à signer en HMAC avec la clé publique de l’IdP, est couverte par un test dédié. - L’expiration est réévaluée à chaque acte, et pas seulement à l’ouverture de session. Si le jeton a été renouvelé sur disque, la passerelle enregistre une nouvelle délégation ; sans quoi un acte sous jeton renouvelé paraîtrait autorisé par une délégation déjà expirée.
La chaîne de délégation
Section intitulée « La chaîne de délégation »Un jeton qui dit « marie.dupont » ne dit pas qui agissait en son nom. L’échange de jetons RFC 8693, si. Obsign l’enregistre :
| Mode du jeton | Chaîne d’acteurs | principal_kind |
|---|---|---|
| Jeton utilisateur | u:marie.dupont | human |
Échange de jetons (claim act) | support-copilot → u:marie.dupont | delegated_human |
client_credentials | batch-agent | machine |
Le troisième cas est celui que personne ne couvre : un agent batch, sans
aucun humain derrière lui, qui supprime en production. Il est reconnu par les
marqueurs que les IdP visés émettent réellement (sub == client_id,
l’idtyp: "app" d’Entra ID, le préfixe de nom d’utilisateur
service-account- de Keycloak), et la politique peut alors l’exprimer :
@id("destructive_requires_human")forbid (principal, action == Action::"tool_call", resource)when { resource.destructive && !context.has_human_delegation };« Aucun agent ne détruit quoi que ce soit sans un humain identifiable au bout
de la chaîne. » Cedar reçoit aussi context.actor_chain,
context.delegation_depth (pour borner les topologies multi-agents) et
context.principal_kind.
Fournisseurs d’identité
Section intitulée « Fournisseurs d’identité »Rien n’est spécifique à un fournisseur, et c’est délibéré. Keycloak,
Entra ID, Okta et Ping sont des fournisseurs OIDC : ils fonctionnent tels
quels. Ce qui varie, c’est où chaque fournisseur range l’information ; le
bundle d’identité décrit donc les chemins de claims, avec * pour les
segments dépendant du client :
"claims": { "subject": "/sub", "scopes": ["/scope", "/scp"], "groups": ["/groups", "/roles", "/realm_access/roles", "/resource_access/*/roles"], "client_id": ["/client_id", "/azp"]}Ces valeurs par défaut couvrent Keycloak et Entra ID. Le cas Keycloak mérite
d’être signalé : les rôles ne sont jamais à plat. Un mapping naïf renvoie
des groupes vides, et aucune règle principal in Group::"dba" ne correspond
jamais, sans erreur visible.
Les marqueurs machine suivent le même langage de chemins et vivent à
l’intérieur du bundle signé (format obsign-identity/2) : élargir ce qui
compte comme humain doit être signé comme tout autre changement
d’autorisation.
Deux points côté realm Keycloak, à faire une fois : un mapper d’audience
(les jetons d’accès par défaut portent aud: "account", que la passerelle
refuse à juste titre), et le token exchange activé sur le client de
l’agent pour le claim act (officiellement supporté depuis Keycloak 26.2).
Pour SAML, placez Keycloak devant en pont SAML↔OIDC, et la passerelle n’a
jamais à savoir que SAML existe.
Rotation des clés
Section intitulée « Rotation des clés »Les fournisseurs font tourner leurs clés de signature couramment. La passerelle ne fait aucun appel réseau : la rotation consiste donc à recharger depuis le disque le bundle d’identité signé, là où le plan de contrôle a publié la nouvelle version.
- Déclenchée par un
kidinconnu — le signal exact d’une rotation, si bien que le rechargement ne coûte rien en fonctionnement nominal. Une seule nouvelle tentative. - La signature est revalidée à chaque rechargement — sans quoi écrire le fichier suffirait à injecter un JWKS.
- Un bundle invalide ne met jamais la passerelle à terre — déploiement raté, fichier tronqué, mauvaise signature : la configuration précédente reste en vigueur.
- Fréquence bornée — une tentative par seconde, détectée par empreinte du
contenu (la granularité de
mtimepeut manquer des écritures rapprochées). - Le rechargement est lui-même enregistré — un enregistrement
config_reloadentre dans la chaîne d’audit, tentatives rejetées comprises : déposer un JWKS malveillant sur le disque est une attaque, et la tentative est précisément ce qu’une investigation veut voir.