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.
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:
/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.p12Copy the two certificate files to the other nodes.
Elasticsearch Master Node Configuration
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.p12Restart the service:
systemctl restart elasticsearchSet Up Authentication Passwords
# Auto‑generate passwords
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
# Or interactively set passwords
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactiveAdd the passwords to the keystore:
/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_passwordVerify node status:
curl -u elastic:Goldwind@2019 http://192.168.73.133:9200/_cat/nodes?vOther 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
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"Logstash Input Configuration (unchanged)
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' } }
}Logstash Output to Elasticsearch (with authentication)
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 }
}
}Fixing the Head Plugin after Installing X‑Pack
Add the following CORS settings to elasticsearch.yml:
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization, X-Requested-With, Content-Length, Content-TypeAccess the Head plugin with credentials, e.g.:
http://192.168.73.133:9100/?auth_user=elastic&auth_password=Goldwind@2019Kibana Web UI
Finally, create new users and assign roles through the Kibana Management UI.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
