Elasticsearch と Kibana のセキュリティを設定する

この記事は Elasticsearch のベーシックライセンス(デフォルトの配布)で、Elastic Stack 6.8 および 7.1 から一部無料になったセキュリティ機能の設定を調査、実施した内容をまとめたものです。

目次

動機と前提

検証・調査のためにいろいろ試行錯誤できる Elasticsearch を設置したいと考えました。
検証用途なので、できるだけリーズナブルに運用するため、フルマネージドのサービスは使用せず、社用のVPS上に構築して、Elastic Stack 6.8 および 7.1 から一部が無料になっているセキュリティ機能の設定を行ってみました。

環境は CentOS 7 に Elasticsearch と Kibana(バージョンは 7.6.2)がインストールされている状態です。
また、Elasticsearch はシングルノードで構築しています。

セキュリティって?

ご存じの方には釈迦に説法ですが、セキュリティを有効化する前に、そもそも何を行えばセキュリティが有効になっている(扱う情報が守られた状態になっている)のかを考えてみたいと思います。

まずわかりやすいのは、 認証 かと思います。
ユーザー名とパスワードを用いて、ログインしようとしているユーザーがそのサービスの正当なユーザーかどうかを判別するサービスを目にする機会は多いかと思います。認証を行うことで、大切な情報を不正なユーザーに閲覧、操作されることを防ぐことができます。

次に 認可 です。
認証 によって、正当なユーザーかどうかを判別できたとしても、ログインできたユーザーが全ての情報にアクセスできる状態では、誤って他のユーザーに必要な情報を壊したり削除してしまうかもしれません。多くのサービスはユーザー毎に情報への適切なアクセス許可が必要になります。ロールの設定、などと呼ばれるようなアクセス権限を施すことで、適切なユーザーが適切な情報へアクセスすることができます。

最後に 暗号化 です。
単純に暗号化という言葉だけでは様々な意味が考えられますが、ここでは通信する情報の内容を第三者に盗聴されたり改ざんされたりすることを防ぐ手法を指します。
せっかく 認証認可 をおこなっていても、通信中に情報が漏洩し、改ざんされてしまっては意味がありませんので、通信する情報を暗号化する必要があります。

認証認可暗号化 が揃うことで、最低限のセキュリティを有効にしたといえそうですので、これらの設定を行っていきたいと思います。

Elastic Security の有効化とビルトインユーザーのパスワードの設定

Elastic Security を有効化するためには、以下の一行を elasticsearch.yml へ追記します。

xpack.security.enabled: true

追記できたら、サービスを再起動します。

$ sudo systemctl restart elasticsearch

パスワードの設定

次に、以下のコマンドでネイティブ認証を有効にして、ビルトインユーザーのパスワードをリセットします。
※今回はシングルノードで構成していますが、このパスワードは、クラスター全体で有効になるようです。
<ES_HOME> は Elasticsearch がインストールされているディレクトリです。

$ sudo <ES_HOME>/bin/elasticsearch-setup-passwords auto

ビルトインユーザー(elastic、kibana、apm_system、logstash_system、beats_system、remote_monitoring_user)のパスワードが表示されるので、控えておきます。
ちなみに、オプションを auto ではなく interactive にすると、対話形式で一つ一つパスワードの設定が行えます。  

Kibana の設定

Kibana を使用するために、 kibana.yml へ Elasticsearch のユーザーとして、先程生成したビルトインユーザー kibana と、そのパスワードを追記してサービスを再起動します。

elasticsearch.username: "kibana"
elasticsearch.password: "<KIBANA_PASSWORD>"
$ sudo systemctl restart kibana

ブラウザで Kibana にアクセスし、ビルトインユーザー elastic でログオンできれば成功です。

この時点で、Kibana の ManagementSecurity から、ユーザーとロールの作成、設定、削除が行えるようになります。

f:id:ken01-linkode:20200514125839p:plain

任意のユーザーを作成、設定して、そのユーザーで Kibana へログインし直すこともできます。
これで、 認証認可 が行えるようになりました。

通信の暗号化

続けて 暗号化 を行っていきます。
Elasticsearch ノードとクライアントの通信はデフォルトではメッセージを平文のままで送受信する HTTP で行われていますが、これを暗号化された HTTPS にすることができます。
Kibana との通信も同様です。

