Vault生成的TLS证书无法被MongoDB自动加载,必须通过外部机制原子替换tlsCertificateKeyFile文件并触发db.rotateCertificates()或SIGUSR1信号;客户端需重建连接池,否则复用旧TLS会话导致失败。

Vault 生成的 TLS 证书如何被 MongoDB 客户端动态加载?
MongoDB 本身不支持“自动轮换证书”这个动作——它只认当前加载的 tlsCertificateKeyFile 文件内容。所谓“自动轮换”,本质是让客户端(或驱动)在证书过期前,用新证书替换旧文件,并触发连接重连或热重载。关键在于:**你得自己监听 Vault 的证书更新事件,再写个轻量代理或钩子来刷新文件并通知 MongoDB 进程**。
常见错误现象:SSL handshake failed 或 unable to get local issuer certificate,往往不是 Vault 没发新证书,而是 MongoDB 还在读旧文件、没重启也没 reload。
- Vault 需启用
cert引擎并配置ttl/max_ttl,确保能定期签发新证书 - 客户端侧必须调用 Vault 的
/v1/cert/issue(或使用vault write -field=certificate cert/issue/my-role)获取新证书+私钥 - 不能直接覆盖正在被 mongod/mongos 使用的
tlsCertificateKeyFile,否则可能触发 OpenSSL 错误;建议先写入临时路径,再mv原子替换 - Linux 下可用
kill -SIGUSR1(仅限 mongod 6.0+)触发 TLS 配置重载,但需确认启动时带了--tlsMode=requireTLS且未用--tlsDisabledProtocols破坏热重载能力
mongod 能否监听文件系统变化自动重载证书?
不能。MongoDB 没有 inotify 或 fsnotify 集成,mongod 启动后只在初始化 TLS 时读一次 tlsCertificateKeyFile,后续修改完全无感。硬要“自动”,就得靠外部工具补位。
推荐做法是写一个简短的轮询脚本(例如每 15 分钟执行一次),对比 Vault 返回的证书指纹与本地文件是否一致:
#!/bin/bash NEW_CERT=$(vault write -field=certificate cert/issue/my-role) NEW_KEY=$(vault write -field=private_key cert/issue/my-role) echo "$NEW_CERT$NEW_KEY" | openssl x509 -noout -fingerprint -sha256 2>/dev/null | cut -d'=' -f2 > /tmp/new.fp openssl x509 -in /etc/mongo/tls.pem -noout -fingerprint -sha256 2>/dev/null | cut -d'=' -f2 > /tmp/old.fp if ! cmp -s /tmp/old.fp /tmp/new.fp; then echo "$NEW_CERT$NEW_KEY" > /tmp/tls.new.pem mv /tmp/tls.new.pem /etc/mongo/tls.pem kill -SIGUSR1 $(cat /var/run/mongodb/mongod.pid) fi
- 注意:
kill -SIGUSR1仅对 mongod 有效,mongos 不支持该信号 - 若用 systemd,可改用
systemctl reload mongodb,但 reload 会中断连接,不如 SIGUSR1 平滑 - 别用
cat $CERT $KEY > tls.pem—— Vault 返回的private_key是 PEM 格式但不含-----BEGIN RSA PRIVATE KEY-----头尾,需手动补全或改用pkcs8格式输出
Go 驱动中如何避免硬编码证书路径实现动态加载?
如果你用的是应用层连接 MongoDB(比如 Go 服务),比改 mongod 更灵活:直接在代码里定期从 Vault 拉证书,构造新的 *x509.CertPool 和 tls.Config,再传给 mongo.Connect()。
关键点不在驱动版本,而在你是否绕过了文件系统依赖:
- 用
vault api调用cert/issue接口,缓存响应中的certificate、private_key、ca_chain - 每次新建 client 前,调用
tls.X509KeyPair([]byte(cert), []byte(key))生成tls.Certificate - 把 CA 证书加入
tls.Config.RootCAs,否则会报x509: certificate signed by unknown authority - 不要复用同一个
*mongo.Client跨证书周期——MongoDB 驱动不支持运行时切换 TLS 配置,必须client.Disconnect()后重建
为什么用 Vault Agent Auto-Auth + Caching 仍可能失败?
因为 Vault Agent 默认不会把证书写到磁盘供 mongod 读取,它的 auto_auth 只负责维持 token,cache 只缓存 secret 数据,不触发文件落地或进程通知。
除非你显式配置 template 模块写文件并绑定 command:
template {
source = "/vault/templates/cert.tpl"
destination = "/etc/mongo/tls.pem"
command = "kill -SIGUSR1 $(cat /var/run/mongodb/mongod.pid)"
}
但要注意:template 渲染依赖于 Vault Agent 的 cache freshness,而 cache TTL 若设得太长(比如 1h),就可能错过 Vault 后端的证书吊销或提前轮换。
最容易被忽略的一点:Vault 的 cert 引擎颁发的证书默认包含 extKeyUsage = serverAuth, clientAuth,但 MongoDB 服务端只要求 serverAuth,客户端只要求 clientAuth。如果用同一张证书既当 server 又当 client(比如 mongos ↔ shard),务必确认 allowed_usages 中两者都启用,否则握手会静默失败。


















