SIEM Integration
Controlio's monitoring findings, security activity and administrative actions can be forwarded to your own security information and event management (SIEM) system. This page explains what the integration is, who can configure it, and which part of it is available today.
The SIEM data endpoint is live. You can set the connection up from the Integrations screen in the panel, take the address and the credential, and start reading from your own SIEM.
The integration is in pilot: the endpoint works, but field mapping on the QRadar side, re-reading after an outage and continuous delivery have not yet been verified end to end in a customer environment. The Microsoft Sentinel path was verified with a synthetic pilot and carries only test records today. We recommend setting the first connection up together and running the initial tests with our support team.
What is forwarded, and what is not
Three sources feed the export: monitoring findings, security activity, and administrative actions (monitoring being enabled or stopped, baseline and exception decisions). Raw Graph responses, full user lists, message bodies, tokens and whole configuration snapshots are not forwarded.
The limits are part of the contract and are stated inside each event:
| Field | Meaning |
|---|---|
status: "observed" | The event is the version of the record as observed. It is not a resolution state. |
completeLifecycle: false | The full lifecycle of a finding is not guaranteed; intermediate versions can be missed. |
captureMode | Audit records travel as stored; the others travel as the latest observed version. |
| Retention | The export journal holds 30 days. Anything older lives in your SIEM, not with us. |
severity | If the source states no severity, the value is unknown. We do not guess one. |
A re-delivery carries the same eventId; different versions of the same source record share a
correlationId. A bulk maintenance correction can produce new versions of the affected records,
which appear in your SIEM as new events under that same correlationId.
Writing your SIEM rules
status always being observed, and completeLifecycle staying false, have concrete
consequences for the rules you write:
- Do not use it as an open-alert counter. We do not report that a finding closed; "how many open deviations are there" is a question for the Controlio panel.
- Group on
correlationId. That field is bound to the record itself and is independent of its version.eventIdchanges with every version, so use it as the deduplication key: a re-delivered event arrives with the sameeventId. - Do not take deltas from counters.
evidence.occurrenceCount,firstAtandlastAtgive the latest observed state correctly, but the series can have gaps: if a record is updated twice between two reads, the version in between never becomes an event. Rules of the form "how many times did it rise in the last hour" will be wrong. - Keep the 30-day window in view. If your reader stops for more than 30 days, the records in
between drop out. You then get a
410, have to start a fresh read, and accept the skipped range.
Administrative actions are the exception: audit records travel as stored, each one a separate and immutable event.
Event names
Every event carries product: "controlio_ccm"; what the event is comes from eventType and
category. There is no separate prefix. On the QRadar side the log source is identified as
controlio-ccm-<tenant id>.
eventType | category | What it reports |
|---|---|---|
configuration.drift.observed | configuration | A deviation from the approved TrueState baseline |
configuration.change.observed | configuration | A configuration change observed while the baseline is not locked |
breakglass.activity.observed | identity | A sign-in or change on an emergency access account |
vip.identity.activity.observed | identity | Identity activity on a monitored VIP account (MFA method, device, password) |
vip.inbox.finding.observed | mailbox | A delegation or forwarding finding on a VIP mailbox |
entra.conditional_access.observed | identity | A Conditional Access policy change |
entra.group_membership.observed | identity | A membership change in a monitored group |
administration.action.recorded | administration | An administrative action inside Controlio (monitoring, baseline, exception, erasure) |
A record that cannot be classified is not given an invented name: it arrives as
finding.unclassified or security.unclassified with category: "unknown".
Address and endpoints
The base address is https://siem.controlio.ai. There are three endpoints, all GET, all
requiring a credential:
| Endpoint | For |
|---|---|
/api/v1/siem/health | Whether the connection is up, and when each source was last read |
/api/v1/siem/schema | The event schema itself (JSON Schema) and the export capabilities |
/api/v1/siem/events | The events. ?limit= defaults to 50, caps at 100; ?cursor= pages |
Calling without a credential, or with an invalid one, returns 401. That does not mean the endpoint is disabled; it means the credential was not accepted. An address that is not one of these three returns 404. Reads are limited to 120 requests per minute per client.
The wire format is JSON. For a SIEM that expects CEF or LEEF, the collector we publish reads this JSON and converts it to the format you choose; there is no per-product configuration on the Controlio side.
Two ways to authenticate
- Entra application — you register an application in your own tenant and consent to the
Siem.Events.Readpermission; your SIEM obtains a token over OAuth 2.0. This is the preferred path in an enterprise tenant. - Controlio API key — if you cannot register an application in Entra, you generate a key from
the panel. The key has the form
ccmsiem.<tenant id>.<secret>and is shown once: we keep only its SHA-256 digest. If you lose it we cannot show it again; you generate a new one.
Whichever you choose, the address, the schema and the way you read are the same.
Who can configure it
Only an active Global Administrator or Security Administrator of your own tenant can configure the connection. Global Readers, Security Readers and ordinary users cannot. The role is resolved live on every request: being eligible in PIM is not enough, the role has to be active.
If monitoring has stopped for your tenant — licence expired, access revoked, or monitoring turned off — the SIEM endpoint stops serving data as well.
Where it lives in the panel
Integrations sits in the left menu immediately above Settings, and offers three choices:
- IBM QRadar — reading events over the REST API; the screen gives you the values to paste into the QRadar workflow parameters, under exactly those names
- Microsoft Sentinel — Azure Logs Ingestion (pilot)
- Other SIEM products — address, key and format. The product does not matter; this is also where you generate the API key
Choosing a product does not create a separate permission list. The Controlio API access list is shared across all SIEM clients: seeing a client registered while looking at QRadar does not mean Sentinel is connected, and revoking access here affects every registered client.
Each client registration carries an expiry (at most one year), and at most five clients can be defined. An expired client is refused automatically; renewing means updating the registration.
Identity fields
Events carry identity information only for the people involved in that event: the object
identifier (GUID), display name, user principal name and mail address. The stable key is
tenantId + objectId — names, UPNs and mail addresses change over time, so correlation has to be
built on the GUID. A UPN is not assumed to equal a mail address.
Your tenant's full user list is never exported or stored. An identity that cannot be resolved does
not get an invented name: the field stays empty and identityStatus says so. It takes six values:
resolved (the name was resolved), not_found (the identity is not in the directory),
unavailable (resolution was attempted, no answer), not_resolved (a GUID is present, the name
has not been resolved yet), not_recorded (the source record holds no identity) and
source_recorded (the label is written in the source record, with no record of when it was
resolved). identityObservedAt records when the name was resolved, and does not
claim that the name was in use at the time of the event.
Tenant separation
Every request rests on a verified credential, and the tenant is taken from it: from the application token on the Entra path, from the key itself on the key path. The key states its tenant openly, but that alone grants nothing — nothing is read until the key's secret matches the stored digest, and whether a tenant is monitored at all is only asked after that check. Sending a tenant identifier in the body or the URL grants nothing. The paging cursor is likewise bound to the tenant, the client and the connection version, and cannot be used to reach another tenant's data.
If the connection is revoked or the tenant's data is erased, a read already in progress is stopped as well.
Troubleshooting
| Status | Meaning | What to do |
|---|---|---|
| 401 | The credential was not accepted: the token is invalid or expired, or the key is wrong | Renew the credential. This does not mean the endpoint is disabled |
| 403 | The client is not authorised, has expired, or monitoring has stopped for the tenant | Check the registration expiry and your monitoring status |
| 404 | The address is not one of the three endpoints | Compare it against /api/v1/siem/events, /api/v1/siem/health, /api/v1/siem/schema |
| 429 | The per-minute read limit (120 requests per client) was exceeded | Honour the Retry-After delay in the response and try again |
| 410 | The cursor expired, or records in between fell out of the 30-day window | Start a fresh read and accept the skipped range |
| 412 / 428 | The configuration version is stale or was not supplied | Refresh the screen and save the change again |
Seeing "Configured" does not mean data reached your SIEM. An HTTP 200 or 204 only means the
request was accepted. Real verification is finding an event on the SIEM side by its eventId and
tenantId.
Turning the connection off
Turning the connection off in the Integrations screen stops further reads. Events already delivered to your SIEM remain in your system under your own retention policy; Controlio cannot recall them.