MongoDB基础之 用户和数据库基于角色的访问控制
mongod 关键字参数:--auth
默认值是不需要验证,即 --noauth,该参数启用用户访问权限控制;当mongod 使用该参数启动时,MongoDB会验证客户端连接的账户和密码,以确定其是否有访问的权限。如果认证不通过,那么客户端不能访问MongoDB的数据库。
这个参数我们可以写在配置文件中,表示每次启动服务都打开auth认证,在这里我们是加在了mongod的启动指令中,如下所示
[root@:vg_adn_tidbCkhsTest /usr/local/mongodb]#bin/mongo -u "admin" -p "123456" --authenticationDatabase "admin" MongoDB shell version v3.4.18 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.18 > db test
这里的“admin”数据库是我们在安装mongo的时候就已经创建的,并且在数据库中创建了admin用户,且拥有“userAdminAnyDatabase”角色
下面讲解基于角色的访问控制
角色是授予User在指定资源上执行指定操作的权限,MongoDB官方手册对角色的定义是:
A role grants privileges to perform the specified actions on resource.
MongoDB为了方便管理员管理权限,在DB级别上预先定义了内置角色;如果用户需要对权限进行更为细致的管理,MongoDB允许用户创建自定义的角色,能够在集合级别上控制User能够执行的操作。
MongoDB使用角色(Role)授予User访问资源的权限,Role决定User能够访问的数据库资源和执行的操作。一个User能够被授予一个或多个Role,如果User没有被授予Role,那么就没有访问MongoDB系统的权限。
A user is granted one or more roles that determine the user’s access to database resources and operations. Outside of role assignments, the user has no access to the system.
1,内置角色(Built-In Roles)
内置角色是MongoDB预定义的角色,操作的资源是在DB级别上。MongoDB拥有一个SuperUser的角色:root,拥有最大权限,能够在系统的所有资源上执行任意操作。
数据库用户角色(Database User Roles):
- read:授予User只读数据的权限
- readWrite:授予User读写数据的权限
数据库管理角色(Database Administration Roles):
- dbAdmin:在当前dB中执行管理操作
- dbOwner:在当前DB中执行任意操作
- userAdmin:在当前DB中管理User
备份和还原角色(Backup and Restoration Roles):
- backup
- restore
跨库角色(All-Database Roles):
- readAnyDatabase:授予在所有数据库上读取数据的权限
- readWriteAnyDatabase:授予在所有数据库上读写数据的权限
- userAdminAnyDatabase:授予在所有数据库上管理User的权限
- dbAdminAnyDatabase:授予管理所有数据库的权限
现在我们举例子介绍一下
上面我们已经创建好了admin用户,该用户拥有有grant权限,我们创建的admin用户是在admin数据库中创建的。即:账号管理的授权权限。注意一点,帐号是跟着库走的,所以在指定库里授权,必须也在指定库里验证(auth)。
由于我们的admin用户建立了 userAdminAnyDatabase 角色,用来管理用户,可以通过这个角色来创建、删除用户。验证:需要开启auth参数
[root@:vg_adn_tidbCkhsTest:23.22.172.65:172.31.22.29 /usr/local/mongodb]#bin/mongo -u "admin" -p "123456" --authenticationDatabase "admin" MongoDB shell version v3.4.18 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.18 > db test > use admin switched to db admin > db admin > show users; { "_id" : "admin.admin", "user" : "admin", "db" : "admin", "roles" : [ { "role" : "dbOwner", "db" : "test" }, { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } > show dbs; admin 0.000GB local 0.000GB test 0.000GB test1 0.000GB
我们连接上去admin用户之后,在admin数据库中就有了权限,注意admin用户拥有的角色是userAdminAnyDatabase。所以才可以创建用户等等操作
> use test2 #在test2库中创建账号 switched to db test2 > db.createUser( ... { ... user:"test", ... pwd:"test", ... roles:[{role:"readWrite",db:"test2"}] ... } ... ) Successfully added user: { "user" : "test", "roles" : [ { "role" : "readWrite", "db" : "test2" } ] } > show users; { "_id" : "test2.test", "user" : "test", "db" : "test2", "roles" : [ { "role" : "readWrite", "db" : "test2" } ] }
现在我们开始验证一下:
> use test2 switched to db test2> db test2 > db.abc.insert({"name":"chaofeng","id":1}) WriteResult({ "writeError" : { "code" : 13, "errmsg" : "not authorized on test2 to execute command { insert: \"abc\", documents: [ { _id: ObjectId('5bea73410816d4c446c6c0d1'), name: \"chaofeng\", id: 1.0 } ], ordered: true }" } })
因为我目前还是admin登录的,所以在test2数据库中,admin用户没有权限,只有我们刚刚建立的“test”用户才有权限。
注意:admin用户只是拥有了创建用户,删除用户的角色,这并不是最高权限。
所以现在我想在test2数据库下插入数据,我得使用test用户才行。
这里还要注意一点:
1、我在admin数据库中认证test用户
> db.auth("test","test") Error: Authentication failed. 0 > db admin
我在admin数据库中使用test用户认,来让test用户可以访问test2数据库,是失败的。记住一点:在admin下创建的账户,不能直接在admin库上验证。
2、我在test2数据库中认证test用户
> db.auth("test","test") 1 > db test2
这样就成功了,记住一点:在哪个库上创建的账户,就在那里认证,也说明了一点,数据库账户是跟着数据库走的,先有数据库,然后才有账户去认证这个数据库,从而有权限操作。
现在我们的test用户已经可以登录到test2数据库中操作了,我们尝试一下
> use test2 switched to db test2> db.abc.insert({"name":"chaofeng","id":1}) WriteResult({ "nInserted" : 1 }) > db.abc.find() { "_id" : ObjectId("5bea76f00816d4c446c6c0d2"), "name" : "chaofeng", "id" : 1 } >
最后我们再看一下数据库中创建的所有账户
> use admin switched to db admin> db.system.users.find().pretty() { "_id" : "admin.admin", "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "2VmpmkRbVjolDoXjzbjHTw==", "storedKey" : "/Rd7OGTHEsGhsK8ZsFGe8DOzHTk=", "serverKey" : "8+JA2FBdUVtvo3AZNNDSvREZpOg=" } }, "roles" : [ { "role" : "dbOwner", "db" : "test" }, { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } { "_id" : "test1.ccf", "user" : "ccf", "db" : "test1", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "cqPSk8h1ucAnJEl3mjx8MQ==", "storedKey" : "kNNTRqVv63fVy0r1KH9Oem0iKNo=", "serverKey" : "yTO6i7IIu7wuTEfd+VJG/l59veM=" } }, "roles" : [ { "role" : "readWrite", "db" : "test1" } ] } { "_id" : "test2.test", "user" : "test", "db" : "test2", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "0K+o35PrySZbdTq0kl79vg==", "storedKey" : "z3Z8dDswfQsnJ98qpUG8qChIafQ=", "serverKey" : "b6kLZoYhZwgxXmSNLpVIqyr6AyE=" } }, "roles" : [ { "role" : "readWrite", "db" : "test2" } ] }
查看所有的用户我们必须在admin数据库下,在其他的数据中是查看不到的。比如
> use test2 switched to db test2 > db.system.users.find().pretty()
同样的查看数据库用户的指令,在test2数据库中就不起作用,什么也查不出来。
同样的道理,当我们登录到mongo的时候,想要进入到admin库中查看所有用户的操作也是需要验证的,比如:
[root@:vg_adn_tidbCkhsTest /usr/local/mongodb]#bin/mongo MongoDB shell version v3.4.18 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.18 > db test > use test2 switched to db test2 > use admin switched to db admin > db.system.users.find().pretty() Error: error: { "ok" : 0, "errmsg" : "not authorized on admin to execute command { find: \"system.users\", filter: {} }", "code" : 13, "codeName" : "Unauthorized" } >
紧接着这里我们还没有在test2库中认证账户密码,还能访问数据库吗?
> use test2 switched to db test2 > show dbs #发现连数据库都查看不了 2018-11-13T07:09:19.437+0000 E QUERY [thread1] Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not authorized on admin to execute command { listDatabases: 1.0 }", "code" : 13, "codeName" : "Unauthorized" } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1 shellHelper.show@src/mongo/shell/utils.js:814:19 shellHelper@src/mongo/shell/utils.js:704:15 @(shellhelp2):1:1 > db.abc.find() #test2数据库的记录也查看不了 Error: error: { "ok" : 0, "errmsg" : "not authorized on test2 to execute command { find: \"abc\", filter: {} }", "code" : 13, "codeName" : "Unauthorized" } > db.auth("test","test"); #开启认证账户 1 > db.abc.find() #成功 { "_id" : ObjectId("5bea76f00816d4c446c6c0d2"), "name" : "chaofeng", "id" : 1 } >
总结:mongo数据库和别的数据库认证过程是不一样的,我们无需退出客户端便可以自动切换用户,来实现对不同数据库的操作。mongo中,在哪个数据库下创建的用户,就在哪个数据库下开启认证,也就是说,在A数据库创建的用户user1,只能在数据库A下面开启认证,在B数据库下面认证user1是不能成功的,在B数据库下只能认证user2数据库。数据库账户是跟着数据库走的。
现在我想删除数据库,
> use test2 switched to db test2 > show dbs admin 0.000GB local 0.000GB test1 0.000GB test2 0.000GB > db.auth("test","test"); 1 > db.abc.find() { "_id" : ObjectId("5bea76f00816d4c446c6c0d2"), "name" : "chaofeng", "id" : 1 } { "_id" : ObjectId("5bea7b4f6aeeebc0eb076f44"), "name" : "chen", "id" : 2 } > db.dropDatabase(); { "ok" : 0, "errmsg" : "not authorized on test2 to execute command { dropDatabase: 1.0 }", "code" : 13, "codeName" : "Unauthorized" }
发现是不能删除数据库的,仔细一想就知道test用户只有对当前test2数据库读写操作,但是没有删除权限。
我们再对test2数据库创建一个用户,使其拥有管理权限
> db test2 > db.createUser( ... { ... user:"gl", ... pwd:"gl", ... roles:[{role:"dbOwner",db:"test2"}] ... } ... ) Successfully added user: { "user" : "gl", "roles" : [ { "role" : "dbOwner", "db" : "test2" } ] }> db.auth("gl","gl") 1 > db.dropDatabase() { "dropped" : "test2", "ok" : 1 }
现在我们创建的gl用户拥有dbOwner角色,也就是对当前数据库拥有最高管理权限,这个时候就可以删除数据库test2了。