x-pack/solutions/security/plugins/security_solution/scripts/data/README.md
generate.ts)This directory contains a fast, lightweight data generator for Elastic Security development/testing.
It generates:
--attacks)
Instead of inventing ECS docs from scratch, this generator starts from real episode NDJSON (captured telemetry) and then:
--start-date → --end-date window-n/--events while rewriting common identity fields (host/user/agent/process IDs) to avoid collisionsEpisode fixtures live here:
x-pack/solutions/security/plugins/security_solution/scripts/data/episodes/attacks/x-pack/solutions/security/plugins/security_solution/scripts/data/episodes/noise/ (false positives / benign-but-suspicious)The episode fixture files under scripts/data/episodes/** are vendored artifacts intended to make Security development/testing fast and deterministic without requiring external downloads.
This script uses the Rule Preview API:
POST /api/detection_engine/rules/preview (API version 2023-10-31)Preview writes alerts into:
.preview.alerts-security.alerts-<spaceId>The generator then copies those canonical alert docs into:
.alerts-security.alerts-<spaceId>This produces alerts that look/behave like real detections (full kibana.alert.* schema).
The generator runs rule preview and then rewrites kibana.alert.rule.* so alerts are attributed to real installed+enabled rules (a set of 15 prebuilt rules, unique by title).
To avoid alerts appearing in large grouped blocks per rule (a common artifact of batch generation), the generator also applies a deterministic per-alert timestamp “jitter” (within your requested time window) while copying preview alerts into .alerts-security.alerts-<spaceId>.
yarn kbn bootstrap)POST /api/detection_engine/index..alerts-security.alerts-<spaceId> does not exist yet, the script will still index raw events/endpoint alerts, but will skip generating/copying Security alerts and log a warning..preview.alerts-security.alerts-* + write to .alerts-security.alerts-*From Kibana repo root:
node x-pack/solutions/security/plugins/security_solution/scripts/data/generate_cli.js \
-n 100 -h 5 -u 5 \
--start-date 1d --end-date now
To also generate synthetic Attack Discoveries (and optionally cases):
node x-pack/solutions/security/plugins/security_solution/scripts/data/generate_cli.js \
-n 100 -h 5 -u 5 \
--start-date 1d --end-date now \
--attacks
node x-pack/solutions/security/plugins/security_solution/scripts/data/generate_cli.js \
-n 100 -h 5 -u 5 \
--start-date 1d --end-date now \
--cases
-n, --events: Number of source events to generate (default: 100)-h, --hosts: Number of hosts to distribute activity across (default: 5)-u, --users: Number of users to distribute activity across (default: 5)--clean: Delete previously generated data created by this script before generating new data (default: false)
--episodes (across the requested date range)
${indexPrefix}.events.*.<YYYY.MM.DD>, ${indexPrefix}.alerts.*.<YYYY.MM.DD>, insights-alerts-*-<YYYY.MM.DD>.alerts-security.alerts-<spaceId>
data-generatorrule_ids (for older generator runs).alerts-security.attack.discovery.alerts-<spaceId> (current).adhoc.alerts-security.attack.discovery.alerts-<spaceId> (legacy; best-effort cleanup)data-generator, plus a narrow legacy fallback)--start-date: Date math start (default: 1d)
now-1d style date math, and a shorthand like 1d (treated as now-1d)--end-date: Date math end (default: now)--episodes: Comma-separated list of episode IDs (default: ep1-ep8,noise1,noise2)
--episodes ep1,ep2,ep3--episodes 1,2,3 (numbers auto-expand to epN)--indexPrefix: Prefix for the endpoint event/alert indices created by this script (default: logs-endpoint)
logs-endpoint.*, set this to something else (e.g. security-solution-data-gen).logs-*-* (for example logs-endpoint-generator), because Elasticsearch can reject creating concrete indices that match data-stream-only templates. Prefer something like logs-endpoint_generator, or keep the default logs-endpoint.--seed: Optional seed string used to make cloning/host-user assignment deterministicRule preview can be the slowest step for large time ranges (e.g. --start-date 60d) because it runs multiple executor invocations per rule.
--max-preview-invocations: Caps rule preview invocations per rule (lower is faster). Default: 12--skip-alerts: Skip rule preview + copying alerts entirely (raw event/endpoint alert indexing only)--skip-alerts also skips Attack Discoveries / Cases (because they depend on Security alerts)--skip-ruleset-preview: Skip previews of the selected prebuilt rules (baseline attribution only; faster)--attacks: Generate synthetic Attack Discoveries (opt-in)--cases: Create Kibana cases from ~50% of generated Attack Discoveries (implies --attacks)
.alerts-security.alerts-<spaceId>)created_at) to a deterministic time within 0–12 hours after the discovery timestamp.
updated_at is intentionally not modified, so Updated on reflects real runtime activity (attachments, edits, etc.).--kibanaUrl (default: http://127.0.0.1:5601)--elasticsearchUrl (default: http://127.0.0.1:9200)--username (default: elastic)--password (default: changeme)--apiKey: Elasticsearch API key (base64, with or without ApiKey prefix). When provided, the script uses API key auth for both Kibana + Elasticsearch.
ES_API_KEY (or ELASTIC_API_KEY) instead of passing --apiKey.--spaceId (optional; defaults to default)episodes/attacks/ and episodes/noise/ (supports .ndjson and .ndjson.gz)YYYY.MM.DD):
epN episodes: ${indexPrefix}.events.insights.epN.<YYYY.MM.DD>${indexPrefix}.events.<episode>.<YYYY.MM.DD>epN episodes: ${indexPrefix}.alerts.insights.epN.<YYYY.MM.DD>${indexPrefix}.alerts.<episode>.<YYYY.MM.DD>insights-alerts-<episode>-<YYYY.MM.DD> (for the Insights-style baseline).alerts-security.alerts-<spaceId> exists)--skip-alerts is set, stops after raw indexing..alerts-security.alerts-<spaceId> doesn’t exist yet, stops after raw indexing (with a warning)..alerts-security.alerts-<spaceId>:--skip-ruleset-preview)kibana.alert.rule.* is rewritten so alerts are attributed to real installed+enabled rules--attacks, or --cases) creates synthetic Attack Discoveries (no LLM) from generated Security alertsPOST /internal/elastic_assistant/data_generator/attack_discoveries/_create.alerts-security.attack.discovery.alerts-<spaceId>@timestamp / kibana.alert.start fall within the requested --start-date → --end-date range.--cases) creates cases from ~50% of generated Attack Discoveries (tagged data-generator)node_modules are incomplete/out of date. Run yarn kbn bootstrap..alerts-security.alerts-<spaceId>):
--indexPrefix that does not match data-stream-only templates (avoid logs-*-* patterns like logs-endpoint-generator).insights-alerts-* indices (the generator writes these for you).