Legacy-Modernisierung

Security beim Legacy-Umbau warum Backends Daten leaken

Backend-Teams merken Sicherheits- und Datenschutzkosten bei Legacy-Migrationen oft erst dann, wenn Daten schon kopiert, Logs schon geschrieben und Schnittstellen schon geöffnet sind. Meine Position: Datenbankmodernisierung ist zuerst ein Privacy-Engineering-Problem und erst danach ein Performance- oder Architekturproblem, weil falsche Datenflüsse später teurer zu korrigieren sind als langsame Queries.

Die gefährlichste Migration beginnt mit einer vollständigen Kopie

Der erste Reflex ist verständlich: Dump ziehen, Staging befüllen, Migration testen. Genau dort entsteht aber der erste Trade-off, den viele zu spät sehen. Eine vollständige Produktionskopie macht Tests realistischer, erhöht aber den Kreis der Personen, Systeme und Tools mit Zugriff auf personenbezogene Daten, weshalb sie das Angriffs- und Auskunftsrisiko vergrößert.

Ich würde nicht mit einem vollständigen PostgreSQL- oder MySQL-Produktionsdump in einer Entwicklerumgebung starten, weil Debug-Komfort kein ausreichender Grund ist, Klartextdaten in schwächer überwachte Netze, Laptops oder CI-Runner zu verschieben. Stattdessen würde ich zuerst entscheiden, welche Tabellen für Integritätstests wirklich produktionsnah sein müssen und welche synthetisch erzeugt werden können.

Ein backendnahes Beispiel: Die Tabelle customer enthält E-Mail, Telefonnummer, Rechnungsadresse und Consent-Historie. Die Fremdschlüssel zu orders und invoices sind für Migrationstests wichtig, die echten Namen sind es meistens nicht. Mit PostgreSQL 16, pg_dump –section=pre-data, pg_restore –no-owner, pgcrypto und Faker 24.x lassen sich Struktur, Kardinalität und Verteilung realistischer testen, ohne jede Klartextspalte mitzunehmen.

Ein in einem Migrationsprojekt gemessener Wert von 27 Prozent personenbezogenen Spalten in vermeintlich technischen Tabellen ist kein Naturgesetz, aber er zeigt, warum Schema-Review allein nicht reicht. Session-Tabellen, Audit-Events, Suchindizes und Dead-Letter-Queues enthalten häufig E-Mail-Adressen oder freie Textfelder, weil frühere Entwickler dort Fehler schneller nachvollziehen wollten.

Legacy umbauen ohne Budget und ploetzlich DSGVO-Risiko trifft den unangenehmen Punkt, dass Budgetmangel oft nicht zu weniger Risiko führt, sondern zu unsichtbarerem Risiko, weil Teams dann Datenkopien, Log-Ausnahmen und manuelle Workarounds nicht sauber dokumentieren.

Für dich als Backend-Entwickler heißt das: Suche nicht zuerst nach dem perfekten Migrationstool, sondern nach den Stellen, an denen Daten aus ihrem ursprünglichen Schutzkontext fallen. Praktisch sind OpenAPI 3.1 für Schnittstellenverträge, JSON Schema Draft 2020-12 für Payload-Prüfung, SQLFluff 3.x für SQL-Reviews, Semgrep 1.x für Log-Leak-Regeln und OWASP ASVS 4.0.3 als Prüfraster für Zugriffskontrollen.

Maskierung beruhigt Stakeholder, aber Pseudonymisierung bricht oft Fachlogik

Viele Teams nennen alles „anonymisiert“, was keine echten Namen mehr zeigt. Das ist gefährlich, weil Hashes, Token und deterministische Masken häufig weiterhin Personen wiedererkennbar machen. Ein SHA-256-Hash einer E-Mail-Adresse schützt schlecht, wenn der Wertebereich klein ist und Angreifer Wörterbuchlisten verwenden können; der Hash ist dann eher ein stabiler Identifier als eine Löschung.

Deterministische Pseudonymisierung gewinnt, wenn Regressionstests stabile Joins brauchen, weil dieselbe Kundin über mehrere Tabellen hinweg gleich ersetzt wird. Sie kostet jedoch Privatsphäre, weil Wiedererkennung über Releases hinweg möglich bleibt. Nichtdeterministische Anonymisierung gewinnt, wenn Daten für Lasttests oder UI-Screenshots reichen, weil sie Wiederverknüpfung erschwert. Sie kostet Testtiefe, weil fachliche Historien und Dublettenlogik kaputtgehen können.

Diese Abwägung ist unbequem, aber sie ist ehrlicher als der Satz „wir maskieren das einfach“. Bei einem aus PostgreSQL 16 exportierten Kundensatz kann eine deterministische Funktion mit geheimem Salt für Joins sinnvoll sein, während freie Textfelder besser verworfen oder per Presidio 2.x erkannt und ersetzt werden. Microsoft Presidio findet Namen, Telefonnummern und IBANs brauchbar, aber es übersieht projektspezifische IDs, weil Modelle ohne Domänenwissen keine internen Konventionen kennen.

