🦀

AWS のスイッチロールを簡単に実行するコマンドを書きました

2024/05/25に公開

類似品は色々とあるし、何なら AWS CLI と簡単なシェルスクリプトだけでも実現できます[1]

https://github.com/99designs/aws-vault
https://github.com/yoshihitoh/assume-rolers
https://github.com/sinofseven/aws-masquerade

環境変数に AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY なんかを入れておいたらよしなにしてくれるやつが欲しかったんですが、探してみたけどどれもそういうことはできませんでした。
aws-vault は自分で Secret Service や Keychain につないで安全に AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY を保存してくれるみたいなんですが MFA で使う TOTP の計算は外部のコマンドを使わないといけなくて微妙に使いたい感じではありませんでした。あと、元から envchain を使っていたので AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY だけでなく任意の環境変数をいくつかまとめて設定したいというのもありました。

環境変数から色々とセットしたいのと TOTP くらい自動で計算して欲しいというので作りました。

https://github.com/okkez/aws-assume-role-rs

使い方は README.md を見てください。Linux では動作確認しています。たぶん Unix 系の OS だったら動く思います。

おすすめの使い方は envchain と組み合わせて使う方法です。[2]

まず、設定ファイルを用意します。ここでは TOML を使っていますが $HOME/.aws/config に INI で書くこともできます。

$HOME/.aws/config.toml
[profile.test]
role_arn = "arn:aws:iam::123456789012:role/Developer"

[profile.test-admin]
role_arn = "arn:aws:iam::123456789012:role/PowerUserRole"

[profile.production-viewer]
role_arn = "arn:aws:iam::123456789876:role/Viewer"

[profile.production-maintainer]
role_arn = "arn:aws:iam::123456789876:role/Maintainer"

こんな感じで環境変数を保存します。ポイントは SERIAL_NUMBERTOTP_SECRET です。
SEREAL_NUMBER は AWS コンソールの IAM User に対して作成する MFA の ARN です。
TOTP_SECRET は普段は QR コードで読み込むアレです。MFA の登録時に保存しておいてください。
TOTP コードをセットするオプションもあるので、TOTP の計算には外部ツールを使いたい人も安心です。

$ envchain --set jump AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_REGION SERIAL_NUMBER TOTP_SECRET
# ... input secret values

これで jump という名前で列挙した環境変数が保存できました。
使ってみましょう。

$ envchain jump assume-role -p test-admin aws s3 ls
... S3 のバケット名がリストされる

簡単ですね。

もう一つ便利な機能があって --profile-name (-p) オプションを省略すると skim という crate を使って Fuzzy-Finder が動きます。

$ envchain jump assume-role aws s3 ls

もう一つ便利な使い方としては、スクリプトに組み込んで使うこともできます。例えば、メインの AWS アカウントにある docker image を pull してから、その docker image を使って docker run するときに assume-role で取得した一時的なクレデンシャルをセットするみたいなことができます。

docker-run.sh
#!/bin/bash

image=987654321234.dkr.ecr.ap-northeast-1.amazonaws.com/app/main:latest
docker pull ${image}

eval $(assume-role --format bash)

docker run -it --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}" \
       -e AWS_EXPIRATION=${AWS_EXPIRATION} \
       -e AWS_REGION=ap-northeast-1 \
       --mount "type=bind,src=$PWD,dst=/work" \
       --workdir /work \
       ${image} \
       bash

docker image は ECR にあるやつならなんでもいいですが envchain jumpdocker pull できるようにしておくとよいです。

$ envchain jump ./docker-run.sh

これで docker pull が終わってから eval $(assume-role --format bash) で選択したプロファイルを使って取得したクレデンシャルが環境変数にセットされます。その環境変数を使って docker run を実行します。

まとめ

自分では中身も理解しているから、結構便利に使っています。
お仕事では複数の AWS アカウントや IAM ロールを切り替えて動作確認したり、スクリプト実行したりするので、切り替え先の AWS アカウントや IAM ロールが検索して選択できるのが便利です。

ぼやき

GitHub Actions で Rust で書いたツールを自動的にリリースするベストプラクティスが知りたい。
release-plz というのを使ってみたけど、いくつかの PR をテンポよくマージしていくとなんか変更を取り零してしまうっぽくて困ってます。

脚注
  1. 軽く検索するといっぱい見つかる。なんならクラスメソッドのブログだけで5本くらいある。 ↩︎

  2. https://github.com/okkez/envchain-rs ↩︎

Discussion