开发环境权限必须在admin数据库创建角色,因所有角色元数据存于admin.system.roles;角色需在admin库中创建并限定privileges的db字段作用域,避免误用dbAdmin等高危角色,且用户连接时须指定--authenticationDatabase=admin。

开发环境权限必须在 admin 数据库中创建角色
自管理 MongoDB 部署中,所有用户和角色的元数据都存于 admin 数据库的 system.roles 集合里。你不能在 test 或 dev 等业务数据库里直接创建跨库生效的角色——哪怕只是想让开发人员读写自己库,角色本身也得建在 admin 中,再通过 db 字段限定作用域。
常见错误是:在 use dev 后执行 db.createRole(),结果角色只存在于 dev 库,无法被其他库用户继承,也无法绑定到需要跨库调试的开发账号上。
- 必须先
use admin,再运行角色创建命令 - 角色名全局唯一,但仅靠名字不保证作用范围——关键看
privileges里声明的resource和roles数组中的db - 如果忘了切库,
db.createRole()会静默成功,但后续db.createUser()绑定时提示role not found
Develop 角色应显式限制集合级操作,而非依赖 dbAdmin
很多团队直接给开发人员分配 dbAdmin 或 dbOwner,以为“方便调试”,实则埋下高危隐患:dbAdmin 允许 dropCollection、reIndex、甚至 collMod 修改集合选项,这些操作在共享开发库中极易误伤他人数据。
真正安全的 Develop 角色,应聚焦在“可读写、可调试、不可破坏”三原则,用最小权限覆盖日常开发动作:
- 对目标开发库(如
dev)的所有非系统集合,授予find、insert、update、delete、createIndex、dropIndex - 显式排除
dropCollection、convertToCapped、collMod等高危动作 - 允许执行
aggregate和explain,但禁止mapReduce(易触发长时间阻塞) - 若需查看慢查询,可附加
system.profile的find权限,而非开放整个dbAdmin
示例命令片段(在 admin 库中执行):
db.createRole({
role: "Develop",
privileges: [
{
resource: { db: "dev", collection: "" },
actions: ["find", "insert", "update", "delete", "createIndex", "dropIndex", "aggregate", "explain"]
},
{
resource: { db: "dev", collection: "system.profile" },
actions: ["find"]
}
],
roles: []
})
开发账号必须显式指定 authenticationDatabase 才能生效
即使你在 admin 库创建了 Develop 角色,并为用户 dev_user 分配了该角色,连接时若不指定 --authenticationDatabase admin,MongoDB 默认尝试在当前库(比如 dev)里查用户凭证,必然失败。
典型报错是:Authentication failed. 或更隐蔽的 not authorized on dev to execute command { find: "xxx" },让人误以为权限没配对,其实是认证库错了。
- 创建用户时,
roles数组里的db指的是“权限作用域”,不是“认证数据库” - 客户端连接时,
--authenticationDatabase参数必须与用户实际存储的库一致——对绝大多数情况,就是admin - 使用
mongosh连接示例:mongosh "mongodb://dev_user:pwd@localhost:27017/dev?authSource=admin"
不要把 Develop 角色加进 admin 数据库的内置角色链
有些团队为了省事,让 Develop 角色继承 readWriteAnyDatabase 或 userAdminAnyDatabase,认为“反正只是开发环境”。这是最危险的简化——它会让开发账号无意中获得对 production、staging 等其他库的读写权,尤其当多个环境共用一套 MongoDB 实例时,风险直接拉满。
真实开发场景中,权限边界必须严格按数据库隔离:
-
Develop角色的privileges只应包含明确列出的dev、test等开发专用库 -
roles数组保持为空,避免隐式继承任何全局角色 - 如果真需要跨库调试(例如查
shared_config),应在privileges中单独添加对应resource,而不是引入readAnyDatabase
容易被忽略的一点:MongoDB 不校验角色名是否存在才允许创建用户,所以 roles: [{role:"Develop", db:"admin"}] 写错成 db:"dev" 也不会报错,但该角色永远无法生效——因为角色定义在 admin,而你却告诉系统去 dev 库找它。


