CREATE EXTENSION IF NOT EXISTS pgcrypto;

BEGIN;
UPDATE customer
SET email = encode(digest(lower(email) || 'migration-salt-2026', 'sha256'), 'hex') || '@example.invalid',
    phone = NULL,
    full_name = 'Test User ' || id::text
WHERE email IS NOT NULL;
COMMIT;

SELECT id, email, phone, full_name FROM customer LIMIT 5;

Dieses SQL läuft in PostgreSQL mit pgcrypto, aber es ist keine Anonymisierung im strengen Sinn, weil gleiche Eingaben gleiche Ausgaben erzeugen. Als zu justierender Wert ist ein Salt-Wechsel pro Testdaten-Generation sinnvoll, wenn Tests keine releaseübergreifende Wiedererkennung brauchen; ein stabiler Salt ist nur dann vertretbar, wenn Vergleichbarkeit wichtiger ist und der Salt wie ein Geheimnis in HashiCorp Vault 1.15 oder AWS Secrets Manager liegt.

Eine veröffentlichte AWS-KMS-Grenze von 4 KB pro direktem Encrypt-Aufruf ist ein gutes Beispiel für versteckte Architekturkosten: Große Datenbankfelder verschlüsselt man deshalb üblicherweise per Envelope Encryption, nicht direkt pro Blob. Das zwingt dich zu Entscheidungen über Data Encryption Keys, Rotation und Caching, bevor du die erste produktive Migration planst.

Auch Metriken gehören in diese Phase. k-Anonymity, l-Diversity und t-Closeness sind keine magischen DSGVO-Schalter, aber sie zwingen dich, Reidentifikation messbar zu diskutieren. Eine intern festgelegte Schwelle von k=10 kann für Testdaten ein brauchbarer Startwert sein, wenn kleine Gruppen sonst einzelne Personen verraten würden; sie ist ungeeignet für seltene Ereignisse, weil diese trotz Gruppierung auffällig bleiben.

Verschlüsselung löst weniger, als sie in Reviews verspricht

Verschlüsselung ist wichtig, aber sie wird in Legacy-Migrationen überschätzt, weil sie Zugriffe nicht automatisch minimiert. TLS 1.3 schützt Daten auf dem Transportweg, PostgreSQL sslmode=verify-full verhindert einfache Man-in-the-Middle-Fehler, und AES-256-GCM ist für viele Speicherszenarien solide. Trotzdem sieht jeder Service, der entschlüsseln darf, die Daten wieder im Klartext.

Das späte Erwachen kommt oft bei Reporting, Suche und Support-Tools. Wenn du E-Mail-Adressen feldweise verschlüsselst, bricht die Suche nach Domain-Endungen oder Dubletten. Wenn du sie nur in der Datenbank per Transparent Data Encryption schützt, bleiben Applikationslogs und ETL-Jobs weiterhin ein Problem. Beide Aussagen sind unbequem, aber sie stimmen, weil Sicherheitskontrollen an unterschiedlichen Stellen der Datenreise wirken.

Die explizite Gegenüberstellung ist hier: Feldverschlüsselung mit libsodium 1.0.19 gegen datenbankseitige Verschlüsselung wie MySQL Enterprise TDE oder PostgreSQL mit verschlüsseltem Volume über LUKS2. Feldverschlüsselung gewinnt, wenn Datenbankadministratoren oder replizierte Lesesysteme den Klartext nicht sehen sollen; sie kostet Query-Fähigkeit, Index-Design und Key-Management-Komplexität. Datenbank- oder Volume-Verschlüsselung gewinnt, wenn das Hauptszenario verlorene Datenträger, Snapshots oder Backups sind; sie kostet weniger Entwicklungsaufwand, schützt aber kaum vor kompromittierten Applikationsrechten.

Ein gemessener zusätzlicher Latenzanteil von 8 bis 15 Millisekunden pro Request kann bei externer Schlüsselabfrage über KMS realistisch sein, wenn Keys nicht gecacht werden. Dieser Wert ist kein allgemeiner Benchmark, aber er reicht, um zu zeigen, warum Security-Design Performance-Design berührt. Wer danach hektisch Caches einbaut, verschiebt das Risiko nur, weil gecachte Data Keys ebenfalls geschützt, rotiert und invalidiert werden müssen.

Die NIST SP 800-57-Empfehlungen zur Schlüssellebensdauer, FIPS 140-3-validierte Module, mTLS mit SPIFFE/SPIRE und Audit-Trails nach ISO/IEC 27001:2022 helfen nur, wenn du die Verantwortlichkeiten konkret machst. „Der Service darf entschlüsseln“ ist keine ausreichende Regel, weil ein kompromittierter Service-Account dann alle Datensätze lesen kann. Besser ist ein Policy-Modell mit Open Policy Agent 0.60+, Claims aus OIDC und tabellen- oder zweckbezogenen Entscheidungen.

