Search
Close this search box.

How to Secure Elasticsearch Cluster with Docker Secrets – part 1

Table of Contents

1. Introduction

Docker in swarm mode brings secrets that allow to store sensitive information like passwords. Elasticsearch on another hand has keystore as storage for sensitive information. These two guys can cooperate together.
When starting Elasticsearch container user need to provide somehow password for elastic user, additionally it will be more secure to protect keystore from access with password. Providing these values with open text form as environment variable is not secure for sure as simple docker inspect command can reveal secret, instead use docker secrets to mount values inside container and read them when needed.

2. Official Docker Elasticsearch Image

Official Docker Image for Elasticsearch comes with two environmental variables that controls initial Elasticearch password named bootstrap.password and variable that allow Elastic process to read from secured keystore. Their names are respectively ELASTIC_PASSWORD and KEYSTORE_PASSWORD. Moreover there are versions for files with _FILE suffix ELASTIC_PASSWORD_FILE and KEYSTORE_PASSWORD_FILE serving same purpose but reading password candidates from files. This giving opportunity to utilize docker secrets as these are mounted in container as regular file.

3. Limitations of Official Image

As of now version docker.elastic.co/elasticsearch/elasticsearch:8.9.1 contain bug that makes bootstrap.password as empty string if you start Elasticsearch container with password protected keystore and ELASTIC_PASSWORD variable set. Reason for that is line of code responsible for insertion into keystore.

				
					        (echo "$COMMANDS" | elasticsearch-keystore add -x 'bootstrap.password')
				
			

You can check this source yourself. Despite of this bug, current functionality do not allow to create password protected keystore using mentioned environmental variable KEYSTORE_PASSWORD_FILE as input. Everytime keystore will be only obfuscated which does not matter because you can open it using elasticsearch-keystore command. That limitation can be fixed by editing docker-entrypoint.sh script.

In this first part of tutorial I will focus on workaround how to start Elasticsearch with bootstrap password and later on run command that will take password from docker secret location and secure keystore.

4. Secure keystore manually

To password protect keystore simply run

elasticsearch-keystore passwd

and you will be asked for password. This require human interaction with terminal and that’s not what I aim for.

5. Secure keystore with scripting

When running setup with scripts human can sleep and machine to the work.

I am using Named pipe as FIFO messaging bus. Whatever is cast from secret file is waiting for pickup by bash process and therefore I can script it.

Look  at below one-liner:

				
					(mkfifo pipe1); ( (elasticsearch-keystore passwd < pipe1) & ( cat /run/secrets/keystore_password > pipe1) );sleep 5;rm pipe1
				
			

Now if you want to change key value in such storage you can use same technique.

6. Prepare docker secrets

Time for action. Start docker swarm node and create secrets. When you typing values for secrets you finish work by Ctrl+D combination or ^D
For bootstrap password you type value once, for keystore_password you type twice separated by new line character, this is because keystore password will be provided twice to elasticsearch-keystore shell program due to password confirmation needed.

				
					docker swarm init

docker secret create bootstrap_password -
docker secret create keystore_password -
				
			

7. Start Elasticsearch container with non-secured keystore

Elasticsearch will start now with non-secured keystore with bootstrap.password equal to contant of bootstrap_password docker secret.

				
					docker service create \
--name elastic \
--publish published=9200,target=9200 \
--secret source=bootstrap_password,target=bootstrap_password,uid=1000,gid=1001,mode=0400 \
--secret source=keystore_password,target=keystore_password,uid=1000,gid=1001,mode=0600 \
--env ELASTIC_PASSWORD_FILE=/run/secrets/bootstrap_password \
--env KEYSTORE_PASSWORD_FILE=/run/secrets/keystore_password \
--mount type=volume,src=elkdata,dst=/usr/share/elasticsearch/data \
--mount type=volume,src=elkconf,dst=/usr/share/elasticsearch/config \
docker.elastic.co/elasticsearch/elasticsearch:8.9.1
				
			

8. Secure Elasticsearch Keystore

For security you want keystore to be secured. By running below command  one-liner is executed inside Elasticsearch container and makes keystore be password protected with password equal to keystore_password docker secret.

				
					docker exec -it `docker ps --filter name=elastic -q` bash -c "(mkfifo pipe1); ( (elasticsearch-keystore passwd < pipe1) & ( cat /run/secrets/keystore_password > pipe1) );sleep 5;rm pipe1"
				
			

9. Restart Elasticsearch

To confirm that now Elasticsearch node can work with password protected keystore you will restart service. Elasticsearch process should get password via ‘<<<‘ known as here-string (check sources to know). To restart trigger update of docker service:

				
					docker service update --force elastic 
				
			

Service will start successfully and Elasticsearch will have green status. This is working!!!

10. Conclusions and next steps

You may noticed already that instead of running these commands I could prepare my own docker image with slightly different docker entrypoint script that will handle keystore password variable properly to let keystore be protected from the begining. This I will do in second part of this tutorial.
Stay tuned and have a nice coding!

Leave a Reply

Your email address will not be published. Required fields are marked *

Follow me on LinkedIn
Share the Post:

Enjoy Free Useful Amazing Content

Related Posts