Amazon Elasticsearch Service は、アクセス制御が IAM や IPアドレスでできます。最初は IPアドレスフィルタでいじってたのですが、将来的にドツボにはまりそうだったため IAM で行うようにしました。
なお、Amazon Elasticsearch Service のアクセスポリシーの変更は、指定してから20分ぐらい待たないと反映されないため、面倒です。早めの IAM 化が楽だと思います。(反映待ちの間もサービスは使えます)
IAM ユーザーの作成
IAM のユーザーページ
https://console.aws.amazon.com/iam/home#users
より「新規ユーザーの作成」
→適当に作ります
完成後、 「ユーザーのセキュリティ認証情報を表示」リンクをクリックして、
アカウント名、アクセスキー ID、シークレットアクセスキー を記録しておきます。
できたら、左タブより「ユーザー」ページを表示し、先ほど作成したユーザーを選択。
「ユーザーのARN」が表示されているので、これもコピーしておきます。
こんなの → arn:aws:iam::000000000000:user/xxxxxxxxxxxxx
Elasticsearch のアクセスポリシーの作成
Amazon Elasticsearch Service dashboard
https://ap-northeast-1.console.aws.amazon.com/es/home
を開き、ドメインを選択。
Modify access policy → Select a template → Allow or deny access to one or more AWS accounts or IAM users を選択。
Effect: Allow にして、 Account ID or ARN に先ほどの ARN をペースト。
アクセスポリシーの JSON が生成されるので、「Submit」→「OK」とボタンを押します。
再度、Modify access policy ページを開くと、Status が Processing になります。反映されるとここが Active になります(ブラウザリロード不要)。20分ぐらいかかります。
IPアドレスでも許可する場合
この手順でアクセスポリシーを作った場合、IAM 認証をしないと ES にアクセスできないため、Kibana をブラウザから見たい場合ちょっと困ります。そのため、Kibana にアクセスする IPアドレスを OR 条件で許可した方が使い勝手が良いでしょう。
アクセスポリシーの Statement リストに、ポリシーを追加します。
(上のがIPアドレスホワイトリスト、下のが IAM での制御)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"000.000.000.000"
]
}
},
"Resource": "arn:aws:es:ap-northeast-1:000000000000:domain/hogehoge/*"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::000000000000:user/xxxxxxxxxxxxx"
},
"Action": "es:*",
"Resource": "arn:aws:es:ap-northeast-1:000000000000:domain/hogehoge/*"
}
]
}
テストスクリプトの作成
https://github.com/elastic/elasticsearch-py/issues/280 この Issue を参考に
必要ライブラリのインストール
$ pip install elasticsearch requests_aws4auth
(もしかしたら requests も必要かもしれません。僕の環境では既に入ってたので必要かわかりませんでした)
コード
import elasticsearch
from requests_aws4auth import AWS4Auth
host = 'xxxxxxxx.ap-northeast-1.es.amazonaws.com'
awsauth = AWS4Auth(
'アクセスキーID',
'シークレットアクセスキー', 'ap-northeast-1', 'es')
es = elasticsearch.Elasticsearch(
hosts=[{'host': host, 'port': 443}],
http_auth=awsauth,
use_ssl=True,
verify_certs=True,
connection_class=elasticsearch.connection.RequestsHttpConnection
)
print(es.info())
print(es.cluster.health())
先ほどの、AWSの Elasticsearch の アクセスポリシーページの、「Status」が「Active」になるまで待ちます。
ページを開きっぱなしで待ってて良いです。(ブラウザのリロードを連打しなくても良い)
Active になる前だと
elasticsearch.exceptions.AuthorizationException: TransportError(403, '{"Message":"User: arn:aws:iam::000000000000:user/xxxxxxxxxxxxx is not authorized to perform: es:ESHttpGet on resource: arn:aws:es:ap-northeast-1:000000000000:domain/hogehoge/"}')
このエラーになります。
Status が Active になった後は
{'version': {'lucene_version': '4.10.4', 'build_timestamp': '2015-04-27T09:21:06Z', 'build_snapshot': False, 'build_hash': '62ff9868b4c8a0c45860bebb259e21980778ab1c', 'number': '1.5.2'}, 'status': 200, 'cluster_name': '000000000000:hedgehoge', 'tagline': 'You Know, for Search', 'name': 'Ororo Munroe'}
{'active_primary_shards': 11, 'number_of_pending_tasks': 0, 'cluster_name': '000000000000:hedgehoge', 'relocating_shards': 0, 'active_shards': 11, 'status': 'yellow', 'timed_out': False, 'number_of_nodes': 1, 'unassigned_shards': 11, 'number_of_data_nodes': 1, 'initializing_shards': 0}
結果が返ってきます🎉
…ビルド古い…