Worum es geht
Eingebettet heißt: CIAS ist kein eigenes Programm, sondern eine Sammlung von Jar-Dateien im selben Prozess wie die Anwendung. Ein Prozess ist ein laufendes Programm; CDMS und CIAS teilen sich dann Speicher, Datenbankverbindung und Konfiguration.
Die Anwendung, die CIAS aufnimmt, heißt hier Gastgeber. Das ist zum Beispiel das Hub-Backend oder ein mit dem CDMS-Generator erzeugtes Projekt.
Wie derselbe Aufbau mit zwei Diensten aussieht, steht unter CIAS als eigener Service. Die Unterschiede nebeneinander stehen unter Eingebettet und getrennt im Vergleich.
Das Prozessbild
flowchart LR
F["Frontend mit BFF"] -- "Bearer-Token" --> P
subgraph P["Ein Prozess"]
direction TB
FK["Filterkette<br/>(cias-authentication)"]
C["CDMS"]
CI["CIAS-Module<br/>tenancy, user, authorization, …"]
FK --> C
FK --> CI
C <-->|Methodenaufruf| CI
end
P --> SDB[("System-Datenbank<br/>CDMS-Tabellen + CIAS-Tabellen")]
C --> TDB[("Mandanten-Datenbanken")]
CI -- "Adapter" --> K[(Keycloak)]
FK -- "Schlüssel, Token-Tausch" --> K
classDef client fill:#475569,stroke:#475569,color:#fff
classDef cdms fill:#1976d2,stroke:#1976d2,color:#fff
classDef cias fill:#8e24aa,stroke:#8e24aa,color:#fff
classDef idp fill:#c2410c,stroke:#c2410c,color:#fff
classDef db fill:#4d7c0f,stroke:#4d7c0f,color:#fff
class F client
class C cdms
class FK,CI cias
class K idp
class SDB,TDB db
Alles innerhalb des Kastens ist ein Programm. Nach außen gehen nur noch drei Leitungen: zur Datenbank, zu Keycloak und zum Frontend.
Welche Module ein Gastgeber einbindet
CIAS besteht aus vielen kleinen Modulen, die jeweils ein eigenes Jar sind. Ein Gastgeber nimmt nicht automatisch alle. Es gibt zwei Wege, sie einzubinden.
cias-spring-boot-starter- eine Abhängigkeit, die alle Fachmodule mitbringt:
cias-tenancy,cias-user,cias-authorization,cias-registration,cias-notification,cias-audit - verdrahtet sie selbst (Auto-Konfiguration), der Gastgeber schreibt keine Konfigurationsklassen
- baut auch die Ports zum Identity Provider, den ersten Start (Bootstrap) und die Zeitgeber
- bringt einen eigenen Migrationslauf für die CIAS-Tabellen mit
- so läuft der eigenständige CIAS-Dienst
cias-runtime
- der Gastgeber nennt jedes Modul einzeln in seiner
pom.xml - er schreibt die Verdrahtung selbst, in eigenen Konfigurationsklassen
- er nimmt nur, was er braucht – oft
cias-tenancy,cias-user,cias-authorization,cias-iam-keycloak - so arbeitet das Hub-Backend, und so erzeugt der CDMS-Generator ein Projekt mit
cias: EMBEDDED
Warum überhaupt ohne Starter? Weil der Starter mehr mitbringt, als ein CDMS-Gastgeber will: seinen eigenen Aufrufer-Kontext, seinen eigenen Migrationslauf und eine Bohne für den Identity Provider, die den Start abbricht, wenn kein Anbieter eingestellt ist. Ein Gastgeber, der CIAS nur schlafend mitführen möchte, nimmt deshalb die einzelnen Jars.
Kein CIAS-Modul schaltet sich selbst ein
Jedes Modul hängt an einem Schalter codamai.cias.<modul>.enabled, und keiner dieser Schalter hat einen Standardwert. Das ist Absicht: CDMS durchsucht beim Start alle Klassen unter com.codamai. Ohne diese Schalter würde CIAS in jeder Anwendung anspringen, die das Jar zufällig auf dem Klassenpfad hat.
Der Starter umgeht die Suche auf einem zweiten Weg: er meldet sich als Auto-Konfiguration an, und Auto-Konfigurationen sind von der Klassensuche ausgenommen. Er kommt also, weil das Jar da ist und die Bedingungen passen, nicht weil jemand einen Paketnamen durchsucht hat.
Wie CDMS CIAS aufruft
Eingebettet sind alle drei Fragen zwischen CDMS und CIAS gewöhnliche Methodenaufrufe. Kein HTTP, kein Token, keine Zeitüberschreitung.
| Frage | Wer fragt | Wer antwortet | Wie |
|---|---|---|---|
Darf Mandant kunde-a bedient werden? | das Mandanten-Tor in cias-authentication | LocalTenantLookupAdapter in cias-tenancy | Methodenaufruf |
| Welche mandantengebundenen Attributwerte hält diese Person hier? | der Attribut-Lookup in cias-authentication | LocalTenantBoundAttributeAdapter in cias-user | Methodenaufruf |
| Welche Rollen und Attribute meldet CDMS an? | der Abgleich in cias-authorization | LocalModuleDeclarationAdapter liest die Bean des Gastgebers | Methodenaufruf |
Ein paar Wörter dazu:
- Das Mandanten-Tor ist die Stelle, die vor jeder Anfrage prüft, ob der Kunde überhaupt bedient wird. Details unter Den Mandanten zulassen.
- Ein Attribut ist ein Wert an einer Person, mit dem CDMS Zeilen filtert, etwa
regionen. Manche gelten je Mandant getrennt, siehe Ein Wert pro Person oder pro Mandant. - Die Deklaration ist die Liste aller Rollen und Attribute, die ein Modul kennt. Siehe Module melden ihre Rollen an.
- Eine Bean ist ein Objekt, das Spring beim Start erzeugt und verwaltet. „Als Bean deklarieren“ heißt hier: das Objekt liegt schon im Prozess, man muss es nur benennen.
Die Deklaration als Bean
Eingebettet fragt CIAS den Endpunkt GET /cias/fetch nicht an. Stattdessen nennt die Konfiguration je Modul den Namen der Bean, die die Deklaration hält:
codamai:
cias:
authorization:
declarations:
modules:
- name: cias
client: ${cias_client}
bean: ciasIdentityRegistry
- name: cdms
client: ${cias_client}
bean: roleRegistryService
Beide Module liegen im selben Prozess und teilen sich deshalb einen Keycloak-Client. name sagt, wessen Rollen welche sind; ohne den Namen könnte der Abgleich sie nicht auseinanderhalten. roleRegistryService ist die Klasse, die der CDMS-Generator aus den Modellen schreibt.
Jeder Eintrag nennt entweder eine Bean oder eine URL, nie beides und nie keines von beidem. Wer sich vertippt, bekommt den Fehler beim Start und nicht Wochen später beim Abgleich.
Eine Anfrage von vorn bis hinten
sequenceDiagram
participant B as BFF
participant F as Filterkette (CIAS)
participant T as Mandanten-Tor (CIAS)
participant U as cias-user
participant C as CDMS
participant DB as Mandanten-DB
B->>F: POST /api/rest/crm/customer/query + Token
F->>F: Token prüfen, tauschen, Mandant auflösen
F->>T: darf "kunde-a" bedient werden?
Note over F,T: Methodenaufruf, kein Netz
T-->>F: ja (30 s gemerkt)
F->>U: welche Attributwerte hält die Person in "kunde-a"?
U-->>F: regionen = [nord]
F->>C: RequestContext gefüllt
C->>DB: SELECT … (nur erlaubte Zeilen)
DB-->>C: Zeilen
C-->>B: data + meta
Die 30 Sekunden sind der Vorrat des Mandanten-Tors (codamai.cias.tenant-gate.ttl). Eingebettet spart er nur eine Datenbankabfrage – ein Ausfall von CIAS allein ist hier nicht möglich, weil CIAS mit dem Prozess steht und fällt.
Welche Datenbank CIAS nutzt
Eingebettet hat CIAS keine eigene Datenbank. Seine Tabellen liegen in der System-Datenbank des Gastgebers, neben dessen eigenen Tabellen. Das muss so sein: cias_tenant listet alle Mandanten der Installation auf und kann deshalb nicht einmal pro Mandant existieren.
Welche Datenbanken es sonst gibt, steht unter Welche Datenbank? Das Persistenzziel.
Wie die Tabellen entstehen
Wann: Der Gastgeber nimmt cias-spring-boot-starter und schaltet codamai.cias.migration.enabled: true.
Der Starter führt einen eigenen Flyway-Lauf je Modul aus, jeder mit einer eigenen Historientabelle (flyway_schema_history_cias_tenancy, …_cias_user, …). Das ist nötig, weil jedes CIAS-Modul ein eigenes Repository ist und seine Zählung bei V1__ beginnt – sechs Module mit sechs Skripten „Version 1“ passen nicht in eine gemeinsame Historie.
-
1BuildDer Gastgeber nennt die Orte, die er migriert – je Modul einen. Ein genannter Ort ohne Skripte bricht den Start ab
-
2DatenbankFehlt die Historientabelle eines Moduls, beginnt der Lauf bei Version 0 und wendet alle Skripte anDie übliche Grundlinie „Version 1“ wäre hier falsch: das Schema ist nach dem ersten Modul nie mehr leer, und das zweite Modul würde seine eigene
V1__als „schon erledigt“ überspringen. -
3CIASErst danach startet die PersistenzschichtErgebnis: Jedes Modul hat seine eigene Historie und kann für sich weiterwandern
Wann: Der Gastgeber bindet die Module einzeln ein, wie das Hub-Backend oder ein generiertes Projekt.
Dann gibt es keinen CIAS-Migrationslauf. Der Gastgeber meldet die CIAS-Entitäten stattdessen bei seiner eigenen Persistenz an – eine ManagedTypesContribution mit Geltungsbereich SYSTEM – und die Tabellen entstehen auf demselben Weg wie die Tabellen des Gastgebers.
Ergebnis: Ein Schema, ein Weg, keine zweite Migrationsmaschinerie im Prozess.
Wie ein CDMS-Projekt sein Schema führt, steht unter Datenbanken und Verbindungspools.
Was der Gastgeber selbst beisteuern muss
CIAS weigert sich, ein paar Dinge zu erraten. Ohne Starter nennt der Gastgeber sie in einer eigenen Konfigurationsklasse; mit Starter füllt der Starter die technischen Teile, die Sicherheitsaussagen bleiben beim Gastgeber.
-
1EntwicklerWelche Rollen die Plattform verwalten (
codamai.cias.platform-administrator-roles)Ohne Standardwert. Eine leere Angabe heißt „niemand“ und ist eine gültige Aussage; eine geratene Standardrolle würde die Plattformverwaltung an den verteilen, der zufällig diese Rolle hält. -
2EntwicklerWer gerade aufruft – ein
CallerContextProvider, der Benutzer und Rollen aus dem Anfragekontext liestCDMS führt diesen Kontext ohnehin. Eine Anfrage ohne Benutzer ist anonym und kein Fehler, denn Systemläufe haben keinen Aufrufer. -
3EntwicklerDie Entitäten anmelden, damit die CIAS-Tabellen zur System-Datenbank gehören
-
4EntwicklerEine Transaktionsklammer für die schreibenden CIAS-DiensteCDMS arbeitet ohne zentralen Transaktionsmanager – seine Grenze ist die Anfrage, nicht die Methode. Der Gastgeber baut die Klammer deshalb lokal und stellt sie nur CIAS zur Verfügung.
-
5EntwicklerWelche Rollen
GET /cias/fetchlesen dürfen (codamai.cdms.cias.reader-roles)Ergebnis: Auch eingebettet ist der Endpunkt vorhanden und geschützt. Vorbelegt ist die Realm-Rolledeclaration-reader.
Fallen
Weiter
- CIAS als eigener Service: dieselbe Fachlichkeit mit zwei Diensten
- Eingebettet und getrennt im Vergleich: alle Unterschiede in einer Tabelle
- Warum beide Betriebsarten fachlich gleich sind
- Was eingestellt wird und SINGLE oder MULTI
- Die Beteiligten einer Anfrage
- CIAS als Brücke zum Identity Provider