第十一章:安全配置

最后更新: 2024-01-01 作者: MongoDB Team
页面目录

第十一章:安全配置

MongoDB 安全机制与访问控制

11.1 安全概述

┌─────────────────────────────────────────────────────────────────┐
│                      MongoDB 安全层级                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────────────────────────────────────────────────────┐│
│  │                    网络层安全                                 ││
│  │  - TLS/SSL 加密                                              ││
│  │  - IP 白名单                                                 ││
│  │  - VPN/专用网络                                              ││
│  └─────────────────────────────────────────────────────────────┘│
│                              ↓                                  │
│  ┌─────────────────────────────────────────────────────────────┐│
│  │                    认证机制                                   ││
│  │  - SCRAM 认证 (默认)                                         ││
│  │  - x.509 证书认证                                            ││
│  │  - LDAP 认证 (企业版)                                        ││
│  │  - Kerberos 认证 (企业版)                                    ││
│  └─────────────────────────────────────────────────────────────┘│
│                              ↓                                  │
│  ┌─────────────────────────────────────────────────────────────┐│
│  │                    授权机制                                   ││
│  │  - 基于角色的访问控制 (RBAC)                                  ││
│  │  - 内置角色                                                   ││
│  │  - 自定义角色                                                 ││
│  └─────────────────────────────────────────────────────────────┘│
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

11.2 认证配置

启用 SCRAM 认证

# mongod.conf
security:
  authorization: enabled
# 重启服务
sudo systemctl restart mongod

创建用户

// 连接到 MongoDB(需要认证)
mongosh -u admin -p password --authenticationDatabase admin

// 创建管理员用户
use admin
db.createUser({
  user: "admin",
  pwd: "strong_password",
  roles: [
    { role: "root", db: "admin" }
  ]
})

// 创建应用用户
use admin
db.createUser({
  user: "app_user",
  pwd: "app_password",
 Mechanisms: ["SCRAM-SHA-256"],  // 强制使用 SCRAM-SHA-256
  roles: [
    { role: "readWrite", db: "app_database" },
    { role: "dbAdmin", db: "app_database" }
  ]
})

// 创建只读用户
db.createUser({
  user: "readonly_user",
  pwd: "readonly_password",
  roles: [
    { role: "read", db: "app_database" }
  ]
})

连接认证

# 命令行认证
mongosh -u username -p password --authenticationDatabase admin

# 指定认证数据库
mongosh -u username -p password --authenticationDatabase myauthdb

# 多用户切换
db.auth("username", "password")

11.3 x.509 证书认证

生成证书

# 生成 CA 证书
openssl req -new -x509 -days 3650 -nodes \
  -out mongodb-ca.crt \
  -keyout mongodb-ca.key \
  -subj "/CN=mongodb-ca/O=MongoDB"

# 生成服务器证书
openssl req -new -nodes -newkey rsa:2048 \
  -keyout mongodb-server.key \
  -out mongodb-server.csr \
  -subj "/CN=mongodb-server"

# 签署服务器证书
openssl x509 -req -days 365 -CA mongodb-ca.crt \
  -CAkey mongodb-ca.key -CAcreateserial \
  -in mongodb-server.csr \
  -out mongodb-server.crt

# 合并证书
cat mongodb-server.crt mongodb-server.key > mongodb-server.pem

# 生成客户端证书
openssl req -new -nodes -newkey rsa:2048 \
  -keyout mongodb-client.key \
  -out mongodb-client.csr \
  -subj "/CN=mongodb-client"

openssl x509 -req -days 365 -CA mongodb-ca.crt \
  -CAkey mongodb-ca.key -CAcreateserial \
  -in mongodb-client.csr \
  -out mongodb-client.crt

cat mongodb-client.crt mongodb-client.key > mongodb-client.pem

配置 x.509 认证

# mongod.conf
net:
  port: 27017
  ssl:
    mode: requireSSL
    PEMKeyFile: /etc/ssl/mongodb-server.pem
    CAFile: /etc/ssl/mongodb-ca.crt
    allowConnectionsWithoutCertificates: false

security:
  clusterAuthMode: x509
  authorization: enabled

使用 x.509 连接

# 连接时使用客户端证书
mongosh --ssl --sslCAFile mongodb-ca.crt \
  --sslPEMKeyFile mongodb-client.pem \
  --host mongodb-server

11.4 基于角色的访问控制 (RBAC)

内置角色

角色 权限
数据库用户角色
read 读取集合数据
readWrite 读写集合数据
数据库管理角色
dbAdmin 管理索引、统计信息
dbOwner readWrite + dbAdmin + userAdmin
userAdmin 管理用户和角色
集群管理角色
clusterAdmin 所有集群管理权限
clusterManager 集群监控和管理
clusterMonitor 只读集群监控
hostManager 管理主机
备份/恢复角色
backup 备份数据
restore 恢复数据
超级用户角色
root 所有权限
__system MongoDB 内部使用

