CodamAIDocs
Themafertig

Regeln, die nie gebrochen werden

Die Sicherheitsinvarianten der Mandantentrennung: kein Rückfall auf die System-DB, getrennte Typmengen, nur drei Stellen dürfen einen Mandanten setzen.

Worum es geht

Die Mandantentrennung ist die wichtigste Sicherheitszusage von CDMS: Ein Kunde sieht nie die Daten eines anderen. Damit das hält, gibt es ein paar Regeln, die überall gelten und für die es keine Ausnahme gibt. Man nennt solche Regeln Invarianten.

Diese Seite sammelt sie an einer Stelle. Jede Regel hat einen Grund. Wer eigenen Code schreibt, einen Hook, einen Job oder eine Erweiterung, darf keine davon umgehen.

Die Merkliste

Nr.RegelWarum
1Kein Rückfall auf die System-Datenbank. Fehlt der Mandant, fehlt der RequestContext oder lässt sich die Mandanten-Datenbank nicht öffnen, bricht der Zugriff ab.Sonst landen Mandanten-Daten in der System-Datenbank und sind dort für alle Mandanten erreichbar.
2System-Modelle gehen immer in die System-Datenbank, und das wird vor jeder Prüfung des Kontexts entschieden.Ein fehlender oder manipulierter Kontext kann System-Daten weder umleiten noch blockieren.
3Getrennte Typmengen. Die System-Datenbank kennt nur System-Modelle, eine Mandanten-Datenbank nur Mandanten- und Benutzer-Modelle.Ein falsch geleitetes Objekt scheitert an Hibernate, statt in der falschen Datenbank gespeichert zu werden. Das ist eine zweite, vom Routing unabhängige Sicherung.
4Nur drei Stellen setzen einen Mandanten: das Lesen des Tokens, der erlaubte Mandantenwechsel und der Rahmen für Arbeit ohne Anfrage.Jede weitere Stelle wäre ein Weg, den Mandanten an den Prüfungen vorbei zu ändern.
5Der Mandant stammt aus einer signierten Quelle. Header sind nur Wünsche; die Liste der erlaubten Mandanten kommt aus dem Token.Einen Header kann jeder Client setzen.
6Ein Wechsel wird zweimal geprüft: in CIAS und noch einmal in der Persistenz.Fällt eine Prüfung einem Fehler zum Opfer, hält die andere.
7Das Tor fragt nach dem tatsächlich genutzten Mandanten, also nach einem Wechsel noch einmal.Ein Wechsel darf keinen gesperrten Mandanten zurückholen, auch nicht für Administratoren.
8Keine unbestätigte Antwort bei Ausfall. Ist CIAS nicht erreichbar, gilt nur eine schon gemerkte Antwort; ohne sie wird abgelehnt.Ein Ausfall darf niemanden hereinlassen, der vorher nicht drin war.
9Eine Datenbank entsteht nur mit Freigabe, und „nicht erreichbar“ gilt nie als „nicht vorhanden“.Ein kurzer Ausfall oder ein Tippfehler im Schlüssel darf keine Datenbank anlegen.
10Nichts in CDMS löscht eine Datenbank.Eine verlorene Datenbank lässt sich nicht zurückholen. Eine leere, verwaiste ist das kleinere Übel.
11Der Mandantenschlüssel ist fest: nur a-z, 0-9 und -, höchstens 64 Zeichen, nicht system oder single, nie umbenannt. Er wird geprüft, nicht bereinigt.Er ist Datenbankname und Verzeichnisname. Bereinigen könnte zwei Mandanten auf denselben Namen abbilden.
12Die Betriebsart hat keinen Standardwert, und widersprüchliche Angaben halten den Start an.Ein geratener Wert würde still eine Trennung abschalten oder erfinden.
13Der RequestContext wird nach jeder Anfrage gelöscht.Sonst trägt der nächste Auftrag auf demselben Thread Mandant, Person und Rollen der vorigen Anfrage.

Verbotene Rückfälle

Diese Abkürzungen gibt es nicht und darf es auch in eigenem Code nicht geben:

Situation und was stattdessen passiert
SituationWas passiert
Mandant fehlt400 CDMS_TENANT_REQUIRED bzw. vorher 403 tenant-required; nie System-Datenbank
RequestContext fehlt500 CDMS_PERSISTENCE_CONTEXT_MISSING; nie System-Datenbank
Mandant unbekannt oder gesperrt403 tenant-not-served; nie automatisch anlegen
Wechsel nicht erlaubt403 CDMS_TENANT_SWITCH_NOT_AUTHORIZED; nicht still im eigenen Mandanten weiter
Mandanten-Datenbank fehlt oder ist nicht erreichbar500 bzw. 503; nie System-Datenbank
Token nennt mehrere Mandanten ohne Auswahl403 tenant-unresolved; nie der erste oder ein Standard-Mandant

Eine Ausnahme ist gewollt und keine Abkürzung: Fehlt nur die Rolle für einen Wechsel, dessen Ziel erlaubt ist, läuft die Anfrage still im eigenen Mandanten weiter. Das Token hat dann keinen Wechsel verlangt, sondern der Client hat ihn nur gewünscht. Siehe Mandantenwechsel per Header.

Die drei Stellen, die einen Mandanten setzen

Wer den Mandanten einer Anfrage festlegen darf
Token lesen
jede Anfrage mit Token
  • bestimmt den Mandanten aus Organisation oder Attribut tenant
  • fragt das Mandanten-Tor
  • füllt die Liste der erlaubten Mandanten
Mandantenwechsel
Header tenant
  • nur mit Realm-Rolle allowed-tenant-context-switch
  • nur zu einem Ziel aus der Liste der erlaubten Mandanten
  • danach fragt das Tor noch einmal
Arbeit ohne Anfrage
Jobs, Listener
  • Code nennt Mandant und das technische Konto, für das er handelt
  • fragt vorher das Mandanten-Tor
  • läuft ohne Rollen und nur in diesem einen Mandanten

Wie der dritte Weg aussieht, steht unter Arbeiten für einen Mandanten ohne Anfrage.

Was das für eigenen Code heißt

Wie es weitergeht

Quellen im Code und in der Wissensdatenbank
  • commons-persistence – DatabaseRequestContext.resolveTenant (System-Modell zuerst, kein Rückfall, A-3-Prüfung), DataSourceManager (Freigabe, erreichbar ≠ vorhanden), TenantModeConsistencyCheck, TenantProperties (@NotNull), TenantProvisioningPort (nichts löscht)
  • CDMS/cdms-persistence-database – EntityClassFilterService (getrennte Typmengen), EntityClassificationValidator (Startprüfung)
  • CIAS/cias-authentication – TokenParser, ContextSwitch, TenantScope (die drei Stellen, die setUserTenant aufrufen), TenantGate, JwtSessionFilter (Kontext wird nach jeder Anfrage gelöscht)
  • CIAS/cias-kernel – TenantKey (^[a-z0-9-]+$, höchstens 64 Zeichen, unveränderlich)
  • documentation/30-daten-und-persistenz/01-mandantentrennung.md (Verbotene Rückfallebenen, getrennte Typmengen)
Suchen