Skip to content

MongoDB 授权模型

内置角色体系

数据库用户角色

  1. read

    • 允许读取指定数据库中的所有集合
    • 包含权限:findaggregatelistCollectionslistIndexes
    • 适用场景:只读用户
  2. readWrite

    • 继承read角色的所有权限
    • 增加写操作权限:insertupdateremovecreateIndexdropIndex
    • 适用场景:读写用户
  3. dbAdmin

    • 数据库管理权限
    • 包含权限:collModcreateCollectiondropCollectionrenameCollection
    • 适用场景:数据库管理员
  4. dbOwner

    • 数据库所有者权限
    • 继承readWrite、dbAdmin和userAdmin角色
    • 适用场景:数据库所有者
  5. userAdmin

    • 用户管理权限
    • 包含权限:createUserdropUserupdateUsergrantRolesToUser
    • 适用场景:用户管理员

集群管理角色

  1. clusterAdmin

    • 集群管理最高权限
    • 继承clusterManager、clusterMonitor和hostManager角色
    • 包含权限:addShardremoveShardshutdown
    • 适用场景:集群管理员
  2. clusterManager

    • 集群管理权限
    • 包含权限:replSetConfigurereplSetGetStatusaddShard
    • 适用场景:集群配置管理员
  3. clusterMonitor

    • 集群监控权限
    • 包含权限:serverStatusreplSetGetStatusgetCmdLineOpts
    • 适用场景:监控用户
  4. hostManager

    • 主机管理权限
    • 包含权限:setParameterserverStatusshutdown
    • 适用场景:主机管理员

备份恢复角色

  1. backup

    • 备份权限
    • 包含权限:listDatabasesdbAdmin(所有数据库)、find(所有数据库)
    • 适用场景:备份用户
  2. restore

    • 恢复权限
    • 包含权限:listDatabasesdbAdmin(所有数据库)、insert(所有数据库)
    • 适用场景:恢复用户

超级用户角色

  1. root

    • 超级用户权限
    • 继承所有内置角色
    • 包含权限:anyAction(所有资源)
    • 适用场景:超级管理员
  2. __system

    • 内部系统角色
    • MongoDB内部使用
    • 不建议在生产环境使用

自定义角色创建

创建自定义角色

  1. 基本语法

    javascript
    db.createRole({
      role: "角色名称",
      privileges: [
        { resource: { 资源描述 }, actions: ["操作列表"] },
        // 更多权限
      ],
      roles: [
        { role: "继承角色", db: "数据库" },
        // 更多继承角色
      ]
    })
  2. 创建示例

    javascript
    // 创建一个只能读取特定集合的角色
    db.createRole({
      role: "readOrders",
      privileges: [
        { 
          resource: { db: "sales", collection: "orders" },
          actions: ["find", "aggregate"] 
        }
      ],
      roles: []
    })
  3. 创建带条件的角色

    javascript
    // 创建一个只能读取自己数据的角色
    db.createRole({
      role: "readOwnData",
      privileges: [
        { 
          resource: { db: "users", collection: "profiles" },
          actions: ["find"],
          conditions: {
            field: "userId",
            operator: "$eq",
            value: "$$CURRENT_USER"
          }
        }
      ],
      roles: []
    })

查看自定义角色

  1. 查看所有角色

    javascript
    // 查看当前数据库的所有角色
    db.getRoles({ showPrivileges: true, showBuiltinRoles: true })
  2. 查看特定角色

    javascript
    // 查看readOrders角色
    db.getRole("readOrders", { showPrivileges: true })

修改和删除自定义角色

  1. 修改角色

    javascript
    // 修改readOrders角色,增加write权限
    db.updateRole("readOrders", {
      privileges: [
        { 
          resource: { db: "sales", collection: "orders" },
          actions: ["find", "aggregate", "insert", "update"] 
        }
      ]
    })
  2. 删除角色

    javascript
    // 删除readOrders角色
    db.dropRole("readOrders")

权限资源与操作

资源类型

  1. 数据库资源

    javascript
    // 所有数据库
    { anyResource: true }
    
    // 特定数据库
    { db: "mydb", collection: "" }
  2. 集合资源

    javascript
    // 特定集合
    { db: "mydb", collection: "mycoll" }
    
    // 数据库中的所有集合
    { db: "mydb", collection: "*" }
  3. 集群资源

    javascript
    // 集群资源
    { cluster: true }
  4. 系统资源

    javascript
    // 系统.profile集合
    { db: "local", collection: "system.profile" }

操作类型

  1. 读写操作

    • findinsertupdateremove
    • aggregatecountdistinct
  2. 管理操作

    • createCollectiondropCollection
    • createIndexdropIndex
    • collModrenameCollection
  3. 集群操作

    • replSetConfigurereplSetGetStatus
    • addShardremoveShard
    • shutdownsetParameter
  4. 用户管理操作

    • createUserdropUserupdateUser
    • grantRolesToUserrevokeRolesFromUser

角色授予与撤销

