Secure Elasticsearch with SSL/TLS#

This guide will walk you through how to secure your multi-node Elasticsearch cluster with SSL/TLS. This guide assumes you are using the squirro-ansible role.

It uses the most pragmatic approach using long-lived wildcard certificates with SANs for localhost and 127.0.0.1 and a certificate authority (CA) to sign them.

Note

This might not be compliant with your company’s security policies, but it is a good starting point to get your cluster and the traffic from/to and inside the cluster secured. Always consult your security team for the best approach for your company. It is likely that you will need to use short-lived certificates and a certificate authority (CA) that is trusted by your company and each instance of Elasticsearch might need its own certificate.

Create the root CA#

The first step is to create a root CA that will be used to sign the certificates for the cluster.

Generate a root CA key#

openssl genrsa -out rootCA.key 4096

Generate a root CA certificate#

You can adjust the number of days the certificate is valid for, we use 10 years:

openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt

Create the certificate for the cluster#

The next step is to create a certificate for the cluster. We want to cover all the nodes in the cluster, so we will use a wildcard certificate with SANs for localhost and 127.0.0.1.

In this example we will additionally use *.example.local as the wildcard domain, but you should use your own domain. Alternatively, you can add each cluster domain name as a SAN. It is key that each server in the cluster can resolve these domains to the IP addresses of the nodes.

Generate a private key for the certificate#

openssl genrsa -out star.example.local.key 2048

Create a config file for the certificate#

Use the following template, and adjust the C, ST, L, O, OU, and CN values to your needs. Also adjust DNS.3 to your wildcard domain.

Call the file star.example.local.conf:

[ req ]
default_bits        = 2048
prompt              = no
default_md          = sha256
distinguished_name  = req_distinguished_name
req_extensions      = req_ext

[ req_distinguished_name ]
C                   = US
ST                  = New York
L                   = New York City
O                   = Example Inc
OU                  = IT Department
CN                  = *.example.local

[ req_ext ]
subjectAltName      = @alt_names

[ alt_names ]
DNS.1               = localhost
DNS.2               = localhost.localdomain
DNS.3               = *.example.local
IP.1                = 127.0.0.1

Create the signing request for the certificate (CSR)#

openssl req -new -key star.example.local.key -out star.example.local.csr -config star.example.local.conf

Create the certificate for the cluster#

openssl x509 -req -in star.example.local.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out star.example.local.crt -days 3650 -sha256 -extfile star.example.local.conf -extensions req_ext

Create a PKCS#12 file for the certificate and key#

openssl pkcs12 -export -out elasticsearch.p12 -inkey star.example.local.key -in star.example.local.crt -name "server_cert"

Use a strong password for the PKCS#12 file, you will need it later.

Import the ca certificate into the PKCS#12 file#

keytool -importcert -keystore elasticsearch.p12 -storetype PKCS12 -file rootCA.crt -alias "rootca"

Base64 Export#

Create a base64-encoded string of the PKCS#12 file, we will use this as an ansible variable.

base64 elasticsearch.p12

Configure the cluster#

Configure the squirro-ansible role with the following variables on all nodes:

elasticsearch_http_p12_base64_string: "MII..."
elasticsearch_http_p12_password: "..."
elasticsearch_transport_p12_base64_string: "{{ elasticsearch_http_p12_base64_string }}"
elasticsearch_transport_p12_password: "{{ elasticsearch_http_p12_password }}"

Note: Note that you should not put such secrets into plaintext variable, use Ansible vault or other means to encrypt them.

You can also leave away the base64 string variables and manually copy the PKCS#12 file to the nodes. You need to place it in /etc/elasticsearch/certs/http.p12 and /etc/elasticsearch/certs/transport.p12 on every node. In this case you need to handle the distribution/permission of the files yourself.