Elastic Stack のTLS化

#はじめに
自分の環境でElastic Stack のTLS化をして運用する計画なので，今のうちに手順をまとめておく．環境は以下の通り．

- OS: Ubuntu 20.04
- Elasticsearch: 7.8.1
- Kibana: 7.8.1

#準備

##Elasticsearch とKibana のインストール
以下のURL より，パッケージをダウンロードする．
https://www.elastic.co/jp/downloads/

その後，以下のコマンドによりインストールを実行する．

```terminal:実行コマンド
$ sudo dpkg -i elasticsearch-7.8.1-amd64.deb
$ sudo dpkg -i kibana-7.8.1-amd64.deb 
```

##環境変数の設定

以下のコマンドを実行し，Shift+G で末尾に移動して環境変数を追記する．

```terminal:実行コマンド
# vim ~/.bashrc

ES_HOME=/usr/share/elasticsearch
ES_PATH_CONF=/etc/elasticsearch
```

echo コマンドで，設定されたかを確認する．

```terminal:実行コマンド
# echo $ES_HOME
/usr/share/elasticsearch

# echo $ES_PATH_CONF
/etc/elasticsearch
```

##Elasticsearch の起動確認

以下のコマンドで，設定ファイルを編集する．

```terminal:実行コマンド
# vim /etc/elasticsearch/elasticsearch.yml
```

編集内容は下記の通り．

```yml:/etc/elasticsearch/elasticsearch.yml
cluster.name: exam-cluster
node.name: node-4
network.host: 0.0.0.0
http.port: 9200
cluster.initial_master_nodes: ["node-4"]
```

編集が完了したら，サービスの起動とステータス確認を実行する．

```terminal:実行コマンド
$ sudo systemctl start elasticsearch
$ sudo systemctl status elasticsearch
● elasticsearch.service - Elasticsearch
     Loaded: loaded (/lib/systemd/system/elasticsearch.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2020-08-09 13:35:05 JST; 3min 44s ago
       Docs: https://www.elastic.co
   Main PID: 5145 (java)
      Tasks: 74 (limit: 9455)
     Memory: 1.2G
     CGroup: /system.slice/elasticsearch.service
             ├─5145 /usr/share/elasticsearch/jdk/bin/java -Xshare:auto -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=10 -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys>
             └─5343 /usr/share/elasticsearch/modules/x-pack-ml/platform/linux-x86_64/bin/controller

 8月 09 13:34:55 elastic-tls systemd[1]: Starting Elasticsearch...
 8月 09 13:35:05 elastic-tls systemd[1]: Started Elasticsearch.
```

Active: active (running) と表示されていれば，サービスが起動しているはずなので，curl にてAPI にアクセスしてみる．

```terminal:実行コマンド
$ curl localhost:9200
{
  "name" : "node-4",
  "cluster_name" : "exam-cluster",
  "cluster_uuid" : "COZ8D3F4TjGYtc0f8zkvRw",
  "version" : {
    "number" : "7.8.1",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "b5ca9c58fb664ca8bf9e4057fc229b3396bf3a89",
    "build_date" : "2020-07-21T16:40:44.668009Z",
    "build_snapshot" : false,
    "lucene_version" : "8.5.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
```

##Kibana の起動確認

以下のコマンドで，設定ファイルを編集する．

```terminal:実行コマンド
# vim /etc/elasticsearch/elasticsearch.yml
```

編集内容は下記の通り．

```yml:/etc/kibana/kibana.yml
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://localhost:9200"]
```

編集が完了したら，サービスの起動とステータス確認を実行する．

```terminal:実行コマンド
$ sudo systemctl start kibana
$ sudo systemctl status kibana
● kibana.service - Kibana
     Loaded: loaded (/etc/systemd/system/kibana.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2020-08-09 13:37:06 JST; 3min 17s ago
   Main PID: 5406 (node)
      Tasks: 11 (limit: 9455)
     Memory: 637.7M
     CGroup: /system.slice/kibana.service
             └─5406 /usr/share/kibana/bin/../node/bin/node /usr/share/kibana/bin/../src/cli
```

Active: active (running) と表示されていれば，サービスが起動しているはずなので，Web ブラウザにてhttp://localhost:5601/ にアクセスする．

#Elasticsearch の設定

作業用ディレクトリを作成する．

```terminal:実行コマンド
# mkdir /tmp/cert_blog
```

CA とサーバー証明書を生成する．

