Overview
Microsoft Sentinel is Azure's cloud-native SIEM and SOAR platform. Raw data connectors alone are not enough — you need analytics rules to surface threats, automation rules to route and enrich incidents, and playbooks (Logic Apps) to trigger automated response actions.
As of March 2026, Microsoft deprecated the ability to invoke playbooks directly from analytics rules. All playbook invocations must now go through automation rules. This guide covers the full pipeline from detection to response, including migrating any legacy alert-trigger playbooks.
What You Will Learn:
- Scheduled and Near-Real-Time (NRT) analytics rule construction with production-grade KQL
- Automation rule design for incident triage, enrichment, and routing
- Logic App playbook creation and linking to automation rules
- Rule tuning and alert-to-incident deduplication strategies
Who Should Use This Guide:
- SOC analysts and engineers building detection content
- Cloud security architects designing Azure SIEM pipelines
- Security teams migrating from Splunk, QRadar, or a legacy SIEM to Sentinel
Architecture Overview
Data Connectors (raw logs)
│
▼
Log Analytics Workspace (tables: SecurityEvent, SigninLogs, etc.)
│
▼
Analytics Rules (KQL queries → Alerts)
│
▼
Automation Rules (incident creation, enrichment, routing, triage)
│
├──► Manual analyst investigation
│
└──► Playbooks (Logic Apps) → Response actions
(Teams notify, block user, isolate endpoint, etc.)
Every alert generated by an analytics rule can create or update an incident. Automation rules run first — they handle grouping, severity overrides, tag assignment, and playbook invocation before a human ever sees the ticket.
Section 1: Analytics Rules
1.1 Rule Types
| Type | Query frequency | Lookback window | Best for |
|---|---|---|---|
| Scheduled | Every 5 min → 1 day | 5 min → 14 days | Threshold-based, aggregated detections |
| NRT (Near Real-Time) | ~1 minute | Trailing 5 minutes | Low-latency alerting on high-signal events |
| Microsoft Security | Real-time | N/A | Promote Defender/Entra alerts into incidents |
| Anomaly | Built-in ML | Varies | Behavioral baselines |
| Threat Intelligence | Real-time | N/A | IOC matching from TI feeds |
Use Scheduled rules for most custom detections. Use NRT rules only for the highest-priority, lowest-volume queries — they consume more capacity.
1.2 Creating a Scheduled Analytics Rule
Navigate to Microsoft Sentinel → Analytics → Create → Scheduled query rule.
Example: Brute-Force Success After Multiple Failures
This rule fires when a successful Entra ID sign-in follows 10+ failed attempts from the same IP within 20 minutes.
Step 1 — General tab
| Field | Value |
|---|---|
| Name | BruteForce: Successful Login After Multiple Failures |
| Description | Detects successful Entra ID login preceded by ≥10 failures from same IP |
| Severity | High |
| Tactics | Credential Access |
| Techniques | T1110 — Brute Force |
Step 2 — Set rule logic
Paste the following KQL into the rule query editor:
let lookback = 20m;
let failure_threshold = 10;
// Collect failed sign-ins
let failures = SigninLogs
| where TimeGenerated > ago(lookback)
| where ResultType != 0 // non-zero = failure
| summarize FailureCount = count(), FailedAccounts = make_set(UserPrincipalName, 50)
by IPAddress, bin(TimeGenerated, lookback)
| where FailureCount >= failure_threshold;
// Find successful logins from same IPs
SigninLogs
| where TimeGenerated > ago(lookback)
| where ResultType == 0 // success
| join kind=inner failures on IPAddress
| project
TimeGenerated,
UserPrincipalName,
IPAddress,
AppDisplayName,
Location,
FailureCount,
FailedAccounts,
UserAgent
| extend
AccountDomain = tostring(split(UserPrincipalName, "@")[1]),
RiskScore = iff(FailureCount > 50, "Critical", iff(FailureCount > 20, "High", "Medium"))Step 3 — Alert enrichment
Under Alert enrichment → Entity mapping, map the following:
| Entity type | Identifier | Column |
|---|---|---|
| Account | Name | UserPrincipalName |
| IP | Address | IPAddress |
Under Custom details, expose:
| Key | Value column |
|---|---|
| FailureCount | FailureCount |
| RiskScore | RiskScore |
| FailedAccounts | FailedAccounts |
Step 4 — Query scheduling
| Setting | Value |
|---|---|
| Run query every | 5 minutes |
| Lookup data from the last | 20 minutes |
| Alert threshold | Greater than 0 results |
| Event grouping | Group all events into a single alert |
Step 5 — Incident settings
Enable Create incidents from alerts triggered by this analytics rule. Configure alert grouping:
- Group alerts into a single incident if
IPAddressandUserPrincipalNameare the same - Grouping time window: 24 hours
- Re-open closed incident if new alert arrives: Enabled
Step 6 — Review and create
Click Review + create. The rule activates immediately and will generate its first alert on the next scheduled run.
1.3 Creating an NRT Rule
NRT rules use the same KQL syntax but run approximately every minute. Use them for detections where speed is critical.
Example: New Global Admin Assignment
AuditLogs
| where OperationName == "Add member to role"
| extend RoleDisplayName = tostring(TargetResources[0].modifiedProperties[?(@.displayName == "Role.DisplayName")].newValue)
| where RoleDisplayName contains "Global Administrator"
| extend
InitiatedByUser = tostring(InitiatedBy.user.userPrincipalName),
TargetUser = tostring(TargetResources[0].userPrincipalName)
| project TimeGenerated, InitiatedByUser, TargetUser, RoleDisplayName, CorrelationIdCreate via Analytics → Create → NRT query rule. The query window is fixed at the trailing 5 minutes. Scheduling is automatic.
Capacity note: NRT rules consume approximately 25× more compute than equivalent scheduled rules. Keep your NRT rule count under 50 per workspace.
1.4 KQL Tuning Patterns
Exclude known-good IPs
let allowlisted_ips = dynamic(["10.0.0.5", "203.0.113.10"]);
SigninLogs
| where IPAddress !in (allowlisted_ips)
| where ResultType == 0
// ... rest of queryTime-based noise suppression (exclude business hours)
SigninLogs
| where hourofday(TimeGenerated) !between (8 .. 18) // flag after-hours logins only
| where dayofweek(TimeGenerated) !in (0d, 6d) // skip weekendsTunable threshold via watchlist
Store thresholds in a Sentinel Watchlist named TuningParameters with columns RuleName and Threshold:
let params = _GetWatchlist("TuningParameters")
| where RuleName == "BruteForce_FailureThreshold"
| project Threshold = toint(SearchKey);
let threshold = toscalar(params | summarize max(Threshold));
// Use threshold in your query
SigninLogs
| summarize FailCount = count() by IPAddress
| where FailCount >= thresholdSection 2: Automation Rules
Automation rules replace the deprecated alert-trigger playbook pattern. They run in order (priority 1 → 1000) and can:
- Change incident severity, status, or owner
- Add tags and comments
- Run a playbook
- Suppress duplicate incidents
2.1 Creating an Automation Rule
Navigate to Microsoft Sentinel → Automation → Create → Automation rule.
Example: Auto-Close Low-Severity Informational Incidents from Known Scanners
Conditions:
| Field | Operator | Value |
|---|---|---|
| Incident severity | Equals | Informational |
| Incident title | Contains | NessusScanner |
Actions (in order):
- Add tag:
scanner-noise - Change status: Closed
- Closing classification: Benign Positive — Suspicious but Expected
Rule expiration: Never
Order: 1 (highest priority — runs before all other rules)
Example: SOC Tier-1 Auto-Triage Rule
Route Medium incidents to the Tier-1 analyst queue and tag for SLA tracking:
Conditions:
| Field | Operator | Value |
|---|---|---|
| Incident severity | Equals | Medium |
| Analytics rule name | Contains | SigninLogs |
Actions:
- Assign owner:
soc-tier1@contoso.com - Add tag:
sla-4h - Add comment:
Auto-triaged by Sentinel automation. SLA: 4 hours.
2.2 Running a Playbook from an Automation Rule
Under Actions → Run playbook, select your Logic App. The playbook must:
- Use the Microsoft Sentinel Incident trigger (not the Alert trigger — deprecated since March 2026)
- Have the Microsoft Sentinel Responder role on the Sentinel workspace
- Be in the same subscription or be explicitly shared cross-subscription
Migration note: If you have existing playbooks using the
When a Microsoft Sentinel alert is triggeredtrigger, migrate them toWhen Azure Sentinel incident creation rule was triggeredand re-link via automation rules. Microsoft's migration wizard is at Sentinel → Automation → Migrate playbooks.
Section 3: Playbooks (Logic Apps)
3.1 Playbook: Post Incident to Teams and Await Analyst Acknowledgement
This playbook fires on a High/Critical incident, posts a formatted Teams message, and waits for an analyst to click Acknowledge before closing the loop.
Step 1 — Create the Logic App
In Azure Portal:
- Search for Logic Apps → Add
- Select Consumption plan (cheaper for low-volume SOC playbooks)
- Name:
SentinelNotify-Teams-Incident - Region: match your Sentinel workspace region
Step 2 — Designer: Trigger
Add trigger → Search Microsoft Sentinel → Select When Azure Sentinel incident creation rule was triggered
This provides the incident object with all enriched properties.
Step 3 — Parse and format the message
Add an action: Parse JSON on Body/object/properties using this schema:
{
"type": "object",
"properties": {
"incidentNumber": { "type": "integer" },
"title": { "type": "string" },
"severity": { "type": "string" },
"status": { "type": "string" },
"incidentUrl": { "type": "string" },
"description": { "type": "string" }
}
}Step 4 — Post to Teams channel
Add action → Microsoft Teams → Post message in a chat or channel
Channel: SOC-Alerts
Message:
🚨 **SENTINEL INCIDENT #@{body('Parse_JSON')?['incidentNumber']}**
**Title:** @{body('Parse_JSON')?['title']}
**Severity:** @{body('Parse_JSON')?['severity']}
**Status:** @{body('Parse_JSON')?['status']}
**Link:** @{body('Parse_JSON')?['incidentUrl']}
Step 5 — Add comment back to incident
Add action → Microsoft Sentinel → Add comment to incident
Incident ARM ID: @{triggerBody()?['object']?['id']}
Comment: Teams notification sent to SOC-Alerts channel at @{utcNow()}
Step 6 — Save and grant permissions
- Save the Logic App
- Navigate to your Sentinel workspace → Access control (IAM)
- Add role assignment: Microsoft Sentinel Responder → Assign to the Logic App's managed identity
3.2 Playbook: Entra ID — Revoke Sessions and Require MFA Re-registration
For compromised account incidents. This playbook revokes all active sessions and forces MFA re-registration.
Trigger: Sentinel incident trigger (same as above)
Actions:
1. Get incident entities (Accounts)
2. For each Account entity:
a. HTTP POST https://graph.microsoft.com/v1.0/users/{userId}/revokeSignInSessions
Method: POST
Authentication: Managed Identity with Graph API User.ReadWrite.All permission
b. HTTP POST https://graph.microsoft.com/v1.0/users/{userId}/authentication/methods/{methodId}
(DELETE MFA methods to force re-registration)
3. Add Sentinel incident comment: "Sessions revoked and MFA reset for {UserPrincipalName} at {utcNow()}"
4. Change incident status: Active (do not auto-close — analyst must verify)
Managed Identity permissions needed:
User.ReadWrite.All
UserAuthenticationMethod.ReadWrite.All
Grant via Azure CLI:
# Get the Logic App's managed identity Object ID
LOGIC_APP_ID=$(az logic workflow show \
--name "SentinelRevoke-EntraID-Sessions" \
--resource-group "rg-sentinel" \
--query "identity.principalId" -o tsv)
# Get Microsoft Graph Service Principal ID
GRAPH_SP=$(az ad sp list --display-name "Microsoft Graph" --query "[0].id" -o tsv)
# Grant User.ReadWrite.All
az rest \
--method POST \
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/${GRAPH_SP}/appRoleAssignments" \
--body '{
"principalId": "'"${LOGIC_APP_ID}"'",
"resourceId": "'"${GRAPH_SP}"'",
"appRoleId": "741f803b-c850-494e-b5df-cde7c675a1ca"
}'3.3 Playbook: Defender for Endpoint — Isolate Machine
For ransomware or worm-spread incidents. Issues a machine isolation command via the MDE API.
Trigger: Sentinel Incident
1. Get incident entities (Hosts)
2. For each Host:
a. HTTP POST https://api.securitycenter.microsoft.com/api/machines/{machineId}/isolate
Body: { "Comment": "Auto-isolated by Sentinel playbook. Incident #[incidentNumber]", "IsolationType": "Selective" }
Authentication: Managed Identity with WindowsDefenderATP.ReadWrite.All
3. Add Sentinel comment: "Machine [hostname] isolated at [utcNow()]"
4. Change incident severity: Critical (if not already)
5. Assign to: soc-tier2@contoso.com
Selective isolation blocks all traffic except the MDE management channel, keeping the agent responsive. Use
Fullonly for severe confirmed breaches.
Section 4: Automation Rule Ordering and Playbook Chaining
Automation rules execute sequentially by priority number. Design your priority ladder:
| Priority | Rule name | Purpose |
|---|---|---|
| 1 | Scanner noise suppression | Close known-benign scanner alerts |
| 10 | Duplicate incident merger | Group related alerts |
| 50 | Severity override: Entra admin changes | Force Critical on Global Admin changes |
| 100 | Tier-1 auto-triage | Assign Medium incidents to queue |
| 200 | Teams notification playbook | Notify on High/Critical |
| 300 | Entra session revoke playbook | Run on Identity: Compromised tag |
| 500 | MDE isolation playbook | Run on Endpoint: Ransomware tag |
| 1000 | Default: tag as unreviewed | Catch-all for unprocessed incidents |
Chaining playbooks: You cannot call a playbook from within another playbook via Sentinel's native automation — use Logic App nested workflows or Azure Functions for complex chaining.
Section 5: Monitoring Rule Health
5.1 Analytics Rule Performance Dashboard
Create a Sentinel Workbook with this KQL to monitor rule health:
// Rules that generated no alerts in the past 7 days (possible misconfiguration or data gap)
SecurityAlert
| where TimeGenerated > ago(7d)
| summarize LastAlert = max(TimeGenerated) by AlertName
| join kind=rightouter (
_SentinelHealth
| where TimeGenerated > ago(7d)
| where SentinelResourceType == "Analytics Rule"
| summarize LastRun = max(TimeGenerated), Status = any(Status)
by SentinelResourceName
) on $left.AlertName == $right.SentinelResourceName
| where isempty(LastAlert) or LastAlert < ago(7d)
| project SentinelResourceName, LastRun, Status, LastAlert
| order by LastRun asc5.2 Automation Rule Execution Audit
// Track automation rule actions applied to incidents over the last 24 hours
SecurityIncident
| where TimeGenerated > ago(24h)
| where ModifiedBy == "Automation"
| extend Tags = tostring(Labels)
| summarize
IncidentsModified = count(),
SeverityDistribution = make_bag(pack(Severity, count()))
by bin(TimeGenerated, 1h)
| render timechart5.3 Playbook Failure Alerts
Monitor Logic App run failures with this diagnostic KQL (requires Logic App diagnostics sent to the same Log Analytics workspace):
AzureDiagnostics
| where ResourceType == "WORKFLOWS/RUNS"
| where status_s == "Failed"
| where resource_workflowName_s startswith "Sentinel"
| project TimeGenerated, WorkflowName = resource_workflowName_s, ErrorMessage = error_message_s
| order by TimeGenerated descSet up a scheduled analytics rule on this query to alert the SOC when a playbook fails silently.
Section 6: March 2026 Migration Checklist
If you have pre-existing analytics rules that invoke playbooks via the deprecated alert trigger, complete this migration:
[ ] Audit existing playbooks:
Sentinel → Automation → Playbooks tab
Filter by Trigger type = "Alert"
[ ] For each alert-trigger playbook:
[ ] Open Logic App designer
[ ] Change trigger from "When a Microsoft Sentinel alert is triggered"
to "When Azure Sentinel incident creation rule was triggered"
[ ] Update all subsequent steps that reference the Alert schema
to use the Incident schema (properties path changes)
[ ] Save and test with a sample incident
[ ] Create matching automation rule:
[ ] Condition: matches the analytics rule(s) that used to invoke this playbook
[ ] Action: Run playbook → select migrated Logic App
[ ] Set appropriate priority
[ ] Validate:
[ ] Trigger a test alert from analytics rule
[ ] Confirm incident is created
[ ] Confirm automation rule fires (check Automation → Activity log)
[ ] Confirm playbook executes (check Logic App run history)
[ ] Decommission old alert-trigger workflow after 30-day validation period
Troubleshooting
Automation rule not firing
- Check rule is Enabled and not expired
- Verify the incident matches all conditions — use the incident detail view to see Tags, Severity, and rule name
- Check Sentinel → Automation → Activity log for rule execution history
- Ensure the automation rule order is correct — a higher-priority rule with a
Stop processingaction may be blocking it
Playbook permissions error
Error: The playbook does not have permission to perform action on incident
Fix: Assign the Logic App's system-assigned managed identity the Microsoft Sentinel Responder role on the workspace:
az role assignment create \
--assignee "${LOGIC_APP_IDENTITY_OBJECT_ID}" \
--role "Microsoft Sentinel Responder" \
--scope "/subscriptions/${SUB_ID}/resourceGroups/${RG}/providers/Microsoft.OperationalInsights/workspaces/${WS}"KQL rule returns no results unexpectedly
- Run the KQL directly in Logs against the target table with the same time range
- Check data connector health: Sentinel → Data connectors → Status
- Verify the table exists and has recent data:
SigninLogs | summarize max(TimeGenerated) - Check for schema drift — table columns change after connector updates
Alert grouping creating too many incidents
Lower noise by adjusting Alert grouping in the analytics rule's Incident settings:
- Increase grouping window from 1h → 24h
- Group by additional entities (add
AppDisplayNameto reduce cross-app grouping) - Use automation rules to merge related incidents post-creation via the Merge incidents action
Summary
| Component | Purpose | Where configured |
|---|---|---|
| Scheduled analytics rule | Detect threats via KQL | Sentinel → Analytics |
| NRT analytics rule | Near-real-time high-priority detection | Sentinel → Analytics |
| Automation rule | Triage, enrich, route, invoke playbook | Sentinel → Automation |
| Logic App (Sentinel trigger) | SOAR response actions | Azure Logic Apps |
| Watchlist | Tunable allow/block lists for KQL | Sentinel → Watchlists |
| Workbook | Rule health and coverage monitoring | Sentinel → Workbooks |
A production Sentinel deployment is built in layers: high-fidelity analytics rules that minimize false positives, automation rules that handle the mechanical triage work, and targeted playbooks that execute response actions only when the evidence warrants it. Start with the OOTB Microsoft content packages, layer your custom detections on top, and continuously tune using the health monitoring queries above.