Skip to content

Commit

Permalink
feat: Simplify TLS certs creation, remove built-in certs
Browse files Browse the repository at this point in the history
  • Loading branch information
antoineco committed Oct 1, 2024
1 parent 3b853ba commit 2c7b062
Show file tree
Hide file tree
Showing 46 changed files with 285 additions and 717 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
- name: Pre-build container images
run: >-
docker compose
--profile=setup
-f docker-compose.yml
-f extensions/fleet/fleet-compose.yml
-f extensions/fleet/agent-apmserver-compose.yml
Expand All @@ -38,6 +39,24 @@ jobs:
-f extensions/enterprise-search/enterprise-search-compose.yml
build
- name: Generate X.509 assets for TLS communications
run: |
echo '::group::Generate certificates and private keys'
docker compose up tls
echo '::endgroup::'
echo '::group::Provide CA fingerprint for Fleet output'
declare ca_fingerprint
ca_fingerprint="$(openssl x509 -fingerprint -sha256 -noout -in tls/certs/ca/ca.crt \
| cut -d '=' -f2 \
| tr -d ':' \
| tr '[:upper:]' '[:lower:]'
)"
sed -i "s/#\(ca_trusted_fingerprint:\).*/\1 ${ca_fingerprint}/g" kibana/config/kibana.yml
git diff
echo '::endgroup::'
########################################################
# #
# Ensure §"Initial setup" of the README remains valid. #
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scripts/run-tests-core.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ ip_es="$(service_ip elasticsearch)"
ip_ls="$(service_ip logstash)"
ip_kb="$(service_ip kibana)"

es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/kibana/elasticsearch-ca.pem)
es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/certs/ca/ca.crt)

grouplog 'Wait for readiness of Elasticsearch'
poll_ready "$cid_es" 'https://elasticsearch:9200/' --resolve "elasticsearch:9200:${ip_es}" --cacert "$es_ca_cert" -u 'elastic:testpasswd'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scripts/run-tests-enterprise-search.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ cid_en="$(container_id enterprise-search)"
ip_es="$(service_ip elasticsearch)"
ip_en="$(service_ip enterprise-search)"

es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/kibana/elasticsearch-ca.pem)
es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/certs/ca/ca.crt)

grouplog 'Wait for readiness of Elasticsearch'
poll_ready "$cid_es" 'https://elasticsearch:9200/' --resolve "elasticsearch:9200:${ip_es}" --cacert "$es_ca_cert" -u 'elastic:testpasswd'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scripts/run-tests-filebeat.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ cid_fb="$(container_id filebeat)"
ip_es="$(service_ip elasticsearch)"
ip_fb="$(service_ip filebeat)"

es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/kibana/elasticsearch-ca.pem)
es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/certs/ca/ca.crt)

grouplog 'Wait for readiness of Elasticsearch'
poll_ready "$cid_es" 'https://elasticsearch:9200/' --resolve "elasticsearch:9200:${ip_es}" --cacert "$es_ca_cert" -u 'elastic:testpasswd'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scripts/run-tests-fleet.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ ip_es="$(service_ip elasticsearch)"
ip_fl="$(service_ip fleet-server)"
ip_apm="$(service_ip apm-server)"

es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/kibana/elasticsearch-ca.pem)
es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/certs/ca/ca.crt)

grouplog 'Wait for readiness of Elasticsearch'
poll_ready "$cid_es" 'https://elasticsearch:9200/' --resolve "elasticsearch:9200:${ip_es}" --cacert "$es_ca_cert" -u 'elastic:testpasswd'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scripts/run-tests-heartbeat.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ cid_hb="$(container_id heartbeat)"
ip_es="$(service_ip elasticsearch)"
ip_hb="$(service_ip heartbeat)"

es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/kibana/elasticsearch-ca.pem)
es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/certs/ca/ca.crt)

grouplog 'Wait for readiness of Elasticsearch'
poll_ready "$cid_es" 'https://elasticsearch:9200/' --resolve "elasticsearch:9200:${ip_es}" --cacert "$es_ca_cert" -u 'elastic:testpasswd'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scripts/run-tests-metricbeat.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ cid_mb="$(container_id metricbeat)"
ip_es="$(service_ip elasticsearch)"
ip_mb="$(service_ip metricbeat)"

