MongoDB无“只允许聚合查询”的内置角色,须用admin库创建自定义角色,仅授collStats、dbStats及特定集合的find权限,显式禁止count、distinct等动作,并为跨库$lookup和分片环境补全对应权限。

MongoDB 默认没有“只允许聚合查询”的内置角色,必须通过自定义角色 + 精确权限控制来实现,否则容易误放 find 或 count 权限,导致绕过限制。
用 clusterAdmin 或 root 创建自定义角色
受限角色必须在 admin 数据库中创建,且需具备 createRole 和 grantRole 权限。普通用户无法自行创建角色——这点常被忽略,导致反复报 not authorized on admin to execute command createRole。
- 登录时用具有
userAdminAnyDatabase或更高权限的账号(如admin用户) - 执行命令前确认当前数据库是
admin:use admin - 角色名建议带前缀避免混淆,例如
readAggregationOnly
只授权 collStats、dbStats 和 find 的特定资源限制
聚合查询(aggregate)本身不对应独立权限动作,它底层依赖 find 权限;但若直接授予 find,用户就能执行任意 db.collection.find(),破坏限制目标。正确做法是:仅对特定集合授予 find,且配合 actions: ["collStats"] 支持 $lookup 和分片统计等聚合所需元数据访问。
- 必须显式指定
resource: { db: "mydb", collection: "orders" },不能用{ db: "mydb", collection: "" }(空字符串表示所有集合,等于放行) - 如果聚合涉及跨库
$lookup,目标库集合也要单独授find权限,否则报unauthorized: not authorized on target_db to execute command { find: ... } -
collStats和dbStats动作需作用于{ db: "mydb", collection: "" }(空 collection 表示整个库),这是获取聚合执行计划或$indexStats所需
禁止 insert、update、remove,同时拦截 count 和 distinct
很多团队只关读写,却忘了 count 和 distinct 也能泄露原始数据分布——它们不走 aggregate,但权限模型里属于独立 action,必须显式排除。
- 自定义角色中
privileges列表里不要出现count、distinct、findAndModify - 即使没授
insert,也要明确列出"deny": ["insert", "update", "remove", "count", "distinct"](MongoDB 5.0+ 支持 deny 规则,旧版需靠不授予来隐式禁止) - 测试时用
db.runCommand({ aggregate: "orders", pipeline: [{$group: {_id: null, cnt: {$sum: 1}}}] })验证聚合可行,再用db.orders.countDocuments({})确认被拒绝
真正难的是跨集合聚合和分片集群下的权限扩散——比如一个 $lookup 查三个库的表,就得为每个目标集合单独配 find 权限;而分片环境下,collStats 还要额外给 config 库的 shards 集合读权限,否则 $sort + $limit 可能因缺少分片统计信息而降级执行。

















