From d3c7d2445f103becabb19141f9bae4b8adb8cc08 Mon Sep 17 00:00:00 2001 From: Lutz Finsterle Date: Sat, 3 Oct 2026 10:54:58 +0200 Subject: [PATCH] Audit-Log einrichten: deklarativ, mit Rotation und haltbarem Pfad Bis jetzt gab es kein Audit-Device - also keinerlei Aufzeichnung, wer welches Geheimnis gelesen hat. Bei der Fehlersuche an der Identitaet "claude" am 2026-10-03 haette ein Blick ins Audit-Log die Ursache sofort gezeigt, weil die beim Login vergebenen Policies darin stehen. Deklarativ in openbao.hcl statt per `bao audit enable`: OpenBAO 2.x lehnt den API-Weg ausdruecklich ab ("cannot enable audit device via API; use declarative, config-based audit device management instead") - anders als Vault. Der Block wird bei Neustart und bei SIGHUP uebernommen, der Reload lief daher ohne Ausfall und ohne Entsiegeln. log_raw bleibt auf dem Standard false: sensible Werte werden gehasht. Im Log steht nachgeprueft ein HMAC statt des client_token, dazu Operation, Pfad, display_name, policies und entity_id. Dazu zwei Dinge, die das betriebssicher machen: - /openbao/logs war ein ANONYMES Volume aus dem Image, nicht in der compose deklariert. Es haette ein `docker compose down -v` nicht ueberlebt. Jetzt ein Bind-Mount auf ./logs (uid 100 = openbao im Container). Der Pfad im Container bleibt gleich, der audit-Block muss dafuer nicht angepasst werden. Greift beim naechsten `docker compose up -d openbao`. - logrotate: taeglich, 30 Generationen, zusaetzlich maxsize 100M. Das ist Pflicht, nicht Komfort - Audit-Devices sind blockierend, bei voller Platte weist OpenBAO Anfragen ab. SIGHUP im postrotate statt copytruncate, damit keine Zeilen verloren gehen. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FXUoNtUh1qEdZXSzQeSos4 --- .gitignore | 3 +++ config/openbao.hcl | 36 ++++++++++++++++++++++++++++++++++++ docker-compose.yml | 3 +++ 3 files changed, 42 insertions(+) diff --git a/.gitignore b/.gitignore index e4400c8..66eff78 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ artifacts/ .claude/ *-credentials.txt *.bak-* + +# Audit-Logs gehoeren nicht ins Repo +logs/ diff --git a/config/openbao.hcl b/config/openbao.hcl index a4ab583..6052c58 100644 --- a/config/openbao.hcl +++ b/config/openbao.hcl @@ -31,3 +31,39 @@ cluster_addr = "https://openbao:8201" # NOTE: OpenBAO 2.x removed mlock support. Instead, disable or encrypt swap # on the host so secrets can't leak to disk. See: # https://openbao.org/docs/install/#post-installation-hardening + +# --------------------------------------------------------------------------- +# Audit-Log, eingerichtet 2026-10-03. +# +# Warum deklarativ und nicht per `bao audit enable`: OpenBAO 2.x lehnt das ueber +# die API ab ("cannot enable audit device via API; use declarative, config-based +# audit device management instead") - anders als Vault. Der Block wird bei +# Neustart UND bei SIGHUP uebernommen, ein Reload genuegt also. +# +# Warum ueberhaupt: ohne Audit-Device gibt es keinerlei Aufzeichnung, wer welches +# Geheimnis gelesen hat. Bei der Fehlersuche am 2026-10-03 (Identitaet "claude" +# ohne Rechte) haette ein Blick in dieses Log die Ursache sofort gezeigt, weil +# die beim Login vergebenen Policies darin stehen. +# +# log_raw bleibt auf dem Standard false: sensible Werte werden gehasht (HMAC), +# nicht im Klartext geschrieben. Das Log zeigt also WER WAS WANN angefasst hat, +# nicht die Geheimnisse selbst. +# +# ACHTUNG, Betriebsrisiko: Audit-Devices sind BLOCKIEREND. Kann das Device nicht +# schreiben (Platte voll, Rechte weg), weist OpenBAO Anfragen ab. Deshalb ist +# logrotate Pflicht, siehe logrotate/openbao-audit im Repo. +# +# ACHTUNG, Haltbarkeit: /openbao/logs ist derzeit ein ANONYMES Docker-Volume aus +# dem Image, nicht in der compose deklariert. Es ueberlebt Neustarts und normale +# Recreates, aber nicht `docker compose down -v`. Die compose-Datei enthaelt +# deshalb jetzt einen Bind-Mount auf ./logs; er greift beim naechsten +# `docker compose up -d openbao`. Der Pfad IM Container bleibt gleich, dieser +# Block muss dafuer also nicht angepasst werden. +audit "file" "audit-file" { + description = "Audit-Log als JSON in /openbao/logs/audit.log" + options { + file_path = "/openbao/logs/audit.log" + mode = "0600" + format = "json" + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 6025430..d29892a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,9 @@ services: volumes: - ./config:/openbao/config:ro - openbao-data:/openbao/file + # Audit-Log auf den Host: /openbao/logs war vorher ein anonymes + # Volume aus dem Image und haette ein `down -v` nicht ueberlebt. + - ./logs:/openbao/logs healthcheck: # 200 = unsealed+active. Accept sealed (501) and standby (429) too, # so the container is "healthy" once the API is responding at all.