readAnyDatabase可以读取所有的database吗?

2021-05-10 16:29:07 浏览数 (1)

//

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"
        }
    ]
}

0 人点赞