Authentication & Authorization

Elasticsearch xpack security — built-in users, custom roles, role mappings, API keys, and securing access to indices.

30m20m reading10m lab

Enabling Security

Security is enabled by default in Elasticsearch 8.x. For earlier versions or Docker setups:

# elasticsearch.yml
xpack.security.enabled: true

In Docker Compose:

environment:
  - xpack.security.enabled=true
  - ELASTIC_PASSWORD=changeme

Built-in Users

Elasticsearch ships with reserved users for internal services:

UserPurpose
elasticSuperuser — full cluster access
kibana_systemKibana connects to Elasticsearch
logstash_systemLogstash monitoring
beats_systemBeats monitoring
apm_systemAPM server
remote_monitoring_userCross-cluster monitoring

Set Built-in User Passwords

Interactive (first time setup):

docker exec -it elasticsearch bin/elasticsearch-setup-passwords interactive

Auto-generate passwords:

docker exec -it elasticsearch bin/elasticsearch-setup-passwords auto

Change a specific password:
curl -k -u elastic:oldpassword -X POST \
  "https://localhost:9200/_security/user/elastic/_password" \
  -H 'Content-Type: application/json' -d'
{
  "password": "newpassword"
}'

Creating Users

Create a User

curl -k -u elastic:changeme -X POST \
  "https://localhost:9200/_security/user/app_reader" \
  -H 'Content-Type: application/json' -d'
{
  "password": "reader_password_123",
  "roles": ["read_logs"],
  "full_name": "Application Log Reader",
  "email": "reader@example.com",
  "enabled": true
}'

List Users

curl -k -u elastic:changeme \
  "https://localhost:9200/_security/user?pretty"

Delete a User

curl -k -u elastic:changeme -X DELETE \
  "https://localhost:9200/_security/user/app_reader"

Roles

Roles define what a user can do. They combine cluster privileges and index privileges.

Create a Read-Only Role

curl -k -u elastic:changeme -X POST \
  "https://localhost:9200/_security/role/read_logs" \
  -H 'Content-Type: application/json' -d'
{
  "cluster": ["monitor"],
  "indices": [
    {
      "names": ["logs-*", "filebeat-*"],
      "privileges": ["read", "view_index_metadata"],
      "field_security": {
        "grant": ["*"],
        "except": ["password", "secret"]
      }
    }
  ]
}'

Create a Write Role

curl -k -u elastic:changeme -X POST \
  "https://localhost:9200/_security/role/write_logs" \
  -H 'Content-Type: application/json' -d'
{
  "cluster": ["monitor", "manage_index_templates"],
  "indices": [
    {
      "names": ["logs-*"],
      "privileges": ["write", "create_index", "create", "index", "delete"]
    }
  ]
}'

Create an Admin Role (Non-Superuser)

curl -k -u elastic:changeme -X POST \
  "https://localhost:9200/_security/role/cluster_admin" \
  -H 'Content-Type: application/json' -d'
{
  "cluster": [
    "monitor",
    "manage",
    "manage_ilm",
    "manage_index_templates",
    "manage_pipeline",
    "manage_ingest_pipelines"
  ],
  "indices": [
    {
      "names": ["*"],
      "privileges": ["all"]
    }
  ]
}'

Cluster Privileges Reference

PrivilegeAccess
allFull cluster access
monitorRead-only cluster state, stats, health
manageCluster management (settings, templates)
manage_securityManage users and roles
manage_ilmManage ILM policies
manage_index_templatesCreate/delete index templates
manage_pipelineManage ingest pipelines
manage_mlManage machine learning jobs

Index Privileges Reference

PrivilegeAccess
allFull index access
readSearch and get
writeIndex, update, delete documents
create_indexCreate new indices
delete_indexDelete indices
manageManage index settings
monitorIndex stats and status
view_index_metadataView mappings, settings, aliases

Field-Level Security

Restrict which fields a role can see:

curl -k -u elastic:changeme -X POST \
  "https://localhost:9200/_security/role/restricted_reader" \
  -H 'Content-Type: application/json' -d'
{
  "indices": [
    {
      "names": ["customers-*"],
      "privileges": ["read"],
      "field_security": {
        "grant": ["name", "email", "created_at"],
        "except": []
      }
    }
  ]
}'

Document-Level Security

Restrict which documents a role can see:

curl -k -u elastic:changeme -X POST \
  "https://localhost:9200/_security/role/team_reader" \
  -H 'Content-Type: application/json' -d'
{
  "indices": [
    {
      "names": ["projects-*"],
      "privileges": ["read"],
      "query": {
        "term": {
          "team": "engineering"
        }
      }
    }
  ]
}'
This user only sees documents where team == "engineering".

API Keys

API keys are the preferred authentication method for services and automation.

Create an API Key

curl -k -u elastic:changeme -X POST \
  "https://localhost:9200/_security/api_key" \
  -H 'Content-Type: application/json' -d'
{
  "name": "logstash-writer",
  "expiration": "30d",
  "role_descriptors": {
    "logstash_writer": {
      "cluster": ["monitor", "manage_index_templates"],
      "indices": [
        {
          "names": ["logstash-*"],
          "privileges": ["write", "create_index"]
        }
      ]
    }
  }
}'

Response includes id and api_key. Use them as:
# Base64 encode id:api_key
echo -n "ID:API_KEY" | base64

# Use in requests
curl -k -H "Authorization: ApiKey BASE64_ENCODED_KEY" \
  "https://localhost:9200/_cluster/health"

Manage API Keys

# List all API keys
curl -k -u elastic:changeme \
  "https://localhost:9200/_security/api_key?pretty"

# Invalidate an API key
curl -k -u elastic:changeme -X DELETE \
  "https://localhost:9200/_security/api_key" \
  -H 'Content-Type: application/json' -d'
{
  "ids": ["key-id-here"]
}'

Service Authentication for the Stack

Kibana

# kibana.yml
elasticsearch.username: "kibana_system"
elasticsearch.password: "kibana_password"

Logstash

# logstash output
output {
  elasticsearch {
    hosts => ["https://elasticsearch:9200"]
    user => "logstash_writer"
    password => "writer_password"
    ssl_certificate_authorities => "/etc/logstash/certs/ca.crt"
  }
}

Filebeat

# filebeat.yml
output.elasticsearch:
  hosts: ["https://elasticsearch:9200"]
  username: "filebeat_writer"
  password: "writer_password"
  ssl.certificate_authorities: ["/etc/filebeat/certs/ca.crt"]

Security Checklist

SettingStatus
xpack.security.enabled: true
Transport TLS enabled
HTTP TLS enabled
Default passwords changed
elastic superuser password secured
Service accounts created (Kibana, Logstash, Beats)
Application roles created with least privilege
API keys used for automation
Field-level security for sensitive data
Anonymous access disabled

Lab: Secure Your Cluster

  1. 1 Enable security and set passwords for built-in users
  2. 2 Create a read-only role for the logs-* index pattern
  3. 3 Create a user with the read-only role
  4. 4 Test access — verify the user can read but not write
  5. 5 Create an API key for a Logstash writer
  6. 6 Test the API key with a curl request

Next Steps

Discussion