Skip to main content
CMDashCybersecurity Maturity Dashboard
← Back to Elastic Security

Elastic Security — Integration Setup

Note: This guide covers the Elastic Security detection engine — the detection-rule catalog Kibana exposes, which CMDash reads to compute MITRE ATT&CK detection coverage. CMDash does not ingest Elastic alerts/signals or run ES|QL searches through this integration; only rule metadata is read.

Prerequisites

  • An Elastic Stack deployment (Elastic Cloud or self-managed) with the Security solution in use and detection rules created
  • A Kibana endpoint reachable from CMDash's sync workers over the public internet (see the base-URL note in Step 2 — private/internal hostnames are rejected)
  • Ability to create a Kibana API key
  • CMDash Essentials tier or above

Step 1: Create a Kibana API Key

  1. In Kibana, go to Stack Management → Security → API keys → Create API key.
  2. Name it CMDash Integration.
  3. Turn on Control security privileges and give the key a role descriptor whose only Kibana privilege is Security: Read in the space where your detection rules live.
  4. Click Create API key, then copy the Encoded value.

Minimum privileges. The adapter issues exactly one kind of request — GET /api/detection_engine/rules/_find — and never creates, edits, enables, or deletes a rule, and never reads an index. That means no Elasticsearch cluster or index privileges are required: do not grant read on .alerts-security.*, .siem-signals-*, or any data stream for this integration. Kibana Security: Read on the relevant space is sufficient and is the least privilege that works.

Copy the Encoded value, not the raw key. CMDash sends the credential verbatim as Authorization: ApiKey <value>, which is the header form Kibana expects for the base64 id:api_key string. Pasting the raw api_key field instead produces a 401 on every call.

