CodamAIDocs
Topicdone

Modules register their roles

Every module declares its roles and attributes itself. How CIAS takes in the declaration, embedded as a bean or standalone via /cias/fetch, and what happens with a rejected declaration.

Variants
embedded (bean)standalone (GET /cias/fetch)REJECTED: only this module drops outREFUSED: key collisionattribute conflict stops everythingmodule declares platform role → rejected

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.

Request
GET /cias/fetch
Authorization: Bearer <token with declaration-reader>
Response
{
  "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 roleMeaning
keythe role name, unique within the module
namewhat people read
groupdisplay 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:

Two ways, one declaration

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.

  1. 1
    CIAS→CDMS
    GET /cias/fetch with a token that carries the realm role declaration-reader
  2. 2
    CDMS
    checks the role, otherwise 403
  3. 3
    CDMS→CIAS
    returns 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

From the declaration into the catalog
  1. 1
    CIAS
    reads the declaration of cdms: role order-edit
  2. 2
    CIAS→Keycloak
    creates the client role order-edit on the module's client, if it is missing
  3. 3
    CIAS
    enters it in the catalog: owner cdms, scope TENANT, delegation from the installation's configuration
    Result: 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 PLATFORM would 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

What CIAS does with a faulty declaration
FindingaffectsConsequence
module not reachable or answer not 200one moduleUNREADABLE: nothing changes for this module, not even a retirement
required attribute without default value, or one attribute twice with different valuesone moduleREJECTED: the whole declaration of this module is not applied, its roles neither
attribute that another module already keeps differentlyone moduleREJECTED, as above
two modules register the same role key on one client, or the key there already belongs to another moduleone clientREFUSED: nothing is written on this client, other clients run normally
two modules describe one attribute differently in the same runeverythingSKIPPED 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

Sources in the code and the knowledge base
  • commons – IdentityRegistryInterface (roles, attributes), models.Role (key, group, name)
  • CIAS/cias-authorization – ModuleDeclaration, ModuleDeclarationPort, LocalModuleDeclarationAdapter, RemoteModuleDeclarationAdapter (only 200 is an answer), DeclarationReaderCredentials, CiasIdentityRegistry (tenant-admin, tenant-owner, tenant-user)
  • CIAS/cias-authorization – RoleReconciliationService (defect, attributeContradictions, attributeTakenFromAnotherModule, keyCollisions, define: always TENANT), ReconciliationReport.Status
  • CDMS/cdms-authorization – CiasApi (GET /cias/fetch), CiasReaderRoles; CDMS/cdms-generator – RoleRegistryProcessor
  • CIAS/cias-runtime – application.yml (codamai.cias.authorization.declarations), CiasDeclaredRoleDelegationConfiguration
  • CIAS/cias-authorization/docs/adr – ADR-023, ADR-025, ADR-027, ADR-028, ADR-031, ADR-040
Search