Audit forwarding to a SIEM
Two ways to feed a SIEM
| Push (syslog) | Pull (API) | |
|---|---|---|
| Direction | Vaks PM connects out to your collector. | Your collector connects in and reads. |
| Latency | Real time, event by event. | Whatever polling interval you set. |
| Best when | You run Splunk, Graylog, Wazuh, QRadar — anything with a syslog input. | Your collector prefers to fetch, or you archive on your own schedule. |
| Format | RFC 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
| Side | What you need |
|---|---|
| Push | A 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. |
| Pull | Nothing on your side beyond a collector that can send a bearer token and parse JSON Lines or CEF. |
| Vaks PM | org: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:
| Field | What to put |
|---|---|
| Collector host | DNS name or IP of the receiver. A bare host — no scheme, no port suffix. siem.internal, not tls://siem.internal:6514. |
| Port | 6514 for syslog-TLS (the default), 514 for common raw TCP. |
| Transport | TLS 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 severity | INFO 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 SIEM | The 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.
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:
- mTLS client certificate (PEM), in the syslog settings — the public certificate only.
- The private key is mounted on the worker as a deployment secret named
syslog_client_key. It is one key for the whole deployment, not per organization, and it is installed by an operator with shell access, not through the admin panel.
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.
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:
- SIEM connection OK — the message reached the collector.
- Syslog failure with a reason — the handshake or the send failed; the reason names which.
- No response from the worker — the worker did not report a result; check its logs.
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>.
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.
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:
| Setting | Effect |
|---|---|
| Audit entry retention | How long entries are kept, in days. Default 365, between 30 and 3650. Older entries are purged by the daily job. |
| Archive before purge | When 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.
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.
| Symptom | Cause & fix |
|---|---|
| Hôte syslog invalide on save | The 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 attendu | The CA field does not contain a PEM certificate. Paste the block including the -----BEGIN CERTIFICATE----- line. |
| Test says No response from the worker | The 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 collector | Certificate verification is on by default. Supply the collector's CA in Collector CA (PEM). |
| Nothing forwarded, no error in the UI | Redis 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 SIEM | Minimum severity is probably CRITICAL. Most routine activity is INFO and is filtered out before sending. |
| Collector authentication fails despite a client certificate | The 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 SIEM | Expected — 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.