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


102

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


2
ラップトップでDockerコンテナーを実行している場合、ECSでプッシュすると魔法のように動作すると思われますか?私は--volumeフラグを使用するつもりです...誰かがすでに答えているに違いありません...
Randy L

回答:


105

最善の方法は、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を実行すると、これらの環境変数にアクセスできます。


35
本番環境のセキュリティを損なうことなくローカルでの開発/テスト中にこれを行う良い方法はありますか?イメージを完全に展開しなくても機能することを確認したいです。
honktronic 2016年

3
環境変数を使用して投稿した代替案は、dev / local環境で正常に機能します。
Vor

5
これはタイプミスですか?と入力しなければなりAWS_SECRET_ACCESS_KEYませんがAWS_SECRET_KEY、とにかくあなたの答えはとても役に立ちました。ありがとうございました。
Akavall 2017

14
簡単に言えば(私が行ったのと同じ方法でこの答えにたどり着く人のために)。EC2で実行されるDockerコンテナーは、ホストインスタンスと同じ役割を継承します。(コンテナーにAWS CLIコマンドが渡されたにもかかわらず、クレデンシャルが渡されなかったにもかかわらず、不可解に機能した場合、このような「ELI5」が必要でした!)
Adam Westbrook

8
ローカルのプロファイルからキー値を取得して、開発目的で環境変数に割り当てる簡単な方法(cameroneckelberry.co/words/…推奨): "aws --profile default configure get aws_access_key_id"
Altair7852

89

この質問が行われてからDockerで多くの変更が行われたので、ここで更新された回答の試みを示します。

まず、具体的にはクラウド内で既に実行されているコンテナーのAWS認証情報で、Vorが示唆するように IAMロールを使用することは本当に良いオプションです。それができる場合は、彼の回答に1プラス1を追加し、残りの部分はスキップしてください。


クラウドの外で実行を開始したり、シークレットの種類が異なる場合、シークレット保存しないことをお勧めする2つの重要な場所があります。

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

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


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

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

オプション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へのアクセスはホストのrootであり、rootは任意のユーザーのファイルを表示できるため、そのホストでコンテナーを実行する権限を持つ誰でも資格情報を表示できます。ホストにrootを持つユーザーを信頼しない場合、

の場合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です。次に、すべてのアプリケーションが独自のトークンセットを取得してシークレットを要求します。これらのトークンは、Vaultサーバーにアクセスできる限り、これらのトークンに時間制限のあるシークレットを要求する機能を提供します。これは、シークレットが機能しないか、すぐに期限切れになるため、シークレットがネットワークから削除された場合のリスクを軽減します。Vault for AWSに固有の機能は、https://www.vaultproject.io/docs/secrets/aws/index.htmlに記載されています。


20

別のアプローチは、ホストマシンからDockerコンテナーにキーを渡すことです。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}

3
正しいリージョン環境変数はAWS_REGIONです。stackoverflow.com/questions/44151982/…を
John Camerin


7
AWS_DEFAULT_REGIONを使用すると、デフォルトのリージョンが見つからないという例外が発生しました。私の検索は、AWS_REGION環境変数を指定するdocs.aws.amazon.com/sdk-for-java/v1/developer-guide/…につながり、それは私のために働いた。
John Camerin

一時的な認証情報を使用している場合は、次の情報も必要になる可能性がありますAWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
ダボス

12

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

他のプロファイルを使用したい場合は、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 -読み取り専用のDockerボリュームを表します

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


Windowsでは.aws`カタログがあり"%UserProfile%\.aws"ます。だから私はあなたが変更する必要があると思います: - ~/.aws/:/root/.aws:ro- %UserProfile%\.aws:/root/.aws:ro
Artur Siepietowski

1
これは、単一のビルドプロセスでのみ機能し、マルチステージでは機能しません。
wlarcheveque

@wlarcheveque詳しく説明しますか?
ErikE

- host:container(ルートとして)作成されたホストにファイル/フォルダーが存在せず、awscliが0バイトのファイルをフィードしてくれない場合は、構文の使用には十分注意してください。タイプがバインド、ホストパス、およびコンテナーパスを別々の行で指定する「長い形式」を使用する必要があります。これは、ファイルが存在しない場合に失敗します。これはdocker-compose.devに必要です。 ymlがdocker-compose.ymlにない(prod / AWSデプロイ)。
dragon788

0

あなたは~/aws_env_creds包含を作成することができます

touch ~/aws_env_creds
chmod 777 ~/aws_env_creds
vi ~/aws_env_creds

以下の値を追加します(自分のキーを置き換えます)

AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY
AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2C

「esc」でファイルを保存します。

コンテナーを実行してテストする

 my_service:
      build: .
      image: my_image
      env_file:
        - ~/aws_env_creds
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.