hashicorp/vault
Audit pipeline
Audit logging in Vault isn't a single subsystem — it's a pipeline that runs alongside every request. This page covers how an HTTP request becomes one or more audit log lines, including the formatting, HMAC, and fan-out steps. The components themselves are documented in systems / audit.
Purpose
Provide an unforgeable record of what Vault was asked to do, what answer it returned, and who asked.
Stages
graph LR
HTTP[http/handler.go] -->|*logical.Request| Core[Core.HandleRequest]
Core -->|LogRequest| Pre[Pre-call audit]
Pre --> Route[Backend dispatch]
Route -->|*logical.Response| Core
Core -->|LogResponse| Post[Post-call audit]
Pre & Post --> EF[entry_formatter.go]
EF --> Hash[hashstructure.go HMAC sensitive fields]
Hash --> Bus[Broker fan-out]
Bus --> File[file device]
Bus --> Sock[socket device]
Bus --> Sys[syslog device]The pre-call entry uses the request as-is. The post-call entry uses the request plus the response. Both entries reference each other by request_id.
Pre-call entry shape
{
"type": "request",
"auth": {
"client_token": "hmac-sha256:abc...",
"accessor": "hmac-sha256:def...",
"display_name": "userpass-alice",
"policies": ["default", "team-secrets"],
"metadata": { "username": "alice" },
"entity_id": "..."
},
"request": {
"id": "...",
"operation": "update",
"namespace": "root",
"mount_type": "kv",
"path": "secret/data/team/api-keys",
"client_token": "hmac-sha256:abc...",
"data": { "data": { "key": "hmac-sha256:val..." } }
}
}Fields wrapped in hmac-sha256: were HMAC'd by audit/hashstructure.go using the device's salt. The salt itself never leaves Vault.
Header allow/deny
audit/headers.go (and the sys/config/auditing/request-headers API) controls which incoming HTTP headers appear in the entry and which of those are HMAC'd. The default allow list is small.
Mount tunables
Per-mount tunables audit_non_hmac_request_keys and audit_non_hmac_response_keys add to a per-mount safelist of fields that should appear in plain text. Useful for non-sensitive fields that auditors need to query (e.g. metadata.user_email).
Failure semantics
If a configured audit device fails to write, the entire request fails (default behavior). This is intentional: a missing audit log is treated as a security incident, not a recoverable error.
The override prefix= and fallback= per-device options can change this in narrow edge cases (e.g. an emergency device that should not block on failure during a known outage).
Integration with eventlogger
The broker is built on top of HashiCorp's eventlogger library: each audit device is one node in an eventlogger pipeline. Filters, formatters, and sinks plug into pipelines uniformly. See audit/nodes.go.
Common debugging
- Enable a
fileaudit device pointing at/tmp/audit.logto see what's being logged. - Set log level on the
vault.auditlogger todebugto see broker decisions. - Run
tail -f /tmp/audit.log | jq .to format entries. - Look for
audit log not configuredwarnings — they suggest the broker started but no devices are wired.
Entry points for modification
- Add a new sensitive field: extend the safelist in
audit/headers.goor the per-mount tunables. - New device kind: implement
audit.Backendinaudit/backend_<name>.go, register a factory incommand/commands.go. - Change the on-disk format (use with care):
audit/entry_formatter.go.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.