あんパン

こしあん派

AWS CLIでSwitch Roleするパターン

AWSアカウントを組織で管理していると複数アカウント利用するケースは多いかと思う。別のアカウントに切り替えるには、WebコンソールからSwitch Roleすればよい。そして以下のように $HOME/.aws/config$HOME/.aws/credentials を設定すればAWS CLIからもSwitch Roleできる。

$ cat $HOME/.aws/credentials
[main-account]
aws_access_key_id = ACCESS_KEY_ID
aws_secret_access_key = SECRET_ACCESS_KEY

$ cat $HOME/.aws/config
[profile sub-account]
source_profile = main-account
role_arn = ROLE_ARN
mfa_serial = MFA_SERIAL_ARN
region = ap-northeast-1

$ aws s3 ls --profile sub-account
(sub-accountのS3 bucketのリスト)

ただこれだと、 ACCESS_KEY_IDSECRET_ACCESS_KEY を平文で保存することになりやや脆弱なのでenvchainを使いたい。envchainはmacOSのKeychainやLinuxのGNOME Keyring等で暗号化保存したcredentialsを復号して環境変数に設定してくれる。使い方はREADMEの通り。

github.com

envchainを併用する場合 $HOME/.aws/credentials$HOME/.aws/config を以下のように設定すればSwitch Roleできる。

$ cat $HOME/.aws/credentials
(envchainに寄せたのでcredentialsは空)

$ cat $HOME/.aws/config
[profile sub-account]
credential_source=Environment
role_arn = ROLE_ARN
mfa_serial = MFA_SERIAL_ARN
region = ap-northeast-1

$ envchain aws-main-account env
...
AWS_ACCESS_KEY_ID=ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY=SECRET_ACCESS_KEY
AWS_DEFAULT_REGION=ap-northeast-1

$ envchain aws-main-account env aws s3 ls --profile sub-account
(sub-accountのS3 bucketのリスト)

$HOME/.aws/configcredential_source=Environment を足しておかないと Partial credentials found in assume-role, missing: source_profile or credential_source というエラーが出るので注意。また、profileの指定は --profile オプションでのみ可能で、環境変数 AWS_PROFILE で指定することはできない。このあたりはドキュメントにも載っている。

awscli.amazonaws.com

ところでこの方法だと $HOME/.aws/cli/cache/*.json に一時的なcredentialが吐き出されてしまい、envchainを使う意図としてはやや片手落ちな感がある。ではどうするかというと、AssumeRoleのコマンドを手で発行して、返ってきたcredentialを環境変数に設定する。具体的な方法は以下の記事が詳しい。

dev.classmethod.jp

自分の場合は以下のようなラッパーを書いて利用している。

github.com

このように使う:

$ cat $HOME/.aws/config
[profile sub-account]
role_arn = ROLE_ARN
mfa_serial = MFA_SERIAL_ARN
region = ap-northeast-1

$ envchain aws-main-account env aws-switch-role sub-account
Enter MFA code for MFA_SERIAL_ARN:
$ (sub-account) aws s3 ls
(sub-accountのS3 bucketのリスト)

やっていることとしては aws sts assume-role で取得したcredentialを環境変数に設定して $SHELL を新しく立ち上げているだけ。一時的なcredentialはこのプロセス内でのみ有効になるので、平文で保存されるよりは幾らかマシということにしている。(2022-08-12 追記: sudo cat /proc/$PID/environ | sed 's/\x00/\n/g' とかすれば読み取れてしまうので気持ちの問題ではある…)

ところでこの方法だとcredentialを環境変数に設定するのでAWS CLIの利用時にprofileを指定する必要がなくなるが、逆に現在どのprofileに対して操作しているのかが分かりづらくなる。そこで自分は $SHELL を立ち上げるときに本来必要ない環境変数 AWS_PROFILE を一緒に設定してあげて、これが設定されていたらプロンプトの表示を変えている。

$ cat $HOME/.zshrc
...
PROMPT="%{${fg[yellow]}%}%(!.#.$) $([[ -n $AWS_PROFILE ]] && echo "($AWS_PROFILE) ")%{$reset_color%}"
...

立ち上がったシェルを終了すれば元に戻れるので、一時的にセッションを張る使用感になる。


現実的にはひとつめのパターンやふたつめのパターンで十分ということもありそう。社のセキュリティーポリシーや自分のセキュアにしたい気持ちと相談して選択されたい。