What this is about
The operating mode of an installation is set in codamai.persistence.tenant.mode (environment variable CODAMAI_PERSISTENCE_TENANT_MODE). There are two values:
MULTI: Every tenant has its own database. The installation has several customers.SINGLE: There is a single database. The installation has no tenants, usually only one customer, often the operator itself.
Keycloak is often shared by several installations. Its tokens carry organizations and tenant attributes that are meant for the other installations. An installation in SINGLE would never create these tenants. If it checked them anyway, the gate would refuse every request: “tenant unknown”.
SINGLE and MULTI side by side
| MULTI | SINGLE | |
|---|---|---|
| Resolution | runs, by the six rules | does not run, result always "without tenant" |
| Several organizations without selection | 403 tenant-unresolved | no error |
| Tenant gate | asks for every tenant | never asks |
| Tenant in the RequestContext | the resolved key | empty |
| List of allowed tenants | own tenant, organizations, allowedTenants | empty |
| Header tenant | selection or privileged switch | does nothing, even with the role |
| Token without tenant | 403 tenant-required, except /cias/** | admitted |
| Roles from an organization | apply in the selected tenant | do not apply |
| Creating tenants | database is set up | nothing to set up, ACTIVE right away |
| Work without a request with a named tenant | asks the gate | asks the gate anyway |
The list of allowed tenants stays empty in SINGLE on purpose. A switch is only possible into a tenant on this list. That way the tenant that was just skipped does not come back by a detour through the header tenant.
What happens to the roles without an organization
In MULTI, roles can be attached to an organization: a person has them only while working in this organization. In SINGLE there is no tenant, so there is also no organization the person is currently working in.
When: realm_access.roles in the token
Apply as in MULTI.
Result: unchanged
When: resource_access.<client>.roles in the token
Apply. They are not attached to any organization.
Result: These are the roles an installation in SINGLE works with.
When: Roles that the token grants only through a membership in an organization
Do not apply. They belong to a tenant this installation does not have.
Result: If a SINGLE installation needs these roles, they must be granted in Keycloak as global client roles.
Why one switch carries two meanings here
codamai.persistence.tenant.mode actually describes the data storage: one database or many. CIAS reads the same switch to decide how it evaluates tokens. This is intended: whether an installation has tenants is a statement about the whole installation, and a second setting could contradict the first. But you need to know the consequence:
| Who reads the switch | What it does with it |
|---|---|
| Persistence (CDMS) | SINGLE: everything into the one database, no check of the allowed tenants. MULTI: one database per tenant |
| Setup of new tenants | SINGLE: nothing to set up. MULTI: create and migrate the database |
| Filter chain (CIAS) | SINGLE: skip tenants in the token. MULTI: resolve, admit, refuse without a tenant |
So whoever sets an installation to SINGLE because it has only one database also switches off the tenant check of CIAS.
If the switch is missing entirely, that is not SINGLE. Such an installation has no CDMS persistence, for example a CIAS without any data storage for tenants. It evaluates tenants in the token and asks the gate, but does not require every request to have a tenant. Where the CDMS persistence exists, the switch must be set, otherwise the application does not start.
Pitfalls
Where to go next
- The CDMS view: SINGLE and MULTI
- Both modules together: SINGLE and MULTI across both modules
- Admit the tenant (tenant gate)