Information Security 13 min read

Secure Your ELK Stack Using Free X‑Pack: TLS, Auth, and RBAC

This guide explains how to enable and configure the free core security features of Elastic Stack 6.8/7.1, including TLS encryption, user and role management, Kibana Spaces for multi‑tenant protection, and step‑by‑step setup of certificates, keystore passwords, and Logstash‑to‑Elasticsearch authentication across multiple nodes.

Ops Development Stories
Ops Development Stories
Ops Development Stories
Secure Your ELK Stack Using Free X‑Pack: TLS, Auth, and RBAC

Scenario

Elasticsearch and Kibana are often used by multiple users, so implementing access control is essential for security.

On May 21, 2019 Elastic announced that the core security features of Elastic Stack 6.8.0 and 7.1.0 are now free.

The free features include TLS encryption, user and role management, role‑based access control for cluster and index APIs, and Kibana Spaces for multi‑tenant protection.

1. X‑Pack Evolution

Before 5.x there was no X‑Pack; security, watch, and alert were separate modules. In 5.x they were packaged together as X‑Pack. Prior to 6.3 an extra installation was required; from 6.3 onward X‑Pack is bundled, with basic security in the paid Gold tier. Starting with 7.1 the basic security features became free.

2. How Security Was Handled Before Free Features

Scenario 1: No protection – services run on internal networks without exposing ports.

Scenario 2: Simple protection using Nginx basic auth and firewall rules.

Scenario 3: Third‑party security plugins such as SearchGuard or ReadonlyREST.

Scenario 4: Purchasing Elastic X‑Pack Gold or Platinum for advanced security, alerts, and machine‑learning features.

3. Configuring TLS and Authentication

Generate certificates:

<code>/usr/share/elasticsearch/bin/elasticsearch-certutil ca</code>
<code>/usr/share/elasticsearch/bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12</code>
<code># Press Enter for all prompts; no password needed</code>
<code># Move generated certificates to /etc/elasticsearch/</code>
<code>mv elastic-* /etc/elasticsearch/</code>
<code>chown elasticsearch.elasticsearch elastic-*</code>
<code>chgrp elasticsearch /etc/elasticsearch/elastic-certificates.p12 /etc/elasticsearch/elastic-stack-ca.p12</code>
<code>chmod 640 /etc/elasticsearch/elastic-certificates.p12 /etc/elasticsearch/elastic-stack-ca.p12</code>

Copy the two certificate files to the other nodes.

Elasticsearch Master Node Configuration

<code>cluster.name: elk-cluster
node.name: elk-1
node.master: true
node.data: true
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
bootstrap.memory_lock: false
network.host: 192.168.73.133
http.port: 9200
discovery.zen.ping.unicast.hosts: ["192.168.73.133", "192.168.73.135"]
discovery.zen.minimum_master_nodes: 1
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-credentials: true
http.cors.allow-methods: OPTIONS, HEAD, GET, POST, PUT, DELETE
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: /etc/elasticsearch/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: /etc/elasticsearch/elastic-certificates.p12</code>

Restart the service:

<code>systemctl restart elasticsearch</code>

Set Up Authentication Passwords

<code># Auto‑generate passwords
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
# Or interactively set passwords
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive</code>

Add the passwords to the keystore:

<code>/usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
/usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password</code>

Verify node status:

<code>curl -u elastic:Goldwind@2019 http://192.168.73.133:9200/_cat/nodes?v</code>

Other Elasticsearch Nodes Configuration

Copy the same certificates and keystore to the data nodes, then use a similar

elasticsearch.yml

(adjust

node.name

and

network.host

).

Kibana Configuration

<code>server.port: 5601
server.host: "192.168.73.133"
server.name: "192.168.73.133"
elasticsearch.hosts: ["http://192.168.73.133:9200"]
kibana.index: ".kibana"
elasticsearch.username: "kibana"
elasticsearch.password: "Goldwind@2019"
logging.quiet: true
i18n.locale: "zh-CN"</code>

Logstash Input Configuration (unchanged)

<code>input {
    file { path => "/var/log/messages" type => "system" start_position => "beginning" }
    file { path => "/var/log/secure" type => "secure" start_position => "beginning" }
    file { path => "/var/log/httpd/access_log" type => "http" start_position => "beginning" }
    file { path => "/usr/local/nginx/logs/elk.access.log" type => "nginx" start_position => "beginning" }
}
output {
    if [type] == "http" { redis { host => "192.168.73.133" password => 'root123' port => "6379" db => "2" data_type => "list" key => 'nagios_http' } }
    if [type] == "nginx" { redis { host => "192.168.73.133" password => 'root123' port => "6379" db => "2" data_type => "list" key => 'nagios_nginx' } }
    if [type] == "secure" { redis { host => "192.168.73.133" password => 'root123' port => "6379" db => "2" data_type => "list" key => 'nagios_secure' } }
    if [type] == "system" { redis { host => "192.168.73.133" password => 'root123' port => "6379" db => "2" data_type => "list" key => 'nagios_system' } }
}</code>

Logstash Output to Elasticsearch (with authentication)

<code>output {
    if [type] == "system" {
        elasticsearch { hosts => ["192.168.73.133:9200"] index => "nagios-system-%{+YYYY.MM.dd}" user => "elastic" password => "Goldwind@2019" sniffing => false }
    }
    if [type] == "secure" {
        elasticsearch { hosts => ["192.168.73.133:9200"] index => "nagios-secure-%{+YYYY.MM.dd}" user => "elastic" password => "Goldwind@2019" sniffing => false }
    }
    if [type] == "http" {
        elasticsearch { hosts => ["192.168.73.133:9200"] index => "nagios-http-%{+YYYY.MM.dd}" user => "elastic" password => "Goldwind@2019" sniffing => false }
    }
    if [type] == "nginx" {
        elasticsearch { hosts => ["192.168.73.133:9200"] index => "nagios-nginx-%{+YYYY.MM.dd}" user => "elastic" password => "Goldwind@2019" sniffing => false }
    }
}</code>

Fixing the Head Plugin after Installing X‑Pack

Add the following CORS settings to

elasticsearch.yml

:

<code>http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization, X-Requested-With, Content-Length, Content-Type</code>

Access the Head plugin with credentials, e.g.:

<code>http://192.168.73.133:9100/?auth_user=elastic&auth_password=Goldwind@2019</code>

Kibana Web UI

Kibana UI
Kibana UI
Kibana UI
Kibana UI

Finally, create new users and assign roles through the Kibana Management UI.

ElasticsearchsecurityTLSELKLogstashkibanaX-Pack
Ops Development Stories
Written by

Ops Development Stories

Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.