Files
OpenBAO/config/openbao.hcl
Lutz Finsterle d3c7d2445f 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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXUoNtUh1qEdZXSzQeSos4
2026-10-03 10:54:58 +02:00

70 lines
3.0 KiB
HCL

ui = true
# Integrated Raft storage — self-contained, supports snapshot backups.
# Path is /openbao/file because that directory is pre-created in the image
# owned by the unprivileged "openbao" user; a named volume mounted there
# inherits that ownership and is writable after the entrypoint drops root.
storage "raft" {
path = "/openbao/file"
node_id = "openbao-node-1"
}
# API listener. TLS is disabled here for an initial home-lab setup; the
# expectation is that a reverse proxy (Caddy/Traefik/nginx) terminates TLS,
# or you enable native TLS below. Do NOT expose this port to the internet
# without TLS in front of it.
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
# To enable native TLS instead of a reverse proxy:
# tls_disable = 0
# tls_cert_file = "/openbao/config/tls/cert.pem"
# tls_key_file = "/openbao/config/tls/key.pem"
}
# Advertised addresses. api_addr is the external URL clients/UI use — here the
# Traefik-fronted HTTPS name. cluster_addr is for Raft peer traffic (single node).
api_addr = "https://openbao.famfi.home"
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"
}
}