TutorielGuides

Autoriser l'accès avec les politiques de TOSIAM

Sur cette page

Une API qui décide elle-même qui peut lire ou modifier ses données finit par disperser ses règles d’accès dans son code : chaque changement demande un développement et un déploiement. TOSIAM peut porter ces règles à sa place. L’API décrit ce que l’utilisateur veut faire (une action sur une ressource), TOSIAM répond par une décision calculée à partir de politiques, et l’API applique la décision. Les règles se changent dans la console, sans toucher à l’API.

Ce tutoriel construit une API de documents : les membres du groupe lecteurs lisent, ceux du groupe redacteurs lisent et modifient, personne ne supprime. Le code est dans le dépôt tosiam-samples, dossier tosiam-policies : l’API et une commande qui l’essaie, en Node.js sans dépendance.

  1. Commande documents vers TOSIAM Connexion de dduck (REST) : jeton de session
  2. Commande documents vers API des documents GET /documents/42, en-tête iPlanetDirectoryPro : la session de dduck
  3. API des documents vers TOSIAM Évaluation : ressource https://documents.example/documents/42, sujet : la session de dduck
  4. TOSIAM vers API des documents actions: { lire: true }, attribut mail
  5. API des documents vers Commande documents 200 : le document
  6. Commande documents vers API des documents DELETE /documents/42
  7. API des documents vers TOSIAM Évaluation
  8. TOSIAM vers API des documents actions: { lire: true } : pas de supprimer
  9. API des documents vers Commande documents 403 acces_refuse
L’API ne connaît pas les règles : elle pose la question à TOSIAM pour chaque requête.

Les notions (ensemble de stratégies, type de ressource, politique, sujets et conditions) sont présentées dans Autorisation. Ce tutoriel les met en œuvre de bout en bout.

Étape 1 : le type de ressource#

Un type de ressource décrit la forme des ressources protégées (des modèles d’URL) et les actions possibles. Dans Autorisation, onglet Types de ressource, créez le type documents avec le modèle https://documents.example/documents/* :

Type de ressource documents, onglet Modèles : modèle https://documents.example/documents/* Type de ressource documents, onglet Modèles : modèle https://documents.example/documents/*
Le modèle des ressources (1) : un document est https://documents.example/documents/<id>.

La ressource n’a pas besoin d’être une vraie adresse : c’est un nom, que l’API construit à partir de la requête. documents.example n’est jamais appelé.

Onglet Actions, ajoutez les trois actions de l’API :

Type de ressource documents, onglet Actions : lire, supprimer et modifier, valeur par défaut Autoriser Type de ressource documents, onglet Actions : lire, supprimer et modifier, valeur par défaut Autoriser
Les actions lire (1), supprimer (2) et modifier (3).

La valeur à côté de chaque action (« Autoriser ») est seulement celle que la console propose quand une politique ajoute l’action : un type de ressource n’accorde rien.

Étape 2 : l’ensemble de stratégies#

Un ensemble de stratégies regroupe des politiques et fixe les types de ressource qu’elles peuvent viser. L’API le nomme dans chaque demande d’évaluation. Dans Autorisation, Nouvel ensemble de stratégies : nom documents, type de ressource documents. Une fois les politiques de l’étape 3 créées, l’ensemble les liste :

Ensemble de stratégies Documents : politiques lecture et redaction, type de ressource documents, actives Ensemble de stratégies Documents : politiques lecture et redaction, type de ressource documents, actives
Les politiques lecture (1) et redaction (2).

Quand plusieurs politiques visent la même ressource, un refus l’emporte sur une autorisation (combinateur DenyOverride).

Étape 3 : les politiques#

Deux politiques, créées par Nouvelle politique dans l’ensemble documents :

Faites défiler le tableau
PolitiqueSujetliremodifiersupprimerAttribut de réponse
lecturegroupe lecteursautorisémail
redactiongroupe redacteursautoriséautorisérefusémail

Voici redaction, section par section. Ressources : le type documents et la ressource https://documents.example/documents/*, que TOSIAM enregistre avec le port (:443) :

Politique redaction, section Ressources : type de ressource documents, ressource https://documents.example:443/documents/* Politique redaction, section Ressources : type de ressource documents, ressource https://documents.example:443/documents/*
Le type de ressource (1) et la ressource protégée (2).

