Concepts

SCIM 2.0 : provisionner les utilisateurs et les groupes

Sur cette page

À partir de la version 3.38.0, TOSIAM est un fournisseur de service SCIM 2.0 (RFC 7643 et RFC 7644). Un outil de gestion des identités, comme TOSIDM, Microsoft Entra ID ou Okta, crée, modifie, désactive et supprime les utilisateurs et les groupes d’un royaume.

Les écritures passent par les dépôts d’identités, jamais directement par l’annuaire. Les caches et les notifications aux autres serveurs du site restent donc justes, et un utilisateur désactivé perd ses accès en cours, voir Désactivation d’un compte et révocation des accès.

1. Activer SCIM dans un royaume#

SCIM est désactivé par défaut. Il faut trois choses, dans le royaume.

Un client OAuth2 autorisé à utiliser le flux client_credentials avec la portée tosiam:scim. Sa durée de vie de jeton se règle sur le client.

Un compte de service : un utilisateur actif du royaume, qui n’est pas un super-utilisateur, et qui a le privilège de délégation RealmAdmin, directement ou par l’un de ses groupes. Ses droits viennent de la délégation, jamais du client ni du jeton.

Le service ScimService du royaume :

Faites défiler le tableau
Réglage (API)RôleDéfaut
enabledActive SCIMfalse
clientsClients OAuth2 acceptésaucun
serviceAccountCompte de serviceaucun
userMappingAttributs des utilisateursvoir section 4
groupMappingAttributs des groupesvoir section 4
idAttributeAttribut de l’identryUUID
indexedAttributesAttributs avec un index d’égalitéuid, mail, cn, uniqueMember
substringAttributesAttributs avec un index de sous-chaîneaucun
searchWindowRésultats qu’une recherche peut parcourir1000
bash
curl -X POST "$TOSIAM/api/realms/clients/realm-config/services/ScimService" \
  -H 'Content-Type: application/vnd.tosiam+json' -H "X-XSRF-TOKEN: $XSRF" -b cookies.txt \
  -d '{"enabled": true, "clients": ["idm"], "serviceAccount": "scim-service"}'

Le client obtient ensuite un jeton, et le présente à chaque requête :

bash
curl -u idm:secret "$TOSIAM/oauth2/clients/access_token" \
  -d grant_type=client_credentials -d scope=tosiam:scim

curl "$TOSIAM/scim/v2/realms/clients/Users?filter=userName%20eq%20%22bjensen%22" \
  -H "Authorization: Bearer $TOKEN"

L’URL de locataire à donner à l’outil est /scim/v2/realms/{royaume}. root désigne le royaume racine, et : sépare les sous-royaumes (clients:mobile).

Un outil qui ne sait qu’envoyer un en-tête fixe, comme Okta, reçoit un jeton obtenu à la main : donnez alors au client une durée de vie de jeton adaptée, et prévoyez son renouvellement.

Un jeton révoqué est refusé à la requête suivante. Un retrait de délégation, ou un compte de service désactivé, prend effet en 30 secondes au plus.

Les jetons des agents IA sont refusés, même si leur client est listé.

SCIM lit les administrateurs, mais ne les écrit pas. Les utilisateurs et les groupes qui portent un privilège de délégation, les membres de ces groupes et le compte de service répondent 403 à PUT, PATCH et DELETE, et leur nom ne peut pas être recréé. Un client volé ne peut donc ni changer le mot de passe d’un administrateur, ni rejoindre un groupe privilégié. Gérez ces comptes par la console ou par /api. Un nouvel administrateur est protégé en 30 secondes au plus.

2. Points d’accès#

Faites défiler le tableau
Point d’accèsOpérations
/Users, /GroupsGET (recherche), POST
/Users/{id}, /Groups/{id}GET, PUT, PATCH, DELETE
/ServiceProviderConfig, /ResourceTypes, /SchemasGET

La recherche accepte filter, startIndex, count (200 au plus), attributes et excludedAttributes. meta.version est un ETag : If-Match protège une écriture (412), If-None-Match une lecture (304).

/Bulk, /Me et le tri ne sont pas pris en charge, comme l’annonce /ServiceProviderConfig.

Les schémas sont User, EnterpriseUser (dont manager) et Group. id est opaque et stable. Il vient de entryUUID.

Quand un PUT omet un attribut, celui-ci est vidé, sauf le mot de passe, le statut (active), et cn et sn, que l’annuaire exige. Sans members, un PUT sur un groupe ne change pas ses membres. Le mot de passe n’est jamais renvoyé.