授予角色给用户

  1. 创建用户时授予角色

    javascript
    // 创建用户并授予角色
    db.createUser({
      user: "john",
      pwd: "password123",
      roles: [
        { role: "readWrite", db: "sales" },
        { role: "read", db: "reporting" }
      ]
    })
  2. 授予角色给现有用户

    javascript
    // 授予角色
    db.grantRolesToUser("john", [
      { role: "dbAdmin", db: "sales" },
      "readOrders" // 自定义角色
    ])

撤销用户角色

  1. 撤销角色

    javascript
    // 撤销角色
    db.revokeRolesFromUser("john", [
      { role: "dbAdmin", db: "sales" }
    ])
  2. 替换用户角色

    javascript
    // 替换所有角色
    db.updateUser("john", {
      roles: [
        { role: "read", db: "sales" }
      ]
    })

权限继承关系

角色继承

  1. 垂直继承

    • 角色可以继承其他角色的权限
    • 如readWrite继承read角色
  2. 水平继承

    • 角色可以继承多个不同角色
    • 如dbOwner继承readWrite、dbAdmin和userAdmin
  3. 继承示例

    javascript
    // 创建一个继承多个角色的角色
    db.createRole({
      role: "salesManager",
      privileges: [],
      roles: [
        { role: "readWrite", db: "sales" },
        { role: "read", db: "reporting" },
        "readOrders" // 自定义角色
      ]
    })

权限继承规则

  1. 最小权限原则

    • 只授予必要的最小权限
    • 避免过度授权
  2. 权限叠加原则

    • 继承的权限是叠加的
    • 角色的权限是直接权限和继承权限的总和
  3. 权限覆盖原则

    • 明确的拒绝权限优先于允许权限
    • 使用denyActions指定拒绝的操作

权限审计与监控

启用审计日志

  1. 配置审计日志

    yaml
    # mongod.conf
    security:
      authorization: enabled
      auditLog:
        destination: file
        format: JSON
        path: /var/log/mongodb/audit.log
        filter: '{ "atype": "authCheck" }'  # 只记录授权检查
  2. 审计日志内容

    • 用户认证事件
    • 权限检查事件
    • 角色授予和撤销事件

监控权限使用

  1. 使用db.setProfilingLevel

    javascript
    // 启用慢查询和所有命令日志
    db.setProfilingLevel(2, { slowms: 100 })
  2. 查询审计日志

    javascript
    // 查看审计日志
    db.adminCommand({ getLog: 'audit' })
  3. 使用MongoDB Atlas

    • 内置权限使用监控
    • 可视化权限使用报告
    • 异常权限使用告警

最佳实践

最小权限原则

  1. 根据职责分配权限

    • 只读用户:read角色
    • 读写用户:readWrite角色
    • 管理员:根据需要分配特定角色
  2. 避免使用root角色

    • 生产环境中尽量不使用root角色
    • 为不同管理员分配特定角色
  3. 定期审查权限

    javascript
    // 定期审查用户权限
    db.getUsers({ showPrivileges: true, showCredentials: false })

角色命名规范

  1. 角色命名建议

    • 包含资源范围:如sales_readreporting_write
    • 包含职责:如admin_clusterbackup_user
    • 使用下划线分隔:如read_only_sales
  2. 示例

    • sales_read_write:sales数据库读写权限
    • cluster_monitor:集群监控权限
    • backup_restore:备份恢复权限

权限管理流程

  1. 权限申请

    • 用户提交权限申请
    • 包含所需权限和理由
  2. 权限审批

    • 管理员审批权限申请
    • 确保符合最小权限原则
  3. 权限授予

    • 授予相应角色
    • 记录权限变更
  4. 权限审查

    • 定期审查权限使用情况
    • 撤销不必要的权限

常见问题(FAQ)

Q1: 如何创建一个只能读取特定集合的角色?

A1: 可以使用db.createRole()创建自定义角色,指定资源为特定集合,操作为find和aggregate:

javascript
db.createRole({
  role: "readSpecificCollection",
  privileges: [
    { 
      resource: { db: "mydb", collection: "mycoll" },
      actions: ["find", "aggregate"] 
    }
  ],
  roles: []
})

Q2: 如何查看用户的所有权限?

A2: 使用db.getUser()命令查看用户权限:

javascript
db.getUser("username", { showPrivileges: true, showCredentials: false })

Q3: 如何撤销用户的所有权限?

A3: 可以使用db.updateUser()替换用户的所有角色:

javascript
db.updateUser("username", {
  roles: []
})

Q4: 什么是最小权限原则?

A4: 最小权限原则是指只授予用户完成工作所需的最小权限,避免过度授权。这可以减少安全风险,防止误操作或恶意操作。

Q5: 如何监控权限使用情况?

A5: 可以通过以下方式监控权限使用:

  • 启用审计日志,记录权限检查事件
  • 使用数据库Profiler记录命令执行
  • 使用第三方监控工具(如MongoDB Atlas)监控权限使用

Q6: 如何处理角色冲突?

A6: 角色冲突处理方法:

  • 明确的拒绝权限优先于允许权限
  • 避免授予相互冲突的角色
  • 使用自定义角色精确控制权限
  • 定期审查角色权限,确保没有冲突