Сертификаты докер-контейнера ssl

Есть ли какой-нибудь элегантный способ добавить ssl-сертификаты в изображения, полученные из docker pull?

Я ищу простой и воспроизводимый способ добавления файла в / etc / ssl / certs и запуска update-ca-Certificates. (Это должно охватывать образы Ubuntu и Debian).

Я использую docker на CoreOS, и машина coreos доверяет необходимым ssl-сертификатам, но контейнеры docker, очевидно, имеют только значение по умолчанию.

Я пытался использовать docker run --entrypoint=/bin/bash затем добавить сертификат и запустить update-ca-certificates, но это, кажется, навсегда перекрывает точку входа.

Мне также интересно теперь, было бы более элегантно просто смонтировать /etc/ssl/certs на контейнер с хост-машин копировать? Это неявно позволит контейнерам доверять тем же вещам, что и хосту.

Я работаю с надоедливым прокси, который отказывается от всего:(. Который ломает SSL и делает контейнеры странными для работы.

7 ответов

Решение

Установите сертификаты на контейнер Docker, используя -v:

docker run -v /host/path/to/certs:/container/path/to/certs -d IMAGE_ID "update-ca-certificates"

Я пытаюсь сделать что-то похожее на это. Как отмечалось выше, я думаю, вы захотите создать новый образ с помощью пользовательского файла Dockerfile (используя изображение, которое вы извлекли в качестве базового изображения), ADD тогда ваш сертификат RUN update-ca-certificates, Таким образом, вы будете иметь согласованное состояние каждый раз, когда запускаете контейнер из этого нового изображения.

# Dockerfile
FROM some-base-image:0.1
ADD you_certificate.crt:/container/cert/path
RUN update-ca-certificates

Скажем docker build против этого Dockerfile выдал IMAGE_ID. На следующем docker run -d [any other options] IMAGE_IDконтейнер, запущенный этой командой, будет содержать информацию о вашем сертификате. Просто и воспроизводимо.

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

На хосте (и контейнере) Debian я успешно выполнил:

docker run -v /etc/ssl/certs:/etc/ssl/certs:ro ...

Вы можете использовать относительный путь для подключения тома к контейнеру:

docker run -v `pwd`/certs:/container/path/to/certs ...

Обратите внимание на обратную галочку на pwdкоторые дают вам настоящий рабочий каталог. Предполагается, что у вас естьcerts папка в текущем каталоге, которую docker runвыполняется. Отлично подходит для локальной разработки и сохраняет папку сертификатов видимой для вашего проекта.

Я написал скрипт, который упаковывает и настраивает SSL-сертификаты хоста в гостевой системе.

Преимущество в том, что вам не нужно пересобирать контейнеры — все должно работать.

Он называется , так что вы можете либо скопировать его куда-нибудь на свой $PATHвыше чем dockerили переименовать и поместить в другое место.

Дайте мне знать через Github, если у вас возникнут какие-либо проблемы с этим!

Это не будет прямым ответом на ваш вопрос, но именно так я решил ту же проблему.

я бегал golang:1.16.4-busterи ничего, что я пробовал с сертификатами, не работало. я переключился на golang:1.17.8-alpine3.15и он работал с самого начала, не пытаясь загрузить какие-либо сертификаты. Плюс бонус в виде меньшего дистрибутива.

На самом деле нет отличного способа решить эту проблему, когда вы говорите о CoreOS (Fedora) и гостевой системе Ubuntu/Debian. Fedora использует современный стандарт для организации «якорей доверия», в то время как Ubuntu/Debian по-прежнему использует старый стиль. Эти два не совместимы напрямую.

Потратив слишком много времени на решение обратной проблемы (Fedora на Ubuntu), у вас есть следующие варианты:

  1. Получите образ контейнера, чтобы добавить первоклассную поддержку пользовательских сертификатов, которые будут добавлены через переменную среды (обычно для хорошо созданных контейнеров, но не произойдет для прямого образа дистрибутива Ubuntu).
  2. Найдите способ запустить аналогичную хост-систему (обычно это нежизнеспособный вариант) и установите якоря доверия хоста поверх гостевых.
  3. Создайте свою собственную версию образа, которая добавляет сертификаты или поддерживает их указание (обычно не поддерживается для управления долгоживущим форком).
  4. Оберните ENTRYPOINT сценарием, который добавляет и запускает добавление/установку CA с необязательного дополнительного хост-монтирования (очень проблематично, см. ниже)
  5. Запустите контейнер один раз с измененными аргументами, чтобы сгенерировать копию обновленного хранилища доверенных сертификатов в монтировании хоста, а затем монтируйте его при последующих запусках контейнера (сделайте это ) .

Самый лучший вариант, как правило, — попытаться получить поддержку образа контейнера (или отправить PR самостоятельно), чтобы добавить поддержку загрузки дополнительных сертификатов CA из переменной среды, поскольку это очень распространенный вариант использования среди корпоративных пользователей и самостоятельных хостеров. Однако это обычно добавляет чрезмерные накладные расходы для одноразовых контейнеров, что неприемлемо, и у сопровождающего образа могут быть другие веские причины не делать этого. Это также не решает проблему для вас в то же время.

Изменение вашего хоста и «разветвление» образа для создания собственного также не являются хорошими вариантами, обычно они не подходят для развертывания или соображений удобства обслуживания.

Обертывание ENTRYPOINT в основном эквивалентно специальной версии модификации контейнера для поддержки пользовательских сертификатов, но исключительно снаружи образа. У него есть все те же потенциальные причины для того, чтобы этого не делать, и недостатки, заключающиеся в том, что вы делаете это вне контейнера, но есть то преимущество, что вам не нужно ждать обновления образа, чтобы сделать это. Я бы не рекомендовал этот вариант обычно. Это решение в основном состоит в том, чтобы написать сценарий, который вы монтируете в контейнер, который будет выполнять настройку ЦС, а затем запускать любые ENTRYPOINT и CMD. Однако здесь есть несколько серьезных ошибок. Во-первых, вам нужно настроить его для конкретного контейнера, который вы используете, чтобы он работал с той же точкой входа. С помощью некоторых сценариев это, вероятно, можно определить, но вам нужно следить за хорошо продуманными контейнерами, у которых есть система инициализации для решения проблемы pid 1 (https://github.com/Yelp/dumb-init#why-you-need-an-init-system tl;dr: перехватывать такие сигналы, как прерывания, и не терять системные ресурсы, когда для принудительной остановки контейнера требуется процесс инициализации pid 1 для управления им). Существует несколько различных систем инициализации, и вы не можете обернуть систему инициализации. Кроме того, если вы используете Docker, выне может переопределить точки входа несколькими командами из командной строки. Контейнеры с системами инициализации, например, принимают аргумент для фактически выполняемой команды, поэтому точка входа представляет собой список (). Docker позволяет указывать точки входа с несколькими командами только через API, а не через командную строку, поэтому нет возможности сохранитькоманду и укажите свой собственный сценарий для второго аргумента.

«Лучшее» решение . Несмотря на то, что долго работающие контейнеры сильно выиграют от варианта № 1, описанного выше, лучшим выбором для одноразовых контейнеров и немедленного решения является создание хост-монтирования гостевых якорей доверия.
Лучший способ — создать сохраненную на хосте копию того, как должны выглядеть обновленные привязки доверия контейнера, и смонтировать ее поверх хранилища доверия контейнера. Наиболее совместимый способ — сделать это с помощью самого образа целевого контейнера, но с переопределением точки входа, монтируя папку «кэш» для якорей доверия в рабочей области проекта, связанной с контейнером. Однако это может не работать в облачных и CI-ситуациях. Альтернативным вариантом является создание отдельного тома контейнера, который использует каждый из двух основных стилей привязки доверия (современный, например, Fedora, Arch и т. д., и устаревший, например, Debian, Ubuntu и т. д.) и отдельно обновляется полурегулярно из общий образ контейнера соответствующего типа. Результирующие тома контейнера затем просто становятся зависимостью тома, где правильный выбирается на основе типа образа целевого контейнера. Суть того, как сгенерировать один из них, заключается в том, чтобы смонтировать на хосте сценарий, который добавляет корневые центры сертификации в соответствующую папку (к вашему сведению, устаревшие якоря доверия будут рекурсивно искать папки корневых центров сертификации, а современные — нет). команда обновления привязки, а затем копирует полученные папки привязки доверия на хост-монтирование.


Обновлять:

Если это все еще актуально, большинство базовых образов контейнеров Ubuntu используются внутри (сейчас), которые поддерживают множество общих вещей, включая добавление пользовательских корневых центров сертификации в образ контейнера, например, они уже поддерживают вариант 1. https:
//cloudinit.readthedocs.io/en/latest/topics/examples.html#configure-an-instances-trusted-ca-certificates

Я считаю, что вы можете добавить монтирование файла вкоторый имеет YAML, как в ссылке примера, и он будет выбран во время загрузки контейнера. Вы можете легко сгенерировать этот YAML программно на основе дополнительных корневых сертификатов CA, которые вам нужны.


EDIT1: исправлено: я поменял местами хост и гость из исходного вопроса. Также добавлено обновление о. EDIT2: исправлена ​​опечатка стиля

Другие вопросы по тегам