はじめに
まいどおなj(ry
API Keyとは
Elasticsearch 6.7以降に追加されるAPI Key Serviceを使うと、BASIC認証の代わりにAPI Keyを使ってElasticsearchにアクセスできるようになります。
ドキュメントは、このへんです。
使い方
さっそく使ってみます。
準備
API Keyを使うには、Securityを有効にした状態のElasticsearchで、さらにTLS/SSLを有効にするか、xpack.security.authc.api_key.enabled
をtrueにします。
細かいことは、ここに書いてあります。
API Keyの作成(その1)
準備ができたところで、API Keyを作成します。
Keyの作成は、以下のようなリクエストを送ります。
このリクエストでは、clusterに対するすべての権限を持ち、test_idx*
というIndexに対してread
権限を持つAPI Keyを作成しています。
POST /_security/api_key
{
"name": "api-key-1",
"role_descriptors": {
"role-a": {
"cluster": ["all"],
"index": [
{
"names": ["test_idx*"],
"privileges": ["read"]
}
]
}
}
}
すると、レスポンスとしてid
やapi key
が返ってきます。
{
"id" : "HW2CxWgBpzHQiGdVVGQo",
"name" : "api-key-1",
"api_key" : "AFBTRIOlS3eF1whp9qvnIw"
}
API Keyの確認
確認してみます。
GET _security/api_key?name=api-key-1
{
"api_keys" : [
{
"id" : "HW2CxWgBpzHQiGdVVGQo",
"name" : "api-key-1",
"creation" : 1549501879290,
"invalidated" : false,
"username" : "elastic",
"realm" : "reserved"
}
]
}
今回作成したAPI Keyは有効期限を指定していないのでexpiration
の項目はありません。
よくよく見ると、API Key自体は返ってきません。なので、作成時のレスポンスに記載されたAPI Keyは忘れないように、どっかに保存しておきましょう。
API Keyの作成(その2)
え?さっき作成したでしょ?
いえ。実際に使うには、「<id>:<api key>」をbase64でエンコードしたものを使います。
その辺の話は、ここの下の方に書いてあります。
というわけで早速API Keyを作ります。
# echo -n HW2CxWgBpzHQiGdVVGQo:AFBTRIOlS3eF1whp9qvnIw | base64
SFcyQ3hXZ0JwekhRaUdkVlZHUW86QUZCVFJJT2xTM2VGMXdocDlxdm5Jdw==
できましたね。この「SFcyQ3hXZ0JwekhRaUdkVlZHUW86QUZCVFJJT2xTM2VGMXdocDlxdm5Jdw==」も重要なのでどっかに保存しておきます。
検索してみる
では、作成したAPI Keyを使って検索してみます。
# curl -H 'Authorization: ApiKey SFcyQ3hXZ0JwekhRaUdkVlZHUW86QUZCVFJJT2xTM2VGMXdocDlxdm5Jdw==' -H 'Content-type: application/json' 'http://localhost:9200/test_idx1/_search?pretty' -d'{"size": 0}'
Securityが有効なので、通常であれば-u
でユーザとパスワードを指定するところですが、上のリクエストでは書いてませんね。
でも、ちゃんと結果は返ってきます。
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 0.0,
"hits" : [ ]
}
}
curlだと長ったらしいので、HTTPieを使ってみます(若干癖がありますが)。
# http localhost:9200/test_idx1/_search Content-type:"application/json" Authorization:"ApiKey SFcyQ3hXZ0JwekhRaUdkVlZHUW86QUZCVFJJT2xTM2VGMXdocDlxdm5Jdw=="
ちゃんと結果が返ってきます。
HTTP/1.1 200 OK
content-encoding: gzip
content-length: 202
content-type: application/json; charset=UTF-8
{
"_shards": {
"failed": 0,
"skipped": 0,
"successful": 5,
"total": 5
},
"hits": {
"hits": [
{
"_id": "OVu3JmgBLVkCxyA_LNSK",
"_index": "test_idx1",
"_score": 1.0,
"_source": {
"foo": "bar"
},
"_type": "docs"
}
],
"max_score": 1.0,
"total": 1
},
"timed_out": false,
"took": 1
}
権限のないIndexを検索してみます。
# curl -H 'Authorization: ApiKey SFcyQ3hXZ0JwekhRaUdkVlZHUW86QUZCVFJJT2xTM2VGMXdocDlxdm5Jdw==' -H 'Content-type: application/json' 'http://localhost:9200/metricbeat-*/_search?pretty' -d'{"size": 0}'
検索結果がありませんね。ただ、エラーが出るわけじゃないですね。
ちょっとわかりにくいかも。
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 0,
"successful" : 0,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 0,
"max_score" : 0.0,
"hits" : [ ]
}
}
API Keyの無効化
では、API Keyを無効化してみます。
# curl -XDELETE http://localhost:9200/_security/api_key -d'{"name": "api-key-1"}' -H 'Content-type: application/json' -u elastic:<elasticユーザのパスワード>
{"invalidated_api_keys":["HW2CxWgBpzHQiGdVVGQo"],"previously_invalidated_api_keys":[],"error_count":0}
無事に無効化できました。
それでは、再度API Keyを使って検索してみます。
# http localhost:9200/test_idx1/_search Content-type:"application/json" Authorization:"ApiKey SFcyQ3hXZ0JwekhRaUdkVlZHUW86QUZCVFJJT2xTM2VGMXdocDlxdm5Jdw=="
ちゃんと無効化されていることがわかります。
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="security" charset="UTF-8"
content-encoding: gzip
content-length: 177
content-type: application/json; charset=UTF-8
{
"error": {
"header": {
"WWW-Authenticate": "Basic realm=\"security\" charset=\"UTF-8\""
},
"reason": "api key has been invalidated",
"root_cause": [
{
"header": {
"WWW-Authenticate": "Basic realm=\"security\" charset=\"UTF-8\""
},
"reason": "api key has been invalidated",
"type": "security_exception"
}
],
"type": "security_exception"
},
"status": 401
}
おわりに
若干動きが不思議ちゃん(KibanaのConsoleから無効化ができない)とかありますが、色々と遊べそうな機能ですね。