Hoppa till huvudinnehåll
Petanque Life

Audit Log

F21.11 7 features

I korthet

The forensic record for everything sys does: append-only `sys_audit_entries` WORM-sealed after 24 hours via SHA-256 hash chain, rich filter/search with cursor pagination, sync and async export, an impersonation sub-view, daily integrity checks that page on tamper, and a 15-minute SIEM push to Azure Monitor / Splunk / Datadog.

Så fungerar det

The audit log is the contract behind every other guarantee on the platform. Each row in `sys_audit_entries` carries the operator (`actor_id`), the underlying user when impersonating (`actual_user_id`), the action, target type and id, tenant, impersonation id, reason, IP, user agent, request id, sys session id, and an action-specific metadata blob. After 24 hours the row is sealed: a SHA-256 hash chain links each sealed row to its predecessor (`worm_sealed`, `worm_hash`, `prev_hash`, `seal_sequence`), and a mutation guard rejects any write to a sealed row with `409 audit_worm_sealed`.

The hourly `audit-worm-seal` cron is what advances the chain. Search supports actor, target, action, tenant, time range, and free-text reason with cursor pagination (timestamp DESC, then `_id` DESC, encoded as base64url JSON) so the UI can scroll through millions of rows without hitting an offset wall. Per-operator saved searches are isolated by owner.

Export streams sync for ≤100 000 rows; larger sets queue a `SysAuditExportJob`, persist the artefact through `AuditExportSink` (Azure Blob SAS in production, in-memory in dev/test), and return a 7-day signed URL. The impersonation sub-view aggregates rows by `impersonation_id` into distinct sessions with start/end/target/reason and read/write counts, and clicking drills into the audit list pre-filtered to that session. The daily `audit-integrity-check` cron walks the chain end to end, persists a `SysAuditIntegrityDigest`, and opens a SEV1 `SysIncident` if any link is broken; the dashboard surfaces the latest `latest_ok` digest so an on-call engineer can see at a glance that the chain is intact.

Manual integrity runs are gated on `sys_security` plus fresh-auth. SIEM export is per-tenant configurable via `SysSiemConfig` (Azure Monitor, Splunk, Datadog, or mock); the 15-minute `audit-siem-push` cron ships the delta since `last_pushed_at` through a pluggable transport, and a test endpoint pushes a probe payload through the configured sink to confirm the credentials work.

Centrala funktioner

  • Append-only `sys_audit_entries` with rich actor, target, reason, request, session metadata
  • WORM seal at 24 hours via SHA-256 hash chain; mutation guard rejects sealed writes
  • Filter/search with cursor pagination and per-operator saved searches
  • Sync export ≤100k rows; async `SysAuditExportJob` for larger sets with 7-day signed URL
  • Impersonation sub-view aggregates rows by `impersonation_id` into sessions
  • Daily integrity check with SEV1 incident on tamper, dashboard surfaces last `latest_ok`
  • SIEM export per-tenant (Azure Monitor / Splunk / Datadog) every 15 minutes

I praktiken

A regulator asks for proof that a refund issued last quarter was authorised by a finance operator. The auditor opens the audit search, filters by `action=billing.refund.execute`, time range Q1, and the target invoice id. One row returns.

She clicks through to see the actor, fresh-auth timestamp, reason, IP, and the linked `request_id`. She exports the row plus its surrounding 50 to JSON; the sync stream completes in under a second. The next morning the integrity-check cron flags a hash mismatch — actually a clock skew on a Cosmos replica — and opens a SEV1; the on-call security engineer confirms no tamper, closes the incident, and the daily digest goes back to `latest_ok`.

Features i detta subsystem

7
ID Status Funktioner
F21.11.01 Levererad Immutable audit collection sys_audit_entries — append-only, WORM-stored after 24 h via SHA-256 hash chain. Hourly audit-worm-seal cron, mutation guard rejects sealed-row writes with 409 audit_worm_sealed. ✅ PL-T131
F21.11.02 Levererad Entry schema — actor_id, actual_user_id (nullable, set during impersonation), action, target_type, target_id, tenant_id, impersonation_id, reason, ip, ua, request_id, sys_session_id, metadata (action-specific JSON), timestamp plus seal columns (worm_sealed, worm_hash, prev_hash, seal_sequence). Implemented (PL-T131)
F21.11.03 Levererad Filter + search UI — by actor, target, action, tenant, time range, reason text. Cursor pagination (timestamp DESC, _id DESC, base64url JSON cursor). Per-operator saved searches with owner isolation. Implemented (PL-T131)
F21.11.04 Levererad Export — CSV and JSON. Sync stream for ≤ 100 k rows; larger sets queue a SysAuditExportJob, persist the artifact via AuditExportSink (Azure Blob SAS in prod, in-memory in dev/test), return a signed URL with 7-day expiry. Implemented (PL-T131)
F21.11.05 Levererad Impersonation sub-view — distinct sessions aggregated by impersonation_id (start/end/target/reason/reads/writes), clickable to drill into the audit list filtered by that session. Implemented (PL-T131)
F21.11.06 Levererad Integrity check — daily audit-integrity-check cron walks the chain, persists a SysAuditIntegrityDigest, opens a SEV1 SysIncident on tamper detection. Dashboard surfaces latest_ok digest. Manual run gated on sys_security + fresh-auth. Implemented (PL-T131)
F21.11.07 Levererad SIEM export — per-tenant SysSiemConfig (Azure Monitor / Splunk / Datadog / mock). 15-minute audit-siem-push cron ships the delta since last_pushed_at. Pluggable transport, test endpoint pushes a probe payload through the configured sink. Implemented (PL-T131)