Докер и защита паролей
Я недавно экспериментировал с Docker по созданию некоторых сервисов для игры, и одна вещь, которая продолжает меня беспокоить, - это ввод паролей в файл Dockerfile. Я разработчик, поэтому хранение паролей в источнике похоже на удар в лицо. Должно ли это вообще быть проблемой? Существуют ли какие-либо хорошие соглашения о том, как обрабатывать пароли в Dockerfiles?
11 ответов:
безусловно, это вызывает беспокойство. Dockerfiles обычно проверяются в репозиториях и совместно с другими людьми. Альтернативой является предоставление любых учетных данных (имена пользователей, пароли, токены, что-либо чувствительное) переменные среды во время выполнения. Это возможно через
-eаргумент (для отдельных vars на CLI) или--env-fileаргумент (для нескольких переменных в файле) вdocker run.используя
, переменные окружения не особо безопасно, либо. Они видны через--env-fileопределенно более безопасный вариант, так как это защищает от секретов, появляющихся вpsили в журналах, если используетсяset -x.docker inspect, и, следовательно, они доступны для любого пользователя, который может работатьdockerкоманды. (Конечно, любой пользователь, который имеет доступ кdockerна хосте тоже имеет корень в любом случае.)мой предпочтительный шаблон-использовать сценарий обертки в качестве
ENTRYPOINTилиCMD. Сценарий-оболочка может сначала импортировать секреты из внешнего расположения в контейнер во время выполнения, а затем выполнить приложение, предоставляя секреты. Точная механика этого зависит от вашей среды выполнения. В AWS, вы можете использовать комбинацию ролей в IAM, в Служба Управления Ключами, и S3 для хранения зашифрованных секретов в корзине S3. Что-то вроде HashiCorp Хранилище или credstash это еще один вариант.AFAIK нет оптимального шаблона для использования конфиденциальные данные как часть процесса сборки. На самом деле, у меня есть и на эту тему. Вы можете использовать докер-сквош для удаления слоев из изображения. Но для этого в Docker нет собственной функциональности.
вы можете найти shykes комментарии к конфигурации в контейнерах полезное.
наша команда избегает помещать учетные данные в репозитории, так что это означает, что они не допускаются в
Dockerfile. Наша лучшая практика в приложениях-использовать creds из переменных среды.мы решаем для этого с помощью
docker-compose.внутри
docker-compose.yml, вы можете указать файл, содержащий переменные среды для контейнера:env_file: - .envдобавьте
.envдо.gitignore, затем установите учетные данные в.envфайл например:SOME_USERNAME=myUser SOME_PWD_VAR=myPwdсохранить
.envфайл локально или в безопасном месте, где остальная часть команды может захватить его.см.:https://docs.docker.com/compose/environment-variables/#/the-env-file
Docker now (версия 1.13 или 17.06 и выше) поддерживает управление секретной информацией. Вот это обзор и более подробно документация
аналогичная функция существует в kubernetes и DCOS
вы никогда не должны добавлять учетные данные в контейнер, если вы не в порядке вещания creds кому-либо может загрузить изображение. В частности, делать и
ADD credsи позжеRUN rm credsне является безопасным, поскольку файл creds остается в конечном образе на промежуточном уровне файловой системы. Это легко для тех, кто имеет доступ к изображению, чтобы извлечь его.типичное решение, которое я видел, когда вам нужны creds для проверки зависимостей, и это использовать один контейнер для создания другого. Т. е., как правило, у вас есть некоторая среда сборки в базовом контейнере, и вам нужно вызвать ее для создания контейнера приложения. Таким образом, простое решение состоит в том, чтобы добавить свой источник приложения, а затем
RUNкоманды строить. Это небезопасно, если вам нужно удостоверение в том, чтоRUN. Вместо этого вы помещаете свой источник в локальный каталог, запускаете (как вdocker run) контейнер для выполнения шага сборки с локальным исходным каталогом, смонтированным как Том, а creds либо вводится, либо монтируется как другой том. После завершения этапа сборки вы создаете свой последний контейнер простоADDing локальный исходный каталог, который теперь содержит встроенные артефакты.Я надеюсь, что докер добавляет некоторые функции, чтобы упростить все это!
Update: похоже, что метод, идущий вперед, будет иметь вложенные сборки. Короче говоря, dockerfile описывает первый контейнер, который используется для создания среды выполнения, а затем вторую вложенную сборку контейнера, которая может собрать все части в последний контейнер. Таким образом, время сборки не находится во втором контейнере. Это приложение Java, где вам нужен JDK для создания приложения, но только JRE для его запуска. Есть ряд предложений, которые обсуждаются, лучше всего начать с https://github.com/docker/docker/issues/7115 и перейдите по некоторым ссылкам для альтернативных предложений.
С настройки В1.9 можно использовать ARG инструкция чтобы извлечь аргументы, переданные командной строкой в изображение на создать действие. Просто используйте -- build-arg флаг. Таким образом, вы можете избежать сохранения явного пароля (или другой разумной информации) на Dockerfile и передавать их на лету.
источник:https://docs.docker.com/engine/reference/commandline/build/ http://docs.docker.com/engine/reference/builder/#arg
пример:
Dockerfile
FROM busybox ARG user RUN echo "user is $user"команды построения изображения
docker build --build-arg user=capuccino -t test_arguments -f path/to/dockerfile .во время сборки он печатает
$ docker build --build-arg user=capuccino -t test_arguments -f ./test_args.Dockerfile . Sending build context to Docker daemon 2.048 kB Step 1 : FROM busybox ---> c51f86c28340 Step 2 : ARG user ---> Running in 43a4aa0e421d ---> f0359070fc8f Removing intermediate container 43a4aa0e421d Step 3 : RUN echo "user is $user" ---> Running in 4360fb10d46a **user is capuccino** ---> 1408147c1cb9 Removing intermediate container 4360fb10d46a Successfully built 1408147c1cb9надеюсь, что это помогает! Пока.
в качестве альтернативы использованию переменных среды, которые могут стать грязными, если у вас их много, следует использовать тома, чтобы сделать каталог на хосте доступным в контейнере.
Если вы поместите все свои учетные данные в виде файлов в эту папку, то контейнер может читать файлы и использовать их по своему усмотрению.
например:
$ echo "secret" > /root/configs/password.txt $ docker run -v /root/configs:/cfg ... In the Docker container: # echo Password is `cat /cfg/password.txt` Password is secretмногие программы могут читать свои учетные данные из отдельного файла, так таким образом, вы можете просто указать программе на одном из папка.
мой подход, кажется, работает, но, наверное, наивно. Скажи мне, почему это неправильно.
параметры установить при сборке настройки выставлены по истории подкоманды, поэтому не пойду туда. Однако при запуске контейнера переменные среды, заданные в команде run, доступны контейнеру, но не являются частью образа.
Итак, в файле Dockerfile выполните настройку, которая не включает секретные данные. Установите CMD чего-то вроде
/root/finish.sh. В команде запуска, использования окружающей среды переменные для отправки секретных данных в контейнер.finish.shиспользует переменные по существу для завершения задач сборки.чтобы упростить управление секретными данными, поместите их в файл, который загружается docker run с помощью
--env-fileпереключатель. Конечно, держите файл в секрете..gitignoreи так далее.для меня
finish.shзапускает программу Python. Он проверяет, чтобы убедиться, что он не работал раньше, а затем завершает установку (например, копирует имя базы данных в Django'ssettings.py).
хотя я полностью согласен, что нет простого решения. По-прежнему существует одна точка отказа. Либо dockerfile, etcd и так далее. Apcera имеет план, который выглядит как sidekick-двойная аутентификация. Другими словами, два контейнера не могут разговаривать, если нет правила конфигурации Apcera. В их демо uid / pwd был в чистом виде и не мог быть повторно использован, пока администратор не настроил связь. Для этого, однако, это, вероятно, означало исправление Docker или, по крайней мере, сети плагин (если есть такая вещь).
существует новая команда docker [1] для управления" секретами", но это работает только для кластеров Роя.
docker service create --name my-iis --publish target=8000,port=8000 --secret src=homepage,target="\inetpub\wwwroot\index.html" microsoft/iis:nanoserver
решение только во время выполнения
docker-compose также предоставляет решение без Роя (начиная с версии 1.1: секреты с помощью привязки монтирует).
секреты монтируются в виде файлов ниже
/run/secrets/по docker-compose. Это решает проблему во время выполнения (запуск контейнера), но не во время сборки (создание образа), потому что/run/secrets/не монтируется во время сборки. Кроме того, это поведение зависит от запуска контейнера с помощью докер-сочинять.
пример:
Dockerfile
FROM alpine RUN cat /run/secrets/password CMD sleep inifinitydocker-compose.в формате YML
version: '3.1' services: app: build: . secrets: - password secrets: password: file: password.txtпостроить, выполнить:
docker-compose up -dчитайте далее:
The 12-факторная методология приложения говорит, что любая конфигурация должна храниться в переменных окружения.
Docker compose может сделать подстановка переменных в конфигурации, так что может быть использован для передачи паролей от хоста к докеру.
Comments