Setting up the Elasticsearch keystore for a containerized environment

The Elasticsearch keystore is a vital component in the Elasticsearch security architecture. But, how do we create the keystore file before starting Elasticsearch in a containerized environment?

The Elasticsearch keystore is a vital component in the Elasticsearch security architecture which is managed through a command line utility found in bin/elasticsearch-keystore. This command-line utility is used to create and maintain the elasticsearch.keystore file.

The elasticsearch.keystore file must be present in every container that runs Elasticsearch. But, how do we create the keystore file before starting Elasticsearch in a containerized environment?

Using a Setup container

One option is to create the Elasticsearch keystore during the container startup process. Typically, this is done using a setup container or, entrypoint override that retrieves the secrets from some place such as Docker Secrets, Vault, etc. and configures the keystore before starting the Elasticsearch container. This results in a dependency between the Elasticsearch container and the Setup container.

Creating a custom Elasticsearch image

However, another option is to create a custom Docker image for Elasticsearch and copy the keystore file into the image during the image build process. However, that makes upgrading more difficult since a new image must be built before we can upgrade. This stops us from simply using the Elasticsearch published images as-is.

Creating and distributing the keystore

Yet, another option, and my preference, is to create the elasticsearch.keystore file beforehand and mount it into the container. That is, to create the keystore outside of the container startup process. The snippet below shows how to create the keystore with Azure Storage account credentials for snapshots.

docker run --rm -v $(pwd)/:/es-keystore/ docker.elastic.co/elasticsearch/elasticsearch:8.12.0 /bin/bash -c "elasticsearch-keystore create && echo {{storage-account}} | bin/elasticsearch-keystore add --force --stdin azure.client.default.account && echo {{storage-account-key}} | bin/elasticsearch-keystore add --force --stdin azure.client.default.key && bin/elasticsearch-keystore list && cp /usr/share/elasticsearch/config/elasticsearch.keystore /es-keystore/elasticsearch.keystore"

Essentially, it starts up an Elasticsearch container, runs the elasticsearch-keystore utility and copies the file out of the container onto the local machine by means of a mounted volume.

This way the keystore file is created but it will need to be distributed to each node, using Ansible, Salt, Puppet, etc., on which Elasticsearch will be running so that it can be mounted. For example:

volumes:
  - ./elasticsearch.keystore:/usr/share/elasticsearch/config/elasticsearch.keystore:ro,z

Remember to setup the environment variable with your keystore password, if you have a password configured for the keystore file:

KEYSTORE_PASSWORD=mypassword