これは、なにをしたくて書いたもの?
Elasticsearchのセキュリティまわりを勉強しようかなぁと思いまして。まずは、認証からかな、と。
無料の暗号化とユーザー認証で、Elasticsearchクラスターを安全に保つ | Elastic Blog
SSL、TLS、HTTPSを設定してElasticsearch/Kibana/Beats/Logstashを安全に保つ | Elastic Blog
Elasticsearchをシングルノードで使うか、クラスタを構成するかで、X-Packのセキュリティに関する要件が変わるようなので、
今回はシングルノードで認証・認可に限定して試してみたいと思います。
This requirement applies to clusters with more than one node and to clusters with a single node that listens on an external interface. Single-node clusters that use a loopback interface do not have this requirement. For more information, see Encrypting communications.
Configuring security in Elasticsearch | Elasticsearch Reference [7.5] | Elastic
環境
今回の環境は、こちら。
$ java --version openjdk 11.0.5 2019-10-15 OpenJDK Runtime Environment (build 11.0.5+10-post-Ubuntu-0ubuntu1.118.04) OpenJDK 64-Bit Server VM (build 11.0.5+10-post-Ubuntu-0ubuntu1.118.04, mixed mode, sharing) $ curl localhost:9200 { "name" : "ubuntu1804.localdomain", "cluster_name" : "elasticsearch", "cluster_uuid" : "ZY8nisNbQZmYufnGTBi79Q", "version" : { "number" : "7.5.2", "build_flavor" : "default", "build_type" : "deb", "build_hash" : "8bec50e1e0ad29dad5653712cf3bb580cd1afcdf", "build_date" : "2020-01-15T12:11:52.313576Z", "build_snapshot" : false, "lucene_version" : "8.3.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
Elasticsearch 7.5.2です。
設定は、まずはこんな感じで。
$ sudo grep -vE '^ *#|^$' /etc/elasticsearch/elasticsearch.yml path.data: /var/lib/elasticsearch path.logs: /var/log/elasticsearch network.host: 0.0.0.0 discovery.type: "single-node"
X-Pack Securityを有効にして、認証・認可に関する設定を行う
まずは、X-PackのSecurityを有効にする必要があります。
認証・認可に関する設定の流れは、こちらに書いています。
Configuring security in Elasticsearch | Elasticsearch Reference [7.5] | Elastic
Basicサブスプリクションでも、すべてのX-Pack Securityに関する機能が使えるわけではないですが、ある程度は利用することができます。
サブスクリプション | Elastic Stackプロダクトとサポート | Elastic
X-Pack Securityに関する設定は、こちら。
Security settings in Elasticsearch | Elasticsearch Reference [7.5] | Elastic
User authentication | Elasticsearch Reference [7.5] | Elastic
User authorization | Elasticsearch Reference [7.5] | Elastic
Encrypting communications | Elasticsearch Reference [7.5] | Elastic
とりあえず、認証・認可の設定を行ってみましょう。
まずは、X-Pack Securityを有効にします。
xpack.security.enabled: true
Elasticsearchを再起動します。
$ sudo systemctl restart elasticsearch
この時点で、Elasticsearchにアクセスするのに認証が必要になっています。
$ curl localhost:9200?pretty { "error" : { "root_cause" : [ { "type" : "security_exception", "reason" : "missing authentication credentials for REST request [/?pretty]", "header" : { "WWW-Authenticate" : "Basic realm=\"security\" charset=\"UTF-8\"" } } ], "type" : "security_exception", "reason" : "missing authentication credentials for REST request [/?pretty]", "header" : { "WWW-Authenticate" : "Basic realm=\"security\" charset=\"UTF-8\"" } }, "status" : 401 }
ステータスコード401が返却されました。
次に、ビルドインユーザーのパスワード設定をします。
elasticsearch-setup-passwords | Elasticsearch Reference [7.5] | Elastic
ビルドインユーザーとは、こちらに書かれているユーザーのことです。
Built-in users | Elasticsearch Reference [7.5] | Elastic
「elastic」が管理ユーザー、その他は、たとえばLogstashやBeatsからElasticsearchに接続する際に使用するユーザーです。
パスワードは、今回は「interactive」を指定して、自分で明示します。
$ sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive
「interactive」ではなく「auto」にすると、ビルトインユーザーのパスワードが自動生成されます。
また「-u」オプションで、別のホストだったり、アクセスするプロトコルをHTTPSに変えるといった指定の仕方もしたりします。
$ sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive -u https://[elasticsearch-host]:9200
で、パスワード設定。今回は、一律「password」にしました。
Initiating the setup of passwords for reserved users elastic,apm_system,kibana,logstash_system,beats_system,remote_monitoring_user. You will be prompted to enter passwords as the process progresses. Please confirm that you would like to continue [y/N]y Enter password for [elastic]: Reenter password for [elastic]: Enter password for [apm_system]: Reenter password for [apm_system]: Enter password for [kibana]: Reenter password for [kibana]: Enter password for [logstash_system]: Reenter password for [logstash_system]: Enter password for [beats_system]: Reenter password for [beats_system]: Enter password for [remote_monitoring_user]: Reenter password for [remote_monitoring_user]: Changed password for user [apm_system] Changed password for user [kibana] Changed password for user [logstash_system] Changed password for user [beats_system] Changed password for user [remote_monitoring_user] Changed password for user [elastic]
「elastic」ユーザーを使って、再度Elasticsearchにアクセスすると、今度はアクセス可能になっています。
$ curl -u elastic:password localhost:9200?pretty { "name" : "ubuntu1804.localdomain", "cluster_name" : "elasticsearch", "cluster_uuid" : "ZY8nisNbQZmYufnGTBi79Q", "version" : { "number" : "7.5.2", "build_flavor" : "default", "build_type" : "deb", "build_hash" : "8bec50e1e0ad29dad5653712cf3bb580cd1afcdf", "build_date" : "2020-01-15T12:11:52.313576Z", "build_snapshot" : false, "lucene_version" : "8.3.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
ビルトインユーザーの情報は、「.security」インデックスに入っているみたいです。
$ curl -u elastic:password localhost:9200/_cat/indices?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open .security-7 y1BdDpirSX2g-hYkJp6uhg 1 0 6 0 20.1kb 20.1kb
今回は必須ではありませんが、Realmの設定方法も少し見てみましょう。
ここでは、Native Realmを見てみます。Native Realmは、REST APIやKibanaを使ってユーザーを管理することができるRealmで、
もっとも簡単なものになります。
Native user authentication | Elasticsearch Reference [7.5] | Elastic
Native Realmに関する設定は、こちら。
ドキュメントに習って、Native Realmを最初に確認するようにしてみましょう。ここで指定している「reaml1」というのは、任意で
指定するRealmの名前みたいです。
xpack.security.enabled: true xpack.security.authc.realms: native: realm1: order: 0
Realmの設定は、Nodeに関する情報を取得すると見ることができました。
$ curl -u elastic:password localhost:9200/_nodes?pretty
次に、権限設定をしてみましょう。クラスタ、インデックスに関する権限があるようです。
Security privileges | Elasticsearch Reference [7.5] | Elastic
REST APIを使って、ロールやユーザーの作成などを行うことができます。
Security APIs | Elasticsearch Reference [7.5] | Elastic
最初に、あるインデックスパターンに対する管理者的なロールを作成してみます。ロールの内容はJSONで指定し、ロール名は
URLパスの末尾で指定する形です。
$ curl -XPOST -u elastic:password -H 'Content-Type: application/json' 'localhost:9200/_security/role/my-index-admin-role' -d '{ "indices" : [ { "names" : [ "my-index*" ], "privileges" : [ "all" ] }, { "names" : [ ".kibana*" ], "privileges" : [ "manage", "read", "index" ] } ] } '
インデックスに関する権限を指定し、「my-index*」というパターンに対してすべての権限を、「.kibana」に関しては「manage」、
「read」、「index」権限(ドキュメントのサンプルのまま)を与えます。
次に、「my-index*」パターンに対して、参照のみが可能なロールを作成してみます。
$ curl -XPOST -u elastic:password -H 'Content-Type: application/json' 'localhost:9200/_security/role/my-index-read-only-role' -d '{ "indices" : [ { "names" : [ "my-index*" ], "privileges" : [ "read" ] } ] } '
これらのロールを持ったユーザーを、それぞれ作成します。ロールと同じく、ユーザーの情報はJSONで指定して、ユーザー名はURLの
末尾になります。
$ curl -XPOST -u elastic:password -H 'Content-Type: application/json' 'localhost:9200/_security/user/admin-user' -d '{ "password" : "admin-password", "full_name" : "Admin User", "email" : "admin@example.com", "roles" : [ "my-index-admin-role" ] } ' $ curl -XPOST -u elastic:password -H 'Content-Type: application/json' 'localhost:9200/_security/user/read-only-user' -d '{ "password" : "read-only-password", "full_name" : "ReadOnly User", "email" : "read_only@example.com", "roles" : [ "my-index-read-only-role" ] } '
では、「my-index-1」というインデックスに対して、ドキュメントを登録してみましょう。
ユーザー指定なしでアクセス。
$ curl -XPUT -H 'Content-Type: application/json' 'localhost:9200/my-index-1/_doc/1?pretty' -d' { "name": "Taro" } '
こちらは、認証していないのでエラーになります。
{ "error" : { "root_cause" : [ { "type" : "security_exception", "reason" : "missing authentication credentials for REST request [/my-index-1/_doc/1?pretty]", "header" : { "WWW-Authenticate" : "Basic realm=\"security\" charset=\"UTF-8\"" } } ], "type" : "security_exception", "reason" : "missing authentication credentials for REST request [/my-index-1/_doc/1?pretty]", "header" : { "WWW-Authenticate" : "Basic realm=\"security\" charset=\"UTF-8\"" } }, "status" : 401 }
管理者ロールを持ったユーザーでドキュメントを登録してみます。
$ curl -XPUT -u admin-user:admin-password -H 'Content-Type: application/json' 'localhost:9200/my-index-1/_doc/1?pretty' -d' { "name": "Taro" } '
こちらは成功します。
{ "_index" : "my-index-1", "_type" : "_doc", "_id" : "1", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 0, "_primary_term" : 1 }
参照は、管理者ロールを持ったユーザー、読み取り権限のみのロールを持ったユーザーのいずれでも可能です。
$ curl -u admin-user:admin-password localhost:9200/my-index-1/_doc/1?pretty $ curl -u read-only-user:read-only-password localhost:9200/my-index-1/_doc/1?pretty
読み取り権限のみのロールを持ったユーザーで、ドキュメントの登録を試みてみましょう。
$ curl -XPUT -u read-only-user:read-only-password -H 'Content-Type: application/json' 'localhost:9200/my-index-1/_doc/2?pretty' -d' { "name": "Jiro" } '
認証はできているけれど、書き込み権限がないのでエラーになりました。
{ "error" : { "root_cause" : [ { "type" : "security_exception", "reason" : "action [indices:data/write/index] is unauthorized for user [read-only-user]" } ], "type" : "security_exception", "reason" : "action [indices:data/write/index] is unauthorized for user [read-only-user]" }, "status" : 403 }
ステータスコードも、403ですし。
ユーザーに指定したロール(に含まれる権限)が、有効になっていることが確認できましたね。
監査ログ
あと、監査ログに関する設定もあるみたいですが、今回はパス。
Enabling audit logging | Elasticsearch Reference [7.5] | Elastic
まとめ
Elasticsearchで、シングルノードにおけるX-Pack Securityの有効化と、認証・認可を試してみました。
とりあえず、基礎的なことはわかった気がするので、今度はクラスタを構成したり、SSL/TLSまわりに踏み込んでみようかなと
思います。