Files
opencrm/backend/src/routes/auditLog.routes.ts
T
duffyduckandClaude Opus 5 23505afc05 audit:export gatete nichts - Export hing an audit:read
Bei der Gegenprobe zur neuen Rolle "Gegenbuch" gefunden: Ein Konto mit
ausschliesslich audit:read bekam auf GET /audit-logs/export eine 200. Die
Berechtigung audit:export stand im Katalog und in der Rollenverwaltung -
und wurde nirgends geprueft.

Der Unterschied ist nicht kosmetisch. Blaettern zeigt 50 Zeilen; der
Export liefert in einem Zug das gesamte Protokoll inklusive changesBefore
und changesAfter, also der vollstaendigen Vorher/Nachher-Datensaetze,
dazu resourceLabel mit Klartextnamen, IP-Adressen und User-Agents. Live
nachgewiesen auf Staging: 43 Eintraege mit gefuellter resourceLabel
allein fuer resourceType=Customer.

Damit konnte ausgerechnet das Dienstkonto des Gegenbuchs Personendaten
exportieren - das Konto, dessen Passwort im Klartext in der .env auf der
Notar-Maschine liegt, und dem README und Rollenname "nur Pruefwerte
lesen" zusichern.

/audit-logs/export verlangt jetzt audit:export. Betroffen ist genau eine
Rolle: Gegenbuch, und zwar gewollt. Die DSGVO-Rolle traegt audit:*
vollstaendig und behaelt den Export.

In der Oberflaeche erscheinen JSON- und CSV-Knopf nur noch mit
audit:export - sonst stuenden dort Knoepfe, die zuverlaessig 403 liefern.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 12:56:53 +02:00

57 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Router } from 'express';
import { authenticate, requirePermission } from '../middleware/auth.js';
import * as auditLogController from '../controllers/auditLog.controller.js';
const router = Router();
// Alle Routen erfordern Authentifizierung
router.use(authenticate);
// ACHTUNG Reihenfolge: Alle konkreten Pfade MÜSSEN vor der Parameter-Route
// '/:id' stehen, sonst schluckt diese sie und antwortet mit
// "Ungültige Audit-Log-ID". Genau so war GET /retention-policies unerreichbar
// (Pentest R166-04).
// Audit-Logs abrufen
router.get('/', requirePermission('audit:read'), auditLogController.getAuditLogs);
// Audit-Logs exportieren
//
// Verlangt `audit:export`, nicht `audit:read`. Die Berechtigung stand im
// Katalog und in der Rollenverwaltung, gatete aber NICHTS - jeder Leser
// konnte das vollstaendige Protokoll in einem Zug herausziehen.
//
// Das ist etwas anderes als Blaettern: Der Export liefert `changesBefore` und
// `changesAfter`, also die vollstaendigen Vorher/Nachher-Datensaetze, dazu
// `resourceLabel` mit Klartextnamen, IP-Adressen und User-Agents. Aufgefallen
// am Dienstkonto des Gegenbuchs: Es soll ausschliesslich Pruefwerte lesen -
// und konnte Personendaten exportieren.
router.get('/export', requirePermission('audit:export'), auditLogController.exportAuditLogs);
// Retention-Policies
router.get('/retention-policies', requirePermission('audit:admin'), auditLogController.getRetentionPolicies);
router.put('/retention-policies/:id', requirePermission('audit:admin'), auditLogController.updateRetentionPolicy);
// Kontrollwert für das externe Gegenbuch (nur lesend, ohne Geheimnisse)
router.get('/checkpoint', requirePermission('audit:read'), auditLogController.getCheckpoint);
// Audit-Logs für einen Kunden (DSGVO)
router.get('/customer/:customerId', requirePermission('audit:read'), auditLogController.getAuditLogsByCustomer);
// Hash-Ketten-Integrität prüfen
router.post('/verify', requirePermission('audit:read'), auditLogController.verifyIntegrity);
// Hash-Kette reparieren
router.post('/rehash', requirePermission('audit:admin'), auditLogController.rehashAll);
// Altbestand versiegeln (nicht destruktiv)
router.post('/seal-backlog', requirePermission('audit:admin'), auditLogController.sealBacklog);
// Retention-Cleanup manuell ausführen
router.post('/cleanup', requirePermission('audit:admin'), auditLogController.runRetentionCleanup);
// Einzelnes Audit-Log abrufen als LETZTE GET-Route, siehe Hinweis oben
router.get('/:id', requirePermission('audit:read'), auditLogController.getAuditLogById);
export default router;