Splunk HEC: CEF ingest from MaestroHub
Bring MaestroHub audit events into Splunk as CEF, parsed by Splunk's built-in CEF extractor with no custom parser.
- Where
- Admin › Identity & Access › API Clients
- Scope
- audit_log:export
- Role
- One that exports the audit trail
- Sourcetype
- cef
- Poll interval
- 60 seconds
Poll /audit/export from Splunk's HTTP Event Collector or the Modular HTTP Input. Records arrive as CEF and land in your existing CEF sourcetype without a custom parser.
1. Create an OAuth2 client for the collector
In MaestroHub:
- Admin → Identity & Access → API Clients → Register Application, as a Confidential Client.
- Grant type: Client Credentials.
- Scopes:
audit_log:export(nothing else: the SIEM collector is a machine and needs nothing else). - Access: give the client a role that can export the audit trail. The scope alone is not enough: a new client has no access until it holds a role, and its requests are refused until then. In release 3.0 give it Workspace Administrator; with only the
audit_log:exportscope the client can still use nothing but the export. See the three things every setup needs for the choice of role. You can also add the role later under Roles on the client's page. - Copy the client ID and client secret. Store the secret in Splunk's credential vault.
2. Fetch an access token
curl -s -X POST https://<your-maestro>/api/v1/oauth2/token \
-d grant_type=client_credentials \
-d client_id=$MAESTRO_CLIENT_ID \
-d client_secret=$MAESTRO_CLIENT_SECRET \
-d scope=audit_log:export \
| jq -r .access_token
Splunk's HEC integrations refresh the token on their own cadence. See Splunk docs: Modular Input token refresh for the reference config.
3. Configure the modular HTTP input
inputs.conf:
[maestrohub_audit://main]
endpoint = https://<your-maestro>/api/v1/audit/export
params = format=cef&from=${last_cursor_timestamp}&to=now&cursor=${last_cursor}&limit=1000
method = GET
auth_type = bearer
token = ${maestrohub_access_token}
interval = 60
sourcetype = cef
index = security_audit
${last_cursor} is Splunk's checkpoint variable: the modular input persists it across polls. On the first poll, it's empty; subsequent polls send the previous response's X-Audit-Next-Cursor.
4. Set the sourcetype extractor
props.conf:
[cef]
SHOULD_LINEMERGE = false
LINE_BREAKER = ([\r\n]+)CEF:
TRUNCATE = 10000
KV_MODE = auto
Splunk's out-of-the-box CEF extractor handles the header + extension parsing. The KV_MODE=auto line applies to the extension section.
5. Validate
Search:
sourcetype=cef | head 20
You should see recent audit events with signature=<action>, suser=<actor>, duser=<subject>, cs1=<correlation_id>, cs2=<workspace_id>, cat=iam|authentication|configuration.
Field reference
| CEF field | Maestro source | Note |
|---|---|---|
act | Action | e.g. role.assigned |
suser | Actor.Email (falls back to Actor.ID) | The actor identity |
duser | Subject | The user acted upon |
src | Actor.IPAddress | Origin IP |
requestClientApplication | Actor.UserAgent | Truncated at 1024 chars |
cat | Category | ECS-aligned: iam, authentication, configuration, process |
outcome | Result | success · failure · denied |
cs1 (label correlationId) | CorrelationID | OpenTelemetry trace id |
cs2 (label workspaceId) | WorkspaceID | Workspace ID, the pivot across workspaces |
cs3 (label impersonator) | ImpersonatorID | When set: admin impersonating a user |
cs4 (label resource) | ResourceType/ResourceID | The resource operated on |
Troubleshooting
Splunk shows cef events but the extractor didn't split fields.
Check props.conf: the extractor stanza name must match the sourcetype in inputs.conf (both cef).
429 in Splunk's modular-input log.
The collector polled faster than the rate limit. Extend interval to 60 (from a lower value) and, for large windows, set limit=1000 explicitly.
Response body is empty but X-Audit-Records-Exported: 0.
No records in the requested window. The endpoint response is well-formed; this just means the poll caught an empty window. Splunk skips the batch and re-polls on the next interval.
Bearer token returned 401. The access token expired. Splunk's HEC refresh cycle is typically 30 minutes; check that the token-refresh script is running.