• Русский
  • Проверка происхождения системы сборки

    В SLSA provenance есть поле builder.id, которое используется для указания среды сборки образа.

    В этом документе мы будем использовать это поле builder.id для проверки образа.

    TIP

    Поскольку Tekton Chains уже выполняет и подпись образов, и генерацию SLSA provenance на этапе подготовки, мы можем напрямую повторно использовать процесс и образы из Quick Start: Signed Provenance.

    В этом документе мы сосредоточимся на проверке SLSA provenance.

    Обзор функциональности

    Этот метод использует Chains для автоматической генерации SLSA Provenance для собранного образа, а затем Kyverno — для проверки provenance:

    1. Настройте Tekton Chains на автоматическую генерацию SLSA Provenance для собранного образа.
    2. Используйте Tekton Task buildah для сборки образа.
    3. (Необязательно) Используйте cosign CLI для проверки attestation.
    4. Настройте правила Kyverno для проверки attestation.
    5. Используйте образ для создания Pod, чтобы проверить attestation.

    Сценарии использования

    Следующие сценарии требуют обращения к рекомендациям в этом документе:

    • Проверка среды сборки контейнерных образов с использованием SLSA provenance
    • Реализация проверки происхождения системы сборки с использованием политик CUE или Rego
    • Применение политик безопасности, разрешающих только образы, собранные в определённых средах сборки
    • Настройка автоматической проверки происхождения системы сборки в CI/CD pipeline
    • Обеспечение целостности и подлинности происхождения системы сборки в production-средах

    Предварительные требования

    • Кластер Kubernetes, в котором установлены Tekton Pipelines, Tekton Chains и Kyverno
    • Registry с включённой возможностью push образов
    • Установленный и настроенный для доступа к кластеру CLI kubectl
    • Установленный CLI-инструмент cosign
    • Установленный CLI-инструмент jq

    Обзор процесса

    ШагОперацияОписание
    1Сгенерировать ключи подписиСоздать пару ключей для подписи артефактов с помощью cosign
    2Настроить аутентификациюНастроить учётные данные registry для push образов
    3Настроить Tekton ChainsПодготовить Chains для использования OCI storage и настроить подпись
    4Создать пример pipelineСоздать определение pipeline с необходимыми task и workspace
    5Запустить пример pipelineСоздать и запустить PipelineRun с корректной конфигурацией
    6Дождаться подписиДождаться, пока PipelineRun будет подписан Chains
    7Получить информацию об образеИзвлечь URI и digest образа из PipelineRun
    8(Необязательно) Проверить подписи с cosignПроверить attestation образа с помощью CLI cosign
    9Проверить подписи с KyvernoНастроить и проверить attestation образа с помощью политик Kyverno
    10Очистить ресурсыУдалить тестовые Pod и политики

    Пошаговые инструкции

    Шаги 1–7: (Необязательно) Базовая настройка

    NOTE

    Если вы измените поле builder.id, вам нужно повторно запустить pipeline, чтобы сгенерировать образ. Потому что старый образ не подписан новым builder.id, поэтому он будет заблокирован политикой.

    В противном случае вы можете пропустить этот шаг и использовать старый образ для проверки политики.

    Эти шаги идентичны руководству Quick Start: Signed Provenance. Следуйте инструкциям из этого руководства для:

    Шаг 8: (Необязательно) Проверить информацию о builder с помощью cosign

    TIP

    Этот шаг необязателен и выполняется, когда вам нужно проверить подлинность builder образа с помощью cosign.

    Если вам интересно, как использовать CUE или Rego для проверки информации о builder, вы можете продолжить чтение следующего содержимого.

    Получите открытый ключ подписи согласно разделу Получить открытый ключ подписи.

    Cosign предоставляет два способа проверки attestation:

    Ниже будут показаны методы проверки для этих двух способов.

    Способ 1: Использовать CUE для проверки

    Сгенерируйте CUE-файл для проверки информации о builder.

    // The predicate must match the following constraints.
    predicate: {
        builder: {
            id: "https://alauda.io/builders/tekton/v1"
        }
    }

    Сохраните CUE-файл как builder.cue

    Проверьте информацию о builder с помощью cosign.

    # Disable tlog upload and enable private infrastructure
    $ export COSIGN_TLOG_UPLOAD=false
    $ export COSIGN_PRIVATE_INFRASTRUCTURE=true
    
    $ export IMAGE=<<registry>/test/chains/demo-1:latest@sha256:93635f39cb31de5c6988cdf1f10435c41b3fb85570c930d51d41bbadc1a90046>
    
    $ cosign verify-attestation --key cosign.pub --type slsaprovenance --policy builder.cue $IMAGE

    Если вы получаете вывод, подобный следующему, это означает, что проверка информации о builder выполнена успешно.

    will be validating against CUE policies: [builder.cue]
    will be validating against CUE policies: [builder.cue]
    
    Verification for <registry>/test/chains/demo-1:latest@sha256:8ac1af8dd89652bf32abbbd0c5f667ae9fe6d92c91972617e70b5398303c8e27 --
    The following checks were performed on each of these signatures:
      - The cosign claims were validated
      - The signatures were verified against the specified public key
    {"payloadType":"application/vnd.in-toto+json","payload":"","signatures":[]}

    Измените builder.id в файле builder.cue на другое значение https://alauda.io/builders/tekton/v2 и повторите проверку.

    $ cosign verify-attestation --key cosign.pub --type slsaprovenance --policy builder.cue $IMAGE

    Если вы получаете вывод, подобный следующему, это означает, что проверка информации о builder не выполнена.

    will be validating against CUE policies: [builder.cue]
    will be validating against CUE policies: [builder.cue]
    There are 2 number of errors occurred during the validation:
    
    - predicate.builder.id: conflicting values "https://alauda.io/builders/tekton/v1" and "https://alauda.io/builders/tekton/v2"
    - predicate.builder.id: conflicting values "https://alauda.io/builders/tekton/v1" and "https://alauda.io/builders/tekton/v2"
    Error: 2 validation errors occurred
    error during command execution: 2 validation errors occurred

    Способ 2: Использовать Rego для проверки

    Сгенерируйте Rego-файл для проверки информации о builder.

    package signature
    
    default allow = false
    
    # Define the allowed builder.id
    allowed_builder_id = "https://alauda.io/builders/tekton/v1"
    
    # Verify the builder.id
    allow {
        # Check if the builder.id in the predicate is equal to the allowed value
        input.predicate.builder.id == allowed_builder_id
    }
    
    # Return error message when not match
    deny[msg] {
        input.predicate.builder.id != allowed_builder_id
        msg := sprintf("unexpected builder.id: %v, expected: %v", [input.predicate.builder.id, allowed_builder_id])
    }

    Сохраните Rego-файл как builder.rego

    Проверьте информацию о builder с помощью cosign.

    # Disable tlog upload and enable private infrastructure
    $ export COSIGN_TLOG_UPLOAD=false
    $ export COSIGN_PRIVATE_INFRASTRUCTURE=true
    
    $ export IMAGE=<<registry>/test/chains/demo-1:latest@sha256:93635f39cb31de5c6988cdf1f10435c41b3fb85570c930d51d41bbadc1a90046>
    
    $ cosign verify-attestation --key cosign.pub --type slsaprovenance --policy builder.rego $IMAGE

    Если вы получаете вывод, подобный следующему, это означает, что проверка информации о builder выполнена успешно.

    will be validating against Rego policies: [builder.rego]
    will be validating against Rego policies: [builder.rego]
    
    Verification for <registry>/test/chains/demo-1:latest --
    The following checks were performed on each of these signatures:
      - The cosign claims were validated
      - The signatures were verified against the specified public key
    {"payloadType":"application/vnd.in-toto+json","payload":"","signatures":[]}

    Измените builder.id в файле builder.rego на другое значение https://alauda.io/builders/tekton/v2 и повторите проверку.

    $ cosign verify-attestation --key cosign.pub --type slsaprovenance --policy builder.rego $IMAGE

    Если вы получаете вывод, подобный следующему, это означает, что проверка информации о builder не выполнена.

    will be validating against Rego policies: [builder.rego]
    will be validating against Rego policies: [builder.rego]
    There are 2 number of errors occurred during the validation:
    
    - expression value, false, is not true
    - expression value, false, is not true
    Error: 2 validation errors occurred
    error during command execution: 2 validation errors occurred

    Шаг 9: Проверить подпись с помощью Kyverno

    TIP

    Для этого шага требуются привилегии администратора кластера.

    Содержимое provenance примерно следующее; мы будем использовать поле builder.id для проверки среды сборки.

    {
      "_type": "https://in-toto.io/Statement/v0.1",
      "predicateType": "https://slsa.dev/provenance/v0.2",
      "predicate": {
        "buildType": "tekton.dev/v1beta1/TaskRun",
        "builder": {
          "id": "https://alauda.io/builders/tekton/v1"
        },
        "materials": [
          {
            "digest": {
              "sha256": "8d5ea9ecd9b531e798fecd87ca3b64ee1c95e4f2621d09e893c58ed593bfd4c4"
            },
            "uri": "oci://<registry>/devops/tektoncd/hub/buildah"
          }
        ],
        "metadata": {
          "buildFinishedOn": "2025-06-06T10:21:27Z",
          "buildStartedOn": "2025-06-06T10:20:55Z"
        }
      }
    }

    Шаг 9.1: Создать политику Kyverno, разрешающую к развёртыванию только образы, собранные в определённых средах сборки

    TIP

    Более подробную информацию о Kyverno ClusterPolicy см. в Kyverno ClusterPolicy

    Политика выглядит следующим образом:

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: verify-tekton-built-images
    spec:
      webhookConfiguration:
        failurePolicy: Fail
        timeoutSeconds: 30
      background: false
      rules:
        - name: check-image
          match:
            any:
              - resources:
                  kinds:
                    - Pod
                  namespaces:
                    - policy
          verifyImages:
            - imageReferences:
                - "*"
                # - "<registry>/test/*"
              skipImageReferences:
                - "ghcr.io/trusted/*"
              failureAction: Enforce
              verifyDigest: false
              required: false
              useCache: false
              imageRegistryCredentials:
                allowInsecureRegistry: true
                secrets:
                  # The credential needs to exist in the namespace where kyverno is deployed
                  - registry-credentials
    
              attestations:
                - type: https://slsa.dev/provenance/v0.2
                  attestors:
                    - entries:
                        - keys:
                            publicKeys: |- # <- The public key of the signer
                              -----BEGIN PUBLIC KEY-----
                              MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFZNGfYwn7+b4uSdEYLKjxWi3xtP3
                              UkR8hQvGrG25r0Ikoq0hI3/tr0m7ecvfM75TKh5jGAlLKSZUJpmCGaTToQ==
                              -----END PUBLIC KEY-----
    
                            ctlog:
                              ignoreSCT: true
    
                            rekor:
                              ignoreTlog: true
                  conditions:
                    - all:
                        - key: "{{ builder.id }}"
                          operator: Equals
                          value: "https://alauda.io/builders/tekton/v1"
                          message: "The builder.id must be equal to https://alauda.io/builders/tekton/v1, not {{ builder.id }}"
    Пояснение полей YAML
    • Эта политика в целом соответствует политике из Проверка подписи образа. Ниже описаны только различия.
    • spec.rules[0].verifyImages[].attestations[0].conditions
      • type: тип SLSA provenance — это https://slsa.dev/provenance/v0.2 или https://slsa.dev/provenance/v1.
      • attestors: то же самое, что и выше.
      • conditions: условия, которые необходимо проверить.
        • all: должны быть выполнены все условия.
          • key: "{{ builder.id }}": эта проверка убеждается, что поле builder.id в attestation равно https://alauda.io/builders/tekton/v1

    Необходимо скорректировать конфигурацию

    • spec.rules[].attestors[].entries[].keys.publicKeys: открытый ключ подписанта.

    Сохраните политику в YAML-файл с именем kyverno.verify-tekton-built-images.yaml и примените её:

    $ kubectl apply -f kyverno.verify-tekton-built-images.yaml
    
    clusterpolicy.kyverno.io/verify-tekton-built-images configured

    Шаг 9.2: Проверить политику

    В пространстве имён policy, где определена политика, создайте Pod для проверки политики.

    Используйте собранный образ для создания Pod.

    $ export NAMESPACE=<policy>
    $ export IMAGE=<<registry>/test/chains/demo-1:latest@sha256:93635f39cb31de5c6988cdf1f10435c41b3fb85570c930d51d41bbadc1a90046>
    
    $ kubectl run -n $NAMESPACE built --image=${IMAGE} -- sleep 3600
    
    pod/built created

    Pod будет создан успешно.

    $ kubectl get pod -n $NAMESPACE built
    
    NAME      READY   STATUS    RESTARTS   AGE
    built   1/1     Running   0          10s

    Измените builder.id в ClusterPolicy на другое значение https://alauda.io/builders/tekton/v2 и повторите проверку.

    conditions:
      - all:
          - key: "{{ builder.id }}"
            operator: Equals
            value: "https://alauda.io/builders/tekton/v2"
            message: "The builder.id must be equal to https://alauda.io/builders/tekton/v2, not {{ builder.id }}"
    $ kubectl run -n $NAMESPACE unbuilt --image=${IMAGE} -- sleep 3600

    Если вы получаете вывод, подобный следующему, это означает, что Pod заблокирован политикой.

    Error from server: admission webhook "mutate.kyverno.svc-fail" denied the request:
    
    resource Pod/policy/unbuilt was blocked due to the following policies
    
    verify-tekton-built-images:
      check-image: 'image attestations verification failed, verifiedCount: 0, requiredCount:
        1, error: .attestations[0].attestors[0].entries[0].keys: attestation checks failed
        for <registry>/test/chains/demo-1@sha256:93635f39cb31de5c6988cdf1f10435c41b3fb85570c930d51d41bbadc1a90046
        and predicate https://slsa.dev/provenance/v0.2: The builder.id must be equal to
        https://alauda.io/builders/tekton/v2, not https://alauda.io/builders/tekton/v1'

    Шаг 10: Очистка ресурсов

    Удалите Pod, созданные на предыдущих шагах.

    $ export NAMESPACE=<policy>
    $ kubectl delete pod -n $NAMESPACE built

    Удалите политику.

    $ kubectl delete clusterpolicy verify-tekton-built-images

    Ожидаемые результаты

    После выполнения этого руководства:

    • У вас будет рабочая настройка Tekton Chains для генерации SLSA provenance
    • Ваши контейнерные образы будут автоматически подписываться provenance системы сборки во время процесса сборки
    • Вы сможете проверять среду сборки образов с помощью политик CUE или Rego
    • Только образы, собранные в указанной среде сборки, можно будет развёртывать в указанном namespace
    • Образы, собранные в неавторизованных средах сборки, будут автоматически блокироваться политиками Kyverno
    • Вы реализуете базовый контроль проверки происхождения системы сборки для ваших контейнерных образов

    Это руководство даёт основу для внедрения проверки происхождения системы сборки в ваших CI/CD pipeline. В production-среде вам следует:

    1. Настроить корректную изоляцию namespace и контроль доступа
    2. Реализовать безопасное управление ключами для ключей подписи
    3. Настроить мониторинг и оповещения о нарушениях политик
    4. Регулярно ротировать ключи подписи и обновлять политики безопасности
    5. Рассмотреть возможность внедрения дополнительных мер безопасности, таких как сканирование уязвимостей

    Ссылки