Skip to content

MongoDB 数据加密

传输加密(TLS/SSL)

基本概念

  1. 加密原理

    • 使用 TLS/SSL 协议加密 MongoDB 客户端和服务器之间的通信
    • 防止网络窃听和中间人攻击
    • 验证服务器身份,确保客户端连接到正确的服务器
  2. 适用场景

    • 生产环境中的 MongoDB 部署
    • 跨网络的 MongoDB 连接
    • 对安全性要求较高的应用场景

配置方法

  1. 生成 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
  2. 配置 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
  3. 配置 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. 证书管理

    • 使用有效期较长的证书(建议 1-3 年)
    • 定期轮换证书
    • 安全存储私钥,设置适当的权限
    • 使用受信任的 CA 颁发证书
  2. TLS 版本和加密套件

    • 使用 TLS 1.2 或 TLS 1.3
    • 配置强加密套件
    • 禁用不安全的 TLS 版本(如 TLS 1.0、TLS 1.1)
  3. 客户端配置

    • 客户端连接时验证服务器证书
    • 考虑使用客户端证书认证
    • 配置适当的 TLS 选项

静态加密(Encryption at Rest)

基本概念

  1. 加密原理

    • 对存储在磁盘上的数据进行加密
    • 防止物理设备丢失或被盗导致的数据泄露
    • 加密发生在存储引擎层面
  2. 适用场景

    • 生产环境中的 MongoDB 部署
    • 云环境中的 MongoDB 部署
    • 对数据安全性要求较高的场景

WiredTiger 存储引擎加密

  1. 配置方法

    yaml
    # mongod.conf
    storage:
      engine: wiredTiger
      wiredTiger:
        engineConfig:
          encryption:
            keyId: "localKey"
            keyFile: /etc/mongodb/encryption.key
  2. 生成加密密钥

    bash
    # 生成随机加密密钥
    openssl rand -base64 32 > /etc/mongodb/encryption.key
    
    # 设置适当的权限
    chmod 400 /etc/mongodb/encryption.key
  3. 加密范围

    • 数据文件
    • 索引文件
    • 临时文件
    • 日志文件
    • 诊断数据

文件系统级加密

  1. 适用场景

    • 无法使用 WiredTiger 加密的旧版本 MongoDB
    • 需要加密整个文件系统的场景
    • 云环境中的磁盘加密
  2. 常用加密方案

    • Linux
      • LUKS (Linux Unified Key Setup)
      • dm-crypt
    • Windows
      • BitLocker
    • 云环境
      • AWS EBS 加密
      • Azure Disk Encryption
      • Google Cloud Persistent Disk Encryption
  3. 配置示例(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

云提供商加密

  1. AWS 加密选项

    • EBS 加密
    • S3 加密(用于备份)
    • AWS KMS 集成
  2. Azure 加密选项

    • Azure Disk Encryption
    • Azure Storage Service Encryption
    • Azure Key Vault 集成
  3. Google Cloud 加密选项

    • Persistent Disk 加密
    • Cloud Storage 加密
    • Cloud KMS 集成

客户端字段级加密(Client-Side Field Level Encryption)

基本概念

  1. 加密原理

    • 在客户端对敏感字段进行加密,然后再发送到服务器
    • 服务器只存储加密后的数据,无法查看原始数据
    • 支持自动加密和解密
  2. 适用场景

    • 存储敏感数据,如信用卡号、个人身份信息
    • 符合数据隐私法规(如 GDPR、PCI DSS)
    • 需要严格控制数据访问权限的场景

配置方法

  1. 生成数据加密密钥

    javascript
    // 使用 mongosh 生成数据加密密钥
    use admin
    var clientEncryption = db.getMongo().getClientEncryption()
    var dataKeyId = clientEncryption.createDataKey("local", { keyAltNames: ["dataKey1"] })
    print(dataKeyId)
  2. 配置自动加密

    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"
              }
            }
          }
        }
      }
    }
  3. 使用自动加密连接

    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()

加密算法

  1. 确定性加密(Deterministic Encryption)

    • 相同的明文总是生成相同的密文
    • 支持等值查询
    • 适用于需要对加密字段进行查询的场景
    • 算法:AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic
  2. 随机加密(Random Encryption)

    • 相同的明文每次生成不同的密文
    • 安全性更高
    • 不支持等值查询
    • 算法:AEAD_AES_256_CBC_HMAC_SHA_512-Random
  3. 范围查询加密(Range Query Encryption)

    • 支持对加密字段进行范围查询
    • 算法:AEAD_AES_256_CBC_HMAC_SHA_512-Range

