• Русский
  • Подписанное происхождение

    Это руководство поможет новым пользователям быстро настроить Tekton Chains для защиты их CI/CD конвейеров путем генерации и проверки SLSA Provenance для Tekton PipelineRuns.

    Введение

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

    Tekton Chains помогает защитить вашу цепочку поставок программного обеспечения, автоматически генерируя SLSA Provenance для ваших артефактов сборки. В этом руководстве показано, как настроить Tekton Chains, создать ключ для подписи, запустить пример конвейера и проверить его SLSA Provenance.

    Оценочное время чтения

    15-20 минут

    Важные замечания

    • Tekton Chains устанавливается по умолчанию в пространстве имен tekton-pipelines при использовании Alauda Devops Pipelines Operator
    • Ключи для подписи должны храниться в безопасности; в производственных средах рекомендуется использовать систему управления ключами (KMS)
    • В этом руководстве используется упрощенный рабочий процесс с генерацией Containerfile непосредственно в конвейере
    • В производственных средах следует использовать правильное управление исходным кодом и систему контроля версий

    Требования

    • Kubernetes кластер с установленными Tekton Pipelines и Tekton Chains
    • Реестр с разрешением на отправку образов
    • Установленный и настроенный CLI kubectl для доступа к кластеру
    • Установленный CLI инструмент cosign
    • Установленный CLI инструмент jq

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

    ШагОперацияОписание
    1Генерация ключей подписиСоздание пары ключей для подписи артефактов с помощью cosign
    2Настройка аутентификацииКонфигурация учетных данных реестра для отправки образов
    3Настройка Tekton ChainsНастройка Chains для использования OCI-хранилища и подписи
    4Создание примерного конвейераСоздание определения конвейера с необходимыми задачами и рабочими областями
    5Запуск примерного конвейераСоздание и запуск PipelineRun с правильной конфигурацией
    6Ожидание подписиОжидание подписи PipelineRun Chains
    7Получение информации об образеИзвлечение URI и дайджеста образа из PipelineRun
    8Проверка подписейПроверка подписи образа и аттестации SLSA provenance

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

    Шаг 1: Генерация ключей подписи

    TIP

    Для подробностей смотрите Signing Key Configuration

    Tekton Chains использует криптографические ключи для подписи артефактов. По умолчанию он ищет секрет с именем signing-secrets в пространстве имен Chains.

    1. Установите cosign, если он еще не установлен

    2. Сгенерируйте пару ключей и сохраните их как секрет Kubernetes:

      $ COSIGN_PASSWORD={password} cosign generate-key-pair k8s://tekton-pipelines/signing-secrets
      
      Successfully created secret signing-secrets in namespace tekton-pipelines
      Public key written to cosign.pub
      TIP

      Этот пароль будет сохранен в секрете Kubernetes с именем signing-secrets в пространстве имен tekton-pipelines.

    3. Проверьте, что секрет создан:

      $ kubectl get secret signing-secrets -n tekton-pipelines
      
      NAME              TYPE     DATA   AGE
      signing-secrets   Opaque   3      3m

    Шаг 2: Настройка аутентификации

    TIP

    Для подробностей смотрите Authentication for Chains

    Настройте учетные данные реестра для отправки образов:

    1. Создайте секрет с учетными данными:

      $ kubectl create secret docker-registry registry-credentials \
        --docker-server=<gcr.io> \
        --docker-username=<username> \
        --docker-email=<email> \
        --docker-password=<password> \
        -n $NAMESPACE
    2. Установите ключ config.json:

      $ DOCKER_CONFIG=$(kubectl get secret -n $NAMESPACE $REGISTRY_CREDENTIALS -o jsonpath='{.data.\.dockerconfigjson}')
      $ kubectl patch secret -n $NAMESPACE $REGISTRY_CREDENTIALS -p "{\"data\":{\"config.json\":\"$DOCKER_CONFIG\"}}"
    3. Измените service account для использования секрета:

      $ kubectl patch serviceaccount $SERVICE_ACCOUNT_NAME \
        -p "{\"secrets\": [{\"name\": \"registry-credentials\"}]}" -n $NAMESPACE

    Шаг 3: Настройка Tekton Chains

    TIP

    Для подробностей смотрите Chains Configuration

    Настройте Tekton Chains для хранения артефактов в формате OCI:

    $ kubectl patch tektonconfigs.operator.tekton.dev config --type=merge -p='{
      "spec": {
        "chain": {
          "artifacts.oci.format": "simplesigning",
          "artifacts.oci.storage": "oci",
          "artifacts.pipelinerun.format": "in-toto",
          "artifacts.pipelinerun.storage": "oci",
          "artifacts.taskrun.format": "in-toto",
          "artifacts.taskrun.storage": "oci"
        }
      }
    }'

    Шаг 4: Создание примерного конвейера

    Это ресурс Pipeline, который используется для сборки образа и генерации аттестации SLSA Provenance.

    apiVersion: tekton.dev/v1
    kind: Pipeline
    metadata:
      name: chains-demo-1
    spec:
      params:
        - default: |-
            echo "Generate a Containerfile for building an image."
    
            cat << 'EOF' > Containerfile
            FROM ubuntu:latest
            ENV TIME=1
            EOF
    
            echo -e "\nContainerfile contents:"
            echo "-------------------"
            cat Containerfile
            echo "-------------------"
            echo -e "\nContainerfile generated successfully!"
          description: Скрипт для генерации Containerfile для сборки образа.
          name: generate-containerfile
          type: string
        - default: <registry>/test/chains/demo-1:latest
          description: Адрес целевого образа для сборки
          name: image
          type: string
      tasks:
        - name: generate-containerfile
          params:
            - name: script
              value: $(params.generate-containerfile)
          taskRef:
            params:
              - name: kind
                value: task
              - name: catalog
                value: catalog
              - name: name
                value: run-script
              - name: version
                value: "0.1"
            resolver: hub
          timeout: 30m0s
          workspaces:
            - name: source
              workspace: source
        - name: build-image
          params:
            - name: IMAGES
              value:
                - $(params.image)
            - name: TLS_VERIFY
              value: "false"
          runAfter:
            - generate-containerfile
          taskRef:
            params:
              - name: kind
                value: task
              - name: catalog
                value: catalog
              - name: name
                value: buildah
              - name: version
                value: "0.9"
            resolver: hub
          timeout: 30m0s
          workspaces:
            - name: source
              workspace: source
            - name: registryconfig
              workspace: registryconfig
      results:
        - description: вывод первого артефакта образа
          name: first_image_ARTIFACT_OUTPUTS
          type: object
          value:
            digest: $(tasks.build-image.results.IMAGE_DIGEST)
            uri: $(tasks.build-image.results.IMAGE_URL)
      workspaces:
        - name: source
          description: Рабочее пространство для исходного кода.
        - name: registryconfig
          description: Рабочее пространство для конфигурации реестра распространения.
    TIP

    В производственных средах следует:

    1. Использовать задачу git-clone для получения исходного кода из вашего репозитория
    2. Строить образ, используя Containerfile, который находится в вашем исходном коде
    3. Такой подход обеспечивает правильное управление версиями и разделение кода и конфигурации конвейера
    Объяснение полей YAML
    • params: Параметры конвейера.
      • generate-containerfile: Скрипт для генерации Containerfile для сборки образа.
      • image: Адрес целевого образа для сборки.
    • tasks: Задачи конвейера.
      • generate-containerfile: Задача для генерации Containerfile.
      • build-image: Задача для сборки и отправки образа в реестр.
        • params.TLS_VERIFY: Проверять ли TLS-сертификат реестра.
    • results: Результаты конвейера.
      • first_image_ARTIFACT_OUTPUTS: Результат первого артефакта образа.
        • digest: Дайджест образа.
        • uri: URI образа.
      • Этот формат соответствует Tekton Chains, см. Tekton Chains Type Hinting для подробностей.
    • workspaces: Рабочие области конвейера.
      • source: Рабочее пространство для исходного кода.
      • registryconfig: Рабочее пространство для конфигурации реестра распространения.

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

    • params:
      • generate-containerfile
        • default: Измените адрес исходного образа.
      • image:
        • default: Адрес целевого образа для сборки.

    Сохраните в файл с именем chains.demo-1.pipeline.yaml и примените командой:

    $ export NAMESPACE=<default>
    $ kubectl apply -n $NAMESPACE -f chains.demo-1.pipeline.yaml

    Шаг 5: Запуск примерного конвейера

    Это ресурс PipelineRun, который используется для запуска конвейера.

    apiVersion: tekton.dev/v1
    kind: PipelineRun
    metadata:
      generateName: chains-demo-1-
    spec:
      pipelineRef:
        name: chains-demo-1
      taskRunTemplate:
        serviceAccountName: <default>
      workspaces:
        - name: registryconfig
          secret:
            secretName: <registry-credentials>
        - name: source
          volumeClaimTemplate:
            spec:
              accessModes:
                - ReadWriteOnce
              resources:
                requests:
                  storage: 1Gi
              storageClassName: <nfs>
    Объяснение полей YAML
    • pipelineRef: Конвейер для запуска.
      • name: Имя конвейера.
    • taskRunTemplate: Шаблон запуска задачи.
      • serviceAccountName: Сервисный аккаунт для конвейера.
    • workspaces: Рабочие области конвейера.
      • registryconfig: Рабочее пространство для конфигурации реестра распространения.
      • source: Рабочее пространство для исходного кода.

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

    • taskRunTemplate:
      • serviceAccountName: Сервисный аккаунт, подготовленный на предыдущем шаге ServiceAccount Configuration.
    • workspaces:
      • registryconfig:
      • source:
        • volumeClaimTemplate.spec.storageClassName: Имя класса хранения для шаблона запроса тома.

    Сохраните в файл с именем chains.demo-1.pipelinerun.yaml и примените командой:

    $ export NAMESPACE=<default>
    
    # создайте ресурс pipeline run в пространстве имен
    $ kubectl create -n $NAMESPACE -f chains.demo-1.pipelinerun.yaml

    Дождитесь завершения PipelineRun.

    $ kubectl get pipelinerun -n $NAMESPACE -w
    
    chains-demo-1-<xxxxx>   True        Succeeded   2m         2m

    Шаг 6: Ожидание подписи PipelineRun

    Дождитесь, пока у PipelineRun появится аннотация chains.tekton.dev/signed: "true".

    $ export NAMESPACE=<default>
    $ export PIPELINERUN_NAME=<chains-demo-1-xxxxx>
    
    $ kubectl get pipelinerun -n $NAMESPACE $PIPELINERUN_NAME -o yaml | grep "chains.tekton.dev/signed"
    
        chains.tekton.dev/signed: "true"

    Когда у PipelineRun появится аннотация chains.tekton.dev/signed: "true", это означает, что образ подписан.

    Шаг 7: Получение образа из PipelineRun

    # Получить URI образа
    $ export IMAGE_URI=$(kubectl get pipelinerun -n $NAMESPACE $PIPELINERUN_NAME -o jsonpath='{.status.results[?(@.name=="first_image_ARTIFACT_OUTPUTS")].value.uri}')
    
    # Получить дайджест образа
    $ export IMAGE_DIGEST=$(kubectl get pipelinerun -n $NAMESPACE $PIPELINERUN_NAME -o jsonpath='{.status.results[?(@.name=="first_image_ARTIFACT_OUTPUTS")].value.digest}')
    
    # Объединить URI и дайджест для формирования полного ссылки на образ
    $ export IMAGE=$IMAGE_URI@$IMAGE_DIGEST
    
    # Вывести ссылку на образ
    $ echo $IMAGE
    
    <registry>/test/chains/demo-1:latest@sha256:93635f39cb31de5c6988cdf1f10435c41b3fb85570c930d51d41bbadc1a90046

    Этот образ будет использоваться для проверки подписи.

    Шаг 8: Проверка образа и аттестации

    1. Получите публичный ключ подписи

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

      $ export NAMESPACE=<tekton-pipelines>
      $ kubectl get secret -n $NAMESPACE signing-secrets -o jsonpath='{.data.cosign\.pub}' | base64 -d > cosign.pub
    2. Проверьте подпись

      $ cosign verify --key cosign.pub ${IMAGE}

      Если успешно, вы увидите следующий вывод:

      [{"critical":{"identity":{"docker-reference":"<registry>/test/chains/demo-1"},"image":{"docker-manifest-digest":"sha256:93635f39cb31de5c6988cdf1f10435c41b3fb85570c930d51d41bbadc1a90046"},"type":"cosign container image signature"},"optional":null}]
    3. Проверьте аттестацию SLSA provenance

      $ cosign verify-attestation --key cosign.pub --type slsaprovenance ${IMAGE}

      Если успешно, вы увидите следующий вывод:

      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":[{"keyid":"SHA256:B8CzieJ9/kKhU9hiIPXY+dvvz9DLVOQ3XokyYLdladc","sig":"MEQCIEeS/gGpMV4Y22pYJw3hTyCg92KXACAYvnDwm3fzPxyLAiA3cDP6zjCfaVrf35wED1ylSUdsEJzwlXDCvj2i2A6BYg=="}]}
    4. Извлеките полезную нагрузку с помощью jq:

      $ cosign verify-attestation --key cosign.pub --type slsaprovenance ${IMAGE} | jq '.payload | @base64d' | jq -r '.' | jq '.'
      Полезная нагрузка аттестации
       {
         "_type": "https://in-toto.io/Statement/v0.1",
         "subject": [
           {
             "name": "<registry>/test/chains/demo-1",
             "digest": {
               "sha256": "213a270c14f88abdd283f4ceaf8a8a73f5f8b5c2303609295680a6e751ef6f0f"
             }
           }
         ],
         "predicateType": "https://slsa.dev/provenance/v0.2",
         "predicate": {
           "buildConfig": {
             "steps": [
               {
                 "annotations": null,
                 "arguments": [
                   "--images",
                   "<registry>/test/chains/demo-1:latest",
                   "--build-args",
                   ""
                 ],
                 "entryPoint": "",
                 "environment": {
                   "container": "build-and-push",
                   "image": "oci://<registry>/devops/tektoncd/hub/buildah@sha256:8d5ea9ecd9b531e798fecd87ca3b64ee1c95e4f2621d09e893c58ed593bfd4c4"
                 }
               }
             ]
           },
           "buildType": "tekton.dev/v1beta1/TaskRun",
           "builder": {
             "id": "https://alauda.io/builders/tekton/v1"
           },
           "invocation": {
             "configSource": {
               "digest": {
                 "sha256": "3225653d04c223be85d173747372290058a738427768c5668ddc784bf24de976"
               },
               "uri": "http://tekton-hub-api.tekton-pipelines:8000/v1/resource/catalog/task/buildah/0.9/yaml"
             },
             "environment": {
               "annotations": {
                 "cpaas.io/creator": "admin@cpaas.io",
                 "cpaas.io/operator": "admin@cpaas.io",
                 "cpaas.io/updated-at": "2025-06-16T06:04:04Z",
                 "pipeline.tekton.dev/affinity-assistant": "affinity-assistant-691f2fff6f",
                 "pipeline.tekton.dev/release": "002f74eea37b0f5dbcfed39c13d7cd762c8fcdc4",
                 "tekton.dev/categories": "Image Build",
                 "tekton.dev/displayName": "Buildah",
                 "tekton.dev/icon": "",
                 "tekton.dev/pipelines.minVersion": "0.56.0",
                 "tekton.dev/platforms": "linux/amd64,linux/arm64",
                 "tekton.dev/tags": "image-build"
               },
               "labels": {
                 "app.kubernetes.io/managed-by": "tekton-pipelines",
                 "app.kubernetes.io/version": "0.9",
                 "tekton.dev/memberOf": "tasks",
                 "tekton.dev/pipeline": "chains-demo-1",
                 "tekton.dev/pipelineRun": "chains-demo-1-zp9tk",
                 "tekton.dev/pipelineRunUID": "ad8234b8-19a6-4c5c-b2fd-5673444aeda8",
                 "tekton.dev/pipelineTask": "build-image",
                 "tekton.dev/task": "buildah"
               }
             },
             "parameters": {
               "BUILDER_IMAGE": "<registry>/devops/tektoncd/hub/buildah:v1.33.12-v4.0.0-beta.240.g2b61d46",
               "BUILD_ARGS": [
                 ""
               ],
               "BUILD_EXTRA_ARGS": "",
               "CONTEXT": ".",
               "CONTAINERFILE": "./Containerfile",
               "FORMAT": "oci",
               "IMAGES": [
                 "<registry>/test/chains/demo-1:latest"
               ],
               "PUSH_EXTRA_ARGS": "",
               "SKIP_PUSH": "false",
               "STORAGE_DRIVER": "vfs",
               "TLS_VERIFY": "false",
               "VERBOSE": "false"
             }
           },
           "materials": [
             {
               "digest": {
                 "sha256": "8d5ea9ecd9b531e798fecd87ca3b64ee1c95e4f2621d09e893c58ed593bfd4c4"
               },
               "uri": "oci://<registry>/devops/tektoncd/hub/buildah"
             }
           ],
           "metadata": {
             "buildFinishedOn": "2025-06-16T06:04:41Z",
             "buildStartedOn": "2025-06-16T06:04:15Z",
             "completeness": {
               "environment": false,
               "materials": false,
               "parameters": false
             },
             "reproducible": false
           }
         }
       }

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

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

    • У вас настроен рабочий Tekton Chains с ключом подписи
    • Ваши PipelineRuns автоматически подписываются после завершения, и образ содержит аттестацию SLSA Provenance
    • Вы можете проверять подписи и аттестации для обеспечения целостности сборок

    Это руководство предоставляет основу для реализации безопасности цепочки поставок в ваших CI/CD конвейерах. В производственной среде следует:

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

    Ссылки