(可选)无密钥签名验证

TIP
  • 如果您对无密钥签名验证感兴趣,可以继续阅读以下内容。
  • 本章内容需要能够访问公共网络。
  • 但如果您已经部署了私有 Rekor 服务,也可以使用这些服务。
NOTE
  • 此方法要求环境能够访问 Internet。
  • 如果您已经部署了私有 Rekor 服务,也可以通过调整相关配置来使用这些功能。
  • 关于部署私有 Rekor 服务的内容不在本文档范围内,请参阅相关文档。

目前,ACP(Alauda Container Platform)尚不提供部署私有 Rekor 实例的能力,但支持与 Rekor 服务进行集成。

下面以集成公共 Rekor 为例,介绍如何使用这些服务。 如果您已经部署了私有 Rekor 服务,请参阅相关文档进行配置。

功能概述

此方法使用透明日志来增强安全性,从而无需进行密钥管理:

  1. 配置 Tekton Chains 以使用无密钥签名。
  2. 使用 buildah Tekton Task 构建镜像。
  3. 配置 Kyverno 规则以验证无密钥签名。
  4. 使用该镜像创建 Pod,以验证无密钥签名。

使用场景

以下场景需要参考本文档中的指导:

  • 在 Kubernetes 集群中为容器镜像实施无密钥签名和验证
  • 强制实施安全策略,在不管理签名密钥的情况下验证镜像签名
  • 在 CI/CD 流水线中设置自动化透明日志验证
  • 通过 Rekor 透明日志确保镜像来源和完整性
  • 通过针对公共 Rekor 服务验证镜像签名来实施供应链安全控制

前提条件

  • 已安装 Tekton Pipelines、Tekton Chains 和 Kyverno 的 Kubernetes 集群
  • 已启用镜像推送功能的 registry
  • 已安装并配置 kubectl CLI,以访问您的集群
  • 已安装 cosign CLI 工具
  • 已安装 jq CLI 工具
  • 已安装 curl
  • 已安装 rekor-cli
    • 用于验证和与存储在 Rekor 透明日志服务器中的声明进行交互。

流程概览

步骤操作描述
1生成签名密钥使用 cosign 创建用于签名制品的密钥对
2设置身份验证配置用于推送镜像的 registry 凭据
3配置 Tekton Chains设置 Chains 以使用 OCI 存储并配置签名
4重新运行流水线触发新的流水线运行以生成透明日志条目
5获取 Rekor 日志索引从 PipelineRun 注解中提取 Rekor 日志索引
6验证 Rekor 签名使用 curl 获取并验证 Rekor 签名
7使用 Rekor CLI使用 rekor-cli 工具获取并验证签名
8使用 Kyverno 进行验证设置 Kyverno 策略以进行 Rekor 验证

分步说明

步骤 1-3:基本设置

这些步骤与快速入门:已签名的来源证明指南完全相同。请按照该指南中的说明执行以下操作:

TIP
  • 如果您使用的是私有 Rekor 服务,可以将 transparency.url 设置为您的 Rekor 服务器 URL。
    • transparency.url: "<https://rekor.sigstore.dev>"

有关配置的更多详细信息,请参阅透明日志

步骤 4:重新运行流水线以生成镜像

TIP
  • 由于我们修改了透明日志配置,因此需要在已签名的来源证明中触发新的流水线运行。
  • 这样 Tekton Chains 就可以为新的镜像和 PipelineRun 生成透明日志条目。

步骤 5:获取 Rekor 日志索引

从 PipelineRun 的注解中获取 Rekor 日志索引。

$ export NAMESPACE=<pipeline-namespace>
$ export PIPELINERUN_NAME=<pipelinerun-name>
$ kubectl get pipelinerun -n $NAMESPACE $PIPELINERUN_NAME -o jsonpath='{.metadata.annotations.chains\.tekton\.dev/transparency}'

https://rekor.sigstore.dev/api/v1/log/entries?logIndex=232330257

步骤 6:通过 curl 获取 Rekor 签名

$ curl -s "https://rekor.sigstore.dev/api/v1/log/entries?logIndex=232330257" | jq

如果需要查看 Rekor 签名的内容,可以执行以下命令:

$ curl -s "https://rekor.sigstore.dev/api/v1/log/entries?logIndex=232330257" | jq -r '.[keys[0]].attestation.data | @base64d' | jq .