```terminal:実行コマンド
# cd $ES_HOME
# bin/elasticsearch-certutil cert ca --pem
This tool assists you in the generation of X.509 certificates and certificate
signing requests for use with SSL/TLS in the Elastic stack.

The 'cert' mode generates X.509 certificate and private keys.
    * By default, this generates a single certificate and key for use
       on a single instance.
    * The '-multiple' option will prompt you to enter details for multiple
       instances and will generate a certificate and key for each one
    * The '-in' option allows for the certificate generation to be automated by describing
       the details of each instance in a YAML file

    * An instance is any piece of the Elastic Stack that requires an SSL certificate.
      Depending on your configuration, Elasticsearch, Logstash, Kibana, and Beats
      may all require a certificate and private key.
    * The minimum required value for each instance is a name. This can simply be the
      hostname, which will be used as the Common Name of the certificate. A full
      distinguished name may also be used.
    * A filename value may be required for each instance. This is necessary when the
      name would result in an invalid file or directory name. The name provided here
      is used as the directory name (within the zip) and the prefix for the key and
      certificate files. The filename is required if you are prompted and the name
      is not displayed in the prompt.
    * IP addresses and DNS names are optional. Multiple values can be specified as a
      comma separated string. If no IP addresses or DNS names are provided, you may
      disable hostname verification in your SSL configuration.

    * All certificates generated by this tool will be signed by a certificate authority (CA).
    * The tool can automatically generate a new CA for you, or you can provide your own with the
         -ca or -ca-cert command line options.

By default the 'cert' mode produces a single PKCS#12 output file which holds:
    * The instance certificate
    * The private key for the instance certificate
    * The CA certificate

If you specify any of the following options:
    * -pem (PEM formatted output)
    * -keep-ca-key (retain generated CA key)
    * -multiple (generate multiple certificates)
    * -in (generate certificates from an input file)
then the output will be be a zip file containing individual certificate/key files

Please enter the desired output file [certificate-bundle.zip]: 

Certificates written to /usr/share/elasticsearch/certificate-bundle.zip

This file should be properly secured as it contains the private key for 
your instance.

After unzipping the file, there will be a directory for each instance.
Each instance has a certificate and private key.
For each Elastic product that you wish to configure, you should copy
the certificate, key, and CA certificate to the relevant configuration directory
and then follow the SSL configuration instructions in the product guide.

For client applications, you may only need to copy the CA certificate and
configure the client to trust this certificate.
```

生成されたzipファイルを展開し，ファイル(ca.crt, instance.crt, instance.key)を移動する．

```terminal:実行コマンド
# mv certificate-bundle.zip /tmp/cert_blog/
# cd /tmp/cert_blog
# unzip certificate-bundle.zip -d ./certs
# cd $ES_PATH_CONF/
# mkdir certs
# cp /tmp/cert_blog/certs/ca/ca.crt /tmp/cert_blog/certs/instance/instance.crt /tmp/cert_blog/certs/instance/instance.key certs/
```

ファイルが移動したかを確認する．

```terminal:実行コマンド
# ls -l /etc/elasticsearch/certs/
合計 12
-rw-r--r-- 1 root elasticsearch 1200  8月  9 13:54 ca.crt
-rw-r--r-- 1 root elasticsearch 1147  8月  9 13:56 instance.crt
-rw-r--r-- 1 root elasticsearch 1675  8月  9 13:56 instance.key
```

elasticsearch.yml を編集する．

```terminal:実行コマンド
# vim /etc/elasticsearch/elasticsearch.yml
```

以下の内容を編集する．

```yml:/etc/elasticsearch/elasticsearch.yml
xpack.security.enabled: true
xpack.security.http.ssl.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.http.ssl.key: certs/instance.key
xpack.security.http.ssl.certificate: certs/instance.crt
xpack.security.http.ssl.certificate_authorities: certs/ca.crt
xpack.security.transport.ssl.key: certs/instance.key
xpack.security.transport.ssl.certificate: certs/instance.crt
xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
xpack.security.http.ssl.verification_mode: certificate
```

サービスを再起動する．

```terminal:実行コマンド
$ sudo systemctl restart elasticsearch
$ sudo systemctl status elasticsearch
● elasticsearch.service - Elasticsearch
     Loaded: loaded (/lib/systemd/system/elasticsearch.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2020-08-09 14:50:09 JST; 15s ago
       Docs: https://www.elastic.co
   Main PID: 9276 (java)
      Tasks: 75 (limit: 9455)
     Memory: 1.2G
     CGroup: /system.slice/elasticsearch.service
             ├─9276 /usr/share/elasticsearch/jdk/bin/java -Xshare:auto -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=10 -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.>
             └─9475 /usr/share/elasticsearch/modules/x-pack-ml/platform/linux-x86_64/bin/controller

 8月 09 14:50:00 elastic-tls systemd[1]: Starting Elasticsearch...
 8月 09 14:50:09 elastic-tls systemd[1]: Started Elasticsearch.
```

