Я запускаю докер-контейнер на Amazon EC2. В настоящее время я добавил учетные данные AWS в Dockerfile. Не могли бы вы сообщить мне, как это лучше всего сделать?
Я запускаю докер-контейнер на Amazon EC2. В настоящее время я добавил учетные данные AWS в Dockerfile. Не могли бы вы сообщить мне, как это лучше всего сделать?
Ответы:
Лучший способ - использовать роль 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 на терминале.
AWS_SECRET_ACCESS_KEY
, но в AWS_SECRET_KEY
любом случае ваш ответ был очень полезен. Спасибо.
С тех пор, как был задан этот вопрос, в Docker многое изменилось, так что вот попытка дать обновленный ответ.
Во-первых, особенно с учетными данными AWS для контейнеров, уже работающих внутри облака, использование ролей IAM, как предлагает Вор, является действительно хорошим вариантом. Если вы можете это сделать, добавьте к его ответу еще один плюс один и пропустите все остальное.
Когда вы начинаете запускать что-то вне облака или имеете секреты другого типа, я рекомендую не хранить секреты в двух ключевых местах :
Переменные среды: когда они определены в контейнере, каждый процесс внутри контейнера имеет к ним доступ, они видны через / proc, приложения могут выгружать свою среду в стандартный вывод, где она сохраняется в журналах, и, что наиболее важно, они появляются в чистый текст при осмотре контейнера.
В самом изображении: изображения часто помещаются в реестры, где у многих пользователей есть доступ по запросу, иногда без каких-либо учетных данных, необходимых для получения изображения. Даже если вы удалите секрет с одного уровня, образ можно разобрать с помощью обычных утилит 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.
Другой подход - передать ключи с хост-машины в контейнер докера. Вы можете добавить в 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}
AWS_DEFAULT_REGION
docs.aws.amazon.com/cli/latest/userguide/…
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
Еще один подход - создать временный том только для чтения в 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, но локально их нет.
"%UserProfile%\.aws"
. Итак, я предполагаю, что вам нужно сменить: - ~/.aws/:/root/.aws:ro
на- %UserProfile%\.aws:/root/.aws:ro
- host:container
синтаксиса, если файл / папка не существует на хосте, который он был создан (как root), и awscli не поблагодарит вас за то, что вы загрузили ему файл с нулевым байтом. Вы должны использовать «длинную форму», которая указывает тип привязки, путь к хосту и путь к контейнеру в отдельных строках, это не сработает, если файл не существует, что вы хотите в своем docker-compose.dev. yml, но не в вашем docker-compose.yml (prod / AWS deploy).
Вы можете создать, ~/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