Каков наилучший способ передать учетные данные AWS в контейнер Docker?

Я запускаю докер-контейнер на Amazon EC2. В настоящее время я добавил учетные данные AWS в файл Docker. Не могли бы вы сообщить мне лучший способ сделать это?

Ответы

Ответ 1

Лучший способ - использовать роль IAM и вообще не заниматься учетными данными. (см. http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)

http://169.254.169.254..... можно получить из http://169.254.169.254..... Так как это частный IP-адрес, он может быть доступен только из экземпляров EC2.

Все современные клиентские библиотеки AWS "знают", как извлекать, обновлять и использовать учетные данные оттуда. Поэтому в большинстве случаев вам даже не нужно об этом знать. Просто запустите ec2 с правильной ролью IAM, и вам будет хорошо.

В качестве опции вы можете передать их во время выполнения в качестве переменных среды (например, docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage)

Вы можете получить доступ к этим переменным среды, запустив printenv на терминале.

Ответ 2

С тех пор, как был задан этот вопрос, многое изменилось в Docker, поэтому здесь попытка получить обновленный ответ.

Во-первых, особенно с учетными данными AWS для контейнеров, уже работающих в облаке, использование ролей IAM, как Вор предполагает, что - это действительно хороший вариант. Если вы можете сделать это, добавьте еще один плюс один к его ответу и пропустите остальную часть этого.


Как только вы начинаете запускать что-то за пределами облака или приобретаете другой тип секрета, есть два ключевых места, которые я рекомендую против хранения секретов:

  1. Переменные среды: когда они определены в контейнере, каждый процесс внутри контейнера имеет к ним доступ, они видны через /proc, приложения могут выгружать свою среду в стандартный вывод, где она хранится в журналах, и, что наиболее важно, они появляются в текст при проверке контейнера.

  2. На самом изображении: изображения часто отправляются в реестры, где многие пользователи имеют доступ по запросу, иногда без каких-либо учетных данных, необходимых для получения изображения. Даже если вы удалите секрет из одного слоя, изображение можно разобрать с помощью обычных утилит Linux, таких как tar, и секрет можно найти на шаге, где он был впервые добавлен в изображение.


Итак, какие еще есть варианты для секретов в контейнерах Docker?

Вариант A: Если вам нужен этот секрет только во время сборки вашего образа, вы не можете использовать его до начала сборки и пока не имеете доступа к BuildKit, тогда многоэтапная сборка будет лучший из плохих вариантов. Вы добавили бы секрет на начальные этапы сборки, использовали его там, а затем скопировали выходные данные этого этапа без секрета на этап выпуска и передавали только этап выпуска на серверы реестра. Этот секрет все еще находится в кэше изображений на сервере сборки, поэтому я склонен использовать его только в качестве крайней меры.

Вариант B: Также во время сборки, если вы можете использовать BuildKit, выпущенный 18.09, в настоящее время есть экспериментальные функции, позволяющие вводить секреты в качестве монтирования тома для одной линии 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 Mode или другой оркестровки вы можете подключить учетные данные как том только для чтения. Доступ к этим учетным данным требует того же доступа, который вы имеете вне докера, к тому же файлу учетных данных, поэтому он не лучше и не хуже сценария без докера. Самое главное, что содержимое этого файла не должно отображаться при проверке контейнера, просмотре журналов или отправке изображения на сервер реестра, поскольку в каждом сценарии объем находится за пределами этого тома. Для этого необходимо скопировать свои учетные данные на хост докера, отдельно от развертывания контейнера. (Обратите внимание, что любой, кто может запускать контейнеры на этом хосте, может просматривать ваши учетные данные, поскольку доступ к API докера является корневым на хосте, а root может просматривать файлы любого пользователя. Если вы не доверяете пользователям с root на хосте, тогда не давайте им доступ к докеру 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 не могут монтировать этот секрет непосредственно в свой собственный контейнер, однако, с открытым доступом к 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: Существуют и другие инструменты для управления секретами, и моим любимым является Хранилище, поскольку оно дает возможность создавать ограниченные по времени секреты, срок действия которых истекает автоматически. Каждое приложение затем получает свой собственный набор токенов для запроса секретов, и эти токены дают им возможность запрашивать секреты, ограниченные во времени, до тех пор, пока они могут достигнуть сервера хранилища. Это снижает риск, если секрет будет удален из вашей сети, поскольку он либо не будет работать, либо быстро истечет. Функции, специфичные для AWS для Vault, описаны в https://www.vaultproject.io/docs/secrets/aws/index.html

Ответ 3

Другой подход заключается в передаче ключей от хост-машины в док-контейнер. Вы можете добавить следующие строки в файл 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}

Ответ 4

Еще один подход заключается в создании временного тома только для чтения в docker-compose.yaml. AWS CLI и SDK (например, boto3 или AWS SDK для Java и т.д.) ~/.aws/credentials профиль по default в ~/.aws/credentials.

Если вы хотите использовать другие профили, вам нужно также экспортировать переменную AWS_PROFILE перед запуском команды docker-compose

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

В этом примере я использовал пользователя root на докере. Если вы используете другого пользователя, просто измените /root/.aws на домашний каталог пользователя.

:ro - обозначает доступный только для чтения том докера

Это очень полезно, когда у вас есть несколько профилей в ~/.aws/credentials и вы также используете MFA. Также полезно, если вы хотите локально протестировать Docker-контейнер перед его развертыванием в ECS, в котором у вас есть роли IAM, но локально у вас нет.