Nightbot-Befund #34 (Teil 1 von 2 – "eigene DB-Rolle für Audit ohne UPDATE/DELETE"): eine echte separate DB-Rolle nur für Audit-Schreibzugriffe ist mit dem bestehenden Muster (audit() schreibt oft in derselben Transaktion wie die Fachaktion, die sie protokolliert, über dieselbe Connection) nicht sauber vereinbar, ohne diese Atomarität zu verlieren oder alle ~50 Tabellen einzeln neu zu berechtigen (MySQL/MariaDB kann eine datenbankweite Berechtigung nicht durch eine engere Tabellen- Berechtigung "überschreiben" – Rechte sind additiv, nicht spezifischer gewinnt). Stattdessen: BEFORE UPDATE/DELETE-Trigger auf audit_events, die beides unabhängig vom verbindenden DB-Nutzer grundsätzlich verweigern (Migration 033). INSERT/SELECT bleiben uneingeschränkt möglich – genau das, was audit()/verifyAuditChain() je brauchen. TRUNCATE bleibt technisch möglich (feuert keine Trigger, betrifft nur die Testdatenbank-Zurücksetzung zwischen Testdateien), DROP TABLE weiterhin auch – echte Kompromittierung der DB-Zugangsdaten bleibt außerhalb dieser Verteidigungslinie, aber versehentliche oder fehlerhafte Anwendungscode-Änderungen sind jetzt ausgeschlossen. test/core.test.ts angepasst: die bisherige Manipulationssimulation per UPDATE ist jetzt selbst Teil des Tests (muss fehlschlagen); die Prüfung "Hash-Kette erkennt Fälschung" simuliert stattdessen eine eingeschleuste Fälschung per INSERT (weiterhin erlaubt). Verifiziert: Testsuite (59/59, neuer Testfall für die Trigger-Ablehnung), echte UPDATE/DELETE-Versuche gegen die Produktionsdatenbank beide abgelehnt, Hash-Kette danach weiterhin intakt (192 Einträge), volles Backup+Wiederherstellungstest gegen die echte Produktionsdatenbank gefahren (Trigger werden korrekt mitgesichert/wiederhergestellt). Aufbewahrungsfristen (DSGVO) und Export sind Teil desselben Tickets, brauchen aber eine fachliche/rechtliche Entscheidung des Nutzers und bleiben offen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
10 lines
941 B
SQL
10 lines
941 B
SQL
-- Nightbot-Befund #34 (Teil "eigene DB-Rolle für Audit ohne UPDATE/DELETE"): eine echte separate DB-Rolle
|
|
-- ist mit dem bestehenden Muster (audit() schreibt oft in derselben Transaktion wie die Fachaktion, die sie
|
|
-- protokolliert) nicht sauber vereinbar, ohne diese Atomarität zu verlieren. Stattdessen: Trigger, die UPDATE/
|
|
-- DELETE auf audit_events unabhängig vom verbindenden DB-Nutzer grundsätzlich verweigern (append-only auf
|
|
-- DB-Ebene, nicht nur per Konvention im Anwendungscode). INSERT/SELECT bleiben uneingeschränkt möglich.
|
|
CREATE TRIGGER audit_events_no_update BEFORE UPDATE ON audit_events
|
|
FOR EACH ROW SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'audit_events ist unveraenderlich (append-only) - UPDATE nicht erlaubt';
|
|
|
|
CREATE TRIGGER audit_events_no_delete BEFORE DELETE ON audit_events
|
|
FOR EACH ROW SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'audit_events ist unveraenderlich (append-only) - DELETE nicht erlaubt';
|