这周工作过程中,遇到了一个MongoDB权限相关的问题。记录一下,希望对大家有帮助。
01
背景
业务同学的代码中使用了一个框架,想要创建一个固定集合,关于固定集合的详细知识,大家可以参考:
MongoDB固定集合Capped Collections
固定集合也叫Capped Collections,它的特点是集合固定大小,如果我们写入的数据超过了集合的大小,那么集合中的老数据就会被覆盖删除;
类似的,MongoDB中还有另外一种TTL索引机制,它是给某个时间字段上创建一个索引,索引上定义了这个时间字段的保留周期,一旦超过某个周期,则对应的数据就被删除了。
固定集合和TTL索引,一般需要根据业务的实际需求进行选择,这里不再进行赘述。
这个框架在创建固定集合的时候,出现了报错,类似下图;
PRIMARY> db.createCollection('test1',{capped:'true'} ... ) { "ok" : 0, "errmsg" : "not authorized on xxx to execute command { create: "test1", capped: "true", lsid: { id: UUID("c44d35fc-29e2-4c05-9ef1-62513ae82e6e") }, $db: "xxx" }", "code" : 13, "codeName" : "Unauthorized" }
这个问题怎么分析呢?
02
分析过程
1、查看当前账号的权限
首先查看当前账号的权限,在MongoDB中,查看一个账号的权限,可以使用下面的命令:
db.getUser('user_rw',{showPrivileges:true})
来查看权限
PRIMARY> db.getUser('user_rw',{showPrivileges:true}) { "_id" : "db_name.user_rw", "userId" : UUID("f264e7b6-87ca-47f1-bdb6-850ba028c616"), "user" : "user_rw", "db" : "db_name", "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ], "roles" : [ { "role" : "role_name", "db" : "db_name" } ], "inheritedRoles" : [ { "role" : "role_name", "db" : "db_name" } ], "inheritedPrivileges" : [ { "resource" : { "db" : "db_name", "collection" : "" }, "actions" : [ "collStats", "createCollection", "createIndex", "dbHash", "dbStats", "dropIndex", "find", "insert", "killCursors", "listCollections", "listIndexes", "reIndex", "remove", "update" ] } ], "inheritedAuthenticationRestrictions" : [ [ ] ] }
从输出结果中,我们可以看到,我们的账号,是有createCollection权限的,意味着它可以进行createCollection操作。
2、查看createCollection命令的说明
既然我们的账号已经有了createCollection的权限,那么就再来看真正执行的createCollection命令的情况吧。
官方文档地址:http://218.206.242.148:12345/images/20_tencent/20220917/aat2l0zeoza
createCollection命令的官方文档说明中,可以看到描述如下:
也就是说,这个命令可以用来创建集合或者视图,由于MongoDB的普通集合一般是自动创建的,所以这个createCollection通常被用来创建有特殊限制的集合,例如固定集合。
那么createCollection命令执行过程中有哪些权限限制?
1、创建普通集合:
需要有database级别的createCollection权限;
需要有对应集合的insert权限
2、创建固定集合:
需要有database级别的createCollection权限;
需要有对应集合的convertToCapped权限
到这里,基本比较明朗了。
3、验证判断是否正确
因为我们的用户和角色绑定的,所以只需要给对应的角色赋予权限即可,命令如下:
PRIMARY> db.grantPrivilegesToRole( "role_name", [ { resource: { db: "db_name", collection: "" }, actions: [ "convertToCapped" ] } ] )
再来创建固定集合:
PRIMARY> db.runCommand({ create: "test2", capped: true, size: 52}) { "ok" : 1 }
创建成功。
总结:
当我们使用createCollection命令创建固定集合的时候,需要有database级别的createCollection权限,和对应集合的convertToCapped权限