こんにちは。
付録に記載したセキュリティ要件を満たしつつ、DockerでElasticsearchとKibanaを起動することを目的としたページです。
記載内容に間違いがあったり、改善点があったりしたら是非ご指摘をいただきたいです。
よろしくお願いいたします。
前提
Elasticsearchの設定ファイル elasticsearch.yml
Kibanaの設定ファイル kibana.yml
上記が入っている場所を設定ディレクトリという
Elasticsearch側 設定ディレクトリe (e.g. $ES_PATH_CONF
)
Kibana側 設定ディレクトリ (e.g. $KBN_PATH_CONF
)
ブラウザからElasticsearchにログインするユーザー: elastic
→これはsuperuser
KibanaからElasticsearchにログインするユーザー: kibana_system
Elasticsearchはシングルノードで作成する
⚠️マルチノードの場合本番環境では推奨されていないので注意
transport層のセキュリティも気にしないといけない(ノード間通信)
構成
今回は前段として、⓪証明書系の生成(ここは本番では使わないはず?)を行ったのち
① Elasticsearchの起動
①’ kibana_system
のパスワード変更
② Kibanaの起動
を行います。
パスワードを変更してKibanaを再起動する必要があるようなので、後から起動してしまう作戦です。
ではみていきます。
ネットワーク作成
docker network create elastic
証明書作成
docker run --rm --user=root --network=elastic -v certs:$ES_PATH_CONF/certs docker.elastic.co/elasticsearch/elasticsearch:$VERSION \
/bin/bash -c "elasticsearch-certutil ca --silent --pem";
docker runを使ってコンテナ内でelasticsearch-certutil
を実行する形です。
証明書はVolumeで管理してるので、docker runでやってしまいます。
composeファイル
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:${VERSION}
container_name: es01
environment:
- node.name=es01
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms${ES_HEAP_MEMORY_SIZE_MIN} -Xmx${ES_HEAP_MEMORY_SIZE_MAX}"
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=${ES_PATH_CONF}/certs/es01/es01.key
- xpack.security.http.ssl.certificate=${ES_PATH_CONF}/certs/es01/es01.crt
- xpack.security.http.ssl.certificate_authorities=${ES_PATH_CONF}/certs/ca/ca.crt
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data01:/usr/share/elasticsearch/data
- ${HOME}/certs:${ES_PATH_CONF}/certs:ro
ports:
- 9200:9200
networks:
- elastic
healthcheck:
test: curl --cacert ${ES_PATH_CONF}/certs/ca/ca.crt -s https://${ES_HOST}:9200 >/dev/null || exit 1
interval: 30s
timeout: 10s
retries: 5
kib01:
image: docker.elastic.co/kibana/kibana:${VERSION}
container_name: kib01
depends_on:
- es01
environment:
- ELASTICSEARCH_USERNAME=kibana_system
- ELASTICSEARCH_PASSWORD=${ES_PASSWORD}
- ELASTICSEARCH_HOSTS=https://es01:9200
- ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=${KIB_PATH_CONF}/certs/ca/ca.crt
- ELASTICSEARCH_SSL_VERIFICATIONMODE=certificate
- csp.strict=true
- SERVER_HOST=0.0.0.0
- SERVER_SSL_ENABLED=true
- SERVER_SSL_CERTIFICATE=${KIB_PATH_CONF}/certs/es01/es01.crt
- SERVER_SSL_KEY=${KIB_PATH_CONF}/certs/es01/es01.key
- server.securityResponseHeaders.disableEmbedding=true
- server.securityResponseHeaders.strictTransportSecurity="max-age=31536000"
volumes:
- kibanadata:/usr/share/kibana/data
- ${HOME}/certs:${KIB_PATH_CONF}/certs:ro
ports:
- 5601:5601
networks:
- elastic
healthcheck:
test: curl -s https://${ES_HOST}:5601 >/dev/null || exit 1
interval: 30s
timeout: 10s
retries: 5
volumes:
certs:
driver: local
data01:
driver: local
kibanadata:
driver: local
networks:
elastic:
driver: bridge
KibanaのEnvironmentについては以下でも書いた通り大文字で設定する必要があります。
設定したcomposeファイルを使って次のような順序でサービスを起動します。
docker-compose up es01 -d
bash set_password.sh # 下で触れます
docker-compose up kib01 -d
パスワード生成
KibanaがElasticsearchにアクセスするためのパスワードを生成します。
前提でも書いたように、アクセス用のアカウントとしてkibana_system
が用意されています。
パスワードのリセットにはElasticsearchのコンテナが必要で、特に再起動の予定もないので先に起動してます。
echo "Start Creating Containers...";
echo "Waiting for Elasticsearch availability";
until curl --cacert certs/ca/ca.crt -s https://$ES_HOST:9200 >/dev/null; do
sleep 5;
# certs/ca/ca.crtはローカルにある証明書
# なんらかの返答があればサービスの起動が確認できたことになるのでパスワードのリセット処理に入る
echo "Waiting for Elasticsearch...";
done;
# パスワードリセットして出力を保存
docker exec -it es01 elasticsearch-reset-password -u kibana_system --url https://$ES_HOST:9200 --batch > pwd_output.txt
# 出力からパスワードを抽出して.envに追加
# ここはあんまいけてない
NEW_PWD=$(grep 'New value:' pwd_output.txt | sed 's/New value: //'| tr -d '\n\r')
if [ ! -z "$NEW_PWD" ]; then
echo -e "ES_PASSWORD=\"$NEW_PWD\"" >> .env
echo "パスワードを.envに追加しました"
fi
echo "Finish Creating Containers...";
これでKibanaがElasticsearchに接続できるようになったので、満を持してKibanaのサービスを起動します。
しばらく待ったら、
https://localhost:5601
などでアクセスできるはずです。
※localhostの箇所は設定したホストによって変わります。
ログインするときはelastic
ユーザーを使うと良いです。
パスワードのリセットはローカルでkibana_system
を参考にしてやってください。
以上です!
感想
とりあえず動かすことはできました。
現状の課題としては、内部で作成された鍵を用いている点とそれらをvolumeで共有していることです。
外部で生成した鍵をそれぞれで保存する形にすれば問題ないように思います。
問題があればぜひ教えてください。
付録)最低限のセキュリティ ざっくりまとめ
これらドキュメントをまとめただけ
xpack.security.enabled: true
を elasticsearch.yml
に設定
この設定によってユーザー名とパスワードによるbasic認証が通る
パスワードのリセット
./bin/elasticsearch-reset-password -u kibana_system
このコマンドでユーザーkibana_system
のパスワードをリセットできる
elastic
についても同コマンドでパスワードをリセットできる
KibanaからElasticsearchへのパスワードによる接続
KibanaからElasticsearchに接続するうえで必要な設定
elasticsearch.username: "kibana_system"
をkibana.yml
に設定
Kibana内のセキュアな情報を保護するための設定
キーストアの作成
./bin/kibana-keystore create
Elasticsearchのパスワードをキーストアに追加
./bin/kibana-keystore add elasticsearch.password
Kibanaをリスタートする
For HTTPs ElasticSearch & Client 編
動作を止める
以下コマンドを実行し、CAのパス等を指定
./bin/elasticsearch-certutil http
生成されるelasticsearch-ssl-http.zip
を解凍する
http.p12
を設定ディレクトリeに移動
xpack.security.http.ssl.enabled: true
をelasticsearch.yml
に設定
xpack.security.http.ssl.keystore.path: http.p12
をelasticsearch.yml
に設定
キーストアに追加
./bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password
For HTTPs Kibana & ElasticSearch 編
elasticsearch-ca.pem
を設定ディレクトリkに移動
elasticsearch.ssl.certificateAuthorities: $KBN_PATH_CONF/elasticsearch-ca.pem
をkibana.yml
に設定
elasticsearch.hosts: https://<your_elasticsearch_host>:9200
をkibana.yml
に設定
Kibanaをリスタート
For HTTPs Kibana & Client 編
サーバーの証明書と秘密鍵を生成
./bin/elasticsearch-certutil csr -name kibana-server -dns example.com,www.example.com
生成されるcsr-bundle.zip
を解凍
server.ssl.certificate: $KBN_PATH_CONF/kibana-server.crt
をkibana.yml
に設定
server.ssl.key: $KBN_PATH_CONF/kibana-server.key
をkibana.yml
に設定
server.ssl.enabled: true
をkibana.yml
に設定
仲間を募集中!
株式会社ホープでは、福岡で働くエンジニアを募集中です。
ぜひ、求人を見てみてください!
▼ Wantedly求人
https://www.wantedly.com/projects/1684027
▼ コーポレートサイト
https://www.zaigenkakuho.com/recruit/
「自治体を通じて人々に新たな価値を提供し、会社及び従業員の成長を追求する」
この理念の実現に向けて、今後も自治体の課題解決に取り組んでいきます。
ご応募お待ちしております!