This guide walks you through installing and configuring the ELK Stack (Elasticsearch, Logstash, and Kibana) with security features enabled.
Elasticsearch requires an official package repository to be added before installation. Run the following commands to add the repository and update your package list:
curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/elastic.gpg
echo "deb https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-8.x.list
apt updateapt install elasticsearchElasticsearch 8.x comes with authentication, authorization, and TLS encryption enabled by default. The autogenerated CA and TLS certificates are stored under:
ls -1l /etc/elasticsearch/certs/Expected output:
http_ca.crt
http.p12
transport.p12
Elasticsearch 8.x Autogenerated CA and TLS Certificates
See etc/elasticsearch/elasticsearch.yml for more details. The CA and
self signed TLS certificates are generated by default and stored under:
--------------------------- Security autoconfiguration information ------------------------------
Authentication and authorization are enabled.
TLS for the transport and HTTP layers is enabled and configured.
The generated password for the elastic built-in superuser is : Zcjz-oCdnxtnK*vyj1ps
If this node should join an existing cluster, you can reconfigure this with
'/usr/share/elasticsearch/bin/elasticsearch-reconfigure-node --enrollment-token <token-here>'
after creating an enrollment token on your existing cluster.
You can complete the following actions at any time:
Reset the password of the elastic built-in superuser with
'/usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic'.
Generate an enrollment token for Kibana instances with
'/usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibana'.
Generate an enrollment token for Elasticsearch nodes with
'/usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s node'.
-------------------------------------------------------------------------------------------------
### NOT starting on installation, please execute the following statements to configure elasticsearch service to start automatically using systemd
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch.service
### You can start elasticsearch service by executing
sudo systemctl start elasticsearch.serviceCheck the elastic password in the output: Zcjz-oCdnxtnK*vyj1ps
Each file serves a different purpose:
http_ca.crt: Self-signed CA certificate for Elasticsearch.http.p12: Encrypts client communication (e.g., Kibana to Elasticsearch).transport.p12: Encrypts cluster communications.
Elastic search Keystore is used to store secrets information for example your p12 passwords, you can look at the contents of the Keystore by using the following command:
/usr/share/elasticsearch/bin/elasticsearch-keystore listModify the Elasticsearch configuration file /etc/elasticsearch/elasticsearch.yml and set the following parameters:
Change cluster.name, node.name and network.host in /etc/elasticsearch/elasticsearch.yml file.
grep -Ev '^#|^$' /etc/elasticsearch/elasticsearch.ymlcluster.name: logs
node.name: logs
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
http.port: 9200
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl:
enabled: true
keystore.path: certs/http.p12
xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: certs/transport.p12
truststore.path: certs/transport.p12
cluster.initial_master_nodes: [ "elk-01" ]
http.host: 0.0.0.0
http.cors.enabled: true
http.cors.allow-origin: "*"systemctl daemon-reload # reload systemd
systemctl enable elasticsearch # enable elasticsearch service
systemctl start elasticsearch # start elasticsearch service
systemctl status elasticsearch # check status of elasticsearch serviceIn case of error, check the logs:
journalctl -fu elasticsearch --since yesterdayTo ensure Elasticsearch is running and responding, use the following command:
curl https://localhost:9200 --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic:Zcjz-oCdnxtnK*vyj1psA successful response should return JSON output with cluster details:
{
"name": "logs",
"cluster_name": "logs",
"cluster_uuid": "dID2u4CmRT6-9fR2YXlOzA",
"version": {
"number": "8.7.0",
"build_flavor": "default",
"build_type": "deb",
"build_hash": "09520b59b6bc1057340b55750186466ea715e30e",
"build_date": "2023-03-27T16:31:09.816451435Z",
"build_snapshot": false,
"lucene_version": "9.5.0",
"minimum_wire_compatibility_version": "7.17.0",
"minimum_index_compatibility_version": "7.0.0"
},
"tagline": "You Know, for Search"
}autoconfiguration.password_hash
keystore.seed
xpack.security.http.ssl.keystore.secure_password
xpack.security.transport.ssl.keystore.secure_password
xpack.security.transport.ssl.truststore.secure_password
You can list them by using the following command:
/usr/share/elasticsearch/bin/elasticsearch-keystore show keystore.seed
/usr/share/elasticsearch/bin/elasticsearch-keystore show xpack.security.http.ssl.keystore.secure_password # this one is used to encrypt client communication
/usr/share/elasticsearch/bin/elasticsearch-keystore show xpack.security.transport.ssl.keystore.secure_password
/usr/share/elasticsearch/bin/elasticsearch-keystore show xpack.security.transport.ssl.truststore.secure_password To open the http.p12 file and look at its contents you can type, password is IFQzPruaSwWIBactv0fIlg:
openssl pkcs12 -nokeys -info -in /etc/elasticsearch/certs/http.p12 Install Kibana using the package manager:
apt install kibanaModify /etc/kibana/kibana.yml to set up Kibana’s host, name, and Elasticsearch connection:
server.port: 5601
server.host: "0.0.0.0"
server.name: "kibana-node"
elasticsearch.hosts: [ "https://localhost:9200" ]Enable Kibana to start on boot and start the service:
systemctl enable kibana
systemctl start kibana
systemctl status kibanaInstall Logstash using the following command:
apt install logstashCreate a logstash_writer role in Elasticsearch to define necessary privileges:
curl -X POST "https://localhost:9200/_security/role/logstash_writer" \
-H 'Content-Type: application/json' \
-u elastic:your_password \
-d'{"cluster": ["manage_index_templates", "monitor", "manage_ilm"], "indices": [ { "names": [ "*" ], "privileges": ["write","create","create_index","manage","manage_ilm"] }]}'Next, create a Logstash user and assign it the logstash_writer role:
curl -X POST "https://localhost:9200/_security/user/logstash" \
-H 'Content-Type: application/json' \
-u elastic:your_password -d'{"password" : "logstash", "roles" : ["logstash_writer"], "full_name" : "Internal Logstash User"}'Enable Logstash to start on boot and start the service:
systemctl enable logstash
systemctl start logstash
systemctl status logstashThen in /etc/kibana/kibana.yml change server.host, server.name and elasticsearch.hosts:
grep -Ev '^#|^$' /etc/kibana/kibana.ymlserver.port: 5601
server.host: "0.0.0.0"
server.name: "logs"
logging:
appenders:
file:
type: file
fileName: /var/log/kibana/kibana.log
layout:
type: json
root:
appenders:
- default
- file
pid.file: /run/kibana/kibana.pidThen use elasticsearch-create-enrollment-token to create token for Kibana:
/usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibanaeyJ2ZXIiOiI4LjE0LjAiLCJhZHIiOlsiMTAuMi4yMDAuMjQ1OjkyMDAiXSwiZmdyIjoiM2JlOWQ0NDA0N2U5ZmYzYjExODhmYTEzODA2MmZlMzJiNjMzNjg5ZGFlYTFjNGRhZWJhMGYyOTZhODU4MTFhMSIsImtleSI6InRveHk5WlVCejh4cy1aQXR4STFVOlBZVmt3WUJjUUxTbEJPSFd6eWlPRmcifQ==And setup kiabana with this token:
/usr/share/kibana/bin/kibana-setup --enrollment-token eyJ2ZXIiOiI4LjE0LjAiLCJhZHIiOlsiMTAuMi4yMDAuMjQ1OjkyMDAiXSwiZmdyIjoiM2JlOWQ0NDA0N2U5ZmYzYjExODhmYTEzODA2MmZlMzJiNjMzNjg5ZGFlYTFjNGRhZWJhMGYyOTZhODU4MTFhMSIsImtleSI6InRveHk5WlVCejh4cy1aQXR4STFVOlBZVmt3WUJjUUxTbEJPSFd6eWlPRmcifQ==There should be created another *.crt files in /var/lib/kibana/ directory:
curl https://localhost:9200 --cacert /var/lib/kibana/ca_1743522857893.crt -u elastic:Zcjz-oCdnxtnK*vyj1psand in /etc/kibana/kibana.yml should be automatically added following lines:
elasticsearch.hosts: [ 'https://10.2.200.245:9200' ]
elasticsearch.serviceAccountToken: AAEAAWVsYXN0aWMva2liYW5hL2Vucm9sbC1wcm9jZXNzLXRva2VuLTE2ODI2MTEyMTQ4NjM6RzU5aWotOVVULWFWVkk4eHUzaDFPUQ
elasticsearch.ssl.certificateAuthorities: [ /var/lib/kibana/ca_1743522857893.crt ]
xpack.fleet.outputs: [ { id: fleet-default-output, name: default, is_default: true, is_default_monitoring: true, type: elasticsearch, hosts: [ 'https://10.2.200.245:9200' ], ca_trusted_fingerprint: 93e437ecdede3340ddae02b9156af68310458bd9807f1e34b25fc5c62c8ef568 } ]systemctl enable kibana
systemctl start kibana
systemctl status kibanaFirst time you should login with elastic user using password Zcjz-oCdnxtnK*vyj1ps. Then you can create new users
with Kibana - under Management > Security > Users.
Then you can add multiple users (e.g. OzzyCzech) with superuser role:
curl -s --cacert /etc/logstash/ca.crt -u elastic:Zcjz-oCdnxtnK*vyj1ps \
-X POST "https://localhost:9200/_security/user/OzzyCzech" -H 'Content-Type: application/json' \
-d'{"password" : "123456", "roles" : ["superuser"], "full_name" : "Roman Ožana"}'first create filebeat_writer role:
curl -s --cacert /etc/logstash/ca.crt -u elastic:Zcjz-oCdnxtnK*vyj1ps \
-X POST "https://localhost:9200/_security/role/filebeat_writer" \
-H 'Content-Type: application/json' \
-d'{"cluster": ["all"], "indices": [ { "names": [ "*" ], "privileges": ["all"] }]}'and filebeat user:
curl -s --cacert /etc/logstash/ca.crt -u elastic:Zcjz-oCdnxtnK*vyj1ps \
-X POST "https://localhost:9200/_security/user/filebeat" \
-H 'Content-Type: application/json' \
-d'{"password" : "filebeat", "roles" : ["filebeat_writer"], "full_name" : "Internal Filebeat User"}'then check if you can login with this user:
curl https://localhost:9200 --cacert /etc/elasticsearch/certs/http_ca.crt -u filebeat:filebeatYou have to get http_ca.crt password from elasticsearch keystore:
# this one is used to encrypt client communication
/usr/share/elasticsearch/bin/elasticsearch-keystore show xpack.security.http.ssl.keystore.secure_passwordThen you have to dump the keys to a PEM file:
openssl pkcs12 -in /etc/elasticsearch/certs/http.p12 -nocerts -nodes \
-out /certs/http_ca_key.pemThe next step is to package up the CA key into its own p12 file:
openssl pkcs12 -export -out /certs/http_ca_key.p12 \
-inkey /certs/http_ca_key.pem \
-in /etc/elasticsearch/certs/http_ca.crtYou will be prompted to enter an export password. Feel free to use the
same password as for /etc/elasticsearch/certs/http.p12.
Now we can generate a key-certificate pair for the logstash instance:
/usr/share/elasticsearch/bin/elasticsearch-certutil cert --ca /certs/http_ca_key.p12 --ip $(ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p') --name client --out /certs/client.p12Since client.crt will contain both the CA and client certificates, you will need to separate them out
into different files. Copy the CA cert into a file named http_ca.crt.
mkdir -p /certs/filebeat
cp /etc/elasticsearch/certs/http_ca.crt /certs/filebeatExtract the certificates from the p12 file as well:
openssl pkcs12 -in /certs/client.p12 -nocerts -nodes -out /certs/filebeat/filebeat.keyopenssl pkcs12 -in /certs/client.p12 -nokeys -nodes -out /certs/filebeat/filebeat.crtDownload certificates to the filebeat host and update the configuration:
output.elasticsearch:
hosts: [ "http://elk-01.int.wikidi.net:9200" ]
username: "filebeat"
password: "filebeat"
ssl.enabled: true
ssl.certificate_authorities: [ "/etc/filebeat/certs/http_ca.crt" ]
ssl.certificate: "/etc/filebeat/certs/filebeat.crt"
ssl.key: "/etc/filebeat/certs/filebeat.key"wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elastic-keyring.gpg
sudo apt-get install apt-transport-https
echo "deb [signed-by=/usr/share/keyrings/elastic-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-8.x.listapt update
apt install apt-transport-httpsFist copy the certificates to logstash directory:
openssl s_client -showcerts -connect localhost:9200 </dev/null 2>/dev/null | openssl x509 > /etc/logstash/ca.crtor you can use the http_ca.crt certificate from elasticsearch:
mkdir /etc/logstash/certs
cp /etc/elasticsearch/certs/http_ca.crt /etc/logstash/ca.crtthen you have to create logstash_writer role:
curl -s --cacert /etc/logstash/ca.crt -u elastic:Zcjz-oCdnxtnK*vyj1ps \
-X POST "https://localhost:9200/_security/role/logstash_writer" -H 'Content-Type: application/json' \
-d'{"cluster": ["manage_index_templates", "monitor", "manage_ilm"], "indices": [ { "names": [ "*" ], "privileges": ["write","create","create_index","manage","manage_ilm"] }]}'and logstash user:
curl -s --cacert /etc/logstash/ca.crt -u elastic:Zcjz-oCdnxtnK*vyj1ps \
-X POST "https://localhost:9200/_security/user/logstash" -H 'Content-Type: application/json' \
-d'{"password" : "logstash", "roles" : ["logstash_writer"], "full_name" : "Internal Logstash User"}'then check if you can login with this user:
curl https://localhost:9200 --cacert /etc/elasticsearch/certs/http_ca.crt -u logstash:logstash{
"name" : "logs",
"cluster_name" : "logs",
"cluster_uuid" : "dID2u4CmRT6-9fR2YXlOzA",
"version" : {
"number" : "8.7.0",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "09520b59b6bc1057340b55750186466ea715e30e",
"build_date" : "2023-03-27T16:31:09.816451435Z",
"build_snapshot" : false,
"lucene_version" : "9.5.0",
"minimum_wire_compatibility_version" : "7.17.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "You Know, for Search"
}then update the logstash.yml file:
xpack.monitoring.enabled: true
xpack.monitoring.elasticsearch.username: logstash
xpack.monitoring.elasticsearch.password: logstashjournalctl -fu logstash --since "5 minute ago"Define the filebeat_writer role in Elasticsearch:
curl -X POST "https://localhost:9200/_security/role/filebeat_writer" \
-H 'Content-Type: application/json' \
-u elastic:your_password -d'{"cluster": ["all"], "indices": [ { "names": [ "*" ], "privileges": ["all"] }]}'Create a Filebeat user with appropriate permissions:
curl -X POST "https://localhost:9200/_security/user/filebeat" \
-H 'Content-Type: application/json' \
-u elastic:your_password -d'{"password" : "filebeat", "roles" : ["filebeat_writer"], "full_name" : "Internal Filebeat User"}'Modify the Filebeat configuration file /etc/filebeat/filebeat.yml to enable secure communication with Elasticsearch:
output.elasticsearch:
hosts: ["https://localhost:9200"]
username: "filebeat"
password: "filebeat"
ssl.enabled: true
ssl.certificate_authorities: ["/etc/filebeat/certs/http_ca.crt"]
ssl.certificate: "/etc/filebeat/certs/filebeat.crt"
ssl.key: "/etc/filebeat/certs/filebeat.key"