tl;dr
Amazon ES のアクセス制御を IP だけでしかやったことなかったので、実運用を考慮すると IAM role で制御する場合の方法を模索してみました。
参考
- http://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/es-createupdatedomains.html#es-createdomain-configure-access-policies
- http://dev.classmethod.jp/cloud/aws/amazon-es-iam-based-access-control/
- https://www.hands-lab.com/tech/entry/1034.html
- http://elasticsearch-py.readthedocs.io/en/master/#running-on-aws-with-iam
- https://pypi.python.org/pypi/requests-aws4auth
ありがとうございます。
memo
構成
- EC2 には AmazonESFullAccess ポリシーを付与した IAM role がアタッチされている
- Amazon ES にはポリシー未適用
この状態で Amazon ES にアクセスしてみると…
$ curl https://your_domain-xxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com/ {"Message":"User: anonymous is not authorized to perform: es:ESHttpGet on resource: your_domain"}
リクエストに認証情報を埋め込んであげる必要があるようです。curl の場合にはどーやるのかな…と思ったら…
残念ながら curl で実現するのは難しいようです。
さんぷるスクリプト
ということで、参考として上げさせて頂いた記事を真似て以下のようなスクリプトをこさえてみました。
from elasticsearch import Elasticsearch, RequestsHttpConnection from requests_aws4auth import AWS4Auth import requests import json, os region = 'ap-northeast-1' es_endpoint = 'your_domain-xxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com' role_name = 'your_role_name' def get_credential(): metadata_url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/' + role_name response = requests.get(metadata_url) credential = json.loads(response.text) return { 'access_key': credential['AccessKeyId'], 'secret_key': credential['SecretAccessKey'], 'token': credential['Token'] } credentials = get_credential() awsauth = AWS4Auth( credentials['access_key'], credentials['secret_key'], region, 'es', session_token=credentials['token'] ) es = Elasticsearch( hosts=[{'host': es_endpoint, 'port': 443}], http_auth=awsauth, use_ssl=True, verify_certs=True, connection_class=RequestsHttpConnection ) print json.dumps(es.info())
pypi.python.org
requests-aws4auth という AWS リクエストに認証情報を追加するAWS 署名バージョン 4を良しなに扱ってくれるモジュールを利用することでシンプルなコードになっていると思います。
実行してみると…
# # 環境の確認 # $ cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) $ python -V Python 2.7.5 # # 必要なモジュールを導入 # $ cat requirements.txt boto3 elasticsearch requests requests_aws4auth $ sudo pip install -r requirements.txt # # スクリプトを実行 # $ python test.py | jq . { "cluster_name": "1234567890123:your_domain", "tagline": "You Know, for Search", "version": { "lucene_version": "5.5.0", "build_hash": "0944b4bae2d0f7a126e92b6133caf1651ae316cc", "number": "2.3.2", "build_timestamp": "2016-05-20T07:46:04Z", "build_snapshot": false }, "name": "Rage" }
おわり
先人の方々の努力のおかげでなんとかなりそうです。ありがとうございました。
おまけ : docker コンテナから Amazon ES にアクセスする場合
ファイル達
上記のサンプルを sample.py で保存。
$ tree . . ├── Dockerfile ├── requirements.txt └── sample.py 0 directories, 3 files
Dockerfile
FROM python:2.7.12-alpine MAINTAINER inokappa RUN apk --update add tzdata && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ apk del tzdata && \ rm -rf /var/cache/apk/* RUN mkdir /app COPY . /app WORKDIR /app RUN pip install -r requirements.txt ENTRYPOINT ["python"]
build して run
$ docker build -t es-sample-python . $ docker run --rm es-sample-python sample.py | jq . { "cluster_name": "1234567890123:your_domain", "tagline": "You Know, for Search", "version": { "lucene_version": "5.5.0", "build_hash": "0944b4bae2d0f7a126e92b6133caf1651ae316cc", "number": "2.3.2", "build_timestamp": "2016-05-20T07:46:04Z", "build_snapshot": false }, "name": "Space Turnip" }