在 TPM 2.0 芯片中存储密钥并验证容器签名
解读
国内金融、政务云及等保 2.0 三级以上场景,普遍要求密钥不出硬件。TPM 2.0 作为主板级可信根,可提供持久化 SRK(Storage Root Key)与 NV 索引区,满足“密钥硬件绑定 + 远程证明”合规需求。Docker 容器镜像签名若能在 TPM 内部完成验签,即可实现“镜像完整性 → 节点可信 → 运行时拒绝篡改”的闭环,解决传统 cosign verify 仅把公钥放文件系统、易被替换的痛点。面试官想确认候选人是否能把Docker 内容信任机制与**国产 TPM 2.0 芯片(国民技术、国芯、信大捷安等)**打通,落地到 CI/CD 与 K8s 准入控制。
知识点
- TPM 2.0 密钥层次:SRK → RSA/ECC 子密钥 → NV 索引;密钥模板固定为
TPM2_RH_OWNER,属性位fixedTPM|fixedParent|sensitiveDataOrigin保证私钥不可导出。 - Docker 镜像签名规范:OCI Image Layout + SimpleSigning JSON;摘要算法国内要求SM3 或 SHA-256;签名格式支持 RSA-PSS 与 ECDSA-P256,与 TPM 2.0 默认算法兼容。
- 验签流程:
docker pull→containerd调用 Notation 或 Cosign → 插件从 TPM 2.0 加载公钥证书 → 使用 TPM2_VerifySignature 命令完成摘要校验 → 结果写入 Attestation Key 供节点远程证明。 - 密钥密封:把签名私钥密封到 TPM NV 索引,绑定 PCR0~7(BIOS、GRUB、内核、systemd、Docker 版本)值;节点启动时若 PCR 值变动,TPM 拒绝解封,容器无法解密签名密钥,直接阻断启动。
- 国产算法适配:若芯片仅支持 SM2/SM3,需把 Cosign 的 x509.Verify 替换为 国密 GM/T 0009 验签库,并在 TPM2_CreateLoaded 时指定
TPM_ALG_SM2算法标识(0x001B),此步骤需重新编译 tpm2-tss 与 tpm2-openssl 引擎。 - CI/CD 集成:在 GitLab-Runner 或 Jenkins in Kubernetes 阶段,调用 tpm2-tools 容器(privileged 模式)把公钥证书写入 ConfigMap,私钥句柄以
0x81000002形式注入;准入控制器(如 Kyverno)通过 TPM2_Quote 验证节点 PCR 值后再放行 Pod。 - 故障排查:
tpm2_getcap handles-persistent查看句柄是否丢失;tpm2_pcrread sha256:0,1,2,3核对 PCR 值;journalctl -u docker检查 dockerd 是否启用 cri-containerd 的 verity-plugin;若出现TPM_RC_PCR_CHANGED,需重新密封密钥或更新白名单。
答案
- 在节点上安装 tpm2-tss 3.2.0、tpm2-abrmd 与 tpm2-tools 5.5,确认
/dev/tpmrm0存在; - 生成签名密钥对:
私钥句柄tpm2_createprimary -C o -g sha256 -G rsa2048 -c primary.ctx tpm2_create -C primary.ctx -g sha256 -G rsa2048:rsapss:null -u key.pub -r key.priv -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|sign" tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx tpm2_evictcontrol -C o -c key.ctx -F 0x810000020x81000002永驻 TPM,不可导出; - 在 CI 阶段用 cosign 签名镜像:
tpmkms 插件需提前编译进 cosign,底层调用 TPM2_Sign 完成 SM2/RSA-PSS 签名;cosign sign --key tpmkms://0x81000002 registry.cn-shanghai.aliyuncs.com/myapp:v1.2.0 - 节点端配置 docker-content-trust=0,由 containerd 接管;在 /etc/containerd/config.toml 启用 cri 插件的
enable_tls_streaming = true,并加载 verity 快照插件; - 创建 Kyverno ClusterPolicy:
其中verifyImages: - image: "registry.cn-shanghai.aliyuncs.com/myapp*" key: | -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... -----END PUBLIC KEY----- attestors: - entries: - tpm: quote: nonce: "{{ random }}" pcr: ["0","1","2","3"] publicKeyHandle: "0x81000003"0x81000003为 AK(Attestation Key) 句柄,policy 要求 PCR 值与密封时一致; - 当 Pod 调度到节点,kubelet 调用 containerd 拉取镜像,verity-plugin 通过 tpm2_verifyquote 校验节点 PCR,再用 TPM2_VerifySignature 验证镜像签名;任一环节失败,Pod 创建事件返回
FailedCreatePodSandBox,并提示tpm: signature verification failed; - 升级维护:节点内核升级导致 PCR 值变化,需提前在 维护窗口 使用
tpm2_policypcr重新计算新 PCR 摘要,并执行tpm2_unseal→tpm2_seal把签名密钥密封到新的 PCR 策略,保证业务容器可继续启动。
拓展思考
- 双因子加固:把 TPM 2.0 与 国密 USBKey(SKF 接口) 做“协同签名”,私钥分片分别存于 TPM 和 USBKey,验签时需同时在线,满足**人行《金融容器云安全指引》**对“多因子密钥拆分”要求。
- 零信任网络:结合 Istio + SPIFFE 把 TPM 的 AK 证书作为 nodeattestor,Envoy SDS 动态下发 mTLS 证书,实现“容器签名验证 → 节点身份 → 东西向流量加密”全链路可信;
- 跨云灾备:利用 TPM 2.0 的 Duplication 功能,把签名密钥安全迁移到异地机房 TPM,流程需授权策略
TPM2_PolicyAuthorize并由国密 CA 签发跨域证书,解决“密钥不离境”前提下的多云容灾难题; - 性能调优:TPM 2.0 单核频率仅 100 MHz,RSA-2048 签名 QPS ≈ 30;高并发场景可启用 tpm2-abrmd 的连接池 + 批量验签缓存,或把摘要计算 offload 到 CPU 的 SM3 扩展指令,降低 40% 延迟;
- 合规审计:通过 tpm2_eventlog 把节点启动度量写入 Lark/钉钉机器人,PCR 值与镜像签名验证结果实时推送至等保测评平台,满足公安部 151 号文对“关键操作可追溯”要求。