Sichere Datenbank-Modernisierung und Legacy-System Migration klingt für meinen Geschmack zu sehr nach einem erreichbaren Endzustand, denn „sicher“ ist bei Migrationen eher eine Reihe begründeter Verluste: weniger Query-Komfort, weniger Debug-Daten, weniger spontane Exporte und weniger direkte Produktionsnähe.

Auditierbarkeit wird zur Datenpanne, wenn Logs alles wissen

Backend-Entwickler lieben Logs, weil sie Migrationsfehler sichtbar machen. Datenschutzbeauftragte fürchten Logs, weil sie selten dieselben Lösch-, Zugriff- und Korrekturpfade haben wie Primärdaten. Beide Seiten haben recht, weil Migrationen ohne Nachvollziehbarkeit riskant sind, aber unkontrollierte Nachvollziehbarkeit selbst personenbezogene Daten vervielfacht.

Der Fehler passiert in unscheinbaren Details: DEBUG-Logs bleiben in Kubernetes länger aktiv, Debezium 2.5 schreibt Change Events mit vollständigem Payload nach Kafka 3.6, ein Spring Boot 3.2 Exception Handler serialisiert Request-Bodies, oder ein Nginx log_format enthält Query-Parameter. Danach liegen personenbezogene Daten in OpenSearch, S3, Loki oder Splunk, obwohl die eigentliche Datenbank sauber migriert wurde.

Eine als Betriebsziel definierte Log-Aufbewahrung von 14 Tagen kann für Migrationsfehler reichen, wenn Wiederanläufe schnell stattfinden; eine pauschale Aufbewahrung von 365 Tagen ist schwerer zu rechtfertigen, weil der Zweck „vielleicht brauchen wir es“ schwach ist. Gleichzeitig kann eine gesetzliche oder vertragliche Nachweispflicht längere Fristen verlangen, weshalb die Entscheidung dokumentiert und nicht aus Bequemlichkeit getroffen werden sollte.

Ich würde außerdem keine zentrale „Migration Admin“-Rolle bauen, die alles darf, weil sie im Incident-Fall zum perfekten Angriffsziel wird. Besser sind zeitlich begrenzte Rollen, zum Beispiel PostgreSQL ALTER DEFAULT PRIVILEGES, Row Level Security, separate Service-Accounts pro Migrationsschritt und JIT-Zugriff über Teleport 15 oder Boundary 0.15. Das kostet Setup-Zeit, aber es reduziert den Schaden, wenn ein Token in einem CI-Log landet.

Bei Change Data Capture ist der Trade-off besonders scharf. Debezium plus Kafka gewinnt, wenn Downtime minimal sein muss und parallele Konsumenten die Migration beobachten sollen; es kostet Datenschutzfläche, weil jedes Topic, jede Retention Policy und jeder Consumer zur Datenverarbeitung wird. Ein Offline-Import mit pg_restore –jobs=4 gewinnt, wenn ein Wartungsfenster akzeptabel ist; er kostet Verfügbarkeit, reduziert aber die Zahl der bewegten Kopien.

Auch hier braucht es konkrete Kontrollen: Kafka retention.ms, cleanup.policy=delete, Schema Registry-Kompatibilität auf BACKWARD, Redaction in Logback über TurboFilter, OpenTelemetry Collector 0.91 mit attributesprocessor, und S3 Bucket Policies mit s3:PutObjectRetention. Diese Namen sind nicht Dekoration, weil ein Review ohne echte Konfiguration nur Absichtserklärungen prüft.

Du solltest zuerst eine Datenflussbilanz bauen, nicht ein Migrationsboard

Der beste erste Schritt ist klein und unangenehm: Nimm eine einzige kritische Entität, etwa Kunde, Vertrag oder Nutzerkonto, und zeichne jede Kopie vom Legacy-System bis zum letzten Log-Index auf. Notiere Zweck, Aufbewahrung, Zugriff, Verschlüsselung und Löschweg. Erst wenn diese Bilanz stimmt, lohnt sich der nächste Migrations-Sprint.

Eugene begann seine Karriere bei Chudovo im Jahr 2015. Der Experte ist für Beratungsleistungen verantwortlich, die unter anderem eine enge Kommunikation mit den Kunden, die Analyse ihrer Bedürfnisse, die Entwicklung maßgeschneiderter Softwarestrategien usw. umfassen. Während seiner Tätigkeit bei Chudovo nahm ein IT-Berater an über 17 Projekten teil, die ein breites Spektrum an Kundendienstleistungen abdeckten und Kundenprobleme aus geschäftlicher Sicht lösten. Dank Eugenes Beteiligung konnten die Kunden eine effiziente Strategie für das Geschäftswachstum sowie eine langfristige Technologie-Roadmap entwickeln. Eugene nimmt in der Rolle des IT-Beraters aktiv an Softwareentwicklungsprojekten teil und erstellt Vorschläge für die Kunden.