ADG Оставить заявку
Блог DevOps 5 мин чтения

SBOM в GitFlic CI: генерация, подпись и хранение артефактов под требования ФСТЭК

ФСТЭК рекомендует SBOM как меру защиты для разработчиков ПО для КИИ. Настраиваем генерацию и подпись в GitFlic CI, разбираем форматы и интеграцию с CMDB.

Контекст момента

ФСТЭК рекомендует внедрение SBOM как обязательную меру защиты для разработчиков ПО для КИИ

ФСТЭК на прошлой неделе выпустил методические рекомендации, в которых SBOM (Software Bill of Materials) фигурирует уже не как опциональная практика, а как обязательная защитная мера для организаций, разрабатывающих ПО для объектов КИИ. До этого момента нас регулярно спрашивали клиенты: «А зачем нам SBOM, если мы всё равно не публикуем open source?» Теперь ответ на этот вопрос дал сам регулятор, что значительно упрощает внутренние переговоры.

Что именно ФСТЭК имеет в виду

В рекомендациях фигурируют два требования, которые касаются нас напрямую. Первое - наличие актуального перечня компонентов для каждой версии ПО, поставляемого на объект КИИ. Второе - возможность проверить целостность этого перечня, то есть убедиться, что он не был модифицирован после формирования.

С точки зрения форматов регулятор называет CycloneDX и SPDX как приемлемые - оба в формате JSON или XML. SPDX исторически чаще встречается в «бумажных» требованиях американских вендоров, CycloneDX проще интегрируется с инструментарием анализа уязвимостей. Мы в итоге остановились на CycloneDX JSON как основном формате: он компактнее, хорошо читается Grype и Dependency-Track.

GitFlic CI: откуда стартовали

Большинство наших клиентов на КИИ к этому моменту уже мигрировали с GitHub/GitLab на GitFlic - это стало нормой после соответствующих требований регулятора в 2023-2024 годах. GitFlic CI по функциональности близок к GitLab CI с поправкой на то, что часть плагинной экосистемы там своя, часть вообще отсутствует.

Хорошая новость: Syft и Cosign, которые мы используем для генерации и подписи SBOM, - это просто бинарники. Их можно положить в образ раннера или подтянуть в pipeline как артефакты. GitFlic это не ограничивает.

Что мы настроили в pipeline

Шаг SBOM-генерации выглядит примерно так:

sbom-generate:
  stage: security
  image: registry.internal/devtools/syft:latest
  script:
    - syft packages dir:. --output cyclonedx-json=sbom.cdx.json
    - syft packages dir:. --output spdx-json=sbom.spdx.json
  artifacts:
    paths:
      - sbom.cdx.json
      - sbom.spdx.json
    expire_in: 1 year

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

Подпись. Здесь пришлось немного повозиться. Cosign поддерживает несколько режимов подписи; в изолированном контуре без доступа к Sigstore мы используем режим с ключевой парой:

sbom-sign:
  stage: security
  image: registry.internal/devtools/cosign:latest
  needs: [sbom-generate]
  script:
    - cosign sign-blob --key env://COSIGN_PRIVATE_KEY
        --output-signature sbom.cdx.json.sig
        sbom.cdx.json
  artifacts:
    paths:
      - sbom.cdx.json.sig
    expire_in: 1 year

COSIGN_PRIVATE_KEY - переменная из хранилища секретов GitFlic, ключ генерируется один раз и хранится там. Публичный ключ - в репозитории рядом с политикой подписи. Проверка при получении: cosign verify-blob --key cosign.pub --signature sbom.cdx.json.sig sbom.cdx.json.

Это не keyless Sigstore, но для изолированного контура это единственный рабочий вариант. ФСТЭК в рекомендациях не требует конкретного механизма подписи, лишь «возможность проверки целостности» - мы эту галку закрываем.

Хранение и CMDB

Артефакты в GitFlic CI живут в хранилище самого GitFlic - это удобно для разработчиков, но не очень удобно для инвентаризации. CMDB не умеет ходить в GitFlic API за SBOM-артефактами сама по себе.

Мы решили это простым шагом в pipeline - после генерации и подписи SBOM отправляется в Nexus Repository, где лежит в отдельном raw-репозитории по схеме {project}/{version}/sbom.cdx.json. Nexus умеют опрашивать и Dependency-Track, и несколько CMDB-систем через REST.

Dependency-Track в нашей конфигурации играет роль промежуточного слоя: принимает SBOM, анализирует состав на предмет CVE (используя локально загруженные базы NVD и OSV), ведёт историю версий. Из Dependency-Track уже по API данные о компонентах уходят в CMDB - как список артефактов, лицензий и известных уязвимостей на момент сборки.

Это не real-time инвентаризация, но для целей аудита - вполне: проверяющий может получить состав любой задеплоенной версии и убедиться, что SBOM не редактировался после подписи.

Что не заработало с первого раза

Syft генерирует SBOM из того, что видит в файловой системе: package.json, go.sum, requirements.txt, pom.xml. Если зависимости подтягиваются в момент сборки внутри docker build, а pipeline работает с исходниками - Syft их не видит. Для Java-проектов с fat JAR нам пришлось добавить отдельный шаг: сначала собрать артефакт, потом прогнать Syft по нему как по директории.

Второй момент - транзитивные зависимости. CycloneDX-формат умеет описывать дерево зависимостей, Syft это поддерживает, но по умолчанию выдаёт плоский список. Для полного дерева нужен флаг --scope all-layers при работе с образами или настройка через syft.yaml. Без этого SBOM технически валидный, но неполный.

Где сейчас стоит точка

Рекомендации ФСТЭК - это рекомендации, а не требования НПА. Пока что. Но по нашему опыту, расстояние между «рекомендует» и «проверяет» у регулятора не очень большое, и готовить почву лучше сейчас, чем объяснять на проверке, почему ничего не сделано.

Весь описанный стек - Syft, Cosign, Dependency-Track, Nexus - работает в изолированном контуре без внешнего интернета, что для КИИ принципиально. Интеграция с конкретной CMDB требует индивидуальной настройки, но базовый pipeline занимает день-два в рамках аудита и настройки DevSecOps-процессов.

Тема SBOM-дифференцирования между версиями (что изменилось в составе с прошлого релиза) - отдельная история, которую мы пока только пробуем автоматизировать.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.