MongoDB 7.0副本集本身不支持直接启用Queryable Encryption,该功能必须由客户端驱动(如Node.js≥6.7.0)配合KMS和autoEncryption配置实现,服务端仅处理已加密的查询请求。

MongoDB 7.0 副本集本身不支持直接启用 Queryable Encryption —— 这个功能必须通过带自动加密能力的驱动(如 Node.js、Python、Java 驱动)配合密钥管理服务(KMS)在客户端侧完成,服务端副本集只是被动接收和处理已加密的查询请求。
为什么副本集不能“配置”可查询加密
Queryable Encryption 不是数据库服务端的开关式功能,也不是通过 rs.conf() 或 mongod.conf 启用的选项。它依赖三个不可替代的客户端组件:
- 支持自动加密的驱动版本(例如 Node.js 驱动 ≥ 6.7.0,Python 驱动 ≥ 4.7.0)
- 客户端本地或远程 KMS(如 AWS KMS、Azure Key Vault、本地
local KMS)提供密钥加密密钥(KEK) - 应用代码中显式定义
encryptedFieldsMap并传入autoEncryption配置
副本集节点只负责按标准 BSON 协议解析、路由、执行加密后的查询(比如 { "ssn": { "$eq": BinData(6, "...") } }),不做密钥解封或字段解密。所以你在 mongosh 里运行 rs.status() 或修改 replSetReconfig 完全不影响该特性是否生效。
真正要做的:在连接驱动里启用 autoEncryption
以 Node.js 为例,关键不是改副本集配置,而是构造连接时传入正确的 autoEncryption 参数:
const client = new MongoClient("mongodb://rs1.example.com:27017,rs2.example.com:27017", {
autoEncryption: {
keyVaultNamespace: "encryption.__keyVault",
kmsProviders: {
local: {
key: Buffer.from("...", "base64"), // 96字节本地 KEK
},
},
encryptedFieldsMap: {
"sensitive.users": {
fields: [
{ path: "ssn", bsonType: "string", queries: { queryType: "equality" } },
{ path: "salary", bsonType: "double", queries: { queryType: "range" } }
]
}
}
}
});
注意几个硬性条件:
-
keyVaultNamespace对应的集合必须已存在,且含有效密钥文档(用createKey方法生成) - 副本集所有节点必须能被驱动正常发现(即
mongosh能连上主节点并执行rs.status()) - 驱动连接字符串中必须包含全部种子节点(或使用 SRV 记录),不能只写一个节点地址
- 若用
localKMS,KEK 必须严格为 96 字节;用 AWS KMS 时需确保 IAM 角色有kms:Decrypt权限
常见报错与对应检查点
遇到加密失败,优先查这些地方,而不是怀疑副本集配置:
-
AutoEncryptException: key not found for namespace→ 检查keyVaultNamespace是否拼写正确,且对应集合中已有匹配keyAltNames的密钥文档 -
Invalid key document: missing 'keyMaterial'→createKey未成功执行,或密钥被意外删改 -
Failed to connect to KMS provider→ 网络不通(AWS KMS endpoint 被防火墙拦截)、凭据过期、或kmsProviders对象结构错误(比如漏了local.key) - 查询返回空结果但无报错 → 很可能是字段未加密就写入(驱动未启用 autoEncryption)或
encryptedFieldsMap中路径与实际文档结构不一致(如写成"user.ssn"但实际是"profile.ssn")
社区版 vs Atlas:功能差异直接影响落地
如果你用的是 MongoDB 社区版(非 Atlas),必须自己部署密钥管理并严格控制 local KMS 密钥分发 —— 因为社区版不支持 automatic key rotation 或托管 KMS 集成。而 Atlas 用户可以直接勾选 UI 中的 Queryable Encryption 开关,后台自动创建 __keyVault、注入 KMS 凭据、校验驱动兼容性。
最容易被忽略的一点:即使副本集启用了 TLS(SSL)、开启了 enableEncryption(TDE),这些和 Queryable Encryption 完全无关。前者保护静态数据和传输链路,后者保护的是查询逻辑和内存中明文字段 —— 两者必须同时启用,才构成纵深防御。


