{
  "_type": "https://in-toto.io/Statement/v0.1",
  "subject": null,
  "predicateType": "https://slsa.dev/provenance/v0.2",
  "predicate": {
    "buildType": "tekton.dev/v1beta1/PipelineRun",
    "builder": {
      "id": "https://alauda.io/builders/tekton/v1"
    },
    "materials": [
      {
        "digest": {
          "sha256": "8d5ea9ecd9b531e798fecd87ca3b64ee1c95e4f2621d09e893c58ed593bfd4c4"
        },
        "uri": "oci://<registry>/devops/tektoncd/hub/buildah"
      }
    ],
    "metadata": {
      "buildFinishedOn": "2025-06-08T03:11:52Z",
      "buildStartedOn": "2025-06-08T03:10:33Z"
    }
  }
}

此内容与镜像中的声明相同,可用于验证镜像内容的真实性和完整性。 无需从镜像 registry 获取凭据即可从 Rekor 检索声明信息,因此验证过程更加便捷和易于访问。

步骤 7:通过 rekor-cli 获取 Rekor 签名

通过日志索引获取签名

# the log index is same as the one in the annotations of the PipelineRun
$ rekor-cli get --log-index 232330257 --format json | jq -r .Attestation | jq .

通过镜像摘要获取签名

# get the uuid by image digest
$ rekor-cli search --sha da4885861a8304abad71fcdd569c92daf33422073d1102013a1fed615dfb285a

Found matching entries (listed by UUID):
108e9186e8c5677a1364e68001a916d3a7316bc2580bd6b5fbbce39a9c62f13282d3e974a6b434ab

# get the signature by uuid
$ rekor-cli get --uuid 108e9186e8c5677a1364e68001a916d3a7316bc2580bd6b5fbbce39a9c62f13282d3e974a6b434ab --format json | jq -r .Attestation | jq .

步骤 8:在 Kyverno 中验证 Rekor

修改 keys 的 ClusterPolicy 部分,以添加 Rekor 验证。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
spec:
  rules:
    - name: check-image
      verifyImages:
        - attestors:
            - count: 1
              entries:
                - keys:
                    publicKeys: |- # <- The public key of the signer
                      -----BEGIN PUBLIC KEY-----
                      MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFZNGfYwn7+b4uSdEYLKjxWi3xtP3
                      UkR8hQvGrG25r0Ikoq0hI3/tr0m7ecvfM75TKh5jGAlLKSZUJpmCGaTToQ==
                      -----END PUBLIC KEY-----

                    rekor:
                      ignoreTlog: false
                      # url: <https://rekor.sigstore.dev>
                      # # get the public key from the rekor server
                      # # curl <https://rekor.sigstore.dev>/api/v1/log/publicKey
                      # pubkey: |-
                      #   -----BEGIN PUBLIC KEY-----
                      #   MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2G2Y+2tabdTV5BcGiBIx0a9fAFwr
                      #   kBbmLSGtks4L3qX6yYY0zufBnhC8Ur/iy55GhWP/9A/bY2LhC30M9+RYtw==
                      #   -----END PUBLIC KEY-----
Explanation of YAML fields
  • rekor:Rekor 验证配置。
    • ignoreTlog:是否忽略透明日志。
      • 如果为 false,则会验证 Rekor 服务器。
    • url:Rekor 服务器的 URL。
      • 如果未设置,则使用默认 Rekor 服务器 https://rekor.sigstore.dev。
    • pubkey:签名者的公钥。
      • 如果未设置,则从 Rekor 服务器获取公钥。
      • 如果 Rekor 服务器是私有的,则需要从 Rekor 服务器获取公钥。
        • curl <https://rekor.sigstore.dev>/api/v1/log/publicKey

如果您的镜像未签名,Pod 将被阻止。

Error from server: admission webhook "mutate.kyverno.svc-fail" denied the request:

resource Pod/policy/sign was blocked due to the following policies

only-cosign-image-deploy:
  check-image: 'failed to verify image <registry>/test/chains/demo-1:latest:
    .attestors[0].entries[0].keys: no matching signatures: searching log query: Post
    "http:///api/v1/log/entries/retrieve": POST http:///api/v1/log/entries/retrieve
    giving up after 4 attempt(s): Post "http:///api/v1/log/entries/retrieve": http:
    no Host in request URL'

预期结果

完成本指南后:

  • 您将拥有一个可正常运行的 Tekton Chains 配置,用于无密钥签名和 Rekor 集成
  • 您的容器镜像将自动进行签名,其签名将存储在 Rekor 透明日志中
  • 无需管理签名密钥即可验证镜像签名
  • 只有在 Rekor 中具有有效签名的镜像才能部署到指定命名空间
  • 您已通过 Rekor 验证镜像签名,实现了无密钥供应链安全控制

本指南为在 CI/CD 流水线中实现无密钥签名和验证奠定了基础。在生产环境中,您应:

  1. 配置适当的命名空间隔离和访问控制
  2. 为签名验证失败设置监控和告警
  3. 定期审查和更新安全策略
  4. 考虑部署私有 Rekor 实例,以增强安全性

参考