Докер і захист паролів


162

Нещодавно я експериментував з Docker над створенням деяких сервісів, з якими можна пограти, і одна річ, яка мене постійно нудить, - це введення паролів у Dockerfile. Я розробник, тому зберігання паролів у джерелі відчуває себе ударом у обличчя. Чи це навіть повинно викликати занепокоєння? Чи є добрі умови щодо обробки паролів у Dockerfiles?


7
У Github є відкрите питання, яке вимагає кращих практик щодо Докера та секретів, питання тут: github.com/docker/docker/isissue/13490
Luís Bianchin

Відповіді:


92

Однозначно це турбота. Докерфайли зазвичай реєструються у сховищах та діляться з іншими людьми. Альтернативою є надання будь-яких облікових даних (імен користувачів, паролів, маркерів, нічого чутливого) як змінних середовища під час виконання . Це можливо через -eаргумент (для окремих vars на CLI) або --env-fileаргумент (для декількох змінних у файлі) до docker run. Прочитайте це для використання навколишнього середовища з докер-композитом.

Використання --env-file, безумовно, більш безпечний варіант, оскільки це захищає від секретів, які відображаються psв журналах або в журналах, якщо вони використовуються set -x.

Однак екологія також не є особливо захищеною. Вони видно через docker inspect, а значить, вони доступні будь-якому користувачеві, який може виконувати dockerкоманди. (Зрозуміло, будь-який користувач, який має доступ до dockerхоста , все одно має корінь .)

Мій кращий зразок - використовувати сценарій обгортки як ENTRYPOINTабо CMD. Сценарій обгортки може спочатку імпортувати секрети із зовнішнього місця в контейнер під час виконання, а потім виконати програму, надавши секрети. Точна механіка цього варіюється залежно від вашого середовища роботи. У AWS ви можете використовувати комбінацію ролей IAM, служби керування ключами та S3 для зберігання зашифрованих секретів у відрі S3. Щось на зразок HashiCorp Vault або confstash - це інший варіант.

AFAIK не існує оптимальної схеми для використання конфіденційних даних як частини процесу збирання. Насправді у мене є питання на цю тему. Ви можете використовувати docker-сквош для видалення шарів із зображення. Але в Docker для цієї мети немає нативного функціоналу.

Ви можете виявити корисні коментарі shykes щодо конфігурації в контейнерах .


Як зазначається в інших коментарях, .configфайл містить 2 шари (після ADD та після першого RUN) .
Петро Гладких

1
Так, найкращі шляхи представляються змінними env. Я розглядав це в контексті розробки Dockerfile TDDing.
gnoll110

5
Мене хвилює те, що якщо ваш пароль є змінною env, він відображається в docker inspect.
струнка

Установка docker за замовчуванням (на Linux) вимагає запуску привілеїв sudoer docker inspect. Якщо зловмисник вже може судогу, вилучення вашого пароля з докерської перевірки, ймовірно, у вашому списку речей, які зараз можуть піти не так. Ця деталь видається для мене прийнятною загрозою.
GrandOpener

7
@GrandOpener Це стосується лише ситуації, коли зловмисник використовує вашу систему. Якщо я натискаю зображення докера до сховища, і його витягує хтось інший, мені байдуже, чи мають вони судо у власній системі, але я, безумовно, байдуже, чи бачать вони секрети у env, які вже не мають бути там.
vee_ess

74

Наша команда уникає розміщення облікових даних у сховищах, тож це означає, що їх заборонено Dockerfile. Наша найкраща практика в рамках програм - використовувати кредити від змінних середовища.

Для цього ми вирішуємо, використовуючи 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


15
Ви також можете зробити це без файлу .env, якщо бажаєте. Просто використовуйте властивість оточення у файлі docker-compose.yml. "Змінні середовища, що мають лише ключ, вирішують їх значення на машині. Compose працює, що може бути корисною для секретних або специфічних для хоста значень."
Д. Віссер

1
дай цій людині печиво! :) так, це дійсно хороша практика. Я просто хочу додати, що docs.docker.com/compose/env-file це має працювати автоматично, але у версії 2 docker складатиметься, мабуть, вам потрібно оголосити це так, як описано в цій відповіді.
еквівалент8

5
Використання змінних середовищ відмовляє сама команда Docker, оскільки env var можна побачити через / proc / <pid> / Environment та докер перевірити. Це лише прикриває спосіб отримання облікових даних для зловмисника, який отримав кореневий доступ. Звичайно, облікові дані ніколи не повинні відслідковуватися CVS. Я думаю, що єдиний спосіб запобігти користувачеві root отримати кредит - це прочитати облікові дані з веб-додатку (сподіваючись, що він не оновлює файл proc Environment) із зашифрованого файлу, процес дешифрування надійно запитує пароль. Я думаю, що я спробую з гробницею: github.com/dyne/Tomb
pawamoy

