//
readAnyDatabase可以读取所有的database吗?
//
01
问题背景
今天在线上环境中,发现了一个有意思的小问题。这个问题是权限相关的。
我们首先使用root权限登录,并在admin的这个数据库下面创建了test账号,给了它readAnydatabase的角色,创建这个账号的语句如下:
代码语言:javascript复制use admin
db.createUser({
"user" : "test",
"pwd" : "test_password",
"roles" : [
{
"role" : "readAnyDatabase",
"db" : "admin"
}
]
})
创建账号完毕后,然后我们创建一个新的集合aaa.bbb,并向bbb这个集合插入数据,
代码语言:javascript复制testInit:PRIMARY> use aaa
switched to db aaa
testInit:PRIMARY> db.bbb.insert({id:1})
WriteResult({ "nInserted" : 1 })
然后我们重新使用test这个用户和test_password这个密码登录相关的mongod实例,并查询bbb的这个集合,结果如下:
代码语言:javascript复制[root@ ~]# /data1/yazhou5/mongodb/mongodb-linux-4.0.4/bin/mongo --port=45011 -u "test" -p "test_password" --authenticationDatabase "admin" --host=10.xx.xx.80
MongoDB shell version v4.0.4
connecting to: mongodb://10.13.88.80:45011/
Implicit session: session { "id" : UUID("daf6970a-aa4b-4984-9aa6-769e92f27c55") }
MongoDB server version: 4.0.4
testInit:PRIMARY>
testInit:PRIMARY> use aaa
switched to db aaa
testInit:PRIMARY> db.bbb.find()
{ "_id" : ObjectId("607da365a9028d75b2dc970c"), "id" : 1 }
到这里,似乎没有什么问题,我们创建的账号在admin数据库下面,有readAnydatabase的权限,所以即使不在aaa数据库下面,也可以直接读取aaa数据库下面的bbb集合。
如果我们使用这个账号去读取local数据库中的oplog.rs这个集合的时候,会发现下面的问题:
代码语言:javascript复制testInit:PRIMARY> db.oplog.rs.find()
Error: error: {
"operationTime" : Timestamp(1618847798, 1),
"ok" : 0,
"errmsg" : "not authorized on local to execute command { find: "oplog.rs", filter: {}, lsid: { id: UUID("a84e7282-ad63-4a53-8f14-1e8681ee2f06") }, $clusterTime: { clusterTime: Timestamp(1618847788, 1), signature: { hash: BinData(0, 81ABC979D562DC82476920680BB0B7B1940EDF46), keyId: 6912418480415309825 } }, $db: "local" }",
"code" : 13,
"codeName" : "Unauthorized",
"$clusterTime" : {
"clusterTime" : Timestamp(1618847798, 1),
"signature" : {
"hash" : BinData(0,"FmxZI9KxpqsjBgtPuVX/I7mlSvo="),
"keyId" : NumberLong("6912418480415309825")
}
}
}
看来,readAnyDatabase的角色只是一个"顾名思义"上的错觉,它也不能访问所有的数据库,那么这个角色能访问哪些数据库呢?
02
官方文档说明
readAnyDatabase
Provides the same read-only privileges as read
on all databases except local
and config
. The role also provides the listDatabases
action on the cluster as a whole.
Changed in version 3.4: Prior to 3.4, readAnyDatabase
includes local
and config
databases. To provide read
privileges on the local
database, create a user in the admin
database with read
role in the local
database.
从官方文档描述不难看出,在3.4版本之前,这个用户可以访问local库和config库,而在3.4版本的MongoDB中进行了改造,后续版本不再能够访问local库和config库中的表,只能访问除这两个库之外的其他业务库和系统库。
如果想要访问local库和config库,需要单独创建这两个数据库的read或者readwrite角色账号。
那么我们可以将test用户设置成下面这样:
代码语言:javascript复制{
"user" : "test",
"pwd" : "test_password",
"roles" : [
{
"role" : "readAnyDatabase",
"db": "admin"
},
{
"role" : "readWrite",
"db" : "config"
},
{
"role" : "readWrite",
"db" : "local"
}
]
}