Skip to content

Elastic Security integration

The elastic.notify rule action writes a matched rule alert and its cited fully qualified domain names (FQDNs) to an Elasticsearch data stream as an Elastic Common Schema (ECS) document. It works with Elastic Cloud Hosted, Elastic Cloud Serverless, and self-managed clusters that are reachable from the public internet. Each rule controls which alerts are sent. Connecting Elastic alone does not export alerts.

  1. Choose a data stream. The default, logs-haveibeensquatted.finding-default, matches the built-in logs-*-* index template, so Elasticsearch creates it on first write.
  2. Create an API key limited to that data stream (see Least-privilege API key). Copy the Encoded value.
  3. In the app, open Connectors > Elastic Security.
  4. Enter the deployment or project Cloud ID, or select Elasticsearch endpoint URL and enter the HTTPS endpoint. Enter the data stream and the API key.
  5. Select Save to store the configuration.
  6. Select Test connection to verify the saved configuration and enable export.
  7. Open each intended rule in the rule editor. In the Response tab, select Add action > Notify Elastic Security and choose the configured destination. Save the rule and ensure it is enabled.

Test connection checks, through the has privileges API, that the key holds create_doc on the data stream. It does not write a document, and it does not check that the data stream exists or can be created.

Saving does not test the connection. The saved connection remains inactive until Test connection succeeds. Save any configuration changes before testing. If a test fails, the configuration stays saved and export remains inactive.

The setup page does not display the saved API key. Leave the key blank to keep it when updating the same endpoint. Changing the endpoint or Cloud ID requires entering the key again. You can paste either the encoded key or its id:api_key pair.

Create the key in Kibana (Stack Management > API keys) or with the create API key API. Grant create_doc on the one data stream. Add auto_configure only when Elasticsearch must create the data stream on first write. Without it, create the data stream in advance.

POST /_security/api_key
{
"name": "have-i-been-squatted",
"role_descriptors": {
"haveibeensquatted_writer": {
"indices": [
{
"names": ["logs-haveibeensquatted.finding-default"],
"privileges": ["create_doc", "auto_configure"]
}
]
}
}
}

The key needs no cluster privileges. create_doc only adds documents; it cannot update, delete, or read them.

Delivery originates from Cloudflare Workers that only reach public internet addresses. Elastic Cloud Hosted and Serverless endpoints work without further configuration. A self-managed cluster must expose its HTTPS REST endpoint on a public address, on port 443, 9200, or 9243, with a certificate valid for its host name. Private addresses, IP address endpoints, redirects, and paths such as reverse-proxy prefixes are rejected. A traffic filter or IP allowlist that admits only specific source addresses blocks delivery unless it permits Cloudflare’s IP ranges.

An enabled elastic.notify action sends a matched rule alert only when the Elastic connection is enabled and connected and its destination is enabled. Each alert is written with the bulk API as one create operation whose _id is the rule alert ID (event.id).

  • If the document already exists, Elasticsearch returns a version conflict, which is recorded as delivered. This deduplication holds only within one backing index: after a data stream rolls over, a replay of an older alert can write a second copy.
  • When Elasticsearch throttles the request (HTTP 429, including a throttled bulk item), the document is resent once, after at most ten seconds.
  • A mapping conflict or other rejected document, an authentication or authorization failure, and a missing data stream are recorded as failures and are not retried.
  • If the request fails in transit or Elasticsearch returns a server error, the outcome is unknown and is not resent automatically.

Failures before delivery starts may be retried, but the connector makes no further attempts after delivery starts. A service interruption can therefore lose an export. Historical backfill and automatic replay are not available.

The setup page shows the last connection-test result, never provider response text or the API key.

Each finding becomes one ECS document. url.domain and related.hosts hold the alert’s cited FQDNs, and are omitted when the alert cites none. event.severity and event.risk_score use Elastic Security’s severity bands: informational 0, low 21, medium 47, high 73, critical 99. The unchanged version 1 finding is kept under haveibeensquatted.

{
"@timestamp": "2026-09-24T12:00:00Z",
"ecs": { "version": "8.17.0" },
"message": "Possible impersonation",
"event": {
"kind": "alert",
"category": ["threat"],
"type": ["indicator"],
"id": "d16b752d-3d3b-4e72-bc6f-cfd12112f0b4",
"action": "finding.created",
"created": "2026-09-24T12:00:00Z",
"module": "haveibeensquatted",
"dataset": "haveibeensquatted.finding",
"severity": 73,
"risk_score": 73
},
"rule": {
"id": "1af143cb-34dd-4cac-9c58-2aa0bbd181f0",
"name": "Brand lookalike"
},
"url": { "domain": ["login-example.test", "mail.login-example.test"] },
"related": { "hosts": ["login-example.test", "mail.login-example.test"] },
"observer": {
"vendor": "Have I Been Squatted",
"product": "Have I Been Squatted"
},
"haveibeensquatted": {
"schema_version": 1,
"event_type": "finding.created",
"finding": {
"id": "d16b752d-3d3b-4e72-bc6f-cfd12112f0b4",
"domain_id": "c2b351e1-7bd5-401d-9b42-5c3f3a17542b",
"lookup_id": "1c5804dd-86ec-42c9-bce3-8b456c937936",
"rule_id": "1af143cb-34dd-4cac-9c58-2aa0bbd181f0",
"title": "Possible impersonation",
"name": "Brand lookalike",
"description": null,
"level": "high",
"alert_status": "active",
"created_on_unix": 1790251200,
"fqdns": ["login-example.test", "mail.login-example.test"]
}
}
}

The document sets no data_stream.* fields; Elasticsearch derives them from the data stream name. finding.fqdns is resolved from the alert’s cited source records as described in the Splunk guide. A retrieval failure skips the Elastic action instead of reporting an empty result.