Skip to main content

Sentinel

Security Threat Intelligence Flow Control

Synopsis

Evaluates Microsoft Sentinel analytics rules against each event. The rule's KQL is compiled once, then run per event; a match annotates the event with the rule's name, severity, tactics, techniques, and resolved MITRE ATT&CK enrichment.

The rules are Sentinel analytics rules used unchanged. To convert a Sentinel ASIM parser into a pipeline instead, see From KQL; to use detection rules to reduce what reaches the SIEM, see Smart Engine.

Schema

- sentinel:
library: <string[]>
rules: <string[]>
rule_files: <string[]>
rule_dirs: <string[]>
select: <object>
mode: <enum>
mark_field: <ident>
min_severity: <enum>
mitre_enrich: <boolean>
include_query: <boolean>
table_field: <ident>
strict_table: <boolean>
enrich_on_unresolved: <boolean>
description: <text>
if: <script>
tag: <string>
disabled: <boolean>
ignore_failure: <boolean>
on_failure: <processor[]>
on_success: <processor[]>

Configuration

At least one rule source is required. With none, the processor fails.

FieldRequiredDefaultDescription
libraryY*Names of Sentinel rule packs assigned through the Library.
rulesY*Rules given inline, as rule YAML.
rule_filesY*Paths to rule files (.yml, .yaml).
rule_dirsY*Directories searched recursively for rule files.
selectNall rulesNarrows which of the loaded rules are registered. See below.
modeNannotateannotate marks matches and forwards every event. filter drops every event that matches no rule.
mark_fieldN_sentinelRoot field the match markers are written under.
min_severityNIgnore rules below this severity: informational, low, medium, or high.
mitre_enrichNtrueResolve MITRE ATT&CK tactics and techniques onto each match.
include_queryNfalseInclude the rule's KQL in the match.
table_fieldN_vmetric.tableThe event field holding the table name a rule is scoped against.
strict_tableNfalseRequire an event to declare a matching table before a table-scoped rule applies. See below.
enrich_on_unresolvedNfalseMake a rule whose KQL cannot be compiled match every event it is scoped to, rather than nothing.
descriptionNExplanatory note.
ifNCondition that must be true for the processor to run.
tagNIdentifier for this processor instance.
disabledNfalseWhen true, the processor is skipped.
ignore_failureNfalseContinue pipeline processing if the processor fails.
on_failureNSee Handling Failures.
on_successNSee Handling Success.

* = At least one of library, rules, rule_files, or rule_dirs is required. Sources are combined, in that order.

Loading include...

Select

All criteria are combined with AND; the values within one criterion are combined with OR. Matching is case-insensitive.

FieldDescription
tablesRules whose declared data types include any of these, such as SecurityEvent or CommonSecurityLog.
connectorsRules by required data connector id.
severitiesinformational, low, medium, or high.
kindsScheduled or NRT.
tacticsMITRE tactic. Separator-insensitive, so CommandAndControl and command-and-control are equivalent.
techniquesMITRE technique id. A parent id also selects its sub-techniques, so T1059 selects T1059.001.
idsRule id, matched exactly.
name_prefix, name_contains, name_regexRule title matching.
desc_containsRule description matching.
tagsRule tags.

A select that matches no rules is an error, raised when the first event reaches the processor.

Details

Annotating and Filtering

In the default annotate mode, every event is forwarded. A matching event gains its markers; a non-matching event passes through untouched.

Setting mode: filter turns the processor into an allowlist: an event that matches no rule is dropped. Use it deliberately — it discards telemetry.

Table Scoping

A rule that declares no table applies to every event. A rule scoped to a table applies to events whose table_field names that table, compared case-insensitively.

An event carrying no table at all is, by default, still evaluated against every table-scoped rule — the rule's own field predicates decide whether it fires. This favors never missing a detection, at the cost of occasional cross-table matches. Set strict_table: true to require a positive table match instead, which skips table-scoped rules for any event that does not declare a table.

This differs from Smart Engine, where an untabled event has no applicable detections at all. The two processors read the same rules but scope them differently, so do not carry an assumption from one to the other.

Rules That Cannot Be Compiled

Some Sentinel rules use KQL that has no per-event form. Such a rule is marked unmatchable and enriches nothing — it fails closed. Setting enrich_on_unresolved: true reverses that: the rule instead matches every event whose table it positively declares, which annotates far more events but never misses one.

Markers

FieldDescription
_sentinel.matchedtrue on a matching event.
_sentinel.rulesOne entry per matched rule.
_sentinel.countThe number of matched rules.

Each entry in _sentinel.rules carries name, and — when the rule defines them — id, severity (lower-cased), tactics, techniques, tables, fields, and mitre. The rule's query is included only under include_query.

Examples

Annotating a Match

Registering an assigned rule pack, narrowed to the rules for one table...

- sentinel:
library:
- "*"
select:
tables:
- SecurityEvent

A matching event is annotated with the rule and its ATT&CK enrichment. The event itself is unchanged...

{
"_sentinel": {
"matched": true,
"count": 1,
"rules": [
{
"name": "Suspicious process executed",
"severity": "high",
"tactics": ["Execution"],
"techniques": ["T1059"]
}
]
}
}

Filtering to Rule Matches Only

Forwarding only events that some high-severity rule matched...

- sentinel:
library:
- "*"
mode: filter
min_severity: high

An event matching no high-severity rule is dropped. Nothing is forwarded for it...

// dropped

Requiring a Declared Table

Scoping strictly, so a rule fires only for events that positively declare its table...

- sentinel:
library:
- windows_rules
strict_table: true

An event without _vmetric.table is skipped by every table-scoped rule rather than evaluated against it. Without strict_table, the same event would have been evaluated...

{
"EventID": 4688,
"Process": "powershell.exe"
}