Generate or reuse one shared mock.json payload for a Microsoft Sentinel Analytic Rule and its converted Defender XDR Custom Detection. Uses only Azure-Sentinel repository content and never writes to Azure.
73%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./.github/skills/sentinel-solution-mock-data-generation/SKILL.mdUse this skill when a migration or optional-testing workflow needs mock data for a specific Analytic Rule and converted Custom Detection.
--output-root, or under this toolkit
repository's default mock root when no output root is supplied. Cross-worktree
generation must always use --output-root.Require:
Solutions\<solution>\XDR Detections\, or its exact path.The generator uses:
Sample Data\Tables\<Table>\base-event.json;Sample Data\Tables\<Table>\metadata.json;Package\mainTemplate.json;streamDeclarations, dataFlows, transformKql, and output stream.Tools\AzureMonitorLogsIngestion\registry.yaml for writable standard-table
routes, schemas, and transforms.For separate checkouts, pass --source-root for the repository containing the
solution and --toolkit-root for the repository containing this generator and
its registry. The toolkit's Sample Data is used by default; pass
--sample-data-root only when the neutral table samples live elsewhere.
Absolute AR/CD paths are resolved and checked to remain inside --source-root.
Output and table paths reject symlink escapes; the resolved source, toolkit,
sample-data, and output roots are printed in the result and recorded in the
scenario manifest.
Check:
<output-root>\<solution>\<rule-id>\ (defaults to toolkit Sample Data\Solutions\Mock)
mock.json
scenario.jsonRun:
python Tools\SolutionMigration\generate_mock_scenario.py `
--solution "<solution-folder>" `
--rule "<rule-id-or-exact-name>" `
--custom-detection "Solutions\<solution>\XDR Detections\<detection>.yaml" `
--source-root "<Azure-Sentinel-repository>" `
--toolkit-root "<repository-containing-this-generator>" `
--output-root "<Azure-Sentinel-repository>\Sample Data\Solutions\Mock"Without --force, a complete scenario that passed schema validation is
returned with status=existing-scenario. Reuse it after reviewing that its AR,
CD, stream, and hypothesis still match the current content.
The final output location is <output-root>\<solution>\<rule-id>\; the tool
does not silently fall back to a source-root-relative destination.
For a simple rule, the tool:
Custom-* input stream exists;mock.json payload.The registry only supports explicit reviewed capabilities. Field extraction
matches exact identifiers already present in a known table schema; it is not a
general KQL parser. Unknown/ambiguous tables, unregistered fields, or unresolved
mapping produce a blocked/offline scenario instead of a guessed contract.
Registry schema and transform fingerprints identify the exact template used.
liveValidated=false means the contract still needs exact-workspace validation;
generation never claims that the live table/DCR accepts it.
Optional deterministic controls:
python Tools\SolutionMigration\generate_mock_scenario.py `
--solution "<solution>" `
--rule "<rule>" `
--custom-detection "<path>" `
--randomize --copies 3 --seed 42 `
--lock "requestId=campaign-1" `
--benign-set "action=read"An unreviewed candidate is not a reviewed scenario. Pass it with
--candidate-scenario; this transports and type-checks the rows but does not
assert human acceptance or semantic query validation. Candidate input always
yields generationStatus=generated-offline-only, including simple rules, so it
cannot pass the direct-ingestion gate. The API result uses
status=generated-candidate (or existing-candidate on reuse). The
scenarioReview manifest object reports status=review-pending,
inputKind=candidate, the resolved input path and SHA-256, and
semanticValidation=not-run; validation.semanticReview=pending and
validation.semanticMatch=not-run. Reuse checks the candidate hash, and
--force cannot overwrite an unreviewed fixture.
python Tools\SolutionMigration\generate_mock_scenario.py `
--solution "<solution>" `
--rule "<rule>" `
--custom-detection "<path>" `
--candidate-scenario "<candidate.json>" `
--source-root "<Azure-Sentinel-repository>" `
--toolkit-root "<repository-containing-this-generator>" `
--output-root "<Azure-Sentinel-repository>\Sample Data\Solutions\Mock"For complex behavior, supply a candidate or reviewed JSON file:
{
"name": "reviewed-sequence",
"hypothesis": "Documented behavior observable in the selected telemetry.",
"lockedPaths": ["requestId"],
"maliciousRecords": [
{}
],
"benignRecords": [
{}
]
}Run with:
python Tools\SolutionMigration\generate_mock_scenario.py `
--solution "<solution>" `
--rule "<rule>" `
--custom-detection "<path>" `
--reviewed-scenario "<scenario.json>" `
--source-root "<Azure-Sentinel-repository>" `
--toolkit-root "<repository-containing-this-generator>" `
--output-root "<Azure-Sentinel-repository>\Sample Data\Solutions\Mock"Use --candidate-scenario while human review is pending and
--reviewed-scenario only after a human reviewer accepts the hypothesis and
records. The JSON contract is exactly name (non-empty string), hypothesis
(non-empty string), optional lockedPaths (string array),
maliciousRecords (non-empty array of objects), and benignRecords (non-empty
array of objects). Each record must already match the selected raw DCR input
contract or Standard-table metadata contract; malformed or unknown fields and
type mismatches block generation. This transports reviewed multi-field and
multi-record fixtures; it does not solve KQL joins, aggregates, thresholds, or
prove that records satisfy either query. Keep those cases manual-review-required
and generated-offline-only until independently validated. Do not treat
schema validation as semantic matching or approval for environment writes.
expectedMatchKeys is not a supported machine-checked field; record expected
join/grouping keys and unique marker values in the hypothesis/review notes and
verify them against the exact AR and CD queries separately.
For the Cisco ASA average-rate rule, candidate records must preserve the exact
one-hour current window and prior ago(6h)..ago(1h) five-hour interval,
including the source's prev6hCumTotal / 6 comparison and OR of all three
doubling thresholds. Keep the five join/group keys aligned across the two
windows and construct Message values that the source's parsing expressions
actually accept. For the exfiltration rule, preserve the >=1-GiB sent-byte
threshold, rounded >=95% upload ratio, time window, ASA/FTD product, allowed
action, private source IP, and public destination IP predicates. The generator
only transports and type-checks these reviewed rows; it does not synthesize
Cisco message grammar, calculate query aggregates, or prove a match. Include
separate benign controls and keep both rules blocked from automatic semantic
qualification.
Example Cisco ASA routing (candidate JSON paths are supplied by the author; this generator does not invent them):
python Tools\SolutionMigration\generate_mock_scenario.py `
--source-root "<Azure-Sentinel-1 checkout>" `
--toolkit-root "<toolkit checkout>" `
--solution CiscoASA `
--rule 795edf2d-cf3e-45b5-8452-fe6c9e6a582e `
--custom-detection "Solutions\CiscoASA\XDR Detections\CiscoASA-ThreatDetectionMessage.yaml" `
--candidate-scenario "<candidate-threat-detection-message.json>" `
--output-root "<Azure-Sentinel-1 checkout>\Sample Data\Solutions\Mock"
python Tools\SolutionMigration\generate_mock_scenario.py `
--source-root "<Azure-Sentinel-1 checkout>" `
--toolkit-root "<toolkit checkout>" `
--solution CiscoASA `
--rule 79f29feb-6a9d-4cdf-baaa-2daf480a5da1 `
--custom-detection "Solutions\CiscoASA\XDR Detections\CiscoASA-AvgAttackDetectRateIncrease.yaml" `
--candidate-scenario "<candidate-average-detection-rate.json>" `
--output-root "<Azure-Sentinel-1 checkout>\Sample Data\Solutions\Mock"
python Tools\SolutionMigration\generate_mock_scenario.py `
--source-root "<Azure-Sentinel-1 checkout>" `
--toolkit-root "<toolkit checkout>" `
--solution CiscoASA `
--rule f3a8c2d0-7b41-4e9a-9f6a-2d8a1c4e5b72 `
--custom-detection "Solutions\CiscoASA\XDR Detections\CiscoASA-PossibleDataExfiltration.yaml" `
--candidate-scenario "<candidate-data-exfiltration.json>" `
--output-root "<Azure-Sentinel-1 checkout>\Sample Data\Solutions\Mock"<output-root>\<solution>\<rule-id>\ (defaults to toolkit Sample Data\Solutions\Mock)
mock.json
scenario.jsonscenario.json records:
Only generationStatus=qualification-ready scenarios with
directLogsIngestionSupported=true may proceed to direct DCR ingestion.
generated-offline-only scenarios remain valid for query harnesses but not
for direct Logs Ingestion API qualification.
After generation or reuse:
sentinel-solution-optional-testing only when the user requests
live qualification;Azure/Azure-Sentinel
2985095
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.