Ratify 制品验证、策略裁决与 Gatekeeper 接入手册
平台团队上线 Ratify 后,用一张已签名镜像验证成功,又把签名删掉重试,部署竟然仍被允许。Ratify 没有伪造报告:Store 没发现可交给目标 Verifier 的证据,策略却只表达“所有已经运行的验证器都成功”。零份报告让这个全称条件空集成立,系统把“没有失败”误写成“存在一份成功”,缺证据的镜像因此穿过门禁。
另一次故障中,团队把 Gatekeeper webhook 改为 fail-closed,希望 Registry 或验证服务出问题时停止所有发布。随后节点扩容与 Ratify 恢复 Deployment 也进入同一准入链,webhook 已不可达,新 Node 和恢复 Pod 又因 failurePolicy: Fail 被拒绝。验证服务等资源、资源又等验证服务,自恢复形成死锁;最后只能走独立管理通道解除 webhook,并补验故障窗口中的对象。
Ratify 是验证编排器,不是准入控制器
Ratify 接收 subject,发现相关 OCI 证据,调用匹配的验证器,再把报告交给策略。它可以被 CLI、服务或 Gatekeeper External Data 调用,但 Ratify 自己不拦截 Kubernetes API 请求。集群里的最终 allow/deny 由 API server 调用 Gatekeeper validating webhook,Gatekeeper 的 Constraint/Rego 再根据 Ratify 响应产生 violation。把 Ratify 写成 admission controller 会掩盖 webhook scope、timeout、failurePolicy、豁免和审计这些真正决定准入行为的配置。
Ratify 当前是 CNCF Sandbox 项目,稳定文档线、chart、CRD API、插件状态和支持矩阵仍需随目标版本核对;高可用指南也不应被解读成所有 HA 能力都已达到同一成熟度。Ratify Getting Started给出快速体验与 Gatekeeper 路径,同时提醒 OCI Index 或 Manifest List 当前只验证 index/list 层,不会自动按平台继续验证子 manifest。多架构镜像策略必须明确信任的是 index,还是每个平台 manifest 的独立证据。
Kubernetes 的 Validating Admission Policy 能在 API server 内执行 CEL 策略,却不能由此推导出它会访问 Registry、发现 OCI referrer 并完成 Notation/Cosign 密码学验证。Ratify解决外部证据验证,Gatekeeper解决请求时策略执行,两者组合会把 Registry、DNS、证书、缓存和 webhook 可用性都带入 API 写路径,生产 SLO 必须按整条链路设计。
Store、Verifier、Policy 与 Executor 各自保存不同事实
Store 负责从 subject 所在 Registry 或配置的来源发现、拉取 reference artifacts。当前稳定 CRD 文档中的默认实现是 ORAS Store;它处理 Registry 认证、附件发现和本地 blob/cache,却不判断签名者是否可信。useHttp 会放弃安全传输预期,只能用于隔离开发环境;Cosign 场景还要确认 ORAS Store 的 cosignEnabled,否则证据可能根本没有进入验证器。
Verifier 根据 artifact type 判断自己能否处理证据,并返回包含成功状态、消息、artifact type、reference digest 与扩展信息的报告。Notation verifier 读取 trust policy、trust store 和 trusted identities;Cosign verifier 读取 scopes、keys 或 keyless identity,以及 Rekor/CT log 约束;SBOM verifier 处理的是另一种语义。一个 verifier 成功不能替另一个证据类型背书,最终日志必须保留 VerifierName、VerifierType 与 reference digest,而不是只写“Ratify passed”。
Policy 评估报告,Executor 编排 Store、Verifier 与 Policy 的调用顺序。config-policy 可按 artifact type 表达 any/all,rego-policy 可由 Ratify直接决策;passthroughEnabled: true 时 Ratify把报告交给 Gatekeeper,由 Gatekeeper Rego 决定。两层同时维护独立 allow 逻辑,会出现一层放行、另一层拒绝或字段升级后静默偏差,因此必须指定唯一最终裁决点。
Kubernetes API request
-> Gatekeeper validating webhook
-> Constraint / Rego calls external_data(provider=ratify)
-> Ratify Executor
-> Store discovers OCI reference artifacts
-> matching Verifiers emit reports
-> Ratify Policy decides, or passthrough returns reports
-> Gatekeeper emits violation or no violation
-> API server rejects or persists the object安装时把快速体验拆成可治理组件
官方 quick start 可以用 Helmfile 一次安装 Gatekeeper、Ratify 和样例 Constraints,适合观察调用链;生产环境应分开固定 Gatekeeper chart、Ratify chart、镜像 digest、CRD 与 policy library 版本。不同官方页面曾出现不同的最低 Kubernetes/Gatekeeper 要求,因此不要凭一段安装命令承诺兼容性,应读取目标 release 的 chart metadata、release notes 和 CI compatibility matrix,再在与生产同小版本的集群验证。
set -euo pipefail
: "${GATEKEEPER_CHART_VERSION:?pin Gatekeeper chart version}"
: "${RATIFY_CHART_VERSION:?pin Ratify chart version}"
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm repo add ratify https://notaryproject.github.io/ratify
helm repo update
helm template gatekeeper gatekeeper/gatekeeper \
--version "$GATEKEEPER_CHART_VERSION" \
--namespace gatekeeper-system \
--set enableExternalData=true > rendered-gatekeeper.yaml
helm template ratify ratify/ratify \
--version "$RATIFY_CHART_VERSION" \
--namespace gatekeeper-system > rendered-ratify.yaml
kubectl apply --server-side --dry-run=server -f rendered-gatekeeper.yaml
kubectl apply --server-side --dry-run=server -f rendered-ratify.yaml渲染后检查 CRD group/version、ClusterRole、Secret 引用、Service、webhook、Provider URL、CA bundle、replica、PodDisruptionBudget、NetworkPolicy、资源限制和镜像 digest。安装 Ratify 前先确认 Gatekeeper External Data 已启用;安装后分别看 Gatekeeper webhook ready、Ratify provider ready、Provider 对象状态以及一次真实 Registry 查询。Pod Running 只能证明进程启动,不能证明 Registry auth、trust root 或 Rego response schema 正确。
生产安装要明确谁拥有 cluster-scoped CRD 与 Gatekeeper webhook,谁拥有 namespace 级 Store/Verifier/Policy,谁能修改 Registry Secret 和信任材料。样例证书、通配 Registry scope、trustedIdentities: ["*"] 与公开测试镜像都只能用于训练环境;验证成功后删除测试对象和凭据,再接入企业 Registry。
配置字段改变的是发现面、信任面和裁决面
ORAS Store 的 Registry endpoint、认证提供方、cosignEnabled、localCachePath 和 HTTP/TLS 设置决定“能看见哪些证据”。认证失败、附件 API 不兼容或 scope 错误都可能表现为零报告,不能让 Policy 把它当作 unsigned 的同义词,更不能当作成功。localCachePath 只是本地 OCI blob/cache 路径,不是完整证据档案,也不保证跨副本一致。
Verifier 的 scope 决定哪个 Registry/repository 适用哪组 key 或 keyless identity。Notation 的 trustPolicyDoc 应采用严格签名验证、精确 registry scope、明确 trust store 与 identity;Cosign 新配置采用 trustPolicies,把 scope 与 keys/identity、Rekor 和 CT log要求绑定。旧的单一 key、rekorURL 字段属于迁移债务,不应继续复制到新环境。密钥证书来源优先使用 KeyManagementProvider,避免把已弃用 CertificateStore 当长期接口。
Policy 名称、作用域与回退同样影响结果。集群中活动 Policy 的命名有固定契约;NamespacedPolicy 缺失时可能回退 cluster-wide policy。如果全局策略比租户策略宽,删除或拼错 namespace policy 会意外放行。每个 namespace 都要有“策略存在”“策略生效版本”“缺失时行为”的监控和负例,不能只检查 CRD 已创建。
# 结构示意:字段必须以目标 Ratify CRD 的 explain/schema 为准。
verificationProfile:
store:
type: oras
registryScope: registry.example.com/payments
transport: https
cosignEnabled: true
credentialRef: registry-readonly
verifier:
type: cosign
trustPolicies:
- name: payments-release
scopes: [registry.example.com/payments]
identities:
- issuer: https://token.actions.githubusercontent.com
subject: repo:acme/payments:ref:refs/heads/main
requireTransparencyEvidence: true
decision:
requireReportTypes: [application/vnd.dev.cosign.simplesigning.v1+json]
rejectOnSystemError: true
rejectEmptyReports: true上面的 YAML 是审查清单,不应原样当作 Ratify CR。真正落库前运行 kubectl explain store.spec --api-version=<TARGET_API>、kubectl explain verifier.spec 和 helm show crds,再用服务器 dry-run 校验。这样既展示字段意图,也避免稳定文章把某一 release 的嵌套结构伪装成永久 API。
空集成功必须用存在性断言封死
策略逻辑中的 all reports are successful 对空数组通常为真,这叫 vacuous truth。Ratify 找不到证据、没有匹配 verifier、插件未加载、artifact type 未被策略要求,都可能产生零份目标报告。可靠规则至少同时表达:外部调用没有 system_error;subject 本身没有解析错误;要求类型的报告数量大于等于阈值;每份要求报告成功;报告来自允许 verifier;reference digest 与当前 subject 绑定。
不要把“Store 返回空”和“签名验证失败”压成同一个 reason。前者要继续区分 unsigned、Registry 401/403、404、429、附件发现不兼容、超时、unsupported artifact type 和 verifier 未注册。只有这样,平台才能让确定性不合规直接拒绝,让暂时故障按可用性策略处理,并对权限误配快速告警。
下面的 Rego 片段展示 Gatekeeper passthrough 场景的核心不变量。实际字段名要跟随固定的 Ratify response schema,升级时用契约测试锁定;关键不是语法模板,而是零报告和系统错误都产生 violation。
package ratify_required_evidence
required_type := "application/vnd.dev.cosign.simplesigning.v1+json"
required_reports := [r |
r := input.ratify.verifierReports[_]
r.artifactType == required_type
]
violation["ratify external data failed"] if {
input.ratify.system_error != ""
}
violation["required signature report is missing"] if {
count(required_reports) == 0
}
violation[msg] if {
some r in required_reports
not r.isSuccess
msg := sprintf("signature verification failed: %s", [r.message])
}正反实验先验证密码学,再验证零报告语义
第一组实验使用同一 repository 下两个 digest-pinned 镜像:一个由允许 key/identity 签名,一个没有签名。对 CLI 路径和 Gatekeeper External Data 路径分别执行,正例保存 subject digest、reference digest、artifact type、verifier identity、policy version 和 trace ID;反例必须明确出现 missing required evidence 或 unsigned,而不是空数组加 200。
set -euo pipefail
: "${SIGNED_IMAGE:=registry.example.com/payments/api@sha256:SIGNED}"
: "${UNSIGNED_IMAGE:=registry.example.com/payments/api@sha256:UNSIGNED}"
# 正向:要求至少一份指定类型报告,且每份均成功。
ratify verify -s "$SIGNED_IMAGE" -o json > signed-result.json
jq -e '
[.verifierReports[] | select(.artifactType | contains("simplesigning"))] as $r
| ($r | length) > 0 and all($r[]; .isSuccess == true)
' signed-result.json
# 反向:无签名对象不得以零报告成功。
if ratify verify -s "$UNSIGNED_IMAGE" -o json > unsigned-result.json; then
jq -e '.isSuccess == false or (.verifierReports | length) == 0' unsigned-result.json
echo 'Check policy: command success must not become admission allow' >&2
fi再删除或禁用目标 Verifier,用同一个已签名 digest 重试。密码学材料没有变化,但报告集合应从成功变成“无匹配 verifier”;最终策略仍应拒绝。这一反例能发现“所有已执行验证器成功”的空集漏洞。恢复 Verifier 后清理相关缓存并重验,证明成功来自验证器恢复,不是旧 decision 残留。
第二组实验使用错误 key、错误 OIDC issuer、错误 identity 和错误 Registry scope。四种情况都应产生可区分的失败报告。随后把 multi-arch index 固定为 digest,替换测试 repository 中某个平台子 manifest,再验证 index;若 index digest没变在 OCI 模型上本就不成立,说明替换会产生新 index digest。更重要的是检查当前策略只验证 index 证据,还是还要求每个平台 manifest 的独立证据,不能用“multi-arch image passed”掩盖层级。
positive:
signed digest + exact scope + allowed identity -> report count >= 1, allow
negative-a:
signed digest + wrong key/issuer/identity -> failed verifier report, deny
negative-b:
signed digest + verifier removed -> zero required reports, deny
negative-c:
unsigned digest -> missing evidence, deny
negative-d:
registry 401/429 or provider timeout -> system error, follow declared failure modeGatekeeper 接入决定真正的准入结果
Gatekeeper Rego 调用 External Data Provider,把镜像引用批量发给 Ratify;Ratify响应包含 subject 级结果、verifier reports 和可能的 system_error。ConstraintTemplate 负责解释响应,Constraint 决定匹配哪些 kind、namespace 和参数。最终没有 violation 才放行,因此 Rego 中任何遗漏字段、旧字段名或错误的默认值都可能变成静默允许。
Gatekeeper Policy Authoring展示了 Ratify报告交给 Gatekeeper 的方式,并建议显式处理 system_error 和失败报告。自定义模板还要检查空 response、重复 subject、sidecar/initContainer/ephemeralContainer、CronJob 等工作负载路径。只匹配 Pod 不能覆盖控制器创建前的 Deployment,反过来只匹配 Deployment 又会漏掉直接创建的 Pod。
准入只覆盖被 webhook rules、namespaceSelector、objectSelector 和 Constraint 匹配的 API 写请求。它不会自动扫描已存在对象,不覆盖节点上直接运行的容器,也阻止不了 admission 后可变 tag 指向新 digest。生产 workload 应在进入准入前解析或强制使用 digest;审计任务定期重验存量对象和豁免窗口,对 tag、未匹配 kind 与 provider 故障造成的漏网对象补偿。
fail-open 与 fail-closed 是可用性契约
Gatekeeper 当前默认对约束 webhook 错误采用 failurePolicy: Ignore,服务不可达时可能允许请求,再依靠 audit 发现违规;Failing Closed说明改为 Fail 后,webhook 故障会拒绝 API 请求,也会带来 admission deadlock 风险。Ratify策略返回 deny 与 webhook 根本没有响应是两类事件,前者始终拒绝,后者才由 failurePolicy 决定。
fail-open 适合观察期或低风险环境,但必须带审计、告警、故障窗口资产清单和恢复后重验,不能宣称为强制门禁。fail-closed 适合高保证 namespace,代价是 Registry、Ratify、Gatekeeper、DNS、证书、网络和信任材料共同进入写路径 SLO。timeout 要小于 API server 整体请求预算;过长不会增加安全性,只会让上游先超时。
故障实验应分别制造 Registry 401、404、429、provider 5xx、DNS 失败和超时,并在两个 failure mode 下记录 API 响应、Gatekeeper audit、Ratify trace 与实际对象是否落库。密码学失败在两种 mode 下都应该拒绝;只有基础设施错误的行为随契约变化。如果所有失败都显示为同一个 Forbidden,值班人员无法判断应修证书、扩容还是启动例外流程。
set -euo pipefail
IMAGE=registry.example.com/payments/api@sha256:TEST
# 正向:健康链路允许受信 digest。
kubectl run ratify-positive --image="$IMAGE" --restart=Never
# 反向实验由隔离环境临时阻断 Ratify provider 或 Registry。
# failurePolicy=Ignore:对象可能创建,必须出现 audit/告警并进入补验清单。
# failurePolicy=Fail:请求必须失败,且恢复 namespace 的独立路径仍可操作。
kubectl run ratify-provider-down --image="$IMAGE" --restart=Never \
2>&1 | tee admission-outage.txt
kubectl get pod ratify-provider-down -o json 2>/dev/null \
| jq '{name:.metadata.name,image:.spec.containers[0].image}' || true缓存提高吞吐,也会延长撤销窗口
Gatekeeper External Data 和 Ratify/插件可能各自缓存 Registry 解析、blob、报告或最终响应。缓存键必须以不可变 subject digest 为核心,并包含 verifier 配置、trust root/key 版本、policy version 和要求的 artifact type。按 tag 缓存会把旧成功应用到新 manifest;只按 digest 缓存但忽略策略版本,会让收紧 identity 后继续复用旧 allow。
撤销 key、删除签名、禁用 signer identity 或轮换 root 后,Registry 中的事实已经改变,缓存却可能继续返回旧结果。每种缓存都要有 owner、TTL、命中指标、显式 purge 或滚动重启方法,并记录“撤销传播最大延迟”。高风险事件不能等待普通 TTL 自然结束,应暂停推广、清 Gatekeeper provider cache、清 Ratify共享/本地缓存,再用旧签名负例和新签名正例复验。
缓存不是离线证据库。Pod 重建、节点漂移或版本升级都可能丢失本地内容;缓存中也未必包含原始签名、证书链、透明日志证据和根。灾备需要按 digest 归档 subject manifest、reference artifacts、验证策略与信任材料,并在无原 Registry 的环境恢复验证。把 localCachePath 备份后宣称“Ratify 可离线恢复”通常是不完整的。
break-glass 要能打破恢复死锁而不变成永久后门
fail-closed 环境必须先画出 Gatekeeper、Ratify、Registry auth、DNS、证书和节点扩容的恢复依赖。若恢复这些组件所需的 Node、Pod、Deployment、Secret 或 ConfigMap 同样被故障 webhook 拦截,就形成环。更低爆炸半径的设计是独立恢复 namespace、受保护的 namespaceSelector/objectSelector 豁免、独立管理员身份和外部可读 runbook;普通租户不能自行添加豁免标签。
Gatekeeper 官方紧急恢复可删除 gatekeeper-validating-webhook-configuration,但该动作会移除全部 Gatekeeper admission checks,不只绕过 Ratify。执行权限应双人取用,全程写入独立审计,并先冻结非必要发布。若 operator 或 GitOps 会立刻重建 webhook,还要有暂停调谐的独立步骤,否则恢复操作会被自动抵消。
# 只在批准的集群恢复流程中执行;先记录对象与摘要。
kubectl get validatingwebhookconfiguration \
gatekeeper-validating-webhook-configuration -o yaml \
> gatekeeper-webhook-before-break-glass.yaml
kubectl delete validatingwebhookconfiguration \
gatekeeper-validating-webhook-configuration
# 恢复 Gatekeeper/Ratify 后,由固定版本清单重新创建 webhook。
kubectl apply -f approved-gatekeeper-webhook.yaml
kubectl wait --for=condition=Available deployment/gatekeeper-controller-manager \
-n gatekeeper-system --timeout=120s恢复后先清缓存,重放正反验证,再从 API audit 与对象创建时间线收集 break-glass 窗口内所有 workload;逐个解析到 digest 并补验,不合规对象隔离或删除。最后回收临时管理员凭证、恢复调谐、确认 webhook CA 与 rules 正确,并演练旧豁免身份不能继续发布。break-glass 的价值是恢复控制能力,不是为紧急发布提供免检通道。
凭证、插件与敏感数据需要分层隔离
Store 只需要目标 Registry 的 pull/referrer read 权限,不应持有 push 或删除;私有 Registry auth 可来自 Docker config Secret、云工作负载身份或受控 credential provider。Secret 读取限制到实际 namespace 与 ServiceAccount,日志不输出完整 Docker config、bearer token、KMS URI中的秘密参数或私有仓库清单。Registry 401 与没有证据必须保留不同原因,但响应正文也要脱敏。
Verifier 读取公钥、证书、trust store 或 KMS 公共验证材料。轮换采用新旧 key 的有限双信任,先让新签名通过,再停旧签发,最后在历史保留语义允许时移除旧 key。Dynamic Plugins 受实验 feature flag 约束,且会从 OCI 拉取可执行代码;采用时固定插件 digest、验证插件自身签名、限制 Registry auth、只读根文件系统与系统调用权限。插件供应链不能靠插件自己证明自己可信。
验证报告可能含 signer identity、证书 subject、内部 Registry、镜像 repository、SBOM 组件和错误详情。指标标签只保留 verifier、结果类别、Registry 逻辑名与低基数 policy version,不把完整 digest、用户、token 或镜像路径全部做 label。审计日志按 trace ID 关联 admission UID、subject digest 和 decision,敏感扩展字段进入受控存储并设置保留期。
排障按发现、验证、策略和准入四层取证
Store 层先用 Registry 原生命令确认 digest 存在、凭据可读 referrers、TLS 链可信,再检查 Ratify 的 scope、ORAS Store、cosignEnabled 和网络。401/403 是身份授权,404 可能是 subject 或附件缺失,429 是容量限制;把它们都归为 unsigned 会误导修复。多副本间结果不一致时,比较缓存、Secret 挂载、节点 DNS 和实际配置 generation。
Verifier 层查看 artifact type 是否匹配、插件是否加载、key/identity scope、证书链、Rekor/CT 要求和 reference digest。Policy 层检查活动 ratify-policy、NamespacedPolicy 回退、any/all 语义、passthrough 与 response schema;最重要的探针是零份目标报告是否拒绝。升级后若 Name/Type 已迁移到 VerifierName/VerifierType 而 Rego 仍读旧字段,可能造成全拒绝或空条件放行。
准入层检查 Provider URL/CA、Gatekeeper External Data、ConstraintTemplate、Constraint match、webhook rules、selector、timeout、failurePolicy、audit 和 admission UID。Ratify CLI 成功只证明 CLI 路径,不能证明 Gatekeeper Rego、网络和 webhook 契约。反过来,Forbidden 也不一定是 Ratify拒绝,可能来自其他 Constraint;输出 violation 名和 trace ID 才能定位。
HA、容量与成本要覆盖 Registry 和 API 写路径
Ratify 多副本前先确认状态与缓存模式是否支持共享,以及目标 HA 能力在固定版本中的成熟状态。所有副本必须读取相同 Store、Verifier、Policy、Secret 与根版本;readiness 不只检查 HTTP 监听,还应确认配置已加载。Gatekeeper controller-manager 同样需要副本、反亲和、PDB 和容量余量,但副本数不能修复单一 Registry、DNS、KMS 或错误 CA 的共同故障。
容量模型从 admission 峰值反推:每个 workload 包含多少普通、init 和 sidecar 镜像;每个 digest 有多少 referrer;一次验证触发多少 Registry 请求、证书/透明日志调用和 Rego 计算;缓存命中率与撤销 TTL是多少。节点扩容、批量部署、灾后重放和缓存冷启动通常比日常均值更陡。压测记录 p50/p95/p99、429、timeout、报告数量、缓存命中、Gatekeeper webhook 延迟、API server 拒绝率、CPU/内存和 Registry egress。
成本不仅是 Ratify Pod,还包括 Gatekeeper、副本与跨区流量、Registry API/存储、共享缓存、KMS/证书服务、审计日志、策略维护、值班与 break-glass 演练。缓存降低外部调用,却增加撤销陈旧窗口与清理复杂度;fail-closed 提高执行强度,却要求更高可用性预算。选型时把这些代价与“在 CI 推广前离线验证一次”比较,低频封闭发布未必需要把外部验证放进每次 API 写路径。
升级、迁移、清理与退出要保持契约同步
升级把 chart、image、CRD、Store/Verifier/Policy、KeyManagementProvider、Ratify response schema、ConstraintTemplate 和 Gatekeeper chart 当作一个版本集合。Helm 不会自动升级 CRD,不能在生产直接照搬“卸载后删除全部 CRD”的快捷步骤;先导出对象和 status,阅读 schema conversion,恢复到隔离集群并运行正反契约测试。回退镜像也不保证能读取已经前向迁移的 CRD 或缓存格式。
迁移旧 CertificateStore 到 KeyManagementProvider、旧 Cosign key/rekorURL 到 trustPolicies、旧报告 Name/Type 到 VerifierName/VerifierType 时,先让候选环境读取现有 subject,比较报告字段和最终 decision。双跑阶段同一 digest 同时请求旧、新 Ratify,只比较结构化结果,不让两个准入 webhook竞争最终决定;确认零报告、错误 identity、Registry 401、超时和撤销后,再切换 Provider URL。
清理测试安装时先导出实际 Helm manifest 与 CRD 实例,删除 Constraint、ConstraintTemplate、Provider、Policy、Verifier、Store、KMP 和专用 Secret,再卸载 Ratify;只有确认 CRD 没有其他租户对象后才处理 CRD。Gatekeeper、Dapr、Redis 或 Registry若为共享服务,不随 Ratify测试环境通用删除。清理后用测试 namespace 确认不存在残留 webhook、ClusterRoleBinding、豁免标签、缓存卷与可用测试凭据。
退出平台时按 digest 导出 subject manifests、OCI reference artifacts、签名/证书/透明日志 bundle、Store/Verifier/Policy/KMP、ConstraintTemplate/Constraint、webhook scope/failure policy、可信根和 decision logs。目标验证器先只读重验历史样本,再让消费者切换;观察期结束后移除 Ratify Provider 与旧 trust policy。最后用旧 key、旧插件、旧 Provider URL和旧豁免身份执行反向请求,预期都无法获得部署权限。退出不是删掉 Helm release,而是证明旧验证路径和旧信任都已失效。
Ratify Getting Started 与多架构验证限制。Ratify Framework Overview。Ratify Verifiers 与支持的验证器
Ratify Gatekeeper Policy Authoring。Gatekeeper fail-open、fail-closed 与恢复死锁
