Хабрахабр

[Перевод] Секреты сборки и пересылка SSH в Docker 18.09

image

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

09 включает множество обновлений. Команда сборки Docker 18. Серверное приложение BuildKit обзавелось новыми функциями, среди которых — поддержка секретов сборки Dockerfile. Основная особенность — в том, что появился абсолютно новый вариант реализации серверной части, он предлагается в рамках проекта Moby BuildKit.

Использование секретов

BuildKit в версии 18. В первую очередь нужно включить серверную часть BuildKit. В следующей версии планируется сделать BuildKit серверной частью по умолчанию. 09 — это функция выбора, которую можно включить с помощью переменной среды DOCKER_BUILDKIT=1 перед запуском docker build.

export DOCKER_BUILDKIT=1

Одна из них — возможность использования пользовательского интерфейса, загруженного из образов в реестре; вторая — возможность использования монтажных точек в командах RUN для Dockerfile. Реализация секретов сборки основана на двух новых функциях BuildKit. Пока что секреты в стабильном канале внешних Dockerfile недоступны: потребуется одна из версий в экспериментальном канале, например, docker/dockerfile:experimental или docker/dockerfile/1.  Чтобы воспользоваться функцией реализации с поддержкой секретов (вместо стандартной), определите образ компоновщика с помощью синтаксической директивы в первой строке Dockerfile — указав на образ контейнера, который хотите использовать. 0-experimental. 0.

# syntax=docker/dockerfile:1.0.0-experimental

Метка --mount принимает разделенную запятой структуру как в --mount для docker run. Если вам как автору Dockerfile известно, что команда RUN, установленная в Dockerfile, требует секретного значения, используйте для нее метку --mount, указывая, какой секрет нужен команде, и где его следует монтировать.

# syntax=docker/dockerfile:1.0.0-experimental
FROM alpine
RUN --mount=type=secret,id=mysite.key command-to-run

Секрет доступен только команде с меткой mount, а не другим частям сборки. Эта метка указывает, что во время работы команда имеет доступ к секретному файлу по пути /run/secrets/mysite.key. В настоящее время интерфейс командной строки Docker поддерживает раскрытие секретов из локальных файлов клиента с помощью метки --secret. Данные в этом файле загружаются из хранилища секретов на основании указанного идентификатора «mysite.key».

docker build --secret id=mysite.key,src=path/to/mysite.key .

Если «target» указано, а «id» — нет, то «id» по умолчанию становится базовое имя пути назначения. Как описано выше, секреты по умолчанию устанавливаются в /run/secrets, однако можно указать любой путь с помощью ключа «target».

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

Если подобная ситуация нежелательна, используйте ключ «required»: это покажет, что без значения произойдет сбой сборки. Если автор Dockerfile указывает, что инструкция RUN может использовать секрет, а пользователь, вызывающий сборку, не предоставляет его, то секрет игнорируется, и по указанному пути никакой файл не устанавливается.

# syntax=docker/dockerfile:1.0.0-experimental
FROM alpine
RUN --mount=type=secret,id=mysite.key,required <command-to-run>

Реализация

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

Секретные значения также исключаются из расчетов кэша сборки, чтобы нельзя было использовать кэш метаданных.

SSH

Да, чтобы раскрыть личный ключ SSH для сборки, можно использовать секретные элементы, однако есть решение лучше. Чаще всего, наверное, пытаются получить доступ к частным хранилищам — через протокол SSH. Например, если вы используете несколько компьютеров с SSH, не нужно передавать свой ключ — достаточно обеспечить соединение через протокол ssh-A. В протоколе SSH используется криптография с открытым ключом, и благодаря этой конструкции не нужно никому сообщать свой личный ключ.

Вместо того, чтобы передавать данные о ключе, Docker просто сообщит компоновщику о наличии такой возможности. Мы добавили аналогичную возможность в docker build, где можно использовать метку --ssh для направления существующего агентского соединения SSH или ключа в программу-компоновщик. Сам ключ не покидает программу-клиент, а после завершения программы, потребовавшей доступа, со стороны компоновщика не остается никаких данных для повторной установки удаленного соединения. Если компоновщику потребуется доступ к удаленному серверу через SSH, он обратится к клиенту и попросит подтверждения конкретного запроса, необходимого для соединения.

Другие команды не имеют данных о доступном агенте SSH. Доступ к передаче файлов по протоколу SSH получают только команды в Dockerfile, прямо запросившие доступ к SSH, указав блок type=ssh.

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

Получить этот открытый ключ можно несколькими способами. При выполнении сборок с Dockerfile правильность этого запроса не проверить, и соответственно, открытый ключ сервера должен уже существовать в контейнере, пытающемся использовать SSH. Если хотите решение попроще, запустите в рамках сборки программу ssh–keyscan — она загрузит актуальный открытый ключ хоста. Например, его предоставит базовый образ, либо вы скопируете его из контекста сборки.

Тогда во время выполнения процесса будет установлен сокет с доступом к агенту SSH только для чтения. Для запроса доступа SSH к команде RUN в Dockerfile необходимо указать блок с типом «ssh». Это также настроит переменную среды SSH_AUTH_SOCK, чтобы программы, использующие протокол SSH, автоматически использовали этот сокет.

# syntax=docker/dockerfile:experimental
FROM alpine
# install ssh client and git
RUN apk add --no-cache openssh-client git
# download public key for github.com
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# clone our private repository
RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git myproject

Со стороны клиента Docker необходимо с помощью метки --ssh указать, что пересылка по протоколу SSH разрешена для этой сборки.

docker build --ssh default .

Если хотите использовать значение default=$SSH_AUTH_SOCK, путь к сокету можно оставить пустым. Метка принимает пару ключевых значений, определяющую положение сокета локального агента SSH или закрытых ключей.

Например, доступ в различные хранилища в Dockerfile можно получить с различными ключами развертывания. В блоке Dockerfile можно также использовать ключ «id» для разделения различных серверов, входящих в одну сборку. В данном случае в Dockerfile Вы будете использовать:


RUN --mount=type=ssh,id=projecta git clone projecta …
RUN --mount=type=ssh,id=projectb git clone projectb …

Заметьте, что даже если указать фактические ключи, компоновщику сообщается только агентское соединение, а не фактическое содержание этих закрытых ключей. и раскроете данные клиента с помощью docker build --ssh projecta=./projecta.pem --ssh projectb=./projectb.pem.

09 завершен. На этом обзор новых возможностей секретов сборки в Docker 18. Надеюсь, новые функции помогут шире использовать возможности Dockerfile в проектах и обеспечить более высокий уровень безопасности сборочного конвейера.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть