CodamAIDocs
Topicdone

The ceiling: nobody grants more than they have

The rule above every write path: a grant never exceeds the granter. What it means for roles, groups and attributes, and how it differs from delegation.

Variants
RolesGroups (through their roles)Attributes (range of values)platform-admin

What this is about

Above every path on which CIAS grants permissions stands one rule:

The ceiling is not a setting. There is no switch, no role and no entry in the role catalog that turns it off.

Why is it needed? Without a ceiling, a tenant administrator could give a new colleague, or themselves, a role they never had. A single careless entry in the catalog would then be a path to every permission in the installation.

The set diagram

Picture a person’s permissions as a set. What they grant must lie entirely inside this set.

flowchart LR
    subgraph H["What Anna holds in tenant nordbau"]
      direction TB
      R1["hr-employee-read"]
      R2["hr-employee-edit"]
      A1["attribute projects = alpha, beta"]
    end
    V1["grants hr-employee-read"] -- "contained ✔" --> R1
    V2["grants projects = alpha"] -- "contained ✔" --> A1
    V3["grants hr-salary-read"] -. "not contained ✘" .-> H
    V4["grants projects = gamma"] -. "not contained ✘" .-> H

Anna may pass on what is in the box, and nothing beyond it. Whether Anna may pass it on at all is decided by delegation as well.

Delegation and ceiling are two questions

Easily confused:

Delegation
may you pass this on at all?
  • a list in the role catalog: who may grant the role
  • configurable per installation
  • protects against everyone handing out permissions
Ceiling
do you have at least this much?
  • compares with what you hold yourself
  • not configurable
  • protects against someone making an account stronger than themselves

Both have to agree. Neither replaces the other: having a role does not mean you may pass it on. And being on the delegation list only lets you grant what you hold yourself.

A tenant administrator wants to grant a role
Delegation allows it?In their own tenant?Do they hold the role themselves?Result
no––403
yesno–403
yesyesno403, the ceiling applies
yesyesyesrole is granted

For a role grant, all refusals look the same: 403 with the text not permitted, without a reason. That way nobody can find out the installation’s rules by trial and error. CIAS writes the exact reason to the log. See Refusals that reveal nothing.

CIAS decides what you hold

The obvious idea would be to compare the roles in the caller’s token. That does not work. The token only contains the client of this deployment, and the role names appear there without their client. cdms-backend / model-editor and crms-backend / model-editor would look the same.

So CIAS calculates what you hold from its own records:

How your ceiling in the tenant comes about
  1. CIAS
    Person
    Does the token belong to a person CIAS knows?
    ↳ no you hold nothing
  2. CIAS
    Grants
    Which of your role grants are active now and apply globally or in exactly this tenant?
  3. CIAS
    Groups
    Which groups are you a member of? Their roles count too
  4. CIAS
    Attributes
    Which attribute values do you have in exactly this tenant?
  5. Your ceiling, exact down to client and key

It follows that:

  • A grant that starts later or has expired does not count.
  • A role you have in another tenant does not count here.
  • A role that someone granted by hand in the Keycloak console does not count. CIAS does not know it. You can then pass on less than you actually have. That is the safe direction.

This only works because only CIAS writes permissions into Keycloak. See The write direction.

Each variant

Ceiling for roles, groups, attributes and the platform administrator

When: Someone grants a role by hand.

  1. 1
    Admin→CIAS
    grants cdms-backend / hr-employee-edit to a person in tenant nordbau
  2. 2
    CIAS
    Is the role a platform role? Then only a platform administrator may
  3. 3
    CIAS
    Is the caller on the role's delegation list?
  4. 4
    CIAS
    Is nordbau the tenant from their token?
  5. 5
    CIAS
    Do they hold cdms-backend / hr-employee-edit themselves in nordbau?
  6. 6
    CIAS→Keycloak
    writes the grant

Result: Granted, or 403 at the first check that fails.

When: It is about groups, as the source of your permissions or as something being granted.

For your ceiling, the roles of your groups count, not the membership. Being a member of a group is not a permission of its own. Whoever adds a person to a group gives them all roles of the group at once. Groups and members are managed only by a platform administrator, who holds every permission.

Result: Group roles count towards what you hold.

When: Someone writes an attribute value per tenant, for example projects for a person in nordbau.

  1. 1
    CIAS
    Is the attribute registered in the catalog? If not, nobody may write it
  2. 2
    CIAS
    Does the attribute's delegation allow the caller to write?
  3. 3
    CIAS
    Is every written value contained in their own value in this tenant?
  4. 4
    CIAS
    stores the values, all or none

Result: Written, or 403. If one value fails, nothing is written at all.

When: The caller has the role platform-admin.

A platform administrator creates roles, maintains the delegation and can therefore reach every permission anyway. Their ceiling is therefore every permission. This is not an exception to the rule but its application: they hold everything, so they may grant everything. Without this, a fresh installation could never go live, because the first administrator could give nobody anything.

Result: Always passes the ceiling.

Attributes: when a value is “contained”

In CDMS an attribute value narrows down rows. One more value is more reach, and * turns the filter off. CIAS therefore compares exactly the way the filter reads the values: split at commas, spaces trimmed, * as “everything”.

May someone with this own value write that value?
own valuewritten valueResult
alpha, betaalphaallowed, alpha is contained
alpha, betabeta, alphaallowed, order does not matter
alpha, betagammarefused
alpha, beta*refused, * is more than any single value
*anythingallowed
nonealpharefused, whoever has nothing gives nothing
–emptyallowed: clearing takes reach away. Delegation still has to agree

Where the ceiling applies

PathWho may take itCeiling
grant a role by handper delegation, in their own tenantyes, as the last check
write a rule for the registration’s initial rolesper delegationyes: whoever writes a rule must hold every role in it
write an attribute value per tenantper the attribute’s delegationyes, with the value comparison above
create and change groups, add membersplatform administratoralways passes
write an attribute value on the person (profile in Keycloak)platform administratoralways passes

Next

Sources in the code and the knowledge base
  • CIAS/CLAUDE.md – §13.3 the ceiling
  • CIAS/cias-authorization/docs/adr – ADR-043, ADR-048
  • CIAS/cias-authorization – ConferralCeiling, AttributeContainment, AttributeWritePermission, RoleAssignmentService.authorize, AuthorizationExceptionHandler
  • CIAS/cias-registration – RegistrationRoleRuleService, ConferralCeilingPort
  • CIAS/cias-user – TenantBoundAttributeService, UserExceptionHandler
Search