diff --git a/.buildkite/scripts/steps/checks/capture_oas_snapshot.sh b/.buildkite/scripts/steps/checks/capture_oas_snapshot.sh
index 8775fe2d3cbfa..27d79d25d6a8c 100755
--- a/.buildkite/scripts/steps/checks/capture_oas_snapshot.sh
+++ b/.buildkite/scripts/steps/checks/capture_oas_snapshot.sh
@@ -21,7 +21,8 @@ cmd="node scripts/capture_oas_snapshot\
--include-path /api/saved_objects/_export \
--include-path /api/maintenance_window \
--include-path /api/agent_builder \
- --include-path /api/workflows"
+ --include-path /api/workflows \
+ --include-path /api/security/entity_store"
run_check() {
eval "$cmd"
diff --git a/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh b/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh
index 5f140efc5db8d..e0937ed299883 100755
--- a/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh
+++ b/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh
@@ -21,4 +21,7 @@ echo -e "\n[Security Solution OpenAPI Code Generation] Endpoint Exceptions Commo
echo -e "\n[Security Solution OpenAPI Code Generation] Security Solution Plugin\n"
(cd x-pack/solutions/security/plugins/security_solution && yarn openapi:generate)
-check_for_changed_files "yarn openapi:generate" true
\ No newline at end of file
+echo -e "\n[Security Solution OpenAPI Code Generation] Entity Store Plugin\n"
+(cd x-pack/solutions/security/plugins/entity_store && yarn openapi:generate)
+
+check_for_changed_files "yarn openapi:generate" true
diff --git a/oas_docs/output/kibana.serverless.yaml b/oas_docs/output/kibana.serverless.yaml
index a497a389f9767..7287e141722a4 100644
--- a/oas_docs/output/kibana.serverless.yaml
+++ b/oas_docs/output/kibana.serverless.yaml
@@ -216,6 +216,7 @@ tags:
Use the Security entity analytics APIs to manage entity analytics and risk scoring, including asset criticality, privileged user monitoring, and entity engines.
name: Security Entity Analytics API
x-displayName: Security entity analytics
+ - name: Security entity store
- description: |
Exceptions are associated with detection and endpoint rules, and are used to prevent a rule from generating an alert from incoming events, even when the rule's other criteria are met. They can help reduce the number of false positives and prevent trusted processes and network activity from generating unnecessary alerts.
@@ -63857,6 +63858,1245 @@ paths:
x-metaTags:
- content: Kibana, Elastic Cloud Serverless
name: product_name
+ /api/security/entity_store:
+ put:
+ description: |-
+ **Spaces method and path for this operation:**
+
+
put /s/{space_id}/api/security/entity_store
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Update the Entity Store log extraction configuration.
[Required authorization] Route required privileges: securitySolution.
+ operationId: put-security-entity-store
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ updateLogExtractionExample:
+ description: Update the log extraction configuration with a new lookback period and frequency.
+ summary: Update log extraction settings
+ value:
+ logExtraction:
+ fieldHistoryLength: 15
+ frequency: 10m
+ lookbackPeriod: 6h
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ updateSuccessExample:
+ description: The Entity Store configuration was successfully updated.
+ summary: Entity Store updated
+ value:
+ ok: true
+ description: Indicates a successful response.
+ '400':
+ content:
+ application/json:
+ examples:
+ invalidDurationExample:
+ description: A log extraction parameter has an invalid duration format.
+ summary: Invalid duration parameter
+ value:
+ error: Bad Request
+ message: '[request body]: logExtraction.frequency: must be a valid duration of at least 30 seconds (e.g. 1m, 30s)'
+ statusCode: 400
+ description: Bad request.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: The Entity Store has not been installed yet.
+ summary: Entity Store not installed
+ value:
+ error: Not Found
+ message: Entity store is not installed
+ statusCode: 404
+ description: Entity Store not found.
+ summary: Update the Entity Store
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"logExtraction":{"lookbackPeriod":"6h","frequency":"10m","fieldHistoryLength":15}}' \
+ "${KIBANA_URL}/api/security/entity_store"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store
+ {
+ "logExtraction": {
+ "lookbackPeriod": "6h",
+ "frequency": "10m",
+ "fieldHistoryLength": 15
+ }
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/entities:
+ get:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ get /s/{space_id}/api/security/entity_store/entities
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ List entity records from the Entity Store with paging, sorting, and filtering. Supports two modes: page-based pagination (page/per_page) and cursor-based pagination (searchAfter). The two modes cannot be combined.
[Required authorization] Route required privileges: securitySolution.
+ operationId: get-security-entity-store-entities
+ parameters: []
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ emptyResultExample:
+ description: No entities matched the query.
+ summary: Empty result
+ value:
+ page: 1
+ per_page: 10
+ records: []
+ total: 0
+ pageModeExample:
+ description: A paginated list of host entities sorted by timestamp in descending order, including query inspection data.
+ summary: Page mode response with host entities
+ value:
+ inspect:
+ dsl:
+ - '{"index":["entities-latest-default"],"body":{"terms":{"entity.EngineMetadata.Type":["host"]}}}'
+ response:
+ - '{"took":1,"timed_out":false,"hits":{"total":{"value":1,"relation":"eq"}}}'
+ page: 1
+ per_page: 10
+ records:
+ - '@timestamp': '2026-04-10T08:30:00.000Z'
+ asset:
+ criticality: high_impact
+ environment: production
+ entity:
+ attributes:
+ asset: true
+ managed: true
+ id: host:web-server-prod-01
+ lifecycle:
+ first_seen: '2026-01-15T10:00:00.000Z'
+ last_activity: '2026-04-10T08:30:00.000Z'
+ name: web-server-prod-01
+ risk:
+ calculated_level: Moderate
+ calculated_score: 47.5
+ calculated_score_norm: 47.5
+ source:
+ - logs
+ type: host
+ host:
+ hostname:
+ - web-server-prod-01.example.com
+ ip:
+ - 10.0.1.42
+ name: web-server-prod-01
+ os:
+ name: Ubuntu
+ type: linux
+ total: 1
+ searchAfterModeExample:
+ description: A cursor-based response with entities and a search_after token for the next page.
+ summary: Search-after mode response
+ value:
+ entities:
+ - '@timestamp': '2026-04-10T08:30:00.000Z'
+ entity:
+ id: user:jane.doe@example.com
+ name: jane.doe
+ type: user
+ user:
+ email:
+ - jane.doe@example.com
+ name: jane.doe
+ nextSearchAfter:
+ - 1712736600000
+ - 1
+ description: Indicates a successful response.
+ '400':
+ content:
+ application/json:
+ examples:
+ invalidFilterExample:
+ description: The provided Kibana Query Language filter could not be parsed.
+ summary: Invalid filter
+ value:
+ error: Bad Request
+ message: |-
+ Invalid filter: Expected "(", "{", value, whitespace but ":" found.
+ invalid :: query
+ ---------^
+ statusCode: 400
+ mixedModesExample:
+ description: Cannot combine page-based pagination with cursor-based pagination in the same request.
+ summary: Mixed pagination modes
+ value:
+ error: Bad Request
+ message: '[request query]: Cannot combine page/per_page with searchAfter'
+ statusCode: 400
+ description: Bad request.
+ summary: List entities
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X GET -H "Authorization: ApiKey ${API_KEY}" \
+ "${KIBANA_URL}/api/security/entity_store/entities?entity_types=host&page=1&per_page=10&sort_field=%40timestamp&sort_order=desc"
+ - lang: Console
+ source: |
+ GET kbn://api/security/entity_store/entities?entity_types=host&page=1&per_page=10&sort_field=@timestamp&sort_order=desc
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/entities/:
+ delete:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ delete /s/{space_id}/api/security/entity_store/entities/
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Delete a single entity record from the Entity Store. The entity is immediately removed from the latest index.
[Required authorization] Route required privileges: securitySolution.
+ operationId: delete-security-entity-store-entities
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ deleteEntityExample:
+ description: Delete a single entity from the Entity Store using its entity identifier.
+ summary: Delete an entity by identifier
+ value:
+ entityId: host:web-server-prod-01
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ deleteSuccessExample:
+ description: The entity was found and successfully removed from the latest index.
+ summary: Entity deleted
+ value:
+ deleted: true
+ description: Indicates the entity was successfully deleted.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: No entity with the specified identifier exists in the Entity Store.
+ summary: Entity not found
+ value:
+ error: Not Found
+ message: Entity ID 'host:web-server-prod-01' not found
+ statusCode: 404
+ description: Entity not found.
+ summary: Delete an entity
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X DELETE -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityId":"host:web-server-prod-01"}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/"
+ - lang: Console
+ source: |
+ DELETE kbn://api/security/entity_store/entities/
+ {
+ "entityId": "host:web-server-prod-01"
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/entities/{entityType}:
+ post:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ post /s/{space_id}/api/security/entity_store/entities/{entityType}
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Create a new entity record in the Entity Store for the specified entity type.
[Required authorization] Route required privileges: securitySolution.
+ operationId: post-security-entity-store-entities-entitytype
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ createHostEntityExample:
+ description: Create a new host entity record with basic host and entity fields. The entity identifier must match the auto-generated format for the entity type.
+ summary: Create a host entity
+ value:
+ asset:
+ business_unit: Engineering
+ criticality: high_impact
+ environment: production
+ entity:
+ attributes:
+ asset: true
+ managed: true
+ id: host:web-server-prod-01
+ name: web-server-prod-01
+ source:
+ - manual
+ type: host
+ host:
+ hostname:
+ - web-server-prod-01.example.com
+ ip:
+ - 10.0.1.42
+ name: web-server-prod-01
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ createSuccessExample:
+ description: The entity record was successfully created in the Entity Store.
+ summary: Entity created
+ value:
+ ok: true
+ description: Indicates the entity was successfully created.
+ '400':
+ content:
+ application/json:
+ examples:
+ euidMismatchExample:
+ description: The supplied entity identifier does not match the auto-generated identifier derived from the entity fields.
+ summary: Entity identifier mismatch
+ value:
+ error: Bad Request
+ message: 'Bad request: Supplied ID my-custom-id does not match generated EUID host:web-server-prod-01'
+ statusCode: 400
+ description: Bad request.
+ '409':
+ content:
+ application/json:
+ examples:
+ conflictExample:
+ description: An entity with the specified identifier already exists.
+ summary: Entity already exists
+ value:
+ error: Conflict
+ message: Entity ID 'host:web-server-prod-01' already exists
+ statusCode: 409
+ description: Conflict.
+ summary: Create an entity
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entity":{"id":"host:web-server-prod-01","name":"web-server-prod-01","type":"host","source":["manual"],"attributes":{"asset":true}},"host":{"name":"web-server-prod-01","ip":["10.0.1.42"]}}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/host"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/entities/host
+ {
+ "entity": {
+ "id": "host:web-server-prod-01",
+ "name": "web-server-prod-01",
+ "type": "host",
+ "source": ["manual"],
+ "attributes": { "asset": true }
+ },
+ "host": {
+ "name": "web-server-prod-01",
+ "ip": ["10.0.1.42"]
+ }
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ put:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ put /s/{space_id}/api/security/entity_store/entities/{entityType}
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Update an existing entity record in the Entity Store. By default only certain fields can be updated. Set the `force` query parameter to `true` to update protected fields.
[Required authorization] Route required privileges: securitySolution.
+ operationId: put-security-entity-store-entities-entitytype
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ updateEntityAttributesExample:
+ description: Update the attributes of an existing user entity. Fields like entity.name and entity.type are protected and require the force query parameter.
+ summary: Update entity attributes
+ value:
+ entity:
+ attributes:
+ managed: true
+ mfa_enabled: true
+ id: user:jane.doe@example.com
+ lifecycle:
+ last_activity: '2026-04-10T14:30:00.000Z'
+ name: jane.doe
+ type: user
+ user:
+ email:
+ - jane.doe@example.com
+ name: jane.doe
+ roles:
+ - admin
+ - analyst
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ updateSuccessExample:
+ description: The entity record was successfully updated.
+ summary: Entity updated
+ value:
+ ok: true
+ description: Indicates the entity was successfully updated.
+ '400':
+ content:
+ application/json:
+ examples:
+ protectedFieldsExample:
+ description: The request attempts to update protected fields without the force query parameter.
+ summary: Protected fields without force
+ value:
+ error: Bad Request
+ message: 'Bad request: The following attributes are not allowed to be updated without forcing it (?force=true): entity.name, entity.type'
+ statusCode: 400
+ description: Bad request.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: No entity with the specified identifier exists.
+ summary: Entity not found
+ value:
+ error: Not Found
+ message: Entity ID 'user:jane.doe@example.com' not found
+ statusCode: 404
+ description: Entity not found.
+ summary: Update an entity
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entity":{"id":"user:jane.doe@example.com","name":"jane.doe","type":"user","attributes":{"managed":true,"mfa_enabled":true}},"user":{"name":"jane.doe"}}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/user?force=true"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/entities/user?force=true
+ {
+ "entity": {
+ "id": "user:jane.doe@example.com",
+ "name": "jane.doe",
+ "type": "user",
+ "attributes": { "managed": true, "mfa_enabled": true }
+ },
+ "user": { "name": "jane.doe" }
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/entities/bulk:
+ put:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ put /s/{space_id}/api/security/entity_store/entities/bulk
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Update multiple entity records in the Entity Store in a single request.
[Required authorization] Route required privileges: securitySolution.
+ operationId: put-security-entity-store-entities-bulk
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ bulkUpdateExample:
+ description: Update a host entity and a user entity in a single request.
+ summary: Bulk update multiple entities
+ value:
+ entities:
+ - doc:
+ entity:
+ attributes:
+ asset: true
+ id: host:web-server-prod-01
+ name: web-server-prod-01
+ type: host
+ host:
+ name: web-server-prod-01
+ type: host
+ - doc:
+ entity:
+ attributes:
+ managed: true
+ id: user:jane.doe@example.com
+ name: jane.doe
+ type: user
+ user:
+ name: jane.doe
+ type: user
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ bulkUpdatePartialExample:
+ description: Some entities were updated but others encountered Elasticsearch-level errors.
+ summary: Partial success with errors
+ value:
+ errors:
+ - _id: 5de9f93a68a72532e736bf5a6184b06300b9cabf
+ reason: '[5de9f93a68a72532e736bf5a6184b06300b9cabf]: document missing'
+ status: 404
+ type: document_missing_exception
+ ok: true
+ bulkUpdateSuccessExample:
+ description: All entities were successfully updated with no errors.
+ summary: All entities updated
+ value:
+ errors: []
+ ok: true
+ description: Indicates a successful response.
+ '400':
+ content:
+ application/json:
+ examples:
+ protectedFieldsExample:
+ description: The request attempts to update protected fields without the force query parameter.
+ summary: Protected fields without force
+ value:
+ error: Bad Request
+ message: 'Bad request: The following attributes are not allowed to be updated without forcing it (?force=true): entity.name, entity.type'
+ statusCode: 400
+ description: Bad request.
+ summary: Bulk update entities
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entities":[{"type":"host","doc":{"entity":{"id":"host:web-server-prod-01","name":"web-server-prod-01","type":"host","attributes":{"asset":true}},"host":{"name":"web-server-prod-01"}}}]}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/bulk?force=true"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/entities/bulk?force=true
+ {
+ "entities": [
+ {
+ "type": "host",
+ "doc": {
+ "entity": {
+ "id": "host:web-server-prod-01",
+ "name": "web-server-prod-01",
+ "type": "host",
+ "attributes": { "asset": true }
+ },
+ "host": { "name": "web-server-prod-01" }
+ }
+ }
+ ]
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/install:
+ post:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ post /s/{space_id}/api/security/entity_store/install
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Install the Entity Store, creating engines for the specified entity types and configuring log extraction.
[Required authorization] Route required privileges: securitySolution.
+ operationId: post-security-entity-store-install
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ installDefaultExample:
+ description: Install the Entity Store for all entity types with default log extraction settings.
+ summary: Install with default entity types
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ logExtraction: {}
+ installWithCustomSettingsExample:
+ description: Install the Entity Store for host entities only with a custom lookback period and field history length.
+ summary: Install with custom log extraction
+ value:
+ entityTypes:
+ - host
+ logExtraction:
+ delay: 2m
+ fieldHistoryLength: 20
+ filter: 'host.os.type: linux'
+ frequency: 5m
+ lookbackPeriod: 12h
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ alreadyInstalledExample:
+ description: All requested entity types were already installed.
+ summary: Already installed
+ value:
+ ok: true
+ description: Indicates all requested entity types are already installed.
+ '201':
+ content:
+ application/json:
+ examples:
+ installSuccessExample:
+ description: The Entity Store was installed and engines are being created.
+ summary: Entity Store installed
+ value:
+ ok: true
+ description: Indicates the Entity Store was successfully installed.
+ '403':
+ content:
+ application/json:
+ examples:
+ forbiddenExample:
+ description: The user does not have the required Elasticsearch privileges.
+ summary: Insufficient privileges
+ value:
+ error: Forbidden
+ message: User 'analyst' has insufficient privileges
+ statusCode: 403
+ description: Insufficient privileges.
+ summary: Install the Entity Store
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"],"logExtraction":{}}' \
+ "${KIBANA_URL}/api/security/entity_store/install"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/install
+ {
+ "entityTypes": ["user", "host", "service", "generic"],
+ "logExtraction": {}
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/resolution/group:
+ get:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ get /s/{space_id}/api/security/entity_store/resolution/group
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Get the resolution group for a given entity, returning all linked entities. Requires an enterprise license.
[Required authorization] Route required privileges: securitySolution AND securitySolution-entity-analytics.
+ operationId: get-security-entity-store-resolution-group
+ parameters: []
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ resolutionGroupExample:
+ description: Returns the resolution group for an entity, including the target entity, all aliases, and the group size.
+ summary: Resolution group with linked entities
+ value:
+ aliases:
+ - '@timestamp': '2026-04-10T08:25:00.000Z'
+ entity:
+ id: user:jdoe@example.com
+ name: jdoe
+ relationships:
+ resolution:
+ resolved_to: user:jane.doe@example.com
+ type: user
+ user:
+ name: jdoe
+ group_size: 2
+ target:
+ '@timestamp': '2026-04-10T08:30:00.000Z'
+ entity:
+ id: user:jane.doe@example.com
+ name: jane.doe
+ type: user
+ user:
+ email:
+ - jane.doe@example.com
+ name: jane.doe
+ description: Indicates a successful response.
+ '400':
+ content:
+ application/json:
+ examples:
+ truncatedSearchExample:
+ description: The resolution search returned too many results and was truncated.
+ summary: Search results truncated
+ value:
+ error: Bad Request
+ message: Resolution search truncated
+ statusCode: 400
+ description: Bad request.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: The specified entity does not exist or has no resolution group.
+ summary: Entity not found
+ value:
+ error: Not Found
+ message: 'Entities not found: [user:nonexistent@example.com]'
+ statusCode: 404
+ description: Entity not found.
+ summary: Get resolution group
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X GET -H "Authorization: ApiKey ${API_KEY}" \
+ "${KIBANA_URL}/api/security/entity_store/resolution/group?entity_id=user%3Ajane.doe%40example.com"
+ - lang: Console
+ source: |
+ GET kbn://api/security/entity_store/resolution/group?entity_id=user:jane.doe@example.com
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/resolution/link:
+ post:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ post /s/{space_id}/api/security/entity_store/resolution/link
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Link one or more entities to a target entity, creating a resolution group. Requires an enterprise license.
[Required authorization] Route required privileges: securitySolution AND securitySolution-entity-analytics.
+ operationId: post-security-entity-store-resolution-link
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ linkEntitiesExample:
+ description: Link two user entities to a target entity, creating a resolution group.
+ summary: Link entities to a target
+ value:
+ entity_ids:
+ - user:jdoe@example.com
+ - user:j.doe@example.com
+ target_id: user:jane.doe@example.com
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ linkSuccessExample:
+ description: The entities were successfully linked to the target entity.
+ summary: Entities linked
+ value:
+ linked:
+ - user:jdoe@example.com
+ - user:j.doe@example.com
+ skipped: []
+ target_id: user:jane.doe@example.com
+ description: Indicates a successful response.
+ '400':
+ content:
+ application/json:
+ examples:
+ mixedTypesExample:
+ description: All entities in a resolution group must be of the same type.
+ summary: Mixed entity types
+ value:
+ error: Bad Request
+ message: Cannot link entities of different types
+ statusCode: 400
+ selfLinkExample:
+ description: Cannot link an entity to itself.
+ summary: Self-link error
+ value:
+ error: Bad Request
+ message: Cannot link entity 'user:jane.doe@example.com' to itself.
+ statusCode: 400
+ description: Bad request.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: One or more of the specified entity identifiers were not found.
+ summary: Entities not found
+ value:
+ error: Not Found
+ message: 'Entities not found: [user:nonexistent@example.com, user:also-nonexistent@example.com]'
+ statusCode: 404
+ description: Entities not found.
+ summary: Link entities
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"target_id":"user:jane.doe@example.com","entity_ids":["user:jdoe@example.com"]}' \
+ "${KIBANA_URL}/api/security/entity_store/resolution/link"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/resolution/link
+ {
+ "target_id": "user:jane.doe@example.com",
+ "entity_ids": ["user:jdoe@example.com"]
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/resolution/unlink:
+ post:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ post /s/{space_id}/api/security/entity_store/resolution/unlink
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Remove one or more entities from their resolution group. Requires an enterprise license.
[Required authorization] Route required privileges: securitySolution AND securitySolution-entity-analytics.
+ operationId: post-security-entity-store-resolution-unlink
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ unlinkEntitiesExample:
+ description: Remove entities from their resolution group, restoring them as standalone entities.
+ summary: Unlink entities from their resolution group
+ value:
+ entity_ids:
+ - user:jdoe@example.com
+ - user:j.doe@example.com
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ unlinkSuccessExample:
+ description: The entities were successfully removed from their resolution group.
+ summary: Entities unlinked
+ value:
+ skipped: []
+ unlinked:
+ - user:jdoe@example.com
+ - user:j.doe@example.com
+ description: Indicates a successful response.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: One or more of the specified entity identifiers were not found.
+ summary: Entities not found
+ value:
+ error: Not Found
+ message: 'Entities not found: [user:nonexistent@example.com]'
+ statusCode: 404
+ description: Entities not found.
+ summary: Unlink entities
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entity_ids":["user:jdoe@example.com"]}' \
+ "${KIBANA_URL}/api/security/entity_store/resolution/unlink"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/resolution/unlink
+ {
+ "entity_ids": ["user:jdoe@example.com"]
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/start:
+ put:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ put /s/{space_id}/api/security/entity_store/start
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Start previously stopped entity engines, resuming data processing for the specified entity types.
[Required authorization] Route required privileges: securitySolution.
+ operationId: put-security-entity-store-start
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ startAllExample:
+ description: Start all stopped entity engines.
+ summary: Start all entity engines
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ startSingleExample:
+ description: Start only the host entity engine.
+ summary: Start a single entity engine
+ value:
+ entityTypes:
+ - host
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ startSuccessExample:
+ description: The specified entity engines were successfully started.
+ summary: Engines started
+ value:
+ ok: true
+ description: Indicates a successful response.
+ summary: Start Entity Store engines
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"]}' \
+ "${KIBANA_URL}/api/security/entity_store/start"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/start
+ {
+ "entityTypes": ["user", "host", "service", "generic"]
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/status:
+ get:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ get /s/{space_id}/api/security/entity_store/status
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Get the overall Entity Store status and per-engine statuses, optionally including component-level health details.
[Required authorization] Route required privileges: securitySolution.
+ operationId: get-security-entity-store-status
+ parameters: []
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ notInstalledExample:
+ description: The Entity Store has not been installed.
+ summary: Entity Store not installed
+ value:
+ engines: []
+ status: not_installed
+ runningStatusExample:
+ description: The Entity Store is running with two started engines using default settings.
+ summary: Entity Store running
+ value:
+ engines:
+ - delay: 1m
+ docsPerSecond: -1
+ enrichPolicyExecutionInterval: null
+ fieldHistoryLength: 10
+ filter: ''
+ frequency: 30s
+ indexPattern: ''
+ lastExecutionTimestamp: '2026-04-10T08:30:00.000Z'
+ lookbackPeriod: 3h
+ maxPageSearchSize: 10000
+ status: started
+ timeout: 25s
+ timestampField: '@timestamp'
+ type: host
+ - delay: 1m
+ docsPerSecond: -1
+ enrichPolicyExecutionInterval: null
+ fieldHistoryLength: 10
+ filter: ''
+ frequency: 30s
+ indexPattern: ''
+ lastExecutionTimestamp: '2026-04-10T08:30:00.000Z'
+ lookbackPeriod: 3h
+ maxPageSearchSize: 10000
+ status: started
+ timeout: 25s
+ timestampField: '@timestamp'
+ type: user
+ status: running
+ description: Indicates a successful response.
+ summary: Get Entity Store status
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X GET -H "Authorization: ApiKey ${API_KEY}" \
+ "${KIBANA_URL}/api/security/entity_store/status?include_components=false"
+ - lang: Console
+ source: |
+ GET kbn://api/security/entity_store/status?include_components=false
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/stop:
+ put:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ put /s/{space_id}/api/security/entity_store/stop
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Stop running entity engines, pausing data processing for the specified entity types.
[Required authorization] Route required privileges: securitySolution.
+ operationId: put-security-entity-store-stop
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ stopAllExample:
+ description: Stop all running entity engines.
+ summary: Stop all entity engines
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ stopSuccessExample:
+ description: The specified entity engines were successfully stopped.
+ summary: Engines stopped
+ value:
+ ok: true
+ description: Indicates a successful response.
+ summary: Stop Entity Store engines
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"]}' \
+ "${KIBANA_URL}/api/security/entity_store/stop"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/stop
+ {
+ "entityTypes": ["user", "host", "service", "generic"]
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
+ /api/security/entity_store/uninstall:
+ post:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ post /s/{space_id}/api/security/entity_store/uninstall
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Uninstall the Entity Store, removing engines and associated resources for the specified entity types.
[Required authorization] Route required privileges: securitySolution.
+ operationId: post-security-entity-store-uninstall
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ uninstallAllExample:
+ description: Uninstall all entity engines from the Entity Store.
+ summary: Uninstall all entity types
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ uninstallSingleExample:
+ description: Uninstall only the host engine from the Entity Store.
+ summary: Uninstall a single entity type
+ value:
+ entityTypes:
+ - host
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ uninstallSuccessExample:
+ description: The specified entity engines were successfully uninstalled.
+ summary: Entity Store uninstalled
+ value:
+ ok: true
+ description: Indicates a successful response.
+ summary: Uninstall the Entity Store
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"]}' \
+ "${KIBANA_URL}/api/security/entity_store/uninstall"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/uninstall
+ {
+ "entityTypes": ["user", "host", "service", "generic"]
+ }
+ x-metaTags:
+ - content: Kibana, Elastic Cloud Serverless
+ name: product_name
/api/security/role:
get:
operationId: get-security-role
diff --git a/oas_docs/output/kibana.yaml b/oas_docs/output/kibana.yaml
index fcc989659c70e..5831068ae28c0 100644
--- a/oas_docs/output/kibana.yaml
+++ b/oas_docs/output/kibana.yaml
@@ -255,6 +255,7 @@ tags:
Use the Security entity analytics APIs to manage entity analytics and risk scoring, including asset criticality, privileged user monitoring, and entity engines.
name: Security Entity Analytics API
x-displayName: Security entity analytics
+ - name: Security entity store
- description: |
Exceptions are associated with detection and endpoint rules, and are used to prevent a rule from generating an alert from incoming events, even when the rule's other criteria are met. They can help reduce the number of false positives and prevent trusted processes and network activity from generating unnecessary alerts.
@@ -67701,6 +67702,1245 @@ paths:
x-metaTags:
- content: Kibana
name: product_name
+ /api/security/entity_store:
+ put:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ put /s/{space_id}/api/security/entity_store
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Update the Entity Store log extraction configuration.
[Required authorization] Route required privileges: securitySolution.
+ operationId: put-security-entity-store
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ updateLogExtractionExample:
+ description: Update the log extraction configuration with a new lookback period and frequency.
+ summary: Update log extraction settings
+ value:
+ logExtraction:
+ fieldHistoryLength: 15
+ frequency: 10m
+ lookbackPeriod: 6h
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ updateSuccessExample:
+ description: The Entity Store configuration was successfully updated.
+ summary: Entity Store updated
+ value:
+ ok: true
+ description: Indicates a successful response.
+ '400':
+ content:
+ application/json:
+ examples:
+ invalidDurationExample:
+ description: A log extraction parameter has an invalid duration format.
+ summary: Invalid duration parameter
+ value:
+ error: Bad Request
+ message: '[request body]: logExtraction.frequency: must be a valid duration of at least 30 seconds (e.g. 1m, 30s)'
+ statusCode: 400
+ description: Bad request.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: The Entity Store has not been installed yet.
+ summary: Entity Store not installed
+ value:
+ error: Not Found
+ message: Entity store is not installed
+ statusCode: 404
+ description: Entity Store not found.
+ summary: Update the Entity Store
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"logExtraction":{"lookbackPeriod":"6h","frequency":"10m","fieldHistoryLength":15}}' \
+ "${KIBANA_URL}/api/security/entity_store"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store
+ {
+ "logExtraction": {
+ "lookbackPeriod": "6h",
+ "frequency": "10m",
+ "fieldHistoryLength": 15
+ }
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/entities:
+ get:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ get /s/{space_id}/api/security/entity_store/entities
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ List entity records from the Entity Store with paging, sorting, and filtering. Supports two modes: page-based pagination (page/per_page) and cursor-based pagination (searchAfter). The two modes cannot be combined.
[Required authorization] Route required privileges: securitySolution.
+ operationId: get-security-entity-store-entities
+ parameters: []
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ emptyResultExample:
+ description: No entities matched the query.
+ summary: Empty result
+ value:
+ page: 1
+ per_page: 10
+ records: []
+ total: 0
+ pageModeExample:
+ description: A paginated list of host entities sorted by timestamp in descending order, including query inspection data.
+ summary: Page mode response with host entities
+ value:
+ inspect:
+ dsl:
+ - '{"index":["entities-latest-default"],"body":{"terms":{"entity.EngineMetadata.Type":["host"]}}}'
+ response:
+ - '{"took":1,"timed_out":false,"hits":{"total":{"value":1,"relation":"eq"}}}'
+ page: 1
+ per_page: 10
+ records:
+ - '@timestamp': '2026-04-10T08:30:00.000Z'
+ asset:
+ criticality: high_impact
+ environment: production
+ entity:
+ attributes:
+ asset: true
+ managed: true
+ id: host:web-server-prod-01
+ lifecycle:
+ first_seen: '2026-01-15T10:00:00.000Z'
+ last_activity: '2026-04-10T08:30:00.000Z'
+ name: web-server-prod-01
+ risk:
+ calculated_level: Moderate
+ calculated_score: 47.5
+ calculated_score_norm: 47.5
+ source:
+ - logs
+ type: host
+ host:
+ hostname:
+ - web-server-prod-01.example.com
+ ip:
+ - 10.0.1.42
+ name: web-server-prod-01
+ os:
+ name: Ubuntu
+ type: linux
+ total: 1
+ searchAfterModeExample:
+ description: A cursor-based response with entities and a search_after token for the next page.
+ summary: Search-after mode response
+ value:
+ entities:
+ - '@timestamp': '2026-04-10T08:30:00.000Z'
+ entity:
+ id: user:jane.doe@example.com
+ name: jane.doe
+ type: user
+ user:
+ email:
+ - jane.doe@example.com
+ name: jane.doe
+ nextSearchAfter:
+ - 1712736600000
+ - 1
+ description: Indicates a successful response.
+ '400':
+ content:
+ application/json:
+ examples:
+ invalidFilterExample:
+ description: The provided Kibana Query Language filter could not be parsed.
+ summary: Invalid filter
+ value:
+ error: Bad Request
+ message: |-
+ Invalid filter: Expected "(", "{", value, whitespace but ":" found.
+ invalid :: query
+ ---------^
+ statusCode: 400
+ mixedModesExample:
+ description: Cannot combine page-based pagination with cursor-based pagination in the same request.
+ summary: Mixed pagination modes
+ value:
+ error: Bad Request
+ message: '[request query]: Cannot combine page/per_page with searchAfter'
+ statusCode: 400
+ description: Bad request.
+ summary: List entities
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X GET -H "Authorization: ApiKey ${API_KEY}" \
+ "${KIBANA_URL}/api/security/entity_store/entities?entity_types=host&page=1&per_page=10&sort_field=%40timestamp&sort_order=desc"
+ - lang: Console
+ source: |
+ GET kbn://api/security/entity_store/entities?entity_types=host&page=1&per_page=10&sort_field=@timestamp&sort_order=desc
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/entities/:
+ delete:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ delete /s/{space_id}/api/security/entity_store/entities/
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Delete a single entity record from the Entity Store. The entity is immediately removed from the latest index.
[Required authorization] Route required privileges: securitySolution.
+ operationId: delete-security-entity-store-entities
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ deleteEntityExample:
+ description: Delete a single entity from the Entity Store using its entity identifier.
+ summary: Delete an entity by identifier
+ value:
+ entityId: host:web-server-prod-01
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ deleteSuccessExample:
+ description: The entity was found and successfully removed from the latest index.
+ summary: Entity deleted
+ value:
+ deleted: true
+ description: Indicates the entity was successfully deleted.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: No entity with the specified identifier exists in the Entity Store.
+ summary: Entity not found
+ value:
+ error: Not Found
+ message: Entity ID 'host:web-server-prod-01' not found
+ statusCode: 404
+ description: Entity not found.
+ summary: Delete an entity
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X DELETE -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityId":"host:web-server-prod-01"}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/"
+ - lang: Console
+ source: |
+ DELETE kbn://api/security/entity_store/entities/
+ {
+ "entityId": "host:web-server-prod-01"
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/entities/{entityType}:
+ post:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ post /s/{space_id}/api/security/entity_store/entities/{entityType}
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Create a new entity record in the Entity Store for the specified entity type.
[Required authorization] Route required privileges: securitySolution.
+ operationId: post-security-entity-store-entities-entitytype
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ createHostEntityExample:
+ description: Create a new host entity record with basic host and entity fields. The entity identifier must match the auto-generated format for the entity type.
+ summary: Create a host entity
+ value:
+ asset:
+ business_unit: Engineering
+ criticality: high_impact
+ environment: production
+ entity:
+ attributes:
+ asset: true
+ managed: true
+ id: host:web-server-prod-01
+ name: web-server-prod-01
+ source:
+ - manual
+ type: host
+ host:
+ hostname:
+ - web-server-prod-01.example.com
+ ip:
+ - 10.0.1.42
+ name: web-server-prod-01
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ createSuccessExample:
+ description: The entity record was successfully created in the Entity Store.
+ summary: Entity created
+ value:
+ ok: true
+ description: Indicates the entity was successfully created.
+ '400':
+ content:
+ application/json:
+ examples:
+ euidMismatchExample:
+ description: The supplied entity identifier does not match the auto-generated identifier derived from the entity fields.
+ summary: Entity identifier mismatch
+ value:
+ error: Bad Request
+ message: 'Bad request: Supplied ID my-custom-id does not match generated EUID host:web-server-prod-01'
+ statusCode: 400
+ description: Bad request.
+ '409':
+ content:
+ application/json:
+ examples:
+ conflictExample:
+ description: An entity with the specified identifier already exists.
+ summary: Entity already exists
+ value:
+ error: Conflict
+ message: Entity ID 'host:web-server-prod-01' already exists
+ statusCode: 409
+ description: Conflict.
+ summary: Create an entity
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entity":{"id":"host:web-server-prod-01","name":"web-server-prod-01","type":"host","source":["manual"],"attributes":{"asset":true}},"host":{"name":"web-server-prod-01","ip":["10.0.1.42"]}}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/host"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/entities/host
+ {
+ "entity": {
+ "id": "host:web-server-prod-01",
+ "name": "web-server-prod-01",
+ "type": "host",
+ "source": ["manual"],
+ "attributes": { "asset": true }
+ },
+ "host": {
+ "name": "web-server-prod-01",
+ "ip": ["10.0.1.42"]
+ }
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ put:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ put /s/{space_id}/api/security/entity_store/entities/{entityType}
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Update an existing entity record in the Entity Store. By default only certain fields can be updated. Set the `force` query parameter to `true` to update protected fields.
[Required authorization] Route required privileges: securitySolution.
+ operationId: put-security-entity-store-entities-entitytype
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ updateEntityAttributesExample:
+ description: Update the attributes of an existing user entity. Fields like entity.name and entity.type are protected and require the force query parameter.
+ summary: Update entity attributes
+ value:
+ entity:
+ attributes:
+ managed: true
+ mfa_enabled: true
+ id: user:jane.doe@example.com
+ lifecycle:
+ last_activity: '2026-04-10T14:30:00.000Z'
+ name: jane.doe
+ type: user
+ user:
+ email:
+ - jane.doe@example.com
+ name: jane.doe
+ roles:
+ - admin
+ - analyst
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ updateSuccessExample:
+ description: The entity record was successfully updated.
+ summary: Entity updated
+ value:
+ ok: true
+ description: Indicates the entity was successfully updated.
+ '400':
+ content:
+ application/json:
+ examples:
+ protectedFieldsExample:
+ description: The request attempts to update protected fields without the force query parameter.
+ summary: Protected fields without force
+ value:
+ error: Bad Request
+ message: 'Bad request: The following attributes are not allowed to be updated without forcing it (?force=true): entity.name, entity.type'
+ statusCode: 400
+ description: Bad request.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: No entity with the specified identifier exists.
+ summary: Entity not found
+ value:
+ error: Not Found
+ message: Entity ID 'user:jane.doe@example.com' not found
+ statusCode: 404
+ description: Entity not found.
+ summary: Update an entity
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entity":{"id":"user:jane.doe@example.com","name":"jane.doe","type":"user","attributes":{"managed":true,"mfa_enabled":true}},"user":{"name":"jane.doe"}}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/user?force=true"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/entities/user?force=true
+ {
+ "entity": {
+ "id": "user:jane.doe@example.com",
+ "name": "jane.doe",
+ "type": "user",
+ "attributes": { "managed": true, "mfa_enabled": true }
+ },
+ "user": { "name": "jane.doe" }
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/entities/bulk:
+ put:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ put /s/{space_id}/api/security/entity_store/entities/bulk
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Update multiple entity records in the Entity Store in a single request.
[Required authorization] Route required privileges: securitySolution.
+ operationId: put-security-entity-store-entities-bulk
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ bulkUpdateExample:
+ description: Update a host entity and a user entity in a single request.
+ summary: Bulk update multiple entities
+ value:
+ entities:
+ - doc:
+ entity:
+ attributes:
+ asset: true
+ id: host:web-server-prod-01
+ name: web-server-prod-01
+ type: host
+ host:
+ name: web-server-prod-01
+ type: host
+ - doc:
+ entity:
+ attributes:
+ managed: true
+ id: user:jane.doe@example.com
+ name: jane.doe
+ type: user
+ user:
+ name: jane.doe
+ type: user
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ bulkUpdatePartialExample:
+ description: Some entities were updated but others encountered Elasticsearch-level errors.
+ summary: Partial success with errors
+ value:
+ errors:
+ - _id: 5de9f93a68a72532e736bf5a6184b06300b9cabf
+ reason: '[5de9f93a68a72532e736bf5a6184b06300b9cabf]: document missing'
+ status: 404
+ type: document_missing_exception
+ ok: true
+ bulkUpdateSuccessExample:
+ description: All entities were successfully updated with no errors.
+ summary: All entities updated
+ value:
+ errors: []
+ ok: true
+ description: Indicates a successful response.
+ '400':
+ content:
+ application/json:
+ examples:
+ protectedFieldsExample:
+ description: The request attempts to update protected fields without the force query parameter.
+ summary: Protected fields without force
+ value:
+ error: Bad Request
+ message: 'Bad request: The following attributes are not allowed to be updated without forcing it (?force=true): entity.name, entity.type'
+ statusCode: 400
+ description: Bad request.
+ summary: Bulk update entities
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entities":[{"type":"host","doc":{"entity":{"id":"host:web-server-prod-01","name":"web-server-prod-01","type":"host","attributes":{"asset":true}},"host":{"name":"web-server-prod-01"}}}]}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/bulk?force=true"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/entities/bulk?force=true
+ {
+ "entities": [
+ {
+ "type": "host",
+ "doc": {
+ "entity": {
+ "id": "host:web-server-prod-01",
+ "name": "web-server-prod-01",
+ "type": "host",
+ "attributes": { "asset": true }
+ },
+ "host": { "name": "web-server-prod-01" }
+ }
+ }
+ ]
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/install:
+ post:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ post /s/{space_id}/api/security/entity_store/install
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Install the Entity Store, creating engines for the specified entity types and configuring log extraction.
[Required authorization] Route required privileges: securitySolution.
+ operationId: post-security-entity-store-install
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ installDefaultExample:
+ description: Install the Entity Store for all entity types with default log extraction settings.
+ summary: Install with default entity types
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ logExtraction: {}
+ installWithCustomSettingsExample:
+ description: Install the Entity Store for host entities only with a custom lookback period and field history length.
+ summary: Install with custom log extraction
+ value:
+ entityTypes:
+ - host
+ logExtraction:
+ delay: 2m
+ fieldHistoryLength: 20
+ filter: 'host.os.type: linux'
+ frequency: 5m
+ lookbackPeriod: 12h
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ alreadyInstalledExample:
+ description: All requested entity types were already installed.
+ summary: Already installed
+ value:
+ ok: true
+ description: Indicates all requested entity types are already installed.
+ '201':
+ content:
+ application/json:
+ examples:
+ installSuccessExample:
+ description: The Entity Store was installed and engines are being created.
+ summary: Entity Store installed
+ value:
+ ok: true
+ description: Indicates the Entity Store was successfully installed.
+ '403':
+ content:
+ application/json:
+ examples:
+ forbiddenExample:
+ description: The user does not have the required Elasticsearch privileges.
+ summary: Insufficient privileges
+ value:
+ error: Forbidden
+ message: User 'analyst' has insufficient privileges
+ statusCode: 403
+ description: Insufficient privileges.
+ summary: Install the Entity Store
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"],"logExtraction":{}}' \
+ "${KIBANA_URL}/api/security/entity_store/install"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/install
+ {
+ "entityTypes": ["user", "host", "service", "generic"],
+ "logExtraction": {}
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/resolution/group:
+ get:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ get /s/{space_id}/api/security/entity_store/resolution/group
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Get the resolution group for a given entity, returning all linked entities. Requires an enterprise license.
[Required authorization] Route required privileges: securitySolution AND securitySolution-entity-analytics.
+ operationId: get-security-entity-store-resolution-group
+ parameters: []
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ resolutionGroupExample:
+ description: Returns the resolution group for an entity, including the target entity, all aliases, and the group size.
+ summary: Resolution group with linked entities
+ value:
+ aliases:
+ - '@timestamp': '2026-04-10T08:25:00.000Z'
+ entity:
+ id: user:jdoe@example.com
+ name: jdoe
+ relationships:
+ resolution:
+ resolved_to: user:jane.doe@example.com
+ type: user
+ user:
+ name: jdoe
+ group_size: 2
+ target:
+ '@timestamp': '2026-04-10T08:30:00.000Z'
+ entity:
+ id: user:jane.doe@example.com
+ name: jane.doe
+ type: user
+ user:
+ email:
+ - jane.doe@example.com
+ name: jane.doe
+ description: Indicates a successful response.
+ '400':
+ content:
+ application/json:
+ examples:
+ truncatedSearchExample:
+ description: The resolution search returned too many results and was truncated.
+ summary: Search results truncated
+ value:
+ error: Bad Request
+ message: Resolution search truncated
+ statusCode: 400
+ description: Bad request.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: The specified entity does not exist or has no resolution group.
+ summary: Entity not found
+ value:
+ error: Not Found
+ message: 'Entities not found: [user:nonexistent@example.com]'
+ statusCode: 404
+ description: Entity not found.
+ summary: Get resolution group
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X GET -H "Authorization: ApiKey ${API_KEY}" \
+ "${KIBANA_URL}/api/security/entity_store/resolution/group?entity_id=user%3Ajane.doe%40example.com"
+ - lang: Console
+ source: |
+ GET kbn://api/security/entity_store/resolution/group?entity_id=user:jane.doe@example.com
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/resolution/link:
+ post:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ post /s/{space_id}/api/security/entity_store/resolution/link
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Link one or more entities to a target entity, creating a resolution group. Requires an enterprise license.
[Required authorization] Route required privileges: securitySolution AND securitySolution-entity-analytics.
+ operationId: post-security-entity-store-resolution-link
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ linkEntitiesExample:
+ description: Link two user entities to a target entity, creating a resolution group.
+ summary: Link entities to a target
+ value:
+ entity_ids:
+ - user:jdoe@example.com
+ - user:j.doe@example.com
+ target_id: user:jane.doe@example.com
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ linkSuccessExample:
+ description: The entities were successfully linked to the target entity.
+ summary: Entities linked
+ value:
+ linked:
+ - user:jdoe@example.com
+ - user:j.doe@example.com
+ skipped: []
+ target_id: user:jane.doe@example.com
+ description: Indicates a successful response.
+ '400':
+ content:
+ application/json:
+ examples:
+ mixedTypesExample:
+ description: All entities in a resolution group must be of the same type.
+ summary: Mixed entity types
+ value:
+ error: Bad Request
+ message: Cannot link entities of different types
+ statusCode: 400
+ selfLinkExample:
+ description: Cannot link an entity to itself.
+ summary: Self-link error
+ value:
+ error: Bad Request
+ message: Cannot link entity 'user:jane.doe@example.com' to itself.
+ statusCode: 400
+ description: Bad request.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: One or more of the specified entity identifiers were not found.
+ summary: Entities not found
+ value:
+ error: Not Found
+ message: 'Entities not found: [user:nonexistent@example.com, user:also-nonexistent@example.com]'
+ statusCode: 404
+ description: Entities not found.
+ summary: Link entities
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"target_id":"user:jane.doe@example.com","entity_ids":["user:jdoe@example.com"]}' \
+ "${KIBANA_URL}/api/security/entity_store/resolution/link"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/resolution/link
+ {
+ "target_id": "user:jane.doe@example.com",
+ "entity_ids": ["user:jdoe@example.com"]
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/resolution/unlink:
+ post:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ post /s/{space_id}/api/security/entity_store/resolution/unlink
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Remove one or more entities from their resolution group. Requires an enterprise license.
[Required authorization] Route required privileges: securitySolution AND securitySolution-entity-analytics.
+ operationId: post-security-entity-store-resolution-unlink
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ unlinkEntitiesExample:
+ description: Remove entities from their resolution group, restoring them as standalone entities.
+ summary: Unlink entities from their resolution group
+ value:
+ entity_ids:
+ - user:jdoe@example.com
+ - user:j.doe@example.com
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ unlinkSuccessExample:
+ description: The entities were successfully removed from their resolution group.
+ summary: Entities unlinked
+ value:
+ skipped: []
+ unlinked:
+ - user:jdoe@example.com
+ - user:j.doe@example.com
+ description: Indicates a successful response.
+ '404':
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ description: One or more of the specified entity identifiers were not found.
+ summary: Entities not found
+ value:
+ error: Not Found
+ message: 'Entities not found: [user:nonexistent@example.com]'
+ statusCode: 404
+ description: Entities not found.
+ summary: Unlink entities
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entity_ids":["user:jdoe@example.com"]}' \
+ "${KIBANA_URL}/api/security/entity_store/resolution/unlink"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/resolution/unlink
+ {
+ "entity_ids": ["user:jdoe@example.com"]
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/start:
+ put:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ put /s/{space_id}/api/security/entity_store/start
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Start previously stopped entity engines, resuming data processing for the specified entity types.
[Required authorization] Route required privileges: securitySolution.
+ operationId: put-security-entity-store-start
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ startAllExample:
+ description: Start all stopped entity engines.
+ summary: Start all entity engines
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ startSingleExample:
+ description: Start only the host entity engine.
+ summary: Start a single entity engine
+ value:
+ entityTypes:
+ - host
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ startSuccessExample:
+ description: The specified entity engines were successfully started.
+ summary: Engines started
+ value:
+ ok: true
+ description: Indicates a successful response.
+ summary: Start Entity Store engines
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"]}' \
+ "${KIBANA_URL}/api/security/entity_store/start"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/start
+ {
+ "entityTypes": ["user", "host", "service", "generic"]
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/status:
+ get:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ get /s/{space_id}/api/security/entity_store/status
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Get the overall Entity Store status and per-engine statuses, optionally including component-level health details.
[Required authorization] Route required privileges: securitySolution.
+ operationId: get-security-entity-store-status
+ parameters: []
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ notInstalledExample:
+ description: The Entity Store has not been installed.
+ summary: Entity Store not installed
+ value:
+ engines: []
+ status: not_installed
+ runningStatusExample:
+ description: The Entity Store is running with two started engines using default settings.
+ summary: Entity Store running
+ value:
+ engines:
+ - delay: 1m
+ docsPerSecond: -1
+ enrichPolicyExecutionInterval: null
+ fieldHistoryLength: 10
+ filter: ''
+ frequency: 30s
+ indexPattern: ''
+ lastExecutionTimestamp: '2026-04-10T08:30:00.000Z'
+ lookbackPeriod: 3h
+ maxPageSearchSize: 10000
+ status: started
+ timeout: 25s
+ timestampField: '@timestamp'
+ type: host
+ - delay: 1m
+ docsPerSecond: -1
+ enrichPolicyExecutionInterval: null
+ fieldHistoryLength: 10
+ filter: ''
+ frequency: 30s
+ indexPattern: ''
+ lastExecutionTimestamp: '2026-04-10T08:30:00.000Z'
+ lookbackPeriod: 3h
+ maxPageSearchSize: 10000
+ status: started
+ timeout: 25s
+ timestampField: '@timestamp'
+ type: user
+ status: running
+ description: Indicates a successful response.
+ summary: Get Entity Store status
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X GET -H "Authorization: ApiKey ${API_KEY}" \
+ "${KIBANA_URL}/api/security/entity_store/status?include_components=false"
+ - lang: Console
+ source: |
+ GET kbn://api/security/entity_store/status?include_components=false
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/stop:
+ put:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ put /s/{space_id}/api/security/entity_store/stop
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Stop running entity engines, pausing data processing for the specified entity types.
[Required authorization] Route required privileges: securitySolution.
+ operationId: put-security-entity-store-stop
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ stopAllExample:
+ description: Stop all running entity engines.
+ summary: Stop all entity engines
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ stopSuccessExample:
+ description: The specified entity engines were successfully stopped.
+ summary: Engines stopped
+ value:
+ ok: true
+ description: Indicates a successful response.
+ summary: Stop Entity Store engines
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"]}' \
+ "${KIBANA_URL}/api/security/entity_store/stop"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/stop
+ {
+ "entityTypes": ["user", "host", "service", "generic"]
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
+ /api/security/entity_store/uninstall:
+ post:
+ description: |-
+ **Spaces method and path for this operation:**
+
+ post /s/{space_id}/api/security/entity_store/uninstall
+
+ Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.
+
+ Uninstall the Entity Store, removing engines and associated resources for the specified entity types.
[Required authorization] Route required privileges: securitySolution.
+ operationId: post-security-entity-store-uninstall
+ parameters:
+ - description: A required header to protect against CSRF attacks
+ in: header
+ name: kbn-xsrf
+ required: true
+ schema:
+ example: 'true'
+ type: string
+ requestBody:
+ content:
+ application/json:
+ examples:
+ uninstallAllExample:
+ description: Uninstall all entity engines from the Entity Store.
+ summary: Uninstall all entity types
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ uninstallSingleExample:
+ description: Uninstall only the host engine from the Entity Store.
+ summary: Uninstall a single entity type
+ value:
+ entityTypes:
+ - host
+ schema: {}
+ responses:
+ '200':
+ content:
+ application/json:
+ examples:
+ uninstallSuccessExample:
+ description: The specified entity engines were successfully uninstalled.
+ summary: Entity Store uninstalled
+ value:
+ ok: true
+ description: Indicates a successful response.
+ summary: Uninstall the Entity Store
+ tags:
+ - Security entity store
+ x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"]}' \
+ "${KIBANA_URL}/api/security/entity_store/uninstall"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/uninstall
+ {
+ "entityTypes": ["user", "host", "service", "generic"]
+ }
+ x-metaTags:
+ - content: Kibana
+ name: product_name
/api/security/role:
get:
operationId: get-security-role
diff --git a/x-pack/solutions/security/plugins/entity_store/common/domain/definitions/entity.gen.ts b/x-pack/solutions/security/plugins/entity_store/common/domain/definitions/entity.gen.ts
index 20ea8bf761139..d6c7886f248af 100644
--- a/x-pack/solutions/security/plugins/entity_store/common/domain/definitions/entity.gen.ts
+++ b/x-pack/solutions/security/plugins/entity_store/common/domain/definitions/entity.gen.ts
@@ -17,14 +17,11 @@
import { z } from '@kbn/zod/v4';
/**
- * One relationship direction: `raw_identifiers` holds ECS-style dotted keys → keyword arrays (aligned with ENTITY_RELATIONSHIP_IDENTIFIER_FIELDS plus entity.id), and canonical target EUIDs under `ids`.
+ * One relationship direction: a dynamic `raw_identifiers` object (ECS-style dotted keys → string arrays, no enumerated sub-properties) and canonical target EUIDs under `ids`.
*/
export type EntityRelationship = z.infer;
export const EntityRelationship = z
.object({
- /**
- * Raw identifier dimensions for graph / resolution hints. Keys match the entity store relationship identifier field set (see ENTITY_RELATIONSHIP_IDENTIFIER_FIELDS in code).
- */
raw_identifiers: z
.object({
'entity.id': z.array(z.string()).optional(),
@@ -44,37 +41,82 @@ export const EntityRelationship = z
})
.strict();
+/**
+ * Internal metadata attached to an entity by the engine that produced it.
+ */
export type EngineMetadata = z.infer;
export const EngineMetadata = z
.object({
+ /**
+ * The engine type that produced this entity record.
+ */
Type: z.string().optional(),
})
.strict();
+/**
+ * The risk level classification of an entity.
+ */
export type EntityRiskLevels = z.infer;
export const EntityRiskLevels = z.enum(['Unknown', 'Low', 'Moderate', 'High', 'Critical']);
export type EntityRiskLevelsEnum = typeof EntityRiskLevels.enum;
export const EntityRiskLevelsEnum = EntityRiskLevels.enum;
+/**
+ * Core entity fields shared across all entity types.
+ */
export type EntityField = z.infer;
export const EntityField = z
.object({
+ /**
+ * Unique identifier for this entity.
+ */
id: z.string().optional(),
+ /**
+ * Human-readable name of the entity.
+ */
name: z.string().optional(),
+ /**
+ * The entity type.
+ */
type: z.string().optional(),
+ /**
+ * Optional sub-type classification for the entity.
+ */
sub_type: z.string().optional(),
+ /**
+ * Sources that produced this entity record.
+ */
source: z.array(z.string()).optional(),
+ /**
+ * Schema version of the entity record.
+ */
schema_version: z.string().optional(),
+ /**
+ * URL associated with the entity.
+ */
url: z.string().optional(),
EngineMetadata: EngineMetadata.optional(),
+ /**
+ * Boolean flags describing characteristics of the entity.
+ */
attributes: z
.object({
/**
* Watchlist identifiers the entity belongs to (v2).
*/
watchlists: z.array(z.string()).optional(),
+ /**
+ * Whether the entity is classified as an asset.
+ */
asset: z.boolean().optional(),
+ /**
+ * Whether the entity is managed (for example, via a directory service).
+ */
managed: z.boolean().optional(),
+ /**
+ * Whether multi-factor authentication is enabled for the entity.
+ */
mfa_enabled: z.boolean().optional(),
/**
* Storage tier or class assigned to a storage resource (e.g. hot, warm, cold, standard, archive).
@@ -95,6 +137,9 @@ export const EntityField = z
})
.strict()
.optional(),
+ /**
+ * Behavioral signals observed for the entity.
+ */
behaviors: z
.object({
/**
@@ -102,36 +147,81 @@ export const EntityField = z
*/
rule_names: z.array(z.string()).optional(),
/**
- * ML anomaly job identifiers (v2).
+ * Machine learning anomaly job identifiers (v2).
*/
anomaly_job_ids: z.array(z.string()).optional(),
})
.strict()
.optional(),
+ /**
+ * Timestamps tracking the entity lifecycle.
+ */
lifecycle: z
.object({
+ /**
+ * When the entity was first observed.
+ */
first_seen: z.string().datetime().optional(),
+ /**
+ * When the entity was last observed.
+ */
last_seen: z.string().datetime().optional(),
+ /**
+ * When the entity last generated activity.
+ */
last_activity: z.string().datetime().optional(),
})
.strict()
.optional(),
+ /**
+ * Connections between this entity and other entities.
+ */
relationships: z
.object({
+ /**
+ * Entities this entity administers (for example, a user who is an admin of a service).
+ */
administers: EntityRelationship.optional(),
+ /**
+ * Entities this entity communicates with.
+ */
communicates_with: EntityRelationship.optional(),
+ /**
+ * Entities this entity depends on.
+ */
depends_on: EntityRelationship.optional(),
+ /**
+ * Entities inferred to be owned by this entity.
+ */
owns_inferred: EntityRelationship.optional(),
+ /**
+ * Entities this entity accesses infrequently.
+ */
accesses_infrequently: EntityRelationship.optional(),
+ /**
+ * Entities this entity accesses frequently.
+ */
accesses_frequently: EntityRelationship.optional(),
+ /**
+ * Entities owned by this entity.
+ */
owns: EntityRelationship.optional(),
+ /**
+ * Entities supervised by this entity.
+ */
supervises: EntityRelationship.optional(),
+ /**
+ * Resolution metadata linking this entity to another.
+ */
resolution: z
.object({
/**
* entity.id of the entity this one resolves to
*/
resolved_to: z.string().optional(),
+ /**
+ * Aggregated risk score for the resolution group.
+ */
risk: z
.object({
/**
@@ -155,6 +245,9 @@ export const EntityField = z
})
.strict()
.optional(),
+ /**
+ * Risk scoring information for the entity.
+ */
risk: z
.object({
/**
@@ -188,17 +281,47 @@ export const AssetCriticalityLevel = z.enum([
export type AssetCriticalityLevelEnum = typeof AssetCriticalityLevel.enum;
export const AssetCriticalityLevelEnum = AssetCriticalityLevel.enum;
+/**
+ * Asset metadata associated with the entity.
+ */
export type Asset = z.infer;
export const Asset = z
.object({
+ /**
+ * Unique identifier for the asset.
+ */
id: z.string().optional(),
+ /**
+ * Human-readable asset name.
+ */
name: z.string().optional(),
+ /**
+ * The owner of the asset.
+ */
owner: z.string().optional(),
+ /**
+ * Serial number of the asset.
+ */
serial_number: z.string().optional(),
+ /**
+ * Model name or number.
+ */
model: z.string().optional(),
+ /**
+ * Vendor or manufacturer.
+ */
vendor: z.string().optional(),
+ /**
+ * Deployment environment (for example, production, staging).
+ */
environment: z.string().optional(),
+ /**
+ * The criticality level assigned to this asset.
+ */
criticality: AssetCriticalityLevel.nullable().optional(),
+ /**
+ * Business unit the asset belongs to.
+ */
business_unit: z.string().optional(),
})
.strict();
@@ -224,29 +347,68 @@ export const EntityRiskSummary = z
})
.strict();
+/**
+ * An entity record representing a user.
+ */
export type UserEntity = z.infer;
export const UserEntity = z
.object({
+ /**
+ * The time the entity record was last updated.
+ */
'@timestamp': z.string().datetime().optional(),
entity: EntityField.optional(),
+ /**
+ * Elastic Common Schema (ECS) user fields collected on the entity.
+ */
user: z
.object({
+ /**
+ * Observed full names of the user.
+ */
full_name: z.array(z.string()).optional(),
+ /**
+ * Observed user domains.
+ */
domain: z.array(z.string()).optional(),
+ /**
+ * Observed roles assigned to the user.
+ */
roles: z.array(z.string()).optional(),
+ /**
+ * Primary user name.
+ */
name: z.string().optional(),
+ /**
+ * Observed user identifiers.
+ */
id: z.array(z.string()).optional(),
+ /**
+ * Observed email addresses.
+ */
email: z.array(z.string()).optional(),
+ /**
+ * Observed user hashes.
+ */
hash: z.array(z.string()).optional(),
risk: EntityRiskSummary.optional(),
})
.strict()
.optional(),
asset: Asset.optional(),
+ /**
+ * Custom key-value labels attached to the entity.
+ */
labels: z.object({}).catchall(z.unknown()).optional(),
+ /**
+ * Tags attached to the entity.
+ */
tags: z.array(z.string()).optional(),
event: z
.object({
+ /**
+ * When the event was ingested into Elasticsearch.
+ */
ingested: z.string().datetime().optional(),
})
.strict()
@@ -254,23 +416,56 @@ export const UserEntity = z
})
.strict();
+/**
+ * An entity record representing a host.
+ */
export type HostEntity = z.infer;
export const HostEntity = z
.object({
+ /**
+ * The time the entity record was last updated.
+ */
'@timestamp': z.string().datetime().optional(),
entity: EntityField.optional(),
+ /**
+ * Elastic Common Schema (ECS) host fields collected on the entity.
+ */
host: z
.object({
+ /**
+ * Observed hostnames.
+ */
hostname: z.array(z.string()).optional(),
+ /**
+ * Observed host domains.
+ */
domain: z.array(z.string()).optional(),
+ /**
+ * Observed IP addresses.
+ */
ip: z.array(z.string()).optional(),
+ /**
+ * Primary host name.
+ */
name: z.string().optional(),
+ /**
+ * Observed host identifiers.
+ */
id: z.array(z.string()).optional(),
+ /**
+ * Observed host types.
+ */
type: z.array(z.string()).optional(),
+ /**
+ * Observed MAC addresses.
+ */
mac: z.array(z.string()).optional(),
+ /**
+ * Observed CPU architectures.
+ */
architecture: z.array(z.string()).optional(),
/**
- * ECS host.os fields materialized on the entity latest index (v2).
+ * Elastic Common Schema (ECS) host.os fields collected on the entity latest index (v2).
*/
os: z
.object({
@@ -289,10 +484,19 @@ export const HostEntity = z
.strict()
.optional(),
asset: Asset.optional(),
+ /**
+ * Custom key-value labels attached to the entity.
+ */
labels: z.object({}).catchall(z.unknown()).optional(),
+ /**
+ * Tags attached to the entity.
+ */
tags: z.array(z.string()).optional(),
event: z
.object({
+ /**
+ * When the event was ingested into Elasticsearch.
+ */
ingested: z.string().datetime().optional(),
})
.strict()
@@ -300,38 +504,92 @@ export const HostEntity = z
})
.strict();
+/**
+ * An entity record representing a service.
+ */
export type ServiceEntity = z.infer;
export const ServiceEntity = z
.object({
+ /**
+ * The time the entity record was last updated.
+ */
'@timestamp': z.string().datetime().optional(),
entity: EntityField.optional(),
+ /**
+ * Elastic Common Schema (ECS) service fields collected on the entity.
+ */
service: z
.object({
+ /**
+ * Primary service name.
+ */
name: z.string().optional(),
+ /**
+ * Service address.
+ */
address: z.string().optional(),
+ /**
+ * Service environment (for example, production, staging).
+ */
environment: z.string().optional(),
+ /**
+ * Ephemeral identifier of the service.
+ */
ephemeral_id: z.string().optional(),
+ /**
+ * Unique identifier of the service.
+ */
id: z.string().optional(),
+ /**
+ * Node information for the service.
+ */
node: z
.object({
+ /**
+ * Node name.
+ */
name: z.string().optional(),
+ /**
+ * Node role.
+ */
role: z.string().optional(),
+ /**
+ * Node roles.
+ */
roles: z.array(z.string()).optional(),
})
.strict()
.optional(),
+ /**
+ * Current state of the service.
+ */
state: z.string().optional(),
+ /**
+ * Service type.
+ */
type: z.string().optional(),
+ /**
+ * Service version.
+ */
version: z.string().optional(),
risk: EntityRiskSummary.optional(),
})
.strict()
.optional(),
asset: Asset.optional(),
+ /**
+ * Custom key-value labels attached to the entity.
+ */
labels: z.object({}).catchall(z.unknown()).optional(),
+ /**
+ * Tags attached to the entity.
+ */
tags: z.array(z.string()).optional(),
event: z
.object({
+ /**
+ * When the event was ingested into Elasticsearch.
+ */
ingested: z.string().datetime().optional(),
})
.strict()
@@ -339,12 +597,21 @@ export const ServiceEntity = z
})
.strict();
+/**
+ * A generic entity record that can represent cloud resources, orchestrator workloads, or other entity types not covered by user, host, or service.
+ */
export type GenericEntity = z.infer;
export const GenericEntity = z
.object({
+ /**
+ * The time the entity record was last updated.
+ */
'@timestamp': z.string().datetime().optional(),
entity: EntityField.optional(),
asset: Asset.optional(),
+ /**
+ * Elastic Common Schema (ECS) cloud fields for cloud-hosted entities.
+ */
cloud: z
.object({
account: z
@@ -386,6 +653,9 @@ export const GenericEntity = z
})
.strict()
.optional(),
+ /**
+ * Elastic Common Schema (ECS) orchestrator fields for container-orchestrated entities.
+ */
orchestrator: z
.object({
api_version: z.string().optional(),
@@ -432,6 +702,9 @@ export const GenericEntity = z
})
.strict();
+/**
+ * An entity record from the Entity Store. The `entity` namespace is a root-level field in the latest index, unlike source logs where it is nested under `host`, `user`, or `service`.
+ */
export const EntityInternal = z.union([UserEntity, HostEntity, ServiceEntity, GenericEntity]);
export type Entity = z.infer;
diff --git a/x-pack/solutions/security/plugins/entity_store/common/domain/definitions/entity.schema.yaml b/x-pack/solutions/security/plugins/entity_store/common/domain/definitions/entity.schema.yaml
index d0ed67fbc8f7c..cd5247214a4df 100644
--- a/x-pack/solutions/security/plugins/entity_store/common/domain/definitions/entity.schema.yaml
+++ b/x-pack/solutions/security/plugins/entity_store/common/domain/definitions/entity.schema.yaml
@@ -1,5 +1,5 @@
# Generate schema by calling:
-# node scripts/generate_openapi.js --rootDir x-pack/solutions/security/plugins/entity_store/
+# cd x-pack/solutions/security/plugins/entity_store && yarn openapi:generate
openapi: 3.0.0
info:
title: Common Entities Schemas
@@ -56,35 +56,53 @@ components:
EngineMetadata:
type: object
+ description: Internal metadata attached to an entity by the engine that produced it.
additionalProperties: false
properties:
Type:
type: string
+ description: The engine type that produced this entity record.
EntityField:
type: object
+ description: Core entity fields shared across all entity types.
additionalProperties: false
properties:
id:
type: string
+ description: Unique identifier for this entity.
+ example: 'user:jane.doe@example.com'
name:
type: string
+ description: Human-readable name of the entity.
+ example: 'jane.doe'
type:
type: string
+ description: The entity type.
+ example: 'user'
sub_type:
type: string
+ description: Optional sub-type classification for the entity.
source:
type: array
+ description: Sources that produced this entity record.
+ example:
+ - 'logs'
+ - 'manual'
items:
type: string
schema_version:
type: string
+ description: Schema version of the entity record.
+ example: 'v1'
url:
type: string
+ description: URL associated with the entity.
EngineMetadata:
$ref: '#/components/schemas/EngineMetadata'
attributes:
type: object
+ description: Boolean flags describing characteristics of the entity.
additionalProperties: false
properties:
watchlists:
@@ -94,10 +112,13 @@ components:
description: Watchlist identifiers the entity belongs to (v2).
asset:
type: boolean
+ description: Whether the entity is classified as an asset.
managed:
type: boolean
+ description: Whether the entity is managed (for example, via a directory service).
mfa_enabled:
type: boolean
+ description: Whether multi-factor authentication is enabled for the entity.
storage_class:
type: string
description: Storage tier or class assigned to a storage resource (e.g. hot, warm, cold, standard, archive).
@@ -116,6 +137,7 @@ components:
description: OAuth consent restriction (e.g. admin_only, verified_only, unrestricted).
behaviors:
type: object
+ description: Behavioral signals observed for the entity.
additionalProperties: false
properties:
rule_names:
@@ -127,42 +149,59 @@ components:
type: array
items:
type: string
- description: ML anomaly job identifiers (v2).
+ description: Machine learning anomaly job identifiers (v2).
lifecycle:
type: object
+ description: Timestamps tracking the entity lifecycle.
additionalProperties: false
properties:
first_seen:
type: string
format: date-time
+ description: When the entity was first observed.
+ example: '2026-01-15T10:00:00.000Z'
last_seen:
type: string
format: date-time
+ description: When the entity was last observed.
+ example: '2026-04-10T08:30:00.000Z'
last_activity:
type: string
format: date-time
+ description: When the entity last generated activity.
+ example: '2026-04-10T08:25:00.000Z'
relationships:
type: object
+ description: Connections between this entity and other entities.
additionalProperties: false
properties:
administers:
$ref: '#/components/schemas/EntityRelationship'
+ description: Entities this entity administers (for example, a user who is an admin of a service).
communicates_with:
$ref: '#/components/schemas/EntityRelationship'
+ description: Entities this entity communicates with.
depends_on:
$ref: '#/components/schemas/EntityRelationship'
+ description: Entities this entity depends on.
owns_inferred:
$ref: '#/components/schemas/EntityRelationship'
+ description: Entities inferred to be owned by this entity.
accesses_infrequently:
$ref: '#/components/schemas/EntityRelationship'
+ description: Entities this entity accesses infrequently.
accesses_frequently:
$ref: '#/components/schemas/EntityRelationship'
+ description: Entities this entity accesses frequently.
owns:
$ref: '#/components/schemas/EntityRelationship'
+ description: Entities owned by this entity.
supervises:
$ref: '#/components/schemas/EntityRelationship'
+ description: Entities supervised by this entity.
resolution:
type: object
+ description: Resolution metadata linking this entity to another.
additionalProperties: false
properties:
resolved_to:
@@ -170,6 +209,7 @@ components:
description: entity.id of the entity this one resolves to
risk:
type: object
+ description: Aggregated risk score for the resolution group.
additionalProperties: false
properties:
calculated_level:
@@ -187,6 +227,7 @@ components:
description: The normalized numeric value of the resolution group's aggregated risk score.
risk:
type: object
+ description: Risk scoring information for the entity.
additionalProperties: false
properties:
calculated_level:
@@ -197,74 +238,117 @@ components:
type: number
format: double
description: The raw numeric value of the given entity's risk score.
+ example: 83.2
calculated_score_norm:
type: number
format: double
minimum: 0
maximum: 100
description: The normalized numeric value of the given entity's risk score. Useful for comparing with other entities.
+ example: 83.2
Asset:
type: object
+ description: Asset metadata associated with the entity.
additionalProperties: false
properties:
id:
type: string
+ description: Unique identifier for the asset.
+ example: 'asset-web-server-prod-01'
name:
type: string
+ description: Human-readable asset name.
+ example: 'web-server-prod-01'
owner:
type: string
+ description: The owner of the asset.
+ example: 'platform-team'
serial_number:
type: string
+ description: Serial number of the asset.
+ example: 'SN-2026-04-0042'
model:
type: string
+ description: Model name or number.
+ example: 'm5.xlarge'
vendor:
type: string
+ description: Vendor or manufacturer.
+ example: 'AWS'
environment:
type: string
+ description: Deployment environment (for example, production, staging).
+ example: 'production'
criticality:
nullable: true
$ref: '#/components/schemas/AssetCriticalityLevel'
+ description: The criticality level assigned to this asset.
+ example: 'high_impact'
business_unit:
type: string
+ description: Business unit the asset belongs to.
+ example: 'Engineering'
UserEntity:
type: object
+ description: An entity record representing a user.
additionalProperties: false
properties:
"@timestamp":
type: string
format: date-time
+ description: The time the entity record was last updated.
entity:
$ref: '#/components/schemas/EntityField'
user:
type: object
+ description: Elastic Common Schema (ECS) user fields collected on the entity.
additionalProperties: false
properties:
full_name:
type: array
+ description: Observed full names of the user.
+ example:
+ - 'Jane Doe'
items:
type: string
domain:
type: array
+ description: Observed user domains.
+ example:
+ - 'example.com'
items:
type: string
roles:
type: array
+ description: Observed roles assigned to the user.
+ example:
+ - 'admin'
+ - 'analyst'
items:
type: string
name:
type: string
+ description: Primary user name.
+ example: 'jane.doe'
id:
type: array
+ description: Observed user identifiers.
+ example:
+ - 'u-1234'
items:
type: string
email:
type: array
+ description: Observed email addresses.
+ example:
+ - 'jane.doe@example.com'
items:
type: string
hash:
type: array
+ description: Observed user hashes.
items:
type: string
risk:
@@ -274,9 +358,11 @@ components:
additionalProperties: false
labels:
type: object
+ description: Custom key-value labels attached to the entity.
additionalProperties: true
tags:
type: array
+ description: Tags attached to the entity.
items:
type: string
event:
@@ -286,54 +372,80 @@ components:
ingested:
type: string
format: date-time
+ description: When the event was ingested into Elasticsearch.
HostEntity:
type: object
+ description: An entity record representing a host.
additionalProperties: false
properties:
"@timestamp":
type: string
format: date-time
+ description: The time the entity record was last updated.
entity:
$ref: '#/components/schemas/EntityField'
host:
type: object
+ description: Elastic Common Schema (ECS) host fields collected on the entity.
additionalProperties: false
properties:
hostname:
type: array
+ description: Observed hostnames.
+ example:
+ - 'web-server-prod-01.example.com'
items:
type: string
domain:
type: array
+ description: Observed host domains.
+ example:
+ - 'example.com'
items:
type: string
ip:
type: array
+ description: Observed IP addresses.
+ example:
+ - '10.0.1.42'
+ - '172.16.0.5'
items:
type: string
name:
type: string
+ description: Primary host name.
+ example: 'web-server-prod-01'
id:
type: array
+ description: Observed host identifiers.
+ example:
+ - 'i-0abcd1234efgh5678'
items:
type: string
type:
type: array
+ description: Observed host types.
items:
type: string
mac:
type: array
+ description: Observed MAC addresses.
+ example:
+ - '02:42:ac:11:00:02'
items:
type: string
architecture:
type: array
+ description: Observed CPU architectures.
+ example:
+ - 'x86_64'
items:
type: string
os:
type: object
additionalProperties: false
- description: ECS host.os fields materialized on the entity latest index (v2).
+ description: Elastic Common Schema (ECS) host.os fields collected on the entity latest index (v2).
properties:
name:
oneOf:
@@ -364,9 +476,11 @@ components:
additionalProperties: false
labels:
type: object
+ description: Custom key-value labels attached to the entity.
additionalProperties: true
tags:
type: array
+ description: Tags attached to the entity.
items:
type: string
event:
@@ -376,48 +490,71 @@ components:
ingested:
type: string
format: date-time
+ description: When the event was ingested into Elasticsearch.
ServiceEntity:
type: object
+ description: An entity record representing a service.
additionalProperties: false
properties:
"@timestamp":
type: string
format: date-time
+ description: The time the entity record was last updated.
entity:
$ref: '#/components/schemas/EntityField'
service:
type: object
+ description: Elastic Common Schema (ECS) service fields collected on the entity.
additionalProperties: false
properties:
name:
type: string
+ description: Primary service name.
+ example: 'api-gateway'
address:
type: string
+ description: Service address.
+ example: 'api-gateway.default.svc.cluster.local:8080'
environment:
type: string
+ description: Service environment (for example, production, staging).
+ example: 'production'
ephemeral_id:
type: string
+ description: Ephemeral identifier of the service.
id:
type: string
+ description: Unique identifier of the service.
+ example: 'svc-api-gateway-prod'
node:
type: object
+ description: Node information for the service.
additionalProperties: false
properties:
name:
type: string
+ description: Node name.
role:
type: string
+ description: Node role.
roles:
type: array
+ description: Node roles.
items:
type: string
state:
type: string
+ description: Current state of the service.
+ example: 'running'
type:
type: string
+ description: Service type.
+ example: 'http'
version:
type: string
+ description: Service version.
+ example: '2.4.1'
risk:
$ref: '#/components/schemas/EntityRiskSummary'
asset:
@@ -425,9 +562,11 @@ components:
additionalProperties: false
labels:
type: object
+ description: Custom key-value labels attached to the entity.
additionalProperties: true
tags:
type: array
+ description: Tags attached to the entity.
items:
type: string
event:
@@ -437,14 +576,17 @@ components:
ingested:
type: string
format: date-time
+ description: When the event was ingested into Elasticsearch.
GenericEntity:
type: object
+ description: A generic entity record that can represent cloud resources, orchestrator workloads, or other entity types not covered by user, host, or service.
additionalProperties: false
properties:
"@timestamp":
type: string
format: date-time
+ description: The time the entity record was last updated.
entity:
$ref: '#/components/schemas/EntityField'
asset:
@@ -452,6 +594,7 @@ components:
additionalProperties: false
cloud:
type: object
+ description: Elastic Common Schema (ECS) cloud fields for cloud-hosted entities.
additionalProperties: false
properties:
account:
@@ -460,36 +603,46 @@ components:
properties:
id:
type: string
+ example: '123456789012'
name:
type: string
+ example: 'production-account'
availability_zone:
type: string
+ example: 'us-east-1a'
instance:
type: object
additionalProperties: false
properties:
id:
type: string
+ example: 'i-0abcd1234efgh5678'
name:
type: string
+ example: 'web-server-prod-01'
machine:
type: object
additionalProperties: false
properties:
type:
type: string
+ example: 'm5.xlarge'
project:
type: object
additionalProperties: false
properties:
id:
type: string
+ example: 'proj-analytics-01'
name:
type: string
+ example: 'analytics'
provider:
type: string
+ example: 'aws'
region:
type: string
+ example: 'us-east-1'
service:
type: object
additionalProperties: false
@@ -498,26 +651,34 @@ components:
type: string
orchestrator:
type: object
+ description: Elastic Common Schema (ECS) orchestrator fields for container-orchestrated entities.
additionalProperties: false
properties:
api_version:
type: string
+ example: 'v1'
cluster:
type: object
additionalProperties: false
properties:
id:
type: string
+ example: 'cls-abc123'
name:
type: string
+ example: 'prod-k8s'
url:
type: string
+ example: 'https://k8s.example.com:6443'
version:
type: string
+ example: '1.29.2'
namespace:
type: string
+ example: 'default'
organization:
type: string
+ example: 'engineering'
resource:
type: object
additionalProperties: false
@@ -557,12 +718,8 @@ components:
type: string
format: date-time
- # These entities represent the API of Entity Store
- # where entity is a root field, as it's in the final
- # index for entities. Note that this is different from the
- # source logs mapping where `entity` will be nested under
- # `host`, `user` and `service`
Entity:
+ description: An entity record from the Entity Store. The `entity` namespace is a root-level field in the latest index, unlike source logs where it is nested under `host`, `user`, or `service`.
oneOf:
- $ref: '#/components/schemas/UserEntity'
- $ref: '#/components/schemas/HostEntity'
@@ -587,19 +744,23 @@ components:
calculated_level:
$ref: '#/components/schemas/EntityRiskLevels'
description: Lexical description of the entity's risk.
+ example: 'High'
calculated_score:
type: number
format: double
description: The raw numeric value of the given entity's risk score.
+ example: 71.4
calculated_score_norm:
type: number
format: double
minimum: 0
maximum: 100
description: The normalized numeric value of the given entity's risk score.
+ example: 71.4
EntityRiskLevels:
type: string
+ description: The risk level classification of an entity.
enum:
- "Unknown"
- "Low"
diff --git a/x-pack/solutions/security/plugins/entity_store/package.json b/x-pack/solutions/security/plugins/entity_store/package.json
new file mode 100644
index 0000000000000..7a11b1c774d9a
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@kbn/entity-store",
+ "private": true,
+ "version": "1.0.0",
+ "license": "Elastic License 2.0",
+ "scripts": {
+ "openapi:generate": "node scripts/openapi_generate"
+ }
+}
diff --git a/x-pack/solutions/security/plugins/entity_store/scripts/openapi_generate.js b/x-pack/solutions/security/plugins/entity_store/scripts/openapi_generate.js
new file mode 100644
index 0000000000000..3bcc415e5d973
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/scripts/openapi_generate.js
@@ -0,0 +1,21 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+require('@kbn/setup-node-env');
+const { resolve } = require('path');
+const { generate } = require('@kbn/openapi-generator');
+
+const ROOT = resolve(__dirname, '..');
+
+(async () => {
+ await generate({
+ title: 'OpenAPI Entity Store Schemas',
+ rootDir: ROOT,
+ sourceGlob: './common/**/*.schema.yaml',
+ templateName: 'zod_operation_schema',
+ });
+})();
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/check_privileges.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/check_privileges.ts
index 6765ab0f8fa1d..bbeabbea79de8 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/check_privileges.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/check_privileges.ts
@@ -4,6 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
+import path from 'node:path';
import type { IKibanaResponse } from '@kbn/core-http-server';
import {
API_VERSIONS,
@@ -21,6 +22,12 @@ export function registerCheckPrivileges(router: EntityStorePluginRouter) {
.get({
path: ENTITY_STORE_ROUTES.internal.CHECK_PRIVILEGES,
access: 'internal',
+ summary: 'Check Entity Store privileges',
+ description:
+ 'Check whether the current user has the required Elasticsearch and Kibana privileges to use the Entity Store.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -30,6 +37,10 @@ export function registerCheckPrivileges(router: EntityStorePluginRouter) {
{
version: API_VERSIONS.internal.v2,
validate: false,
+ options: {
+ oasOperationObject: () =>
+ path.join(__dirname, 'examples/entity_store_check_privileges.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res): Promise => {
const entityStoreCtx = await ctx.entityStore;
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/bulk_update.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/bulk_update.ts
index 1df5cc2114ced..0302a9a46612c 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/bulk_update.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/bulk_update.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { BooleanFromString, buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
@@ -17,16 +18,20 @@ import { BadCRUDRequestError, EntityStoreNotInstalledError } from '../../../doma
import { Entity } from '../../../../common/domain/definitions/entity.gen';
const bodySchema = z.object({
- entities: z.array(
- z.object({
- type: z.enum(ALL_ENTITY_TYPES),
- doc: z.preprocess((val) => unflattenObject(val as Record), Entity),
- })
- ),
+ entities: z
+ .array(
+ z.object({
+ type: z.enum(ALL_ENTITY_TYPES).describe('The entity type of this record.'),
+ doc: z.preprocess((val) => unflattenObject(val as Record), Entity),
+ })
+ )
+ .describe('The entities to update.'),
});
const querySchema = z.object({
- force: BooleanFromString.optional().default(false),
+ force: BooleanFromString.optional()
+ .default(false)
+ .describe('When true, allows updating protected fields.'),
});
export function registerCRUDBulkUpdate(router: EntityStorePluginRouter) {
@@ -34,6 +39,11 @@ export function registerCRUDBulkUpdate(router: EntityStorePluginRouter) {
.put({
path: ENTITY_STORE_ROUTES.public.CRUD_BULK_UPDATE,
access: 'public',
+ summary: 'Bulk update entities',
+ description: 'Update multiple entity records in the Entity Store in a single request.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -48,6 +58,9 @@ export function registerCRUDBulkUpdate(router: EntityStorePluginRouter) {
query: buildRouteValidationWithZod(querySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, '../examples/entities_bulk_update.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res): Promise => {
const entityStoreCtx = await ctx.entityStore;
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/create.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/create.ts
index 820378179b0b7..2f45928ec79d7 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/create.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/create.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
import { z } from '@kbn/zod/v4';
@@ -22,7 +23,7 @@ import { Entity } from '../../../../common/domain/definitions/entity.gen';
const paramsSchema = z
.object({
- entityType: z.enum(ALL_ENTITY_TYPES),
+ entityType: z.enum(ALL_ENTITY_TYPES).describe('The entity type to create.'),
})
.required();
@@ -31,6 +32,11 @@ export function registerCRUDCreate(router: EntityStorePluginRouter) {
.post({
path: ENTITY_STORE_ROUTES.public.CRUD_CREATE,
access: 'public',
+ summary: 'Create an entity',
+ description: 'Create a new entity record in the Entity Store for the specified entity type.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -47,6 +53,9 @@ export function registerCRUDCreate(router: EntityStorePluginRouter) {
params: buildRouteValidationWithZod(paramsSchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, '../examples/entities_create.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res): Promise => {
const entityStoreCtx = await ctx.entityStore;
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/delete.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/delete.ts
index 0a86f618aeb8c..f72cec100a9d7 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/delete.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/delete.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
@@ -15,7 +16,7 @@ import { wrapMiddlewares } from '../../middleware';
import { EntityNotFoundError } from '../../../domain/errors';
const bodySchema = z.object({
- entityId: z.string(),
+ entityId: z.string().describe('The identifier of the entity to delete.'),
});
export function registerCRUDDelete(router: EntityStorePluginRouter) {
@@ -23,6 +24,12 @@ export function registerCRUDDelete(router: EntityStorePluginRouter) {
.delete({
path: ENTITY_STORE_ROUTES.public.CRUD_DELETE,
access: 'public',
+ summary: 'Delete an entity',
+ description:
+ 'Delete a single entity record from the Entity Store. The entity is immediately removed from the latest index.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -36,6 +43,9 @@ export function registerCRUDDelete(router: EntityStorePluginRouter) {
body: buildRouteValidationWithZod(bodySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, '../examples/entities_delete.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res): Promise => {
const entityStoreCtx = await ctx.entityStore;
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/get.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/get.ts
index ec46740ad44a9..f8b5e49a95018 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/get.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/get.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { ArrayFromString, buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
@@ -21,17 +22,44 @@ const entityTypeSchema = z.enum(['user', 'host', 'service', 'generic']);
const querySchema = z
.object({
- filter: z.string().optional(),
- size: z.coerce.number().int().positive().optional(),
- searchAfter: z.string().optional(),
- source: z.array(z.string()).optional(),
- fields: ArrayFromString(z.string()).optional(),
- sort_field: z.string().optional(),
- sort_order: z.enum(['asc', 'desc']).optional(),
- page: z.coerce.number().int().min(1).optional(),
- per_page: z.coerce.number().int().min(1).max(10_000).optional(),
- filterQuery: z.string().optional(),
- entity_types: ArrayFromString(entityTypeSchema).optional(),
+ filter: z
+ .string()
+ .optional()
+ .describe('A Kibana Query Language (KQL) filter for the search-after mode.'),
+ size: z.coerce
+ .number()
+ .int()
+ .positive()
+ .optional()
+ .describe('Number of entities to return in search-after mode.'),
+ searchAfter: z
+ .string()
+ .optional()
+ .describe('JSON-encoded search_after value for cursor-based pagination.'),
+ source: z.array(z.string()).optional().describe('Fields to include in the response source.'),
+ fields: ArrayFromString(z.string()).optional().describe('Fields to include in the response.'),
+ sort_field: z.string().optional().describe('Field to sort results by in page mode.'),
+ sort_order: z.enum(['asc', 'desc']).optional().describe('Sort order in page mode.'),
+ page: z.coerce
+ .number()
+ .int()
+ .min(1)
+ .optional()
+ .describe('Page number to return (1-indexed) in page mode.'),
+ per_page: z.coerce
+ .number()
+ .int()
+ .min(1)
+ .max(10_000)
+ .optional()
+ .describe('Number of entities per page in page mode.'),
+ filterQuery: z
+ .string()
+ .optional()
+ .describe('An Elasticsearch query string to filter entities in page mode.'),
+ entity_types: ArrayFromString(entityTypeSchema)
+ .optional()
+ .describe('Entity types to include in the results.'),
})
.superRefine((data, ctx) => {
const usesPagePagination = data.page !== undefined || data.per_page !== undefined;
@@ -86,6 +114,12 @@ export function registerCRUDGet(router: EntityStorePluginRouter) {
.get({
path: ENTITY_STORE_ROUTES.public.CRUD_GET,
access: 'public',
+ summary: 'List entities',
+ description:
+ 'List entity records from the Entity Store with paging, sorting, and filtering. Supports two modes: page-based pagination (page/per_page) and cursor-based pagination (searchAfter). The two modes cannot be combined.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -99,6 +133,9 @@ export function registerCRUDGet(router: EntityStorePluginRouter) {
query: buildRouteValidationWithZod(querySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, '../examples/entities_list.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res): Promise => {
const { logger, crudClient } = await ctx.entityStore;
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/update.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/update.ts
index 5da699bf9721a..5113609702314 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/update.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/crud/update.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { BooleanFromString, buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
import { z } from '@kbn/zod/v4';
@@ -22,12 +23,14 @@ import { Entity } from '../../../../common/domain/definitions/entity.gen';
const paramsSchema = z
.object({
- entityType: z.enum(ALL_ENTITY_TYPES),
+ entityType: z.enum(ALL_ENTITY_TYPES).describe('The entity type to update.'),
})
.required();
const querySchema = z.object({
- force: BooleanFromString.optional().default(false),
+ force: BooleanFromString.optional()
+ .default(false)
+ .describe('When true, allows updating protected fields.'),
});
export function registerCRUDUpdate(router: EntityStorePluginRouter) {
@@ -35,6 +38,12 @@ export function registerCRUDUpdate(router: EntityStorePluginRouter) {
.put({
path: ENTITY_STORE_ROUTES.public.CRUD_UPDATE,
access: 'public',
+ summary: 'Update an entity',
+ description:
+ 'Update an existing entity record in the Entity Store. By default only certain fields can be updated. Set the `force` query parameter to `true` to update protected fields.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -52,6 +61,9 @@ export function registerCRUDUpdate(router: EntityStorePluginRouter) {
query: buildRouteValidationWithZod(querySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, '../examples/entities_update.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res): Promise => {
const entityStoreCtx = await ctx.entityStore;
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/get_maintainers.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/get_maintainers.ts
index 6dfbb352f6ad8..8fa5f99386a50 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/get_maintainers.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/get_maintainers.ts
@@ -41,6 +41,8 @@ export function registerGetMaintainers(router: EntityStorePluginRouter) {
.get({
path: ENTITY_STORE_ROUTES.internal.ENTITY_MAINTAINERS_GET,
access: 'internal',
+ summary: 'Get entity maintainers',
+ description: 'Get the status and configuration of registered entity maintainer tasks.',
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/init.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/init.ts
index f4ca07ef21b59..bcc12a84e64b2 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/init.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/init.ts
@@ -22,6 +22,9 @@ export function registerInitMaintainers(router: EntityStorePluginRouter) {
.post({
path: ENTITY_STORE_ROUTES.internal.ENTITY_MAINTAINERS_INIT,
access: 'internal',
+ summary: 'Initialize entity maintainers',
+ description:
+ 'Initialize all registered entity maintainer tasks. Requires the Entity Store to be installed and the user to have sufficient privileges.',
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/run.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/run.ts
index a5efa7e0e5e97..33fa1959c4a6c 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/run.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/run.ts
@@ -20,6 +20,8 @@ export function registerRunMaintainer(router: EntityStorePluginRouter) {
.post({
path: ENTITY_STORE_ROUTES.internal.ENTITY_MAINTAINERS_RUN,
access: 'internal',
+ summary: 'Run entity maintainer',
+ description: 'Trigger an immediate run of a registered entity maintainer task.',
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/start.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/start.ts
index aea7637fac1d2..5ce8bb03bbf63 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/start.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/start.ts
@@ -18,6 +18,8 @@ export function registerStartMaintainer(router: EntityStorePluginRouter) {
.put({
path: `${ENTITY_STORE_ROUTES.internal.ENTITY_MAINTAINERS_START}`,
access: 'internal',
+ summary: 'Start entity maintainer',
+ description: 'Start a registered entity maintainer task by its identifier.',
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/stop.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/stop.ts
index 30a89dac6f50f..50b5aab9e1625 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/stop.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/entity_maintainers/stop.ts
@@ -18,6 +18,8 @@ export function registerStopMaintainer(router: EntityStorePluginRouter) {
.put({
path: `${ENTITY_STORE_ROUTES.internal.ENTITY_MAINTAINERS_STOP}`,
access: 'internal',
+ summary: 'Stop entity maintainer',
+ description: 'Stop a running entity maintainer task by its identifier.',
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_bulk_update.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_bulk_update.yaml
new file mode 100644
index 0000000000000..e27aa5377debb
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_bulk_update.yaml
@@ -0,0 +1,89 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ bulkUpdateExample:
+ summary: "Bulk update multiple entities"
+ description: "Update a host entity and a user entity in a single request."
+ value:
+ entities:
+ - type: host
+ doc:
+ entity:
+ id: "host:web-server-prod-01"
+ name: "web-server-prod-01"
+ type: "host"
+ attributes:
+ asset: true
+ host:
+ name: "web-server-prod-01"
+ - type: user
+ doc:
+ entity:
+ id: "user:jane.doe@example.com"
+ name: "jane.doe"
+ type: "user"
+ attributes:
+ managed: true
+ user:
+ name: "jane.doe"
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ bulkUpdateSuccessExample:
+ summary: "All entities updated"
+ description: "All entities were successfully updated with no errors."
+ value:
+ ok: true
+ errors: []
+ bulkUpdatePartialExample:
+ summary: "Partial success with errors"
+ description: "Some entities were updated but others encountered Elasticsearch-level errors."
+ value:
+ ok: true
+ errors:
+ - _id: "5de9f93a68a72532e736bf5a6184b06300b9cabf"
+ status: 404
+ type: "document_missing_exception"
+ reason: "[5de9f93a68a72532e736bf5a6184b06300b9cabf]: document missing"
+ 400:
+ description: "Bad request."
+ content:
+ application/json:
+ examples:
+ protectedFieldsExample:
+ summary: "Protected fields without force"
+ description: "The request attempts to update protected fields without the force query parameter."
+ value:
+ statusCode: 400
+ error: "Bad Request"
+ message: "Bad request: The following attributes are not allowed to be updated without forcing it (?force=true): entity.name, entity.type"
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entities":[{"type":"host","doc":{"entity":{"id":"host:web-server-prod-01","name":"web-server-prod-01","type":"host","attributes":{"asset":true}},"host":{"name":"web-server-prod-01"}}}]}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/bulk?force=true"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/entities/bulk?force=true
+ {
+ "entities": [
+ {
+ "type": "host",
+ "doc": {
+ "entity": {
+ "id": "host:web-server-prod-01",
+ "name": "web-server-prod-01",
+ "type": "host",
+ "attributes": { "asset": true }
+ },
+ "host": { "name": "web-server-prod-01" }
+ }
+ }
+ ]
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_create.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_create.yaml
new file mode 100644
index 0000000000000..5f474d3dcb958
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_create.yaml
@@ -0,0 +1,85 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ createHostEntityExample:
+ summary: "Create a host entity"
+ description: "Create a new host entity record with basic host and entity fields. The entity identifier must match the auto-generated format for the entity type."
+ value:
+ entity:
+ id: "host:web-server-prod-01"
+ name: "web-server-prod-01"
+ type: "host"
+ source:
+ - "manual"
+ attributes:
+ asset: true
+ managed: true
+ host:
+ name: "web-server-prod-01"
+ hostname:
+ - "web-server-prod-01.example.com"
+ ip:
+ - "10.0.1.42"
+ asset:
+ environment: "production"
+ criticality: "high_impact"
+ business_unit: "Engineering"
+responses:
+ 200:
+ description: "Indicates the entity was successfully created."
+ content:
+ application/json:
+ examples:
+ createSuccessExample:
+ summary: "Entity created"
+ description: "The entity record was successfully created in the Entity Store."
+ value:
+ ok: true
+ 400:
+ description: "Bad request."
+ content:
+ application/json:
+ examples:
+ euidMismatchExample:
+ summary: "Entity identifier mismatch"
+ description: "The supplied entity identifier does not match the auto-generated identifier derived from the entity fields."
+ value:
+ statusCode: 400
+ error: "Bad Request"
+ message: "Bad request: Supplied ID my-custom-id does not match generated EUID host:web-server-prod-01"
+ 409:
+ description: "Conflict."
+ content:
+ application/json:
+ examples:
+ conflictExample:
+ summary: "Entity already exists"
+ description: "An entity with the specified identifier already exists."
+ value:
+ statusCode: 409
+ error: "Conflict"
+ message: "Entity ID 'host:web-server-prod-01' already exists"
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entity":{"id":"host:web-server-prod-01","name":"web-server-prod-01","type":"host","source":["manual"],"attributes":{"asset":true}},"host":{"name":"web-server-prod-01","ip":["10.0.1.42"]}}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/host"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/entities/host
+ {
+ "entity": {
+ "id": "host:web-server-prod-01",
+ "name": "web-server-prod-01",
+ "type": "host",
+ "source": ["manual"],
+ "attributes": { "asset": true }
+ },
+ "host": {
+ "name": "web-server-prod-01",
+ "ip": ["10.0.1.42"]
+ }
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_delete.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_delete.yaml
new file mode 100644
index 0000000000000..1f669da1395cc
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_delete.yaml
@@ -0,0 +1,45 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ deleteEntityExample:
+ summary: "Delete an entity by identifier"
+ description: "Delete a single entity from the Entity Store using its entity identifier."
+ value:
+ entityId: "host:web-server-prod-01"
+responses:
+ 200:
+ description: "Indicates the entity was successfully deleted."
+ content:
+ application/json:
+ examples:
+ deleteSuccessExample:
+ summary: "Entity deleted"
+ description: "The entity was found and successfully removed from the latest index."
+ value:
+ deleted: true
+ 404:
+ description: "Entity not found."
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ summary: "Entity not found"
+ description: "No entity with the specified identifier exists in the Entity Store."
+ value:
+ statusCode: 404
+ error: "Not Found"
+ message: "Entity ID 'host:web-server-prod-01' not found"
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X DELETE -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityId":"host:web-server-prod-01"}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/"
+ - lang: Console
+ source: |
+ DELETE kbn://api/security/entity_store/entities/
+ {
+ "entityId": "host:web-server-prod-01"
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_list.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_list.yaml
new file mode 100644
index 0000000000000..6b2f63426127c
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_list.yaml
@@ -0,0 +1,100 @@
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ pageModeExample:
+ summary: "Page mode response with host entities"
+ description: "A paginated list of host entities sorted by timestamp in descending order, including query inspection data."
+ value:
+ records:
+ - "@timestamp": "2026-04-10T08:30:00.000Z"
+ entity:
+ id: "host:web-server-prod-01"
+ name: "web-server-prod-01"
+ type: "host"
+ source:
+ - "logs"
+ attributes:
+ asset: true
+ managed: true
+ lifecycle:
+ first_seen: "2026-01-15T10:00:00.000Z"
+ last_activity: "2026-04-10T08:30:00.000Z"
+ risk:
+ calculated_level: "Moderate"
+ calculated_score: 47.5
+ calculated_score_norm: 47.5
+ host:
+ name: "web-server-prod-01"
+ hostname:
+ - "web-server-prod-01.example.com"
+ ip:
+ - "10.0.1.42"
+ os:
+ name: "Ubuntu"
+ type: "linux"
+ asset:
+ criticality: "high_impact"
+ environment: "production"
+ total: 1
+ page: 1
+ per_page: 10
+ inspect:
+ dsl:
+ - '{"index":["entities-latest-default"],"body":{"terms":{"entity.EngineMetadata.Type":["host"]}}}'
+ response:
+ - '{"took":1,"timed_out":false,"hits":{"total":{"value":1,"relation":"eq"}}}'
+ searchAfterModeExample:
+ summary: "Search-after mode response"
+ description: "A cursor-based response with entities and a search_after token for the next page."
+ value:
+ entities:
+ - "@timestamp": "2026-04-10T08:30:00.000Z"
+ entity:
+ id: "user:jane.doe@example.com"
+ name: "jane.doe"
+ type: "user"
+ user:
+ name: "jane.doe"
+ email:
+ - "jane.doe@example.com"
+ nextSearchAfter:
+ - 1712736600000
+ - 1
+ emptyResultExample:
+ summary: "Empty result"
+ description: "No entities matched the query."
+ value:
+ records: []
+ total: 0
+ page: 1
+ per_page: 10
+ 400:
+ description: "Bad request."
+ content:
+ application/json:
+ examples:
+ invalidFilterExample:
+ summary: "Invalid filter"
+ description: "The provided Kibana Query Language filter could not be parsed."
+ value:
+ statusCode: 400
+ error: "Bad Request"
+ message: "Invalid filter: Expected \"(\", \"{\", value, whitespace but \":\" found.\ninvalid :: query\n---------^"
+ mixedModesExample:
+ summary: "Mixed pagination modes"
+ description: "Cannot combine page-based pagination with cursor-based pagination in the same request."
+ value:
+ statusCode: 400
+ error: "Bad Request"
+ message: "[request query]: Cannot combine page/per_page with searchAfter"
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X GET -H "Authorization: ApiKey ${API_KEY}" \
+ "${KIBANA_URL}/api/security/entity_store/entities?entity_types=host&page=1&per_page=10&sort_field=%40timestamp&sort_order=desc"
+ - lang: Console
+ source: |
+ GET kbn://api/security/entity_store/entities?entity_types=host&page=1&per_page=10&sort_field=@timestamp&sort_order=desc
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_update.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_update.yaml
new file mode 100644
index 0000000000000..d93080581e03a
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entities_update.yaml
@@ -0,0 +1,78 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ updateEntityAttributesExample:
+ summary: "Update entity attributes"
+ description: "Update the attributes of an existing user entity. Fields like entity.name and entity.type are protected and require the force query parameter."
+ value:
+ entity:
+ id: "user:jane.doe@example.com"
+ name: "jane.doe"
+ type: "user"
+ attributes:
+ managed: true
+ mfa_enabled: true
+ lifecycle:
+ last_activity: "2026-04-10T14:30:00.000Z"
+ user:
+ name: "jane.doe"
+ email:
+ - "jane.doe@example.com"
+ roles:
+ - "admin"
+ - "analyst"
+responses:
+ 200:
+ description: "Indicates the entity was successfully updated."
+ content:
+ application/json:
+ examples:
+ updateSuccessExample:
+ summary: "Entity updated"
+ description: "The entity record was successfully updated."
+ value:
+ ok: true
+ 400:
+ description: "Bad request."
+ content:
+ application/json:
+ examples:
+ protectedFieldsExample:
+ summary: "Protected fields without force"
+ description: "The request attempts to update protected fields without the force query parameter."
+ value:
+ statusCode: 400
+ error: "Bad Request"
+ message: "Bad request: The following attributes are not allowed to be updated without forcing it (?force=true): entity.name, entity.type"
+ 404:
+ description: "Entity not found."
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ summary: "Entity not found"
+ description: "No entity with the specified identifier exists."
+ value:
+ statusCode: 404
+ error: "Not Found"
+ message: "Entity ID 'user:jane.doe@example.com' not found"
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entity":{"id":"user:jane.doe@example.com","name":"jane.doe","type":"user","attributes":{"managed":true,"mfa_enabled":true}},"user":{"name":"jane.doe"}}' \
+ "${KIBANA_URL}/api/security/entity_store/entities/user?force=true"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/entities/user?force=true
+ {
+ "entity": {
+ "id": "user:jane.doe@example.com",
+ "name": "jane.doe",
+ "type": "user",
+ "attributes": { "managed": true, "mfa_enabled": true }
+ },
+ "user": { "name": "jane.doe" }
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_check_privileges.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_check_privileges.yaml
new file mode 100644
index 0000000000000..d863ed5ff965e
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_check_privileges.yaml
@@ -0,0 +1,42 @@
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ allPrivilegesGrantedExample:
+ summary: "All privileges granted"
+ description: "The current user has all required Elasticsearch privileges to use the Entity Store."
+ value:
+ privileges:
+ elasticsearch:
+ index:
+ "entities-latest-default":
+ read: true
+ write: true
+ kibana: {}
+ has_all_required: true
+ has_read_permissions: true
+ has_write_permissions: true
+ missingPrivilegesExample:
+ summary: "Missing privileges"
+ description: "The current user is missing write privileges on the entity index."
+ value:
+ privileges:
+ elasticsearch:
+ index:
+ "entities-latest-default":
+ read: true
+ write: false
+ kibana: {}
+ has_all_required: false
+ has_read_permissions: true
+ has_write_permissions: false
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X GET -H "Authorization: ApiKey ${API_KEY}" \
+ "${KIBANA_URL}/api/security/entity_store/check_privileges"
+ - lang: Console
+ source: |
+ GET kbn://api/security/entity_store/check_privileges
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_install.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_install.yaml
new file mode 100644
index 0000000000000..cff1b1fdee3b1
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_install.yaml
@@ -0,0 +1,73 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ installDefaultExample:
+ summary: "Install with default entity types"
+ description: "Install the Entity Store for all entity types with default log extraction settings."
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ logExtraction: {}
+ installWithCustomSettingsExample:
+ summary: "Install with custom log extraction"
+ description: "Install the Entity Store for host entities only with a custom lookback period and field history length."
+ value:
+ entityTypes:
+ - host
+ logExtraction:
+ lookbackPeriod: "12h"
+ frequency: "5m"
+ delay: "2m"
+ fieldHistoryLength: 20
+ filter: "host.os.type: linux"
+responses:
+ 201:
+ description: "Indicates the Entity Store was successfully installed."
+ content:
+ application/json:
+ examples:
+ installSuccessExample:
+ summary: "Entity Store installed"
+ description: "The Entity Store was installed and engines are being created."
+ value:
+ ok: true
+ 200:
+ description: "Indicates all requested entity types are already installed."
+ content:
+ application/json:
+ examples:
+ alreadyInstalledExample:
+ summary: "Already installed"
+ description: "All requested entity types were already installed."
+ value:
+ ok: true
+ 403:
+ description: "Insufficient privileges."
+ content:
+ application/json:
+ examples:
+ forbiddenExample:
+ summary: "Insufficient privileges"
+ description: "The user does not have the required Elasticsearch privileges."
+ value:
+ statusCode: 403
+ error: "Forbidden"
+ message: "User 'analyst' has insufficient privileges"
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"],"logExtraction":{}}' \
+ "${KIBANA_URL}/api/security/entity_store/install"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/install
+ {
+ "entityTypes": ["user", "host", "service", "generic"],
+ "logExtraction": {}
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_start.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_start.yaml
new file mode 100644
index 0000000000000..58acd105e8b46
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_start.yaml
@@ -0,0 +1,43 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ startAllExample:
+ summary: "Start all entity engines"
+ description: "Start all stopped entity engines."
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ startSingleExample:
+ summary: "Start a single entity engine"
+ description: "Start only the host entity engine."
+ value:
+ entityTypes:
+ - host
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ startSuccessExample:
+ summary: "Engines started"
+ description: "The specified entity engines were successfully started."
+ value:
+ ok: true
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"]}' \
+ "${KIBANA_URL}/api/security/entity_store/start"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/start
+ {
+ "entityTypes": ["user", "host", "service", "generic"]
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_status.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_status.yaml
new file mode 100644
index 0000000000000..536cf24be8e6e
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_status.yaml
@@ -0,0 +1,54 @@
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ runningStatusExample:
+ summary: "Entity Store running"
+ description: "The Entity Store is running with two started engines using default settings."
+ value:
+ status: running
+ engines:
+ - type: host
+ status: started
+ filter: ""
+ delay: "1m"
+ timeout: "25s"
+ frequency: "30s"
+ lookbackPeriod: "3h"
+ fieldHistoryLength: 10
+ docsPerSecond: -1
+ indexPattern: ""
+ enrichPolicyExecutionInterval: null
+ timestampField: "@timestamp"
+ maxPageSearchSize: 10000
+ lastExecutionTimestamp: "2026-04-10T08:30:00.000Z"
+ - type: user
+ status: started
+ filter: ""
+ delay: "1m"
+ timeout: "25s"
+ frequency: "30s"
+ lookbackPeriod: "3h"
+ fieldHistoryLength: 10
+ docsPerSecond: -1
+ indexPattern: ""
+ enrichPolicyExecutionInterval: null
+ timestampField: "@timestamp"
+ maxPageSearchSize: 10000
+ lastExecutionTimestamp: "2026-04-10T08:30:00.000Z"
+ notInstalledExample:
+ summary: "Entity Store not installed"
+ description: "The Entity Store has not been installed."
+ value:
+ status: not_installed
+ engines: []
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X GET -H "Authorization: ApiKey ${API_KEY}" \
+ "${KIBANA_URL}/api/security/entity_store/status?include_components=false"
+ - lang: Console
+ source: |
+ GET kbn://api/security/entity_store/status?include_components=false
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_stop.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_stop.yaml
new file mode 100644
index 0000000000000..e04eb46270d4a
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_stop.yaml
@@ -0,0 +1,37 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ stopAllExample:
+ summary: "Stop all entity engines"
+ description: "Stop all running entity engines."
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ stopSuccessExample:
+ summary: "Engines stopped"
+ description: "The specified entity engines were successfully stopped."
+ value:
+ ok: true
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"]}' \
+ "${KIBANA_URL}/api/security/entity_store/stop"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store/stop
+ {
+ "entityTypes": ["user", "host", "service", "generic"]
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_uninstall.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_uninstall.yaml
new file mode 100644
index 0000000000000..eff01a95dda7c
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_uninstall.yaml
@@ -0,0 +1,43 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ uninstallAllExample:
+ summary: "Uninstall all entity types"
+ description: "Uninstall all entity engines from the Entity Store."
+ value:
+ entityTypes:
+ - user
+ - host
+ - service
+ - generic
+ uninstallSingleExample:
+ summary: "Uninstall a single entity type"
+ description: "Uninstall only the host engine from the Entity Store."
+ value:
+ entityTypes:
+ - host
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ uninstallSuccessExample:
+ summary: "Entity Store uninstalled"
+ description: "The specified entity engines were successfully uninstalled."
+ value:
+ ok: true
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entityTypes":["user","host","service","generic"]}' \
+ "${KIBANA_URL}/api/security/entity_store/uninstall"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/uninstall
+ {
+ "entityTypes": ["user", "host", "service", "generic"]
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_update.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_update.yaml
new file mode 100644
index 0000000000000..0ed6c28bd2579
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/entity_store_update.yaml
@@ -0,0 +1,64 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ updateLogExtractionExample:
+ summary: "Update log extraction settings"
+ description: "Update the log extraction configuration with a new lookback period and frequency."
+ value:
+ logExtraction:
+ lookbackPeriod: "6h"
+ frequency: "10m"
+ fieldHistoryLength: 15
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ updateSuccessExample:
+ summary: "Entity Store updated"
+ description: "The Entity Store configuration was successfully updated."
+ value:
+ ok: true
+ 400:
+ description: "Bad request."
+ content:
+ application/json:
+ examples:
+ invalidDurationExample:
+ summary: "Invalid duration parameter"
+ description: "A log extraction parameter has an invalid duration format."
+ value:
+ statusCode: 400
+ error: "Bad Request"
+ message: "[request body]: logExtraction.frequency: must be a valid duration of at least 30 seconds (e.g. 1m, 30s)"
+ 404:
+ description: "Entity Store not found."
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ summary: "Entity Store not installed"
+ description: "The Entity Store has not been installed yet."
+ value:
+ statusCode: 404
+ error: "Not Found"
+ message: "Entity store is not installed"
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X PUT -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"logExtraction":{"lookbackPeriod":"6h","frequency":"10m","fieldHistoryLength":15}}' \
+ "${KIBANA_URL}/api/security/entity_store"
+ - lang: Console
+ source: |
+ PUT kbn://api/security/entity_store
+ {
+ "logExtraction": {
+ "lookbackPeriod": "6h",
+ "frequency": "10m",
+ "fieldHistoryLength": 15
+ }
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/resolution_group.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/resolution_group.yaml
new file mode 100644
index 0000000000000..d5af16a413f0c
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/resolution_group.yaml
@@ -0,0 +1,64 @@
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ resolutionGroupExample:
+ summary: "Resolution group with linked entities"
+ description: "Returns the resolution group for an entity, including the target entity, all aliases, and the group size."
+ value:
+ target:
+ "@timestamp": "2026-04-10T08:30:00.000Z"
+ user:
+ name: "jane.doe"
+ email:
+ - "jane.doe@example.com"
+ entity:
+ name: "jane.doe"
+ id: "user:jane.doe@example.com"
+ type: "user"
+ aliases:
+ - "@timestamp": "2026-04-10T08:25:00.000Z"
+ user:
+ name: "jdoe"
+ entity:
+ name: "jdoe"
+ id: "user:jdoe@example.com"
+ type: "user"
+ relationships:
+ resolution:
+ resolved_to: "user:jane.doe@example.com"
+ group_size: 2
+ 400:
+ description: "Bad request."
+ content:
+ application/json:
+ examples:
+ truncatedSearchExample:
+ summary: "Search results truncated"
+ description: "The resolution search returned too many results and was truncated."
+ value:
+ statusCode: 400
+ error: "Bad Request"
+ message: "Resolution search truncated"
+ 404:
+ description: "Entity not found."
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ summary: "Entity not found"
+ description: "The specified entity does not exist or has no resolution group."
+ value:
+ statusCode: 404
+ error: "Not Found"
+ message: "Entities not found: [user:nonexistent@example.com]"
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X GET -H "Authorization: ApiKey ${API_KEY}" \
+ "${KIBANA_URL}/api/security/entity_store/resolution/group?entity_id=user%3Ajane.doe%40example.com"
+ - lang: Console
+ source: |
+ GET kbn://api/security/entity_store/resolution/group?entity_id=user:jane.doe@example.com
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/resolution_link.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/resolution_link.yaml
new file mode 100644
index 0000000000000..a211e4c0791fe
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/resolution_link.yaml
@@ -0,0 +1,72 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ linkEntitiesExample:
+ summary: "Link entities to a target"
+ description: "Link two user entities to a target entity, creating a resolution group."
+ value:
+ target_id: "user:jane.doe@example.com"
+ entity_ids:
+ - "user:jdoe@example.com"
+ - "user:j.doe@example.com"
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ linkSuccessExample:
+ summary: "Entities linked"
+ description: "The entities were successfully linked to the target entity."
+ value:
+ linked:
+ - "user:jdoe@example.com"
+ - "user:j.doe@example.com"
+ skipped: []
+ target_id: "user:jane.doe@example.com"
+ 400:
+ description: "Bad request."
+ content:
+ application/json:
+ examples:
+ selfLinkExample:
+ summary: "Self-link error"
+ description: "Cannot link an entity to itself."
+ value:
+ statusCode: 400
+ error: "Bad Request"
+ message: "Cannot link entity 'user:jane.doe@example.com' to itself."
+ mixedTypesExample:
+ summary: "Mixed entity types"
+ description: "All entities in a resolution group must be of the same type."
+ value:
+ statusCode: 400
+ error: "Bad Request"
+ message: "Cannot link entities of different types"
+ 404:
+ description: "Entities not found."
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ summary: "Entities not found"
+ description: "One or more of the specified entity identifiers were not found."
+ value:
+ statusCode: 404
+ error: "Not Found"
+ message: "Entities not found: [user:nonexistent@example.com, user:also-nonexistent@example.com]"
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"target_id":"user:jane.doe@example.com","entity_ids":["user:jdoe@example.com"]}' \
+ "${KIBANA_URL}/api/security/entity_store/resolution/link"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/resolution/link
+ {
+ "target_id": "user:jane.doe@example.com",
+ "entity_ids": ["user:jdoe@example.com"]
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/resolution_unlink.yaml b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/resolution_unlink.yaml
new file mode 100644
index 0000000000000..7142b8b39753a
--- /dev/null
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/examples/resolution_unlink.yaml
@@ -0,0 +1,50 @@
+requestBody:
+ content:
+ application/json:
+ examples:
+ unlinkEntitiesExample:
+ summary: "Unlink entities from their resolution group"
+ description: "Remove entities from their resolution group, restoring them as standalone entities."
+ value:
+ entity_ids:
+ - "user:jdoe@example.com"
+ - "user:j.doe@example.com"
+responses:
+ 200:
+ description: "Indicates a successful response."
+ content:
+ application/json:
+ examples:
+ unlinkSuccessExample:
+ summary: "Entities unlinked"
+ description: "The entities were successfully removed from their resolution group."
+ value:
+ unlinked:
+ - "user:jdoe@example.com"
+ - "user:j.doe@example.com"
+ skipped: []
+ 404:
+ description: "Entities not found."
+ content:
+ application/json:
+ examples:
+ notFoundExample:
+ summary: "Entities not found"
+ description: "One or more of the specified entity identifiers were not found."
+ value:
+ statusCode: 404
+ error: "Not Found"
+ message: "Entities not found: [user:nonexistent@example.com]"
+x-codeSamples:
+ - lang: curl
+ source: |
+ curl -X POST -H "kbn-xsrf: true" -H "Authorization: ApiKey ${API_KEY}" \
+ -H "Content-Type: application/json" \
+ -d '{"entity_ids":["user:jdoe@example.com"]}' \
+ "${KIBANA_URL}/api/security/entity_store/resolution/unlink"
+ - lang: Console
+ source: |
+ POST kbn://api/security/entity_store/resolution/unlink
+ {
+ "entity_ids": ["user:jdoe@example.com"]
+ }
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_ccs_extract_to_updates.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_ccs_extract_to_updates.ts
index 7231f9de44150..fcda39059024b 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_ccs_extract_to_updates.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_ccs_extract_to_updates.ts
@@ -33,6 +33,9 @@ export function registerForceCcsExtractToUpdates(router: EntityStorePluginRouter
.post({
path: ENTITY_STORE_ROUTES.internal.FORCE_CCS_EXTRACT_TO_UPDATES,
access: 'internal',
+ summary: 'Force cross-cluster search extraction',
+ description:
+ 'Trigger an immediate cross-cluster search extraction for the specified entity type, index patterns, and date range.',
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_history_snapshot.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_history_snapshot.ts
index 6228592f7c3cf..3474e24969ee1 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_history_snapshot.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_history_snapshot.ts
@@ -16,6 +16,8 @@ export function registerForceHistorySnapshot(router: EntityStorePluginRouter) {
.post({
path: ENTITY_STORE_ROUTES.internal.FORCE_HISTORY_SNAPSHOT,
access: 'internal',
+ summary: 'Force history snapshot',
+ description: 'Trigger an immediate history snapshot of all entity engines.',
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_log_extraction.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_log_extraction.ts
index cd0766b5187ce..acf78b0440c89 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_log_extraction.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/force_log_extraction.ts
@@ -28,6 +28,9 @@ export function registerForceLogExtraction(router: EntityStorePluginRouter) {
.post({
path: ENTITY_STORE_ROUTES.internal.FORCE_LOG_EXTRACTION,
access: 'internal',
+ summary: 'Force log extraction',
+ description:
+ 'Trigger an immediate log extraction run for the specified entity type and date range.',
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/install/index.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/install/index.ts
index 8c4aa57873c00..d942372958e84 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/install/index.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/install/index.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
import { DEFAULT_ENTITY_STORE_PERMISSIONS } from '../../constants';
@@ -19,6 +20,12 @@ export function registerInstall(router: EntityStorePluginRouter) {
.post({
path: ENTITY_STORE_ROUTES.public.INSTALL,
access: 'public',
+ summary: 'Install the Entity Store',
+ description:
+ 'Install the Entity Store, creating engines for the specified entity types and configuring log extraction.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -32,6 +39,9 @@ export function registerInstall(router: EntityStorePluginRouter) {
body: buildRouteValidationWithZod(BodySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, '../examples/entity_store_install.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res): Promise => {
const entityStoreCtx = await ctx.entityStore;
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/group.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/group.ts
index 07abf0585a3da..4091fdb4d2537 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/group.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/group.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
@@ -16,7 +17,7 @@ import { enterpriseLicenseMiddleware } from '../../middleware/enterprise_license
import { EntitiesNotFoundError, ResolutionSearchTruncatedError } from '../../../domain/errors';
const querySchema = z.object({
- entity_id: z.string(),
+ entity_id: z.string().describe('The entity identifier to look up the resolution group for.'),
});
export function registerResolutionGroup(router: EntityStorePluginRouter) {
@@ -24,6 +25,12 @@ export function registerResolutionGroup(router: EntityStorePluginRouter) {
.get({
path: ENTITY_STORE_ROUTES.public.RESOLUTION_GROUP,
access: 'public',
+ summary: 'Get resolution group',
+ description:
+ 'Get the resolution group for a given entity, returning all linked entities. Requires an enterprise license.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: RESOLUTION_ENTITY_STORE_PERMISSIONS,
},
@@ -37,6 +44,9 @@ export function registerResolutionGroup(router: EntityStorePluginRouter) {
query: buildRouteValidationWithZod(querySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, '../examples/resolution_group.yaml'),
+ },
},
wrapMiddlewares(
async (ctx, req, res): Promise => {
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/link.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/link.ts
index 8803049b21a44..5fafdcabb7b75 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/link.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/link.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
@@ -23,8 +24,12 @@ import {
} from '../../../domain/errors';
const bodySchema = z.object({
- target_id: z.string(),
- entity_ids: z.array(z.string()).min(1).max(1000),
+ target_id: z.string().describe('The entity identifier to resolve the linked entities to.'),
+ entity_ids: z
+ .array(z.string())
+ .min(1)
+ .max(1000)
+ .describe('Entity identifiers to link to the target entity. Minimum 1, maximum 1000.'),
});
export function registerResolutionLink(router: EntityStorePluginRouter) {
@@ -32,6 +37,12 @@ export function registerResolutionLink(router: EntityStorePluginRouter) {
.post({
path: ENTITY_STORE_ROUTES.public.RESOLUTION_LINK,
access: 'public',
+ summary: 'Link entities',
+ description:
+ 'Link one or more entities to a target entity, creating a resolution group. Requires an enterprise license.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: RESOLUTION_ENTITY_STORE_PERMISSIONS,
},
@@ -45,6 +56,9 @@ export function registerResolutionLink(router: EntityStorePluginRouter) {
body: buildRouteValidationWithZod(bodySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, '../examples/resolution_link.yaml'),
+ },
},
wrapMiddlewares(
async (ctx, req, res): Promise => {
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/unlink.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/unlink.ts
index 88c480662a1dd..2af90502695b0 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/unlink.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/resolution/unlink.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
@@ -16,7 +17,11 @@ import { enterpriseLicenseMiddleware } from '../../middleware/enterprise_license
import { EntitiesNotFoundError } from '../../../domain/errors';
const bodySchema = z.object({
- entity_ids: z.array(z.string()).min(1).max(1000),
+ entity_ids: z
+ .array(z.string())
+ .min(1)
+ .max(1000)
+ .describe('Entity identifiers to unlink from their resolution group. Minimum 1, maximum 1000.'),
});
export function registerResolutionUnlink(router: EntityStorePluginRouter) {
@@ -24,6 +29,12 @@ export function registerResolutionUnlink(router: EntityStorePluginRouter) {
.post({
path: ENTITY_STORE_ROUTES.public.RESOLUTION_UNLINK,
access: 'public',
+ summary: 'Unlink entities',
+ description:
+ 'Remove one or more entities from their resolution group. Requires an enterprise license.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: RESOLUTION_ENTITY_STORE_PERMISSIONS,
},
@@ -37,6 +48,9 @@ export function registerResolutionUnlink(router: EntityStorePluginRouter) {
body: buildRouteValidationWithZod(bodySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, '../examples/resolution_unlink.yaml'),
+ },
},
wrapMiddlewares(
async (ctx, req, res): Promise => {
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/start.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/start.ts
index eaf2ff098a972..3a64bc1ac66ef 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/start.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/start.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
@@ -16,7 +17,11 @@ import { ALL_ENTITY_TYPES, EntityType } from '../../../common/domain/definitions
import { ENGINE_STATUS } from '../../domain/constants';
const bodySchema = z.object({
- entityTypes: z.array(EntityType).optional().default(ALL_ENTITY_TYPES),
+ entityTypes: z
+ .array(EntityType)
+ .optional()
+ .default(ALL_ENTITY_TYPES)
+ .describe('Entity types to start. Defaults to all installed types.'),
});
export function registerStart(router: EntityStorePluginRouter) {
@@ -24,6 +29,12 @@ export function registerStart(router: EntityStorePluginRouter) {
.put({
path: ENTITY_STORE_ROUTES.public.START,
access: 'public',
+ summary: 'Start Entity Store engines',
+ description:
+ 'Start previously stopped entity engines, resuming data processing for the specified entity types.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -37,6 +48,9 @@ export function registerStart(router: EntityStorePluginRouter) {
body: buildRouteValidationWithZod(bodySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, 'examples/entity_store_start.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res): Promise => {
const entityStoreCtx = await ctx.entityStore;
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/status.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/status.ts
index eed657e945824..064bf14d47573 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/status.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/status.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod, BooleanFromString } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
@@ -44,7 +45,9 @@ interface EntityStoreStatusResponseBody {
}
const querySchema = z.object({
- include_components: BooleanFromString.optional().default(false),
+ include_components: BooleanFromString.optional()
+ .default(false)
+ .describe('If true, returns a detailed status of each engine including all its components.'),
});
export type StatusRequestQuery = z.infer;
@@ -80,6 +83,12 @@ export function registerStatus(router: EntityStorePluginRouter) {
.get({
path: ENTITY_STORE_ROUTES.public.STATUS,
access: 'public',
+ summary: 'Get Entity Store status',
+ description:
+ 'Get the overall Entity Store status and per-engine statuses, optionally including component-level health details.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -93,6 +102,9 @@ export function registerStatus(router: EntityStorePluginRouter) {
query: buildRouteValidationWithZod(querySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, 'examples/entity_store_status.yaml'),
+ },
},
wrapMiddlewares(
async (ctx, req, res): Promise> => {
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/stop.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/stop.ts
index 407c8019a30e4..34a44f931bc1d 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/stop.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/stop.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
@@ -16,7 +17,11 @@ import { ALL_ENTITY_TYPES, EntityType } from '../../../common/domain/definitions
import { ENGINE_STATUS } from '../../domain/constants';
const bodySchema = z.object({
- entityTypes: z.array(EntityType).optional().default(ALL_ENTITY_TYPES),
+ entityTypes: z
+ .array(EntityType)
+ .optional()
+ .default(ALL_ENTITY_TYPES)
+ .describe('Entity types to stop. Defaults to all running types.'),
});
export function registerStop(router: EntityStorePluginRouter) {
@@ -24,6 +29,12 @@ export function registerStop(router: EntityStorePluginRouter) {
.put({
path: ENTITY_STORE_ROUTES.public.STOP,
access: 'public',
+ summary: 'Stop Entity Store engines',
+ description:
+ 'Stop running entity engines, pausing data processing for the specified entity types.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -37,6 +48,9 @@ export function registerStop(router: EntityStorePluginRouter) {
body: buildRouteValidationWithZod(bodySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, 'examples/entity_store_stop.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res): Promise => {
const entityStoreCtx = await ctx.entityStore;
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/uninstall.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/uninstall.ts
index 6174183c2ac53..fa8d3c7ac1ed3 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/uninstall.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/uninstall.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import { API_VERSIONS, ENTITY_STORE_ROUTES } from '../../../common';
@@ -14,7 +15,11 @@ import { ALL_ENTITY_TYPES, EntityType } from '../../../common/domain/definitions
import { wrapMiddlewares } from '../middleware';
const bodySchema = z.object({
- entityTypes: z.array(EntityType).optional().default(ALL_ENTITY_TYPES),
+ entityTypes: z
+ .array(EntityType)
+ .optional()
+ .default(ALL_ENTITY_TYPES)
+ .describe('Entity types to uninstall. Defaults to all installed types.'),
});
export function registerUninstall(router: EntityStorePluginRouter) {
@@ -22,6 +27,12 @@ export function registerUninstall(router: EntityStorePluginRouter) {
.post({
path: ENTITY_STORE_ROUTES.public.UNINSTALL,
access: 'public',
+ summary: 'Uninstall the Entity Store',
+ description:
+ 'Uninstall the Entity Store, removing engines and associated resources for the specified entity types.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -35,6 +46,9 @@ export function registerUninstall(router: EntityStorePluginRouter) {
body: buildRouteValidationWithZod(bodySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, 'examples/entity_store_uninstall.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res) => {
const {
diff --git a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/update.ts b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/update.ts
index 8d67ced550046..8f8c60274e11f 100644
--- a/x-pack/solutions/security/plugins/entity_store/server/routes/apis/update.ts
+++ b/x-pack/solutions/security/plugins/entity_store/server/routes/apis/update.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import path from 'node:path';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers/v4';
import { z } from '@kbn/zod/v4';
import type { IKibanaResponse } from '@kbn/core-http-server';
@@ -24,6 +25,11 @@ export function registerUpdate(router: EntityStorePluginRouter) {
.put({
path: ENTITY_STORE_ROUTES.public.UPDATE,
access: 'public',
+ summary: 'Update the Entity Store',
+ description: 'Update the Entity Store log extraction configuration.',
+ options: {
+ tags: ['oas-tag:Security entity store'],
+ },
security: {
authz: DEFAULT_ENTITY_STORE_PERMISSIONS,
},
@@ -37,6 +43,9 @@ export function registerUpdate(router: EntityStorePluginRouter) {
body: buildRouteValidationWithZod(bodySchema),
},
},
+ options: {
+ oasOperationObject: () => path.join(__dirname, 'examples/entity_store_update.yaml'),
+ },
},
wrapMiddlewares(async (ctx, req, res): Promise => {
const { logsExtractionClient, logger } = await ctx.entityStore;