Help us understand the problem. What is going on with this article?

EC2 + IAM Role で供給されたクレデンシャルを環境変数として使う

More than 1 year has passed since last update.

2016-12-09 14:15 追記

EC2 上の Docker コンテナ内からでも、AWS_ 環境変数を設定することなくインスタンスプロファイルが使えました。

AWS SDK は AWS_* 環境変数設定されてなかったら自動で http://169.254.169.254/latest/meta-data/... を叩いてクレデンシャルを取りに行きます。で、ホスト直実行でもコンテナ挟むのでもつなぎに行くネットワークは同じ AWS なので問題なくインスタンスプロファイルを取れるのでした。

したがって、この記事に書いてあるような手間をかける必要はありません…

tl;dr

AWS_SECURITY_TOKEN AWS_SESSION_TOKEN を忘れるな

2019-03-11 追記

awscli は AWS_SECURITY_TOKEN で実行できますが、 AWS SDK は AWS_SESSION_TOKEN でないと動作しないものがあるようです。
ログイン画面から発行されるワンタイムパスワードも現在は AWS_SESSION_TOKEN であるため、そちらに統一する方が良さそうです。

時代は IAM Role

EC2 上で AWS リソースにアクセスする場合、専用の IAM ユーザを作ってクレデンシャルを発行してもいいのですが、IAM Role を EC2 に紐付けると便利です。クレデンシャルをアプリケーションコードやスクリプトに埋め込む必要がなくなるからです。

しかし awscli や AWS SDK を埋め込んだコードをホスト上で直に実行する場合は彼らがよしなにクレデンシャルを取得するのでいいのですが、Docker コンテナ上で実行する場合は少々面倒です。-e AWS_ACCESS_KEY_ID= でクレデンシャルを渡したいのですが値はどこから取ればいいのか。

※ 今回は ECS 上ではなく1、直接インスタンス上で docker run する場合の話です。

metadata からクレデンシャルを取り出す

EC2 インスタンス内部から http://169.254.169.254/latest/meta-data/iam/security-credentials/<role name> を叩くと、いま現在有効なクレデンシャルが得られます。これを jq なりでパースして値だけ抜き出せばそのまま使えます。Expiration の時刻になったらクレデンシャルは入れ替わります。

core@ip-10-0-2-126 ~ $ curl -w '\n' http://169.254.169.254/latest/meta-data/iam/security-credentials/<role name>
{
  "Code" : "Success",
  "LastUpdated" : "2016-10-03T09:13:16Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "awsaccesskeyid",
  "SecretAccessKey" : "awssecretaccesskey",
  "Token" : "SecretToken",
  "Expiration" : "2016-10-03T15:26:54Z"
}

ただ、このクレデンシャルを使うには AccessKeyId (= AWS_ACCESS_KEY_ID) と SecretAccessKey (= AWS_SECRET_ACCESS_KEY) だけ抜き出すのでは足りません :cry: Token (= AWS_SECURITY_TOKEN) も一緒にアプリケーション / スクリプトへ渡してあげる必要があります。

シェルスクリプトにするとこういう感じです (curl, jq 前提)。

#!/bin/bash

metadata=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/<role name>/)
export AWS_ACCESS_KEY_ID=$(echo $metadata | jq -r .AccessKeyId)
export AWS_SECRET_ACCESS_KEY=$(echo $metadata | jq -r .SecretAccessKey)
export AWS_SESSION_TOKEN=$(echo $metadata | jq -r .Token)

docker run \
  --rm \
  -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
  -e AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN \
  awesome:latest

自分はこれで数時間ハマったので、今後同じことをする人の助けになれば幸いです。

REF

dtan4
SRE @ Microservices Platform Team
http://dtan4.hatenablog.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away