Безопасность
1 апреля 2026 г.

Воспроизводимые сборки и подпись артефактов: контроль целостности от коммита до деплоя
Особую роль в разработке программного обеспечения наравне с качеством написания кода играет безопасность цепочки его поставок (Software Supply Chain Security). Примером нарушения такой безопасности служит инцидент с Trivy – популярным open source-сканером уязвимостей, атакованным в марте этого года именно через цепочку поставок. Чтобы избежать таких инцидентов, необходимо руководствоваться правилами воспроизводимости сборок и криптографической подписи артефактов.
Изображение 1. Визуальное представление безопасности цепочки поставок программного обеспечения.
Воспроизводимость сборок
Для того, чтобы писать о том, «как это можно применить», нужно дать определение. Воспроизводимость сборок – это процесс, при котором многократная сборка одного и того же исходного кода при одинаковых инструкциях сборки приводит к созданию идентичных файлов сборки. Применяется это обычно для:
обнаружения скрытых механизмов в программном обеспечении, которые позволяют обойти меры защиты (они же бэкдоры). Если привести пример, то злоумышленник собирает код на своём устройстве для подмены и моментально получает другой хэш. А этот «сигнал» скажет, что внутри кода есть что-то лишнее.
детерминированной сборки – сборки одного и того же исходного кода с одной и той же средой и инструкциями сборки, при котором создаются одни и те же двоичные файлы в любом случае, даже если они сделаны на разных устройствах, в разных директориях, с разными именами и в разный диапазон времени.
повышения доверия пользователей. Как ни странно, но сборка из исходного кода, где получается ожидаемый результат при множественном повторении, вне зависимости от сред приводит к тому, что пользователь доверяет данному программному обеспечению.
Этот фактор можно исключить, если следовать определённым правилам реагирования на сигналы:
Временные метки (они же Timestamp). В компиляторах есть стандарт учёта времени сборки, а управлять им можно при помощи переменной SOURCE_DATE_EPOCH
Пути к файлам. Никаких нестандартных абсолютных путей (пример: /custom/path/to/binary.bin), использовать только стандартизированные пути для каждого дистрибутива согласно иерархии файловой системы.
Версионирование и фиксация зависимостей. Все зависимости должны фиксироваться в местах, которые использует тот или иной языка программирования (для NodeJs примером может послужить package-lock.json, для Golang – go.sum)
Окружение сборки. Используя контейнеризированные среды, например Docker, необходимо фиксировать не только версии приложения, но также и версии используемых инструментов как при подготовке образа, так и при установке необходимых утилит внутри него.
Подпись артефактов
Помимо воспроизводимости сборок нужно также гарантировать конечному пользователю, что артефакты не только были благополучно загружены в реестр артефактов, но и не оказались подменены в процессе. На определенных уровнях управления можно получить гарантию сохранности от вмешательства в цепочку поставки:
кода: при загрузке коммитов в веб-платформу для управления проектами и репозиториями программного кода (он же VCS) гарантируем, что код был подписан именно владельцем коммита;
Изображение 2. Демонстрация коммитов подписанным на локальной машине и не подписанным на платформе Gitlab.
сборки: гарантирует, что артефакт был создал доверенным конвейером сборки;
подписи образа: гарантирует целостность получаемого артефакта.
Для удовлетворения данных целей используются следующие инструменты:
Подпись GPG/SSH на начальном (локальном) этапе разработки. Надежный способ избежать Man-in-the-Middle (MITM)-атаки, подмены хоста SSH (SSH Host Key Spoofing) или подмена на сервере управления репозиториями программного кода от внутренних сотрудников (Insider Threat).
Изображение 3. Демонстрация Man-in-the-Middle атаки.
Изображение 4. Демонстрация Insider Threat атаки.
Sigstore/Cosign. Удобный инструмент с открытым исходным кодом для работы с подписью артефактов и верификации подписи напрямую в конвейере. Поддерживает подписывание артефакта, не используя ключи. Плюс от такого подхода в том, что ключ генерируется на лету, используется один раз и исчезает. Подпись привязывается к идентичности конвейера. Если применяются on-prem решения и не доступен сервис в белых листах, то нужно поднять свой или использовать вариант с ключами.
Полная цепочка доверия
Сформируем план проверки полной цепочки:
Исходный код. Необходимо использовать систему контроля версий. Здесь мы защищаемся при помощи подписей коммитов разработчиками и безопасный ветвей.
СборкиДолжны происходить в изолированном окружении.
Должны генерироваться метаданные сборки, которые отвечают на вопросы: Кто собрал? Из какого коммита? Кто автор коммита? Какие этапы сборки приложения? Данный шаг называется провенанс.
Артефакты. Обязательное хранение в защищенном хранилище (Sonatype Nexus, Github releases, Harbor) с защитой от записи (это называют ещё иммутабельностью). В данном шаге подпись артефакта осуществляется после сборки.
Процесс развертывания (Deploy). Контроль среды не допустит запуска не защищенного кода.
Практические примеры
1. Защита исходного кода на этапе разработки. Чтобы добиться данного эффекта, необходимо создать пару ключ публичный/ключ приватный -> в настройках VCS добавить публичную часть и далее следовать инструкции, приведенной ниже.
Изображение 5. Генерация ключа из командой строки.
Изображение 6. Использование ключа для подписи коммитов.
2. Сборка. Создадим тестовое приложение, чтобы проверить различие в хеше при сборке одного приложения и привязке к времени сборки.
Изображение 7. Тестовый код на Golang.
Инициализируем приложение
Изображение 8. Создание go.mod файла.
Проверим сборку с объявленными локально параметрами
Изображение 9. Локальная сборка для демонстрации запуска.
Повторим сборку без объявленных параметров
Изображение 10. Повторная генерация кода для проверки работы переменных.
Как видим, хэш сумма изменилась. Именно такой принцип будет соблюдаться при сборке приложений. Также в зависимости от коммита и объявленных параметров хэш сумма продолжит и дальше изменяться.
Создадим Dockerfile для сборки приложения
Изображение 11. Dockerfile для сборки.
Изображение 12. Локальная сборка образа.
Изображение 12. Локальная сборка образа.
3. Артефакты. Реализуем подписывание образа при помощи ключей. Генерируем ключ – пару cosign generate-key-pair – и заводим 3 переменные: COSIGN_PASSWORD COSIGN_PRIVATE_KEY COSIGN_PUBLIC_KEY
Далее реализуем CI/CD, в котором соберём образ, зальём его в реестр образов, подпишем и верифицируем его. Данный подход даст нам контроль над подменой в реестре образов.
4. Деплой. При использовании Kubernetes рекомендуется использовать Admission Controllers. Для поставки образов можно использовать внешний скрипт со встроенной проверкой, по аналогии выше, `cosign verify …`
Автор: Владислав Авдеев, DevOps, NGR Softlab.
Автор: NGR Softlab Российский разработчик решений по информационной безопасности NGR Softlab работает на рынке с 2019 года. В портфеле компании представлены интеллектуальные системы по управлению безопасностью, инструменты анализа и мониторинга ИБ. Продукты NGR Softlab включены в реестр российского ПО. Центр исследований и производство расположены в России. С 2021 года компания является участником проекта «Сколково» № 1124235.
Продуктам NGR Softlab доверяют крупные финансовые организации, компании нефтегазовой отрасли, ритейла и госсектора. Решения разработчика направлены на комплексное повышение безопасности ИТ-инфраструктуры, конкурентоспособности компаний и решение аналитических задач ИБ.