IAMの一時的なセキュリティ認証情報文字列を手軽に取得したい

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

最近Lambda Functionを実装していたのですが、デプロイが面倒なのでnode-aws-lambdaを利用するようになりました。そこで一時的なセキュリティ認証情報文字列を取得して認証を行うためのBashスクリプトを書きましたという話です。Assume Role可能なこと(例えばSwitch Role可能なIAMロールが存在すること)を前提としています。なお、今回はGulpを例にしていますが、Bashスクリプトを編集すればRedshiftのcopyやunloadのcredentials文字列を生成するのにも利用できると思います。

node-aws-lambdaの利用方法についてはAWS LambdaファンクションをGulpでデプロイを参照して下さい。なお、この記事ではAWSの認証にEC2インスタンスのIAMロールを利用していましが、私はローカルのMacから直接Lambdaにデプロイをしていたのでデプロイ時の認証にEC2インスタンスのIAMロールを利用できませんでした。そこでJavaScript SDKの認証方式の一覧を確認した所、以下の方法が記載されていました。

  1. Loaded from IAM roles for Amazon EC2 (if running on EC2),
  2. Loaded from the shared credentials file (~/.aws/credentials),
  3. Loaded from environment variables,
  4. Loaded from a JSON file on disk,
  5. Hardcoded in your application

この記事で扱うのは「3. Loaded from environment variables」になります。前提として弊社では複数のAWSアカウントを操作することが多いためLambda FunctionをデプロイしているAWSアカウントに対するSwitch Role可能なIAMユーザーのアクセスキーは既に手元にありました。そのため、できればデプロイのためだけにIAMユーザーを作るのではなくSwitch Role可能なIAMユーザーのアクセスキーから一時的なセキュリティ認証情報を取得して利用したいわけです。

一時的なセキュリティ認証情報文字列の取得

以下のようなBashスクリプトを作成しました。要はAWS CLIのsts assume-role1コマンドを実行し、jqでその結果から認証文字列を取得してechoで出力しているだけです。公式ドキュメントに書いてある内容をBashスクリプトにしただけだったりします(^_^;)

#!/bin/bash

profile=$1
role_arn=$2
role_session_name=${USER} # お好みで
duration_seconds=900 # 900-3600 必要に応じて増減

result=`aws --profile ${profile} sts assume-role --role-arn ${role_arn} --role-session-name ${role_session_name} --duration-seconds ${duration_seconds}`
access_key_id=`echo ${result} | jq -r '.Credentials.AccessKeyId'` 
secret_access_key=`echo ${result} | jq -r '.Credentials.SecretAccessKey'` 
session_token=`echo ${result} | jq -r '.Credentials.SessionToken'` 

echo export AWS_ACCESS_KEY_ID=${access_key_id}
echo export AWS_SECRET_ACCESS_KEY=${secret_access_key}
echo export AWS_SESSION_TOKEN=${session_token}

実際に実行すると以下の様な感じになります。前述のBashスクリプトはaws-temporary-token.shというファイル名にしました。コマンドの第一引数の${profile} には~./aws/configに記載しているprofileを、第二引数の${role-name}にはrole_arnを指定して下さい。また、私が利用しているIAMロールはMFAを必須としているため、スクリプトを実行するとMFA codeの入力が求められます。

$ ./aws-temporary-token.sh ${profile} ${role-name}
Enter MFA code: 
export AWS_ACCESS_KEY_ID=ASIAJBXYA7HXE7ZUJ5QQ
export AWS_SECRET_ACCESS_KEY=Q6xKN8TJjkjJ2l8H0nPYSGlkzNTtGzwE2KcIyRC7
export AWS_SESSION_TOKEN=AQoDYXdzEGoakAIS8VUdZ3...
$ 

コマンドの出力結果であるecho文をそのまま貼り付ければGulp(node-aws-lambda)でLambda Functionのデプロイが出来るようになります。以下の様な感じです。

$ export AWS_ACCESS_KEY_ID=ASIAJBXYA7HXE7ZUJ5QQ
$ export AWS_SECRET_ACCESS_KEY=Q6xKN8TJjkjJ2l8H0nPYSGlkzNTtGzwE2KcIyRC7
$ export AWS_SESSION_TOKEN=AQoDYXdzEGoakAIS8VUdZ3...
$ 
$ gulp deploy
[09:32:28] Using gulpfile ~/aaa/bbb/ccc/gulpfile.js
[09:32:28] Starting 'deploy'...
[09:32:28] Starting 'clean'...
[09:32:28] Finished 'clean' after 52 ms
[09:32:28] Starting 'js'...
[09:32:28] Starting 'node-mods'...
[09:32:32] Finished 'node-mods' after 3.97 s
[09:32:33] Finished 'js' after 4.98 s
[09:32:33] Starting 'zip'...
[09:32:34] Finished 'zip' after 803 ms
[09:32:34] Starting 'upload'...
[09:32:35] Finished 'upload' after 1.49 s
[09:32:35] Finished 'deploy' after 7.33 s
$ 

Redshift用のcredentials文字列が欲しい場合

前述のBashスクリプトの最後のechoコマンドを発行している箇所を以下の内容に変更して下さい。

echo "aws_access_key_id=${access_key_id};aws_secret_access_key=${secret_access_key};token=${session_token}"

copyやunloadには長時間かかる場合があると思いますが、公式ドキュメントにもあるように途中で一時的なセキュリティ認証情報が無効なると処理に失敗するのでご注意下さい。Assume Roleで取得可能な一時的なセキュリティ認証情報の有効期限は最大で1時間なので、処理対象となるレコード数を減らして分割で作業するか専用のIAMユーザー(アクセスキー)を作成するようにして下さい。

まとめ

一時的なセキュリティ認証情報は有効期限を過ぎると無効になるため、セキュリティの観点からも積極的に利用していければと思います。あと、IAMユーザー(アクセスキー)を作成しないで済むのも手軽でいいと思っています(Assume Role可能なIAMロールを作成済みという前提はありますが)。


  1. Assume Role自体を一時キーを用いて行う手順についてはAWS CLIがAssumeRoleによる自動クレデンシャル取得とMFAに対応しました!を参照して下さい。