外观
MongoDB 数据加密
传输加密(TLS/SSL)
基本概念
加密原理
- 使用 TLS/SSL 协议加密 MongoDB 客户端和服务器之间的通信
- 防止网络窃听和中间人攻击
- 验证服务器身份,确保客户端连接到正确的服务器
适用场景
- 生产环境中的 MongoDB 部署
- 跨网络的 MongoDB 连接
- 对安全性要求较高的应用场景
配置方法
生成 TLS/SSL 证书
bash# 生成 CA 私钥 openssl genrsa -out ca.key 4096 # 生成 CA 证书 openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt # 生成服务器私钥 openssl genrsa -out mongodb.key 2048 # 生成证书签名请求 openssl req -new -key mongodb.key -out mongodb.csr # 生成服务器证书 openssl x509 -req -in mongodb.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out mongodb.crt -days 365 -sha256 # 合并证书和私钥 cat mongodb.key mongodb.crt > mongodb.pem配置 MongoDB 服务器
yaml# mongod.conf net: port: 27017 bindIp: 0.0.0.0 tls: mode: requireTLS certificateKeyFile: /etc/mongodb/mongodb.pem CAFile: /etc/mongodb/ca.crt security: authorization: enabled配置 MongoDB 客户端
bash# 使用 TLS 连接 MongoDB mongo --host mongodb.example.com --port 27017 --tls --tlsCAFile /etc/mongodb/ca.crt --tlsCertificateKeyFile /etc/mongodb/client.pem --username admin --password password --authenticationDatabase admin
最佳实践
证书管理
- 使用有效期较长的证书(建议 1-3 年)
- 定期轮换证书
- 安全存储私钥,设置适当的权限
- 使用受信任的 CA 颁发证书
TLS 版本和加密套件
- 使用 TLS 1.2 或 TLS 1.3
- 配置强加密套件
- 禁用不安全的 TLS 版本(如 TLS 1.0、TLS 1.1)
客户端配置
- 客户端连接时验证服务器证书
- 考虑使用客户端证书认证
- 配置适当的 TLS 选项
静态加密(Encryption at Rest)
基本概念
加密原理
- 对存储在磁盘上的数据进行加密
- 防止物理设备丢失或被盗导致的数据泄露
- 加密发生在存储引擎层面
适用场景
- 生产环境中的 MongoDB 部署
- 云环境中的 MongoDB 部署
- 对数据安全性要求较高的场景
WiredTiger 存储引擎加密
配置方法
yaml# mongod.conf storage: engine: wiredTiger wiredTiger: engineConfig: encryption: keyId: "localKey" keyFile: /etc/mongodb/encryption.key生成加密密钥
bash# 生成随机加密密钥 openssl rand -base64 32 > /etc/mongodb/encryption.key # 设置适当的权限 chmod 400 /etc/mongodb/encryption.key加密范围
- 数据文件
- 索引文件
- 临时文件
- 日志文件
- 诊断数据
文件系统级加密
适用场景
- 无法使用 WiredTiger 加密的旧版本 MongoDB
- 需要加密整个文件系统的场景
- 云环境中的磁盘加密
常用加密方案
- Linux:
- LUKS (Linux Unified Key Setup)
- dm-crypt
- Windows:
- BitLocker
- 云环境:
- AWS EBS 加密
- Azure Disk Encryption
- Google Cloud Persistent Disk Encryption
- Linux:
配置示例(LUKS)
bash# 创建 LUKS 加密卷 cryptsetup luksFormat /dev/sdb # 打开 LUKS 加密卷 cryptsetup open /dev/sdb mongodb_data # 创建文件系统 mkfs.ext4 /dev/mapper/mongodb_data # 挂载文件系统 mount /dev/mapper/mongodb_data /data/mongodb
云提供商加密
AWS 加密选项
- EBS 加密
- S3 加密(用于备份)
- AWS KMS 集成
Azure 加密选项
- Azure Disk Encryption
- Azure Storage Service Encryption
- Azure Key Vault 集成
Google Cloud 加密选项
- Persistent Disk 加密
- Cloud Storage 加密
- Cloud KMS 集成
客户端字段级加密(Client-Side Field Level Encryption)
基本概念
加密原理
- 在客户端对敏感字段进行加密,然后再发送到服务器
- 服务器只存储加密后的数据,无法查看原始数据
- 支持自动加密和解密
适用场景
- 存储敏感数据,如信用卡号、个人身份信息
- 符合数据隐私法规(如 GDPR、PCI DSS)
- 需要严格控制数据访问权限的场景
配置方法
生成数据加密密钥
javascript// 使用 mongosh 生成数据加密密钥 use admin var clientEncryption = db.getMongo().getClientEncryption() var dataKeyId = clientEncryption.createDataKey("local", { keyAltNames: ["dataKey1"] }) print(dataKeyId)配置自动加密
javascript// 客户端加密选项 const autoEncryptionOpts = { keyVaultNamespace: "admin.datakeys", kmsProviders: { local: { key: Buffer.from("0123456789abcdef0123456789abcdef", "hex") } }, schemaMap: { "test.accounts": { bsonType: "object", properties: { creditCardNumber: { encrypt: { bsonType: "string", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } } } } }使用自动加密连接
javascript// 使用 Node.js 驱动连接 MongoDB 并启用自动加密 const { MongoClient } = require('mongodb') async function main() { const client = await MongoClient.connect( 'mongodb://localhost:27017', { useNewUrlParser: true, useUnifiedTopology: true, autoEncryption: autoEncryptionOpts } ) const db = client.db('test') const accounts = db.collection('accounts') // 插入加密数据 await accounts.insertOne({ name: 'John Doe', creditCardNumber: '1234-5678-9012-3456' }) // 查询加密数据(自动解密) const result = await accounts.findOne({ name: 'John Doe' }) console.log(result) client.close() } main()
加密算法
确定性加密(Deterministic Encryption)
- 相同的明文总是生成相同的密文
- 支持等值查询
- 适用于需要对加密字段进行查询的场景
- 算法:
AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic
随机加密(Random Encryption)
- 相同的明文每次生成不同的密文
- 安全性更高
- 不支持等值查询
- 算法:
AEAD_AES_256_CBC_HMAC_SHA_512-Random
范围查询加密(Range Query Encryption)
- 支持对加密字段进行范围查询
- 算法:
AEAD_AES_256_CBC_HMAC_SHA_512-Range
最佳实践
密钥管理
- 使用专门的密钥管理服务(KMS)
- 定期轮换密钥
- 严格控制密钥访问权限
- 备份密钥,确保密钥不丢失
加密字段选择
- 只加密真正敏感的数据字段
- 考虑加密对查询性能的影响
- 选择合适的加密算法
性能优化
- 对频繁查询的加密字段使用确定性加密
- 避免对大型字段进行加密
- 考虑使用索引优化查询性能
密钥管理
密钥管理服务(KMS)集成
支持的 KMS 提供商
- AWS KMS:使用 AWS Key Management Service
- Azure Key Vault:使用 Azure Key Vault
- Google Cloud KMS:使用 Google Cloud Key Management Service
- HashiCorp Vault:使用 HashiCorp Vault
- 本地 KMS:使用本地生成的密钥
AWS KMS 集成配置
javascript// 客户端加密选项 - AWS KMS const autoEncryptionOpts = { keyVaultNamespace: "admin.datakeys", kmsProviders: { aws: { accessKeyId: "AWS_ACCESS_KEY_ID", secretAccessKey: "AWS_SECRET_ACCESS_KEY", sessionToken: "AWS_SESSION_TOKEN" // 可选 } } }Azure Key Vault 集成配置
javascript// 客户端加密选项 - Azure Key Vault const autoEncryptionOpts = { keyVaultNamespace: "admin.datakeys", kmsProviders: { azure: { tenantId: "AZURE_TENANT_ID", clientId: "AZURE_CLIENT_ID", clientSecret: "AZURE_CLIENT_SECRET" } } }
密钥轮换
轮换策略
- 定期轮换数据加密密钥
- 根据合规要求确定轮换频率
- 保留旧密钥用于解密历史数据
轮换方法
javascript// 使用 mongosh 轮换数据加密密钥 use admin var clientEncryption = db.getMongo().getClientEncryption() // 创建新的加密密钥 var newDataKeyId = clientEncryption.createDataKey("aws", { keyAltNames: ["dataKey2"], masterKey: { region: "us-east-1", key: "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" } }) // 更新集合的加密模式使用新密钥 // 注意:这需要更新客户端的 schemaMap 配置注意事项
- 密钥轮换不会自动重新加密现有数据
- 考虑使用后台任务重新加密现有数据
- 确保旧密钥在轮换后仍然可用
审计日志加密
基本概念
加密原理
- 对 MongoDB 审计日志进行加密
- 防止审计日志中的敏感信息泄露
- 支持传输加密和静态加密
适用场景
- 存储敏感操作的审计日志
- 符合合规要求
- 需要保护审计日志完整性的场景
配置方法
启用审计日志
yaml# mongod.conf systemLog: destination: file path: /var/log/mongodb/mongod.log logAppend: true auditLog: destination: file format: BSON path: /var/log/mongodb/audit.log审计日志加密
- 使用文件系统级加密保护审计日志文件
- 对审计日志传输使用 TLS/SSL 加密
- 考虑将审计日志发送到加密的集中日志管理系统
最佳实践
审计日志管理
- 定期备份审计日志
- 限制审计日志访问权限
- 配置适当的审计日志保留期
- 监控审计日志的完整性
性能考虑
- 只审计必要的操作
- 考虑使用异步审计日志
- 监控审计日志对性能的影响
加密性能优化
性能影响因素
加密类型
- 传输加密:影响网络延迟
- 静态加密:影响 I/O 性能
- 客户端字段级加密:影响客户端 CPU 使用率和网络传输
加密算法
- 不同加密算法的性能开销不同
- 密钥长度越长,加密开销越大
- 加密模式(如 CBC、GCM)影响性能
硬件因素
- CPU 支持 AES-NI 指令集可以提高加密性能
- 磁盘 I/O 性能影响静态加密
- 网络带宽影响传输加密
优化策略
硬件优化
- 使用支持 AES-NI 指令集的 CPU
- 对于静态加密,使用高速存储设备
- 确保足够的网络带宽用于传输加密
配置优化
- 选择适当的加密算法
- 配置合理的密钥长度
- 调整 TLS 选项,如使用会话恢复
应用层优化
- 只加密真正需要加密的数据
- 对频繁查询的字段使用确定性加密
- 考虑使用连接池减少 TLS 握手开销
监控和调优
- 监控加密对性能的影响
- 根据实际情况调整加密配置
- 定期测试加密性能
合规性和最佳实践
合规性要求
GDPR(通用数据保护条例)
- 要求适当的数据保护措施
- 支持数据主体权利(访问、删除、导出)
- 数据泄露通知要求
PCI DSS(支付卡行业数据安全标准)
- 要求加密存储和传输信用卡数据
- 定期密钥轮换
- 严格的访问控制
HIPAA(健康保险流通与责任法案)
- 要求保护电子健康记录
- 加密存储和传输敏感健康数据
- 审计日志要求
SOC 2(服务组织控制 2)
- 要求适当的安全控制措施
- 数据加密是常见的安全控制
- 定期审计和测试
加密最佳实践
分层加密策略
- 实施多层次的加密保护
- 传输加密 + 静态加密 + 客户端字段级加密
- 针对不同数据类型使用不同的加密策略
密钥管理最佳实践
- 使用专门的密钥管理服务
- 实现密钥轮换机制
- 严格控制密钥访问权限
- 备份密钥并测试恢复流程
定期安全审计
- 定期审计加密配置
- 测试加密实现的安全性
- 检查密钥管理流程
- 验证合规性要求
员工培训
- 培训员工了解加密最佳实践
- 提高安全意识
- 确保员工正确使用加密功能
常见问题(FAQ)
Q1: MongoDB 社区版支持哪些加密功能?
A1: MongoDB 社区版支持:
- 传输加密(TLS/SSL)
- 文件系统级静态加密(通过操作系统实现)
- 应用层加密(通过客户端库实现)
MongoDB 企业版额外支持:
- WiredTiger 存储引擎级静态加密
- 客户端字段级加密
- 与 KMS 集成
Q2: 加密会对 MongoDB 性能产生什么影响?
A2: 加密对性能的影响取决于多种因素:
- 传输加密:增加网络延迟,影响约 5-10%
- 静态加密:影响 I/O 性能,使用 AES-NI 时影响约 5-15%
- 客户端字段级加密:增加客户端 CPU 使用率和网络传输,影响约 10-20%
可以通过硬件优化和配置调整减少加密对性能的影响。
Q3: 如何备份加密的 MongoDB 数据?
A3: 备份加密的 MongoDB 数据的方法:
- 使用 mongodump/mongorestore 备份和恢复(会保留加密状态)
- 备份加密的文件系统或磁盘
- 确保备份过程中加密密钥安全
- 测试加密数据的恢复流程
Q4: 密钥丢失怎么办?
A4: 密钥丢失会导致无法访问加密数据,因此:
- 定期备份密钥
- 使用可靠的密钥管理服务
- 实施密钥轮换机制
- 考虑使用多密钥策略
Q5: 如何选择合适的加密方式?
A5: 选择加密方式时考虑:
- 数据敏感性:敏感数据需要更高级别的加密
- 性能要求:高性能场景选择轻量级加密
- 合规要求:满足行业合规标准
- 成本因素:考虑密钥管理成本
Q6: 客户端字段级加密和静态加密有什么区别?
A6: 主要区别:
- 客户端字段级加密:在客户端加密特定字段,服务器存储密文
- 静态加密:在存储引擎或文件系统级加密整个数据文件
- 客户端字段级加密提供更细粒度的加密控制,但性能开销更大
Q7: 如何验证 MongoDB 加密配置是否正确?
A7: 验证加密配置的方法:
- 使用
db.serverStatus()检查 TLS 连接状态 - 尝试不使用 TLS 连接,应该失败
- 检查加密日志,确保没有错误
- 测试数据加密和解密功能
- 进行安全审计,验证加密实现
Q8: 加密会影响 MongoDB 的哪些功能?
A8: 加密可能影响的功能:
- 性能:加密会增加 CPU 和 I/O 开销
- 查询:某些查询在加密字段上可能无法使用索引
- 备份和恢复:需要确保密钥可用
- 复制集:复制集成员之间的通信需要使用 TLS/SSL
Q9: 如何迁移加密的 MongoDB 数据?
A9: 迁移加密数据的注意事项:
- 确保迁移过程中加密密钥安全
- 迁移前后使用相同的加密配置
- 验证迁移后数据可以正常解密
- 考虑使用加密的迁移工具
Q10: 如何监控加密相关的性能指标?
A10: 监控加密性能的方法:
- 使用
db.serverStatus()查看 TLS 连接统计 - 监控 CPU 使用率,特别是加密相关的 CPU 开销
- 监控 I/O 性能,特别是静态加密
- 监控客户端字段级加密的性能指标
- 使用 MongoDB Atlas 或 Ops Manager 监控加密性能
