Microsoft Sentinel — Integration Setup
Note: This guide covers Microsoft Sentinel, Microsoft's cloud SIEM. It is unrelated to SentinelOne, the EDR vendor — if you're looking for that integration, see integration-setup-sentinelone.md instead.
Prerequisites
- A Microsoft Sentinel workspace connected to Microsoft 365 Defender's unified security operations (so its incidents surface through Microsoft Graph)
- An administrator who can grant Microsoft Graph admin consent (and, self-hosted, register an Azure AD app)
- CMDash Essentials tier or above
How CMDash connects
Sentinel uses CMDash's Microsoft app registration with application permissions and an app-only token (the client-credentials grant) — no signed-in user, no refresh token. Which directory is read depends on how the deployment runs its Microsoft integrations; see How CMDash connects to Microsoft.
- CMDash SaaS (per directory): available once CMDash's Microsoft apps are registered. Until then Connect answers that the Microsoft app registration is not set up on this deployment. Once it is, Integrations → Microsoft Sentinel → Connect, fill in the workspace fields, sign in as an active Global Administrator or Privileged Role Administrator and accept the permissions for your organisation; the connection is bound to your directory. Commercial cloud only for now (not GCC High or DoD). What CMDash checks and records is described once, in the Entra ID guide.
- Self-hosted (single directory): Steps 1–4 below.
Step 1 (self-hosted): Register an Azure AD App
- Go to Azure Portal → App registrations.
- Click New registration.
- Name:
CMDash Integration. - Supported account types: Single tenant.
- Redirect URI: leave blank — a single-directory connection has no sign-in step.
- Click Register, then copy the Application (client) ID and Directory (tenant) ID.
Step 2 (self-hosted): Grant Microsoft Graph Security Permissions
- In the app registration, go to API permissions → Add a permission → Microsoft Graph → Application permissions.
- Add SecurityIncident.Read.All.
- Click Grant admin consent for [your org].
Step 3 (self-hosted): Create a Client Secret
- Go to Certificates & secrets → New client secret.
- Description:
CMDash. Expiry: 24 months (set a calendar reminder to rotate). - Copy the Value immediately — it will not be shown again.
Step 4 (self-hosted): Configure the deployment, then connect
The tenant id, client id and secret are server settings, not fields in the connect dialog.
- Set
AZURE_TENANT_ID,AZURE_CLIENT_IDandAZURE_CLIENT_SECRETin the API's environment (leaveAZURE_MULTI_TENANTunset) and restart the API. - In CMDash, navigate to Integrations, find Microsoft Sentinel and click Connect.
- Fill in the Log Analytics workspace Sentinel runs on — Subscription ID, Resource group, Workspace name. They are used for detection-rule coverage (Sentinel analytics rules, read from Azure Resource Manager); incidents come from Microsoft Graph and do not depend on them. Reading analytics rules additionally needs an Azure Resource Manager token, which this connection does not request yet, so that step is currently skipped rather than failing the sync.
- Click Save & Test Connection.
What Syncs
| Data Type | API | Sync Frequency |
|---|---|---|
| Incidents | GET https://graph.microsoft.com/v1.0/security/incidents | Every 4 hours by default (configurable per connection) |
CMDash pulls Sentinel incidents through the Microsoft Graph Security API's unified incidents queue (not Sentinel's own Log Analytics workspace API directly), sorted newest-first and paginated via @odata.nextLink, capped at 2,000 incidents per sync. This means incidents only appear here if your Sentinel workspace is connected to Microsoft 365 Defender's unified security operations platform — a standalone Sentinel workspace not linked into that unified queue will show no data.
Note: Today this adapter syncs incident-level records only. It does not call the separate alert-level Graph endpoint (
/security/alerts_v2), so individual alerts underlying an incident are not surfaced as their own CMDash records — only the rolled-up incident.
Troubleshooting
- 401 Unauthorized: Self-hosted: the client secret behind
AZURE_CLIENT_SECRETexpired, or admin consent forSecurityIncident.Read.Allwas never granted. SaaS: the CMDash app was removed from your directory — reconnect. - 403 Forbidden: The app registration lacks the
SecurityIncident.Read.Allapplication permission, or consent wasn't granted at the tenant level. - No incidents even though Sentinel shows activity: Confirm your Sentinel workspace is onboarded to Microsoft 365 Defender's unified incident experience — Graph's
/security/incidentsendpoint only surfaces incidents from workspaces connected that way. - Connection shows UNHEALTHY: The health check queries
/security/incidents?$top=1; a persistent failure usually means the secret expired or consent was revoked.
Rate Limits & Sync Behavior
| Setting | Value |
|---|---|
| Sync frequency | Every 4 hours by default (syncInterval is configurable per connection) |
| Pagination cap | 2,000 incidents per sync |
| Rate limit handling | Every outbound request is paced through CMDash's shared per-tenant token bucket for this provider, and a vendor 429 (with its Retry-After) holds that tenant's budget until the vendor says it is ready (#507) |
| Failed sync retry | Job queue retries 3 times with exponential backoff (starting at 30s) — see docs/developers/dead-letter.md |
Credential Rotation
- CMDash SaaS: there is nothing on your side to rotate; CMDash rotates its own app's secret.
- Self-hosted: Azure AD client secrets expire (max 24 months). The secret is a server setting (
AZURE_CLIENT_SECRET), shared by every CMDash Microsoft integration, and CMDash does not warn before it expires — keep a calendar reminder.
To rotate before expiry (self-hosted):
- Go to App registrations → CMDash Integration → Certificates & secrets → New client secret.
- Copy the new Value immediately.
- Update
AZURE_CLIENT_SECRETin the API's environment and restart the API. - Delete the old secret in Azure once a sync succeeds.
Multiple Instances / Multi-Site
A CMDash workspace holds one Sentinel connection, bound to one directory. If you run Sentinel in more than one Azure AD tenant (a production tenant and a subsidiary's, say), each needs its own CMDash workspace: on CMDash SaaS each workspace connects its own directory; a single-directory self-hosted install reads only AZURE_TENANT_ID, so a second directory needs the per-directory mode (AZURE_MULTI_TENANT=true, see the Entra ID guide) or its own deployment.
Compliance Framework Coverage
The Microsoft Sentinel integration provides evidence for the following controls. Coverage is automatically mapped when data is synced.
| Framework | Control | Description |
|---|---|---|
| PCI DSS | 10.2 | Event log monitoring — Sentinel incidents mapped to log review evidence |
| PCI DSS | 12.10 | Incident response — Sentinel incident lifecycle data |
| HITRUST | 09.ab | Monitoring system use — SIEM incident telemetry |
| CMMC L2 | IR.2.093 | Incident handling — Sentinel incidents mapped to incident tracking evidence |
| SOC 2 | CC7.1 | Threat detection — Sentinel incidents feed the threat-detection evidence bucket |