ENGINEERING ARTICLE
aws loginの認証情報をDockerコンテナへ引き継ぐ方法
この記事は約7分で読めます
こんにちは、 @Manabu です。
DockerコンテナからAWSへデプロイするために、アクセスキーを環境変数や.envへ設定している方もいるのではないでしょうか。
私もこれまで、コンテナ内でAWS CLIを使うために、IAMユーザーのアクセスキーを渡していました。
ただ、長期間有効なアクセスキーをローカルPCとDockerコンテナの両方で扱うことに不安があり、アクセスキーを使わない方法へ変更しました。
今回は、ホストPCでaws loginを実行し、その一時的な認証情報をDockerコンテナへ引き継いでAWS CLIを実行する方法を紹介します。
この記事は、以下のような方におすすめです。
こんな方におすすめ
- DockerコンテナからAWS CLIを実行したい
- アクセスキーを環境変数や
.envへ保存したくない - aws loginの認証情報をコンテナでも利用したい
aws login自体の使い方は、以下の記事で紹介しています。
REFERENCEAWS CLIのaws loginを使ってアクセスキーなしでログインする方法IT自習室↗実装する構成
今回の構成は以下です。
ホストPC
├─ aws loginを実行
├─ ~/.aws/config
└─ ~/.aws/login/cache
↓ Volume Mount
Dockerコンテナ
└─ AWS CLIで一時認証情報を使用
aws loginを実行すると、プロファイルの設定が~/.aws/configへ保存され、一時認証情報と更新用の情報が~/.aws/login/cacheへ保存されます。
この2つをコンテナ内のAWS CLIから参照できるようにします。
アクセスキーを環境変数で渡す方法との違い
アクセスキーをコンテナへ渡す場合、次のような環境変数を使う方法があります。
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
設定は簡単ですが、長期間有効な認証情報が.env、シェル履歴、Compose設定、CIの変数などへ残る可能性があります。
aws loginを使う場合は、アクセスキーを自分で発行してコンテナへ渡す必要がありません。
ただし、コンテナへマウントしたキャッシュも認証情報です。マウント中のコンテナからは、ログインしたIAMユーザーやロールの権限でAWSを操作できます。
注意
信頼できないイメージやアプリケーションへ、AWSの設定とログインキャッシュをマウントしないでください。
事前準備
以下が必要です。
- Docker
- Docker Compose
- AWS CLIバージョン2.32.0以降
aws loginを利用できるIAMユーザーまたはIAMロールSignInLocalDevelopmentAccessポリシー
コンテナ内のAWS CLIも、aws loginの認証情報に対応したバージョンが必要です。
ホストPCでaws loginを実行する
最初に、ホストPCで名前付きプロファイルを使ってログインします。
aws login --profile docker-dev
ブラウザで認証を完了したら、ホストPCで認証先を確認します。
aws sts get-caller-identity --profile docker-dev
ここでエラーになる場合は、Docker側の設定を始める前にaws loginの設定を確認してください。
Docker Composeを用意する
次のcompose.yamlを作成します。
services:
aws-cli:
image: public.ecr.aws/aws-cli/aws-cli:latest
environment:
AWS_PROFILE: ${AWS_PROFILE:-docker-dev}
AWS_REGION: ${AWS_REGION:-ap-northeast-1}
AWS_DEFAULT_REGION: ${AWS_REGION:-ap-northeast-1}
AWS_PAGER: ""
volumes:
- ${HOME}/.aws/config:/root/.aws/config:ro
- ${HOME}/.aws/login/cache:/root/.aws/login/cache
command:
- sts
- get-caller-identity
設定ファイルは読み取り専用の:roでマウントします。
ログインキャッシュは、AWS CLIが一時認証情報を自動更新できるように、読み書き可能な状態でマウントします。
補足
AWS CLIは一時認証情報を必要に応じて更新します。login cacheを読み取り専用にすると、最初は動作しても、更新が必要になった時に失敗する可能性があります。
コンテナ内で認証情報を確認する
次のコマンドを実行します。
AWS_PROFILE=docker-dev docker compose run --rm aws-cli
正常に引き継がれていれば、次のような結果が表示されます。
{
"UserId": "EXAMPLEUSERID",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/example-role/example-session"
}
ホスト側で実行したget-caller-identityと、AccountやArnが同じことを確認してください。
別のAWS CLIコマンドを実行する
Composeのrunでコマンドを指定すると、commandを上書きできます。
S3バケットを確認する場合は以下です。
AWS_PROFILE=docker-dev docker compose run --rm aws-cli s3 ls
CloudFormationのスタックを確認する場合は以下です。
AWS_PROFILE=docker-dev docker compose run --rm aws-cli \
cloudformation list-stacks \
--stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE
ログインしたIAMユーザーやロールに権限がなければ、AccessDeniedになります。aws loginを使っても、IAMの権限が追加されるわけではありません。
自作コンテナで利用する場合
公式AWS CLIイメージ以外でも、AWS CLIバージョン2.32.0以降がインストールされていれば、同じ考え方で利用できます。
コンテナがrootユーザーで動作する場合は、次へマウントします。
/root/.aws/config
/root/.aws/login/cache
appユーザーなどroot以外で動作する場合は、そのユーザーのホームディレクトリへマウントします。
/home/app/.aws/config
/home/app/.aws/login/cache
また、コンテナ内のHOMEとファイルの所有者・権限も確認してください。
AWS SDKから使用する場合
AWS CLIだけでなく、対応しているAWS SDKもlogin_sessionとログインキャッシュを利用できます。
ただし、SDKとバージョンによって対応状況が異なります。利用しているSDKがlogin credentials providerに対応しているか、AWS公式ドキュメントで確認してください。
対応していないツールでは、AWS CLIのcredential_processを使う方法があります。
[profile docker-process]
credential_process = aws configure export-credentials --profile docker-dev --format process
region = ap-northeast-1
この方法では、コンテナ内に対応バージョンのAWS CLIが必要です。
マウント範囲を小さくする
AWS公式ドキュメントでは、ホストの~/.aws全体をコンテナの/root/.awsへマウントする方法が紹介されています。
docker run --rm -it \
-v ~/.aws:/root/.aws \
public.ecr.aws/aws-cli/aws-cli \
sts get-caller-identity
この方法でも動作しますが、~/.aws/credentialsに長期アクセスキーが残っていると、それもコンテナから参照できる状態になります。
aws loginだけを利用する場合は、configとlogin/cacheだけを個別にマウントする方が、コンテナへ共有する範囲を小さくできます。
コンテナイメージへ認証情報をコピーしない
次のように、DockerfileのCOPYでAWS設定をイメージへ含めてはいけません。
# 使用しない
COPY .aws /root/.aws
イメージのレイヤーに認証情報が残り、レジストリへPushした時に外部へ流出する可能性があります。
AWS設定は実行時のVolume Mountで渡し、イメージには含めないようにします。
ローカル開発以外では別の認証方法を使う
今回の方法は、ローカルPC上のDockerコンテナで開発や手動デプロイを行う場合を想定しています。
次の環境では、実行環境に合ったIAMロールを使う方が適切です。
- ECS:タスクロール
- EC2:インスタンスプロファイル
- EKS:Pod向けのIAMロール
- GitHub ActionsなどのCI/CD:OIDC連携とIAMロール
サーバーやCIへaws loginのキャッシュをコピーして運用する方法はおすすめしません。
作業終了後にログアウトする
作業終了後は、ホストPCでログアウトします。
aws logout --profile docker-dev
コンテナは--rmを付けて実行しているため、コマンド終了後に削除されます。
ログインキャッシュはホストと共有しているため、ログアウトするとコンテナからも認証情報を利用できなくなります。
まとめ
今回は、ホストPCで取得したaws loginの認証情報を、Dockerコンテナへ引き継ぐ方法を紹介しました。
~/.aws/configと~/.aws/login/cacheをマウントすることで、長期アクセスキーを環境変数へ設定せずに、コンテナ内からAWS CLIを実行できます。
ただし、ログインキャッシュも認証情報であり、マウントしたコンテナはAWS環境へアクセスできます。信頼できるコンテナだけに共有し、最小権限と短時間の利用を心がけましょう。
参考資料
REFERENCEAWS CLI に対して公式の Amazon ECR Public イメージまたは Docker イメージを実行する - AWS Command Line Interfacedocs.aws.amazon.com↗
REFERENCEコンソール認証情報を使用して AWS ローカル開発にログインする - AWS Command Line Interfacedocs.aws.amazon.com↗
REFERENCELogin credentials provider - AWS SDKs and Toolsdocs.aws.amazon.com↗