MFA付きロールでAWSにアクセスする際にシームレスにローカル開発したい
背景
メインのサインイン用のポータルのAWSアカウントと各プロジェクトごとにAWSアカウントがあり、assume roleで一時クレデンシャルを取得して、ローカルからAWS上のS3やDynamoDBにアクセスしして、サーバーアプリ等を開発したいケースがあります。
このときに厄介なのは、このクレデンシャルが基本的に短時間で期限切れになることです。ソースコードをウォッチしてファイルが更新されるとサーバーが自動リロードされるような開発環境では、1時間ごとにプロセスを停止してクレデンシャルを再発行し、再度サーバーを起動する手間が発生します。さらにMFA(多要素認証)が必要な場合、ワンタイムパスワードの入力も必要です。
これらの手動操作を一切せずに開発するできるように取り組みました。
一時クレデンシャルの発行
AWS CLI を利用して aws sts assume-role
を呼び出すのが原始的な方法ですが、ここに関しては筆者がリリースしているツール 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_token に 1Password CLI で「AWS Account」の OTP を取得するコマンドを指定しています。
AWS SDK に Process credential provider を適用する
今回調査していて初めて知った機能だったのですが、~/.aws/config
に credential_process という定義を書くと、AWS SDK が実行時に指定されたコマンドを実行し、その結果(標準出力)の JSON をクレデンシャルとして使用します。
この仕様に対応する機能を 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/credentials
に credential_process
を書いても機能します。
後は下記のようにサービス開発時にこのAWSプロファイルを指定してプロセスを走らせれば、このピタゴラスイッチが動作します。
$ AWS_PROFILE=app-dev pnpm dev
クレデンシャル取得が集中すると同じワンタイムパスワードになり失敗するので、クレデンシャルが期限とともに適切にキャッシュされるようにAWS SDKを使用してください。
補足
この仕組みの動作に関して、AWS SDK JavaScript v3 のクレデンシャルのキャッシュ処理についての問題に直面したため、別の記事で解説しています。
また AWS CLI 自体もこの方法で OTP 入力が不要になります。
Discussion