LabHub
学习 学习路径 课程

KCA — Kyverno 认证助理

立起签名验证策略与凭据

在 LabHub 中继续学习

目标

编写验证 cosign 签名和 attestation 的 Kyverno 策略,并在真实集群中创建 Kyverno 与 Pod 各自访问私有镜像仓库所需的凭据资源。

为什么重要

签名验证策略的难点不在语法,而在运行条件。签名是否存在、能否查询该签名、查询到的签名是否属于我所信任的主体,是三种不同的失败模式,但症状都一样:Pod 无法启动。尤其是遗漏 attestors.count 时,entries 中的所有项都必须通过,因此新增密钥的瞬间就可能阻断一切;启用 mutateDigest 后,依靠推送标签来重建 Pod 的流水线也会悄然失效。本实验让你提前在清单上踩过这些陷阱。

步骤

  1. 创建 /root/kca-verify/ 目录,在 verify-keys.yaml 中填写 kind ClusterPolicymetadata.name kca-verify-imagesspec.rules[0].name verify-signature。在 verifyImages[0].imageReferences 中加入 10.0.0.202/platform/*,并在 attestors[0].entries[0].keys.publicKeys 中放入以 BEGIN PUBLIC KEY 开头的 PEM 公钥。
  2. 在同一个 attestors[0] 中将 count 设为 1,并创建两个 entries。第二项采用 keyless:urlhttps://fulcio.sigstore.devrekor.urlhttps://rekor.sigstore.devissuerhttps://token.actions.githubusercontent.comsubject 填写包含 .github/workflows/ 的工作流路径。
  3. 在同一个 verifyImages[0] 中将 requiredverifyDigestmutateDigest 全部设为 true,并在 skipImageReferences 中加入 10.0.0.202/platform/legacy-*。再将 spec.webhookConfiguration.timeoutSeconds 设为 20 到 30 之间的值,但不要使用已弃用的 spec.webhookTimeoutSeconds
  4. /root/kca-verify/verify-attestations.yaml 中填写 kind ClusterPolicy,并在 verifyImages[0].attestations 中加入两项。一项的 type 为 https://slsa.dev/provenance/v1,通过 conditions[0].all[0].key 检查构建者身份;另一项的 type 为 https://cyclonedx.org/bom/v1.4,通过 conditions[0].all[0].key 检查 log4j-core 组件版本。
  5. /root/kca-verify/allowed-registries.yaml 中填写 kind ClusterPolicymetadata.name kca-allowed-registriesspec.rules[0].validate.foreach[0].list 应为 request.object.spec.[initContainers, containers][],不要用花括号包裹。将 deny.conditions.all[0].operator 设为 AnyNotIn,在 value 列表中加入 10.0.0.202/platform/*,并将 validate.failureAction 设为 Enforce
  6. 在集群中创建命名空间 kca-verify,并在其中实际创建 Secret harbor-cred。类型为 kubernetes.io/dockerconfigjson,服务器为 10.0.0.202
  7. 在同一命名空间中创建 ServiceAccount kca-deployer,在 imagePullSecrets 中添加 harbor-cred;再实际创建 Deployment kca-payments,将 serviceAccountName 设为 kca-deployer,容器镜像写成在 10.0.0.202/platform/payments@sha256: 后附加 64 位十六进制字符的形式。

参考

基于静态密钥的 verifyImages

创建 /root/kca-verify/ 目录,在 verify-keys.yaml 中填写 kind ClusterPolicymetadata.name kca-verify-imagesspec.rules[0].name verify-signature。在 verifyImages[0].imageReferences 中加入 10.0.0.202/platform/*,并在 attestors[0].entries[0].keys.publicKeys 中放入以 BEGIN PUBLIC KEY 开头的 PEM 公钥。

verifyImages 是规则中的数组,每一项都包含 imageReferences 和 attestors。公钥以多行 PEM 字符串形式写入。

添加 keyless 并理解 count 的含义

在同一个 attestors[0] 中将 count 设为 1,并创建两个 entries。第二项采用 keyless:urlhttps://fulcio.sigstore.devrekor.urlhttps://rekor.sigstore.devissuerhttps://token.actions.githubusercontent.comsubject 填写包含 .github/workflows/ 的工作流路径。

仅增加 entries 会要求所有项全部通过。若要在不中断服务的情况下度过密钥轮换期,必须明确指定通过多少项即可。

固定摘要、设置例外与超时

在同一个 verifyImages[0] 中将 requiredverifyDigestmutateDigest 全部设为 true,并在 skipImageReferences 中加入 10.0.0.202/platform/legacy-*。再将 spec.webhookConfiguration.timeoutSeconds 设为 20 到 30 之间的值,但不要使用已弃用的 spec.webhookTimeoutSeconds

这三个布尔值分别表示强制验证、强制使用摘要、将标签替换为摘要。例外应写入专用字段,而不是复制策略。需要往返镜像仓库的策略,默认 Webhook 超时时间通常不够。

设置 provenance 与 SBOM 条件

/root/kca-verify/verify-attestations.yaml 中填写 kind ClusterPolicy,并在 verifyImages[0].attestations 中加入两项。一项的 type 为 https://slsa.dev/provenance/v1,通过 conditions[0].all[0].key 检查构建者身份;另一项的 type 为 https://cyclonedx.org/bom/v1.4,通过 conditions[0].all[0].key 检查 log4j-core 组件版本。

attestations 通过 type 选择声明类型,再用 conditions 检查其内容。如果只检查签名,就没有验证是谁完成了构建。

检查允许的镜像仓库

/root/kca-verify/allowed-registries.yaml 中填写 kind ClusterPolicymetadata.name kca-allowed-registriesspec.rules[0].validate.foreach[0].list 应为 request.object.spec.[initContainers, containers][],不要用花括号包裹。将 deny.conditions.all[0].operator 设为 AnyNotIn,在 value 列表中加入 10.0.0.202/platform/*,并将 validate.failureAction 设为 Enforce

foreach 的 list 不用花括号包裹。必须同时遍历初始化容器,并选择在目标不属于允许列表时拒绝的运算符。

创建镜像仓库凭据 Secret

在集群中创建命名空间 kca-verify,并在其中实际创建 Secret harbor-cred。类型为 kubernetes.io/dockerconfigjson,服务器为 10.0.0.202

从这里开始操作真实集群。镜像仓库有专用的 Secret 类型,kubectl 也提供了创建该类型的子命令。

使用服务账号部署固定摘要的镜像

在同一命名空间中创建 ServiceAccount kca-deployer,在 imagePullSecrets 中添加 harbor-cred;再实际创建 Deployment kca-payments,将 serviceAccountName 设为 kca-deployer,容器镜像写成在 10.0.0.202/platform/payments@sha256: 后附加 64 位十六进制字符的形式。

将 imagePullSecrets 添加到服务账号后,使用该账号启动的 Pod 会继承它。镜像必须以摘要而非标签固定,sha256 长度为 64 位。