Actions : lire et modifier autorisées, supprimer refusée :

Politique redaction, section Actions : lire autorisé, supprimer refusé, modifier autorisé Politique redaction, section Actions : lire autorisé, supprimer refusé, modifier autorisé
lire (1) et modifier (3) autorisées, supprimer refusée (2).

Une action absente d’une politique n’est ni autorisée ni refusée par elle ; une action qu’aucune politique n’autorise n’apparaît pas dans la décision. L’API traite les deux cas comme un refus.

Sujets : à qui la politique s’applique. Type Utilisateurs et groupes, groupe redacteurs :

Politique redaction, section Sujets : type Utilisateurs et groupes, groupe redacteurs coché Politique redaction, section Sujets : type Utilisateurs et groupes, groupe redacteurs coché
Le type de sujet (1) et le groupe redacteurs (2).

Viser des groupes plutôt que des utilisateurs : donner ou retirer un droit revient à changer l’appartenance à un groupe, sans toucher aux politiques.

Attributs de réponse : les attributs de l’utilisateur renvoyés avec la décision. Cochez mail (le champ de recherche filtre la liste) :

Politique redaction, section Attributs de réponse : attribut mail coché Politique redaction, section Attributs de réponse : attribut mail coché
L’attribut mail (1), que l’API affiche comme demandeur.

La politique lecture se construit de la même façon, avec le groupe lecteurs et la seule action lire.

Étape 4 : le compte de service et son privilège#

L’API demande les décisions avec sa propre session, celle d’un compte de service api-documents. TOSIAM n’accepte la demande que si ce compte a le privilège Entitlement Rest Access (« Appels REST d’évaluation de politique ») : sinon, il répond 403 The user has insufficient privileges. Le privilège se donne à un groupe. Dans Identités, créez l’utilisateur api-documents (mot de passe Api-Documents-2026, celui que l’API utilise par défaut, ou un autre passé dans API_DOCUMENTS_PASSWORD), puis le groupe evaluateurs avec api-documents pour membre, et activez le privilège dans l’onglet Privilèges du groupe :

Groupe evaluateurs, onglet Privilèges : Entitlement Rest Access accordé Groupe evaluateurs, onglet Privilèges : Entitlement Rest Access accordé
Le privilège Entitlement Rest Access (1), le seul dont l’API a besoin.

En ligne de commande, c’est ce que fait le script de l’exemple :

bash
ssoadm add-privileges --realm ref --idname evaluateurs --idtype Group --privileges EntitlementRestAccess

Le compte de service ne reçoit aucun autre droit : il peut demander des décisions, pas modifier les politiques.

Étape 5 : demander une décision#

L’API reçoit la session de l’utilisateur dans l’en-tête iPlanetDirectoryPro. Elle transforme la requête en question pour TOSIAM : méthode HTTP → action (GET → lire, PUT → modifier, DELETE → supprimer), document → ressource.

http
POST /tosiam/json/ref/policies?_action=evaluate
X-Requested-With: XMLHttpRequest
Accept-API-Version: resource=2.1, protocol=1.0
Content-Type: application/json
iPlanetDirectoryPro: <session du compte de service>

{
  "resources": ["https://documents.example/documents/42"],
  "application": "documents",
  "subject": { "ssoToken": "<session de l'utilisateur>" }
}

X-Requested-With est obligatoire : sans lui, TOSIAM répond 403 sans corps. application est le nom de l’ensemble de stratégies. La réponse pour dduck (groupe lecteurs) :

json
[
  {
    "resource": "https://documents.example/documents/42",
    "actions": { "lire": true },
    "attributes": { "mail": ["donald_duck@tosiam.io"] },
    "advices": {},
    "ttl": 9223372036854775807
  }
]

Pour mmouse (groupe redacteurs) :

json
[
  {
    "resource": "https://documents.example/documents/42",
    "actions": { "lire": true, "supprimer": false, "modifier": true },
    "attributes": { "mail": ["mickey_mouse@tosiam.io"] },
    "advices": {},
    "ttl": 9223372036854775807
  }
]

