Securing a cluster
|
This section documents the current Elasticsearch 9.x line (with 8.19 as the final 8.x release) as published at the Elasticsearch documentation, which is the reference these pages are written and verified against. No specific patch version is pinned. Some capabilities (Kibana-only UIs, the ML/NLP model-management workflow, cross-cluster replication, and parts of the paid / serverless-only surface) are linked, not documented in depth. This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production, as Elasticsearch iterates quickly. This section’s bibliography lists the reference material consulted while preparing these pages. |
Elasticsearch security has three layers: TLS on every connection, an authentication step that resolves a request to a user, and a role-based authorization step that decides what that user may do. Security is enabled by default — a fresh node configures TLS and creates its own certificates on first start. This page covers that first-start flow, the authentication realms, and how roles, users, and role mappings grant access down to the field and document level. See Secure the Elastic Stack for the full checklist.
Transport & HTTP TLS and the first-start enrollment flow
Security on by default
Starting a node from a stock distribution auto-configures the xpack.security. settings: TLS is
required on the *transport layer (node-to-node, port 9300) and on the HTTP layer (client REST,
port 9200), a CA and node certificates are generated into config/certs/, and the built-in users
are created. The node prints the elastic user’s password and a Kibana enrollment token once to
the terminal on that first start. See
Start the Elastic Stack with security enabled.
# config/elasticsearch.yml as written by auto-configuration (abridged).
xpack.security.enabled: true
xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: certs/transport.p12
truststore.path: certs/transport.p12
xpack.security.http.ssl:
enabled: true
keystore.path: certs/http.p12
# https://www.elastic.co/guide/en/elasticsearch/reference/current/security-basic-setup.html
The transport layer uses verification_mode: certificate so any node presenting a cert from the
cluster CA can join; set it to full to also check hostnames. To secure a cluster that was started
with security off, run bin/elasticsearch-certutil to build a CA and certs and set the same keys by
hand — see
Set up basic security
and
…with HTTPS.
Enrollment tokens and password reset
A new node joins an existing secured cluster with an enrollment token: a base64 blob carrying the CA fingerprint and a one-time key. Generate it on a running node and pass it to the joining node (or to Kibana), which then pulls the CA and gets its own certificates automatically.
# On a running node: mint a token for another Elasticsearch node, or for Kibana.
bin/elasticsearch-create-enrollment-token -s node
bin/elasticsearch-create-enrollment-token -s kibana
# On the joining node, first start only:
bin/elasticsearch --enrollment-token <PASTE_NODE_TOKEN_HERE>
# Lost the elastic password, or need a bootstrap password for kibana_system:
bin/elasticsearch-reset-password -u elastic
bin/elasticsearch-reset-password -u kibana_system --auto # print a random one
# https://www.elastic.co/guide/en/elasticsearch/reference/current/reset-password.html
Built-in users
The reserved users live in a special index and back the stack’s own components. Their privileges are fixed; you only set their passwords.
| User | Purpose |
|---|---|
|
Superuser for bootstrap. Set a strong password and stop using it for day-to-day work. |
|
The account Kibana uses to talk to Elasticsearch (not for logging in to Kibana). |
|
Logstash monitoring and the Elasticsearch output’s management calls. |
|
Monitoring data from Beats and APM Server. |
|
Used by Metricbeat to collect monitoring data from the cluster. |
# Set kibana_system's password non-interactively via the change-password API.
curl -sk -u elastic:<ELASTIC_PASSWORD> -X POST \
"https://localhost:9200/_security/user/kibana_system/_password" \
-H 'Content-Type: application/json' \
-d '{ "password": "<GENERATED_PASSWORD>" }'
# https://www.elastic.co/guide/en/elasticsearch/reference/current/built-in-users.html
Authentication realms
A realm authenticates a credential and produces a user with a set of group/role names. Realms are
chained by an order value and consulted in turn until one authenticates the request. The native
and file realms are enabled implicitly; the rest are added under
xpack.security.authc.realms.<type>.<name> in elasticsearch.yml. See
Set up authentication
and Realms.
native and file
The native realm stores users and their hashed passwords in Elasticsearch itself and is managed
entirely through the _security API — this is the default for human users without an external
directory. The file realm reads config/users and config/users_roles on each node; it is meant
for a handful of break-glass accounts that must work even if the cluster is unhealthy.
# native realm: create a user (see the Authorization section for the role).
POST /_security/user/ada
{
"password": "<GENERATED_PASSWORD>",
"roles": [ "app_reader" ],
"full_name": "Ada Lovelace",
"email": "ada@example.com"
}
# file realm: add a break-glass admin on one node.
bin/elasticsearch-users useradd breakglass -p <GENERATED_PASSWORD> -r superuser
# https://www.elastic.co/guide/en/elasticsearch/reference/current/file-realm.html
LDAP and Active Directory
The ldap realm authenticates a bind and then runs a group search; the active_directory realm is
the same with AD’s defaults baked in. Groups come back as distinguished names that a role mapping
(below) turns into roles. Store the bind password in the keystore, not the YAML.
xpack.security.authc.realms.ldap.ldap1:
order: 2
url: "ldaps://ldap.example.com:636"
bind_dn: "cn=es,ou=services,dc=example,dc=com"
user_search.base_dn: "ou=people,dc=example,dc=com"
group_search.base_dn: "ou=groups,dc=example,dc=com"
ssl.certificate_authorities: [ "certs/ldap-ca.crt" ]
# bin/elasticsearch-keystore add xpack.security.authc.realms.ldap.ldap1.secure_bind_password
# https://www.elastic.co/guide/en/elasticsearch/reference/current/ldap-realm.html
SAML and OIDC
For browser SSO through Kibana, use the saml or oidc realm: Elasticsearch is the service
provider / relying party and the identity provider asserts the user and their groups. Both realms
are driven by dedicated _security APIs that Kibana calls during the login handshake.
xpack.security.authc.realms.saml.saml1:
order: 3
idp.metadata.path: "saml/idp-metadata.xml"
idp.entity_id: "https://idp.example.com/"
sp.entity_id: "https://kibana.example.com/"
sp.acs: "https://kibana.example.com/api/security/saml/callback"
attributes.principal: "nameid"
attributes.groups: "http://schemas.xmlsoap.org/claims/Group"
# https://www.elastic.co/guide/en/elasticsearch/reference/current/saml-guide-stack.html
PKI
The pki realm authenticates a client X.509 certificate presented on the TLS handshake — no
password. The certificate’s DN is the principal; a role mapping grants it roles. HTTP client-cert
auth must be turned on for the realm to see the certificate.
xpack.security.authc.realms.pki.pki1:
order: 1
xpack.security.http.ssl.client_authentication: optional
# https://www.elastic.co/guide/en/elasticsearch/reference/current/pki-realm.html
Kerberos
The kerberos realm authenticates a SPNEGO/GSSAPI ticket against a keytab, for environments that
already run an MIT Kerberos or AD KDC. See
Kerberos realm.
xpack.security.authc.realms.kerberos.kerb1:
order: 4
keytab.path: "es.keytab"
API keys — the service-to-service default
For application and service accounts, do not hand out user passwords — issue an API key. A key is
owned by the user who created it, can never exceed that user’s own privileges, may carry its own
scoped role_descriptors, and can be given an expiration. Clients send it in the Authorization:
ApiKey <base64> header.
POST /_security/api_key
{
"name": "billing-service",
"expiration": "90d",
"role_descriptors": {
"billing-writer": {
"cluster": [ "monitor" ],
"indices": [
{ "names": [ "billing-*" ], "privileges": [ "create_doc", "auto_configure" ] }
]
}
},
"metadata": { "team": "payments", "env": "prod" }
}
// Response returns "id" and "api_key" once; the client uses base64(id:api_key).
// https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html
GET /_security/_authenticate // who am I, which realm
GET /_security/api_key?owner=true // list my keys
DELETE /_security/api_key
{ "ids": [ "<API_KEY_ID>" ] } // invalidate
Manage and invalidate keys with the related APIs at Get API key information and Invalidate API key.
Authorization: role-based access control
Every authenticated request is checked against the union of the user’s roles. A role grants
cluster privileges (node-wide actions) and index privileges (per-index-pattern actions), and may
allow run_as impersonation. Unknown actions are denied. See
Authorization.
Roles: cluster and index privileges, run_as
PUT /_security/role/app_reader
{
"cluster": [ "monitor" ],
"indices": [
{
"names": [ "app-*" ],
"privileges": [ "read", "view_index_metadata" ]
}
],
"run_as": [ "report_service" ],
"metadata": { "managed_by": "platform-team" }
}
// Named privileges (read, write, create_doc, index, delete, manage, all, ...) and
// cluster privileges (monitor, manage, manage_security, ...) are listed at
// https://www.elastic.co/guide/en/elasticsearch/reference/current/security-privileges.html
run_as lets a trusted middle-tier authenticate once and then submit each request as the end user
by adding an es-security-runas-user: <username> header, so document-level rules apply per person.
Built-in roles such as superuser, kibana_admin, and viewer cover common cases — see
Built-in roles.
Users and role mappings
Native-realm users get their roles from the roles array on the user document (see the
Authentication section). Users from an external realm (LDAP, SAML, OIDC, PKI, Kerberos) have no such
document — a role mapping assigns roles by matching realm name, username, groups, or metadata.
PUT /_security/role_mapping/sso_app_readers
{
"roles": [ "app_reader" ],
"enabled": true,
"rules": {
"all": [
{ "field": { "realm.name": "saml1" } },
{ "field": { "groups": "cn=app-readers,ou=groups,dc=example,dc=com" } }
]
}
}
// https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-role-mapping.html
Field- and document-level security
An index privilege can restrict which fields a role can see (field_security.grant / except)
and which documents it can see (query, a Query DSL filter evaluated per request). Together they
let one physical index serve many tenants. FLS and DLS require a platform-license tier. See
Field and document level security.
PUT /_security/role/acme_support
{
"indices": [
{
"names": [ "tickets" ],
"privileges": [ "read" ],
"field_security": {
"grant": [ "subject", "body", "status", "@timestamp", "tenant" ],
"except": [ "body.internal_notes" ]
},
"query": { "term": { "tenant": "acme" } }
}
]
}
// A user with this role searching "tickets" only ever sees acme documents,
// and never the body.internal_notes field.
DLS and run_as compose: a middle tier with a per-user query on owner shows each impersonated
user only their own rows. Note that a DLS query cannot use has_child / has_parent on the
join field.
The audit log
Auditing records authentication and authorization events to a separate JSON log
(<cluster>_audit.json) and is enabled per node in elasticsearch.yml. Filter down to the events
that matter to keep volume sane.
xpack.security.audit.enabled: true
xpack.security.audit.logfile.events.include: [ access_denied, authentication_failed, run_as_denied, tampered_request ]
xpack.security.audit.logfile.events.emit_request_body: false
# https://www.elastic.co/guide/en/elasticsearch/reference/current/enable-audit-logging.html
See Audit events for the full event list and the structured fields each one carries.
Cross-cluster security
For cross-cluster search and cross-cluster replication over the API-key-based remote-cluster model, issue a dedicated cross-cluster API key on the remote cluster and configure it on the local one — see Create cross-cluster API key.
Related pages
-
Administration, monitoring & snapshots — operating a secured cluster and keeping the keystore and certificates backed up.
-
Clients & REST conventions — sending API keys and basic auth from the official clients.
-
MongoDB Security and Couchbase Security — how the same authentication-realm and RBAC ideas look in the other databases in this reference.