IAMロールを付与したEC2インスタンスからのAssumeRole

2016.05.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

菅野です。

複数アカウントを使っている場合、AssumeRoleは非常に便利で私のお気に入りの機能の一つです。
以前のエントリーでは「作成したユーザーを使ってAssumeRoleをする方法」を書かせていただきましたが、今回はユーザーを作成しない方法を書かせていただきます。

はじめに

EC2インスタンスは、作成する時「だけ」IAMロールを付与する事ができます。(将来のアップデートで既存のインスタンスにも付与できるようになるといいですよね)
そのIAMロールにAssumeRoleを許可するポリシーを割り当て、別アカウントのS3バケットにあるオブジェクトを取得する事が今回の目的となります。

S3バケットを持つ側のアカウントの設定

バケットを作成し、適当なファイルをアップロードしておいてください。
AssumeRoleを許可するロールを作成する方法は、こちらの「AssumeRole用のロールを作成する」を参考にしてください。
"Action"を"s3:GetObject"にするだけで他は同じです。

オブジェクトを取得する側のアカウントの設定

まずは、AssumeRoleするにあたって相手のアカウントからセキュリティクレデンシャルを取得するコマンドについて説明します。

aws sts assume-role --role-arn 【相手アカウントで作成したロールのarn】 --role-session-name 【任意のセッション名】

コマンドは非常に簡単な内容で、相手のIAMロールのarnと適当なセッション名を指定するだけです。
EC2インスタンスにはIAMロールが割り当てられていて、ポリシーでAssumeRoleが許可されていますので
先ほどのコマンドを実行すると以下のような結果が得られます。

{
    "AssumedRoleUser": {
        "AssumedRoleId": "**************", 
        "Arn": "arn:aws:sts::**************"
    }, 
    "Credentials": {
        "SecretAccessKey": "**************", 
        "SessionToken": "**************", 
        "Expiration": "2016-05-12T01:26:22Z", 
        "AccessKeyId": "**************"
    }
}

ほとんど伏字になってしまいましたが、ここで必要なのは「AccessKeyId」「SecretAccessKey」「SessionToken」となります。
これらをexportした後でS3バケットからオブジェクトを取得するコマンドを実行すればいいのですが、毎回手作業では大変ですのでスクリプト化しましょう。

スクリプトを作成して実行する

作成するスクリプトの内容は以下となります(ファイル名は「get_file.sh」としました)

#!/bin/sh

# デフォルトリージョンを指定
REGION="ap-northeast-1"
export AWS_DEFAULT_REGION=${REGION}

# セキュリティクレデンシャルを取得
security_credentials=`aws sts assume-role --role-arn 【相手アカウントで作成したロールのarn】 --role-session-name 【任意のセッション名】`

# アクセスキーを設定
access_key=`echo ${security_credentials} | jq -r '.Credentials.AccessKeyId'`
export AWS_ACCESS_KEY_ID=${access_key}

# シークレットアクセスキーを設定
secret_access_key=`echo ${security_credentials} | jq -r '.Credentials.SecretAccessKey'`
export AWS_SECRET_ACCESS_KEY=${secret_access_key}

# セッショントークンを設定
session_token=`echo ${security_credentials} | jq -r '.Credentials.SessionToken'`
export AWS_SESSION_TOKEN=${session_token}

# コマンドを実行
aws s3 cp s3://【バケット名】/【アップロードしたファイル名】 【取得したファイルを保存する時のファイル名】

では実行します。 スクリプトの最後の行を「aaaaaa」バケットにある「1.png」ファイルを取得し、「2.png」という名前で保存するように修正してあります。

$ ./get_file.sh
download: s3://aaaaaa/1.png to ./2.png
$ ls
2.png

無事、別アカウントのS3バケットにアップロードしてあるファイルを取得できました。

さいごに

いかがでしたでしょうか。
このスクリプトを使えばIAMユーザーを作成しなくてもAssumeRoleが可能になりますのでお試しください。

本音を言えば「~/aws/config」ファイルに【相手アカウントで作成したロールのarn】を指定するだけで
自動でAssumeRoleして相手のs3バケットのオブジェクトを取得できればいいのですが、
現時点ではaws-cliでIAMロールからの自動クレデンシャル取得は対応していないようです。

参考ページ

これらのページを参考にさせていただきました。
ありがとうございました。
AWS CLIでAssumeRole
assume-role