集合级别权限

// 只读特定集合
db.createRole({
  role: "analyticsReader",
  privileges: [
    {
      resource: { db: "app", collection: "orders" },
      actions: ["find"]
    },
    {
      resource: { db: "app", collection: "products" },
      actions: ["find"]
    }
  ],
  roles: []
})

// 读写特定集合
db.createRole({
  role: "orderManager",
  privileges: [
    {
      resource: { db: "app", collection: "orders" },
      actions: ["find", "insert", "update", "remove"]
    }
  ],
  roles: []
})

用户角色管理

// 创建具有自定义角色的用户
db.createUser({
  user: "analytics_user",
  pwd: "analytics_password",
  roles: [
    { role: "analyticsReader", db: "app" },
    { role: "read", db: "reporting" }
  ]
})

// 查看用户权限
db.getUser("app_user")

// 查看角色权限
db.getRole("analyticsReader", { showPrivileges: true })

// 修改用户角色
db.grantRolesToUser("app_user", [
  { role: "readWrite", db: "app_database" }
])

// 移除用户角色
db.revokeRolesFromUser("app_user", [
  { role: "read", db: "app_database" }
])

// 修改密码
db.changeUserPassword("app_user", "new_strong_password")

角色管理

// 创建自定义角色
db.createRole({
  role: "customRole",
  privileges: [
    {
      resource: { db: "app", collection: "" },
      actions: ["find", "insert", "update"]
    },
    {
      resource: { db: "admin", collection: "" },
      actions: ["serverStatus"]
    }
  ],
  roles: []
})

// 查看所有角色
db.adminCommand({ rolesInfo: 1, showPrivileges: true })

// 删除角色
db.dropRole("customRole")

// 授予角色权限
db.grantPrivilegesToRole("customRole", [
  {
    resource: { db: "app", collection: "logs" },
    actions: ["find"]
  }
])

// 撤销角色权限
db.revokePrivilegesFromRole("customRole", [
  {
    resource: { db: "app", collection: "logs" },
    actions: ["find"]
  }
])

11.5 网络安全

绑定 IP

# mongod.conf
net:
  bindIp: 127.0.0.1,10.0.0.100
  # 或绑定所有接口(仅用于内网)
  # bindIpAll: true

防火墙配置

# Ubuntu/Debian (ufw)
sudo ufw allow from 10.0.0.0/24 to any port 27017
sudo ufw deny 27017

# RHEL/CentOS (firewalld)
sudo firewall-cmd --permanent --add-rich-rule='
  rule family="ipv4" source address="10.0.0.0/24" port port="27017" protocol="tcp" accept
'
sudo firewall-cmd --reload

内部认证

# mongod.conf (副本集/分片集群节点)
security:
  keyFile: /etc/mongodb/keyfile
  authorization: enabled
# 生成 keyfile
openssl rand -base64 756 > /etc/mongodb/keyfile
chmod 400 /etc/mongodb/keyfile

11.6 审计配置

启用审计

# mongod.conf (企业版)
security:
  auditLog:
    destination: file
    format: JSON
    path: /var/log/mongodb/audit.log
    filter: '{ atype: { $in: ["createUser", "dropUser", "updateUser"] } }'

审计输出选项

# 输出到 syslog
security:
  auditLog:
    destination: syslog
    syslogFacility: local0

# 输出到控制台
security:
  auditLog:
    destination: console

# 输出到 MongoDB Atlas (云端)
security:
  auditLog:
    destination: mongodb-atlas

11.7 字段级安全

使用投影限制字段

// 只返回允许的字段
db.users.find(
  { _id: userId },
  { password: 0, sensitive_data: 0 }
)

加密字段(企业版)

// 创建加密集合
db.createCollection("customers", {
  encryptedFields: [
    { fieldName: "ssn", bsonType: "string" },
    { fieldName: "creditCard", bsonType: "string" }
  ]
})

// 配置加密
db.adminCommand({
  configureQueryableEncryption: {
    kms: {
      local: { key: BinData(0, "your-32-byte-key") }
    },
    encryptedFields: "customers",
    algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
  }
})

💡 实践提示

  1. 启用访问控制:生产环境必须启用 --auth
  2. 最小权限原则:只为用户分配所需的最小权限
  3. 强密码策略:使用 SCRAM-SHA-256 和强密码
  4. 网络隔离:使用防火墙限制访问源
  5. 定期轮换:定期更换密钥和密码
  6. 审计日志:启用审计跟踪关键操作

📚 继续学习