ユーザーパスワードを生成する．

```terminal:実行コマンド
# cd $ES_HOME
# bin/elasticsearch-setup-passwords auto -url "https://localhost:9200"
Initiating the setup of passwords for reserved users elastic,apm_system,kibana,kibana_system,logstash_system,beats_system,remote_monitoring_user.
The passwords will be randomly generated and printed to the console.
Please confirm that you would like to continue [y/N]y


Changed password for user apm_system
PASSWORD apm_system = 

Changed password for user kibana_system
PASSWORD kibana_system = 

Changed password for user kibana
PASSWORD kibana = 

Changed password for user logstash_system
PASSWORD logstash_system = 

Changed password for user beats_system
PASSWORD beats_system = 

Changed password for user remote_monitoring_user
PASSWORD remote_monitoring_user = 

Changed password for user elastic
PASSWORD elastic = 
```

パスワードを利用してhttps で接続できるかを確認する．

```terminal:実行コマンド
$ curl -k --cacert /tmp/cert_blog/certs/ca/ca.crt -u elastic 'https://localhost:9200/_cat/nodes?v'
Enter host password for user 'elastic':
ip             heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.44.190           51          98   4    0.18    0.15     0.16 dilmrt    *      node-4
```

#Kibana の設定

環境変数を設定する．

```terminal:実行コマンド
# vim ~/.bashrc

KIBANA_HOME=/usr/share/kibana
KIBANA_PATH_CONFIG=/etc/kibana
```

設定されているか確認する．

```terminal:実行コマンド
# echo $KIBANA_HOME
/usr/share/kibana
# echo $KIBANA_PATH_CONFIG
/etc/kibana
```

Elasticsearch のTLS 化のために生成したファイルをコピーする．

```terminal:実行コマンド
# mkdir -p /etc/kibana/config/certs
# cp -p /etc/elasticsearch/certs/* /etc/kibana/config/certs/
# ls -l /etc/kibana/config/certs/
合計 12
-rw-r--r-- 1 root elasticsearch 1200  8月  9 13:54 ca.crt
-rw-r--r-- 1 root elasticsearch 1147  8月  9 13:56 instance.crt
-rw-r--r-- 1 root elasticsearch 1675  8月  9 13:56 instance.key
```

kibana.yml を編集する．

```terminal:実行コマンド
# vim kibana.yml
```

以下の内容に編集する．

```yml:/etc/kibana/kibana.yml
server.ssl.enabled: true
server.ssl.certificate: /etc/kibana/config/certs/instance.crt
server.ssl.key: /etc/kibana/config/certs/instance.key
elasticsearch.hosts: ["https://localhost:9200"]
elasticsearch.username: "kibana"
elasticsearch.password: ""
elasticsearch.ssl.certificateAuthorities: [ "/etc/kibana/config/certs/ca.crt" ]
elasticsearch.ssl.verificationMode: none
```

サービスを再起動する．

```terminal:実行コマンド
$ sudo systemctl restart kibana
$ sudo systemctl status kibana
● kibana.service - Kibana
     Loaded: loaded (/etc/systemd/system/kibana.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2020-08-09 15:11:59 JST; 6s ago
   Main PID: 9782 (node)
      Tasks: 11 (limit: 9455)
     Memory: 651.7M
     CGroup: /system.slice/kibana.service
             └─9782 /usr/share/kibana/bin/../node/bin/node /usr/share/kibana/bin/../src/cli
```

Web ブラウザを用いて，https://localhost:5601/ にアクセスし，elastic ユーザーのアカウント情報を用いてログインする．

ログインできれば，本記事で設定したかったことは完了している．

#おわりに
かねてから実施したかったTLS 化について実施し，その手順をまとめることができた．
今後は今までの実践内容や書き留めた記事を使ってElastic Stack 構築時に個人的に設定したいことをまとめておきたい．

また，Logstash のTLS 化にも挑戦したい．

#参考文献
- https://www.elastic.co/jp/blog/configuring-ssl-tls-and-https-to-secure-elasticsearch-kibana-beats-and-logstash#enable-tls-kibana
- https://discuss.elastic.co/t/no-living-connections/183480/3