Skip to content

Elasticsearch Integration Guide

Arbitex streams audit events to Elasticsearch using the Bulk API. Events are formatted as OCSF v1.1 JSON and written in batches to a configurable index. Both self-managed clusters and Elastic Cloud deployments are supported.


  • An Elasticsearch cluster (v7.10 or later) reachable from Arbitex platform hosts
  • An API key or username/password with create_doc permission on the target index
  • The target index created (or an index template that auto-creates it)
  • Network path open from Arbitex platform pods to the Elasticsearch endpoint on port 9200 (or 443 for Elastic Cloud)
Terminal window
curl -X POST "https://elastic:9200/_security/api_keys" \
-H "Content-Type: application/json" \
-u elastic:$ELASTIC_PASSWORD \
-d '{
"name": "arbitex-siem-ingest",
"role_descriptors": {
"arbitex_writer": {
"cluster": [],
"index": [
{
"names": ["arbitex-ocsf*"],
"privileges": ["create_doc", "create_index"]
}
]
}
}
}'

The response includes an encoded field. Use that value as ELASTIC_API_KEY.


VariableRequiredDefaultDescription
ELASTIC_URLConditionalElasticsearch base URL, e.g. https://elastic.corp.example.com:9200. Required unless ELASTIC_CLOUD_ID is set.
ELASTIC_API_KEYConditionalElasticsearch API key (Base64-encoded id:key). Required unless username/password is used.
ELASTIC_INDEXNoarbitex-ocsfTarget index name
ELASTIC_CLOUD_IDConditionalElastic Cloud deployment ID. Used to resolve the ES URL automatically if ELASTIC_URL is not set.
ELASTIC_USERNAMEConditionalBasic auth username. Used only if ELASTIC_API_KEY is not set.
ELASTIC_PASSWORDConditionalBasic auth password. Used only if ELASTIC_API_KEY is not set.
ELASTIC_BATCH_SIZENo100Maximum events per batch
ELASTIC_FLUSH_INTERVALNo5Maximum seconds between batch flushes
ELASTIC_MAX_RETRIESNo3Maximum retry attempts on transient failures
ELASTIC_DEAD_LETTER_PATHNo/var/log/arbitex/elastic_dead_letter.jsonlPath for the dead letter queue file

Authentication precedence: API key takes priority over username/password. The connector requires at least one auth method. For endpoint resolution: ELASTIC_URL takes priority over ELASTIC_CLOUD_ID.

Terminal window
ELASTIC_URL=https://elastic.corp.example.com:9200
ELASTIC_API_KEY=aWQxa2V5:base64encodedvalue==
ELASTIC_INDEX=arbitex-ocsf
Terminal window
ELASTIC_CLOUD_ID=arbitex-prod:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQ...
ELASTIC_API_KEY=aWQxa2V5:base64encodedvalue==
ELASTIC_INDEX=arbitex-ocsf

Events are sent via the Elasticsearch Bulk API using NDJSON format. Each event generates an action line followed by the document line:

POST https://elastic:9200/_bulk
Authorization: ApiKey {api_key}
Content-Type: application/x-ndjson
{"index": {"_index": "arbitex-ocsf"}}
{"class_uid": 6003, "class_name": "API Activity", "severity": "Informational", "time": 1741737600000, "actor": {"user": {"email_addr": "alice@example.com"}, "org": {"uid": "org_01jq..."}}, "src_endpoint": {"ip": "203.0.113.45"}, ...}
{"index": {"_index": "arbitex-ocsf"}}
{"class_uid": 2001, "class_name": "Security Finding", ...}

The connector treats a Bulk API response with "errors": true as a failure even when the HTTP status code is 200, and routes those events to the dead letter queue.

The connector health check calls GET /_cluster/health. A cluster status of green or yellow is reported as healthy. A status of red is reported as degraded.


Terminal window
curl -s -H "Authorization: Bearer $ADMIN_TOKEN" \
https://api.arbitex.ai/api/admin/siem/connectors | jq '.[] | select(.connector_id == "elastic")'
Terminal window
curl -X GET "https://elastic:9200/arbitex-ocsf/_search" \
-H "Authorization: ApiKey $ELASTIC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": {"range": {"time": {"gte": "now-15m"}}},
"size": 10,
"sort": [{"time": {"order": "desc"}}]
}'

SymptomLikely causeResolution
status: not_configuredNo URL/Cloud ID or no auth setSet ELASTIC_URL (or ELASTIC_CLOUD_ID) and ELASTIC_API_KEY (or username/password)
status: errorCluster unreachableVerify network path and TLS configuration
HTTP 401Invalid API key or credentialsRecreate the API key and update ELASTIC_API_KEY
HTTP 403Insufficient index permissionsVerify the API key role has create_doc on the target index
errors: true in Bulk responseIndex mapping conflictCheck Elasticsearch logs; consider using a new index or updating the index mapping
Cluster status redCluster health issueCheck Elasticsearch cluster health — this is not an Arbitex issue

Dead letter events are written to ELASTIC_DEAD_LETTER_PATH in JSONL format and are not automatically replayed.