Секреты Docker Compose: переменная окружения может попасть в журнал

|Автор: Редакция QUASA|5 мин чтения| 2
Секреты Docker Compose: переменная окружения может попасть в журнал

В Docker Compose передавайте пароли и ключи через секреты: храните значения в отдельных файлах и разрешайте доступ только тем сервисам, которым они нужны. Документация Docker предупреждает, что переменная окружения может попасть в журнал отладки; разрешённый сервис получает секрет как файл в каталоге /run/secrets.

Для такого переноса приложение должно читать содержимое файла или принимать путь к нему. Если программа по-прежнему ждёт сам пароль в переменной окружения, одного изменения конфигурации недостаточно. Исходный файл остаётся на узле, поэтому его права доступа и резервные копии тоже требуют внимания.

Почему файл с переменными не защищает пароль

Файл .env подставляет значения в конфигурацию. Если пароль после подстановки записан в разделе переменных сервиса, контейнер получает его как обычную переменную окружения. Файл, указанный для передачи переменных сервису, действует так же: смена места хранения исходного файла не меняет способ доставки значения.

Рекомендации OWASP указывают на риск появления секретов из переменных окружения в журналах и дампах системы. Поэтому при миграции важно найти не только исходный файл, но и места, где его значение передаётся дальше: настройки сервиса, команды запуска и сценарии обработки ошибок. Переменная с путём к секретному файлу допустима, если приложение читает файл по этому пути, а не копирует пароль обратно в окружение.

Как перенести значения в секреты

Рассмотрим условную схему: базе данных нужен пароль, а прикладному сервису — тот же пароль для подключения и отдельный ключ доступа к внешнему интерфейсу. Создайте два исходных файла в каталоге с ограниченным доступом. Не добавляйте их в репозиторий и контекст сборки образа: правила исключения для этих двух случаев задаются отдельно. Если значение уже попало в историю репозитория, исключение файла из новых изменений не удалит старую копию.

  1. В верхнем разделе secrets объявите отдельное имя для каждого значения. Полем file укажите путь к соответствующему исходному файлу; в конфигурации будут видны имя и путь, но не содержимое файла.
  2. В списке секретов сервиса базы укажите только пароль базы. Прикладному сервису разрешите пароль базы и его собственный ключ. Объявление секрета на верхнем уровне само по себе не выдаёт его каждому контейнеру.
  3. Удалите прежние значения из переменных сервисов и файлов, которые загружаются в окружение. Настройте приложение читать смонтированный файл с именем секрета в каталоге, указанном выше.
  4. Пересоздайте контейнеры и проверьте, что каждый сервис открывает назначенный ему файл. Для проверки доступности достаточно успешного чтения приложением; выводить содержимое в общий терминал или журнал не требуется.

Некоторые готовые образы поддерживают переменную с суффиксом _FILE: в неё записывают путь, а образ сам читает пароль из файла. Точное имя такой настройки зависит от образа. Если поддержки нет, измените загрузку настроек приложения. Сценарий запуска, который читает файл и затем помещает его содержимое в переменную окружения, возвращает прежний риск.

Как разделить доступ между сервисами

В Docker Compose пароль базы доступен базе и сервису API, а ключ API смонтирован только в сервис API.

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

При работе с локальным исходным файлом защита не заканчивается на списке разрешённых сервисов. Пользователь узла с доступом к файлу может прочитать его вне контейнера; доступ к управлению контейнерами также требует отдельного контроля. Приложение, получившее секрет законно, всё ещё может записать его в собственный журнал при отладке или ошибке. Поэтому перенос меняет канал доставки, но не заменяет проверку поведения программы.

Секрет сборки и внешнее хранилище

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

Ключ для загрузки закрытой зависимости нужен во время сборки образа, а не обязательно после запуска контейнера. Инструкция Docker по секретам сборки описывает временное монтирование для нужной команды вместо передачи значения через аргумент сборки или переменную окружения. Доступ сборщику настраивается отдельно от списка секретов работающего сервиса.

Временное монтирование не делает ключ доступным запущенному контейнеру. Если он требуется и после запуска, настройте отдельную выдачу сервису. Проверяйте также саму команду сборки: она способна напечатать ключ в журнал или сохранить его в создаваемом слое, даже если получила значение через временный файл.

Когда нужны централизованная смена ключей, учёт обращений и отзыв доступа, рассмотрите внешнее хранилище секретов и способ доставки значения приложению. Локальные файлы Compose дают адресную передачу сервисам, но сами не управляют сроком действия ключа. Уже раскрытый пароль нужно заменить в системе, которая его принимает.

Что проверить перед развёртыванием

Сначала проверьте работу схемы на временном значении с ограниченными правами. Затем просмотрите места, где прежний секрет мог сохраниться. Настоящий ключ не вставляйте в команды поиска, вывод или историю которых могут видеть другие пользователи.

  • Конфигурация. Просмотрите результат команды docker compose config. В переменных сервиса и командах запуска не должно быть самого значения; путь к секретному файлу допустим. Не публикуйте вывод команды, пока не убедились, что старая подстановка удалена.
  • Образ. Проверьте команды сборки, переменные образа, его историю и содержимое слоёв. Удаление секрета из новой сборки не очищает ранее опубликованный образ; при утечке потребуется новая сборка и замена ключа.
  • Доступ. Сверьте списки разрешённых секретов. Назначенный файл должен читаться нужным сервисом и отсутствовать у сервиса без разрешения. Отдельно проверьте права на исходные файлы узла и доступ к их резервным копиям.
  • Журналы. Просмотрите сообщения приложения и сборки, в том числе ошибки подключения и отладочный вывод. Если прежний ключ уже оказался в записях, ограничьте доступ к ним и замените ключ: перенос в файл не удаляет старые записи.

Читайте также:

Поделиться:

Подпишитесь на рассылку

Получайте свежие новости Web3, AI и криптовалют прямо на вашу почту.

0