web-dev-qa-db-ja.com

AWS認証情報をDockerコンテナーに渡す最良の方法はどれですか?

Amazon EC2でdocker-containerを実行しています。現在、AWS認証情報をDockerfileに追加しました。これを行う最善の方法を教えてください。

57
suraj chopade

最善の方法は、IAMロールを使用し、資格情報をまったく処理しないことです。 ( http://docs.aws.Amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-Amazon-ec2.html を参照)

資格情報はhttp://169.254.169.254.....から取得できます。これはプライベートIPアドレスであるため、EC2インスタンスからのみアクセスできます。

最新のすべてのAWSクライアントライブラリは、そこから認証情報を取得、更新、使用する方法を「認識」しています。したがって、ほとんどの場合、あなたはそれについて知る必要さえありません。正しいIAMロールでec2を実行するだけで準備完了です。

オプションとして、実行時に環境変数として渡すことができます(つまり、docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage

これらの環境変数にアクセスするには、ターミナルでprintenvを実行します。

67
Vor

この質問が尋ねられてからDockerで多くのことが変わったので、更新された答えを試してみましょう。

まず、具体的には、クラウド内ですでに実行されているコンテナのAWS認証情報を使用して、IAMロールを Vor suggests として使用することは非常に良いオプションです。それができるなら、彼の答えにもう1つプラス1を加えて、残りを飛ばしてください。


クラウドの外部で実行を開始するか、別の種類のシークレットを取得すると、次の2つの重要な場所があります推奨シークレットの保存:

  1. 環境変数:これらがコンテナで定義されている場合、コンテナ内のすべてのプロセスはそれらにアクセスでき、/ procを介して表示され、アプリは環境を標準出力にダンプしてログに保存され、最も重要なことに、コンテナを検査するときはクリアテキスト。

  2. 画像自体:多くのユーザーがプルアクセスを持つレジストリに画像がプッシュされることがよくあります。画像をプルするために必要な資格情報がない場合もあります。 1つのレイヤーからシークレットを削除しても、イメージはtarなどの一般的なLinuxユーティリティで逆アセンブルでき、シークレットは最初にイメージに追加されたステップから見つけることができます。


では、Dockerコンテナのシークレットには他にどのようなオプションがありますか?

オプションA:イメージのビルド中にのみこのシークレットが必要な場合、ビルドの開始前にシークレットを使用できず、BuildKitにまだアクセスできない場合は、 マルチステージbuild は、最良の悪いオプションです。ビルドの初期段階にシークレットを追加し、そこで使用してから、シークレットなしでそのステージの出力をリリースステージにコピーし、そのリリースステージのみをレジストリサーバーにプッシュします。この秘密はまだビルドサーバーのイメージキャッシュにあるため、これは最後の手段としてのみ使用する傾向があります。

オプションB:また、ビルド時に、18.09でリリースされたBuildKitを使用できる場合、現在、 実験的機能 のボリュームマウントとしてシークレットを挿入できるようになっています。単一のRUNライン。そのマウントはイメージレイヤーに書き込まれないため、ビルド中にパブリックレジストリサーバーにプッシュされることを心配せずにシークレットにアクセスできます。結果のDockerfileは次のようになります。

# syntax = docker/dockerfile:experimental
FROM python:3
RUN pip install awscli
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials aws s3 cp s3://... ...

そして、18.09以降のコマンドを使用してビルドします。

DOCKER_BUILDKIT=1 docker build -t your_image --secret id=aws,src=$HOME/.aws/credentials .

オプションC: Swarmモードまたは他のオーケストレーションを使用しない単一ノードでの実行時に、認証情報を読み取り専用ボリュームとしてマウントできます。このクレデンシャルへのアクセスには、同じクレデンシャルファイルへのdockerの外部からのアクセスと同じアクセスが必要なので、dockerのないシナリオよりも良くも悪くもありません。最も重要なことは、ボリュームがすべてのシナリオでボリュームの外側にあるため、コンテナの検査、ログの表示、またはレジストリサーバーへのイメージのプッシュ時に、このファイルの内容が表示されないことです。これには、コンテナーのデプロイとは別に、Dockerホストに資格情報をコピーする必要があります。 (注:Docker APIへのアクセスはホストのルートであり、ルートはすべてのユーザーのファイルを表示できるため、そのホストでコンテナーを実行できるユーザーは資格情報を表示できます。ホストのルートを持つユーザーを信頼しない場合、Docker APIへのアクセスを許可しないでください。)

docker runの場合、これは次のようになります。

docker run -v $HOME/.aws/credentials:/home/app/.aws/credentials:ro your_image

または、作成ファイルの場合、次のようになります。

version: '3'
services:
  app:
    image: your_image
    volumes:
    - $HOME/.aws/credentials:/home/app/.aws/credentials:ro

オプションD: Swarm ModeやKubernetesなどのオーケストレーションツールでは、ボリュームよりも優れたシークレットサポートが用意されています。 Swarmモードでは、ファイルはマネージャーファイルシステムで暗号化されます(ただし、復号化キーもしばしば存在するため、管理者が復号化キーを入力せずにマネージャーを再起動できます)。さらに重要なことは、シークレットはシークレットを必要とするワーカー(そのシークレットでコンテナーを実行する)にのみ送信され、ワー​​カーのメモリにのみ保存され、ディスクではなく、tmpfsを使用してコンテナーとしてファイルとして挿入されますマウント。 swarmの外部のホスト上のユーザーは、そのシークレットを自分のコンテナーに直接マウントすることはできませんが、docker APIへのオープンアクセスでは、ノード上の実行中のコンテナーからシークレットを抽出できます。 API。作成から、この秘密の注入は次のようになります。

version: '3.7'

secrets:
  aws_creds:
    external: true

services:
  app:
    image: your_image
    secrets:
    - source: aws_creds
      target: /home/user/.aws/credentials
      uid: '1000'
      gid: '1000'
      mode: 0700

単一ノードに対してdocker swarm initを使用してスウォームモードをオンにし、指示に従ってノードを追加します。 docker secret create aws_creds $HOME/.aws/credentialsを使用して、外部で秘密を作成できます。そして、docker stack deploy -c docker-compose.yml stack_nameを使用して構成ファイルをデプロイします。

私はしばしば https://github.com/Sudo-bmitch/docker-config-update のスクリプトを使用して秘密をバージョン管理します

オプションE:シークレットを管理する他のツールがありますが、私のお気に入りは Vault です。これは、自動的に期限切れになる時間制限のあるシークレットを作成できるためです。その後、すべてのアプリケーションは独自のトークンセットを取得してシークレットを要求し、それらのトークンを使用すると、ボールトサーバーに到達できる限り、それらの時間制限付きシークレットを要求できます。秘密が機能しないか、すぐに期限切れになるため、ネットワークから秘密が取り出された場合のリスクが軽減されます。 AWSのVault固有の機能は https://www.vaultproject.io/docs/secrets/aws/index.html で文書化されています

21
BMitch

別のアプローチは、ホストマシンからドッカーコンテナにキーを渡すことです。 docker-composeファイルに次の行を追加できます。

services:
  web:
    build: .
    environment:
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
8
prafi

さらに別のアプローチは、docker-compose.yamlに一時的な読み取り専用ボリュームを作成することです。 AWS CLIおよびSDK(Javaなどのboto3またはAWS SDKなど)は、~/.aws/credentialsファイルでdefaultプロファイルを探しています。

他のプロファイルを使用する場合は、docker-composeコマンドを実行する前にAWS_PROFILE変数をエクスポートするだけで済みます。

export AWS_PROFILE=some_other_profile_name

version: '3'

services:
  service-name:
    image: docker-image-name:latest
    environment:
      - AWS_PROFILE=${AWS_PROFILE}
    volumes:
      - ~/.aws/:/root/.aws:ro

この例では、Dockerでrootユーザーを使用しました。他のユーザーを使用している場合は、/root/.awsをユーザーのホームディレクトリに変更するだけです

:ro-読み取り専用ドッカーボリュームの略

~/.aws/credentialsファイルに複数のプロファイルがあり、MFAも使用している場合に非常に役立ちます。 IAMロールがあるECSにデプロイする前にdocker-containerをローカルでテストしたいが、ローカルではない場合にも役立ちます。

4
artusiep