.gitignoreщоб .envфайл із конфіденційною інформацією не потрапив до GitHub. Я впевнений , що це не буде працювати , якщо ви додасте його.dockerignore
theUtherSide

привіт @theUtherSide, дякую за вашу відповідь, у мене виникло питання, коли я не перевіряю .envфайл, і я виконую розгортання на сервері за умови, чи пропонуєте ви створити .envфайл знову на сервері вручну?
opensource-developer

37

Докер зараз (версія 1.13 або 17.06 і новіші) має підтримку управління секретною інформацією. Ось огляд та більш детальна документація

Аналогічна особливість існує в кубернетах та DCOS


Деякі корисні команди із наведених вище посилань:: docker secret createстворити секрет docker secret inspect: відобразити детальну інформацію про секрет docker secret ls: переглянути всі секрети docker secret rm: видалити специфічний секретний --secretпрапор для docker service create: створити секрет під час створення служби --secret-addта --secret-rmпрапори для docker service update: оновити значення секрету або видалити секрет під час завдання оновлення послуги. Секрети докера захищені у спокої на вузлах менеджера та надаються робочим вузлам під час запуску контейнера.
PJ

7
Так, вам потрібно створити рій, щоб використовувати секрети Докера
Heather QC

11
Це є гарним початком відповіді, але потребує набагато більше інформації від тієї, яка пов'язана, щоб з’явитись у самій відповіді.
Джефф Ламбер

7
Не впевнений, що це може бути прийнятою відповіддю, якщо вона працює лише з роями. Багато людей не використовують рої, але все одно потрібно передавати секрети.
Іоанн Y

9

Ніколи не слід додавати облікові дані в контейнер, якщо ви не вповноважите трансляцію кредитів тому, хто може завантажити зображення. Зокрема, виконувати і ADD credsпізніше RUN rm credsне є безпечним, оскільки файл кредитів залишається в кінцевому зображенні в проміжному шарі файлової системи. Кожен, хто має доступ до зображення, легко отримати його.

Типове рішення, яке я бачив, коли вам потрібні записи для перевірки залежностей, і таке використання одного контейнера для створення іншого. Тобто, як правило, у вашому базовому контейнері є деяке середовище збирання, і вам потрібно застосувати це, щоб створити контейнер додатка. Таким простим рішенням є додавання джерела програми, а потім RUNкоманди побудови. Це небезпечно, якщо вам потрібні кредити RUN. Замість того, що ви робите, - це помістити джерело в локальний каталог, запустіть (як і в docker run) контейнер, щоб виконати етап збирання з локальним каталогом джерела, встановленим як об'єм, а кредити - або введені, або змонтовані як інший том. Після завершення кроку збирання ви збираєте свій остаточний контейнер, просто ADDвикористовуючи локальний каталог джерел, який тепер містить вбудовані артефакти.

Я сподіваюся, що Докер додає деякі функції, щоб спростити все це!

Оновлення: схоже, що метод, який рухається вперед, повинен мати вкладені збірки. Коротше кажучи, dockerfile описував би перший контейнер, який використовується для побудови середовища виконання, а потім другий вкладений склад контейнера, який може зібрати всі частини в кінцевий контейнер. Таким чином, речі часу нарощування не знаходяться у другому контейнері. Це програма для Java, де для створення програми вам потрібен JDK, але лише JRE для його запуску. Існує ряд пропозицій, які обговорюються, найкраще починати з https://github.com/docker/docker/isissue/7115 та переходити до деяких посилань на альтернативні пропозиції.


7

Альтернативою для використання змінних оточуючих середовищ, які можуть забруднитися, якщо їх у вас багато, - використовувати томи, щоб зробити каталог на хості доступним у контейнері.

Якщо ви помістите всі свої дані як файли у цю папку, контейнер може читати файли та використовувати їх за власним бажанням.

Наприклад:

$ 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

Багато програм можуть читати свої облікові дані з окремого файлу, тож таким чином ви можете просто навести програму на один із файлів.


5

рішення тільки на час виконання

