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.comREFERENCEコンソール認証情報を使用して AWS ローカル開発にログインする - AWS Command Line Interfacedocs.aws.amazon.comREFERENCELogin credentials provider - AWS SDKs and Toolsdocs.aws.amazon.com