审计追踪成立的条件
一句话总结
审计追踪需要所运行内容的标识符、可信的生产证据,以及按时间点划分的部署记录。并不是保存的机密值越多,证据就越好。
为什么仅靠一个标签是不够的
标签可以移动到另一个镜像上,而 digest 是内容的标识符。因此,最好用 digest 固定期望的部署,并把它与扫描和签名的对象关联起来。digest 本身并不能证明安全性、作者或源码提交。Kubernetes 镜像
用标签部署,并不意味着完全无法调查当前的镜像。status.containerStatuses[].imageID 中有运行时所识别的镜像信息,它可能与声明的镜像不同。格式和 digest 的含义,要根据运行时和镜像的种类来确认。当前的查询无法还原已经被删除的 Pod 的过去状态,所以还要保存部署当时的标识符和时刻。Kubernetes ContainerStatus 源码
工作原理
把四种证据连接起来
| 证据 | 要确认的内容 | 单独无法证明的内容 |
|---|---|---|
| 镜像 digest | 验证对象与部署对象的一致性 | 没有漏洞、源码提交 |
| 镜像签名 | 符合信任策略的签名者的签名 | 该签名者确实是实际的构建者 |
| SBOM | 组件清单及其与对象的关联 | 清单的完整性、作者的可信度 |
| 构建 provenance | 对象、构建者、输入和构建过程 | 不受信任的构建者的诚实性 |
镜像签名与 SBOM 签名是两回事。即使镜像签名有效,放在旁边的任意 SBOM 文件也并不因此就得到了认证。例如,对于装有 SBOM 的 attestation,不仅要验证签名,还要确认 subject 的 digest 是否与对象相同,以及 predicateType 是否是期望的类型。构建 provenance 也必须验证受信任的构建者,以及预期的源码和构建条件。SLSA 制品验证
Sigstore 的 cosign verify 和 cosign verify-attestation 验证的对象不同。在无密钥验证中,要具体限制所允许的证书身份和 OIDC 签发者。从密码学上签名是对的,与是我们的发布主体进行了签名,是不同的判断。Sigstore 验证指南
扫描报告要把对象 digest、扫描器和漏洞库的版本、检查时刻以及例外绑定在一起。仅仅报告生成成功,并不能成为部署关卡。要区分违反标准和检查器出错,并确认两者是否都会恰当地阻止部署。发现新漏洞时,同一个镜像也必须重新评估,所以不能把构建当时的通过当作永久安全的判定。
不要把 Secret 正文复制到审计日志中
Metadata 会留下用户、时刻、资源、动作等记录,但不会留下请求和响应的正文。Request 包含请求正文,RequestResponse 包含双方的正文。如果以详细级别记录 Secret,敏感内容就可能被复制到日志中。Kubernetes 审计级别
Secret 的 base64 不是加密,所以编码后的值也是暴露。即使收紧了 Secret 的查询权限,只要日志的读者能看到正文,就会通过其他路径泄露。也应避免把机密直接放进 ConfigMap 或 Pod 规格中。Secret 管理原则
下面是不留下正文的起点示例。它不是要用 kubectl apply 应用的工作负载,而是 API 服务器的审计策略文件。实际启用时,需要配置策略文件以及日志和 Webhook 的存储路径,托管服务则要确认提供商的设置。不要原样替换生产配置。
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: ""
resources: ["secrets", "configmaps"]
- level: Metadata
一开始把所有请求都按 Metadata 记录。即使之后添加详细规则,也不要把范围广泛的正文记录规则放在敏感资源保护规则之前。第一个匹配的规则会被应用,所以无法用后面的保护规则覆盖前面的决定。子资源以及其他 API 组中的敏感数据,也要另行审查。审计策略 API 契约
Metadata 也不是公开日志。不要把敏感信息放进请求 URI 或审计注解等处,并要管理日志的查看和导出权限、保留期限、完整性以及采集失败告警。省略正文,并不能保证自动清除整个日志中的机密。
在现场相遇的样子
示例场景:调查负责人不需要机密值,但必须知道是谁读取了生产 Secret。在自己拥有的隔离环境中,用不是真实凭据的合成标记来发出创建、查询、删除请求,并确认相应请求的用户、动作、对象和响应结果是否被留下。同时还要检查是否有 requestObject 和 responseObject,以及合成标记的原文和编码值。如果记录是空的,就只会通过第二个条件,所以必须先确认请求证据是否存在。
采集路径是否正常,也是另一个条件。如果 API 服务器的本地文件中有,而中心存储中没有,就无法通过中心搜索来调查事故。把已知的测试请求一直查找到底,比采集器界面上的绿灯更是直接的证据。
下一项测验要确认什么
判断策略范围的遗漏、NetworkPolicy 与 mTLS 的区别、Secret 的审计级别、digest 与 provenance,以及 SBOM 的关联。
实际确认的范围
2026-09-11,在隔离的 k3s v1.36.4+k3s1 探针上,执行了合成 Secret 的创建、查询、删除,以及未被允许的用户的查询。在 Metadata 下,只留下了四个请求的证据;把详细规则放在前面时,合成正文被暴露了;修改之后,正文又消失了。把 Secret 的记录用 None 关闭时,另外的 /version 对照请求被记录下来,但没有 Secret 的证据,导致验证器失败。
复现和反例检查保存在仓库的 scripts/probe_cnpe_audit.py 和 tests/test_cnpe_audit_probe.py 中。这次确认仅限于单节点的本地审计文件。这并不意味着已经验证或更改了中心采集、日志完整性、所有敏感资源的策略,或者生产集群的审计配置。接下来将在个人 VM 上进行 8 个步骤的实验,亲自复现机密暴露、Metadata 恢复和 None 证据缺失。同时确认采集时刻的摘录与当前 API 的新查询,而这份资料并不能保证中心审计存储的完整性。