Wardengate

Operate

SIEM export

The audit stream is the same stream regardless of where it ends up — the operator console, the built-in reports, and your SIEM all see identical event envelopes. This page is the reference for wiring the stream into a downstream pipeline, the schema guarantees it ships with, and the common sinks Wardengate supports out of the box.

Event envelope

Every event is a single JSON object with a stable envelope. Event-type specific fields live under context. The envelope is the contract; new top-level fields are additive and documented per release.

{
  "ts":          "2026-04-20T18:41:02.419Z",  // RFC 3339, UTC, ms precision
  "event_type":  "session.opened",            // dotted namespace, stable
  "event_id":    "evt_01HZ8F4N92Y7EJG1K5T3RCMN8W",
  "sequence":    48210411,                    // monotonic per cluster
  "actor": {
    "id":     "usr_01HX3KQ9FR",
    "email":  "alice@corp",
    "groups": ["sre", "oncall-primary"],
    "kind":   "user"
  },
  "target": {
    "id":       "tgt_01HX4MZ01V",
    "name":     "web-01.prod",
    "protocol": "ssh",
    "address":  "10.10.4.20:22",
    "tags":     { "env": "prod", "role": "web" }
  },
  "result":     "success",                    // success | denied | error
  "session_id": "sess_a91c7f20bb48",
  "policy":     "prod-ssh-write",
  "gateway":    "gw-us-1",
  "source_ip":  "198.51.100.24",
  "context": {
    "account":   "deploy",
    "mfa":       "webauthn",
    "approvals": [{ "approver": "carol@corp", "at": "2026-04-20T18:40:55Z" }]
  },
  "prev_hash":  "8a71f0...c411",
  "hash":       "5f8ab4...d027"
}

Event catalog

The event-type namespace is stable across releases. A shortened catalog:

NamespaceEvents
auth.*sso_login, sso_failed, mfa_challenge, mfa_passed, session_signed_in
session.*requested, approved, opened, closed, terminated, shadowed, handoff
policy.*allowed, denied, matched, changed, deployed
command.*allowed, denied, alerted, approved, filtered
recording.*sealed, viewed, exported, expired, legal_hold
idp.*scim_create, scim_update, scim_disable, sync_failed
system.*gateway_registered, gateway_drained, config_changed, license_updated

Supported sinks

Sinks are declared with an EventSink resource. Multiple sinks can run in parallel — fanning out to a primary SIEM and a cheap archive is the typical setup.

Splunk HEC

apiVersion: wardengate/v1
kind: EventSink
metadata:
  name: splunk-primary
spec:
  kind: splunk-hec
  endpoint: https://splunk.corp.example:8088/services/collector/event
  tokenSecret: splunk-hec-token
  index: wardengate
  sourcetype: wardengate:v1
  batch:
    maxEvents: 500
    maxBytes: 1mb
    flushSeconds: 2

Elastic / OpenSearch

spec:
  kind: elastic
  endpoint: https://elastic.corp.example:9200
  indexTemplate: wardengate-{yyyy.MM.dd}
  auth: { kind: apiKey, secret: elastic-api-key }
  mapping: ecs                # elastic common schema
  pipeline: wardengate_enrich

Datadog

spec:
  kind: datadog
  endpoint: https://http-intake.logs.datadoghq.com/api/v2/logs
  apiKeySecret: datadog-api-key
  ddsource: wardengate
  ddtags: ["env:prod", "service:wardengate"]

Sumo Logic

spec:
  kind: sumo-http
  collectorUrlSecret: sumo-collector-url
  category: wardengate/prod

Chronicle

spec:
  kind: chronicle
  customer: "00000000-0000-0000-0000-000000000000"
  region: us
  serviceAccountSecret: chronicle-sa
  logType: WARDENGATE
  mapping: udm                # Unified Data Model

Syslog (RFC 5424)

spec:
  kind: syslog
  transport: tls              # tcp | udp | tls
  host: siem.corp.example
  port: 6514
  facility: local4
  format: rfc5424             # rfc3164 also supported
  framing: octet-count
  messageFormat: cef          # cef | json | raw
  ca: /etc/wardengate/tls/corp-ca.pem

AWS Kinesis

spec:
  kind: kinesis
  region: us-east-1
  stream: wardengate-audit
  partitionKey: "{{ .actor.id }}"
  credentials: { kind: irsa, roleArn: arn:aws:iam::111:role/wg-kinesis }

Kafka

spec:
  kind: kafka
  brokers: ["kafka-0:9093", "kafka-1:9093", "kafka-2:9093"]
  topic: wardengate.audit.v1
  auth: { kind: sasl-scram-512, secret: kafka-wg }
  tls: { caSecret: kafka-ca, skipVerify: false }
  acks: all
  compression: zstd

Webhook

