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

FieldRequiredSensitiveDefaultDescription
elasticsearch_urlYesNoYour Elasticsearch URL, for example https://es.example.com:9200. Must be https://.
api_keyYesYesThe API key's encoded value (base64 of id:api_key), as Elasticsearch shows it when the key is created.
ca_certificateNoNoA PEM CA certificate to trust in addition to the system CAs.
tls_verificationNoNofullfull, 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

SettingValue
queryYour ES|QL query. It must return the columns in the SIEM query output contract, named with STATS ... BY, EVAL, RENAME and KEEP.
query_languageesql
lookback_window_secondsApplied 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 10000

Replace 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.


Did this page help you?