<!-- Source: https://docs.squirro.com/en/latest/getting/install/ansible/elasticsearch-tls.html -->
# 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](index.md#ansible).

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

```console
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:

```console
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](../../../a-z/industry-glossary.md#term-SAN) 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

```console
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`:

```ini
[ 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)

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

### Create the certificate for the cluster

```console
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

```console
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

```console
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.

```console
base64 elasticsearch.p12
```

## Configure the cluster

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

```yaml
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.
