(可选)无密钥签名验证

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 透明日志服务器中的 attestations 进行交互。

流程概览

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

分步说明

步骤 1-3:基础设置

这些步骤与 快速开始:已签名来源证明 指南完全相同。请按照该指南中的说明完成以下内容:

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

有关该配置的更多详细信息,请参阅 Transparency Log

步骤 4:重新运行 pipeline 以生成镜像

TIP
  • 由于我们修改了透明日志配置,需要在 快速开始:已签名来源证明 中触发一次新的 pipeline 运行。
  • 这样 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"
    }
  }
}

此内容与镜像中的 attestation 相同,用于验证镜像内容的真实性和完整性。 可以直接从 Rekor 获取 attestation 信息,而无需镜像 registry 的凭据,这使得验证过程更加便捷且易于访问。

步骤 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 .

根据镜像 digest 获取签名

# 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

修改 ClusterPolicykeys 部分以添加 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-----
YAML 字段说明
  • rekor:rekor 验证配置。
    • ignoreTlog:是否忽略透明日志。
      • 如果为 false,将验证 rekor server。
    • url:rekor server 的 URL。
      • 如果未设置,将使用默认的 rekor server https://rekor.sigstore.dev
    • pubkey:签名者的公钥。
      • 如果未设置,将从 rekor server 获取公钥。
      • 如果 rekor server 是私有的,你需要从 rekor server 获取公钥。
        • 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 中具有有效签名的镜像才能部署到指定 namespace
  • 你已经通过 Rekor 验证镜像签名,实现了无密钥供应链安全控制

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

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

参考资料