spec:
  kind: webhook
  url: https://siem.corp.example/ingest/wardengate
  headers:
    Content-Type: application/x-ndjson
    Authorization: "Bearer {{ secret:siem-token }}"
  signing:
    algorithm: hmac-sha256
    secret: siem-webhook-signing
    header: X-Wardengate-Signature

Backpressure and delivery guarantees

Each sink has an in-memory batch buffer and an on-disk spool that takes over when the buffer fills. Events flow in this order:

  • In-memory batch (default 500 events or 1 MB, whichever first).
  • On-disk spool if the upstream is slow or unreachable (default 2 GB, configurable).
  • Dead-letter queue for events that the sink rejects repeatedly (4xx-class failures), inspectable through wgctl sink dlq ls and replayable with wgctl sink dlq replay.

Sinks are at-least-once by default. The envelope event_id is idempotent — your SIEM can dedup on it. For sinks that cannot dedup, switch the sink to deliveryMode: exactly-once and Wardengate takes on the cost of transactional batching.

Dead-letter queue

The DLQ catches events that the upstream rejected for reasons that will not fix themselves (malformed, forbidden, bad index). Network errors and 5xx responses are retried with exponential backoff and never hit the DLQ. DLQ events are kept for 14 days and surfaced as an alert when the count crosses a configurable threshold — “my SIEM ate 4000 events and I had no idea” is the exact pain mode this exists to eliminate.

Field mappings for common schemas

The raw envelope maps cleanly to the common normalisation schemas your SIEM already knows. The sink config selects the schema and Wardengate emits pre-mapped fields — your SIEM engineers do not need to write parsers.

CEF (Common Event Format)

CEF:0|Wardengate|WGCP|1.6|session.opened|Session opened|3|\
  src=198.51.100.24 suser=alice@corp duser=deploy \
  dst=10.10.4.20 dpt=22 app=ssh \
  cs1Label=policy cs1=prod-ssh-write \
  cs2Label=sessionId cs2=sess_a91c7f20bb48

OCSF (Open Cybersecurity Schema Framework)

WardengateOCSF
actor.emailactor.user.email_addr
target.addressdst_endpoint.ip/dst_endpoint.port
source_ipsrc_endpoint.ip
session_idsession.uid
resultstatus / status_id

ECS (Elastic Common Schema)

WardengateECS
ts@timestamp
event_typeevent.action
actor.emailuser.email
source_ipsource.ip
target.addressdestination.ip / destination.port

Sample events

policy.denied

{
  "ts": "2026-04-20T19:03:11.802Z",
  "event_type": "policy.denied",
  "event_id": "evt_01HZ8FC7R2Y7EJG1K5T3RCMN8W",
  "actor": { "email": "mallory@corp", "groups": ["contractors"] },
  "target": { "name": "billing-ro.prod", "protocol": "postgres", "tags": {"env":"prod"} },
  "result": "denied",
  "policy": "default-deny",
  "context": {
    "reason": "no allow rule matched",
    "source_ip": "203.0.113.77",
    "attempted_account": "readonly"
  }
}

command.denied

{
  "ts": "2026-04-20T19:05:24.017Z",
  "event_type": "command.denied",
  "session_id": "sess_a91c7f20bb48",
  "actor": { "email": "alice@corp" },
  "target": { "name": "web-01.prod", "protocol": "ssh" },
  "result": "denied",
  "context": {
    "rule": "block-disk-wipes",
    "cmd": "rm",
    "argv": ["-rf", "/*"],
    "policy": "prod-ssh-rails"
  }
}

recording.exported

{
  "ts": "2026-04-20T19:08:41.122Z",
  "event_type": "recording.exported",
  "session_id": "sess_a91c7f20bb48",
  "actor": { "email": "carol@corp", "groups": ["auditors"] },
  "result": "success",
  "context": {
    "format": "mp4",
    "bytes": 14872131,
    "sha256": "7b4e...c910",
    "reason": "ticket SEC-0412"
  }
}

idp.sync_failed

{
  "ts": "2026-04-20T19:10:01.000Z",
  "event_type": "idp.sync_failed",
  "result": "error",
  "context": {
    "provider": "corp-okta",
    "kind": "scim",
    "http_status": 401,
    "error": "invalid_token",
    "retry_at": "2026-04-20T19:15:00Z"
  }
}

Testing the pipeline

wgctl sink test splunk-primary
  connect ............... ok (tls 1.3)
  auth .................. ok
  write 10 synthetic events .... ok (ack in 84ms)
  backlog ............... 0 events / 0 B on-disk
  last error ............ (none in last 24h)

Related

  • Audit & reporting — the same event stream, displayed inside Wardengate.
  • Alerts — firing rules off the event stream before it leaves the cluster.
  • Webhooks — a simpler programmatic consumer when a full SIEM sink is overkill.