docs: AUD-07-Pruefprotokoll (Append-only Audit-Log bereits durchgesetzt)
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
Archive-Schnittstellen-Vertragstests / contract-tests (push) Canceled after 0s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (push) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (push) Canceled after 0s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (push) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (pull_request) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Canceled after 0s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (pull_request) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Canceled after 0s
CI / Web (dms-browser) (pull_request) Canceled after 0s
CI / Web (pdf-viewer) (pull_request) Canceled after 0s
CI / Web (shl) (pull_request) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Canceled after 0s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Canceled after 0s

AUD-07 ist bereits auf main umgesetzt (Commit 6866845: Migration
migrations/0010_audit_events_role_enforcement.{up,down}.sql entzieht der
Rolle nexarch_app UPDATE/DELETE auf audit_events, Trigger
audit_events_prevent_mutation() protokolliert und lehnt Aenderungsversuche
ab; internal/audit/append_only_test.go deckt alle drei Akzeptanzkriterien
ab). Es fehlte bislang nur das Pruefprotokoll.

Auf frischem Checkout (Host 192.168.1.204) real nachgeprueft:
- go test ./internal/audit/... -v -p 1 -count=1: alle 24 Tests PASS,
  inkl. TestAppendOnly_AppRoleHasNoUpdateOrDeletePrivilege (permission
  denied statt Trigger-Fehler), TestAppendOnly_TamperAttemptIsLogged
  (RAISE-WARNING-Notice mit Akteur-/Session-Kontext) und
  TestAppendOnly_NormalWriteAndReadStillWork (Regression).
- Manuelle Stichprobe gegen isolierte Testtabelle: UPDATE/DELETE werden
  vom Trigger abgelehnt und vorher per RAISE WARNING protokolliert;
  normaler INSERT/SELECT bleibt unveraendert nutzbar.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
