AWS SDK for Ruby 2.4.0でSharedCredentialFileに書いたRoleからAssumeRoleする

2016.07.21

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

望月です。

2016/07/19にリリースされた AWS SDK for Ruby 2.4.0から、SharedCredentialFileに記載されたrole_arnに対してのAssumeRoleができるようになっています。

...何だって?

AWSのAPIを実行するためにはAPI Keyの指定が必要です。このAPI Keyはソースコード内にハードコードせずに外部から読み込むことが推奨されています。EC2上でプログラムを実行するのであればIAM Roleから取得するのが最も良い方法ですし、EC2以外の場所でプログラムを実行する場合は、環境変数として設定するか、AWSのクレデンシャル記載用ファイルにアクセスキーとシークレットキーを記載するのが一般的です。

このファイルはデフォルトでは~/.aws/credentialsになります。このファイルのことはShared Credential Fileとドキュメントに記載されることが多いため、以降このブログでもそのように記載します。

AWS CLIや各種言語のSDKからShared Credential Fileに書かれたアクセスキーを読み込んで利用することが可能です。さらにAWS CLI(Python boto)では、クレデンシャルファイルにIAM RoleのARNを書いておけば、AssumeRoleして取得した一時アクセスキーを利用してAPIを実行してくれるboto独自の拡張が実施されていました。詳しくは以下のブログ記事を参照ください。

クラスメソッドでは自分専用のAWSアカウントにIAMユーザを作成し、その他のプロジェクト用AWSアカウントにはIAMユーザを作成せず、IAM RoleでAssumeRoleするようにしています。こうすることで永続化されたアクセスキーを保管する必要が最小限になるため、セキュリティリスクを抑えることができます。そのため、この機能が非常に便利でして私も多用しています。

ですが、Python SDK独自の拡張のため、それ以外の言語ではこの機能を利用することができませんでした。私は普段Rubyを使うことが多いため、Ruby SDKで実装されるのを楽しみにしていました。GithubのPull Requestを発見したのでマージされるのを楽しみにしていました。

このがPRがマージされてGemがリリースされたことで、バージョン2.4.0からはAssumeRoleが利用できるようになりました!

2016/07/21 12:15追記: 調べてみたところ、JavaやC++等のSDKでも本機能に相当するものが実装されているようですが、本記事ではRubyでのみ確認、検証を行っております。

実装

まず、Shared Credential File(~/.aws/credentials)ファイルを以下のように記載します。

$ cat ~/.aws/credentials
[default]
aws_access_key_id = AKIAXXXXXXXXXXXXXXXX
aws_secret_access_key = YYYYYYYYYYYYYYYYYYYYYYY
region = ap-northeast-1

[switchrole]
role_arn = arn:aws:iam::123456789012:role/cm-mochizuki.masao
source_profile = default

[default]セクションにAssumeRole元のクレデンシャルを記載し、[switchrole]セクションに切替対象のrole_arnを記載しておきましょう。source_profileにはAssumeRole元のセクション名が入ります。

これが完了したらあとは簡単なプログラムで動作確認しておきます。以下のファイルは

require 'aws-sdk'

puts "SDK Version: #{Aws::VERSION}"

source_identity = Aws::STS::Client.new(profile: 'default')
puts source_identity.get_caller_identity.account

# AssumeRole用のProfile Nameを記載
switch_identity = Aws::STS::Client.new(profile: 'switchrole')
puts switch_identity.get_caller_identity.account

SDKバージョンを確認したあと、AssumeRole前と後で、それぞれのAWSアカウントIDを取得し、変化があることを確認してみます。以下が実行結果です。

$ ruby sample.rb
SDK Version: 2.4.0
012345678901
123456789012

別AWSアカウントにAssumeRoleしてAPIが発行されていることが確認できました。

今まではSDKの外で都度AssumeRoleして一次クレデンシャルを取得する必要がありましたが、今回のアップデートでその役割をSDKが実施してくれるようになり、たいへん便利になりました。ぜひご活用ください。

また、AssumeRoleができるようになった以外にも、AWSのエンドポイントリージョンもShared Credential Fileから取得してくれるようになりました。そのためリージョン指定が不要になっています。これも地味に嬉しいですね!