Send the audit log to your SIEM
Pull the audit log into your SIEM with a key, or collect it from the API's standard output on your own deployment.
Send the audit log to your SIEM so it keeps its own copy. A collector pulls it with a key, or, on your own servers, reads the API's standard output.
Choose a way#
| Where the product runs | Way |
|---|---|
| Our cloud | The feed, GET /sdk/v1/audit-log |
| Your own servers | Standard output, or the feed |
Pull the feed#
- On Install, open Scopes on a live key that has a secret.
- Tick Read the project’s audit log, for your SIEM and choose Save scopes.
- Store the secret on the collector host only.
- Run the relay below, or point your collector at
GET /sdk/v1/audit-log. - Keep the last
nextCursorand send it asafteron the next call. - Remove duplicates by
id. An entry can arrive more than once.
The feed needs a live key: a test key gets 403 LIVE_KEY_REQUIRED. A key may read it 60 times a minute. Entries younger than 60 seconds are held back, so an entry still being written is not skipped. See Audit log.
Collect standard output#
- Each audit entry is also one JSON line on the API's standard output, with
"context":"AUDIT". - Route the container's logs to your collector with a Compose override.
- Keep only lines whose
contextisAUDIT. - Reload the collector.
- Change a setting in the console and check that its entry arrives.
A line with "stored": false is an entry the database did not store. Whoever runs the deployment can turn the copy off with AUDIT_LOG_STDOUT=false.
Examples for your SIEM#
Compose override, to the host's syslog:
services:
consent-api:
logging:
driver: syslog
options:
syslog-address: "unixgram:///dev/log"
tag: piedap-consentrsyslog, forwarding audit lines over TLS:
global(DefaultNetstreamDriverCAFile="/etc/ssl/certs/siem-ca.pem")
if $programname == "piedap-consent"
and $msg contains "\"context\":\"AUDIT\"" then {
action(type="omfwd" target="siem.example.in" port="6514"
protocol="tcp" StreamDriver="gtls" StreamDriverMode="1"
StreamDriverAuthMode="x509/name"
StreamDriverPermittedPeers="siem.example.in")
stop
}Fluent Bit to the Splunk HTTP Event Collector, with the Compose driver: fluentd, fluentd-address: "127.0.0.1:24224" and tag: piedap.api:
[INPUT]
Name forward
Listen 127.0.0.1
Port 24224
[FILTER]
Name parser
Match piedap.*
Key_Name log
Parser json
Reserve_Data On
[FILTER]
Name grep
Match piedap.*
Regex context ^AUDIT$
[OUTPUT]
Name splunk
Match piedap.*
Host splunk.example.in
Port 8088
TLS On
Splunk_Token ${SPLUNK_HEC_TOKEN}
Event_Sourcetype piedap:auditA relay for the feed, for Node.js 18 or later with no packages:
import { readFileSync, writeFileSync } from 'node:fs';
const API = 'https://consent.example.in/sdk/v1/audit-log';
const KEY = process.env.PIEDAP_AUDIT_KEY;
const STATE = '/var/lib/piedap/audit-cursor';
const sleep = (ms) => new Promise((done) => setTimeout(done, ms));
let cursor = '';
try {
cursor = readFileSync(STATE, 'utf8').trim();
} catch {}
for (;;) {
const query = new URLSearchParams({ limit: '1000' });
if (cursor) query.set('after', cursor);
const response = await fetch(`${API}?${query}`, {
headers: { Authorization: `Bearer ${KEY}` },
});
if (response.status === 429) {
await sleep(Number(response.headers.get('retry-after') || 60) * 1000);
continue;
}
if (!response.ok) throw new Error(`Feed answered ${response.status}`);
const page = await response.json();
for (const item of page.items) {
process.stdout.write(`${JSON.stringify(item)}\n`);
}
if (page.nextCursor) {
cursor = page.nextCursor;
writeFileSync(STATE, cursor);
}
if (!page.hasMore) await sleep(60000);
}node audit-relay.mjs >> /var/log/piedap/audit.jsonlA Splunk Universal Forwarder can watch that file:
[monitor:///var/log/piedap/audit.jsonl]
sourcetype = _json
index = securityindex=security sourcetype=_json action=lookup
| table createdOn userEmail details.recordsFor IBM QRadar, forward the relay file with rsyslog imfile, or the syslog lines above, on TCP 514 or TLS 6514. Use the log source type Universal DSM. Read fields with the JSON expressions /"action", /"resource", /"userEmail", /"ipAddress" and /"details"/"statusCode".
Limits#
- These are examples, not a connector. Keep the collector running yourself.
- Failed sign-ins and sessions are logged by PIEDAP IAM, not here.
- An entry whose write commits later than the 60-second hold reaches the feed late or not at all. The download and standard output still have it.
- Platform actions that belong to no project are on standard output only.
- The log is append-only in the database. The table's owner can still turn the guard off. Each entry is sealed to the one before it, but the log is not anchored, so your SIEM copy is the independent record.
Related#
- Audit log, the feed and its fields
- Download the audit log
- Monitor a deployment
- Configuration