patrickandClaude Sonnet 5 authored and root committed 2026-10-15 20:35:33 +00:00
1 parent dac7fff504
commit 1562016371
1 file changed
+105
+105
View File
@@ -0,0 +1,105 @@
# AUD-07 — Prüfprotokoll: Technische Durchsetzung Append-only Audit-Log
Datum: 2026-10-15
Host: 192.168.1.204 (frisches Wegwerf-Arbeitsverzeichnis `/root/aud-07-work-1792096066`, Clone von `main`)
DB: `postgres`-Wartungsdatenbank, Rolle `nexarch_test` (Admin/Owner-Verbindung, `TEST_ADMIN_DSN` aus `/etc/nexarch-dev/core-dev.env`), cluster-weite Gruppenrolle `nexarch_app` (NOLOGIN)
## Befund: Ticket bereits umgesetzt
AUD-07 ist bereits vollständig implementiert und auf `main` gemerged
(Commit `6866845`, 2026-09-17). Die Umsetzung besteht aus:
- `migrations/0010_audit_events_role_enforcement.up.sql` / `.down.sql`:
- Gruppenrolle `nexarch_app` (NOLOGIN, kein Passwort) wird angelegt, falls
nicht vorhanden.
- `REVOKE ALL ON audit_events FROM PUBLIC` und `FROM nexarch_app`, danach
`GRANT INSERT, SELECT ON audit_events TO nexarch_app` — die
Anwendungsrolle verliert UPDATE/DELETE auf DB-Ebene vollständig
(Akzeptanzkriterium 1).
- Die bereits aus AUD-02 (Migration `0005_audit_append_only.up.sql`)
bestehende Trigger-Funktion `audit_events_prevent_mutation()` wird um
`RAISE WARNING` mit Akteur-/Session-/Client-Kontext ergänzt, bevor sie
den Versuch per `RAISE EXCEPTION` ablehnt (Akzeptanzkriterium 2 — `RAISE
WARNING` ist nicht transaktional und landet unabhängig von einem
Rollback im Postgres-Server-Log sowie als Notice bei der Verbindung).
- `internal/audit/append_only_test.go`: automatisierte Tests je
Akzeptanzkriterium (siehe unten).
Für dieses Ticket wurde daher kein neuer Code geschrieben, sondern die
bestehende Umsetzung auf einem frischen Checkout real nachgeprüft (siehe
Prüfungen unten) und dieses Protokoll ergänzt, das bisher fehlte.
## Prüfung 1 — Automatisierter Testlauf (echte Postgres-Instanz)
Kommando:
```
cd <workdir> && set -a && source /etc/nexarch-dev/core-dev.env && set +a \
&& go test ./internal/audit/... -v -p 1 -count=1
```
Ergebnis: **PASS**, gesamtes Paket `internal/audit`, 24 Tests, 242.161s,
exit code 0. Relevante Tests für AUD-07:
| Test | Akzeptanzkriterium / Prüfung | Ergebnis |
|---|---|---|
| `TestAppendOnly_RejectsUpdateAndDelete` | AC2/3 (AUD-02-Basis: Trigger lehnt UPDATE/DELETE ab) | PASS |
| `TestAppendOnly_AppRoleHasNoUpdateOrDeletePrivilege` | AC1 / Prüfung 1 — Verbindung als Mitglied von `nexarch_app` erhält `permission denied for table audit_events` (Rechteverweigerung auf DB-Ebene, nicht nur Trigger-Fehler) | PASS |
| `TestAppendOnly_TamperAttemptIsLogged` | AC2 / Prüfung 2 — RAISE-WARNING-Notice wird über pgx' `OnNotice`-Hook abgefangen und enthält Akteur-/Session-Kontext | PASS |
| `TestAppendOnly_NormalWriteAndReadStillWork` | AC3 / Prüfung 3 — `Record`/`CountByTenant` funktionieren nach der Rechteänderung unverändert | PASS |
Alle übrigen 20 Tests des Pakets (Export, Four-Eyes, Ingest, Wiring,
Timing-Safe-Compare usw.) liefen ebenfalls grün — keine Regression durch
die AUD-07-Änderungen in anderen Audit-Funktionen.
## Prüfung 2 — Manuelle Stichprobe gegen eigene Testtabelle
Da die geteilte Tabelle `audit_events` auf dem Testhost durch einen
parallel laufenden Testlauf eines anderen Tickets zwischenzeitlich
weggefallen ist (bekanntes Kollisionsrisiko bei gemeinsam genutzter
Postgres-Instanz, siehe Testinfra-Notizen), wurde die DB-Logik zusätzlich
manuell gegen eine isolierte Tabelle `aud07_manualcheck_events` mit
identischem Schema/Trigger/Grant-Muster nachvollzogen:
- `has_table_privilege('nexarch_test', ..., 'UPDATE'/'DELETE')` lieferte
`true`, weil die Verbindung in diesem Test gleichzeitig Tabellenbesitzer
war (Eigentümer behalten implizite Rechte, die ein `REVOKE ... FROM
nexarch_app` nicht entzieht). Das bestätigt genau die im Ticket
angelegte Verteidigung in der Tiefe: selbst wenn eine Rolle (z.B. der
Eigentümer bei Migrationsläufen) noch Rechte hat, greift der Trigger.
- `UPDATE ...` und `DELETE ...` auf dieser Verbindung wurden beide **durch
den Trigger abgelehnt** (`ERROR: append-only: UPDATE/DELETE ist nicht
erlaubt`), **und** vorher wurde je eine `WARNING`-Zeile mit
`op=UPDATE/DELETE current_user=nexarch_test session_user=nexarch_test`
ausgegeben — der Ablehnungsversuch ist damit sichtbar protokolliert.
- Normale `INSERT`/`SELECT` funktionierten davor und danach unverändert.
Die maßgebliche Prüfung für Akzeptanzkriterium 1 (fehlende Rechte für die
tatsächliche Anwendungsrolle, nicht den Tabelleneigentümer) ist die
automatisierte `TestAppendOnly_AppRoleHasNoUpdateOrDeletePrivilege`, die
über eine separate, nur `nexarch_app`-Mitgliedschaft nutzende Verbindung
läuft und dort `permission denied` erhält (siehe Prüfung 1).
## Bewertung je Akzeptanzkriterium
1. **Anwendungsrolle kann Audit-Einträge nachweislich weder ändern noch
löschen (fehlende Rechte):** erfüllt — `REVOKE ALL` + gezieltes `GRANT
INSERT, SELECT` in Migration `0010`, nachgewiesen durch
`TestAppendOnly_AppRoleHasNoUpdateOrDeletePrivilege` (`permission
denied`) und die manuelle Stichprobe.
2. **Änderungs-/Löschversuch wird von der DB abgelehnt und selbst
protokolliert:** erfüllt — Trigger `audit_events_prevent_mutation()`
lehnt per `RAISE EXCEPTION` ab und schreibt vorher `RAISE WARNING` mit
Akteur-/Session-/Client-Kontext ins Postgres-Server-Log (nicht
transaktional, übersteht Rollback), nachgewiesen durch
`TestAppendOnly_TamperAttemptIsLogged` und die manuelle Stichprobe.
3. **Bestehende AUD-01-Funktionalität (Schreiben/Lesen) bleibt nutzbar:**
erfüllt — `TestAppendOnly_NormalWriteAndReadStillWork` sowie alle
übrigen 20 Tests des Pakets `internal/audit` liefen unverändert grün.
## Betriebshinweis (unverändert aus Migration 0010)
`nexarch_app` ist eine reine Gruppenrolle ohne LOGIN/Passwort. Im Betrieb
muss die tatsächliche Login-Rolle des Core-Prozesses dieser Gruppe
zugeordnet werden: `GRANT nexarch_app TO <login-rolle-des-core-prozesses>;`.
Migrationen selbst laufen weiterhin über die separate Owner-/Admin-Rolle
(`NEXARCH_ADMIN_DSN`), die vom `REVOKE` nicht betroffen ist.