Une ressource qu’aucune politique ne vise (https://autre.example/documents/42) reçoit "actions": {} : rien n’est accordé. Les erreurs de TOSIAM :

Faites défiler le tableau
SituationRéponse
Session de l’utilisateur inconnue, expirée ou fermée400 « Invalid value subject »
Session de l’appelant expirée ou fermée401 « Access Denied »
Appelant sans le privilège Entitlement Rest Access403 « The user has insufficient privileges »

Dans l’API, la session du compte de service est ouverte à la première requête, partagée par les suivantes, et renouvelée une fois si TOSIAM la refuse :

javascript· api-documents/app.js
/** The decision of TOSIAM for the user's session on one resource; the caller session is renewed once. */
async function evaluate(subjectToken, resource) {
  const current = callerSession();
  const ask = async callerToken => tosiam.evaluate({ callerToken, subjectToken, resources: [resource], application: APPLICATION });
  let decisions;
  try {
    decisions = await ask(await current);
  } catch (e) {
    if (!(e instanceof TosiamError) || e.kind !== 'caller') throw e;
    // The caller session expired or was ended: a new one, and the question asked again
    if (caller === current) caller = undefined;
    decisions = await ask(await callerSession());
  }
  return decisions.find(d => d.resource === resource) ?? { actions: {}, attributes: {}, advices: {} };
}

Étape 6 : appliquer la décision#

La règle de l’API tient en une ligne : refuser, sauf si TOSIAM répond true pour cette action. Une action à false, absente, une ressource sans décision, une erreur ou un TOSIAM injoignable donnent tous un refus, jamais une opération faite par défaut.

javascript· api-documents/app.js
// Refused unless TOSIAM explicitly answers true for this action
const who = decision.attributes?.mail?.[0] ?? null;
if (decision.actions?.[action] !== true) {
  log(`${req.method} /documents/${id} → 403, ${action} refusé${who ? ` à ${who}` : ''}`);
  return send(res, 403, { error: 'acces_refuse', action, ressource: resource, advices: decision.advices ?? {} });
}
Faites défiler le tableau
CasRéponse de l’API
Action accordée200 (ou 204 pour une suppression)
Action non accordée403 acces_refuse, avec l’action et les advices
Sans session, ou session refusée par TOSIAM (400 Invalid value subject)401
Compte de service refusé ou sans privilège500 : erreur de configuration, pas un refus de l’utilisateur
TOSIAM injoignable ou réponse inattendue503

Étape 7 : lancer et tester#

bash
cd tosiam-policies
./up.sh
TOSIAM_USER=dduck TOSIAM_PASSWORD=Donald-Duck-2026 node documents/documents.js
sortie
Document 42 de http://localhost:8087, en tant que dduck :
  lire       autorisé  « Rapport annuel » (demandeur : donald_duck@tosiam.io)
  modifier   refusé
  supprimer  refusé
Session fermée.
bash
TOSIAM_USER=mmouse TOSIAM_PASSWORD=Mickey-Mouse-2026 node documents/documents.js
sortie
Document 42 de http://localhost:8087, en tant que mmouse :
  lire       autorisé  « Rapport annuel » (demandeur : mickey_mouse@tosiam.io)
  modifier   autorisé  « Rapport annuel » (demandeur : mickey_mouse@tosiam.io)
  supprimer  refusé
Session fermée.

La commande essaie vraiment les trois actions sur l’API : la modification de mmouse change le document. Sans les variables, elle demande l’identifiant et le mot de passe (masqué).

Pour voir une règle changer sans toucher à l’API : dans la console, retirez dduck du groupe lecteurs, puis relancez la commande : les trois actions sont refusées. Remettez-le dans le groupe ensuite.

Le journal de l’API (.tosiam/api-documents.log) nomme l’action, la décision et le mail de l’utilisateur, jamais une session :

sortie
2026-10-10T13:31:41.230Z GET /documents/42 → lire accordé à donald_duck@tosiam.io
2026-10-10T13:31:41.251Z PUT /documents/42 → 403, modifier refusé à donald_duck@tosiam.io

Les advices#

Une politique peut poser une condition d’environnement, par exemple un niveau d’authentification minimal (AuthLevel). Quand la session ne la remplit pas, TOSIAM ne refuse pas sèchement : il renvoie un advice, qui dit ce qui manque. Avec une troisième politique qui accorderait supprimer aux rédacteurs authentifiés au niveau 2, la réponse pour mmouse, connecté au niveau 0, devient :

json
[
  {
    "resource": "https://documents.example/documents/42",
    "actions": {},
    "attributes": { "mail": ["mickey_mouse@tosiam.io"] },
    "advices": { "AuthLevelConditionAdvice": ["2"] },
    "ttl": 9223372036854775807
  }
]

L’API renvoie les advices avec le 403, sans jamais les prendre pour un accord :

sortie
Document 42 de http://localhost:8087, en tant que mmouse :
  lire       refusé    TOSIAM demande plus : AuthLevelConditionAdvice 2
  modifier   refusé    TOSIAM demande plus : AuthLevelConditionAdvice 2
  supprimer  refusé    TOSIAM demande plus : AuthLevelConditionAdvice 2
Session fermée.

Une application peut alors relancer une authentification plus forte (voir StepUpAuthNode) et redemander la décision. Pour éviter de bloquer les autres actions, réservez les conditions à advice à des ressources distinctes (par exemple https://documents.example/suppression/*). L’exemple n’en utilise pas.

Exporter et importer les politiques#

Le modèle de l’exemple a été construit dans la console, puis exporté au format XACML :

bash
ssoadm list-xacml --realm ref --outfile /tmp/documents-policies.xml

Le script up.sh l’importe avec ssoadm create-xacml --realm ref --xmlfile documents-policies.xml. L’import crée aussi l’ensemble de stratégies et un type de ressource, nommé documentsResourceType<nombre> (le format XACML ne transporte pas le type de ressource : TOSIAM le reconstruit à partir des actions des politiques). C’est pourquoi la politique redaction refuse supprimer explicitement : sans elle, aucune politique ne nommerait l’action, et le type importé ne l’aurait pas.

En cas de problème#

Faites défiler le tableau
SymptômeCause probable
L’API répond 500, « Le compte de service n’a pas le privilège EntitlementRestAccess »Le groupe du compte de service n’a pas le privilège : TOSIAM répond 403 The user has insufficient privileges
L’API répond 500, « Le compte de service ne peut pas se connecter à TOSIAM »Compte absent, ou mot de passe différent (API_DOCUMENTS_PASSWORD)
La commande s’arrête sur « –document : identifiant … attendu »Identifiant hors de [A-Za-z0-9_-]{1,64} : l’API ne l’accepterait pas
TOSIAM répond 403 sans corps à l’évaluationEn-tête X-Requested-With absent
Toutes les actions sont refusées pour tousPolitiques absentes ou désactivées, ou application qui ne nomme pas l’ensemble de stratégies
Toutes les actions sont refusées pour un utilisateurIl n’est dans aucun groupe visé par les politiques : remettez-le dans son groupe (./up.sh ne vérifie pas les appartenances)
Toutes les actions sont refusées, avec des advicesUne condition d’environnement n’est pas remplie : voir Les advices
actions: {} pour une ressourceAucune politique ne vise cette ressource : comparez-la au modèle (TOSIAM ajoute :443 aux ressources https)
create-xacml : « XML cannot be parsed »Fichier exporté deux fois au même endroit : exportez dans un fichier neuf

En production#

  • Refus par défaut : n’exécutez une action que sur un true explicite. Une erreur, un TOSIAM injoignable ou une réponse inattendue sont des refus.
  • Un compte de service dédié, avec le seul privilège Entitlement Rest Access, et son mot de passe dans le gestionnaire de secrets de la plateforme.
  • Des groupes comme sujets, pas des utilisateurs : les droits suivent les mouvements de personnel sans toucher aux politiques.
  • Des ressources nommées par l’API, stables et sans données de l’utilisateur ; vérifiez qu’un identifiant reçu ne peut pas sortir du modèle (.., caractères spéciaux).
  • Les advices : relancez l’authentification demandée plutôt que de refuser sans explication, et ne mettez pas de condition à advice sur une ressource dont d’autres actions doivent rester accessibles.
  • Aucune session dans les journaux : ni celle de l’utilisateur, ni celle du compte de service.

Pour aller plus loin#

Mis à jour le