SIEM Integration
IdentityMesh’s compliance and operational signals are designed to flow into a SIEM without code changes. This document maps every emitted surface to where your SIEM picks it up, with concrete ingest recipes for the common platforms and sample detection queries to start with.
If your SIEM isn’t listed below: it almost certainly has a file / Windows Event Log / OTLP / database connector that fits one of the patterns here. The IdentityMesh side is already producing the data — pick the surface that matches your SIEM’s strengths.
Emitted surfaces — the field map
1. Application log files
| Component | File path | Format |
|---|---|---|
| Admin API | <install dir>\logs\identitymesh-api-YYYYMMDD.log | Serilog rolling, daily, 30-day retain, JSON-friendly text template |
| Sync Engine | <install dir>\logs\identitymesh-YYYYMMDD.log | Same template |
| Relay Agent | <install dir>\logs\identitymesh-relay-YYYYMMDD.log | Same template |
Per-line shape (one example):
2026-04-25 11:32:18.421 +00:00 [INF] [12] {RequestId} {RequestPath} permission=connectors.write granted to alice@corp
The interesting fields enriched by Serilog scopes:
| Field | Meaning |
|---|---|
RequestId | ASP.NET Core trace identifier — pivots to/from IM_AdminAudit.CorrelationId |
ConnectionId | Kestrel connection |
RequestPath | Concrete URL |
RequestMethod | HTTP verb |
StatusCode | Final response status |
Elapsed | Request duration ms |
SourceContext | Logger category — identifies the producing component |
MachineName | Stamped via Enrich.WithMachineName() |
ThreadId | Stamped via Enrich.WithThreadId() |
CycleId, InstanceName | Sync engine — present on every line during a connector run |
To switch from the default text template to JSON for easier
SIEM parsing, swap the Console/File Serilog sink config:
"WriteTo": [
{
"Name": "File",
"Args": {
"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
"path": "logs/identitymesh-api-.log",
"rollingInterval": "Day",
"retainedFileCountLimit": 30
}
}
]
The Serilog.Formatting.Compact package already ships with
IdentityMesh; there is nothing to install.
2. Windows Event Log
Warning+ events are also written to the Windows Event Log on each
host, in a dedicated IdentityMesh log with one Source per component
(see event-log.md):
| Component | Event log | Source name |
|---|---|---|
| Admin API | IdentityMesh | IdentityMesh Admin API |
| Sync Engine | IdentityMesh | IdentityMesh Sync Engine |
| Relay Agent | IdentityMesh | IdentityMesh Relay Agent |
| Web UI | IdentityMesh | IdentityMesh Web UI |
| Connect | IdentityMesh | IdentityMesh Connect |
| Installer | IdentityMesh | IdentityMesh Installer |
The API, engine and relay agent write through Serilog.Sinks.EventLog
with restrictedToMinimumLevel: Warning, so the Event Log gets the
“something requires attention” subset, not every INFO line. The Web UI
source carries browser-side errors reported to the API. Connect writes
to the log only on workstations where an administrator registered its
source.
3. Audit tables (SQL)
Two append-only tables holding compliance-grade evidence. Either
poll directly via your SIEM’s database connector or proxy through
the REST endpoints (which are gated on audit.read).
IM_ObjectAudit — identity-data changes
| Column | Type | Meaning |
|---|---|---|
AuditId | bigint | Surrogate key, monotonic |
MeshObjectId | uniqueidentifier | Affected mesh object |
CSObjectId | uniqueidentifier | Management Space object id (or 00000000-… for changes not tied to a Management Space row) |
ChangeType | nvarchar(50) | Create / RefreshAttributes / Link / connector change types |
Source | nvarchar(200) | Connector name or JoinEngine for join-time mutations |
ChangeJson | nvarchar(max) | Mutation payload (object type, attributes, etc.) |
ChangedOn | datetime2 | UTC |
ActorUpn | nvarchar(256) | UPN (or instance name on engine-initiated rows) |
ActorSid | nvarchar(128) | Windows SID or Entra oid |
ActorSource | nvarchar(32) | Api / Engine / Relay / System |
REST equivalent: GET /api/audit?meshObjectId=…&since=…&take=…
(filtered) or GET /api/audit/by-object/{meshObjectId} (all
history for one object).
IM_AdminAudit — admin-surface mutations
| Column | Type | Meaning |
|---|---|---|
AuditId | bigint | Surrogate key |
WhenUtc | datetime2 | UTC |
ActorUpn | nvarchar(256) | UPN |
ActorSid | nvarchar(128) | Windows SID or Entra oid |
Action | nvarchar(200) | HTTP method + route template (e.g. POST /api/connectors) |
TargetKind | nvarchar(64) | Stable name of target type (Connector, Role, …) — populated for high-value mutations |
TargetId | nvarchar(128) | Specific id (GUID, role name) extracted from route values |
StatusCode | int | HTTP response status — denied 403s recorded too |
CorrelationId | nvarchar(128) | Pivots to/from log RequestId |
BeforeJson | nvarchar(max) | Pre-mutation snapshot for high-value handlers (sensitive fields scrubbed) |
AfterJson | nvarchar(max) | Post-mutation snapshot |
REST equivalent: GET /api/admin-audit with filters for
actorUpn, targetKind, targetId, sinceUtc, untilUtc,
paged via skip / take.
Indexes for SIEM polling:
IX_IM_AdminAudit_WhenUtc— descending, perfect for “give me the last N events since timestamp X.”IX_IM_AdminAudit_ActorUpn_WhenUtc— actor-scoped queries.IX_IM_AdminAudit_Target— incident triage (“everything that touched connector X yesterday”).
Retention is governed by license tier (see
audit-retention.md). Don’t size your SIEM
ingest assuming infinite back-history — a Standard-tier deployment
keeps 30 days, Enterprise keeps unlimited.
4. Metrics — OpenTelemetry
When Telemetry:Otlp:Enabled is true, both the Admin API and the
Sync Engine emit OTLP metrics + traces to the configured exporter.
Counters worth alerting on:
| Metric | Meter | What it tells you |
|---|---|---|
identitymesh.runs.failed | IdentityMesh.Engine | Sync run failures (with connector_type, outcome tags) |
identitymesh.exports.objects{outcome="Failed"} | same | Per-object export failures |
identitymesh.license.fallbacks | same | License → Starter trial fallback (reason tag) |
identitymesh.audit.purged | same | Retention sweep volume (per table tag) — sudden spike → investigate |
These flow to whatever your OTel Collector forwards them to — Datadog, Honeycomb, Grafana Cloud, Azure Monitor.
Per-SIEM ingestion recipes
Splunk
Pattern: Universal Forwarder → log files + Windows Event Log → HEC / indexers.
# inputs.conf on each IdentityMesh host
[monitor://C:\Program Files\IdentityMesh\logs\*.log]
sourcetype = identitymesh:json # if you flipped to CompactJsonFormatter
disabled = false
index = identitymesh
[monitor://C:\Program Files\IdentityMesh Relay Agent\logs\*.log]
sourcetype = identitymesh:relay
index = identitymesh
[WinEventLog://IdentityMesh]
disabled = false
index = identitymesh
For the audit tables: a dbx database connector polling
IM_AdminAudit filtered by WhenUtc > "@last_seen".
Microsoft Sentinel
Pattern: Azure Monitor Agent (AMA) → Data Collection Rule (DCR) → Log Analytics custom table.
- Install AMA on each IdentityMesh host (Admin API, Sync Engine, each Relay).
- Author a DCR pointing at
C:\Program Files\IdentityMesh\logs\*.log(file-based) and theIdentityMeshevent log (no source filter needed; the log holds only IdentityMesh events). - The audit tables flow via SQL data connector — Sentinel
workbook polls
IM_AdminAuditdirectly.
For direct ingestion without AMA, see
siem-sentinel.md.
Elastic / Logstash
Pattern: Filebeat → log files + Winlogbeat → Event Log → Logstash → Elasticsearch.
# filebeat.yml
filebeat.inputs:
- type: filestream
paths:
- C:\Program Files\IdentityMesh\logs\*.log
parsers:
- ndjson:
target: "" # if CompactJson formatter
add_error_key: true
fields:
app: identitymesh
component: admin-api
# winlogbeat.yml
winlogbeat.event_logs:
- name: IdentityMesh
Audit tables: standard JDBC input plugin polling IM_AdminAudit.
Datadog
Pattern: Datadog Agent on each host → log file + Windows Event Log integrations → Datadog.
# C:\ProgramData\Datadog\conf.d\identitymesh.d\conf.yaml
logs:
- type: file
path: C:\Program Files\IdentityMesh\logs\*.log
service: identitymesh-admin-api
source: csharp
- type: windows_event
channel_path: IdentityMesh
source: windows.event_log
service: identitymesh
Metrics flow via OTLP to the Datadog Agent if you’ve enabled the OTLP receiver. The audit tables ride a SQL Server integration.
Sample detection queries
Examples that work against IM_AdminAudit directly. Translate to
your SIEM’s query language as needed; the field names are stable.
-- "Privilege escalation" — role mutations grouped by actor
SELECT ActorUpn, COUNT(*) AS RoleEdits, MIN(WhenUtc) AS First, MAX(WhenUtc) AS Last
FROM dbo.IM_AdminAudit
WHERE WhenUtc > DATEADD(DAY, -7, SYSUTCDATETIME())
AND Action LIKE '%/api/roles/%'
GROUP BY ActorUpn
ORDER BY RoleEdits DESC;
-- "Connector deletes" — high-blast-radius operations
SELECT WhenUtc, ActorUpn, TargetId, StatusCode
FROM dbo.IM_AdminAudit
WHERE Action = 'DELETE /api/connectors/{id}'
ORDER BY WhenUtc DESC;
-- "Off-hours admin activity"
SELECT WhenUtc, ActorUpn, Action, TargetKind, TargetId
FROM dbo.IM_AdminAudit
WHERE Action LIKE '%/api/%'
AND Action NOT LIKE 'GET %'
AND (DATEPART(WEEKDAY, WhenUtc) IN (1, 7)
OR DATEPART(HOUR, WhenUtc) NOT BETWEEN 7 AND 19)
ORDER BY WhenUtc DESC;
-- "Denied admin attempts" — who tried and got blocked
SELECT WhenUtc, ActorUpn, Action, TargetId, StatusCode
FROM dbo.IM_AdminAudit
WHERE StatusCode IN (401, 403)
AND WhenUtc > DATEADD(DAY, -1, SYSUTCDATETIME())
ORDER BY WhenUtc DESC;
-- "License upload events" — every license rotation
SELECT WhenUtc, ActorUpn, StatusCode, CorrelationId
FROM dbo.IM_AdminAudit
WHERE Action = 'POST /api/license/upload'
ORDER BY WhenUtc DESC;
For IM_ObjectAudit (identity-data changes):
-- "Mass mesh-object deletion" — single actor / engine instance
-- removing more than 100 objects in 5 minutes.
SELECT ActorUpn, ActorSource, COUNT(*) AS Deletes,
MIN(ChangedOn) AS First, MAX(ChangedOn) AS Last
FROM dbo.IM_ObjectAudit
WHERE ChangeType = 'Delete'
AND ChangedOn > DATEADD(MINUTE, -5, SYSUTCDATETIME())
GROUP BY ActorUpn, ActorSource
HAVING COUNT(*) > 100;
Operational notes
- Time zones: every timestamp emitted by IdentityMesh is UTC. Your SIEM is responsible for any local-time presentation.
- Correlation across surfaces:
IM_AdminAudit.CorrelationIdmatches the SerilogRequestIdfor the same request. Searching for one in your log index will surface the other. - PII:
ActorUpnis identifying.IM_ObjectAudit.ChangeJsonmay contain mesh-attribute values that include PII (display names, emails, group memberships). If your SIEM ingest is cross-region, treat the audit feeds as personal data per your privacy policy. - Volume sizing: a 100k-mesh-object connector with hourly
syncs typically writes 50–200k
IM_ObjectAuditrows/day at steady state, dominated by attribute refreshes.IM_AdminAuditis operator-traffic-bound — usually a few hundred rows/day. - Log retention: in-DB audit retention is governed by
audit-retention.md. Log files retain 30 days by default. Configure your SIEM cold storage accordingly.
Related
audit-retention.md— how long the audit tables are kept.authentication.md— actor-claim shapes for theActorUpn/ActorSidcolumns under Negotiate vs JwtBearer.