Setting up OpenDistro Elasticsearch with TLS
I will be showing how to setup OpenDistro Elasticsearch (ES) with TLS for Windows.
References:
- https://opendistro.github.io/for-elasticsearch-docs/
- https://aws.amazon.com/blogs/opensource/add-ssl-certificates-open-distro-for-elasticsearch/
Pre-requisites
- Docker Desktop
- WSL2
- Git Bash
Pull Docker Images
docker pull amazon/opendistro-for-elasticsearch:latest
docker pull amazon/opendistro-for-elasticsearch-kibana:latest
Docker Compose (default certs)
We will be using docker-compose.yml
to run ES. Below is a sample.
version: '3'
services:
odfe-node1:
image: amazon/opendistro-for-elasticsearch:1.12.0
container_name: odfe-node1
environment:
- cluster.name=odfe-cluster
- node.name=odfe-node1
- discovery.seed_hosts=odfe-node1
- cluster.initial_master_nodes=odfe-node1
- bootstrap.memory_lock=true # along with the memlock settings below, disables swapping
- "ES_JAVA_OPTS=-Xms512m -Xmx512m" # minimum and maximum Java heap size, recommend setting both to 50% of system RAM
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 262144 # maximum number of open files for the Elasticsearch user, set to at least 65536 on modern systems
hard: 262144
volumes:
- odfe-data1:/usr/share/elasticsearch/data
ports:
- 9200:9200
- 9600:9600 # required for Performance Analyzer
networks:
- odfe-net
kibana:
image: amazon/opendistro-for-elasticsearch-kibana:1.12.0
container_name: odfe-kibana
ports:
- 5601:5601
expose:
- "5601"
environment:
ELASTICSEARCH_URL: https://odfe-node1:9200
ELASTICSEARCH_HOSTS: https://odfe-node1:9200
networks:
- odfe-net
volumes:
odfe-data1:
networks:
odfe-net:
Potential error you might face:
Max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
In this case, you need to increase the max_map_count
for WSL2. Open powershell and run:
wsl -d docker-desktop
echo 262144 >> /proc/sys/vm/max_map_count
Checking that ES is up
Navigate to localhost:9200
. You should be able to see the following message.
{
"name" : "odfe-node1",
"cluster_name" : "odfe-cluster",
"cluster_uuid" : "fyO3IMS3SoiWqO8PRC6x4A",
"version" : {
"number" : "7.10.0",
"build_flavor" : "oss",
"build_type" : "tar",
"build_hash" : "51e9d6f22758d0374a0f3f5c6e8f3a7997850f96",
"build_date" : "2020-11-09T21:30:33.964949Z",
"build_snapshot" : false,
"lucene_version" : "8.7.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
Generating certificates
The previous steps works off the demo certificates. Next, I will show how to generate your own self-signed CA and node certificates. Welcome to OpenSSL. Windows Powershell comes with OpenSSL.
Step 1: Generate a private key (root-ca-key.pem) using genrsa
command. This file should be kept private.
openssl genrsa -out root-ca-key.pem 2048
Step 2: Generate root certificate (root-ca.pem) Use the private key to generate a self-signed certification for the root CA:
openssl req -new -x509 -sha256 -key root-ca-key.pem -out root-ca.pem -days 3650
Follow the prompts to specify details (CN, OU, O, L, ST, C) for your organization. These details form the distinguished name (DN) of your CA.
If you encounter error in finding openssl.conf file, you need to update your env variable to point to openssl.conf. By deafult, when you install Git, it comes with OpenSSL. Update your env variable OPENSSL_CONFIG
to point to your config file.
set OPENSSL_CONFIG=C:\Program Files\Git\usr\ssl\openssl.cnf
echo %OPENSSL_CONF%
Step 3: Generate admin certificate (admin-key.pem) Create a new key, convert key to PKCS#8 format for use in Java using PKCS#12-compatible algorithm (3DES)
openssl genrsa -out admin-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in admin-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out admin-key.pem
Next, create a certificate signing request (CSR) to act as an application to a CA (one we created earlier) for signed certificate.
openssl req -new -key admin-key.pem -out admin.csr
Finally, generate the certificate.
openssl x509 -req -in admin.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out admin.pem -days 3650
OpenDistro provided a sample script for all certificates we need.
# Root CA
openssl genrsa -out root-ca-key.pem 2048
openssl req -new -x509 -sha256 -key root-ca-key.pem -out root-ca.pem -days 30
# Admin cert
openssl genrsa -out admin-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in admin-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out admin-key.pem
openssl req -new -key admin-key.pem -out admin.csr
openssl x509 -req -in admin.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out admin.pem -days 30
# Node cert
openssl genrsa -out node-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in node-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out node-key.pem
openssl req -new -key node-key.pem -out node.csr
openssl x509 -req -in node.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node.pem -days 30
#Client cert
openssl genrsa -out client-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in client-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out client-key.pem
openssl req -new -key client-key.pem -out client.csr
openssl x509 -req -in client.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out client.pem -days 30
# Cleanup
rm admin-key-temp.pem
rm admin.csr
rm node-key-temp.pem
rm node.csr
rm client-key-temp.pem
rm client.csr
To get the DN of your certificates, run the following:
openssl x509 -subject -nameopt RFC2253 -noout -in node.pem
Only the following certificates are necessary:
root-ca.pem
admin.pem
admin-key.pem
node-cert.pem
(Optional)node-key.pem
(Optional)
Docker Compose with own certs
We need to update the environment variables and volumes to include the custom elasticsearch.yml
and directories of all certificates.
version: '3'
services:
odfe-node1:
image: amazon/opendistro-for-elasticsearch:1.12.0
container_name: odfe-node1
environment:
- cluster.name=odfe-cluster
- node.name=odfe-node1
- discovery.seed_hosts=odfe-node1
- cluster.initial_master_nodes=odfe-node1
- bootstrap.memory_lock=true # along with the memlock settings below, disables swapping
- "ES_JAVA_OPTS=-Xms512m -Xmx512m" # minimum and maximum Java heap size, recommend setting both to 50% of system RAM
- DISABLE_INSTALL_DEMO_CONFIG=true
- network.host=0.0.0.0 # required if not using the demo security configuration
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 262144 # maximum number of open files for the Elasticsearch user, set to at least 65536 on modern systems
hard: 262144
volumes:
- odfe-data1:/usr/share/elasticsearch/data
- ./root-ca.pem:/usr/share/elasticsearch/config/root-ca.pem
- ./node.pem:/usr/share/elasticsearch/config/node.pem
- ./node-key.pem:/usr/share/elasticsearch/config/node-key.pem
- ./admin.pem:/usr/share/elasticsearch/config/admin.pem
- ./admin-key.pem:/usr/share/elasticsearch/config/admin-key.pem
- ./custom-elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
ports:
- 9200:9200
- 9600:9600 # required for Performance Analyzer
networks:
- odfe-net
kibana:
image: amazon/opendistro-for-elasticsearch-kibana:1.12.0
container_name: odfe-kibana
ports:
- 5601:5601
expose:
- "5601"
environment:
ELASTICSEARCH_URL: https://odfe-node1:9200
ELASTICSEARCH_HOSTS: https://odfe-node1:9200
networks:
- odfe-net
volumes:
odfe-data1:
networks:
odfe-net:
Our new elasticsearch.yml should also be updated to include references to our certificates.
opendistro_security.ssl.transport.pemcert_filepath: node.pem
opendistro_security.ssl.transport.pemkey_filepath: node-key.pem
opendistro_security.ssl.transport.pemtrustedcas_filepath: root-ca.pem
opendistro_security.ssl.transport.enforce_hostname_verification: false
opendistro_security.ssl.http.enabled: true
opendistro_security.ssl.http.pemcert_filepath: node.pem
opendistro_security.ssl.http.pemkey_filepath: node-key.pem
opendistro_security.ssl.http.pemtrustedcas_filepath: root-ca.pem
opendistro_security.allow_default_init_securityindex: true
opendistro_security.authcz.admin_dn:
- CN=A,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA
opendistro_security.nodes_dn:
- 'CN=N,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
opendistro_security.audit.type: internal_elasticsearch
opendistro_security.enable_snapshot_restore_privilege: true
opendistro_security.check_snapshot_restore_write_privileges: true
opendistro_security.restapi.roles_enabled: ["all_access", "security_rest_api_access"]
cluster.routing.allocation.disk.threshold_enabled: false
opendistro_security.audit.config.disabled_rest_categories: NONE
opendistro_security.audit.config.disabled_transport_categories: NONE
Leave a comment