es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/kibana/elasticsearch-ca.pem)
es_ca_cert=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/../../../tls/certs/ca/ca.crt)

grouplog 'Wait for readiness of Elasticsearch'
poll_ready "$cid_es" 'https://elasticsearch:9200/' --resolve "elasticsearch:9200:${ip_es}" --cacert "$es_ca_cert" -u 'elastic:testpasswd'
Expand Down
69 changes: 50 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ Other available stack variants:

## tl;dr

```sh
docker compose up tls
```

```sh
docker compose up setup
```
Expand Down Expand Up @@ -65,7 +69,6 @@ own_. [sherifabdlnaby/elastdocker][elastdocker] is one example among others of p
* [Bringing up the stack](#bringing-up-the-stack)
* [Initial setup](#initial-setup)
* [Setting up user authentication](#setting-up-user-authentication)
* [Generating certificates and keys for TLS communications](#generating-certificates-and-keys-for-tls-communications)
* [Injecting data](#injecting-data)
* [Cleanup](#cleanup)
* [Version selection](#version-selection)
Expand All @@ -75,6 +78,7 @@ own_. [sherifabdlnaby/elastdocker][elastdocker] is one example among others of p
* [How to configure Logstash](#how-to-configure-logstash)
* [How to disable paid features](#how-to-disable-paid-features)
* [How to scale out the Elasticsearch cluster](#how-to-scale-out-the-elasticsearch-cluster)
* [How to re-generate TLS certificates](#how-to-re-generate-tls-certificates)
* [How to re-execute the setup](#how-to-re-execute-the-setup)
* [How to reset a password programmatically](#how-to-reset-a-password-programmatically)
1. [Extensibility](#extensibility)
Expand Down Expand Up @@ -136,10 +140,23 @@ instructions from the [documentation][mac-filesharing] to add more locations.
Clone this repository onto the Docker host that will run the stack with the command below:

```sh
git clone https://github.com/deviantony/docker-elk.git
git clone --branch tls https://github.com/deviantony/docker-elk.git
```

Then, generate X.509 certificates and private keys to enable secure communications over TLS between components:

```sh
docker compose up tls
```

Then, initialize the Elasticsearch users and groups required by docker-elk by executing the command:
> [!NOTE]
> All Elastic components — including [extensions](#how-to-enable-the-provided-extensions) — are pre-configured to use
> the certificates generated by this command. To change the DNS names and IP addresses to include in the certificates,
> or re-generate them at a later time, refer to [How to re-generate TLS
> certificates](#how-to-re-generate-tls-certificates).
After TLS certificates have been generated, initialize the Elasticsearch users and groups required by docker-elk by
executing the command:

```sh
docker compose up setup
Expand Down Expand Up @@ -229,21 +246,6 @@ reset the passwords of all aforementioned Elasticsearch users to random secrets.
> [!NOTE]
> Learn more about the security of the Elastic stack at [Secure the Elastic Stack][sec-cluster].

#### Generating certificates and keys for TLS communications

Communications between stack components and Elasticsearch are secured over TLS.

For convenience reasons, the [`tls/`](./tls/) directory of this repository contains pre-generated X.509 certificates so
that you can get started quickly with docker-elk. The Compose file and all Elastic components are pre-configured to use
those certificates.

> [!WARNING]
> It is critical that you generate your own certificates if you ever intend to expose this stack outside of your local
> development environment.

To re-generate those certificates, follow the instructions at [TLS certificates](./tls/README.md). Alternatively, you
can refer to the documentation page [Manually configure security][es-tls] from the Elastic documentation.

#### Injecting data

Launch the Kibana web UI by opening <http://localhost:5601> in a web browser, and use the following credentials to log
Expand Down Expand Up @@ -368,6 +370,35 @@ methods described in the first paragraph.

Follow the instructions from the Wiki: [Scaling out Elasticsearch](https://github.com/deviantony/docker-elk/wiki/Elasticsearch-cluster)

### How to re-generate TLS certificates

To re-generate TLS certificates and private keys, first ensure that the [tls/instances.yml](./tls/instances.yml) file
contains a list of certificates with suitable domains and IP addresses for your environment (defaults are suitable for
local installations without access from other hosts on the network).

Then, remove existing TLS certificates and private keys using the command below:

```console
$ find tls/certs -name ca -prune -or -type d -mindepth 1 -exec rm -rfv {} +
tls/certs/kibana/kibana.key
tls/certs/kibana/kibana.crt
tls/certs/kibana
tls/certs/apm-server/apm-server.crt
tls/certs/apm-server/apm-server.key
tls/certs/apm-server
tls/certs/fleet-server/fleet-server.key
tls/certs/fleet-server/fleet-server.crt
tls/certs/fleet-server
tls/certs/elasticsearch/elasticsearch.key
tls/certs/elasticsearch/elasticsearch.crt
tls/certs/elasticsearch
```

and run the `tls` service again.

Alternatively, you can refer to the documentation page [Manually configure security][es-tls] from the Elastic
documentation to generate certificates and private keys manually.

### How to re-execute the setup

To run the setup container again and re-initialize all users for which a password was defined inside the `.env` file,
Expand Down Expand Up @@ -395,7 +426,7 @@ In the example below, we reset the password of the `elastic` user (notice "/user

```sh
curl -XPOST -D- 'https://localhost:9200/_security/user/elastic/_password' \
--cacert tls/kibana/elasticsearch-ca.pem \
--cacert tls/certs/ca/ca.crt \
-H 'Content-Type: application/json' \
-u elastic:<your current elastic password> \
-d '{"password" : "<your new password>"}'
Expand Down
46 changes: 35 additions & 11 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
services:

# The 'tls' service runs a one-off script which initializes TLS certificates and
# private keys for all components of the stack inside the local tls/ directory.
#
# This task only needs to be performed once, *before* the first stack startup.
#
# By default, it is excluded from the services started by 'docker compose up'
# due to the non-default profile it belongs to. To run it, either provide the
# '--profile=setup' CLI flag to Compose commands, or "up" the service by name
# such as 'docker compose up tls'.
tls:
profiles:
- setup
build:
context: tls/
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
user: root # ensures we can write to the local tls/ directory.
init: true
volumes:
- ./tls/entrypoint.sh:/entrypoint.sh:ro,Z
- ./tls/instances.yml:/usr/share/elasticsearch/tls/instances.yml:ro,Z
- ./tls/certs:/usr/share/elasticsearch/tls/certs:z

# The 'setup' service runs a one-off script which initializes users inside
# Elasticsearch — such as 'logstash_internal' and 'kibana_system' — with the
# values of the passwords defined in the '.env' file. It also creates the
Expand All @@ -26,8 +49,8 @@ services:
- ./setup/entrypoint.sh:/entrypoint.sh:ro,Z
- ./setup/lib.sh:/lib.sh:ro,Z
- ./setup/roles:/roles:ro,Z
# (!) CA certificate. Generate using instructions from tls/README.md
- ./tls/kibana/elasticsearch-ca.pem:/elasticsearch-ca.pem:ro,z
# (!) CA certificate. Generate using the 'tls' service.
- ./tls/certs/ca/ca.crt:/ca.crt:ro,z
environment:
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
LOGSTASH_INTERNAL_PASSWORD: ${LOGSTASH_INTERNAL_PASSWORD:-}
Expand All @@ -50,9 +73,10 @@ services:
volumes:
- ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro,Z
- elasticsearch:/usr/share/elasticsearch/data:Z
# (!) TLS certificates. Generate using instructions from tls/README.md.
- ./tls/elasticsearch/elasticsearch.p12:/usr/share/elasticsearch/config/elasticsearch.p12:ro,z
- ./tls/elasticsearch/http.p12:/usr/share/elasticsearch/config/http.p12:ro,z
# (!) TLS certificates. Generate using the 'tls' service.
- ./tls/certs/ca/ca.crt:/usr/share/elasticsearch/config/ca.crt:ro,z
- ./tls/certs/elasticsearch/elasticsearch.crt:/usr/share/elasticsearch/config/elasticsearch.crt:ro,z
- ./tls/certs/elasticsearch/elasticsearch.key:/usr/share/elasticsearch/config/elasticsearch.key:ro,z
ports:
- 9200:9200
- 9300:9300
Expand All @@ -78,8 +102,8 @@ services:
volumes:
- ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro,Z
- ./logstash/pipeline:/usr/share/logstash/pipeline:ro,Z
# (!) CA certificate. Generate using instructions from tls/README.md
- ./tls/kibana/elasticsearch-ca.pem:/usr/share/logstash/config/elasticsearch-ca.pem:ro,z
# (!) CA certificate. Generate using the 'tls' service.
- ./tls/certs/ca/ca.crt:/usr/share/logstash/config/ca.crt:ro,z
ports:
- 5044:5044
- 50000:50000/tcp
Expand All @@ -101,10 +125,10 @@ services:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml:ro,Z
# (!) TLS certificates. Generate using instructions from tls/README.md.
- ./tls/kibana/elasticsearch-ca.pem:/usr/share/kibana/config/elasticsearch-ca.pem:ro,z
- ./tls/kibana/instance.crt:/usr/share/kibana/config/instance.crt:ro,Z
- ./tls/kibana/instance.key:/usr/share/kibana/config/instance.key:ro,Z
# (!) TLS certificates. Generate using the 'tls' service.
- ./tls/certs/ca/ca.crt:/usr/share/kibana/config/ca.crt:ro,z
- ./tls/certs/kibana/kibana.crt:/usr/share/kibana/config/kibana.crt:ro,Z
- ./tls/certs/kibana/kibana.key:/usr/share/kibana/config/kibana.key:ro,Z
ports:
- 5601:5601
environment:
Expand Down
9 changes: 6 additions & 3 deletions elasticsearch/config/elasticsearch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ xpack.security.enabled: true
#
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: elasticsearch.p12
xpack.security.transport.ssl.truststore.path: elasticsearch.p12
xpack.security.transport.ssl.certificate_authorities: [ ca.crt ]
xpack.security.transport.ssl.certificate: elasticsearch.crt
xpack.security.transport.ssl.key: elasticsearch.key

## HTTP client communications
## see https://www.elastic.co/guide/en/elasticsearch/reference/current/configuring-tls.html#tls-http
#
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: http.p12
xpack.security.http.ssl.certificate_authorities: [ ca.crt ]
xpack.security.http.ssl.certificate: elasticsearch.crt
xpack.security.http.ssl.key: elasticsearch.key
2 changes: 1 addition & 1 deletion extensions/curator/config/curator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
elasticsearch:
client:
hosts: [ https://elasticsearch:9200 ]
ca_certs: /.curator/elasticsearch-ca.pem
ca_certs: /.curator/ca.crt
other_settings:
username: elastic
password: ${ELASTIC_PASSWORD}
Expand Down
4 changes: 2 additions & 2 deletions extensions/curator/curator-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ services:
volumes:
- ./extensions/curator/config/curator.yml:/.curator/curator.yml:ro,Z
- ./extensions/curator/config/delete_log_files_curator.yml:/.curator/delete_log_files_curator.yml:ro,Z
# (!) CA certificate. Generate using instructions from tls/README.md.
- ./tls/kibana/elasticsearch-ca.pem:/.curator/elasticsearch-ca.pem:ro,z
# (!) CA certificate. Generate using the 'tls' service.
- ./tls/certs/ca/ca.crt:/.curator/ca.crt:ro,z
environment:
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
networks:
Expand Down
2 changes: 1 addition & 1 deletion extensions/enterprise-search/config/enterprise-search.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ elasticsearch.host: https://elasticsearch:9200
elasticsearch.username: elastic
elasticsearch.password: ${ELASTIC_PASSWORD}
elasticsearch.ssl.enabled: true
elasticsearch.ssl.certificate_authority: /usr/share/enterprise-search/config/elasticsearch-ca.pem
elasticsearch.ssl.certificate_authority: /usr/share/enterprise-search/config/ca.crt

# Allow Enterprise Search to modify Elasticsearch settings. Used to enable auto-creation of Elasticsearch indexes.
allow_es_settings_modification: true
4 changes: 2 additions & 2 deletions extensions/enterprise-search/enterprise-search-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ services:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- ./extensions/enterprise-search/config/enterprise-search.yml:/usr/share/enterprise-search/config/enterprise-search.yml:ro,Z
# (!) CA certificate. Generate using instructions from tls/README.md
- ./tls/kibana/elasticsearch-ca.pem:/usr/share/enterprise-search/config/elasticsearch-ca.pem:ro,z
# (!) CA certificate. Generate using the 'tls' service.
- ./tls/certs/ca/ca.crt:/usr/share/enterprise-search/config/ca.crt:ro,z
environment:
JAVA_OPTS: -Xms2g -Xmx2g
ENT_SEARCH_DEFAULT_PASSWORD: 'changeme'
Expand Down
2 changes: 1 addition & 1 deletion extensions/filebeat/config/filebeat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ output.elasticsearch:
ssl:
# Using ${path.home} here while monitoring is enabled causes Beats to exit with:
# missing field accessing 'ssl.certificate_authorities.0'
certificate_authorities: [ /usr/share/filebeat/elasticsearch-ca.pem ]
certificate_authorities: [ /usr/share/filebeat/ca.crt ]

## HTTP endpoint for health checking
## https://www.elastic.co/guide/en/beats/filebeat/current/http-endpoint.html
Expand Down
4 changes: 2 additions & 2 deletions extensions/filebeat/filebeat-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ services:
source: /var/run/docker.sock
target: /var/run/docker.sock
read_only: true
# (!) CA certificate. Generate using instructions from tls/README.md
- ./tls/kibana/elasticsearch-ca.pem:/usr/share/filebeat/elasticsearch-ca.pem:ro,z
# (!) CA certificate. Generate using the 'tls' service.
- ./tls/certs/ca/ca.crt:/usr/share/filebeat/ca.crt:ro,z
environment:
FILEBEAT_INTERNAL_PASSWORD: ${FILEBEAT_INTERNAL_PASSWORD:-}
BEATS_SYSTEM_PASSWORD: ${BEATS_SYSTEM_PASSWORD:-}
Expand Down
10 changes: 5 additions & 5 deletions extensions/fleet/agent-apmserver-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ services:
ELASTIC_VERSION: ${ELASTIC_VERSION}
volumes:
- apm-server:/usr/share/elastic-agent/state:Z
# (!) TLS certificates. Generate using instructions from tls/README.md.
- ./tls/kibana/elasticsearch-ca.pem:/usr/share/elastic-agent/elasticsearch-ca.pem:ro,z
- ./tls/apmserver/instance.crt:/usr/share/elastic-agent/instance.crt:ro,Z
- ./tls/apmserver/instance.key:/usr/share/elastic-agent/instance.key:ro,Z
# (!) TLS certificates. Generate using the 'tls' service.
- ./tls/certs/ca/ca.crt:/usr/share/elastic-agent/ca.crt:ro,z
- ./tls/certs/apm-server/apm-server.crt:/usr/share/elastic-agent/apm-server.crt:ro,Z
- ./tls/certs/apm-server/apm-server.key:/usr/share/elastic-agent/apm-server.key:ro,Z
environment:
FLEET_ENROLL: '1'
FLEET_TOKEN_POLICY_NAME: Agent Policy APM Server
FLEET_URL: https://fleet-server:8220
ELASTICSEARCH_HOST: https://elasticsearch:9200
ELASTICSEARCH_CA: /usr/share/elastic-agent/elasticsearch-ca.pem
ELASTICSEARCH_CA: /usr/share/elastic-agent/ca.crt
# Enrollment.
# (a) Auto-enroll using basic authentication
ELASTICSEARCH_USERNAME: elastic
Expand Down
Loading

0 comments on commit 2c7b062

Please sign in to comment.