Das Hinzufügen einer Mandanten-ID zu jeder Tabelle ist ein sinnvoller erster Schritt. Dies allein reicht jedoch nicht aus, um eine SaaS-Anwendung vollständig zu isolieren. Daten werden zudem über Cache-Einträge, Worker-Nachrichten, Suchindizes, Objektspeicher und Verwaltungsbildschirme übertragen.
Ich betrachte Isolation als eine Eigenschaft der gesamten Anfrage und der darauf folgenden Verarbeitungsschritte. An jeder Grenze sollte das System wissen, um wessen Daten es sich handelt und warum der aktuelle Vorgang berechtigt ist, diese zu verarbeiten.
Tenant-Kontext auf dem Server einrichten
Eine vom Browser bereitgestellte Mandanten-ID stellt lediglich den angeforderten Geltungsbereich dar und ist kein Nachweis für die Zugehörigkeit. Die Anwendung muss den authentifizierten Benutzer identifizieren, den Zugriff auf diesen Mandanten überprüfen und einen Autorisierungskontext einrichten, bevor Geschäftsdaten geladen werden.
Dieser Kontext sollte in den Servicegrenzen explizit festgelegt werden. Ein versteckter globaler Zustand erschwert die Analyse von geplanten Aufgaben und gleichzeitigen Anfragen. Ein Worker sollte genügend Informationen erhalten, um seinen eigenen autorisierten Geltungsbereich zu bestimmen, anstatt Annahmen aus der ursprünglichen HTTP-Anfrage zu übernehmen.
Datenbankabfragen sollten diesen Geltungsbereich widerspiegeln. Beim Laden einer Konversation möchte ich, dass die Abfrage sowohl deren Identität als auch deren Mandanten einschränkt. Das globale Abrufen eines Datensatzes und die spätere Überprüfung der Zugehörigkeit erhöhen das Risiko, dass ein anderer Codepfad diesen versehentlich zuerst verwendet.
Verwenden Sie die Datenbank als weitere Grenze
PostgreSQL unterstützt Sicherheitsrichtlinien auf Zeilenebene, einschließlich einer standardmäßigen Zugriffsverweigerung, wenn die Zeilensicherheit aktiviert ist und keine anwendbare Richtlinie den Zugriff erlaubt. In der Dokumentation wird zudem eine wichtige Unterscheidung getroffen: Superuser und Rollen mit Umgehungsrechten unterliegen keinen Einschränkungen, und Tabellenbesitzer umgehen die Richtlinien in der Regel.
Das bedeutet, dass eine überzeugende Definition der Richtlinien nur ein Teil der Konzeption ist. Die tatsächliche Datenbankrolle der Anwendung, ihre Migrationsrolle, das Connection-Pooling und das Transaktionsverhalten spielen ebenfalls eine Rolle. Ich würde die Richtlinien mit denselben Berechtigungen überprüfen, über die auch die laufende Anwendung verfügt.
Wenn der Mandantenkontext über Verbindungseinstellungen übermittelt wird, ist bei gepoolten Verbindungen besondere Vorsicht geboten. Der Kontext muss über einen vertrauenswürdigen Pfad festgelegt werden, einen angemessenen Geltungsbereich haben und darf nicht in die nächste Anfrage durchdringen. Die Sicherheit auf Zeilenebene stellt einen zusätzlichen Schutz dar, ist jedoch kein Ersatz für das Verständnis des Verbindungslebenszyklus.
Beziehe die Orte außerhalb von SQL mit ein
Ein Cache-Schlüssel wie beispielsweise conversation:123 setzt voraus, dass der Bezeichner global eindeutig ist und dass jeder Aufrufer dieselben Zugriffsregeln einhält. Eine explizite Mandantkomponente macht die Eigentumsgrenzen sichtbar und reduziert versehentliche Kollisionen.
Suche und Abruf erfordern dieselbe Disziplin. Mieter- und Zugriffsfilter gehören in die Kandidatenauswahl. Eine Filterung nach einer globalen Top-k-Suche kann dazu führen, dass gültige Kandidaten verloren gehen, und das Einbeziehen nicht autorisierter Texte in die Neugewichtung oder den Modellkontext stellt bereits eine Offenlegung dar.
Auch Speicherpfade, Exportaufträge, Nutzungszähler und Benachrichtigungswarteschlangen sollten den Mandantenkontext enthalten. Eine Anwendung kann zwar ihre interaktiven Bildschirme absichern, dennoch können durch einen CSV-Export im Hintergrund Daten nach außen gelangen.
Test mit bewusst ähnlichen Mietern
Ich bevorzuge Isolationstests, bei denen zwei Mandanten mit sich überschneidenden Namen, ähnlichen Dokumenten und übereinstimmenden externen Identifikatoren zum Einsatz kommen. Dadurch lassen sich versehentliche globale Abfragen leichter aufdecken als bei einem Datensatz, in dem jeder Wert praktischerweise eindeutig ist.
- Fordern Sie die Daten eines anderen Mieters direkt anhand seiner ID an.
- Suchen Sie nach Formulierungen, die ausschließlich in der Wissensdatenbank des anderen Mandanten vorkommen.
- Eine zwischengespeicherte Antwort nach dem Wechsel zwischen autorisierten Arbeitsbereichen wiederverwenden.
- Eine Worker-Nachricht mit nicht übereinstimmenden Eigentumsmetadaten erneut abspielen.
- Versuchen Sie, den Export über eine Rolle mit eingeschränktem Zugriff durchzuführen.
Außerdem teste ich Support-Tools. Aus Gründen der administrativen Einfachheit werden im Produkt oft weitreichende Berechtigungen vergeben, daher sollte der mandantenübergreifende Zugriff bewusst gestaltet, eingeschränkt und nachverfolgbar sein.
Eine Tenant-Abgrenzung gilt als zuverlässig, wenn sie sowohl die normalen Abläufe als auch die Wiederherstellungsabläufe übersteht. Dabei geht es nicht nur darum, ob der Geltungsbereich der Haupt-API korrekt festgelegt ist, sondern auch darum, ob bei jeder nachfolgenden Kopie und Verwendung der Daten dieser Geltungsbereich beibehalten wird.
Aktualisiert am 25. September 2026.