MongoDB本身不直接通过KMS加密数据,而是依赖客户端字段级加密(CSFLE)或加密存储引擎;KMS仅托管客户主密钥(CMK),数据加密密钥(DEK)由CMK加密后存入keyVault,加解密全程在应用层完成。

keyVault 集合,再由驱动在应用层完成加解密。
你得先明确用的是哪一层加密:是应用侧的 CSFLE(推荐用于字段级可控加密),还是服务侧的加密存储引擎(整库/整卷静态加密)。两者都用 KMS,但集成方式、密钥流和风险点完全不同。
CSFLE 场景下怎么让 KMS 参与加密?
这是最常见也最灵活的方式:加密逻辑在应用代码里,KMS 只管保护 DEK 的 CMK。
-
ClientEncryption.createDataKey()调用时,必须传入kmsProviders和dataKeyOpts,其中dataKeyOpts.keyAltNames或dataKeyOpts.masterKey指向你的 CMK(比如 AWS KMS 的 ARN、GCP 的key_name) - CMK 不接触明文数据,只用来加密新生成的 DEK;DEK 才真正加密 BSON 字段,且全程不出客户端内存
- 驱动自动把加密后的 DEK 存进
keyVault集合(默认是admin.keyvault),字段加密时靠_id或keyAltName查找对应 DEK - 务必提前在
keyVault上建部分唯一索引:db.keyvault.createIndex({ keyAltNames: 1 }, { unique: true, partialFilterExpression: { keyAltNames: { $exists: true } } }),否则备用名冲突会静默失败
加密存储引擎用 KMS 怎么配?
这是服务器级静态加密,KMS 用于保护存储引擎的主密钥(不是 DEK/CMK 那套),只适用于 WiredTiger 引擎。
- 启动 mongod 时必须指定
--enableEncryption --encryptionKeyFile或--kmipServerName等参数;若用 KMIP 协议对接第三方 KMS,需在配置文件中启用security.kmip并设好证书路径 - 注意:MongoDB 无法对已有数据启用加密存储引擎 —— 必须从空实例开始,否则会报错
Encrypted storage engine requires empty data directory - KMIP 默认用 1.2 协议;若 KMS 设备只支持 1.0/1.1,得在配置里显式设
security.kmip.useLegacyProtocol: true - KMIP 服务端必须开放
operation_create、operation_get、operation_encrypt等权限,否则 mongod 启动卡在密钥获取阶段
轮换 CMK 时最容易丢数据的操作
轮换不是改个配置就完事,关键在 keyVault.rewrapManyDataKey() 这步——它才是真正把旧 DEK 用新 CMK 重新封装的动作。
- 必须先在 KMS 侧完成 CMK 轮换(比如 AWS KMS 中启用新密钥、禁用旧密钥),再调用
rewrapManyDataKey();顺序反了会导致新加密失败 - 执行前确认旧 CMK 尚未被删除:一旦删掉,所有用它加密过的 DEK 都无法解封,
rewrapManyDataKey()会直接报错KeyNotFound或InvalidKey - 该命令不自动回滚,如果中途失败(如网络断开),部分 DEK 可能已重包装、部分没动——此时必须人工检查
keyVault中每个 DEK 的masterKey.version字段是否一致 - 别漏掉
keyAltNames:如果应用靠备用名查 DEK,轮换后要确保新旧 CMK 对应的 DEK 都保留相同keyAltNames,否则查询会找不到密钥
kmsProviders 对象写错字段名(比如把 gcp 写成 google),或者忘了给 keyVault 集合开读写权限。

