最佳实践

  1. 密钥管理

    • 使用专门的密钥管理服务(KMS)
    • 定期轮换密钥
    • 严格控制密钥访问权限
    • 备份密钥,确保密钥不丢失
  2. 加密字段选择

    • 只加密真正敏感的数据字段
    • 考虑加密对查询性能的影响
    • 选择合适的加密算法
  3. 性能优化

    • 对频繁查询的加密字段使用确定性加密
    • 避免对大型字段进行加密
    • 考虑使用索引优化查询性能

密钥管理

密钥管理服务(KMS)集成

  1. 支持的 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:使用本地生成的密钥
  2. 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" // 可选
        }
      }
    }
  3. 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"
        }
      }
    }

密钥轮换

  1. 轮换策略

    • 定期轮换数据加密密钥
    • 根据合规要求确定轮换频率
    • 保留旧密钥用于解密历史数据
  2. 轮换方法

    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 配置
  3. 注意事项

    • 密钥轮换不会自动重新加密现有数据
    • 考虑使用后台任务重新加密现有数据
    • 确保旧密钥在轮换后仍然可用

审计日志加密

基本概念

  1. 加密原理

    • 对 MongoDB 审计日志进行加密
    • 防止审计日志中的敏感信息泄露
    • 支持传输加密和静态加密
  2. 适用场景

    • 存储敏感操作的审计日志
    • 符合合规要求
    • 需要保护审计日志完整性的场景

配置方法

  1. 启用审计日志

    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
  2. 审计日志加密

    • 使用文件系统级加密保护审计日志文件
    • 对审计日志传输使用 TLS/SSL 加密
    • 考虑将审计日志发送到加密的集中日志管理系统

最佳实践

  1. 审计日志管理

    • 定期备份审计日志
    • 限制审计日志访问权限
    • 配置适当的审计日志保留期
    • 监控审计日志的完整性
  2. 性能考虑

    • 只审计必要的操作
    • 考虑使用异步审计日志
    • 监控审计日志对性能的影响

加密性能优化

性能影响因素

  1. 加密类型

    • 传输加密:影响网络延迟
    • 静态加密:影响 I/O 性能
    • 客户端字段级加密:影响客户端 CPU 使用率和网络传输
  2. 加密算法

    • 不同加密算法的性能开销不同
    • 密钥长度越长,加密开销越大
    • 加密模式(如 CBC、GCM)影响性能
  3. 硬件因素

    • CPU 支持 AES-NI 指令集可以提高加密性能
    • 磁盘 I/O 性能影响静态加密
    • 网络带宽影响传输加密

优化策略

  1. 硬件优化

    • 使用支持 AES-NI 指令集的 CPU
    • 对于静态加密,使用高速存储设备
    • 确保足够的网络带宽用于传输加密
  2. 配置优化

    • 选择适当的加密算法
    • 配置合理的密钥长度
    • 调整 TLS 选项,如使用会话恢复
  3. 应用层优化

    • 只加密真正需要加密的数据
    • 对频繁查询的字段使用确定性加密
    • 考虑使用连接池减少 TLS 握手开销
  4. 监控和调优

    • 监控加密对性能的影响
    • 根据实际情况调整加密配置
    • 定期测试加密性能

合规性和最佳实践

合规性要求

  1. GDPR(通用数据保护条例)

    • 要求适当的数据保护措施
    • 支持数据主体权利(访问、删除、导出)
    • 数据泄露通知要求
  2. PCI DSS(支付卡行业数据安全标准)

    • 要求加密存储和传输信用卡数据
    • 定期密钥轮换
    • 严格的访问控制
  3. HIPAA(健康保险流通与责任法案)

    • 要求保护电子健康记录
    • 加密存储和传输敏感健康数据
    • 审计日志要求
  4. SOC 2(服务组织控制 2)

    • 要求适当的安全控制措施
    • 数据加密是常见的安全控制
    • 定期审计和测试

加密最佳实践

  1. 分层加密策略

    • 实施多层次的加密保护
    • 传输加密 + 静态加密 + 客户端字段级加密
    • 针对不同数据类型使用不同的加密策略
  2. 密钥管理最佳实践

    • 使用专门的密钥管理服务
    • 实现密钥轮换机制
    • 严格控制密钥访问权限
    • 备份密钥并测试恢复流程
  3. 定期安全审计

    • 定期审计加密配置
    • 测试加密实现的安全性
    • 检查密钥管理流程
    • 验证合规性要求
  4. 员工培训

    • 培训员工了解加密最佳实践
    • 提高安全意识
    • 确保员工正确使用加密功能

常见问题(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 监控加密性能