ようへいの日々精進XP

よかろうもん

IAM Role を付与した EC2 インスタンスから Amazon ES にアクセスするメモ(Ruby 版)

tl;dr

Amazon ES のアクセス制御を IP だけでしかやったことなかったので、実運用を考慮すると IAM role で制御する場合の方法を模索してみましたの Ruby 版。

参考

ありがとうございます。

memo

構成

構成は前回と同様。

  • EC2 には AmazonESFullAccess ポリシーを付与した IAM role がアタッチされている
  • Amazon ES にはポリシー未適用

さんぷるスクリプト

ということで、参考として上げさせて頂いた記事を真似て以下のようなスクリプトをこさえてみました。

require 'elasticsearch'
require 'faraday'
require 'faraday_middleware/aws_signers_v4'
require 'json'

es_endpoint = 'https://your_domain-xxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com'
role_name   = 'your_role_name'
region      = 'ap-northeast-1'

def get_credential
  metadata_url = 'http://169.254.169.254'
  conn = Faraday.new(:url => metadata_url) do |faraday|
    faraday.adapter  Faraday.default_adapter
  end
  response     = conn.get '/latest/meta-data/iam/security-credentials/dev'
  credential   = JSON.parse(response.body)

  return { 'access_key': credential['AccessKeyId'],
           'secret_key': credential['SecretAccessKey'],
           'token': credential['Token'] }

end

credentials  = get_credential()
es = Elasticsearch::Client.new(url: es_endpoint) do |faraday|
  faraday.request :aws_signers_v4,
                  credentials: Aws::Credentials.new(credentials[:access_key], credentials[:secret_key], credentials[:token]),
                  service_name: 'es',
                  region: region
end

puts JSON.dump(es.info)

github.com

この Gem が肝です。前回の Python と同様に署名付きリクエストという壁が立ちはだかりますが、この gem が AWS 署名バージョン 4 を良しなに扱ってくれます。ありがたや、ありがたや。

実行してみると...

#
# 環境の確認
#
$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
$ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]

#
# 必要な gem をインストール
#
$ cat Gemfile
source "https://rubygems.org"

gem 'elasticsearch'
gem 'faraday_middleware-aws-signers-v4'
$ bundle install --path vendor/bundle

#
# スクリプトを実行
#
$ bundle exec ruby sample.rb  | jq .
{
  "name": "Space Turnip",
  "cluster_name": "1234567890123:your_domain",
  "version": {
    "number": "2.3.2",
    "build_hash": "0944b4bae2d0f7a126e92b6133caf1651ae316cc",
    "build_timestamp": "2016-05-20T07:46:04Z",
    "build_snapshot": false,
    "lucene_version": "5.5.0"
  },
  "tagline": "You Know, for Search"
}

おわり

先人の方々の努力のおかげでなんとかなりそうです。ありがとうございました。

おまけ : docker コンテナから Amazon ES にアクセスする場合

ファイル達

上記のサンプルを sample.py で保存。

$ tree .
.
├── Dockerfile
├── Gemfile
└── sample.rb

0 directories, 3 files

Dockerfile

FROM ruby:2.3.1-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 bundle install --path vendor/bundle && \
    bundle clean
ENTRYPOINT ["bundle", "exec", "ruby"]

build して run

$ docker build -t es-sample-ruby .
$ docker run --rm es-sample-ruby sample.rb | 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"
}