Skip to main content

sentinel-xdr-detection-validator

Validate generated XDR Detection YAML structurally and validate source and converted KQL through official Microsoft Sentinel Triage MCP tools first, with direct API fallback.

Source facts

Repository
Azure/Azure-Sentinel
Last source activity
October 25, 2026 at 12:43
Detected SKILL.md language
English
Stars
6,229
Forks
3,857

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
sentinel-xdr-detection-validator
description
Validate generated XDR Detection YAML structurally and validate source and converted KQL through official Microsoft Sentinel Triage MCP tools first, with direct API fallback.
# Validate XDR Detection YAML Offline validation requires `contentProvenance.requiredWorkloads` records (`workload`, `dataTypes`) and `contentProvenance.requiredDataConnectors` records (`connectorId`, `dataTypes`). Missing fields, malformed/unknown workloads and `dependencyReviewRequired: true` block validation. Use `sentinel-xdr-dependency-helper` to review unresolved prerequisites against an explicitly approved lab. Conversion never calls or requires Log Analytics. Reviewed empty connector arrays are valid for native XDR-only content. Live source validation requests `Prefer: include-dataSources=true`, retains input metadata, and compares it with authored workload/connector declarations. It uses API metadata for 1-10 distinct tables; successful missing metadata or more than 10 tables falls back to the conservative scanner. Failed or partial queries never become empty successful dependencies. Source connector declarations are compared without inventing connectors from shared tables. Authoring can use the helper's explicitly approved lab reads and offline metadata import without enabling the Qualification-only SDK execution route. Use the `sentinel-xdr-migration` CLI for deterministic planning, structural validation, fallback execution, and reporting. Runtime query execution prefers: - Microsoft Sentinel Triage MCP for every query operation supported by the connected server: `https://sentinel.microsoft.com/mcp/triage`. - Native Azure Monitor Query SDK for complete original Sentinel-query execution after a Triage provider failure, or when the CLI path is explicitly selected. - Log Analytics CLI/API results remain importable as a legacy original Sentinel-query fallback. - Microsoft Graph Advanced Hunting through the CLI as the Advanced Hunting fallback. ## Provider fallback policy Inspect the connected Triage MCP tools and use a suitable advertised tool first. Do not invent a tool name or assume a capability. Fall back to the corresponding direct provider only when Triage cannot act as a provider, including: - the MCP server or the required query tool is unavailable; - authentication, consent, or permission fails; - the request times out or the MCP service returns a transient/provider error; - a provider failure prevents completion of the full solution batch. Original Sentinel queries fall back to the Azure Monitor Query SDK (or imported legacy Log Analytics CLI/API results). Advanced Hunting queries fall back to Graph. Do not fall back when Triage successfully executes the request and returns a real KQL semantic/runtime error. That is a detection failure, not an MCP failure. Do not combine providers within one query-family report; if Triage fails mid-batch, rerun that complete batch through its direct provider. Before any live query, confirm the exact persisted Log Analytics workspace and/or Defender tenant, and verify the required read permissions for that provider. Never choose another workspace to recover from a failure. Do not launch authentication without first asking. Structural validation, runtime execution, schema binding, and qualification are separate outcomes; a provider fallback or successful query never marks a rule validated or proves parity. For partial publication, do not weaken this rule-level evidence contract. `package-selection-plan` counts only unique, current source IDs represented by eligible deployable Custom Detections against the complete original Sentinel rule inventory; the partial threshold is strictly over 50%. Qualification may use only the fresh applied selected subset and must keep excluded item failures visible. Never relabel a partial selected-query result as full-inventory Validation or Qualification. ## Workflow 1. Run `sentinel-xdr-migration doctor`. 2. On first run, run `sentinel-xdr-migration setup --non-interactive`. 3. Ask before launching interactive authentication. Never block offline conversion. 4. Run: ```powershell sentinel-xdr-migration validate --solution "<solution-path>" ``` 5. Stop if structural errors remain. Each detection requires its own top-level `version` (`major.minor.patch`) in `[3.1.0, 4.0.0)`, separate from `schemaVersion: 1.0.0`. Source Sentinel `1.x` versions remain valid provenance and must not be promoted to satisfy this check. For older files without the XDR version, report the reconversion guidance rather than changing provenance or accepting Data/solution version fallbacks. 6. Generate the complete runtime plan: ```powershell sentinel-xdr-migration validation-plan --solution "<solution-path>" ``` Use advertised official Triage MCP tools first for every supported `sentinelQuery` and `advancedHuntingQuery`. For Advanced Hunting, invoke `RunAdvancedHuntingQuery`. If the connected MCP does not advertise a suitable original Sentinel workspace-query tool, either run the toolkit's native SDK provider for the full family or use the legacy Log Analytics CLI/API import path without treating that capability gap as a KQL failure. The native source-query runner requires an existing Qualification run and its locked target. It verifies the active Azure CLI tenant and subscription without signing in, sends each exact persisted source KQL string directly to `LogsQueryClient.query_workspace(timespan=None)`, and records full returned schemas and rows in the ignored run-local SDK report: ```powershell sentinel-xdr-migration validate-sentinel-sdk ` --solution "<solution-path>" ` --run-id "<qualification-run-id>" ``` Defaults bound each request to 90 seconds and the complete source family to 30 minutes, with at most two transient retries per query. The complete recursive source inventory must map one-to-one to current generated detections. Authentication, authorization, query, transport and partial result failures are retained distinctly. Zero returned rows indicate query execution only, not parity. Normalize Advanced Hunting results into a JSON file containing exactly one entry per detection and the returned target-query output `schema` array when custom details are present. Copy `querySha256` from the matching `advancedHuntingQuerySha256` in the runtime plan; it must hash the exact KQL sent to the provider: ```json { "results": [ { "detection": "Example.yaml", "status": "passed", "statusCode": 200, "rowCount": 0, "querySha256": "<exact advancedHuntingQuery SHA-256 from validation-plan>", "schema": [{"Name": "DeviceId"}, {"Name": "Timestamp"}], "error": null } ] } ``` Allowed statuses are `passed`, `failed`, and `blocked`. Then record the provider results: ```powershell sentinel-xdr-migration record-runtime-validation ` --solution "<solution-path>" ` --provider triage-mcp ` --results "<normalized-results.json>" ``` 7. If Triage cannot complete an entire query family for a provider-level reason, create a run-local `provider-gap-<family>.json` recording the advertised tool name (or `unavailable`), exact target reference, one approved reason code (`tool-unavailable`, `authentication`, `authorization`, `timeout`, `transient-provider-error`, or `batch-provider-failure`), a concise reason, `batchComplete: true`, `scopeVerified: true`, `permissionsVerified: true`, and `kqlError: false`. Do not use a gap record for a real KQL error. The CLI rejects incomplete, cross-family, wrong-provider, or unscoped fallback evidence. For original Sentinel queries, rerun that **complete family** against the exact locked workspace. Prefer the native SDK command above; pass the run-local provider-gap evidence if Triage failed: ```powershell sentinel-xdr-migration validate-sentinel-sdk ` --solution "<solution-path>" ` --run-id "<qualification-run-id>" ` --provider-gap-evidence "<run-local-provider-gap-sentinel.json>" ``` For externally imported provider results, normalize one result per detection and include `querySha256` from that rule's `sentinelQuerySha256` plan entry, then record it with the gap evidence: ```powershell sentinel-xdr-migration record-runtime-validation ` --solution "<solution-path>" ` --provider log-analytics-cli ` --results "<complete-sentinel-results.json>" ` --provider-gap-evidence "<run-local-provider-gap-sentinel.json>" ``` If and only if Triage has an Advanced Hunting provider-level failure, run the complete Advanced Hunting batch through Graph with the same kind of run-local evidence: ```powershell sentinel-xdr-migration validate-advanced-hunting ` --solution "<solution-path>" ` --provider-gap-evidence "<run-local-provider-gap-advanced-hunting.json>" ``` 8. Runtime providers create JSON and self-contained HTML reports under `Solutions\<solution>\Logs\sentinel-xdr-migration\<run-id>`. Treat `blocked` as an environment gap, not a conversion failure. 9. For every rule: - execute the original `sentinelQuery`; - execute the `advancedHuntingQuery`; - record whether each query binds and executes; - compare returned entity columns when representative rows exist. Imported `passed` Sentinel results without a matching `querySha256` are blocked. Graph results bind automatically to the exact Advanced Hunting query executed by the validator. A query rewrite invalidates old evidence; rerun the complete Sentinel and Advanced Hunting families for the current artifact before the workflow can pass runtime validation. 10. Zero rows are not proof of behavioral parity. Record them as execution success with data validation still pending. A table probe that executes and returns zero rows proves the table binds on that query surface. 11. Do not change `contentProvenance.conversion.status` to `validated` unless both queries execute and the entity output has been reviewed. ## Query-surface isolation Defender Advanced Hunting and Sentinel Log Analytics are separate query surfaces even when the Defender portal shows a selected Sentinel workspace. A table name resolving in Advanced Hunting does not prove that the same name resolves through the Log Analytics workspace API, and vice versa. - Probe the original `sentinelQuery` only against the exact persisted Log Analytics workspace. - Probe the converted `advancedHuntingQuery` only through Defender Advanced Hunting. - Never use workspace table-management inventory as query-availability proof. - Never scan other workspaces after the workflow workspace is selected. - Report the surface explicitly, for example: `IdentityInfo unavailable through log-analytics-workspace; available through defender-advanced-hunting`. - Do not say a table is unavailable "in every accessible workspace" unless the user explicitly requested a multi-workspace audit. For an **Authoring** profile, an environment-only runtime block does not prevent V3.1 packaging when structural validation passed. Complete validation as passed with `runtimeStatus=environment-blocked` only when no current exact-query KQL/runtime failure exists, preserve the provider error and query surface, and do not claim the detection is runtime-qualified. For a **Qualification** profile, the same runtime block remains blocking until the selected lab environment satisfies the required query surfaces. Return a per-rule result and an overall pass/needs-review summary. Best-effort entity-mapping assumptions recorded by conversion do not prevent read-only Sentinel/Advanced Hunting execution or output-schema binding tests. Run and report those tests against the exact hash-bound queries, retaining the assumption as pending human review. A successful query or custom-detail schema binding is not approval, entity correlation, or alert parity. Keep technical failures and other unresolved review findings blocking as applicable; do not package or deploy while an entity-mapping review remains pending. For unresolved table/schema or conversion assumptions, use provider-owned evidence: standard-table and schema documentation, live query schema from the selected provider, or the custom connector's DCR/table metadata. Do not substitute customer research or invent a schema. Present each proposed assumption with its exact scope, source/query hash, evidence, and `accept` or `reject` choice; no decision is automatic. Accepted assumptions still require reconversion and the normal structural/runtime checks. If content hashes change, re-review rather than reusing an earlier decision.
View on GitHub