Worum es geht
CIAS ist keine Anwendung, die man startet, sondern eine Sammlung von Jars. Ein Jar ist eine Bibliothek, die im Klassenpfad einer Anwendung liegt. Ob ein CIAS-Modul in dieser Anwendung tatsächlich arbeitet, entscheidet allein die Konfiguration. Dass das Jar da ist, reicht nicht.
Warum kein Modul sich selbst einschaltet
Spring findet Klassen normalerweise über einen Komponentenscan: Es durchsucht Pakete nach Klassen mit Markierungen wie @Service oder @Component und baut sie zusammen. CDMS scannt dabei alles unter com.codamai — und CIAS liegt unter com.codamai.
Trüge eine CIAS-Klasse so eine Markierung, würde jede CDMS-Anwendung sie einsammeln, sobald das Jar irgendwie im Klassenpfad landet, etwa als Abhängigkeit einer Abhängigkeit. Zusammengesteckt würde sie dann mit Objekten, die es dort gar nicht gibt.
Deshalb:
-
1Buildlegt das Jar in den KlassenpfadKeine Klasse darin trägt
@Service,@Repositoryoder@Component. Der Komponentenscan findet nichts. -
2CIASeine Konfigurationsklasse je Modul registriert die Objekte ausdrücklichDer Starter meldet seine Konfigurationen zusätzlich als Auto-Konfiguration an. Auto-Konfigurationen nimmt Spring absichtlich vom Scan aus — auch das ist Schutz gegen die versehentliche Einbindung.
-
3CIASliest den Schalter des Moduls
-
4CIASSchalter steht nicht auf
true→ das Modul arbeitet nicht -
5CIASSchalter steht auf
true→ das Modul arbeitetErgebnis: Ein Modul ist an, weil jemand es hingeschrieben hat, nie weil ein Jar mitgekommen ist.
Die Schalter
Das Bild zeigt, wo die Schalter sitzen. Links das, was immer da ist, sobald die Filterkette läuft; rechts die Module, die einzeln zugeschaltet werden.
flowchart LR
subgraph P["Ein Prozess"]
direction TB
A["cias-authentication<br/>Filterkette, Mandanten-Tor<br/><i>kein Schalter: da oder nicht da</i>"]
L{"codamai.cias.tenancy.lookup"}
A --> L
L -->|local| T["cias-tenancy<br/>codamai.cias.tenancy.enabled"]
L -->|remote| C["cias-tenancy-client<br/>+ client.base-url, client.credentials"]
A -.-> U["cias-user<br/>codamai.cias.user.enabled"]
A -.-> Z["cias-authorization<br/>codamai.cias.authorization.enabled"]
A -.-> R["cias-registration<br/>codamai.cias.registration.enabled"]
A -.-> N["cias-notification<br/>codamai.cias.notification.enabled"]
A -.-> AU["cias-audit<br/>codamai.cias.audit.enabled"]
end
IP{"codamai.cias.iam-provider"}
Z --> IP
U --> IP
IP -->|keycloak| K[(Keycloak)]
Die vollständige Liste:
| Schalter | Wofür | Werte |
|---|---|---|
codamai.cias.tenancy.enabled | Mandanten führen: anlegen, sperren, schließen | true |
codamai.cias.tenancy.lookup | woher das Mandanten-Tor seine Antwort holt | local oder remote |
codamai.cias.tenancy.client.base-url | wo CIAS erreichbar ist | nur bei lookup: remote |
codamai.cias.tenancy.client.credentials.* | der eigene Client beim IAM, mit dem das Dienst-Token geholt wird (token-uri, client-id, client-secret); ohne ihn ein festes .token | nur bei lookup: remote |
codamai.cias.tenancy.rest | die Verwaltungs-API /cias/admin/tenants | true / false |
codamai.cias.tenancy.lookup-rest | der Endpunkt, den andere Dienste fragen | true / false; im eigenständigen CIAS-Dienst true |
codamai.cias.tenancy.lookup-roles | wer diesen Endpunkt fragen darf | Rollennamen |
codamai.cias.user.enabled, .rest | der Benutzerdatensatz und seine API | true / false |
codamai.cias.user.lookup-rest, .lookup-roles | Attributwerte pro Mandant für andere Dienste | true / false (im eigenständigen CIAS-Dienst true), Rollennamen |
codamai.cias.authorization.enabled, .rest | Rollenkatalog, Vergaben, Abgleich mit Keycloak | true / false |
codamai.cias.registration.enabled, .rest | Registrierung und Einladung | true / false |
codamai.cias.notification.enabled, .rest | Mailvorlagen und ihre Bearbeitung | true / false |
codamai.cias.notification.editor-roles | wer jede Mailvorlage ändern darf, auch per CIAS_NOTIFICATION_EDITOR_ROLES | Standard platform-admin,mail-template-admin |
codamai.cias.notification.mail, .mail.from | wie Mails das Haus verlassen | smtp oder log |
codamai.cias.audit.enabled | die Audit-Spur | true / false |
codamai.cias.<modul>.persistence | wie das Modul an die Datenbank kommt | jpa |
codamai.cias.iam-provider | mit welchem Identity Provider CIAS spricht | keycloak oder memory |
codamai.cias.migration.enabled | legt die Tabellen von CIAS an und hebt sie an | true / false |
codamai.cias.platform-administrator-roles | welche Rollen die Plattform verwalten | Rollennamen, leer heißt niemand |
codamai.cdms.cias.reader-roles | wer in CDMS GET /cias/fetch lesen darf | Rollennamen |
codamai.persistence.tenant.mode | die Betriebsart der Datenhaltung | SINGLE oder MULTI |
cias-authentication hat keinen eigenen Schalter. Die Filterkette prüft jedes Token, und sie arbeitet, sobald das Jar da ist. Was sie braucht, ist kein Schalter, sondern eine Antwort: codamai.cias.tenancy.lookup sagt ihr, wen sie nach dem Mandanten fragt.
Die drei Ausprägungen
Wann: Der Schalter steht auf true.
-
1CIASbaut die Objekte des Moduls zusammen
-
2CIASdie Endpunkte des Moduls antworten, die Abläufe laufen
Ergebnis: Das Modul arbeitet.
Wann: Der Schalter fehlt oder steht auf false.
„Aus“ sieht je nach Modul verschieden aus, und beides ist Absicht. Bei tenancy und audit entscheidet der Schalter, ob die Objekte überhaupt entstehen: Sie sind dann nicht da. Bei user, authorization, registration und notification entstehen die Objekte immer, und der Schalter wird dort gelesen, wo er etwas entscheidet: Der Ablauf ist dann eine Ausführung, die jeden Aufruf verweigert, und die Endpunkte antworten 404, bevor überhaupt ein Controller erreicht wird.
Ergebnis: In beiden Fällen passiert fachlich nichts. Nach außen ist der Unterschied nur, ob ein Endpunkt 404 sagt oder gar nicht erst existiert.
Wann: Eine Angabe fehlt, ohne die CIAS raten müsste.
-
1CIASfindet die Angabe nicht; einen Standardwert gibt es absichtlich nicht
-
2CIASbricht den Start ab, die Meldung nennt die Einstellung oder den Typ
Ergebnis: Die Anwendung kommt nicht hoch. Das ist besser als eine, die großzügig hochkommt.
Wann welcher Fall gilt, ist nicht Geschmackssache. Es hängt davon ab, was ein falscher Standardwert anrichten würde:
| Was fehlt | Folge |
|---|---|
codamai.cias.tenancy.lookup | Start scheitert. Ohne diese Angabe gibt es niemanden, der das Mandanten-Tor beantwortet — und ein Tor, das ohne Antwort jeden durchlässt, wäre ein Loch aus einer vergessenen Zeile. |
client.base-url bei lookup: remote | Start scheitert. Eine erfundene Adresse wäre schlimmer als keine. |
codamai.cias.iam-provider, wo die Module ihn brauchen | Start scheitert. Ein CIAS ohne Identity Provider nähme Registrierungen an, die es nie ausführen kann. |
codamai.persistence.tenant.mode, wo es CDMS-Persistenz gibt | Start scheitert. Ein Standardwert würde still eine Mandantentrennung abschalten oder eine erfinden. |
codamai.cias.notification.mail, wenn das Mailmodul an ist | Start scheitert. Der Standard log würde jede Mail als verschickt melden und keine zustellen. |
codamai.cias.user.enabled | Kein Fehler. Das Modul ist aus, und eine Installation ohne Benutzerverwaltung ist ein gültiger Zustand. |
codamai.cias.tenant-gate.ttl und andere Zeiten | Kein Fehler. Sie haben Standardwerte, denn ein falscher Wert macht die Anwendung träger, öffnet aber nichts. |
Die ganze Regel dahinter steht unter Im Zweifel ablehnen, samt der Liste aller Pflicht-Angaben.
Was die Anwendung selbst beisteuern muss
Manche Angaben sind keine Zeile in einer Datei, sondern Beans. Eine Bean ist ein Objekt, das Spring beim Start zusammensteckt.
| Bean | Was sie entscheidet | Liefert CIAS eine mit? |
|---|---|---|
PlatformAdministrators | welche Rollen die Plattform verwalten | nein, und das bleibt so: eine Bibliothek darf keine Administratorrolle erfinden |
RegistrationRoles | welche Rollen eine Registrierung vergibt | nein |
MailTemplateEditPolicy | welche Mails Mandanten-Administratoren umschreiben dürfen; die Editor-Rollen liest sie aus CIAS_NOTIFICATION_EDITOR_ROLES | nein |
ManagedTypesContribution | dass die Tabellen von CIAS in der Persistenz des Gastgebers bekannt sind | nein, das weiß nur der Gastgeber |
CallerContextProvider | woher CIAS erfährt, wer gerade handelt | der Starter bringt eine mit, die auf den RequestContext schaut; ohne Starter legst du sie selbst an |
Clock | die Zeitquelle | wie oben |
Fehlt eine davon, wo sie gebraucht wird, scheitert der Start mit dem Namen des Typs in der Meldung.
Was im Build entschieden wird
Ein Teil der Entscheidung fällt früher, nämlich wenn der Projektrahmen erzeugt wird. Im Hub steht am System ein Feld cias mit drei möglichen Werten. Der Generator legt danach fest, welche Jars in die Anwendung kommen und welche Konfigurationsklassen er schreibt.
cias am System| NONE | REMOTE | EMBEDDED | |
|---|---|---|---|
| Was es bedeutet | Die Anwendung meldet niemanden über CIAS an. | CIAS ist ein eigener Dienst. | CIAS läuft in diesem Prozess. |
| Welche Jars dazukommen | keine | cias-tenancy-client | cias-tenancy, cias-user, cias-authorization, cias-iam-keycloak |
| Was der Generator schreibt | nichts davon | nur den Eintrag in der .env | die Konfigurationsklassen und den ganzen codamai.cias-Block der application.yaml |
| Welche Umgebungsvariablen dazukommen | keine | CODAMAI_CIAS_TENANCY_CLIENT_BASE_URL | CIAS_IAM_PROVIDER, CIAS_USER, CIAS_AUTHORIZATION und die Zugangsdaten des Verwaltungs-Clients |
| Wer das Mandanten-Tor beantwortet | niemand — es gibt keine Filterkette von CIAS | der CIAS-Dienst, über HTTP | cias-tenancy im selben Prozess, als Methodenaufruf |
Zwei Dinge daran sind leicht zu übersehen:
REMOTEist der Wert, der gilt, wenn niemand etwas sagt. Sobald eine Anwendung über CIAS anmeldet, braucht sie eine Antwort auf die Frage des Mandanten-Tors, sonst startet sie nicht. Der Generator lässt diese Frage deshalb nie offen.REMOTEist dabei die zurückhaltendere Wahl: ein Jar und zwei Einstellungen.EMBEDDEDholt Mandanten, Benutzer und Rollenkatalog in die Anwendung, und das ist eine Entscheidung über die Installation, kein Standard.- Bei
EMBEDDEDkommt die Identitäts-Hälfte schlafend mit. Die Jars für Benutzer, Rollenkatalog und Keycloak-Zugriff liegen im Klassenpfad, aberCIAS_IAM_PROVIDER,CIAS_USERundCIAS_AUTHORIZATIONstehen zunächst auf leer beziehungsweisefalse. Erst wer sie setzt, hat sie. Das ist genau der Punkt dieser Seite: was läuft, bestimmt die Konfiguration, nicht der Klassenpfad.
Ein System, das gar nicht über CIAS anmeldet, bekommt immer NONE — auch wenn im Feld etwas anderes steht. Ohne Filterkette gibt es kein Tor, das eine Antwort bräuchte.