4. 内置角色与权限模型
MongoDB 的权限体系建立在“认证(Authentication)+ 授权(Authorization)”两层之上。认证解决“你是谁”,授权解决“你能做什么”。MongoDB 采用基于角色的访问控制(RBAC),权限不直接授予用户,而是先打包成角色,再把角色授予用户。理解内置角色,是设计最小权限模型的基础。
MongoDB 的权限由“资源(Resource)+ 动作(Action)”组成。资源可以是某个数据库、某个集合,甚至是集群级别;动作则包括 find、insert、update、remove、createCollection、dropCollection、createUser、grantRole 等。内置角色本质上是这些权限的预定义集合,按作用范围可分为数据库级角色和集群级角色两大类。
shop 库上授予 read,用户只能读取 shop 库的数据;集群级角色作用于整个 mongod 或 mongos 实例,例如 clusterAdmin 可以管理副本集、分片、关闭实例等。
数据库级内置角色
read:只读角色。授予用户对指定数据库中所有集合的查询能力,包括 find、aggregate、count、distinct 等读取类操作,但不能写入。适用场景:报表系统、BI 工具、数据分析账号、只读从节点查询账号。例如给报表服务创建账号:
use shop
db.createUser({
user: "report_user",
pwd: "Report@2024",
roles: [ { role: "read", db: "shop" } ]
})
readWrite:读写角色。在 read 的基础上增加 insert、update、remove、createCollection、dropCollection 等写权限,但不包含用户管理、索引管理、集合空间管理等运维权限。适用场景:业务应用账号、微服务连接账号。这是生产环境中最常见的应用账号角色。
dbAdmin:数据库管理员角色。负责数据库的结构与性能维护,权限包括 createCollection、dropCollection、createIndex、dropIndex、reIndex、collStats、dbStats、compact、validate、renameCollection 等,但不包含用户管理和数据读写权限。适用场景:DBA 维护账号、索引优化、集合结构变更。注意:dbAdmin 不能读取业务数据,这是它与 readWrite 的关键区别。
userAdmin:用户管理员角色。可以在指定数据库内创建用户、删除用户、授予或回收角色、修改用户密码。它管理的是“谁能访问”,而不是“数据本身”。适用场景:安全管理员、账号运维人员。典型用法是让 userAdmin 与 readWrite 分离,避免业务账号拥有创建用户的权限。
dbOwner:数据库所有者角色。它是 readWrite + dbAdmin + userAdmin 的并集,拥有该数据库内的全部权限。适用场景:单库负责人、开发环境管理员。生产环境应谨慎授予,因为它同时具备数据读写、结构变更和用户管理能力。
集群级内置角色
clusterAdmin:集群管理员角色。作用于整个实例,权限包括副本集配置、分片管理、shutdown、replSetGetStatus、serverStatus、listDatabases、dropDatabase 等。它不自动包含各数据库的读写权限,但可以管理集群拓扑和实例状态。适用场景:集群运维、副本集故障切换、分片均衡管理。
clusterMonitor:集群监控角色。只读访问集群监控信息,如 serverStatus、replSetGetStatus、collStats、dbStats 等。适用场景:Prometheus、Zabbix 等监控系统采集账号。它比 clusterAdmin 安全得多,是监控场景的首选。
backup / restore:备份恢复角色。backup 允许执行 mongodump 等备份操作,restore 允许执行 mongorestore 等恢复操作。适用场景:备份系统专用账号。它们不授予业务数据读写权限,只覆盖备份恢复所需的最小权限。
root:超级管理员角色。拥有所有数据库和集群的全部权限,是 readWriteAnyDatabase + dbAdminAnyDatabase + userAdminAnyDatabase + clusterAdmin 等的并集。适用场景:仅限初始化、紧急运维,日常操作不应使用 root。
角色作用范围与权限关系
下图展示了内置角色的作用范围、权限包含关系以及典型适用场景。左侧为数据库级角色,右侧为集群级角色,箭头表示权限包含或组合关系。
最小权限实践与角色组合
生产环境应遵循最小权限原则:业务账号只给 readWrite,监控账号只给 clusterMonitor,备份账号只给 backup,DBA 账号按需组合 dbAdmin 与 clusterAdmin。下面是一个典型的多角色分配示例:
// 业务应用账号:只读写 shop 库
use shop
db.createUser({
user: "app_user",
pwd: "App@2024",
roles: [ { role: "readWrite", db: "shop" } ]
})
// 监控账号:只读集群状态
use admin
db.createUser({
user: "monitor_user",
pwd: "Monitor@2024",
roles: [ { role: "clusterMonitor", db: "admin" } ]
})
// DBA 账号:管理 shop 库结构 + 集群运维
use admin
db.createUser({
user: "dba_user",
pwd: "Dba@2024",
roles: [
{ role: "dbAdmin", db: "shop" },
{ role: "clusterAdmin", db: "admin" }
]
})
db.auth() 登录后,执行 db.runCommand({ connectionStatus: 1 }) 可以查看当前用户的认证信息和已授予角色;执行 db.getSiblingDB("shop").getCollection("orders").findOne() 验证读权限;执行 db.getSiblingDB("shop").getCollection("orders").insertOne({...}) 验证写权限。若返回 Unauthorized,说明角色未覆盖该操作。
clusterAdmin 可以读写所有数据库——实际上它不包含 readWriteAnyDatabase;② 给业务账号授予 dbOwner 或 root——权限过大,一旦泄露影响面极广;③ 把 userAdmin 和 readWrite 授予同一账号——该账号可自行提权,破坏权限隔离。正确做法是按“数据面、管理面、监控面、备份面”拆分账号,各司其职。
总结来看,read 与 readWrite 面向数据访问,dbAdmin 与 userAdmin 面向库级管理,clusterAdmin、clusterMonitor、backup/restore 面向集群运维,root 仅作兜底。理解每个角色的权限边界与作用范围,才能在实际项目中设计出既安全又可维护的权限模型。