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

108

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

сурадж чопаде
источник
2
Как насчет того, чтобы запустить контейнер Docker на своем ноутбуке, который также должен волшебным образом работать в ECS, когда я нажимаю его туда? Думаю, я использую флаг --volume ... должно быть, кто-то уже ответил ...
Randy L

Ответы:

112

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

Учетные данные могут быть получены с 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 на терминале.

Вор
источник
38
Есть ли хороший способ сделать это во время локальной разработки / тестирования, не ставящий под угрозу безопасность в производстве? Я бы хотел убедиться, что образ работает без его полного развертывания.
honktronic
3
альтернатива, которую я опубликовал с переменными среды, отлично работает в среде dev / local.
Vor
5
Интересно, это опечатка, но мне нужно вводить AWS_SECRET_ACCESS_KEY, но в AWS_SECRET_KEYлюбом случае ваш ответ был очень полезен. Спасибо.
Акавалл
14
Проще говоря (для тех, кто пришел к этому ответу так же, как и я); Контейнер докеров, работающий на EC2, унаследует ту же роль, что и экземпляр хоста. (Мне нужен был такой "ELI5", когда команды AWS CLI в моих контейнерах таинственным образом работали, несмотря на то, что им не передавались учетные данные!)
Адам Уэстбрук,
8
Простой способ получить значения ключей из локального профиля для назначения переменной среды в целях разработки (как предлагается на сайте cameroneckelberry.co/words/… ): «aws --profile default configure get aws_access_key_id»
Altair7852
101

С тех пор, как был задан этот вопрос, в 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 или другой оркестровки, вы можете подключить учетные данные как том только для чтения. Для доступа к этим учетным данным требуется тот же доступ, который у вас был бы за пределами докера к тому же файлу учетных данных, поэтому он не лучше и не хуже, чем сценарий без докера. Что наиболее важно, содержимое этого файла не должно быть видимым при проверке контейнера, просмотре журналов или отправке образа на сервер реестра, поскольку в каждом сценарии том находится за его пределами. Это требует, чтобы вы скопировали свои учетные данные на хост-докер отдельно от развертывания контейнера. (Обратите внимание, что любой, у кого есть возможность запускать контейнеры на этом хосте, может просматривать ваши учетные данные, поскольку доступ к API-интерфейсу докеров является корневым на хосте, а root может просматривать файлы любого пользователя. Если вы не доверяете пользователям с root на хосте ,

Для a 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 крепление. Пользователи на хосте за пределами роя не могут монтировать этот секрет непосредственно в свой собственный контейнер, однако с открытым доступом к API-интерфейсу докеров они могут извлечь секрет из работающего контейнера на узле, так что снова ограничьте, кто имеет этот доступ к API. Из compose эта секретная инъекция выглядит так:

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.

BMitch
источник
23

Другой подход - передать ключи с хост-машины в контейнер докера. Вы можете добавить в 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}
Prafi
источник
3
Правильная переменная среды региона - AWS_REGION. См. Stackoverflow.com/questions/44151982/…
John
3
Пожалуйста, проверьте официальный документ, в котором упоминается AWS_DEFAULT_REGION docs.aws.amazon.com/cli/latest/userguide/…
prafi
7
Когда я использовал AWS_DEFAULT_REGION, я получил исключение, что регион по умолчанию не может быть найден. Мой поиск привел к docs.aws.amazon.com/sdk-for-java/v1/developer-guide/…, в котором указана переменная среды AWS_REGION, и это сработало для меня.
John
Если вы используете временные учетные данные, вам также могут понадобитьсяAWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
Давос,
16

Еще один подход - создать временный том только для чтения в docker-compose.yaml. AWS CLI и SDK (например, boto3 или AWS SDK для Java и т. Д.) Ищут 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. Также полезно, если вы хотите локально протестировать докер-контейнер перед его развертыванием на ECS, на котором у вас есть роли IAM, но локально их нет.

Артур Сепетовски
источник
На windows расположен каталог .aw "%UserProfile%\.aws". Итак, я предполагаю, что вам нужно сменить: - ~/.aws/:/root/.aws:roна- %UserProfile%\.aws:/root/.aws:ro
Артур Семеновски
1
Это будет работать только с одиночными процессами сборки, а не с многоступенчатыми.
wlarcheveque
@wlarcheveque Хочешь уточнить?
ErikE
Будьте ОЧЕНЬ осторожны при использовании - host:containerсинтаксиса, если файл / папка не существует на хосте, который он был создан (как root), и awscli не поблагодарит вас за то, что вы загрузили ему файл с нулевым байтом. Вы должны использовать «длинную форму», которая указывает тип привязки, путь к хосту и путь к контейнеру в отдельных строках, это не сработает, если файл не существует, что вы хотите в своем docker-compose.dev. yml, но не в вашем docker-compose.yml (prod / AWS deploy).
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
Манимаран Самутирапанди
источник