Elastic Security
Vendor key: elastic_security. For how source fields and scan configs fit together, see Agent Discovery Integrations.
Runs your ES|QL query against Elasticsearch over the lookback window. Each row the query returns becomes one discovered agent. Query DSL isn't supported.
Source fields
| Field | Required | Sensitive | Default | Description |
|---|---|---|---|---|
elasticsearch_url | Yes | No | Your Elasticsearch URL, for example https://es.example.com:9200. Must be https://. | |
api_key | Yes | Yes | The API key's encoded value (base64 of id:api_key), as Elasticsearch shows it when the key is created. | |
ca_certificate | No | No | A PEM CA certificate to trust in addition to the system CAs. | |
tls_verification | No | No | full | full, ca_only or off, as for Splunk. ca_only suits Elasticsearch's auto-generated certificate when you connect through a hostname it wasn't issued for. |
Scan config
| Setting | Value |
|---|---|
query | Your ES|QL query. It must return the columns in the SIEM query output contract, named with STATS ... BY, EVAL, RENAME and KEEP. |
query_language | esql |
lookback_window_seconds | Applied as a filter on @timestamp; your query text isn't changed. 0 searches all time. |
Elasticsearch caps an ES|QL result at 1,000 rows by default, or 10,000 with LIMIT 10000. If a result reaches the cap, the scan logs a warning.
Required permissions
The API key needs only read on the indices your query names. No cluster privileges are needed.
Example: self-hosted Kong Gateway
Self-hosted Kong Gateway has no usage API, but if its http-log plugin ships to Elasticsearch and ai-proxy logs statistics (logging.log_statistics: true), this query lists one agent per Kong consumer and the models it used:
FROM kong-ai-logs
| WHERE consumer.id.keyword IS NOT NULL AND ai.proxy.meta.plugin_id.keyword IS NOT NULL
| EVAL model = CASE(
response.status < 400 AND ai.proxy.meta.response_model.keyword IS NOT NULL,
CONCAT(ai.proxy.meta.provider_name.keyword, "/", ai.proxy.meta.response_model.keyword),
NULL)
| STATS last_seen = MAX(@timestamp),
name = MAX(consumer.username.keyword),
llm_models = VALUES(model)
BY consumer_id = consumer.id.keyword
| EVAL external_id = CONCAT("kong:kong:8000:", consumer_id),
name = COALESCE(name, consumer_id),
llm_models = MV_SORT(llm_models)
| KEEP external_id, name, last_seen, llm_models
| SORT external_id
| LIMIT 10000Replace kong-ai-logs with your index and kong:8000 with your Kong proxy's host. Once you've scanned, don't change the external_id prefix: it's each agent's permanent identifier.
Updated 40 minutes ago