SIEM providers
Operator runbook for sending IdentityMesh audit events to your SIEM. You choose where events go in the portal, under Settings → SIEM Integrations. Each destination is a provider with a name you pick, the same way you pick a provider for email or secrets. The product reads events from its own audit record, hands them to each provider in order, and proves what was delivered.
This page covers the model, the delivery guarantees, the shape of
every event and the switches that limit what leaves the product. The
destination-specific pages follow from it: siem-splunk.md for Splunk, siem-webhook.md for HTTPS, siem-syslog.md for syslog and siem-cef-leef.md for the CEF and LEEF formats.
How it works
The SIEM Integrations tab is under Console → Settings. Viewing
it needs the roles.read permission. Adding, changing, testing and
deleting providers need roles.write.
- Providers are chosen by name. Settings → SIEM Integrations lists every provider with its kind, whether it is enabled, its last delivery, its backlog and its last error. Add a provider, pick a kind, fill in its settings and save.
- One provider is the default. Every stream goes to the default provider unless you switch that stream or kind off on it. Other providers receive only what their own switches allow.
- The Windows event log provider is always there. A fresh install
already has a provider named Windows event log. It writes each
event as an Information entry in the
IdentityMeshlog, under the sourceIdentityMesh SIEM, and it is the default until you change that. A Universal Forwarder or Windows Event Forwarding can collect it with no further setup. You can disable it, but you cannot delete it. The installer registers theIdentityMesh SIEMsource. If the provider’s last error says the source is not registered, run Repair on the IdentityMesh installer. - Test uses the real send path and the saved settings. Save the provider first, then press Test. It sends one sample event through exactly the code that sends real events, with the settings and token as saved, not any unsaved edits on the card. A green result means the destination accepted a real send. A new provider can be tested once it is saved.
- Secrets are write-only. Tokens are stored in the configured
secret provider, shown masked, and never returned by the portal. See
secrets-and-dpapi.md. - Changes apply without a restart. Saving a provider takes effect on the next delivery pass. Every change is itself recorded in the admin audit.
Delivery guarantees
| Guarantee | What it means for you |
|---|---|
| Events come from the audit record | Each event is built from a row in the hash-chained audit tables (or from a finished run), after that row is committed. Nothing is built from log lines, so nothing depends on a log level or a text filter. |
| At-least-once, with acknowledgement | A provider’s position moves forward only after the destination accepted the batch. A failed or unanswered send is retried from the same position. A receiver can therefore see an event twice, and must tolerate that. |
| A sequence number on every event | Each provider counts its own events 1, 2, 3 and so on, separately for each stream. A retried batch is sent again with the same numbers. A gap in the sequence proves an event was lost on the way. A gap in the audit table’s own row numbers does not, because a rolled-back write leaves a hole there. |
| Delivery you can see | The Operations page shows, per enabled provider, the backlog, the last delivery, the last error and a Stalled flag. |
| A warning when delivery stalls | When a provider has a backlog and has delivered nothing for 30 minutes, it is marked Stalled and the IdentityMesh event log gets one warning. The default window can be changed by your support contact. |
| Retention waits for delivery | The audit retention sweep never removes an admin, object or group audit entry, or a run history row, that an enabled provider has not delivered yet. Workflow run retention is not held back by delivery. See audit-retention.md. |
Retry and parking
The dispatcher runs every 15 seconds, one provider and stream at a time, and two Admin API instances never send the same batch.
- Accepted. The destination took the batch. The position and the sequence move forward together.
- Retry. A timeout, a network error, HTTP 408, 429 or any 5xx. The
provider backs off, waiting two minutes, then four, eight and so on,
up to one hour, then tries the same batch again, with the same
sequence numbers. When the destination names its own wait
(
Retry-After), that wait is used, up to one hour. A retry also ends that provider’s turn in the pass: its other streams wait for the next pass, so a destination in trouble is not asked again straight away and the providers after it are not held up. - Rejected. Any other 4xx, which means the destination understood the request and refused it, usually because of a wrong token or URL. The provider is parked: nothing is skipped, the last error shows the reason, and nothing is sent until you correct the setting and save the provider, which resumes delivery.
A provider also gives up its turn once it has spent about a minute sending in one pass, for example while a Splunk indexer is slow to acknowledge. Whatever it did not send goes on the next pass.
Run and workflow events are delivered about two minutes after the run ends. That pause lets every engine and API instance finish writing its runs, so a run recorded a moment late is not passed over. Installs with more than one engine or Admin API instance must keep those servers’ clocks in sync with NTP: the run and workflow times come from the server that wrote them, and a clock that runs more than about two minutes behind the others can still cause a run event to be missed.
The dispatch interval is set by Siem:DispatchSeconds in the Admin API
configuration (default 15). Setting it to 0 switches delivery off. Do
that only with every provider switched off as well: because retention
waits for delivery, an enabled provider that is never sent to stops
the audit tables being trimmed. See audit-retention.md.
UDP syslog cannot be acknowledged. A UDP provider counts every send as accepted, so its sequence numbers are still stamped, and a gap at the receiver still shows loss, but the product cannot retry what the network dropped. Use TCP or TLS where the evidence matters.
Streams and kinds
An event belongs to one stream and has one kind within it. On a provider’s card in Settings → SIEM Integrations, each stream has an Event kinds list that names its kinds, marks the ones that carry personal data, and lets you switch kinds off one by one. The severity of each kind is in Severity below.
| Stream | Source | Kind is | Carries personal data |
|---|---|---|---|
admin | Admin audit | The action, such as POST /api/connectors | Yes: the administrator’s identity; snapshots only when attribute values are switched on |
object | Object audit | The change type, such as Add, Update, Delete | Yes, when attribute values are switched on; otherwise attribute names only |
vault | Vault audit | The event type, such as Checkout | Yes: user name and IP address; justification and reason only when free text is switched on |
group | Group audit | The event type, such as MemberAdded | Yes: the acting, target and approving users and the IP address |
run | Finished sync runs | The final status, such as Success or Failed | The error text only when free text is switched on |
workflow | Finished workflow runs | The final status, such as Completed or Failed | The last error only when free text is switched on |
Kinds per stream
- admin. Every audited administrator call, one per call, named by
method and route (
POST /api/connectors,PUT /api/roles/{roleName}/permissions). Refused calls are included with an outcome ofdenied. Named actions are included too:ErasureRequest,AuditChainResealed,SYSTEM secrets/deliver,EmailSettingsChanged,EmailSecretCleared,EmailProviderTested,AiSettingsChanged,AiKeySet,AiKeyCleared,AiProviderTested,AiAgreementAccepted,AiAgreementWithdrawn,AiRuleSuggestionsRequested,AiSuggestionAccepted,AiExplainRequested,AiMimTranslationRequested,MimTranslationAcceptedandAiFeedback. - object.
Add,Update,Delete,Create,RefreshAttributes,Link,Export,WorkflowSetAttributes,WorkflowUpdateObjects,WorkflowRetireObject,Isolate,Release,Disconnect,HoldCreatedandHoldReleased. This is the highest-volume stream. - vault.
Request,Approve,Deny,Cancel,Checkout,Checkin,Expire,CredentialView,CredentialTokenIssued,CredentialTokenConsumed,RotationSucceeded,RotationFailed,ForcedRotation,PolicyCreated,PolicyUpdated,PolicyDeleted,AccountNominated,AccountStatusChanged,AccountArchived,AccountDeleted,SourceMissing,SourceReappeared,ScopeCreated,ScopeUpdated,ScopeDeleted,ScopeAccountAdded,ScopeAccountRemoved,ScopeGroupAdded,ScopeGroupRemoved,CheckoutRefusedByScope,VaultTargetAdded,VaultTargetRemovedandVaultConnectRequested. - group.
GroupCreated,GroupCreateFailed,GroupUpdated,GroupDeleted,GroupRestored,GroupRenewed,GroupActivated,GroupExpired,GroupPurged,GroupOnboarded,GroupOnboardFailed,GroupReleased,OwnerAdded,OwnerRemoved,OwnerEscalated,OwnerRequired,MemberAdded,MemberRemoved,MemberLeft,RequestSubmitted,RequestApproved,RequestDenied,RequestCancelled,PolicyUpdated,ExpiryWarnedandProvisioningErrorNotified. - run. One event when a sync run reaches a status:
Success,Failed,Interrupted,Cancelled,PausedorContinuing. - workflow. One event when a workflow run finishes:
Completed,Failed,Cancelled,Skipped,RejectedorTimedOut.
A kind written by a newer component than the one sending is still delivered, at severity 5 and flagged as personal data.
The event
Every event, in every stream and in every format, carries the same
envelope. JSON is the reference form. CEF and LEEF are renderings of
it, described in siem-cef-leef.md.
{
"product": "IdentityMesh",
"component": "AdminApi",
"instance": "im-api-01",
"provider": "Corporate SIEM",
"seq": 12345,
"stream": "admin",
"sourceId": "88213",
"kind": "POST /api/connectors",
"severity": 3,
"eventTimeUtc": "2026-11-02T09:14:07.421Z",
"readTimeUtc": "2026-11-02T09:14:22.031Z",
"actor": { "upn": "alice@corp.example", "sid": "S-1-5-21-...", "source": "Api", "ip": null },
"subject": { "kind": "Connector", "id": "8e6b8c44-...", "type": null },
"outcome": "success",
"correlationId": "0HMV-...",
"rowHash": "9f2c...",
"previousRowHash": "41ab...",
"detail": { "statusCode": 201 },
"tags": { "env": "prod" }
}
| Field | Meaning |
|---|---|
product | Always IdentityMesh. |
component | The part of the product that wrote the entry: AdminApi, SyncEngine, Relay or System. |
instance | The machine that built the event. |
provider | The name of the provider that sent it, so one receiver can tell several providers apart. |
seq | The provider’s own counter for this stream, increasing by one for every event delivered. See Using the sequence. |
stream | admin, object, vault, group, run or workflow. |
sourceId | The audit row number, or the run id for the run and workflow streams. Stable for the life of the event. |
kind | The action, change type, event type or status. |
severity | 0 to 10, set by the kind. |
eventTimeUtc | When the entry was recorded. For the run and workflow streams, when the run finished, or started if it has no end. |
readTimeUtc | When the dispatcher read the entry to send it. One value per batch. |
actor | Who did it: upn (user name), sid, source (Api, Engine, Relay or System) and ip (vault and group events only). Fields that do not apply are null. |
subject | What it was done to: kind, id and type. See the per-stream tables. |
outcome | success, denied, failed or unknown. |
correlationId | Pivots to the same value on the request in the API log and in the audit table. Empty on object, run and workflow events. |
rowHash | The audit row’s hash. Empty on rows written before the hash chain existed, and on the run and workflow streams. See audit-chain.md. |
previousRowHash | The hash of the row before it in the chain, for independent verification. |
detail | Fields specific to the stream. See below. |
tags | The labels you set on the provider. Present only when you set some, and carried by JSON only. |
Two clocks, both UTC
eventTimeUtc is when the entry was recorded. Where a writer had to
wait for the audit chain, the recorded time is never earlier than the
entry before it, so it can sit a moment after the change itself.
readTimeUtc is when IdentityMesh read the entry to send it. The gap
between the two is your delivery delay. Every time is UTC. In JSON,
times use the default format, so trailing zeros in the fractional
seconds are trimmed. CEF and LEEF times are described in siem-cef-leef.md.
Severity
Severity is fixed by the kind and runs from 0 to 10. The table below gives it by kind:
| Severity | Events |
|---|---|
| 1 | Object add, update, create, refresh, link and export; successful or continuing sync run; completed or skipped workflow run; group expiry warning |
| 3 | Admin endpoint call and named admin actions; workflow object changes; object isolate and release; group update, owner, member and request events; vault cancel, expire and rotation succeeded; cancelled or paused sync run; cancelled or rejected workflow run |
| 4 | Object delete and disconnect; group create, delete, restore, expire and purge, and group failures |
| 5 | Vault request, approve, deny, check-out, check-in, account nomination, status and archive, and remote target events |
| 6 | Audit chain reseal; vault account deletion; group and vault policy changes and vault scope changes; forced rotation; failed or interrupted sync run; failed or timed out workflow run |
| 7 | Admin call refused (401 or 403); vault credential view, credential token events, scope refusals and remote connections |
| 8 | Erasure request; a successful erase or subject access request call; vault rotation failed |
Field reference per stream
The actor, outcome, correlationId and hash fields above come from
the audit row. The subject and detail members are as follows. Where
a switch is named, the member is absent unless the switch is on for the
provider. Members with no value are left out.
admin
| Member | Meaning |
|---|---|
subject.kind, subject.id | The target type and id, when the handler names one. For an erasure, MeshObject and the internal object id. |
detail.statusCode | The HTTP result of the call. |
detail.before, detail.after | Snapshots before and after a high-value change, with sensitive fields already removed. Attribute values switch. Each side is capped at 16 KB: a larger snapshot keeps the top-level fields that fit, and one that is not a set of fields is left out. |
detail.detailTruncated | true when the cap left something out. Present with the snapshots. The full snapshot stays in the audit record. |
The outcome is denied for 401 and 403, success for 2xx and 3xx, and
failed for other 4xx and 5xx. An erasure event has no snapshots. Its
detail holds counts only. A call to a route that names the person, such
as the erase and subject access request calls, is treated the same way:
it has no subject id, no snapshots even when attribute values are on,
and a detail of counts only.
object
| Member | Meaning |
|---|---|
subject.kind, subject.id, subject.type | MeshObject, the mesh object id and the object type. |
detail.source | The connector, or the component, that caused the change. |
detail.msObjectId | The management space object. |
detail.connectorId | The connector, when the change names one. |
detail.changedAttributes | A list of attribute names, capped at 200. Always present. |
detail.changedAttributeCount | How many attributes changed in total. |
detail.changedAttributesTruncated | true when the cap cut the list. The full change stays in the audit record. |
detail.externalId | The object’s id in the connected system. Attribute values switch. |
detail.attributeValues | The current value of each changed attribute, capped at 200 entries. Attribute values switch. Secret attributes are always shown as redacted. |
vault
| Member | Meaning |
|---|---|
subject.kind, subject.id | VaultedAccount and the account id, or VaultPolicy and the policy id for policy events. |
detail.requestId, detail.checkoutSessionId, detail.policyId | The records the event concerns, when there are any. |
other detail members | Whatever the event recorded, such as a failure code, up to 16 KB in all. |
detail.justification, detail.reason | The requester’s justification and the decision reason. Free text switch. |
detail.detailTruncated | true when the 16 KB cap left some recorded members out. The full entry stays in the audit record. |
Credentials are never part of a vault event. The outcome is denied for
Deny and CheckoutRefusedByScope, failed for RotationFailed, and
success otherwise.
group
| Member | Meaning |
|---|---|
subject.kind, subject.id | Group and the group’s mesh object id. |
detail.targetUsername, detail.targetMeshObjectId | The member or owner affected. |
detail.approverUsername, detail.requestId | The approver and the request, for request events. |
detail.before, detail.after | Snapshots of the changed fields. Attribute values switch. Capped at 16 KB per side, as for admin events. |
detail.detailTruncated | true when the cap left something out. Present with the snapshots. |
The outcome is failed for GroupCreateFailed and GroupOnboardFailed,
denied for RequestDenied, and success otherwise.
run
| Member | Meaning |
|---|---|
subject.kind, subject.id, subject.type | Connector, the connector id and the run type. |
detail.runType | The kind of run. |
detail.startTimeUtc, detail.endTimeUtc | When the run started and ended. |
detail.addedCount, detail.updatedCount, detail.deletedCount | What the run changed. |
detail.totalCount, detail.processedCount | How many objects the run expected and handled. |
detail.instanceName | The engine instance that ran it. |
detail.errorMessage | The failure text. Free text switch. |
workflow
| Member | Meaning |
|---|---|
subject.kind, subject.id, subject.type | Workflow, the workflow id and the trigger kind. |
detail.workflowName, detail.workflowVersion | Which workflow and version. |
detail.triggerKind, detail.attempt | What started the run and which attempt this was. |
detail.currentStep, detail.depth | The step it reached and its nesting depth. |
detail.meshObjectId, detail.groupMeshObjectId, detail.direction | The object or group it ran for, and the direction, where there is one. |
detail.startedUtc | When the run started. |
detail.lastError | The last error. Free text switch. |
Limiting what leaves the product
Each provider has its own switches, under its card in Settings → SIEM Integrations.
- Streams on or off. A stream that is off on a provider sends nothing to it.
- Kinds on or off, per stream. Tick off the kinds you do not want. Switching off the object kinds you do not need is the most effective way to cut volume.
- Include attribute values. Off by default. Object events then list which attributes changed and nothing else. Switching it on adds the attribute values and the external id to object events, and the before and after snapshots to admin and group events. Switch it on only for a destination you are cleared to send personal data to. Secret attributes stay redacted either way.
- Include free text. Off by default. It adds the vault justification and decision reason, the run error message and the workflow last error.
- Erasure. An erasure event, and a call to an erase or subject access request route, never carries the identifier of the person concerned. An erasure event’s subject is the internal object id, and its detail holds counts only. Notification text is never an event.
A switched-off stream or kind does not hold back delivery of the others, and it does not hold back audit retention: retention waits only for streams a provider actually has switched on.
Provider kinds
| Kind | Where events go | Settings | Acknowledged |
|---|---|---|---|
| Windows event log | The IdentityMesh log on the API host, source IdentityMesh SIEM, one entry per event with the JSON as its message | None | Yes, once the entry is written |
| HTTPS collector | Any HTTPS endpoint. See siem-webhook.md | Collector URL, Allow plain HTTP, Format (JSON, CEF or LEEF), Auth header name, Auth header value, Batch size, Tags (JSON only) | Yes, on a 2xx answer |
| Syslog | A syslog collector over UDP, TCP or TLS. See siem-syslog.md | Host, Port, Protocol, Format, Tags (JSON only) | TCP and TLS yes; UDP no |
| Splunk HEC | Splunk HTTP Event Collector on Splunk Enterprise or Splunk Cloud. See siem-splunk.md | HEC URL, HEC token, Index, Source, Source type, Source type per stream, Use indexer acknowledgement, Channel, Batch size, Max content bytes, Skip certificate validation, Tags | Yes, on a 2xx answer; with indexer acknowledgement, once Splunk confirms the batch is indexed |
Datadog log forwarding is separate and unchanged. It forwards log lines, not the audit record.
Using the sequence
The sequence is how a receiver proves nothing is missing.
- Key every event on provider name, stream and
seq. That key is unique and never reused: each stream has its own count, and a resend after a retry carries the numbers it had the first time. - Drop an event whose key you have already stored. Retries make duplicates normal.
- Alert when a stream’s next
seqis not the last one plus one. A gap means an event never arrived. A repeat means a retry.
Upgrading from the old webhook and syslog settings
On the first start after the upgrade, IdentityMesh creates the Windows event log provider, makes it the default and then converts what was configured before:
- An enabled webhook becomes an HTTPS collector provider named Webhook (migrated), and its token is copied to the secret store.
- Enabled syslog forwarding becomes a Syslog provider named Syslog (migrated).
- Datadog is not touched.
The conversion reads the webhook and syslog settings saved through the portal first, and the values in the Admin API configuration only where the portal saved none. If an enabled webhook had no URL, or had an auth header name but no token, or enabled syslog had no host, the provider is created switched off, and the IdentityMesh event log gets a warning saying what to fill in. Fill it in on the provider’s card, switch it on and save.
The old settings stay where they were, but after the conversion nothing reads them. Check the new providers in Settings → SIEM Integrations, press Test on each, and remove the old settings when you are satisfied.
The providers the upgrade creates start at the current end of each stream: they deliver what happens from the upgrade on, not the entries already in the database. To send the history that is still retained, add a provider yourself under Settings → SIEM Integrations. A provider you add starts from the oldest retained entry, so expect that backlog to arrive at it.
Related
siem-integration.md: the wider field map, including pulling the audit tables yourself.audit-chain.md: howrowHashandpreviousRowHashlet you verify an event independently.audit-retention.md: the delivery guard on retention.event-log.md: theIdentityMeshlog that the default provider and the stall warning write to.