Проверка происхождения контейнерного образа сводится к трём вопросам: кто собрал этот образ, из чего он собран и не изменён ли он после сборки. Ответить на них помогают подписи образов, манифесты происхождения (provenance) и списки компонентов (SBOM). Если вы используете образы из публичных реестров или собираете их сами, минимальный набор проверок такой: убедиться в наличии и валидности криптографической подписи, запросить provenance-данные о сборке и сверить SBOM с фактическим содержимым образа.
В этой статье разобрано, как устроены эти механизмы, какие инструменты для них существуют, что реально можно проверить, а что остаётся на доверии к издателю, и как встроить проверки в процесс сборки и эксплуатации без избыточной сложности.
- Почему происхождение образа — это не формальность
- Три уровня проверки: подпись, происхождение, состав
- Подписи образов: как это работает на практике
- Что подписывать и где проверять
- Provenance: откуда взялся образ
- SBOM: состав образа и встроенные пакеты
- Проверка встроенных пакетов: практический порядок
- Минимизация поверхности: меньше пакетов — меньше проверок
- Типичные ошибки при проверке происхождения
- Как встроить проверки в процесс: поэтапный план
- Сценарии: что делать в разных условиях
- Частые вопросы
- Достаточно ли проверки дайджеста образа без подписи?
- Нужно ли проверять подписи образов, которые уже работают в кластере?
- SBOM или сканер уязвимостей — что важнее?
- Что делать, если критичная зависимость не обновляется?
- С чего начать прямо сейчас
Почему происхождение образа — это не формальность
Контейнерный образ — это не один файл, а набор слоёв и манифестов в реестре. Любой из них теоретически может быть подменён: скомпрометированная учётная запись мейнтейнера, уязвимость в CI-инфраструктуре или атака на сам реестр приводят к тому, что «проверенный» тег начинает указывать на вредоносное содержимое. Известные инциденты с отравленными версиями популярных пакетов и образов показывают, что доверие к имени репозитория само по себе не защищает.
Отсюда три практических риска, которые закрывает проверка происхождения:
- Подмена содержимого. Тег latest или конкретная версия указывает не на тот образ, который был изначально опубликован. Лечится проверкой дайджеста и подписи.
- Скрытые зависимости. Внутри образа могут оказаться пакеты с известными уязвимостями или нежелательным кодом, о которых вы не знаете. Частично лечится анализом SBOM и сканерами уязвимостей.
- Непроверенная сборка. Образ собран не там и не так, как заявлено: например, не из исходников публичного репозитория. Частично лечится проверкой provenance-аттестаций.
Важно понимать границы: ни один механизм не даёт абсолютной гарантии. Подпись подтверждает, что содержимое не изменилось после подписания и что его подписал владелец ключа. Но если ключ издателя скомпрометирован или издатель сам подписал вредоносный образ, криптография бессильна. Поэтому проверка происхождения — это слой защиты, а не замена сканированию уязвимостей, ограничению привилегий и мониторингу.
Три уровня проверки: подпись, происхождение, состав
Механизмы проверки удобно разделять на три уровня, каждый из которых отвечает на свой вопрос.
| Уровень | Вопрос | Механизм | Что подтверждает |
|---|---|---|---|
| Целостность | Не изменён ли образ после публикации? | Дайджест (sha256), подписи образа | Байты образа совпадают с теми, что подписал издатель |
| Происхождение | Где и как собран образ? | Provenance-аттестации (например, SLSA provenance) | Факт и параметры сборки: репозиторий исходников, CI-система, параметры |
| Состав | Что внутри образа? | SBOM, сканеры уязвимостей | Перечень пакетов и библиотек, наличие известных CVE |
Эти уровни дополняют друг друга. Подпись без SBOM говорит, что образ не тронут, но не раскрывает его содержимое. SBOM без подписи можно подделать вместе с образом. Provenance без подписи аттестации легко сфабриковать. Практическая связка выглядит так: подпись + provenance + SBOM, и все три объекта тоже подписаны.
Подписи образов: как это работает на практике
Стандарт де-факто для подписи образов в экосистеме Kubernetes и облачных платформ — Sigstore и его инструмент cosign. Идея простая: издатель подписывает дайджест образа своим ключом, подпись сохраняется в реестре рядом с образом, а потребитель проверяет её перед развёртыванием.
Типичные проверки, которые имеет смысл выполнять:
- Наличие подписи для конкретного дайджеста образа, а не тега. Тег перемещаемый, дайджест — нет.
- Соответствие идентичности подписавшего ожидаемой. В случае keyless-подписей Sigstore это сертификат, привязанный к учётной записи (например, рабочему процессу GitHub Actions), и проверяется через поле issuer и identity.
- Срок действия сертификата и прозрачность: записи о подписях попадают в публичный журнал прозрачности (Rekor), что затрудняет незаметный отзыв или фабрикацию.
Условный пример проверки подписи публичного образа через cosign выглядит так: сначала фиксируется дайджест (образ@sha256:…), затем выполняется команда вида cosign verify с указанием ожидаемого идентичности подписавшего. Если подпись отсутствует или идентичность не совпадает, образ не проходит проверку. Точные флаги команд зависят от версии инструмента, поэтому сверяйтесь с актуальной документацией.
Альтернативный, более традиционный путь — собственные ключи (NGINX-модель «доверенные коллекции», Notary/Notation в экосистемах Microsoft и OCI). Он требует управления ключами: хранения, ротации, защиты от компрометации. Keyless-подписи Sigstore снимают часть этой нагрузки, но привязывают вас к доступности внешних сервисов Sigstore. Для критичной инфраструктуры некоторые организации комбинируют оба подхода.
Что подписывать и где проверять
Подписывать нужно не только финальные образы приложений, но и промежуточные артефакты: образы CI-этапов, Helm-чарты, конфигурации. Проверка выполняется на нескольких точках:
- На этапе CI: после сборки образ подписывается автоматически, и подпись становится частью конвейера.
- При загрузке в кластер: admission-контроллеры (например, Kyverno или OPA/Gatekeeper с политиками проверки подписей) отклоняют неподписанные образы.
- При аудите: периодическая перепроверка образов, уже работающих в продакшене, на случай компрометации реестра.
Политика «запускать только подписанные образы» — самый действенный способ сделать проверку не ручной, а системной. Без неё проверка подписей быстро превращается в документ, который никто не открывает.
Provenance: откуда взялся образ
Подпись отвечает на вопрос «кто», но не «как». Аттестации происхождения (provenance) описывают процесс сборки: из какого репозитория и коммита собран образ, какая CI-система его собрала, с какими параметрами. Наиболее известная модель — SLSA (Supply-chain Levels for Software Artifacts), которая описывает уровни зрелости защиты цепочки поставок: от полного отсутствия гарантий до герметичных воспроизводимых сборок.
Практически provenance-аттестация — это подписанный JSON-документ, прикреплённый к образу в реестре. Его можно запросить тем же cosign и проверить: совпадает ли заявленный репозиторий исходников с официальным, совпадает ли коммит, собран ли образ в доверенной CI-системе, а не на ноутбуке разработчика.
Что реально даёт проверка provenance:
- Вы убеждаетесь, что образ собран из заявленных исходников, а не из форка с изменениями.
- Вы видите параметры сборки, включая использованные базовые образы и аргументы.
- Вы получаете основу для аудита: если позже выяснится проблема, можно точно определить, какие сборки затронуты.
Ограничение: provenance подтверждает процесс, но не качество кода. Образ может быть честно собран из исходников, в которых уже есть уязвимость или вредоносный коммит. Поэтому provenance работает в связке с проверкой исходников и сканированием.
SBOM: состав образа и встроенные пакеты
SBOM (Software Bill of Materials) — машиночитаемый перечень компонентов образа: системных пакетов, библиотек, их версий и лицензий. Распространённые форматы — SPDX и CycloneDX. SBOM генерируется при сборке (например, средствами BuildKit в Docker или Syft) и хранится как аттестация рядом с образом.
SBOM сам по себе не выявляет угрозы — это инвентаризация. Ценность появляется, когда SBOM используется для:
- Поиска уязвимостей. Сканирующие инструменты (Grype, Trivy, сканеры в CI) сверяют перечень пакетов с базами CVE и показывают, какие компоненты затронуты.
- Реакции на новые CVE. Когда публикуется новая уязвимость, вы по SBOM за минуты определяете, есть ли затронутый пакет в ваших образах, вместо ручного перебора.
- Лицензионного аудита. Перечень лицензий встроенных библиотек помогает не нарушать условия использования, особенно при коммерческом распространении.
- Выявления неожиданных компонентов. Если в образе минимального приложения обнаруживается компилятор, оболочка или пакет, которого там быть не должно, это повод разобраться.
Качество SBOM различается. Список, сгенерированный только по манифестам пакетного менеджера, может не включать статически слинкованные библиотеки и бинарники, собранные вручную. Более точные SBOM строятся анализом файловой системы образа. При сравнении инструментов обращайте внимание на полноту обнаружения, а не только на формат вывода.
Проверка встроенных пакетов: практический порядок
Если задача — понять, что за пакеты внутри образа и насколько им можно доверять, разумная последовательность такая:
- Зафиксируйте дайджест образа, который фактически используется в развёртывании, а не тег.
- Проверьте подпись и provenance-аттестации, если издатель их публикует.
- Извлеките SBOM (из аттестаций образа или сгенерируйте самостоятельно инструментом вроде Syft).
- Просканируйте SBOM и образ на известные уязвимости, отсортировав результаты по критичности и наличию работающего эксплойта.
- Сверьте перечень пакетов с ожидаемым: лишние компоненты, дублирующиеся версии одной библиотеки, пакеты из неизвестных источников — признаки проблемной сборки.
- Для критичных зависимостей проверьте источник: официальный репозиторий проекта, а не зеркало или сторонний пакет с похожим названием (типичный приём supply-chain-атак — тайпсквоттинг).
Для образов, которые вы собираете сами, тот же порядок применяется на этапе CI: генерация SBOM и сканирование встраиваются в конвейер, и сборка с критичными уязвимостями блокируется до публикации.
Минимизация поверхности: меньше пакетов — меньше проверок
Проверка происхождения эффективнее, когда проверять нужно меньше. Практика, которая напрямую снижает риски цепочки поставок:
- Минимальные базовые образы. Дистрибутивы без пакетного менеджера и оболочки (например, distroless-образы или образы на основе scratch) содержат на порядок меньше компонентов, и SBOM для них короткий и проверяемый.
- Фиксация версий. Используйте конкретные версии и дайджесты вместо плавающих тегов. Обновления проводите контролируемо, с повторной проверкой.
- Фиксация зависимостей сборки. Файлы блокировки (lock-файлы) и проверка хешей пакетов в пакетных менеджерах защищают от подмены зависимостей при сборке.
- Один источник истины. Собирайте образы из одного доверенного конвейера, а не позволяйте разработчикам собирать и публиковать их вручную.
Эти меры не заменяют криптографические проверки, но уменьшают объём того, что нужно проверять, и упрощают реакцию на инциденты.
Типичные ошибки при проверке происхождения
- Проверка по тегу вместо дайджеста. Тег можно перепубликовать; подпись, проверенная по тегу, может относиться к другому содержимому. Всегда привязывайтесь к sha256-дайджесту.
- Разовая проверка. Подпись проверили при внедрении и забыли. Образы в реестре меняются; проверки должны выполняться автоматически при каждом развёртывании.
- Слепое доверие к «официальным» образам. Официальность репозитория — это репутационная, а не криптографическая гарантия. Наличие подписей и SBOM у издателя стоит проверять явно.
- Игнорирование базового образа. Вы проверили свой слой, а уязвимость сидит в базовом образе. SBOM и сканирование должны покрывать весь образ целиком.
- Подпись без политики. Если подписи проверяются вручную и необязательно, рано или поздно образ пройдёт без проверки. Автоматизируйте отклонение неподписанных образов.
- Избыточная строгость на старте. Попытка внедрить сразу все уровни SLSA и жёсткие политики часто ломает процессы, и команду откатывают назад. Разумнее вводить проверки поэтапно: сначала подпись и сканирование, затем provenance.
Как встроить проверки в процесс: поэтапный план
- Инвентаризация. Составьте перечень образов, которые вы используете, и зафиксируйте их дайджесты. Без списка защищать нечего.
- Сканирование. Включите сканер уязвимостей в CI и в реестр образов. Определите порог блокировки: например, критичные CVE с публичным эксплойтом останавливают публикацию.
- Подпись своих образов. Настройте автоматическую подпись в CI и хранение подписей в реестре.
- Проверка чужих образов. Для сторонних образов определите требование: подпись обязательна, идентичность подписавшего сверяется со списком доверенных издателей.
- Политика на входе. Подключите admission-контроллер, отклоняющий неподписанные или непрошедшие проверку образы. Начните с режима аудита (логирование без блокировки), затем переключитесь на блокировку.
- SBOM и provenance. Добавьте генерацию SBOM в свои сборки и требуйте provenance от критичных поставщиков. Настройте регулярную сверку SBOM с новыми CVE.
- Аудит и обновления. Периодически перепроверяйте работающие образы и обновляйте базовые образы по контролируемому графику, а не по факту инцидента.
Сценарии: что делать в разных условиях
Вы используете публичные образы без подписей. Проверьте, публикует ли издатель подписи и SBOM (многие крупные проекты публикуют). Если нет — рассмотрите сборку образа самостоятельно из официальных исходников с собственной подписью, либо примите риск осознанно и компенсируйте его сканированием, минимальными привилегиями и сетевой изоляцией.
Вы собираете образы сами. Внедрите подпись, SBOM и provenance в CI. Это самый управляемый сценарий: вы контролируете и состав, и процесс сборки.
Вы в регулируемой отрасли. Требования к цепочке поставок ПО ужесточаются в ряде юрисдикций, и SBOM всё чаще запрашивают заказчики и регуляторы. Уточните актуальные требования для вашей отрасли и региона — они меняются, и универсального списка нет.
Небольшая команда без выделенной безопасности. Начните с трёх вещей: фиксация дайджестов вместо тегов, сканер уязвимостей в CI и подпись собственных образов. Это даёт основную часть пользы при минимальных затратах.
Частые вопросы
Достаточно ли проверки дайджеста образа без подписи?
Дайджест защищает от случайного расхождения между тегом и содержимым и от подмены после того, как вы зафиксировали дайджест. Но он не подтверждает, кто опубликовал содержимое изначально. Дайджест — необходимый минимум, подпись — следующий уровень.
Нужно ли проверять подписи образов, которые уже работают в кластере?
Проверка на входе (admission) закрывает основной сценарий, но периодическая перепроверка работающих образов полезна: она выявляет образы, добавленные в обход политики, и изменения в реестре.
SBOM или сканер уязвимостей — что важнее?
Это разные инструменты. Сканер отвечает «что из известного плохого есть сейчас», SBOM — «что вообще внутри». SBOM ценнее на дистанции: он позволяет мгновенно оценивать каждую новую уязвимость без повторного анализа образов.
Что делать, если критичная зависимость не обновляется?
Оцените реальную эксплуатируемость уязвимости в вашем контексте: используется ли уязвимый компонент, доступен ли он извне. Если риск неприемлем, варианты — изолировать компонент, заменить его, наложить временную компенсирующую меру или перейти на альтернативную библиотеку.
С чего начать прямо сейчас
Главный принцип проверки происхождения: доверяй, но проверяй криптографически, и делай это автоматически. Наибольшее влияние на результат оказывают три условия: привязка к дайджестам вместо тегов, обязательная автоматическая проверка подписей при развёртывании и регулярное сканирование полного состава образа, включая базовый слой.
Конкретный первый шаг: составьте список образов в продакшене с их дайджестами и проверьте, публикуют ли их издатели подписи, provenance и SBOM. По результатам станет ясно, какие образы можно принять как есть, какие — пересобрать самостоятельно, а от каких — отказаться. Затем автоматизируйте проверки, чтобы они выполнялись при каждом развёртывании, а не по памяти.
