Use Elasticsearch API keys and least-privilege roles
# A role scoped to one index pattern and specific actionscurl -sk -u elastic -X PUT https://localhost:9200/_security/role/app_search -H 'Content-Type: application/json' -d '{ "indices": [{ "names": ["app-*"], "privileges": ["read", "view_index_metadata"] }]}'
# An API key that grants only that rolecurl -sk -u elastic -X POST https://localhost:9200/_security/api_key -H 'Content-Type: application/json' -d '{ "name": "app-search-key", "role_descriptors": { "app_search": { "indices": [{ "names": ["app-*"], "privileges": ["read"] }] } }}'Why it matters
Section titled “Why it matters”Every credential is a blast radius. An application authenticating as
elastic can read every index,
delete every index, change cluster settings and create users — so a SQL-injection
equivalent, a leaked config file, or a compromised app container hands all of that
to an attacker.
Scope it down and the same leak is bounded: a key limited to read on app-*
reads some documents and can do nothing else. No deletes, no other indices, no
cluster administration.
Elasticsearch’s RBAC makes this cheap, and there’s no reason an application should ever hold more than the specific privileges it uses.
The three levers
Section titled “The three levers”A role descriptor narrows on three axes, and using all three is the point:
| Axis | Example | Effect |
|---|---|---|
| Indices | "names": ["app-*"] |
Cannot touch other indices, including system ones |
| Privileges | ["read", "view_index_metadata"] |
No write, no delete_index, no manage |
| Documents / fields | query and field_security |
Row- and column-level limits within an index |
The index scope is the one people skip. "names": ["*"] in a role is
elastic-lite — it can read everything even if the privileges are narrow.
Document-level security (a query in the role) and field-level security (a
field_security block) go further, letting one key see only certain documents or
certain fields — useful when a reporting tool needs orders but not the PII columns
in them.
API keys beat user passwords for applications
Section titled “API keys beat user passwords for applications”For non-human callers, prefer an API key over a username and password:
- Keys are independently revocable. Kill one application’s key without touching any other credential or restarting anything.
- Keys can be scoped tighter than the user that created them — the
role_descriptorsin the key intersect with the creator’s privileges, so a key is never more powerful than intended even if created by a broad account. - Keys can expire. Set
"expiration": "90d"and the credential rotates itself out. - A leaked key is one key. A leaked user password may be reused across services; a key is minted per consumer.
The one caveat: an API key is a bearer token. Anyone holding it is that key, so it still needs to be stored like a secret and sent only over TLS — which, on a secured cluster, it is.
Related
Section titled “Related”- Built-in users and passwords — stop using elastic for apps.
- Enable TLS — API keys are bearer tokens; they need encryption.