Encrypting communications in an Elasticsearch Docker Container

Unless you are using a trial license, Elastic Stack security features require SSL/TLS encryption for the transport networking layer.

This section demonstrates an easy path to get started with SSL/TLS for both HTTPS and transport using the Elasticsearch Docker image. The example uses Docker Compose to manage the containers.

For further details, see Encrypting communications and available subscriptions.

Prepare the environment

Install Elasticsearch with Docker.

Inside a new, empty directory, create the following four files:

instances.yml:

  1. instances:
  2. - name: es01
  3. dns:
  4. - es01
  5. - localhost
  6. ip:
  7. - 127.0.0.1
  8. - name: es02
  9. dns:
  10. - es02
  11. - localhost
  12. ip:
  13. - 127.0.0.1

Allow use of embedded Docker DNS server names.

.env:

  1. COMPOSE_PROJECT_NAME=es
  2. CERTS_DIR=/usr/share/elasticsearch/config/certificates
  3. ELASTIC_PASSWORD=PleaseChangeMe

Use an es_ prefix for all volumes and networks created by docker-compose.

The path, inside the Docker image, where certificates are expected to be found.

Initial password for the elastic user.

create-certs.yml:

  1. version: '2.2'
  2. services:
  3. create_certs:
  4. container_name: create_certs
  5. image: docker.elastic.co/elasticsearch/elasticsearch:7.9.1
  6. command: >
  7. bash -c '
  8. if [[ ! -f /certs/bundle.zip ]]; then
  9. bin/elasticsearch-certutil cert --silent --pem --in config/certificates/instances.yml -out /certs/bundle.zip;
  10. unzip /certs/bundle.zip -d /certs;
  11. fi;
  12. chown -R 1000:0 /certs
  13. '
  14. user: "0"
  15. working_dir: /usr/share/elasticsearch
  16. volumes: ['certs:/certs', '.:/usr/share/elasticsearch/config/certificates']
  17. volumes: {"certs"}

The new node certificates and CA certificate+key are placed in a docker volume es_certs.

docker-compose.yml:

  1. version: '2.2'
  2. services:
  3. es01:
  4. container_name: es01
  5. image: docker.elastic.co/elasticsearch/elasticsearch:7.9.1
  6. environment:
  7. - node.name=es01
  8. - discovery.seed_hosts=es01,es02
  9. - cluster.initial_master_nodes=es01,es02
  10. - ELASTIC_PASSWORD=$ELASTIC_PASSWORD
  11. - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
  12. - xpack.license.self_generated.type=trial
  13. - xpack.security.enabled=true
  14. - xpack.security.http.ssl.enabled=true
  15. - xpack.security.http.ssl.key=$CERTS_DIR/es01/es01.key
  16. - xpack.security.http.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
  17. - xpack.security.http.ssl.certificate=$CERTS_DIR/es01/es01.crt
  18. - xpack.security.transport.ssl.enabled=true
  19. - xpack.security.transport.ssl.verification_mode=certificate
  20. - xpack.security.transport.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
  21. - xpack.security.transport.ssl.certificate=$CERTS_DIR/es01/es01.crt
  22. - xpack.security.transport.ssl.key=$CERTS_DIR/es01/es01.key
  23. volumes: ['data01:/usr/share/elasticsearch/data', 'certs:$CERTS_DIR']
  24. ports:
  25. - 9200:9200
  26. healthcheck:
  27. test: curl --cacert $CERTS_DIR/ca/ca.crt -s https://localhost:9200 >/dev/null; if [[ $$? == 52 ]]; then echo 0; else echo 1; fi
  28. interval: 30s
  29. timeout: 10s
  30. retries: 5
  31. es02:
  32. container_name: es02
  33. image: docker.elastic.co/elasticsearch/elasticsearch:7.9.1
  34. environment:
  35. - node.name=es02
  36. - discovery.seed_hosts=es01,es02
  37. - cluster.initial_master_nodes=es01,es02
  38. - ELASTIC_PASSWORD=$ELASTIC_PASSWORD
  39. - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
  40. - xpack.license.self_generated.type=trial
  41. - xpack.security.enabled=true
  42. - xpack.security.http.ssl.enabled=true
  43. - xpack.security.http.ssl.key=$CERTS_DIR/es02/es02.key
  44. - xpack.security.http.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
  45. - xpack.security.http.ssl.certificate=$CERTS_DIR/es02/es02.crt
  46. - xpack.security.transport.ssl.enabled=true
  47. - xpack.security.transport.ssl.verification_mode=certificate
  48. - xpack.security.transport.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
  49. - xpack.security.transport.ssl.certificate=$CERTS_DIR/es02/es02.crt
  50. - xpack.security.transport.ssl.key=$CERTS_DIR/es02/es02.key
  51. volumes: ['data02:/usr/share/elasticsearch/data', 'certs:$CERTS_DIR']
  52. wait_until_ready:
  53. image: docker.elastic.co/elasticsearch/elasticsearch:7.9.1
  54. command: /usr/bin/true
  55. depends_on: {"es01": {"condition": "service_healthy"}}
  56. volumes: {"data01", "data02", "certs"}

Bootstrap elastic with the password defined in .env. See The Elastic bootstrap password.

Automatically generate and apply a trial subscription, in order to enable security features.

Disable verification of authenticity for inter-node communication. Allows creating self-signed certificates without having to pin specific internal IP addresses.

Run the example

  1. Generate the certificates (only needed once):

    1. docker-compose -f create-certs.yml run --rm create_certs
  2. Start two Elasticsearch nodes configured for SSL/TLS:

    1. docker-compose up -d
  3. Access the Elasticsearch API over SSL/TLS using the bootstrapped password:

    1. docker run --rm -v es_certs:/certs --network=es_default docker.elastic.co/elasticsearch/elasticsearch:7.9.1 curl --cacert /certs/ca/ca.crt -u elastic:PleaseChangeMe https://es01:9200
  4. The elasticsearch-setup-passwords tool can also be used to generate random passwords for all users:

    Windows users not running PowerShell will need to remove \ and join lines in the snippet below.

    1. docker exec es01 /bin/bash -c "bin/elasticsearch-setup-passwords \
    2. auto --batch \
    3. --url https://localhost:9200"

Tear everything down

To remove all the Docker resources created by the example, issue:

  1. docker-compose down -v