You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
libmongocrypt:客户端字段级加密依赖 libmongocrypt,它是 MongoDB 驱动程序实现客户端加密/解密的核心组件,对应的 Node.js NPM 包为 mongodb-client-encryption,需要注意这个包依赖于 libbson 和 libmongocrypt C 库,需要 C++ 工具链,但是做为 Node.js Addons 插件,其已经利用 prebuild 在 CI 期间做了模块的预先编译,直接 npm i mongodb-client-encryption 安装即可,如果网络环境问题链接不上 github.com 可能就很麻烦了需要手动构建、编译,因为对模块的预先编译是放在 Github 上的。
mongocryptd:客户端加密必须要 mongocryptd 进程启动才能正常工作,刚开始一直遇到一个问题: MongoError: BSON field 'insert.jsonSchema' is an unknown field. This command may be meant for a mongocryptd process. 貌似就是因为 mongocryptd 进程没有启动导致的。在 MongoDB Server 企业版中包含 mongocryptd 这个组件的,解决办法也很简单就是本机安装下企业版,尽管我们这里使用的是 MongoDB Atlas 也要安装的,安装方法参考 docs.mongodb.com/manual/tutorial/install-mongodb-enterprise-on-os-x。
项目准备
做一些初始化工作,安装依赖、配置文件、创建一个常规的 MongoDB client。
项目初始化
mkdir nodejs-mongodb-client-encryption
cd nodejs-mongodb-client-encryption
npm init
npm i mongodb mongodb-client-encryption -S
某些场景下,对于数据隐私会有较高的要求,例如,用户系统的个人信息(身份证、手机号)、医患系统的患者信息等,怎么用技术手段安全的保护这些敏感数据是我们开发人员需要考虑的问题。
本篇文章,将介绍 MongoDB 的客户端字段级加密功能,英文全称为 Client-Side Field Level Encryption,在有些地方会看到简称为 CSFLE,代表的是一个意思,下文有些地方也会这样称呼。
该功能允许开发人员将数据保存到 MongoDB 服务器之前选择性的指定数据字段进行加密,这些加密/解密操作都是事先在客户端完成,与服务器通信时完全是加密的,最终只有配置了 CSFLE 客户端才能读取和写入敏感数据字段。
文末列举了几个使用中的常见错误原因,如有遇到类似错误可以做为参考。
环境要求
MongoDB Server 选择:MongoDB 客户端字段级加密分为自动加密、手动加密两种类型,自动加密社区版是不支持的,需要 MongoDB Server 4.2 企业版 或 MongoDB Atlas,学习使用推荐 MongoDB Atlas,它是在云服务器中托管的 MongoDB 服务器,不需要安装,且提供了免费的入门套餐是够我们学习使用了。
驱动兼容性:使用支持 CSFLE 功能的 Node.js MongoDB 驱动程序,3.4+ 以上版本是支持的,快速入门。
libmongocrypt:客户端字段级加密依赖 libmongocrypt,它是 MongoDB 驱动程序实现客户端加密/解密的核心组件,对应的 Node.js NPM 包为 mongodb-client-encryption,需要注意这个包依赖于 libbson 和 libmongocrypt C 库,需要 C++ 工具链,但是做为 Node.js Addons 插件,其已经利用 prebuild 在 CI 期间做了模块的预先编译,直接 npm i mongodb-client-encryption 安装即可,如果网络环境问题链接不上 github.com 可能就很麻烦了需要手动构建、编译,因为对模块的预先编译是放在 Github 上的。
mongocryptd:客户端加密必须要 mongocryptd 进程启动才能正常工作,刚开始一直遇到一个问题:
MongoError: BSON field 'insert.jsonSchema' is an unknown field. This command may be meant for a mongocryptd process.
貌似就是因为 mongocryptd 进程没有启动导致的。在 MongoDB Server 企业版中包含 mongocryptd 这个组件的,解决办法也很简单就是本机安装下企业版,尽管我们这里使用的是 MongoDB Atlas 也要安装的,安装方法参考 docs.mongodb.com/manual/tutorial/install-mongodb-enterprise-on-os-x。项目准备
做一些初始化工作,安装依赖、配置文件、创建一个常规的 MongoDB client。
项目初始化
mkdir nodejs-mongodb-client-encryption cd nodejs-mongodb-client-encryption npm init npm i mongodb mongodb-client-encryption -S
配置文件
创建一个 index.js 文件,核心代码逻辑都在该文件编写,
创建常规 Client
数据加密密钥
MongoDB 驱动程序自动加密/解密时需要访问事先创建的数据加密密钥,而这个密钥经过程序的处理会存储在密钥保管数据库的集合中,以下是创建一个数据加密密钥的交互图。
创建主密钥
创建 MongoDB 数据加密密钥还需要另外一个称为 “主密钥” 的密钥进行加密,下图展示了创建主密钥的流程:
主密钥的存储,生产环境 MongoDB 官方的推荐是使用密钥管理服务(KMS):亚马逊网络服务 KMS、Azure 密钥保管库、谷歌云平台密钥管理,更多内容可阅读 客户端字段级加密:使用 KMS 存储主密钥。
学习为目的,简单方便些可使用本地密钥提供程序存储主密钥,这种方式不安全,不适合生产。
创建一个脚本文件
create-master-key.js
,生成一个 96 字节的密钥文件,并写入到本地文件系统的 master-key.txt 文件中。指定 KMS 程序配置
客户端使用如下配置发现主密钥,local 表示的是使用本地主密钥。
获取或创建数据加密密钥
写一个函数 getOrCreateDataKey 分别传入创建的常规 client、上面指定的 KMS 程序配置,该方法目的是获取一个数据密钥,如果不存在则创建,实现为以下几个步骤:
验证数据加密密钥是否成功创建
调用编写好的方法,验证下数据加密密钥是否创建成功。
我使用 Robo 3T 链接的 Atlas 集群,如果一切正常,你会看到在 encryption.__keyVault 集合中有如下一条密钥记录,_id 字段就是为我们需要的数据加密密钥,使用 Base64 格式编码。
JSON Schema 定义
Node.js 驱动程序使用 JSON Schema 定义集合需要加密的字段,文档类型定义使用 BSON 类型。
CSFLE 客户端验证读写操作
在有了数据加密密钥、JSON Schema 之后可以创建一个支持 CSFLE 的 Mongo client,该客户端和 MongDB 服务器交互,读取/写入带有加密字段的数据。
读写操作流程图
下图展示了客户端应用程序和驱动程序为写入字段级加密数据的一个步骤:
下图展示了客户端应用程序和驱动程序为读取加密后字段进行解密操作的一个过程:
创建 CSFLE 客户端
创建 CSFLE 的 mongo client 与常规 mongo client 相比较,需要多传入 autoEncryption 对象,以下参数含义分别为:
执行读写操作验证
在拥有 CSFLE 客户端后,执行一些读写操作,创建一条用户记录,下面的代码和我们常规的读写操作没什么区别,并且 phone 这个字段虽然是经过加密的,我们仍可使用该字段做为索引,更新/查找数据。
当成功插入一条记录之后,在 Robo 3T 工具查询该集合,可以看到需要的字段都已经做了加密,尽管我是一个管理员能够查看数据,也无法查看这些隐私数据。
只能通过程序正确的创建了 CSFLE 的客户端才能读取出解密后的数据。
几个常见错误
文中示例测试时常见的几个错误,可以做为参考。
认证失败
遇到
Authentication failed
错误,基本上都是连接字符串的账号密码或权限错误,使用 MongoDB Atlas 的需要检查下数据库的访问权限配置创建加密客户端链接失败
下面的报错很简单就是服务器链接不上。需要注意的是文中创建加密客户端还会去链接本地安装的 MongoDB 企业版 Server,在本地启动 MongoDB 企业版 Server 时需要指定下端口
bin/mongod --dbpath data --logpath logs/mongo.log --port 27020
。mongocryptd 进程注意事项
在刚开始的环境要求里有提到过 mongocryptd 进程,它会在这里检查 JSON Schema 中定义的加密指令,也就是 getCSFLEClient() 传入的 schemaMap 参数,如果 mongocryptd 进程没有启动,这里会一直报错。
以下是我最开始一直遇到的一个问题,解决办法很简单:
autoEncryption.bypassAutoEncryption=true
会自动生成 mongocryptd 进程。总结
MongoDB 提供的客户端字段级自动加密,对于有数据隐私需要加密保护的还是很方便的,在配置了 CSFLE 客户端后应用程序在读写操作时和常规的客户端读写操作是没有差别的,唯一的阻碍可能是仅企业版支持。
文中我们将主密钥存储放在了本地的文件系统中,这在本地测试环境是可以的,但是生产环境不要用这种方式,因为任何能够访问您本地文件系统主密钥的人都可以读取您的数据加密密钥,建议放在更安全的地方,例如密钥管理系统(KMS)。
Reference
完整代码:
The text was updated successfully, but these errors were encountered: