После SolarWinds пересматриваем CI/CD: Trivy, gitleaks и SBOM через Syft
SolarWinds заставил пересмотреть что именно собирается в образ. Добавляем Trivy для сканирования, gitleaks для secrets detection и Syft для генерации SBOM прямо в pipeline.
SolarWinds усиливает интерес к DevSecOps и встраиванию безопасности в CI/CD на всех этапах
После того как мы разобрали playbook реагирования на supply chain атаку и поговорили с несколькими клиентами о том, что произошло с SolarWinds, у нас образовался неудобный вопрос к собственному пайплайну: а что именно попадает в наши образы? Не в теории, а конкретно - какие пакеты, какие версии, есть ли в них известные CVE, и нет ли в репозиториях секретов, которые туда залетели по ошибке три года назад?
Ответа у нас не было. Точнее, был частичный: SAST мы включили ещё в августе, но это анализ кода, не образов и не зависимостей сборочного процесса. SolarWinds ударил именно по другому слою: доверенный пакет, легитимная подпись, официальный канал доставки - и никакой SAST это не поймал бы.
Решили закрыть пробел. Добавили три инструмента.
Trivy: сканирование образов
Trivy от Aqua Security - сканер уязвимостей для контейнерных образов. Работает локально, без внешних зависимостей, умеет проверять пакеты OS-слоя, библиотеки языков (pip, npm, gem, cargo), и показывает CVE с severity и ссылками.
В pipeline добавили как отдельный stage после docker build:
scan-image:
stage: security
image: aquasec/trivy:0.12.0
script:
- trivy image
--exit-code 1
--severity HIGH,CRITICAL
--no-progress
$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
allow_failure: false
--exit-code 1 при HIGH/CRITICAL - pipeline падает. Это намеренно: у нас не было накопленного долга, мы добавляли Trivy в проекты, где уже был более-менее чистый базовый образ. В проектах с легаси-образами на ubuntu:16.04 так делать нельзя - получишь стену из Medium и сразу же выключишь обратно. Там разумнее начинать с --severity CRITICAL и allow_failure: true, смотреть на результаты, разбирать постепенно.
Первый прогон на боевых образах дал неожиданное: несколько HIGH в системных пакетах, которые тянулись через apt-get install без явных версий. Образ собирался с FROM debian:buster, и в нём оказались curl и libssl версий с известными CVE. Обновление до debian:buster-20201209 закрыло большую часть.
Важный момент с Trivy: он работает на момент сборки. CVE, которую внесут в базу завтра, сегодняшний скан не покажет. Это не недостаток инструмента, это свойство подхода: регулярные пересборки базовых образов - часть процесса, не опциональная.
gitleaks: secrets detection
Второй инструмент - gitleaks. Ищет в истории git-репозитория паттерны, похожие на секреты: ключи AWS, токены, приватные ключи, строки подключения к БД. Работает не только по текущему состоянию, а по всей истории коммитов.
secrets-scan:
stage: security
image: zricethezav/gitleaks:v6.1.2
script:
- gitleaks
--path=.
--verbose
--redact
--report=gitleaks-report.json
artifacts:
when: always
paths:
- gitleaks-report.json
expire_in: 7 days
allow_failure: true
allow_failure: true здесь сознательно: в нескольких репозиториях при первом запуске нашлись исторические срабатывания, которые оказались тестовыми данными, залитыми два года назад. Бросать pipeline нельзя - нужен ручной разбор.
Из реальных находок: в одном репозитории в коммите двухлетней давности обнаружился хардкод access key, который на тот момент уже был отозван. Хорошо что отозван. Но факт в том, что он там был и мы об этом не знали. Секрет из истории git убрать нельзя без переписывания истории - это отдельная процедура с git filter-branch или bfg. Здесь мы её провели, заодно убедились что ключ действительно не активен.
Для .gitleaks.toml можно настроить исключения для конкретных файлов или паттернов:
[allowlist]
description = "Allowlist"
paths = [
'''tests/fixtures''',
'''\.gitleaks\.toml'''
]
regexes = [
'''EXAMPLE_KEY_DO_NOT_USE'''
]
Syft: SBOM-генерация
Третий и самый «долгосрочный» в смысле полезности - Syft от Anchore. Генерирует Software Bill of Materials: список всего, что есть в образе, с версиями, лицензиями и координатами.
generate-sbom:
stage: security
image: anchore/syft:v0.4.0
script:
- syft $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
-o json > sbom-$CI_COMMIT_SHA.json
- syft $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
-o table
artifacts:
paths:
- sbom-$CI_COMMIT_SHA.json
expire_in: 30 days
Зачем это нужно, если уже есть Trivy? Разные задачи. Trivy отвечает на вопрос «есть ли известные CVE прямо сейчас». Syft отвечает на вопрос «что именно здесь есть» - и этот ответ нужен независимо от того, есть CVE или нет. SBOM - это инвентарь. Если завтра выйдет новая критическая уязвимость в какой-то библиотеке, по SBOM можно моментально понять, в каких именно образах она присутствует, вместо того чтобы пересканировать всё.
С учётом SUNBURST: именно документирования зависимостей и не хватало у жертв атаки. Никто точно не знал, что конкретно поставляет SolarWinds Orion, какие DLL входят в состав. SBOM как стандартная практика - это ответ на этот вопрос для собственных систем.
Как это выглядит в пайплайне целиком
build -> scan-image (Trivy) -> generate-sbom (Syft)
-> secrets-scan (gitleaks, параллельно)
-> push (только если scan-image прошёл)
gitleaks идёт параллельно со сборкой - он анализирует репозиторий, а не образ, и не зависит от результата docker build. Trivy и Syft - после сборки. Push только если Trivy чистый.
Что в итоге
Три инструмента, добавленные за последние две недели, дали нам:
- Список CVE в каждом образе на момент сборки, с блокировкой по HIGH/CRITICAL.
- Историческую проверку репозиториев на секреты - нашли несколько артефактов прошлых лет.
- SBOM как инвентарь сборочных зависимостей, хранящийся рядом с артефактом.
Это не серебряная пуля против supply chain атак - SUNBURST прошёл бы и через это, потому что атака шла на уровне легитимного вендора, а не через известные CVE. Но это нижняя планка, ниже которой работать уже некомфортно. Документировать зависимости, проверять образы, мониторить секреты - это не паранойя после инцидента, это просто часть нормальной сборочной гигиены.
Если хотите посмотреть на состояние своего пайплайна - аудит сборочного процесса, как правило, занимает день и даёт конкретный список что добавить и в каком порядке.