Stream your enterprise audit log into your SIEM. Infracodebase exposes a pull API: a paginated JSON feed with strong delivery guarantees. We ship a ready-made poller for Splunk. Any SIEM that polls HTTPS works the same way.
enterprise.audit.read. Create it under Settings → Tokens with the SIEM / audit export template. The token appears once. Store it in your secret manager.app.infracodebase.com. Single-tenant deployments: allow your dedicated gateway IP.Your export endpoint:
https://app.infracodebase.com/api/enterprises/<ENTERPRISE_ID>/audit-log/export
The poller runs as a Splunk scripted input. Where it runs depends on your Splunk:
Direct push to Splunk HEC is on our roadmap and removes the forwarder requirement. Ask your account contact for timing.
The steps use the built-in search app. Substitute your own app if you have one. Paths in inputs.conf resolve against the app directory.
APPBIN="$SPLUNK_HOME/etc/apps/search/bin/scripts"
mkdir -p "$APPBIN"
curl -fsSL -o "$APPBIN/infracodebase_audit.py" \
https://app.infracodebase.com/integrations/splunk/infracodebase_audit.py
chmod +x "$APPBIN/infracodebase_audit.py"
The script uses only the Python 3 standard library. No pip. Put it in the app's bin/scripts, not $SPLUNK_HOME/bin/scripts. Scripted-input paths resolve against the app, not $SPLUNK_HOME.
Splunk silently ignores environment.* keys in inputs.conf for scripted inputs, so pass config through a wrapper. Create $APPBIN/infracodebase_audit.sh:
#!/bin/bash
export INFRACODEBASE_AUDIT_ENDPOINT="https://app.infracodebase.com/api/enterprises/<ENTERPRISE_ID>/audit-log/export"
export INFRACODEBASE_API_TOKEN="<YOUR_TOKEN>"
exec /usr/bin/python3 "$(dirname "$0")/infracodebase_audit.py"
chmod +x "$APPBIN/infracodebase_audit.sh"
Optional: export INFRACODEBASE_SINCE="2026-04-01T00:00:00Z" starts the feed at a timestamp instead of the beginning of history. Applies only before the first cursor exists.
In production, read the token from Splunk's credential store (storage/passwords) or a permission-restricted file. Do not inline it.
$SPLUNK_HOME/etc/apps/search/local/inputs.conf:
[script://./bin/scripts/infracodebase_audit.sh]
disabled = false
index = infracodebase_audit
interval = 300
sourcetype = infracodebase:audit
$SPLUNK_HOME/etc/apps/search/local/props.conf. On a single Splunk Enterprise instance, use the whole block. On Splunk Cloud, put the index-time half on the forwarder and the search-time half on the search head.
[infracodebase:audit]
# --- index-time (forwarder on the Splunk Cloud path) ---
SHOULD_LINEMERGE = false
LINE_BREAKER = ([\r\n]+)
TIME_PREFIX = "timestamp":\s*"
TIME_FORMAT = %Y-%m-%dT%H:%M:%S.%3NZ
# The trailing Z in TIME_FORMAT is a literal, not a timezone directive.
# Without TZ = UTC, Splunk assumes indexer-local time and skews _time.
TZ = UTC
# --- search-time (search head on the Splunk Cloud path) ---
KV_MODE = json
FIELDALIAS-user = actorEmail AS user
FIELDALIAS-src = ipAddress AS src
FIELDALIAS-object = resourceLabel AS object
FIELDALIAS-object_type = resourceType AS object_type
EVAL-app = "infracodebase"
$SPLUNK_HOME/bin/splunk add index infracodebase_audit -auth <user>:<pass>
$SPLUNK_HOME/bin/splunk restart
Splunk runs the input on startup, then every interval. Each run drains the entire backlog: it pages until hasMore=false and backs off on 429. The feed never falls behind, regardless of volume.
index=infracodebase_audit | head 5 | table _time action status user object src
Denied access attempts:
index=infracodebase_audit status=denied | table _time action user object src detail
The platform enforces these:
id.since.Limits: limit max 1000 per page, 100 requests/min/enterprise.
| Field | Splunk (after props) | Description |
|---|---|---|
timestamp | _time | Event time, ISO 8601 UTC |
action | action | What happened, e.g. member.invite |
status | status | success / failure / denied |
actorEmail | user | Who did it |
resourceType | object_type | Kind of resource affected |
resourceLabel | object | Human-readable resource name |
ipAddress | src | Source IP |
detail | detail | Human-readable summary |
id | Unique event ID (dedupe key) |
"$APPBIN/infracodebase_audit.sh"
rm "$APPBIN/.infracodebase_cursor"
interval.enterprise.audit.read and belongs to the enterprise in the URL. Denied attempts appear in your own audit log as audit.export.read with status=denied.enterprise.audit.read. The SIEM template does this.index=_internal source=*splunkd.log* "infracodebase_audit" ERROR plus an absence-of-events check.