Skip to content

Latest commit

 

History

History
109 lines (77 loc) · 4.77 KB

File metadata and controls

109 lines (77 loc) · 4.77 KB

sigma-to-sentinel

Takes a single Sigma rule and renders a deployable Microsoft Sentinel ARM template.

Why it exists

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.

Install (once per machine)

git clone https://github.com/liliyke/detection-tooling
cd detection-tooling
uv sync

Basic usage

uv run sigma-to-sentinel --rule ../detection-rules/rules/credential_access/lsass_memory_access_unusual_process.yml

Output:

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

Flags

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

Sample full output (--print-kql)

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"
| ...

How to use against a folder of rules

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.

What to look at in the output

The ARM template embeds:

  • query — the KQL itself. Validate it once in the Sentinel query editor before mass-deploying.
  • severity — translated from Sigma level. Sentinel doesn't have a "Critical" severity so I map Sigma critical → High. Adjust if your runbook depends on a different mapping.
  • tactics / techniques — pulled from Sigma's tags. 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).

Tuning ideas

  • Per-rule timing overrides. Read a sentinel: block from the Sigma rule's custom_attributes and apply it. Lets a rule author say "this is a daily summary, period=24h".
  • Entity mapping. Sentinel ARM supports entityMappings that 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 -EncodedCommand rules as High regardless of Sigma level. Add an override file.
  • Multi-workspace fan-out. Add a --workspaces flag 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

tests/test_sigma_to_sentinel.py includes round-trip checks for several known-good Sigma rules. Run with uv run pytest -q.

Troubleshooting

  • 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. See pipelines/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.

References