はじめに
docker run コマンドで実行するDockerコンテナ内でAWSのAPI呼び出しを行うとき、何もしないと認証情報がなくて失敗すると思う。なんとかしてホスト側の認証情報を伝えたい。なお、令和なのでアクセスキーはホストのどこにも (~/.aws/credentials ファイルにも) 永続化されておらず、一時的な認証情報 (SSOやAssumeRole) しかないものとする。
やりかた
結論から言うと、aws configure export-credentials コマンドを使って認証情報をアクセスキー・シークレットキーの形式で取得できるので、これが使える。ホスト側でアクセスキーを使っていない限りは永続性のない (有効期限のある) 認証情報として取り回せる。
aws configure export-credentials のようにフォーマットを指定してあげることで、以下のような形式で環境変数の定義が取得できる。実用上は AWS_ACCESS_KEY_ID と AWS_SECRET_ACCESS_KEY があればよくて、残り2つの環境変数は要らない気がするけど、今のところ実害を確認できていないので放置してる。
export AWS_ACCESS_KEY_ID=xxxxxxx export AWS_SECRET_ACCESS_KEY=yyyyyyy export AWS_SESSION_TOKEN=zzzzzzz export AWS_CREDENTIAL_EXPIRATION=YYYY-MM-DDThh:mm:ssZ
--format env-no-export 引数を指定すると、環境変数を export しない文字列が出てくる。
AWS_ACCESS_KEY_ID=xxxxxxx AWS_SECRET_ACCESS_KEY=yyyyyyy AWS_SESSION_TOKEN=zzzzzzz AWS_CREDENTIAL_EXPIRATION=YYYY-MM-DDThh:mm:ssZ
あとはこの環境変数をなんとかして docker run コマンドで使える形に整形する。docker run コマンドでコンテナに環境変数を渡すには -e オプションを使う必要があるので、ひと工夫したらよい。以下はamazon/aws-cliイメージを使う例。サブシェル内で認証情報を環境変数としてexportしつつコマンドを実行している。リージョンだけ個別に渡してあげる必要があるので注意。
% ( eval $(aws configure export-credentials --format env); docker run --rm -e AWS_REGION=ap-northeast-1 -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN amazon/aws-cli sts get-caller-identity )
あるいは、bashやzshを使っているのであれば --env-file オプションと匿名パイプを組み合わせるともっとシンプルに書ける。<(cmd) のように書くことでコマンドの実行結果をファイルディスクリプタ経由で取得できる。少なくともMac zsh + Rancher Desktopではこれで動作した。
% docker run --rm -e AWS_REGION=ap-northeast-1 --env-file=<(aws configure export-credentials --format env-no-export) amazon/aws-cli sts get-caller-identity
追記
もともとは aws --profile configure export-credentials コマンドの実行結果をワンライナーで加工して -e AWS_ACCESS_KEY_ID=xxxxx -e AWS_SECRET_ACCESS_KEY=yyyyyyy のようなコマンドライン引数を組み立てる方法を紹介していましたが、これだとコマンドライン引数から認証情報の中身が見えてしまう問題があるため、修正しました。
まとめ
aws configure export-credentials コマンドを活用することで、ホストのAWS CLIの認証情報を環境変数経由でコンテナに伝えることができて便利。