audit-siem

SIEM streaming

Push every audit log entry to your SIEM (Splunk, Datadog, Elastic, an in-house collector) the moment it happens. Signed with a workspace secret, JSON-per-event, one config per workspace. Complement to the audit CSV export: the export is the archival snapshot, this is the live tail.

Requires the Enterprise plan and workspace admin role.

Configure

Workspace admin only. Settings, then SIEM streaming.

Fields:

  • Webhook URL (https, required): the endpoint your SIEM (or an ingestion proxy in front of it) exposes to receive one JSON object per event.
  • HMAC secret (at least 16 characters, required): the shared secret used to sign every outbound request. Click Generate for a 48-hex random value. The SPA never reads the secret back after save; a leaked bearer token cannot exfiltrate it.
  • Timeout (1 to 300 seconds, default 30): how long Ithura waits for your collector to respond before treating a delivery as failed.
  • Active (toggle): uncheck to pause streaming without deleting the config (useful during a SIEM maintenance window).

Saving writes the config and audits the change under workspace.audit_siem.configured. Removing writes workspace.audit_siem.deleted. Both entries themselves stream to the SIEM (the delete lands before the config row is dropped).

Wire contract

Every audit log row triggers one outbound POST:

POST <your webhook_url>
Content-Type: application/json
X-Ithura-Signature: <hex hmac_sha256 of the body>
User-Agent: Ithura-SIEM/1.0

{
  "id":            "<uuid>",
  "workspace_id":  "<uuid>",
  "actor_user_id": "<uuid or null>",
  "actor_label":   "system / <string> / null",
  "action":        "workspace.member.invited",
  "entity_type":   "workspace_member",
  "entity_id":     "<uuid or null>",
  "metadata":      { /* action-specific object */ },
  "ip_address":    "203.0.113.7 or null",
  "user_agent":    "Mozilla/5.0 ... or null",
  "created_at":    "2026-08-03T14:22:11.123456789Z"
}

Verify the signature before trusting the body:

expected = hex(hmac_sha256(ITHURA_SIEM_SECRET, request_body))

Constant-time compare against the header. Reject on mismatch.

Respond with any 2xx to acknowledge. Non-2xx and network errors are logged on the Ithura side but not retried in v1 (see follow-ups).

Statuses this feature writes about itself

The SIEM config surface writes its own audit entries, which then stream through the same webhook:

ActionWhen
workspace.audit_siem.configuredAdmin saved the config (create or update). Metadata: { webhook_url, is_active, timeout_seconds }.
workspace.audit_siem.deletedAdmin removed the config.

The secret is never included in metadata. The webhook URL is included because it is already visible on the settings page to any admin.

Delivery guarantees (v1)

Fire-and-forget. Ithura calls your webhook once per event, with the configured timeout. There is no retry queue and no dead-letter table in v1. If your collector is down for 30 minutes, those events do not land in the SIEM (they remain in the audit log and are still in the CSV export). Two mitigations:

  1. Ship a small retrying proxy in front of your SIEM (an nginx + fluent-bit sidecar, an SQS queue, a serverless function that buffers to S3). Return 200 fast, then hand off to your durable pipeline.
  2. Fall back to the CSV export for any window where the live stream dropped events. The export covers the same rows and is filter-by-date friendly.

Follow-ups

  • Delivery table + retries. Write every attempt into workspace_audit_siem_deliveries (attempt count, last error, next retry), show a "recent failures" panel in settings, and auto-retry with backoff on 5xx / network errors.
  • Backfill. A "replay last N days into your SIEM" action, so a new customer can seed their collector with the existing audit history rather than only forward-going events.
  • Per-scope filters. Ship only events matching a set of actions or entity types (e.g. only member and permission changes) so a compliance-only SIEM does not receive the whole activity feed.
  • Audit CSV export: batch counterpart. Same rows, batch shape.
  • Agent Dispatch Queue: reuses the same HMAC signing scheme for its outbound webhook, so a customer that verifies one payload verifies the other with the same code.