Produktionsdaten ansehen, ohne das Passwort zu teilen
Support will wissen, ob die Bestellung wirklich ankam. Der schnellste Weg – das Passwort der App und ein Port-Forward – ist fast immer der falsche. Vier Schichten für einen Lesezugriff, der nur liest und nachvollziehbar bleibt.

Dienstagmittag, eine Kundin schreibt: Ihre Bestellung von gestern sei nie angekommen. Der Support will wissen, ob sie überhaupt in der Datenbank steht. Der schnellste Weg ist fast immer derselbe: DATABASE_URL aus den Umgebungsvariablen kopieren, kubectl port-forward, psql. Nach fünf Minuten ist die Frage beantwortet – und drei neue Probleme sind entstanden.
Warum das Passwort der Anwendung der falsche Schlüssel ist
Die Anwendung verbindet sich meist als Eigentümerin ihrer Datenbank. Wer ihr Passwort hat, hat alles:
- Schreibrechte auf jede Tabelle, dazu
DROPundTRUNCATE– ein vergessenesWHEREreicht. - Das Passwort liegt danach im Chat-Verlauf, in der Shell-History und vielleicht in einer Notiz. Wechseln heißt: die Anwendung neu ausrollen.
- Der Port-Forward öffnet einen Weg vom Laptop in das private Netz, so lange er läuft.
- Im Log der Datenbank steht nur der Login der Anwendung. Wer was gesehen hat, weiß später niemand.
Nichts davon ist böse Absicht. Es ist einfach der Weg, der gerade offen ist. Die Lösung ist deshalb kein Verbot, sondern ein besserer Weg, der genauso schnell ist.
Vier Schichten für echten Lesezugriff
Ein Lesezugriff auf die Produktionsdatenbank ist nur dann einer, wenn mehrere Schichten unabhängig voneinander verhindern, dass geschrieben wird. Jede der folgenden vier reicht allein – zusammen fangen sie auch den Fehler in einer von ihnen ab.
- Ein eigener Login mit Leserecht. In PostgreSQL eine Rolle mit
CONNECT,USAGEauf dem Schema undSELECTauf den Tabellen – plusALTER DEFAULT PRIVILEGESfür die Eigentümerrolle, sonst sieht der Login keine Tabelle, die die Anwendung später anlegt. In MySQL genügtGRANT SELECT ON db.*. - Eine Nur-Lese-Transaktion.
BEGIN READ ONLYin PostgreSQL,START TRANSACTION READ ONLYin MySQL, und am Ende immerROLLBACK. Selbst wenn der Login zu viele Rechte hätte, weist die Datenbank Schreibzugriffe auf Tabellen ab. - Eine Anweisung, kein Kommandozeilen-Client. psql kennt Meta-Befehle wie
\!, der einen Shell-Befehl auf dem Rechner des Clients ausführt. Wer Text an einen Client weiterreicht, erbt das. Besser: ein Datenbanktreiber und genau eine Anweisung pro Abfrage. - Grenzen für Zeit und Zeilen. Ein
SELECT *ohne Bedingung auf einer Tabelle mit 40 Millionen Zeilen belastet die Datenbank und den Browser. PostgreSQL bricht mitstatement_timeoutab, MySQL mitmax_execution_timefür SELECT-Abfragen; die Zeilen begrenzt man beim Lesen, nicht erst in der Anzeige.
Die Rechte-Seite davon – warum ein Lesenutzer ohne Default Privileges nach der nächsten Migration nichts mehr sieht – beschreibt der Beitrag Eine Datenbank pro Service: Rollen, Rechte und der Lesenutzer, der nichts sieht.
Der Nachweis: wer hat was gefragt
Ein Lesezugriff auf Kundendaten braucht einen Nachweis – für die eigene Sicherheit, für ISO 27001 und für NIS2. Ins Audit-Log gehören:
- wer gefragt hat und wann,
- in welcher Datenbank,
- der Text der Abfrage,
- wie viele Zeilen zurückkamen und wie lange es dauerte.
Was nicht hineingehört: die Ergebnisse. Sonst wird das Audit-Log zu einer zweiten Kopie der Kundendaten, mit eigenen Löschfristen und eigenem Risiko.
Das Netz: warum kein Port-Forward
Eine gut betriebene Datenbank hat keinen öffentlichen Endpunkt, sie liegt im privaten Netz neben dem Cluster. Ein Port-Forward oder ein Bastion-Host durchbricht genau das, meistens von einem Laptop aus. Der bessere Weg dreht die Richtung um: Ein kleiner Dienst im Cluster führt die Abfrage aus und ist nur über die Kubernetes-API erreichbar, mit derselben Anmeldung und denselben Rechten wie alles andere.
Ein typischer Fall
Zurück zur Kundin mit der verschwundenen Bestellung:
- Der Support öffnet die Datenbank des Shops und sucht die Bestellung nach E-Mail und Datum. Sie ist da, Status „paid“.
- Eine zweite Abfrage zeigt: Der Versand-Job hat sie nie abgeholt. Der Fehler liegt im Worker, nicht in der Bestellung.
- Beide Abfragen stehen im Audit-Log, mit Namen und Uhrzeit. Niemand hatte Schreibrechte, kein Passwort wurde weitergegeben.
Wie Clusterward das umsetzt
Im Cockpit unter Operations → SQL-Konsole: Datenbank wählen, eine Anweisung schreiben, Ergebnis lesen. Die Konsole verbindet sich mit einem eigenen Lese-Login pro Datenbank, jede Abfrage läuft in einer Nur-Lese-Transaktion, die zurückgerollt wird, und stoppt nach 60 Sekunden oder 1.000 Zeilen, soweit nicht anders eingestellt. Der Text, die Datenbank, die Zeilenzahl und die Dauer landen im Audit-Log, die Ergebnisse nie.
Wer die Konsole benutzen darf, regelt eine eigene Berechtigung, getrennt von den Datenbankrechten – Kundendaten zu lesen folgt aus keinem anderen Recht. Die Abfragen laufen über einen kleinen Runner im Cluster, den Clusterward über die Kubernetes-API erreicht; die Datenbank bleibt im privaten Netz.
Fazit
Ein Lesezugriff auf die Produktionsdatenbank ist schnell gebaut, wenn man das Passwort der Anwendung nimmt – und dann ist es keiner. Ein eigener Login, eine Nur-Lese-Transaktion, eine Anweisung ohne Client und Grenzen für Zeit und Zeilen machen ihn zu einem echten; das Audit-Log macht ihn nachvollziehbar.
Zugriff auf Ihre Produktionsdaten regeln? Beschreiben Sie uns, wer heute wie in Ihre Datenbanken schaut. Wir zeigen, wie das ohne geteiltes Passwort geht. Frage stellen →
Quellen und weiterführende Links
Häufige Fragen
- Mit einem eigenen Login, der nur SELECT darf – in PostgreSQL zusätzlich mit ALTER DEFAULT PRIVILEGES für die Eigentümerrolle, damit auch künftige Tabellen lesbar sind. Dazu eine Nur-Lese-Transaktion pro Abfrage, eine Anweisung ohne Kommandozeilen-Client, Zeit- und Zeilenlimits und ein Audit-Log.