Elasticsearch 7.6 と Kibana 7.6 に Security を有効化してDockerで起動する（コピペ）

# やりたいこと

ログの集計・可視化をElasticsearchとKibanaを使って行いたいと思い、色々調べてみたところ、どうやらAmazon Lightsailで動かすのが安そうということで、環境構築について検討した。
Elastic Cloudだと手軽に始められる反面、インスタンスコストが割高で、最小構成だとリサイズに失敗したりしてほとんど何もできなかった。
Lightsailの場合、4GB RAMのインスタンスが$20/月なので、2GBをElasticsearchに、1GBをKibanaに、という構成ができそう。
そして、比較的最近、無償ライセンスのBasicプランでもX-Pack Securityが使えるようになっているので、しっかり認証も付けておきたい。（Lightsailはポート制限しかできない）
開発はMacで行うので、できればローカルの開発環境と本番を同じように構成したい。

**2020.2.12 更新：公式ドキュメントですんなりいかなかったので、TLSの有効化を追記した。**
**2020.2.12 更新：ElasticsearchとKibanaの7.6.0が出たのでバージョンアップした**
**2020.2.13 更新：より簡単で確実な[Elasticsearch & Kibana をLet's EncryptでTLS対応させる](https://qiita.com/hsano/items/3b4fb372c4dec0cabc08) を投稿した。**

## 要点
- Elasticsearch & Kibana を使う
- X-Pack Securityを有効化する
- なるべく安くそこそこの環境を整えたい
- MacとLightsailで同じ環境を作りたい

## 前提
- Dockerが使える状態
- ホスト側がRAM 4GB以上で、Elasticsearchに2GB、Kibanaに1GBを割当てられる
- ~~直近ではSSLオプション使わない~~ ElasticsearchとクライアントをTLS、Kibanaにhttpsで接続するようにする

# 以下をコピペしとけば動く

## 1. データの保存先を作成

- 必要に応じて権限を変える

```shell
mkdir -p ~/Development/Docker/Elasticsearch/data ~/Development/Docker/Elasticsearch/cert
```

## 2. まず、作業用にデフォルト状態のElasticsearchを起動

- 環境変数 `ELASTIC_PASSWORD` が `elastic` ユーザーのパスワードなので変更する

```shell
docker run --name Elasticsearch -d \
-m 2048m \
-p 9200:9200 \
-p 9300:9300 \
-e cluster.name=ES \
-e discovery.type=single-node \
-e network.host=0.0.0.0 \
-e bootstrap.memory_lock=true \
-e xpack.security.enabled=true \
-e xpack.monitoring.collection.enabled=true \
-e "ES_JAVA_OPTS=-Xms1024m -Xmx1024m" \
-e "ELASTIC_PASSWORD=iY69DxipKifV7utYA4t6jgxT" \
-v ~/Development/Docker/Elasticsearch/data:/usr/share/elasticsearch/data \
-v ~/Development/Docker/Elasticsearch/cert:/usr/share/elasticsearch/cert \
--ulimit nproc=4096:4096 \
--ulimit memlock=256000:256000 \
--ulimit nofile=65536:65536 \
docker.elastic.co/elasticsearch/elasticsearch:7.6.0
```

## 3. kibanaユーザーのパスワードを設定する

- BASIC認証のパスワードは2で指定したものを使う
- `password` の値が `kibana` ユーザーのパスワード

```shell
curl -XPUT --user elastic:iY69DxipKifV7utYA4t6jgxT 'localhost:9200/_xpack/security/user/kibana/_password' -H "Content-Type: application/json" -d '{
  "password" : "6ezji8D5jvceXUsTsvg8mAY4"
}'
```

## 4. TLS周りの準備

基本的には公式の [Encrypting communications in Elasticsearch | Elasticsearch Reference [7.6] | Elastic](https://www.elastic.co/guide/en/elasticsearch/reference/7.6/configuring-tls.html) と [Encrypting communications in Kibana | Kibana Guide [7.6] | Elastic](https://www.elastic.co/guide/en/kibana/7.6/configuring-tls.html) に沿ってはいる。

### Elasticsearchコンテナに入る

```shell
docker exec -it Elasticsearch /bin/sh
```

### opensslとunzipを使えるようにする

```shell
yum update
yum install openssl unzip
```

### 認証局を作成

- ダイアログは何も入れずenterを押し続ける（お好みで入力してもいい）

```shell
bin/elasticsearch-certutil ca
```

### 秘密鍵を生成

- ダイアログは何も入れずenterを押し続ける（お好みで入力してもいい）

```shell
bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12
```

### 証明書を作成

```shell
openssl pkcs12 -in elastic-certificates.p12 -cacerts -nokeys -out elastic-stack-ca.pem
```

### Kibanaをhttps化するのに必要なサーバ証明書と秘密鍵を生成

- ダイアログは何も入れずenterを押し続ける（お好みで入力してもいい）

```shell
bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12 --pem --name kibana-server
unzip certificate-bundle.zip
```

### 諸々をホスト側に移動してコンテナを抜ける

```shell
mv elastic-* ./cert/
mv kibana-server ./cert/
exit
```

## 5. TLS周りを組み込んだイメージをビルドする

### 生成しておいた諸々があるディレクトリへ移動

```shell

cd ~/Development/Docker/Elasticsearch/cert
```

### Elasticsearchイメージをビルドする

- 以下の内容で `dockerfile-es` を作成

```Dockerfile
FROM docker.elastic.co/elasticsearch/elasticsearch:7.6.0

RUN \
elasticsearch-plugin install --batch analysis-icu && \
elasticsearch-plugin install --batch analysis-kuromoji

RUN mkdir /usr/share/elasticsearch/config/cert
ADD elastic-certificates.p12 /usr/share/elasticsearch/config/cert/elastic-certificates.p12
ADD elastic-stack-ca.p12 /usr/share/elasticsearch/config/cert/elastic-stack-ca.p12
RUN chown -R elasticsearch /usr/share/elasticsearch/config/cert
RUN chgrp -R root /usr/share/elasticsearch/config/cert
RUN chmod o-rx /usr/share/elasticsearch/config/cert
RUN chmod 640 /usr/share/elasticsearch/config/cert/elastic-stack-ca.p12
RUN chmod 640 /usr/share/elasticsearch/config/cert/elastic-certificates.p12
```

- ビルドする

```
docker build -f dockerfile-es -t elasticsearch-tls .
```

### Kibanaイメージをビルドする

- 以下の内容で `dockerfile-kibana` を作成

```Dockerfile
FROM docker.elastic.co/kibana/kibana:7.6.0

ADD elastic-stack-ca.pem /etc/kibana/elastic-stack-ca.pem
ADD kibana-server/kibana-server.crt /etc/kibana/kibana-server.crt
ADD kibana-server/kibana-server.key /etc/kibana/kibana-server.key
```

- ビルドする

```
docker build -f dockerfile-kibana -t kibana-tls .
```

## 6. ビルドしたElasticsearchイメージを起動する

- まずは作業に使ったデフォルトのコンテナを破棄する

```shell
docker stop Elasticsearch
docker rm Elasticsearch
```

- Elasticsearchを起動する

```shell
docker run --name Elasticsearch -d \
-m 2048m \
-p 9200:9200 \
-p 9300:9300 \
-e cluster.name=ES \
-e discovery.type=single-node \
-e network.host=0.0.0.0 \
-e bootstrap.memory_lock=true \
-e xpack.security.enabled=true \
-e xpack.monitoring.collection.enabled=true \
-e "ES_JAVA_OPTS=-Xms1024m -Xmx1024m" \
-e "ELASTIC_PASSWORD=iY69DxipKifV7utYA4t6jgxT" \
-e xpack.security.transport.ssl.enabled=true \
-e xpack.security.transport.ssl.verification_mode=certificate \
-e xpack.security.transport.ssl.keystore.path=/usr/share/elasticsearch/config/cert/elastic-stack-ca.p12 \
-e xpack.security.transport.ssl.truststore.path=/usr/share/elasticsearch/config/cert/elastic-certificates.p12 \
-e xpack.security.http.ssl.enabled=true \
-e xpack.security.http.ssl.keystore.path=/usr/share/elasticsearch/config/cert/elastic-certificates.p12 \
-e xpack.security.http.ssl.truststore.path=/usr/share/elasticsearch/config/cert/elastic-certificates.p12 \
-v ~/Development/Docker/Elasticsearch/data:/usr/share/elasticsearch/data \
--ulimit nproc=4096:4096 \
--ulimit memlock=256000:256000 \
--ulimit nofile=65536:65536 \
elasticsearch-tls
```


## 7. ビルドしたKibanaイメージを起動する

- `ELASTICSEARCH_PASSWORD` は[3](https://qiita.com/hsano/items/79031c7e23f252c8daeb#3-kibanaユーザーのパスワードを設定する)で設定した `kibana` ユーザーのパスワードを指定する

```sh
docker run --name Kibana -d \
--link Elasticsearch:elasticsearch \
-m 1280m \
-p 443:5601 \
-e "ELASTICSEARCH_HOSTS=https://elasticsearch:9200" \
-e "ELASTICSEARCH_USERNAME=kibana" \
-e "ELASTICSEARCH_PASSWORD=L5eDLkx9EzswECECAsabJauV" \
-e "ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=[\"/etc/kibana/elastic-stack-ca.pem\"]" \
-e "ELASTICSEARCH_SSL_VERIFICATIONMODE=certificate" \
-e "SERVER_SSL_ENABLED=true" \
-e "SERVER_SSL_CERTIFICATE=/etc/kibana/kibana-server.crt" \
-e "SERVER_SSL_KEY=/etc/kibana/kibana-server.key" \
--ulimit nproc=4096:4096 \
--ulimit memlock=256000:256000 \
--ulimit nofile=65536:65536 \
kibana-tls
```

## 8. 諸々設定する

- ブラウザでホストの `https://{ホスト名}/` に接続（自己証明書だとブラウザに警告される）
- `elastic` ユーザーとしてログイン
- グループやユーザーを作成