Audit forwarding to a SIEM

Vaks PM · Integration guide · SIEM · July 2026

What you will end up with. Every audit event — sign-ins, permission changes, data exports, agent actions — streamed to your security monitoring, either pushed in real time over syslog or pulled by your collector from a scoped API. The local audit log stays complete regardless; this is a copy for correlation and long-term retention.

Two ways to feed a SIEM

Push (syslog)Pull (API)
DirectionVaks PM connects out to your collector.Your collector connects in and reads.
LatencyReal time, event by event.Whatever polling interval you set.
Best whenYou run Splunk, Graylog, Wazuh, QRadar — anything with a syslog input.Your collector prefers to fetch, or you archive on your own schedule.
FormatRFC 5424 syslog.JSON Lines or CEF.

They are not exclusive — you can push in real time and still pull for reconciliation. Both draw from the same append-only log, which has exactly one deletion path: the retention purge described at the end.

Prerequisites

SideWhat you need
PushA syslog receiver reachable from the instance, on TCP or TLS. TLS is strongly advised — the log carries IP addresses and email addresses. For an internal or self-signed collector, its CA certificate.
PullNothing on your side beyond a collector that can send a bearer token and parse JSON Lines or CEF.
Vaks PMorg:manage to configure syslog and mint a read token. Pull tokens carry the audit:read scope.

Step 1 — Configure the collector (push)

Open Admin → Security & Compliance and find SIEM / syslog forwarding. Fill in:

FieldWhat to put
Collector hostDNS name or IP of the receiver. A bare host — no scheme, no port suffix. siem.internal, not tls://siem.internal:6514.
Port6514 for syslog-TLS (the default), 514 for common raw TCP.
TransportTLS or TCP. Prefer TLS.
Collector CA (PEM)Only if the receiver presents an internal or self-signed certificate. Leave empty to use the system trust store. Without it, a self-signed collector fails the TLS handshake.
Minimum severityINFO forwards everything, including every routine change. WARNING drops the routine noise. CRITICAL sends only security events. Filtering happens before anything leaves the instance.
Forward to a SIEMThe kill switch. Off means the log stays viewable in the app but nothing is sent.

The stream is RFC 5424 over the transport you chose, octet-counting framing, facility 13. Severity maps to syslog levels: critical → crit, warning → warning, info → info. Each message ends with the full audit entry as compact JSON, and carries an id field.

Deduplicate on the id field. Delivery is at-least-once with automatic retries, so the same entry can reach your collector more than once. The id is stable; use it as the dedup key. Also expect up to a minute of lag after saving a setting change — the configuration is cached for 60 seconds.

Step 2 — Mutual TLS (optional)

If your collector requires the client to authenticate too, mutual TLS splits across two places by design — the public certificate in a setting, the private key never in the database:

On Docker Swarm, an operator installs the key like this:

printf '<PEM private key>' | docker secret create syslog_client_key -
docker service update --force vaks-pm_worker

On Kubernetes it is the syslog_client_key entry of the release secret, mounted into the worker.

mTLS degrades silently if the key is missing. Configure the certificate but leave the secret at its placeholder and the connection simply proceeds without client authentication — no error anywhere. If your collector is meant to require the client certificate and is not seeing one, check that the worker secret holds a real key and that the worker was restarted after it changed.

Step 3 — Test

Save your settings first — the test uses the stored configuration, not what is currently in the form. Then press Test connection. It sends a single audit.test message to the collector and reports back within about fifteen seconds:

The test works even while forwarding is disabled, so you can validate connectivity before flipping the kill switch. Real forwarding needs both the switch on and a non-empty host.

When a batch cannot be delivered

If a batch exhausts its retries, the local log is unaffected — only the SIEM copy of those entries is lost. Vaks PM surfaces this rather than hiding it: an amber banner appears at the top of the audit log for the day, counting the undelivered batches and lost entries, with the last error. It is a signal to check the collector, not a data-loss event on the Vaks PM side.

Read the log by API (pull)

For a collector that prefers to fetch, two endpoints are exposed under the public API:

GET /api/v1/audit-logs                 # keyset-paginated JSON
GET /api/v1/audit-logs/export          # streaming, format=jsonl (default) or format=cef

Both accept the same filters as query parameters: from, to (ISO 8601), action (prefix match), actorId, actorType, severity, outcome, resourceType, resourceId, and q for a free-text contains.

Mint the token in Admin → Integrations → API keys: create an organization key and select the audit:read scope. Call the endpoints on the organization's own hostname with Authorization: Bearer <secret>.

Two practical notes. The scope picker labels audit:read only as "Application permission" — that is the right scope, the description is just generic. And an export reads in batches up to 100,000 rows per call, so for a large window, page with from/to rather than pulling everything at once. Paginated reads return a cursor; pass it back verbatim until it comes back empty.
A personal token is not enough on its own. A user token only reaches audit:read if that user already holds the permission through their role — in practice an organization administrator. An organization key is the clean choice for an unattended collector. Neither an agent nor its capabilities can ever carry audit:read.

Retention & integrity

The audit log is append-only. Its only deletion path is a daily retention purge, and two settings govern what happens before anything is removed:

SettingEffect
Audit entry retentionHow long entries are kept, in days. Default 365, between 30 and 3650. Older entries are purged by the daily job.
Archive before purgeWhen on, entries are exported as gzipped JSON Lines to object storage before deletion — unlimited cold retention for compliance. Fail-safe: if the archive fails, the purge is skipped, so nothing un-archived is ever destroyed.

Independently, once a day Vaks PM seals the previous day's entries into a chained integrity anchor — a fingerprint of that day's log, linked to the day before. The anchor is itself an audit entry, so it is forwarded to your SIEM too, putting the fingerprint out of reach of anyone who might tamper with the database directly. You can check a day at any time with Verify integrity in the audit log: it recomputes the fingerprint and compares it to the sealed anchor, reporting a match or flagging tampering.

Why the anchor matters for a SIEM strategy. Forwarding proves what left the box; the anchor proves the box's own copy was not altered afterwards. Together they mean a tamper attempt is visible both in your SIEM (the anchor arrived, with a fingerprint) and in Vaks PM (verify shows a mismatch). Keep the daily audit.anchor entries in your SIEM; they are the reference to compare against.

Troubleshooting

Settings are validated on save; messages originating from the server come back in French regardless of interface language, reproduced verbatim below.

SymptomCause & fix
Hôte syslog invalide on saveThe host has a scheme or a port suffix. It must be a bare DNS name or IPv4 address — the port goes in its own field.
CA invalide : un certificat PEM est attenduThe CA field does not contain a PEM certificate. Paste the block including the -----BEGIN CERTIFICATE----- line.
Test says No response from the workerThe worker did not report back. Check the vaks-pm_worker logs; often Redis is unreachable, which also stops real forwarding.
TLS handshake fails to an internal collectorCertificate verification is on by default. Supply the collector's CA in Collector CA (PEM).
Nothing forwarded, no error in the UIRedis outage stops the queue silently — the local log still writes. Check Redis. Also confirm the kill switch is on and the host is set.
Very little reaches the SIEMMinimum severity is probably CRITICAL. Most routine activity is INFO and is filtered out before sending.
Collector authentication fails despite a client certificateThe worker secret is still the placeholder, so no client certificate is actually presented. Install the real key and restart the worker.
Duplicate entries in the SIEMExpected — at-least-once delivery. Deduplicate on the id field (in CEF, the externalId extension).

Related: encryption, keys & DORA for the compliance context · operations for backups · all integrations.