STSで一時クレデンシャルを発行する

2019.06.04

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

Switch Role先の環境で作業はしたい。だけど、アクセスキーを発行しないとツールが使えない。Switch Role先の環境でIAM ユーザを作るわけにもいかない...。
こんな感じで困ったことありませんか。そんな時にAWS STSを知っていればなんとか対処できます。自分が手間取ったのでどう対処したかを書きます。

STSとは

AWS Security Token Serviceの略称で、一時的な認証情報を発行します。
発行される認証情報は、「アクセスキー」、「シークレットキー」、「セッショントークン」の3つが発行されます。
スイッチロールの際にもSTSを使用してスイッチ先の各種リソースにアクセスしてるので、認証情報さえ取り出せばうまいことアクセスキーが使えそうですね。

Assume Role

読んで字のごとく、IAM Roleの権限を引き受けます。STSのこれを呼び出せば、認証情報が取得できます。
図にするとこのような流れで一時クレデンシャルを発行します。

  1. 権限を引き受けるIAM Userで assume-roleをコールする
  2. 2つのアカウントで問題なく権限を委任できるかを確認する
  3. STSから一時クレデンシャルが発行され、レスポンスが返ってくる

sts assume role

どうやって一時クレデンシャルを受け取るかをわかったところで、aws cliを使って実際に取得してみましょう。

$ aws sts assume-role \
  --role-arn          arn:aws:iam::xxxxxxxxxxxx:role/xxxxxxxxxxxx \ # スイッチ先のIAM RoleのARN
  --role-session-name foo-bar-session \ # セッション名 自由に指定できる
  --duration-second   900 \ 一時クレデンシャルの有効期限 900秒以上
  --profile           foo-bar # assume-role をコールするユーザ情報

先ほどの図に当てはめると role-arn は、アカウントBのIAM Roleを割り当てて、 profile にはアカウントAのIAMユーザのプロファイル指定します。

MFAが必須の環境の場合は、MFAデバイスのARNとMFAトークンを追加してコマンドを実行します。

$ aws sts assume-role \
  --role-arn          arn:aws:iam::xxxxxxxxxxxx:role/xxxxxxxxxxxx \
  --role-session-name foo-bar-session \
  --duration-second   900 \
  --profile           foo-bar \
  --serial-number     arn:aws:iam::xxxxxxxxxxxx:mfa/xxxxxxxxxxxx \ # MFAデバイスのARN
  --token-code        123456 # MFAで発行される6桁のトークン

あとは、返ってきたレスポンスを元に環境変数としてエクスポートすれば、アクセスキーを用いてのAWSリソースへのアクセスが可能になります。

.bash_profileに登録する

assume-roleは確かに便利ですけど、毎回実行するのは大変です。なので、bash_profileに一時クレデンシャルを呼び出せる関数を登録しましょう。
jqを事前にいれたmac上での動作はすると思います。mac以外なら最後のpbcopyをしなければ動くとは思います。

関数上部の環境変数はよしなに設定してください。 関数をよびだして、MFAトークンを入力して、貼りつけてエンターを押せば、assume-roleが簡単にできます。

.bash_profile

function foo_assume {
  ROLE_ARN='arn:aws:iam::xxxxxxxxxxxx:role/xxxxxxxxxxxx'
  SERIAL_NUMBER='arn:aws:iam::xxxxxxxxxxxx:mfa/xxxxxxxxxxxx'
  SOURCE_PROFILE='xxxxxxxxxxxx'
  DATE=`date +%s`

  read -sp "Input MFA Code: " TOKEN_CODE

  OUTPUT=`aws sts assume-role \
    --role-arn          ${ROLE_ARN} \
    --serial-number     ${SERIAL_NUMBER} \
    --role-session-name ${DATE}-session \
    --profile           ${SOURCE_PROFILE} \
    --duration-second   1800 \
    --token-code        ${TOKEN_CODE}
  `

  AWS_ACCESS_KEY_ID=`echo $OUTPUT | jq .Credentials.AccessKeyId`
  AWS_SECRET_ACCESS_KEY=`echo $OUTPUT | jq .Credentials.SecretAccessKey`
  AWS_SESSION_TOKEN=`echo $OUTPUT | jq .Credentials.SessionToken`
  echo ""
  echo "export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID"
  echo "export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY"
  echo "export AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN"
  echo "Ctl P makes you Happy..."
  echo "export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID && export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY && export AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN" | pbcopy
}

最後に

これで、アクセスキーが必要なツールでも何とか使えそうになりました。
AWSの利便性もさることながらBashもやはり便利ですね。