share facebook facebook twitter menu hatena pocket slack

2016.09.20 TUE

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

川原 洋平

WRITTEN BY 川原 洋平

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)

winebarrel/faraday_middleware-aws-signers-v4
faraday_middleware-aws-signers-v4 - Faraday middleware for AWS Signature Version 4.

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"
}

元記事はこちら

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