Step 2: Connect in CMDash

  1. Navigate to Integrations in your CMDash dashboard.
  2. Find Elastic Security and click Connect.
  3. Enter:
    • API Key — the encoded Kibana API key from Step 1 (stored as this connection's access token)
    • Configuration (JSON):
      json
      { "baseUrl": "https://my-deployment.kb.us-central1.gcp.cloud.es.io:9243" }
      
  4. Click Connect.

Base URL format — this is the single most common setup failure:

  • Give the Kibana endpoint, not the Elasticsearch endpoint. On Elastic Cloud it is the "Kibana" link on the deployment page (usually https://<deployment>.kb.<region>.<cloud>.cloud.es.io:9243); self-managed it is whatever fronts Kibana, including the port if it is not 443.
  • No trailing path. CMDash appends /api/detection_engine/rules/_find itself. A trailing / is stripped for you; a trailing /api is not, and yields 404.
  • baseUrl is required in practice. If you omit it the adapter falls back to https://localhost:5601, which is rejected outright by CMDash's SSRF guard (URL host not allowed: localhost) — it is a developer default, not a usable value.
  • The host must be public. CMDash validates the URL when you save the connection and again on every request: literal private/reserved addresses, hosts that resolve to them, and .local / .internal / localhost suffixes are all refused. An internal-only Kibana needs a public hostname or reverse proxy.
  • Kibana spaces. The adapter always appends the default-space API path, so only rules in the default space are read. To read another space, include its prefix in the base URL — e.g. https://kibana.example.com/s/soc.

What Syncs

Data TypeKibana APISync Frequency
Detection-rule inventory + each rule's ATT&CK mappingGET {baseUrl}/api/detection_engine/rules/_find?per_page=200&page=NEvery 4 hours by default (configurable per connection)

Each rule's own threat[].technique[].id values (and each technique's nested subtechnique[].id) are read as the rule's ATT&CK mapping — CMDash trusts Elastic's metadata first and guesses nothing. A rule whose technique ids validate becomes one DETECTION_TECHNIQUE maturity observation per technique, at the OBSERVED tier. A rule with no threat mapping, or whose technique ids are all rejected as malformed, is not dropped: it is queued for human review under Maturity → Detection Mapping, where a proposed technique can be approved and becomes an observation of its own.

Both enabled and disabled rules are ingested; the rule's enabled flag is recorded on the observation rather than used as a filter. Rules with neither a rule_id nor an id are skipped and logged. Pagination walks 200 rules per page and stops at 5,000 rules per sync.

Troubleshooting

The connection detail page shows the health check's own message. The health check calls the same _find endpoint with per_page=1, so its message maps directly to what a sync would hit:

  • HTTP 401: The API key was deleted or invalidated, or the raw api_key was pasted instead of the Encoded value (see Step 1).
  • HTTP 403: The key's role descriptor lacks Kibana Security: Read in the space being queried.
  • HTTP 404: The base URL carries an extra path segment (e.g. ends in /api), or the target is not a Kibana endpoint — check you did not paste the Elasticsearch endpoint.
  • URL host not allowed: localhost: baseUrl was left out of the connection config, so the adapter's https://localhost:5601 default was used.
  • URL points to a private/reserved address: … or URL host … resolves to a private/reserved address: The Kibana host is internal-only. CMDash's sync workers cannot reach RFC1918 / link-local / CGNAT addresses by design.
  • Request to <host> timed out: No response within 15 seconds — usually a firewall dropping the connection rather than refusing it.
  • Sync log shows Elastic detection-rules API failed: <status>: The paginated fetch got a non-2xx mid-run; the whole sync attempt fails and is retried.
  • Sync log shows a JSON parse error (e.g. Unexpected end of JSON input): A single 200-rule page exceeded the 5 MiB response cap CMDash's HTTP client enforces and was truncated. Unusually large rule bodies (very long queries or investigation guides) are the cause.
  • Rules sync but ATT&CK coverage does not move: The rules carry no threat[].technique[] mapping. Check Maturity → Detection Mapping — they will be sitting in the review queue.
  • Coverage decays even though the connection is healthy: DETECTION_TECHNIQUE observations decay on a 30-day half-life, so a connection that stops syncing loses credit gradually rather than all at once.

Rate Limits & Sync Behavior

SettingValue
Sync frequencyEvery 4 hours by default (syncInterval, in seconds, is configurable per connection; default 14400)
Pagination cap200 rules per request, 5,000 rules per sync
Response size cap5 MiB per response, enforced by CMDash's SSRF-safe HTTP client
Request timeout15 seconds per request
Rate limit handlingEvery outbound request is paced through CMDash's shared per-tenant token bucket for this provider (300 requests/minute), and a Kibana 429 (with its Retry-After) holds that tenant's budget until the vendor says it is ready (#507)
Circuit breakerNot applied to this adapter — unlike the BAS and identity adapters, repeated Elastic failures are not short-circuited between cycles
Observation freshnessDETECTION_TECHNIQUE observations decay on a 30-day half-life
Failed sync retryJob queue retries 3 times with exponential backoff (starting at 30s) — see docs/developers/dead-letter.md

Credential Rotation

Kibana API keys can be created with an expiration; CMDash stores the key as a non-expiring API-key credential and cannot read Kibana's expiry metadata, so no expiry warning banner is shown for this integration. Track the expiration you set in Kibana separately, and rotate at least quarterly.

To rotate:

  1. In Kibana: Stack Management → Security → API keys, create a replacement key with the same role descriptor.
  2. In CMDash: Settings → Integrations → Elastic Security → Edit.
  3. Enter the new Encoded key value and Save.
  4. Invalidate the old key in Kibana once the connection reports healthy.

Multiple Instances / Multi-Site

Each connection reads exactly one Kibana endpoint and one space. Separate deployments (e.g. production and a regional SOC stack), or separate spaces within one deployment, each need their own CMDash connection.

To add another:

  1. Create a Kibana API key in the additional deployment/space, following Step 1.
  2. In CMDash: Settings → Integrations → Add Integration → Elastic Security.
  3. Enter the API key and a baseUrl pointing at that deployment (including the /s/<space> prefix if it is not the default space).
  4. Give the connection a descriptive name (e.g. Elastic - Prod, Elastic - SOC space).
  5. Click Connect.

Detection coverage from all connections is merged into a single ATT&CK coverage view.

Compliance Framework Coverage

Elastic detection rules are ingested as ATT&CK technique evidence rather than as a direct control attestation, so an individual observation carries no control reference of its own. Detection evidence feeds the Detect function of CMDash's ATT&CK coverage rollup, which is what stamps a control:

FrameworkControlDescription
NIST CSF 2DE.CM-09Computing hardware/software and runtime environment monitoring — Elastic detection rules contribute technique coverage to the Detect-function ATT&CK coverage observation, the anchor control for that function

Detection-rule evidence is deliberately scoped to the Detect function only — it never inflates a Protect, Identify, Respond, Recover, or Govern number. Rules queued in Maturity → Detection Mapping contribute nothing until a proposed technique mapping is approved.

Ready to see your posture?

Start a 30-day free trial of any paid plan — a card is required, and it converts unless you cancel — or sign up for Free with no card at all.