db.runcommand({rolesinfo: ...})是唯一可靠方式,db.getrole()根本不存在;必须加showprivileges: true才能看到具体操作权限,查内置角色须指定db: "admin",且需关注resource作用域和authenticationrestrictions限制。

db.runCommand({rolesInfo: ...}) 是唯一可靠方式
别用 db.getRole(),它根本不存在 —— 这是常见误记,执行会报 "no such command: getRole"。MongoDB 官方 Shell 从未提供这个方法,所有角色权限细节必须通过 db.runCommand() 调用 rolesInfo 命令获取。
关键点在于:不加 showPrivileges: true,返回结果里 privileges 字段为空或被省略,你看到的只是角色名和继承关系,看不到具体能执行哪些操作(比如 find、dropCollection)。
- 查内置角色(如
readWrite)必须指定db: "admin",否则报"Role not found" - 查自定义角色要写明它定义在哪个库,比如角色
appReader在myapp库创建,就得用{role:"appReader", db:"myapp"} - 批量查当前库所有角色(含自定义 + 内置):用
{rolesInfo: 1, showPrivileges: true, showBuiltinRoles: true}
注意 authenticationRestrictions 和 resource 范围
权限不只是“能做什么”,还决定“在哪做”和“谁可以做”。rolesInfo 返回的每个 privilege 对象里,resource 字段明确限定作用域 —— 可能是整个数据库、某个集合,甚至只限 {anyResource: true} 的集群级操作。
更易被忽略的是 authenticationRestrictions 字段:如果存在,说明该角色(或其授予的用户)被强制要求从特定 IP 段连接,或必须提供客户端证书。没满足这些条件,哪怕角色权限再大也无效。
- 例如
resource: {db: "myapp", collection: "logs"}表示该权限只对myapp.logs生效,对myapp.users无权操作 -
resource: {anyResource: true}多见于clusterAdmin等系统级角色,表示跨库/跨节点操作能力 -
authenticationRestrictions若为空数组或缺失,不代表没有限制 —— 它可能在用户层单独配置,需配合db.getUser()交叉验证
别把 roles 数组当成最终权限集
usersInfo 或 getUser() 返回的 roles 数组只告诉你“被授予了哪些角色”,不等于“实际能做什么”。MongoDB 权限是叠加+继承的,且受连接方式、认证机制、网络策略共同影响。
比如一个用户同时拥有 read 和 readWriteAnyDatabase,最终权限不是二者交集而是并集;但若连接时没带 --authenticationDatabase admin,即使有 root 角色也可能连不上。
- 查用户角色必须先
use admin再执行db.runCommand({ usersInfo: { user: "...", db: "admin" } }),否则漏掉所有集群级角色 -
db.getUser("xxx")只返回当前库下的用户定义,切错库就查不到人 - 最可靠验证方式:用该用户真实连接,手动试关键操作(如
db.runCommand({ dropDatabase: 1 })),看错误信息里缺哪类权限
auditLog 是唯一能追溯权限变动的来源
角色定义本身不会自动记录谁改过、何时改、为什么改。要审计权限范围是否被异常扩大或缩小,必须依赖 MongoDB 启动时启用的审计日志(auditLog)。
它默认记录 grantRolesToUser、revokeRolesFromUser、createRole、updateRole 等操作,但前提是服务启动时已配置,且路径可写 —— 否则服务直接启动失败,错误提示是 "Failed to open audit log file"。
- 审计日志不记录数据读写,专注权限变更事件,
atype字段是过滤关键 - 重点关注:
"atype": "grantRolesToUser"、"atype": "updateUser"(尤其是修改roles字段)、"atype": "dropAllUsersFromDatabase" - 用
filebeat采集时,务必设json.keys_under_root: true,否则atype会被嵌套,查询困难