3. Filtres et index#

Un filtre qu’aucun index ne peut servir est refusé par invalidFilter, avant toute recherche. Une liste sans filtre lit au plus searchWindow entrées, à chaque page : réservez-la aux petits annuaires ou aux tests de connexion.

Faites défiler le tableau
FormeAcceptée si
attr eq "v"attr a un index d’égalité (indexedAttributes)
attr sw "v"attr a un index de sous-chaîne (substringAttributes)
a and bl’un des deux est accepté seul
a or bles deux sont acceptés seuls
ne, co, pr, gt, ge, lt, le, notseulement sous un and accepté
ewjamais

id est toujours accepté. password ne l’est jamais.

texte
userName eq "bjensen"                                     accepté
userName eq "bjensen" and active eq true                  accepté
id eq "..." and members[value eq "..."]                   accepté
active eq true                                            refusé : pas d'index
userName co "jen"                                         refusé : pas d'index

Pour filtrer sur un autre attribut, par exemple externalId, créez l’index dans l’annuaire, puis ajoutez l’attribut à indexedAttributes.

Les listes par défaut sont celles que TosDJ et OpenLDAP indexent tous les deux. Vérifiez-les sur un annuaire existant : sur OpenLDAP, entryUUID, uid, cn, mail et uniqueMember doivent avoir olcDbIndex ... eq. TosDJ a aussi des index de sous-chaîne : pour autoriser sw, ajoutez par exemple uid, cn et mail à substringAttributes.

4. Correspondance des attributs#

userMapping et groupMapping sont des lignes cheminScim=attribut. Un attribut sensible, comme userPassword hors du chemin password ou unicodePwd, est ignoré et signalé dans les journaux. La valeur par défaut convient à TosDJ et à OpenLDAP, sans schéma à ajouter :

Faites défiler le tableau
SCIMAnnuaire
userNameuid
externalIdsunIdentityServerPPLegalIdentityAltIdValue
displayNamecn
name.givenName, name.familyNamegivenName, sn
titlesunIdentityServerPPEmploymentIdentityJobTitle
preferredLanguage, locale, timezonepreferredlanguage, preferredLocale, preferredtimezone
activeinetUserStatus
passworduserPassword
emails.valuemail
phoneNumbers.valuetelephoneNumber
addresses.formattedpostalAddress
employeeNumber, organization (entreprise)employeeNumber, sunIdentityServerPPEmploymentIdentityOrg
manager.value (entreprise)manager
displayName (groupe)cn
externalId (groupe)description
members.value (groupe)uniqueMember

Un chemin d’extension s’écrit avec son URN : urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:employeeNumber=employeeNumber.

Un attribut doit figurer dans la liste des attributs du data store, sinon le dépôt l’abandonne sans erreur. SCIM le signale alors dans les journaux, au niveau ERROR. Sur un data store créé avant la 3.38.0, ajoutez description aux attributs des groupes pour conserver l’externalId d’un groupe.

5. Plusieurs dépôts d’identités#

Un royaume est vu comme le serveur le voit : une recherche interroge chaque dépôt et combine les résultats, et une création va dans le dépôt que le serveur choisit. SCIM n’a pas de réglage de dépôt cible.

6. Audit#

Chaque écriture produit un événement d’activité AM-IDENTITY-CHANGED, avec l’identité écrite, le compte de service en runAs, et dans after le client, l’identifiant d’audit du jeton et les noms des attributs écrits, jamais leurs valeurs.

7. Limites#

Faites défiler le tableau
LimiteConséquence
userName et le displayName d’un groupe sont immuablesIls nomment l’entrée de l’annuaire : un changement est refusé (400, mutability). Avec Entra ID, un changement d’UPN échoue donc
searchWindow résultats parcourablesAu-delà, le client reçoit tooMany : il doit filtrer. Une fin de liste n’est jamais silencieuse
Un groupe de plus de searchWindow membresLu seulement avec excludedAttributes=members, jamais en partie
Active DirectoryNon pris en charge : son objectGUID est binaire
type et primary de emails et phoneNumbersNon conservés : type vaut work, et primary désigne la première valeur
Groupes imbriquésRefusés : un membre doit être un utilisateur
NomsNi =, ni *, ni caractère invisible dans un userName ou le displayName d’un groupe (400)
Annuaire partagé entre royaumesSCIM ne lit que la délégation du royaume de l’URL : une écriture dans un sous-royaume peut toucher un administrateur du royaume parent. N’activez pas SCIM sur un tel royaume

Mis à jour le