Пиков / КАПО
Как читать авторский курс и нормативные материалы

Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин OSA в разных материалах имеет разный охват. Статус и обязательность нормативного документа проверяются отдельно; проект КАПО опубликован как проект первой редакции.

П15. SLSA и in-toto provenance

Чем provenance отличается от подписи SBOM В П14. Подпись SBOM через Sigstore мы подтверждали что лежит в артефакте (состав). Provenance отвечает на другой вопрос — как и где артефакт был собран: какой исходник (commit), какой builder, какой workflow, с какими параметрами. SLSA задаёт уровни зрелости этой гарантии, а in-toto — формат самого attestation (predicateType: https://slsa.dev/provenance/v1). Цель практики — не просто получить provenance, а проверить его привязку к исходнику, иначе любой может приложить provenance от чужой сборки.

Цель

Получить и верифицировать SLSA build provenance для собранного артефакта: provenance выпущен доверенным builder'ом, оформлен как in-toto attestation, а slsa-verifier подтверждает, что артефакт собран из заявленного source-uri и (опционально) указанным workflow/tag. Проверяемый результат — артефакт, который проходит verify с явным указанием ожидаемого источника, и при подмене источника verify падает.

Команда или действие

Сценарий: артефакт собран в GitHub Actions через официальный SLSA-генератор (slsa-framework/slsa-github-generator), который положил рядом файл *.intoto.jsonl — это DSSE-конверт с provenance, подписанный keyless через Fulcio/Rekor.

# 1. Установить slsa-verifier (Go-инструмент)
go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@latest

# 2. Проверить артефакт против provenance + ожидаемого источника.
#    --source-uri и --source-tag — это контроль: verify проходит, только если
#    provenance действительно ссылается на этот репозиторий и тег.
slsa-verifier verify-artifact app-linux-amd64 \
  --provenance-path app-linux-amd64.intoto.jsonl \
  --source-uri github.com/<github-owner>/<repository> \
  --source-tag v1.4.0

# 3. Посмотреть, что внутри provenance (decoded in-toto statement)
jq -r '.payload' app-linux-amd64.intoto.jsonl | base64 -d | jq '{
  predicateType,
  subject,
  builder: .predicate.runDetails.builder.id,
  invocation: .predicate.buildDefinition.externalParameters
}'

Для контейнерных образов provenance проверяется по digest:

TRUSTED_BUILDER_ID='<trusted-builder-id-from-provenance-policy>'

slsa-verifier verify-image ghcr.io/org/app@sha256:<digest> \
  --source-uri github.com/<github-owner>/<repository> \
  --builder-id "$TRUSTED_BUILDER_ID"

--builder-id — это строковый идентификатор builder из provenance, а не браузерная ссылка. Значение с @refs/tags/... проверяют как часть доверенной политики: оно должно совпадать с заранее разрешённым builder'ом и версией workflow. Для официального GitHub container generator сверяйте семейство builder'а с workflow в репозитории slsa-framework/slsa-github-generator: https://github.com/slsa-framework/slsa-github-generator/blob/main/.github/workflows/generator_container_slsa3.yml.

--source-uri обязателен по смыслу, даже если формально опционален verify без --source-uri подтверждает только то, что provenance подписан и не повреждён — но не то, что артефакт собран из вашего кода. Атакующий с собственным валидным pipeline получит валидное provenance на свой форк. Привязка к источнику (и по возможности к тегу/builder-id) — это и есть граница доверия, ради которой существует SLSA.

Что вы должны увидеть

Успешный verify-artifact заканчивается строкой PASSED:

Verified signature against tlog entry index 88241039 ...
Verified build using builder "https://github.com/slsa-framework/slsa-github-generator/..." at commit a1b2c3d...
Verifying artifact app-linux-amd64: PASSED

PASSED: SLSA verification passed

Декодированный in-toto statement (шаг 3) — это provenance v1 со следующим скелетом:

{
  "predicateType": "https://slsa.dev/provenance/v1",
  "subject": [
    { "name": "app-linux-amd64", "digest": { "sha256": "<digest>" } }
  ],
  "builder": "https://github.com/slsa-framework/slsa-github-generator/.github/workflows/...",
  "invocation": {
    "workflow": {
      "ref": "refs/tags/v1.4.0",
      "repository": "github.com/<github-owner>/<repository>"
    }
  }
}

Ориентир: subject.digest.sha256 обязан совпадать с sha256sum app-linux-amd64. Если хеши расходятся — verify не дойдёт до PASSED, потому что проверяется именно тот артефакт, что лежит на диске.

Если не получилось

Типичные ошибки и как их распознать - FAILED: expected source ... got ... — provenance ссылается на другой репозиторий, чем указан в --source-uri. Это сработавший контроль, а не сбой: либо опечатка в URI, либо артефакт собран не из вашего источника. Не «лечите» это удалением --source-uri. - FAILED: artifact hash does not match provenance subject — вы проверяете не тот файл (например, пересобрали локально, а provenance от релизного артефакта). Сверьте sha256sum с subject.digest. - no matching signatures / ошибка Rekor — provenance не был залогирован в transparency log или повреждён .intoto.jsonl. Скачайте артефакт и provenance заново из release/registry, не редактируйте jsonl вручную. - unexpected builderID при verify-image — образ собран не тем builder'ом, который вы указали в --builder-id. Уточните builder из самого provenance (.predicate.runDetails.builder.id) и сверьте, что он доверенный, а не подставленный.

Критерий зачёта

Показать преподавателю: 1. Вывод slsa-verifier verify-artifact (или verify-image) со строкой PASSED и заполненными --source-uri/--source-tag. 2. Декодированный provenance с predicateType: https://slsa.dev/provenance/v1, где subject.digest.sha256 совпадает с локальным sha256sum. 3. Отрицательный тест: тот же verify с заведомо неверным --source-uri (например, github.com/org/fork) — он должен дать FAILED. Это доказывает, что проверка реально работает, а не «всегда зелёная». 4. Устно: чем provenance (как собрано) дополняет подпись SBOM (что внутри) из П14. Подпись SBOM через Sigstore.

Нормативная связка