What this is about
CIAS does not invent roles. Each module knows best which permissions it needs, and registers them: CDMS for example one role per model and operation, CIAS itself tenant-admin, tenant-owner and tenant-user. This registration is called the declaration. It contains two lists: the module’s roles and the user attributes it needs.
What a module states
Every module that has roles provides a bean of type IdentityRegistryInterface. In a generated CDMS project, the generator writes it from the models.
GET /cias/fetch
Authorization: Bearer <token with declaration-reader>{
"roles": [
{ "key": "order-read", "group": "order", "name": "Read orders" },
{ "key": "order-edit", "group": "order", "name": "Edit orders" }
],
"attributes": [
{ "key": "areas", "multivalued": true, "required": false, … }
]
}| Value per role | Meaning |
|---|---|
key | the role name, unique within the module |
name | what people read |
group | display group, optional |
What a module does not state: the client, the scope, the delegation. The installation sets these three.
How CIAS reads the declaration
The installation names every module in its configuration, with name and client, and says how to reach it:
When: The module runs in the same process as CIAS.
CIAS calls the bean directly. Configuration: name, client and bean, for example bean: roleRegistryService.
Result: A method call, no sign-in needed.
When: The module is a separate service.
-
1CIAS→CDMS
GET /cias/fetchwith a token that carries the realm roledeclaration-reader -
2CDMSchecks the role, otherwise 403
-
3CDMS→CIASreturns the same bean as JSON
Result: Configuration: name, client and url, plus a reader-token for CIAS. Only 200 counts as an answer.
The name of a module matters: it says who owns a role. One client can carry several modules, for example a backend with embedded CDMS and CIAS. Without names, one module’s silence would retire the roles of another. The name must be unique and must not change between two runs: a renamed module would look like one module that withdraws all its roles and a new one that registers them.
Why only 200 counts: a 404 would mean that the endpoint is not where the configuration says. If CIAS read that as “registers nothing”, the next reconciliation would retire all roles of this module, just because of a typo.
What becomes of a registered role
-
1CIASreads the declaration of
cdms: roleorder-edit -
2CIAS→Keycloakcreates the client role
order-editon the module's client, if it is missing -
3CIASenters it in the catalog: owner
cdms, scopeTENANT, delegation from the installation's configurationResult: The role exists and can be granted. It is not granted to anyone yet.
The delegation of a new role comes from the installation, not from the declaration. A module may not decide who passes on its roles. If the configuration says nothing about a role, only a platform administrator may grant it. The standalone CIAS, for example, sets that a tenant-admin may also grant tenant-user. This initial setting is only written with the first entry. If an administrator changes it later, no reconciliation restores the old one.
No platform roles from a declaration
Every registered role becomes a client role with scope TENANT. The format has no field at all for a platform role, and that is on purpose:
- A realm role applies in all modules. A module could not oversee the effects of such a role.
- A client role with scope
PLATFORMwould only apply to people in static tenants and would disappear for people in dynamic tenants. That would not be a platform role, see Realm role, client role, organization role.
So platform roles only come from the installation’s configuration, see The platform’s realm roles.
When CIAS does not accept a declaration
| Finding | affects | Consequence |
|---|---|---|
| module not reachable or answer not 200 | one module | UNREADABLE: nothing changes for this module, not even a retirement |
| required attribute without default value, or one attribute twice with different values | one module | REJECTED: the whole declaration of this module is not applied, its roles neither |
| attribute that another module already keeps differently | one module | REJECTED, as above |
| two modules register the same role key on one client, or the key there already belongs to another module | one client | REFUSED: nothing is written on this client, other clients run normally |
| two modules describe one attribute differently in the same run | everything | SKIPPED for all: the run writes nothing |
Why an attribute conflict stops everything, but a key collision only one client: a client is a namespace of its own. Two identical role names on one client only affect this client. The user attributes, however, form one document for the whole realm. Two modules that describe a field differently describe the same field, and whoever wrote last would win.
Two modules that describe an attribute the same way are not a conflict. Both may register it.
A rejected declaration never stops CIAS, not at startup and not at any other time. CIAS is what everyone registers with. If one module’s error stopped CIAS, the way to fix it would be blocked too. The reconciliation report names the module, the attribute and the broken rule.
Pitfalls
Next
- Reconciliation with Keycloak
- The role catalog
- Both modules together: Modules register roles and attributes