🚴

MFA付きロールでAWSにアクセスする際にシームレスにローカル開発したい

2024/06/03に公開

背景

メインのサインイン用のポータルのAWSアカウントと各プロジェクトごとにAWSアカウントがあり、assume roleで一時クレデンシャルを取得して、ローカルからAWS上のS3やDynamoDBにアクセスしして、サーバーアプリ等を開発したいケースがあります。

このときに厄介なのは、このクレデンシャルが基本的に短時間で期限切れになることです。ソースコードをウォッチしてファイルが更新されるとサーバーが自動リロードされるような開発環境では、1時間ごとにプロセスを停止してクレデンシャルを再発行し、再度サーバーを起動する手間が発生します。さらにMFA(多要素認証)が必要な場合、ワンタイムパスワードの入力も必要です。

これらの手動操作を一切せずに開発するできるように取り組みました。

一時クレデンシャルの発行

AWS CLI を利用して aws sts assume-role を呼び出すのが原始的な方法ですが、ここに関しては筆者がリリースしているツール swrole が存在します。

https://github.com/tilfin/homebrew-aws/tree/master?tab=readme-ov-file#swrole

swrole 1.1 リリース

今回、このツールをアップデートして、ワンタイムパスワード(OTP)の受付を様々な方法でできるようにしました。バージョン1.0では対話式に入力のみサポートしていましたが、コマンド引数で -t 123456 と指定できるようにしました。さらに ~/.aws/config のスイッチ先プロファイルセクションに generate_token の定義できるようになりました。これにより 1Password 等から自動的に OTP を取得できます。

~/.aws/credentials

[my-company]
aws_access_key_id = XXXXXXXXXX
aws_secret_access_key = XXXXXXXXXX

~/.aws/config

[profile my-company]
region = ap-northeast-1

[profile project-dev]
role_arn = arn:aws:iam::111111111111:role/developer
mfa_serial = arn:aws:iam::000000000000:mfa/member
source_profile = my-company
region = ap-northeast-1
generate_token = op item get "AWS Account" --otp

上記の例では generate_token1Password CLI で「AWS Account」の OTP を取得するコマンドを指定しています。

AWS SDK に Process credential provider を適用する

今回調査していて初めて知った機能だったのですが、~/.aws/configcredential_process という定義を書くと、AWS SDK が実行時に指定されたコマンドを実行し、その結果(標準出力)の JSON をクレデンシャルとして使用します。

https://docs.aws.amazon.com/sdkref/latest/guide/feature-process-credentials.html

この仕様に対応する機能を swrole に組み込めば目的が達成できそうなので、バージョン1.1で -j オプションを指定すると Process credential provider の クレデンシャル JSON を出力する機能も追加しました。

但し、SDKがチェーン式で取得を試行する優先順位が Process credential provider は低いため、上記例の project-dev プロファイルに credential_process を指定しても、うまく動作しません。

そのため、アプリケーション開発用のプロファイルを別途定義します。

~/.aws/config

[profile app-dev]
credential_process = swrole -j project-dev

~/.aws/credentials

[app-dev]
region = ap-northeast-1

なお、他の SDK は未確認ですが、AWS SDK JavaScript v3 では ~/.aws/credentialscredential_process を書いても機能します。

後は下記のようにサービス開発時にこのAWSプロファイルを指定してプロセスを走らせれば、このピタゴラスイッチが動作します。

$ AWS_PROFILE=app-dev pnpm dev

クレデンシャル取得が集中すると同じワンタイムパスワードになり失敗するので、クレデンシャルが期限とともに適切にキャッシュされるようにAWS SDKを使用してください。

補足

この仕組みの動作に関して、AWS SDK JavaScript v3 のクレデンシャルのキャッシュ処理についての問題に直面したため、別の記事で解説しています。

https://zenn.dev/tilfin/articles/56f8dc56b83901

また AWS CLI 自体もこの方法で OTP 入力が不要になります。

Discussion