Detection-as-code for Microsoft Sentinel — 12 analytic rules, 10 hunting queries, an L3 triage workbook, a Logic App playbook, ATT&CK Navigator coverage, and Atomic Red Team validation mapping. Every rule is CI-validated.
Author: Sandeep Mothukuri — SOC L3 / Incident Response
Repo: sandeepmothukuri/sentinel-detection-engine
Loaded into MITRE ATT&CK Navigator from attack-navigator/layer.json — the layer is auto-generated from the rule YAML by scripts/generate_coverage.py.
Static render of Workbooks/L3-Triage-Dashboard.json — KPIs, severity donut, top firing rules, ATT&CK density heatmap, top entities, and active-incident table. Deploy the JSON to Microsoft Sentinel for live data.
📷 Live Sentinel portal screenshots (added after I complete a tenant deployment via the 30-minute walkthrough)
The walkthrough produces these on a real M365 dev tenant + Azure free trial + MDE trial. Each is captured by running an Atomic Red Team test that fires the corresponding rule:
01-sentinel-overview.png— Sentinel workspace overview02-data-connectors.png— Data connectors page with ≥ 4 connected sources03-analytics-rules.png— Analytics rules list with 12 deployed detections05-incident-list.png— Real incident from an Atomic Red Team test06-investigation-graph.png— Investigation entity graph07-workbook-live.png— Workbook running against live data
Most public Sentinel content is either (a) a single hand-written query in a blog post, or (b) the full Microsoft community repo with thousands of rules and no curation. This pack sits in the middle: a focused, curated set of high-signal detections an L3 analyst would actually deploy on day one, with the engineering rigour (schema validation, ATT&CK mapping, ART tests) of a production detection-engineering team.
| Area | Count | Folder |
|---|---|---|
| Scheduled analytic rules | 12 | Detections/ |
| Hunting queries | 10 | Hunting Queries/ |
| Workbook (L3 Triage Dashboard) | 1 | Workbooks/ |
| Logic App playbooks (SOAR) | 4 | Playbooks/ |
| ATT&CK Navigator layer | 1 | attack-navigator/ |
| Atomic Red Team mapping | 22 tests | tests/atomics.md |
| Workflow documentation (IR runbook, triage SOP, escalation matrix, tuning log, SOAR flow, maturity assessment) | 6 | docs/workflows/ |
| CI workflows (validate, PR diff report, release) | 3 | .github/workflows/ |
| Sigma → KQL converter | 1 | scripts/sigma_to_kql.py |
- Tactics covered: Initial Access, Execution, Persistence, Privilege Escalation, Defense Evasion, Credential Access, Discovery, Collection, Command & Control, Exfiltration
- Techniques covered: 18 unique ATT&CK techniques (see
coverage.md) - Data sources: Microsoft Entra ID, Microsoft 365 (Exchange, SharePoint, OAuth), Microsoft Defender for Endpoint, Azure Activity, Azure Key Vault
EntraID_ImpossibleTravel.yaml— geo-distance + time-delta sign-in correlationEntraID_MFAFatigue.yaml— repeated MFA prompts followed by successEntraID_LegacyAuthSuccess.yaml— successful auth over legacy protocolsEntraID_ServicePrincipalCredAdd.yaml— credential added to SP outside CI/CD allow-list
M365_InboxRuleExfil.yaml— auto-forward / delete inbox rule creationM365_MassSharePointDownload.yaml— anomalous file download volume per userM365_OAuthConsentSuspiciousApp.yaml— consent to non-verified publisher with high-risk scopes
MDE_LOLBin_Rundll32_Network.yaml— rundll32 making external network connectionsMDE_MSHTA_RemoteScript.yaml— mshta executing remote HTA/scriptMDE_PowerShell_EncodedCommand.yaml— long Base64 -EncodedCommand invocations
Azure_NSG_OpenToInternet.yaml— NSG rule opening port to 0.0.0.0/0Azure_KeyVault_SecretAccessSpike.yaml— abnormal secret-access volume per identity
Hypothesis-driven hunts in Hunting Queries/. Examples:
- First-seen ASN per user (sign-in baseline drift)
- Rare process per device parent-child chain
- Anomalous mailbox forwarding to external domain
- Unsigned binaries executing from
%TEMP% - Sign-in from datacenter ASN (Tor/VPS proxying)
Three deployment paths, in order of recommended:
This repo follows the official Azure/Azure-Sentinel folder schema, so you can connect it directly:
- Sentinel → Repositories → Add new
- Connect this GitHub repo
- Select
mainbranch - Sentinel pulls and deploys all 12 rules + 10 hunts + 1 workbook on every push
Docs: https://learn.microsoft.com/azure/sentinel/ci-cd
Each YAML file is a self-contained Sentinel rule. Paste the query: block into Sentinel → Analytics → New scheduled rule, copy the metadata, save.
The Logic App playbook ships as ARM in Playbooks/AutoEnrichDisableUser/azuredeploy.json. Deploy via:
az deployment group create \
--resource-group <rg> \
--template-file Playbooks/AutoEnrichDisableUser/azuredeploy.jsonYou can run the full pack on a brand-new Azure tenant with $0 spend for the first 30 days.
- Quickstart:
docs/30-minute-walkthrough.md— click-by-click, 30 min, produces real Sentinel screenshots - Reference:
docs/free-tier-setup.md— slower-paced explanation of each component
GitHub Actions runs on every PR (.github/workflows/validate.yml):
- YAML schema lint — every rule conforms to the Sentinel rule schema
- KQL parse check — queries parse without syntax errors
- ATT&CK ID validation — every
tactics:/relevantTechniques:value exists in the current ATT&CK matrix - Markdown link check — no broken internal links
Each detection is mapped to one or more Atomic Red Team tests that should trigger it. See tests/atomics.md.
Example:
T1059.001 (PowerShell) → MDE_PowerShell_EncodedCommand.yaml → Atomic Test-1, Test-3
sentinel-detection-engine/
├── Detections/ # 12 analytic rules (Sentinel YAML schema)
├── Hunting Queries/ # 10 hunts
├── Workbooks/
│ └── L3-Triage-Dashboard.json
├── Playbooks/
│ └── AutoEnrichDisableUser/
│ ├── azuredeploy.json
│ └── README.md
├── attack-navigator/
│ └── layer.json # drop into mitre-attack.github.io/attack-navigator
├── tests/
│ └── atomics.md # ART test ID → rule mapping
├── scripts/
│ └── generate_coverage.py # regenerates coverage.md + Navigator layer
├── docs/
│ ├── free-tier-setup.md
│ └── images/
├── .github/workflows/
│ └── validate.yml
├── coverage.md # auto-generated ATT&CK matrix
└── README.md
Four Logic App playbooks ship with the pack. They compose into the decision pipeline documented in docs/workflows/soar-decision-flow.md:
| Playbook | Trigger | Action |
|---|---|---|
| AutoEnrichDisableUser | Any incident with IP entities | VT + AbuseIPDB enrichment; disables Entra ID user above confidence threshold |
| IsolateDeviceMDE | Incidents from MDE_* rules |
Network-isolates the device via Defender for Endpoint |
| BlockIPAzureFirewall | TI-tagged incidents | Adds public IPs to a deny IP Group on Azure Firewall |
| CreateServiceNowTicket | Severity High / Critical | Opens an INC ticket, severity-mapped, with cross-linking |
The repo is more than a rule list — it ships with the documentation an L3 analyst expects:
- Incident response runbook — SANS / NIST 800-61r2 phases applied to this pack
- Triage SOP — L1 → L2 → L3 hand-off with disposition labels
- Escalation matrix — who gets paged, when, and how
- SOAR decision flow — Mermaid diagram + per-rule automation matrix
- Detection tuning log — open + closed tuning entries with PR links
- Maturity self-assessment — 10-dimension SOC maturity scoring
| Workflow | Trigger | What it does |
|---|---|---|
| validate | Every push + PR | yamllint, schema + UUID + ATT&CK + KQL sanity, coverage-drift check |
| pr-detection-report | PR touches detection files | Posts a sticky PR comment summarising rule diffs, version bumps, and lint warnings |
| release | Push of v*.*.* tag |
Validates, packs rules into a tarball with SHA-256, generates changelog, publishes GitHub Release |
For one-off rules from the public Sigma project, use the bundled converter:
python scripts/sigma_to_kql.py path/to/proc_creation_susp_powershell.ymlOutput is a hand-tunable Defender XDR-flavoured KQL block with ATT&CK tags preserved as comments. Not a full pySigma replacement — it handles the common process_creation, network_connection, image_load, and registry_event categories.
- Add AWS GuardDuty / CloudTrail analog pack (
aws-hunt-pack) - Add Defender for Cloud Apps (MCAS) coverage
- Notebook (
.ipynb) IR playbook for one of the detections fired end-to-end - Sigma → KQL conversion mapping for portability