docker-compose також пропонує рішення, що не належить до рою (оскільки v1.11: секрети за допомогою прив'язки кріплення ).

Секрети монтуються у вигляді файлів нижче /run/secrets/докер-композицією. Це вирішує проблему під час виконання (запуск контейнера), але не під час збирання (побудова зображення), оскільки /run/secrets/не монтується під час збирання. Крім того, така поведінка залежить від запуску контейнера з докер-композитом.


Приклад:

Докерфайл

FROM alpine
RUN cat /run/secrets/password
CMD sleep inifinity

docker-compose.yml

version: '3.1'
services:
  app:
    build: .
    secrets:
      - password

secrets:
  password:
    file: password.txt

Щоб скласти, виконати:

docker-compose up -d

Подальше читання:


2

За допомогою Docker v1.9 ви можете використовувати інструкцію ARG для отримання аргументів, переданих командним рядком, на зображення під час дії збірки . Просто використовуйте прапор --build-arg . Таким чином, ви можете уникнути збереження явного пароля (або іншої розумної інформації) на Dockerfile та передавати їх на льоту.

джерело: https://docs.docker.com/engine/reference/commandline/build/ http://docs.docker.com/engine/reference/builder/#arg

Приклад:

Докерфайл

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

Сподіваюся, це допомагає! До побачення.


26
Згідно з документами ARG Докера : "Не рекомендується використовувати змінні часу збирання для передачі секретів, таких як ключі github, облікові дані користувачів тощо"
Lie Ryan

3
Цікаво, чому Docker відмовляється використовувати --build-arg var=secretдля передачі приватного ключа SSH у зображення, обґрунтування не підтверджено. Хтось може це пояснити?
Хенк Вірсема

2
@HenkWiersema Інформація про процес, журнали та історія команд небезпечні. Інформація про процес доступна для всіх, яка включає всі параметри командного рядка. Часто ці дзвінки закінчуються в журналах, які також можуть бути загальнодоступними. Не рідкість, коли зловмисник перевіряє інформацію про запущені процеси та перебирає загальнодоступні реєстраційні файли на предмет секретів. Навіть коли він не є загальнодоступним, він може зберігатися у вашій історії команд, що полегшить комусь отримання секретів через не адміністративний обліковий запис.
tu-Reinstate Monica-dor duh

2
Який рекомендований спосіб надання облікових даних, необхідних під час збирання? Наприклад, зображення, якому потрібен доступ aws s3 для отримання великого набору даних, який буде знаходитися всередині зображення?
ely

3
Я гадаю, що причина, яку вона не рекомендується, полягає в тому, що docker historyекспонують build-arg/ ARGзмінні. Можна витягти будь-яке зображення, перевірити його і побачити будь-які секрети, передані під час збирання, як build-arg/ ARGпараметр.
vee_ess

2

Мій підхід, здається, працює, але, ймовірно, наївний. Скажи мені, чому це неправильно.

ARG, встановлені під час складання docker, піддаються історії підкоманди, тому нікуди не йдіть. Однак при запуску контейнера змінні середовища, задані командою run, доступні контейнеру, але не є частиною зображення.

Отже, в Dockerfile зробіть налаштування, яке не передбачає секретних даних. Встановіть CMD чогось подібного /root/finish.sh. У команді run використовуйте змінні середовища для надсилання секретних даних у контейнер. finish.shвикористовує змінні, по суті, для завершення побудови завдань.

Щоб полегшити управління секретними даними, вкладіть їх у файл, завантажений докерним запуском за допомогою --env-fileперемикача. Звичайно, зберігайте файл у секреті. .gitignoreі таке.

Для мене finish.shпрацює програма Python. Він перевіряє, чи не працює раніше, а потім закінчує налаштування (наприклад, копіює ім'я бази даних у Django settings.py).


2

Існує нова команда докера для управління "секретами". Але це працює лише для ройних скупчень.

docker service create
--name my-iis
--publish target=8000,port=8000
--secret src=homepage,target="\inetpub\wwwroot\index.html"
microsoft/iis:nanoserver 

1

Методологія додаток 12-Factor говорить, що будь-яка конфігурація повинна зберігатися в змінних оточення.

Docker compose міг зробити змінну заміну в конфігурації, щоб можна було використовувати для передачі паролів від хоста до docker.


Я ціную посилання на Біблію.
JakeCowton

-2

Хоча я повністю згоден, простого рішення немає. Продовжує залишатися єдина точка провалу. Або докерфайл, і т.д., і так далі. У Apcera є план, схожий на побічний результат - подвійна аутентифікація. Іншими словами, два контейнери не можуть говорити, якщо немає правила конфігурації Apcera. У їх демонстраційному режимі uid / pwd був очищений і його не можна було повторно використовувати, поки адміністратор не налаштував зв'язок. Однак для роботи це, ймовірно, означало виправлення Docker або принаймні мережевий плагін (якщо таке є).


2
Чи є десь відповідь на поставлене запитання?
Abhijit Sarkar
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.