EMZETT.
Login

Audit Log

Kurz: Ein fortlaufendes Protokoll sicherheits-/verwaltungsrelevanter Aktionen (wer hat was, wann, an wem getan) — dient der Nachvollziehbarkeit im Nachhinein, z. B. bei Rollenvergaben oder anderen Admin-Eingriffen.

Genauer: Ein Audit Log muss bewusst fehlertolerant geschrieben werden — ein Logging-Fehler darf niemals die eigentliche Aktion selbst blockieren oder zum Absturz bringen. Typischer Aufbau: wer hat gehandelt (Actor), was wurde getan (Action), an welchem Objekt (Target), plus optionale strukturierte Details.

Kontext bei uns: app/utils/auditLog.ts bei Emzett, sichtbar im Adminpanel unter “Audit-Log” (siehe Dynamisches Rollensystem (granulares RBAC) für die Zugriffssteuerung darauf). Schreibt try/catch-geschützt, damit ein DB-Fehler beim Logging z. B. eine Rollenvergabe nicht verhindert.

Im Detail

Ein Audit Log unterscheidet sich von normalem Anwendungs-Logging (Fehler-/Debug-Ausgaben, die irgendwann rotiert/gelöscht werden) in Zweck und Anforderungen: Es muss vollständig, dauerhaft und manipulationssicher sein, weil es im Zweifel als Nachweis dient — wer hat wann welche Berechtigung geändert, wer hat auf welche Daten zugegriffen. Deshalb landet ein Audit Log typischerweise in einer eigenen, meist Insert-only-Tabelle (Einträge werden nie verändert oder gelöscht, nur angehängt), oft mit strengeren Zugriffsrechten als der Rest der Datenbank — im Idealfall kann nicht einmal ein Administrator einzelne Einträge nachträglich löschen, ohne dass das selbst wieder protokolliert wird.

Aufbau eines Eintrags

Ein typischer Audit-Log-Eintrag folgt einem Actor-Action-Target-Schema:

  • Actor — wer hat gehandelt (User-ID, aber auch System-Prozesse wie ein Cron-Job zählen als Actor)
  • Action — was wurde getan, meist als sprechender String (role.grant, user.delete, settings.update)
  • Target — an welchem Objekt (ID des betroffenen Datensatzes)
  • Details — optionale strukturierte Zusatzinformation (z. B. alter und neuer Wert bei einer Änderung)
  • Timestamp und oft zusätzlich die IP-Adresse oder Session-ID des Actors, um Vorfälle später einer konkreten Sitzung zuordnen zu können

Bei sicherheitskritischen Änderungen (z. B. Rechteänderungen) lohnt es sich, sowohl den alten als auch den neuen Wert zu speichern ({ from: "user", to: "admin" }), statt nur den neuen — sonst lässt sich im Nachhinein nicht mehr rekonstruieren, was vorher war.

Fehlertoleranz als Kernprinzip

Das „fehlertolerant schreiben“-Prinzip ist entscheidend: Ein Audit-Log-Eintrag ist eine Nebenwirkung der eigentlichen Aktion, nicht die Aktion selbst. Würde ein Logging-Fehler die Hauptaktion blockieren, könnte ein defektes Logging-System versehentlich die ganze Anwendung lahmlegen — ein klassisches Beispiel für „die Kontrolle darf nicht wichtiger werden als die kontrollierte Sache“. Gleichzeitig darf ein fehlgeschlagener Audit-Log-Eintrag nicht einfach stillschweigend verschwinden — üblich ist, den Fehler zumindest ins reguläre Fehler-Logging (z. B. Sentry) zu schreiben, damit Lücken im Audit Log auffallen, auch wenn sie die Hauptaktion nicht blockieren.

async function grantRole(userId: string, role: string) {
  await db.update(users).set({ role }).where(eq(users.id, userId))
  try {
    await logAudit({ actor: currentUser.id, action: "role.grant", target: userId, details: { role } })
  } catch (err) {
    console.error("Audit-Log fehlgeschlagen:", err) // Rollenvergabe ist trotzdem durchgelaufen
  }
}

Abgrenzung zu verwandten Konzepten

Ein Audit Log wird oft mit einem Event Log oder Activity Feed verwechselt, verfolgt aber einen anderen Zweck: Ein Activity Feed (z. B. „X hat Y kommentiert“) ist für Nutzer gedacht und darf durchaus unvollständig oder gekürzt sein, ein Audit Log ist für Nachvollziehbarkeit/Compliance gedacht und muss vollständig sein. Ein Database Changelog (z. B. über Postgres’ pg_audit-Extension oder Trigger-basierte History-Tabellen) protokolliert auf Datenbankebene JEDE Änderung automatisch, unabhängig von der Anwendungslogik — das ist umfassender, aber auch deutlich rauschintensiver, weil es keine semantische Einordnung wie „das war eine Rollenvergabe“ liefert, sondern nur rohe Zeilenänderungen.

Rechtlich ist ein Audit Log auch im Kontext der DSGVO relevant: Es dokumentiert, wer Zugriff auf personenbezogene Daten hatte, was bei einer Anfrage nach Auskunft oder im Falle eines Datenschutzvorfalls (Art. 33 DSGVO, Meldepflicht binnen 72 Stunden) entscheidend sein kann, um den Umfang eines Vorfalls überhaupt einzugrenzen.

Siehe auch: Dynamisches Rollensystem (granulares RBAC), Protokoll, DSGVO