Audit log
With --audit-log, every request produces one JSON line in a dedicated file
(- for stdout), separate from the operational log. Authentication failures
and denials produce events too.
{"ts":"...","event":"query","request_id":"1a1147f8f9b0...","user":"analyst","roles":["analyst"], "remote_addr":"10.0.0.7","database":"sales","statement_type":"SELECT", "sql":"SELECT count(*) FROM orders WHERE amount > ?","sql_sha256":"...","params_count":0, "tables":["sales.main.orders"],"resolved":true,"decision":"allow","decided_by":"policy", "policy_sha256":"...","status":200,"rows":1,"bytes":42, "timing_ms":{"queue":0,"inspect":1.2,"authorize":0.25,"execute":1.7,"total":3.3}, "curral_version":"0.4.1"}Fields worth knowing
Section titled “Fields worth knowing”decision:allow,denyorerror.decided_by:policy,engine,auth,queue,audit,request,protectionorconcurrency.policy_sha256: proves which version of the rules decided.request_id: also in theX-Request-Idresponse header and the operational log.
Personal data
Section titled “Personal data”By default SQL literals become ?, because they may contain personal data.
Parameter values are never logged, only their count, and passwords never
appear.
--audit-sql |
|
|---|---|
redacted (default) |
literals replaced by ? |
full |
the SQL as sent |
hash |
only sql_sha256 |
If the SQL uses constructs the tokenizer cannot read safely, only the hash is kept.
Fail-closed
Section titled “Fail-closed”Before executing, curral reserves room in the audit queue
(--audit-queue, 4096 events). If the file cannot be written (full disk,
permissions) or the queue is full, the query gets 503 and does not run.
Recovery is checked every 5 seconds and logged as audit_recovered.
A process crash between a write’s commit and its event being recorded can still lose that event.
Rotation
Section titled “Rotation”Move the file and send SIGHUP. The new file starts with an
audit_reopened event; copytruncate is not needed.