必要になるものは次のとおりです。

  1. 認証局の公開鍵(PKCS#12とPEM形式)
  2. Elasticsearchノードの公開鍵と秘密鍵PKCS#12形式)
  3. Kibanaの公開鍵と秘密鍵(PEM形式)

公開鍵、秘密鍵認証局

公開鍵、秘密鍵認証局をそれぞれ簡単に説明すると、次の通りです。

  • 公開鍵: 通信を暗号化するための鍵(データ)です。秘密鍵から作られ、単に「証明書」と呼ばれたりします。
  • 秘密鍵: 暗号化された通信を復号化するための鍵(データ)です。
  • 認証局: 公開鍵証明書の発行者です。

暗号化の手法や規格は、Wikipedia 等でも確認することができます。

公開鍵暗号 - Wikipedia
公開鍵証明書 - Wikipedia
認証局 - Wikipedia PKCS - WikipediaPKCS#12の解説が確認できます)
X.509 - Wikipedia (PEM形式の解説が確認できます)

認証局の作成

Elasticsearch に同梱されているツールを使って、認証局(ファイル)を作成することができます。
コマンドは以下のとおりです。

$ <ES_HOME>/bin/elasticsearch-certutil ca

コマンドを実行すると、対話形式で任意のファイル名とパスワードを求められますが、何も指定せずに進めることもできます。
その場合、認証局のファイル名は elastic-stack-ca.p12 となります。
作成したファイルには、認証局の公開鍵と、秘密鍵が含まれます。
openssl pkcs12 -in elastic-stack-ca.p12 -nodes コマンドで、内容を確認することができます。

Elasticsearch ノードの証明書の発行

次に、認証局秘密鍵を使って、Elasticsearchノードの証明書の発行します。
コマンドは以下のとおりです。

$ <ES_HOME>/bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12

こちらも対話形式で、任意のファイル名やパスワードを求められますが、指定なしで進めることができます。
指定なしで進めた場合の証明書のファイル名は elastic-certificates.p12 となります。

この証明書には、認証局の公開鍵、ノードの公開鍵、秘密鍵が含まれます。内容は openssl pkcs12 -in elastic-certificates.p12 -nodes コマンドで確認することができます。

Elasticsearch と通信するための公開鍵の作成

Kibana が Elasticsearch と通信するために、認証局の公開鍵が必要になります。
以下のコマンドを用いると認証局の公開鍵をPEM形式で取り出すことができます。ファイル名は elastic-stack-cacert.pem としています。

$ openssl pkcs12 -in elastic-stack-ca.p12 -out elastic-stack-cacert.pem

このとき、対話形式で認証局のパスワードが求められますので、設定していたパスワードを入力します(何も設定しなかった場合はそのまま進めます)。
続けてパスフレーズが求められますが、こちらは 4~1024文字のパスフレーズが必要 になるので、注意が必要です。

各証明書の配置と設定

Elasticsearch

Elasticsearch ノードの証明書 elastic-certificates.p12/etc/elasticsearch/certs などのディレクトリへ配置します。
このとき、sudo chmod 660 elastic-certificates.p12 として、適切なアクセス権を設定する必要があります。

配置が行えたら、 elasticsearch.yml へ以下の設定を追加します。

xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: certs/elastic-certificates.p12
xpack.security.http.ssl.truststore.path: certs/elastic-certificates.p12

サービスを再起動すると、先に設定していたユーザー名とパスワードで https://<ES_DOMAIN>:9200/ へアクセスできるようになります。
http://~ ではなく、https://~ になっています。
<ES_DOMAIN> は、Elasticsearch が稼働しているサーバのドメイン名 or IPアドレスです。

Kibana(Kibana と Elasticsearch の通信)

Kibana から Elasticsearch へ通信するために、認証局の公開鍵 elastic-stack-cacerts.pem を任意のディレクト/etc/kibana 等にコピーして、以下の設定を kibana.yml に追加します。

elasticsearch.hosts: ["https://<ES_DOMAIN>:9200"]
elasticsearch.ssl.certificateAuthorities: [ "/etc/kibana/elastic-stack-cacert.pem" ]
elasticsearch.ssl.verificationMode: certificate

Kibana(クライアントと Kibana の通信)

今度はクライアントから Kibana への通信を暗号化します。
公的な認証局を介する代替として、最初に作成した認証局で Kibana の公開鍵と秘密鍵を作成する手段が提供されています。

以下のコマンドで、Kibana の公開鍵と秘密鍵を作成します。

$ <ES_HOME>/bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12 --pem --name kibana

実行すると、certificate-bundle.zip という zip ファイルが出力されます。 zip には kibana.crtkibana.key が含まれていて、公開鍵(証明書)と秘密鍵になります。
それぞれ、/etc/kibana などのディレクトリへコピーします。
また、sudo chmod 660 kibana.key で適切なアクセス権を設定する必要があります。

ファイルの配置が行えたら、 kibana.yml へ以下の設定を追加します。

server.ssl.enabled: true
server.ssl.key: /etc/kibana/kibana.key
server.ssl.certificate: /etc/kibana/kibana.crt

再度、サービスを再起動して、ブラウザから https://<KIBANA_DOMAIN>:5601 へアクセスできれば成功です。
<KIBANA_DOMAIN> はKibanaを稼働させているサーバのドメイン名です。
※今回の例では、公的な認証局を通していないため、ブラウザの警告が出るかと思います。

以上で、Elasticsearch と Kibana の 暗号化 の設定が行えました。

参考資料