お世話になってたディレクトリ移動だけでAWSのクレデンシャルを切り替える仕組みがM1 Macで動かなかったので替わりのスクリプトを書いた

2022.01.26

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

私がこのDevelopers IOでも屈指の良エントリだと思っているのが、以下の佐伯さんのエントリです。

ディレクトリ移動をするだけでAWSのクレデンシャルを切り替えてくれるので、複数のAWSアカウントに対してCLIベース(私はTerraformを使うことが多い)で作業をするような方にはとてもおすすめです。一度お試しください。

M1 Macでは動かなかった

最近開発環境をM1 Macに変えました。するとこの仕組みが動作しませんでした。

環境情報

  • MacBook Pro (13-inch, M1, 2020)
  • チップ: Apple M1
  • OS: MacOS Big Sur (バージョン11.6.2)

原因

上記仕組みはdirenvとassume-roleという2つのツールを組み合わせて実現されているのですが、assume-roleがM1に対応していないようです。

% assume-role
zsh: segmentation fault  assume-role

替わりのスクリプトを書いた

方針

この仕組みを諦めるのにはあまりにも便利なので、代替案を考えました。前述の仕組みの概要はざっくりと以下の様になっています。

  1. direnvで所定のディレクトリに移動すると予め設定したスクリプトが実行される
  2. 上記スクリプトの中でassume-roleを、カレントディレクトリを引数にして実行
  3. クレデンシャル取得できる(認証完了)

なので、2.でassume-roleを実行しているスクリプトの部分を、assume-roleコマンドを使わず実現できればよいわけです。

詳細

最終的に.envrcの中身を以下にすることで実現できました。

.envrc

eval target_profile=$(basename $(pwd))
echo target profile is $target_profile
read -p "MFA Code: " mfa_code
AWS_STS_CREDENTIALS=`aws sts assume-role --profile default --role-arn $(aws configure get ${target_profile}.role_arn) --role-session-name ${target_profile}-session --serial-number $(aws configure get ${target_profile}.mfa_serial) --token-code $mfa_code`;export AWS_ACCESS_KEY_ID=`echo "${AWS_STS_CREDENTIALS}" | jq -r '.Credentials.AccessKeyId'`;export AWS_SECRET_ACCESS_KEY=`echo "${AWS_STS_CREDENTIALS}" | jq -r '.Credentials.SecretAccessKey'`;export AWS_SESSION_TOKEN=`echo "${AWS_STS_CREDENTIALS}" | jq -r '.Credentials.SessionToken'`

1-2行目 ターゲットプロファイル名の取得

この仕組みでは、カレントディレクトリ名 = プロファイル名となります。そのカレントディレクトリ名を取得して変数に格納します。

3行目 MFAコード入力

私はMFA必須のポリシーを持っているユーザーからしかスイッチしないので、標準入力からMFAコードを取得します。

4行目

aws sts assume-roleコマンドで取得した一時クレデンシャルの情報を環境変数にセットします。この部分は以下の若槻さんのエントリを参考(丸々拝借)しています。若槻さんありがとうございます!

使用例

使い勝手としては従来のassume-roleを使っている場合と同じです。

クレデンシャルファイルにassume role元のユーザーとassume role先のロールを設定します。

~/.aws/credentials

[default]
aws_access_key_id=xxxxxxxxxxxxxxxxxxxx
aws_secret_access_key=yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

~/.aws/config

[profile kazue-sandboxes]
source_profile=default
role_arn=arn:aws:iam::012345678901:role/kazue
mfa_serial=arn:aws:iam::111111111111:mfa/kazue

次にassume role先プロファイル名と同じ名前のディレクトリを作成し、そこに前述の.envrcを置きます。そして作ったディレクトリに移動します。

% cd ~/project/kazue-sandboxes/      
direnv: error /Users/kazue.masaki/project/kazue-sandboxes/.envrc is blocked. Run `direnv allow` to approve its content

初回はdirenv allowというコマンドを実行する必要があります。2回目からは不要です。 direnv allowを打つと(2回目からはディレクトリ移動するだけで)MFA Codeを訊かれます。入力すると環境変数がセットされ、認証完了です。

 % direnv allow
direnv: loading ~/project/kazue-sandboxes/.envrc                                                                                                                                                                       
target profile is kazue-sandboxes
MFA Code: 323006
direnv: export +AWS_ACCESS_KEY_ID +AWS_SECRET_ACCESS_KEY +AWS_SESSION_TOKEN 
% aws sts get-caller-identity 
{
    "UserId": "AAAAAAAAAAAAAAAAAAAAA:kazue-sandboxes-session",
    "Account": "012345678901",
    "Arn": "arn:aws:sts::012345678901:assumed-role/kazue/kazue-sandboxes-session"
}