Takes a single Sigma rule and renders a deployable Microsoft Sentinel ARM template.
pySigma's Kusto backend converts a Sigma rule to a KQL query in one line — but that's only half the work. Sentinel needs an ARM template wrapping the query, severity mapping, tactic/technique fields, and a few cron-style timing knobs. This script does the wrapping.
git clone https://github.com/liliyke/detection-tooling
cd detection-tooling
uv syncuv run sigma-to-sentinel --rule ../detection-rules/rules/credential_access/lsass_memory_access_unusual_process.ymlOutput:
wrote converted/lsass_memory_access_unusual_process.arm.json
The generated file is ready to deploy:
az deployment group create \
--resource-group rg-soc-prod \
--template-file converted/lsass_memory_access_unusual_process.arm.json \
--parameters workspace=law-soc-prod| Flag | What it does |
|---|---|
--rule PATH |
Sigma YAML to convert (required) |
--out DIR |
Where to drop the ARM template (default ./converted) |
--print-kql |
Echo the generated KQL to stdout — useful for quick "does this make sense" checks |
wrote converted/lsass_memory_access_unusual_process.arm.json
─────────── KQL ───────────
DeviceEvents
| where ActionType == "ProcessAccessed"
| where TargetProcessFileName endswith "lsass.exe"
| where InitiatingProcessFileName !endswith "\\MsMpEng.exe"
| where InitiatingProcessFileName !endswith "\\MsSense.exe"
| ...
A one-line shell loop covers the bulk case:
find ../detection-rules/rules -name "*.yml" -print0 | \
xargs -0 -n1 -I{} uv run sigma-to-sentinel --rule {}Or PowerShell:
Get-ChildItem ..\detection-rules\rules -Recurse -Filter *.yml | ForEach-Object {
uv run sigma-to-sentinel --rule $_.FullName
}You'll get one ARM file per rule in converted/. Deploy them in a single Bicep module if you prefer — see detection-infra.
The ARM template embeds:
query— the KQL itself. Validate it once in the Sentinel query editor before mass-deploying.severity— translated from Sigmalevel. Sentinel doesn't have a "Critical" severity so I map Sigmacritical → High. Adjust if your runbook depends on a different mapping.tactics/techniques— pulled from Sigma'stags. The ATT&CK fields drive Sentinel's incident graph + investigation panel, so getting them right matters.queryFrequency/queryPeriod— both default to 15 minutes. Override per-rule if needed (some hunt-style rules need a 24h period).
- Per-rule timing overrides. Read a
sentinel:block from the Sigma rule'scustom_attributesand apply it. Lets a rule author say "this is a daily summary, period=24h". - Entity mapping. Sentinel ARM supports
entityMappingsthat link fields in the query result to UEBA entity types (Account, Host, IP). Auto-populate based on common field names (User,Computer,RemoteIP). - Per-environment severity ladders. Some orgs treat all PowerShell
-EncodedCommandrules asHighregardless of Sigmalevel. Add an override file. - Multi-workspace fan-out. Add a
--workspacesflag that takes a list, renders one ARM per workspace with the right param values. - Cross-workspace queries. If you have a federated SIEM (workspace-level + tenant-level), parameterize the table name. Sentinel rule queries can be made workspace-agnostic with
workspace("name").TableName. - Sentinel REST API direct deploy. Skip ARM and call the analytic rules REST endpoint directly — useful in CI where you don't want to maintain a resource group.
tests/test_sigma_to_sentinel.py includes round-trip checks for several known-good Sigma rules. Run with uv run pytest -q.
SigmaTransformationError: backend ... cannot handle field 'CallTrace'— means the Kusto backend doesn't know how to map that field. Add a pySigma pipeline that translates Sigma field names to Sentinel table columns. Seepipelines/sentinel_microsoft_xdr.py.- KQL syntax error after generation — usually a value with quotes that broke escaping. Open a pySigma issue with the offending rule.
- Sentinel ARM template reference — alert rules
- pySigma Kusto backend
- Sentinel detection content repo — the canonical reference