证书生命周期自动化与私有PKI实战
证书故障往往不是加密算法问题,而是资产不清、续期未部署、信任链不一致、私钥泄露或根证书轮换没有计划。一个成熟的证书体系应能回答:谁签发、谁使用、何时到期、如何续期、私钥存在哪里、泄露后如何吊销,以及根证书更换时哪些终端会受影响。
本文覆盖公网TLS、内部服务证书、mTLS和私有PKI的运维方法。示例用于说明流程,生产CA的算法、密钥保护、证书策略和合规要求应由安全团队评审。根CA私钥不应长期在线,也不应复制到普通服务器。
一、先区分四类对象
| 对象 | 作用 | 典型生命周期 |
|---|---|---|
| 根CA | 信任锚,签发中间CA | 多年,通常离线保存 |
| 中间CA | 负责日常签发 | 数年,可分环境或用途 |
| 终端证书 | 服务器、客户端、设备或工作负载身份 | 数小时到数月 |
| 信任库 | 客户端认可的根和中间证书 | 随组织策略分发与更新 |
不要把“把自签名证书复制到服务器”当成私有PKI。真正的PKI还包括身份校验、签发策略、密钥保护、吊销、审计、轮换和信任分发。
二、建立证书资产清单
每张证书至少记录:
- 证书用途、业务和技术负责人;
- 域名、IP、URI等SAN;
- 签发者、序列号、指纹和算法;
- 生效时间、到期时间和建议续期时间;
- 部署位置、负载均衡器、代理或Secret名称;
- 私钥存储方式、权限和是否可导出;
- 自动续期客户端、重载命令和验证探测;
- 是否用于mTLS、代码签名、用户认证或设备身份;
- 吊销与紧急替换流程。
可从外部探测公开服务:
openssl s_client -connect app.example.com:443 \
-servername app.example.com -showcerts </dev/null
查看本地证书:
openssl x509 -in server.crt -noout \
-subject -issuer -serial -dates -fingerprint -sha256 -ext subjectAltName
资产清单必须覆盖入口负载均衡、CDN、API网关、邮件、VPN、数据库、中间件、Kubernetes Secret、Windows证书存储和网络设备。只扫描公网443端口会漏掉大量内部证书。
三、公网证书与私有证书的边界
| 场景 | 建议信任来源 |
|---|---|
| 面向公网浏览器的域名 | 公共受信CA |
| 内网Web与API | 私有CA或受控公共证书 |
| 服务间mTLS | 私有CA、服务网格或工作负载身份系统 |
| 无固定域名的设备 | 私有CA并绑定设备身份 |
| 代码或文档签名 | 专用签名证书和独立策略 |
不要将公共证书用于所有内部工作负载,也不要让公网用户依赖组织私有根证书。不同用途应使用不同中间CA,缩小密钥泄露的影响范围。
四、ACME自动化的核心流程
ACME将“证明标识控制权—提交CSR—签发证书—自动续期”标准化。常见挑战:
HTTP-01:通过80端口提供挑战文件,适合普通Web服务;DNS-01:通过DNS TXT记录证明控制权,适合通配符和无法开放80端口的场景;TLS-ALPN-01:通过TLS握手完成验证,需客户端和入口支持。
自动续期不是只运行客户端。完整链路包括:
- 申请或更新证书;
- 安全写入证书与私钥;
- 原子替换,避免只更新其中一个文件;
- 检查配置语法;
- 平滑重载服务;
- 从客户端重新握手验证新证书;
- 更新资产清单并记录审计事件;
- 失败时告警且保留旧证书。
五、Nginx自动续期示例思路
无论使用哪种ACME客户端,都应把部署钩子设计为可重复执行:
nginx -t && systemctl reload nginx
重载后再验证真实入口,而不是只检查磁盘文件:
echo | openssl s_client -connect app.example.com:443 \
-servername app.example.com 2>/dev/null | \
openssl x509 -noout -serial -dates -fingerprint -sha256
如果前面还有CDN、云负载均衡或WAF,外部探测看到的证书可能不在当前服务器上。必须分别检查每一层终止TLS的位置。
六、Kubernetes证书自动化
Kubernetes通常由cert-manager等控制器把证书写入TLS Secret。运维重点不是资源显示Ready,而是完整验证:
- Issuer或ClusterIssuer认证是否有效;
- Challenge和Order是否成功;
- Secret是否包含匹配的证书与私钥;
- Gateway或Ingress是否引用正确Secret;
- 续期后数据平面是否加载新证书;
- 控制器权限是否限制在必要范围。
常用检查:
kubectl get certificate,certificaterequest,order,challenge -A
kubectl describe certificate -n app-prod app-tls
kubectl get secret -n app-prod app-tls -o jsonpath='{.data.tls\.crt}' | \
base64 -d | openssl x509 -noout -dates -issuer -subject
不要把私钥内容输出到工单、聊天、日志或CI构建记录。
七、使用step-ca建设轻量私有CA
step-ca适合需要私有ACME、短期X.509或SSH证书的环境。典型设计:
离线根CA
└─ 在线中间CA(step-ca)
├─ ACME供Nginx、Apache、设备使用
├─ cert-manager供Kubernetes使用
└─ OIDC或其他Provisioner供人员/工作负载使用
基础过程包括:
- 在隔离环境初始化根与中间CA;
- 将根私钥离线保管,中间私钥放入受保护存储;
- 配置域名、签发策略、最大有效期和Provisioner;
- 向受控终端分发根证书;
- 为客户端配置ACME目录地址;
- 监控签发、续期、失败和CA到期时间;
- 定期执行备份和恢复演练。
启用ACME Provisioner的命令示例:
step ca provisioner add acme --type ACME
生产部署应使用服务管理、反向代理、访问控制、持久数据库和备份,不应把开发环境中的单进程启动命令直接作为生产方案。
八、Vault PKI的适用场景
Vault PKI可按角色限制域名、TTL、密钥类型和签发权限,适合已经运行Vault并需要动态证书、审计和多团队隔离的环境。重点设计:
- 根CA是否外部托管或离线;
- 中间CA是否按环境、业务或有效期拆分;
- Role允许的域名、子域、通配符和最大TTL;
- 认证方式是否使用工作负载身份而非长期Token;
- CRL、OCSP、AIA和签发URL是否稳定可达;
- Vault不可用时,业务能否使用现有证书继续运行;
- CA和存储备份是否经过恢复验证。
Vault支持多个Issuer后,根与中间CA轮换可以在同一挂载中分阶段完成,但仍需规划新旧链并存和信任库更新顺序。
九、私钥保护
私钥的安全级别应与证书用途匹配:
- 根CA私钥离线、分权保管,操作有双人复核;
- 中间CA私钥使用HSM、KMS或严格受控的加密存储;
- 服务器私钥权限最小化,不进入镜像和源码仓库;
- Kubernetes Secret启用静态加密和RBAC限制;
- Windows使用不可导出密钥或受控证书存储;
- CI/CD只在必要阶段短时获得签发能力;
- 备份私钥必须加密,并与解密材料分开保存。
证书通常不是秘密,私钥才是。日志脱敏规则应重点识别PEM私钥、PFX口令、CA令牌和DNS API密钥。
十、根CA和中间CA轮换
错误的轮换顺序会导致全网不信任。推荐步骤:
- 生成新根或新中间CA并保护私钥;
- 在终端信任库中增加新根,暂时保留旧根;
- 验证主要操作系统、JVM、容器和网络设备已经获得新信任;
- 开始用新中间CA签发终端证书;
- 观察握手失败、证书链和旧证书存量;
- 等旧终端证书到期或完成替换;
- 再从信任库移除旧根;
- 归档或销毁旧私钥并保留审计记录。
轮换期间服务端可提供兼容链,但不同客户端的链构建行为可能不同,必须用真实终端测试,不应只用单一OpenSSL版本验证。
十一、到期监控与SLO
建议分级告警:
| 剩余时间 | 建议动作 |
|---|---|
| 60~90天 | 资产负责人确认续期链路 |
| 30天 | 工单跟踪,验证自动续期和部署钩子 |
| 14天 | 提升告警等级,安排人工替换准备 |
| 7天以内 | 事件化处理,建立每日跟踪 |
短期证书应按“生命周期比例”告警,例如有效期24小时的证书不能等到剩余7天。还应监控:
- ACME签发与续期失败次数;
- Challenge、DNS API和CA可用性;
- 线上握手返回证书与资产清单是否一致;
- 不受信、主机名不匹配、链不完整和弱算法;
- 即将到期的根CA和中间CA。
十二、证书泄露响应
发现私钥可能泄露时:
- 确认影响证书、使用位置和访问范围;
- 立即阻断继续访问私钥,保留审计证据;
- 生成新密钥,不要沿用旧私钥续签;
- 签发并部署新证书;
- 吊销旧证书或停止信任旧身份;
- 验证所有入口与客户端已经使用新证书;
- 检查源码、镜像、日志、备份和工单中的泄露副本;
- 复盘为什么私钥可以被读取或外传。
吊销并不保证所有客户端立即检查CRL或OCSP,因此快速替换、缩短有效期和限制私钥权限同样重要。
十三、常见故障
- 自动续期成功,但服务没有重载,线上仍返回旧证书;
- 只更新证书文件,没有更新中间链;
- 证书包含CN但缺少正确SAN;
- DNS-01清理过早或DNS传播未完成;
- 根证书只装进操作系统,JVM或设备使用独立信任库;
- PFX导入时私钥不可用或权限属于错误账号;
- Kubernetes Secret已更新,数据平面控制器未重新加载;
- 时间同步异常导致证书被判断为尚未生效或已经过期;
- 根CA轮换时先删除旧根,导致旧证书全部失效。
十四、上线检查清单
- [ ] 已建立证书、使用位置、负责人和到期时间清单;
- [ ] 公网证书与私有证书的信任边界明确;
- [ ] 根CA离线,中间CA和终端私钥受到适当保护;
- [ ] 自动续期包含部署、重载和线上握手验证;
- [ ] 到期监控同时覆盖终端证书、根CA和中间CA;
- [ ] ACME账号、DNS API密钥和CA令牌不进入日志;
- [ ] 证书轮换、泄露、吊销和紧急替换流程已演练;
- [ ] 备份包含CA配置、数据库和必要密钥,并验证可恢复;
- [ ] 真实客户端、JVM、容器和设备的信任链均已测试;
- [ ] 所有证书变更可关联到工单和审计记录。