注:本文基于MongoDB 4.2.6编写
> db.createUser( { user: "testuser", pwd: "test", roles:[]})
Successfully added user: { "user" : "testuser", "roles" : [ ] }
其中user指定用户名,pwd指定密码,roles指定该用户的角色,这个和权限相关,我们后面再讲。
如果不想明文指定密码,可通过passwordPrompt()使用键盘输入方式设置密码,
> db.createUser( { user: "me", pwd: passwordPrompt(), roles:[]})
Enter password:
Successfully added user: { "user" : "me", "roles" : [ ] }
A、查询特定用户
> db.getUser("me")
{
"_id" : "test.me",
"userId" : UUID("b4a02c61-6d95-41f6-9d3b-11a5493a7476"),
"user" : "me",
"db" : "test",
"roles" : [ ],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
>
B、查询当前数据库中的用户,有两种方式
> db.getUsers()
[
{
"_id" : "test.hello",
"userId" : UUID("da14e1ba-dad7-4c2b-b15e-a59efffe49cc"),
"user" : "hello",
"db" : "test",
"roles" : [ ],
...
},
{
"_id" : "test.me",
"userId" : UUID("b4a02c61-6d95-41f6-9d3b-11a5493a7476"),
"user" : "me",
"db" : "test",
"roles" : [ ],
...
}
]
> show users
{
"_id" : "test.hello",
"userId" : UUID("da14e1ba-dad7-4c2b-b15e-a59efffe49cc"),
"user" : "hello",
"db" : "test",
"roles" : [ ],
...
}
{
"_id" : "test.me",
"userId" : UUID("b4a02c61-6d95-41f6-9d3b-11a5493a7476"),
"user" : "me",
"db" : "test",
"roles" : [ ],
...
}
C、查询所有数据库中的用户
> use admin
switched to db admin
> db.system.users.find().pretty()
{
"_id" : "abc.testuser",
"userId" : UUID("64a2e8ad-a1e1-4733-8845-05f88fc49449"),
"user" : "testuser",
"db" : "abc",
"credentials" : {
...
},
"roles" : [ ]
}
{
"_id" : "test.hello",
"userId" : UUID("da14e1ba-dad7-4c2b-b15e-a59efffe49cc"),
"user" : "hello",
"db" : "test",
"credentials" : {
...
},
"roles" : [ ]
}
{
"_id" : "test.me",
"userId" : UUID("b4a02c61-6d95-41f6-9d3b-11a5493a7476"),
"user" : "me",
"db" : "test",
"credentials" : {
...
},
"roles" : [ ]
}
可以明文指定密码,也可以使用键盘输入方式,
> db.changeUserPassword("hello", "world")
> db.changeUserPassword("hello", passwordPrompt())
Enter password:
>
删除特定用户
> db.dropUser("hello")
true
删除当前数据库所有用户
> db.dropAllUsers()
NumberLong(2)
MongoDB通过RABC来对数据库资源和操作进行权限管理,简单来说就是将数据库权限,如读写删除等,以及资源,如表,集合等按照一定规则聚合成某一些组合,然后将这个组合关联到某个角色,比如普通管理员,admin管理员等,最后将用户与角色关联,从而完成权限管理和认证。K8S中也是采用这种方式来进行认证和授权管理。
默认情况下,MongoDB没有开启鉴权,因此我们只要输入mongo命令就能连接到本地的数据库,而且具有admin权限,
[root@localhost ~]# mongo --quiet
> show dbs
abc 0.000GB
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
而对于开放了公网权限的数据库(mongod监听所有地址),只要知道对方ip地址和服务端口,任何人都可以连接到这个数据库,并拥有root权限。因此如果你的数据未开启鉴权认证,又暴露在公网中,就很容易被一些人通过ip端口扫描的方式控制数据库。
需要修改MongoDB配置文件/etc/mongod.conf,增加以下配置,
security:
authorization: enabled
然后重启服务即可,
systemctl restart mongod
这时候再执行mongo命令连接数据库之后,基本上就无法执行操作,
[root@localhost ~]# mongod --quiet
> show dbs
> show collections
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
>
此时就需要通过用户名和密码来访问连接数据库。但是由于我们上面讲的创建用户都没有关联角色,因此创建的用户能连接到数据库,但是很多权限都没有,因此我们需要创建带有角色的用户。
在创建这个带有角色的用户前,我们先了解一下有哪些角色,这些角色有哪些权限。
这些角色只能在Admin数据库下创建
这些角色只能在Admin数据库下创建
这些角色只能在Admin数据库下创建
这些角色只能在Admin数据库下创建
介绍完各个角色之后,我们尝试创建我们需要的用户。
我们尝试创建一个超管用户,一个管理员用户,以及一个普通用户。
> use admin
switched to db admin
> db.createUser({user: "root", pwd: "root", roles: ["root"]})
Successfully added user: { "user" : "root", "roles" : [ "root" ] }
> db.getUser("root")
{
"_id" : "admin.root",
"userId" : UUID("333f11a3-74a1-4e5d-926e-9d4264098d03"),
"user" : "root",
"db" : "admin",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
],
...
}
而且,只能在admin数据库下创建超管用户,否则会报错,
> use test
switched to db test
> db.createUser({user: "root", pwd: "root", roles: ["root"]})
2020-06-17T10:07:55.883-0400 E QUERY [js] uncaught exception: Error: couldn't add user: No role named root@test :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype.createUser@src/mongo/shell/db.js:1370:11
@(shell):1:1
>
[root@localhost ~]# mongo -u root -p --quiet
Enter password:
> use admin
switched to db admin
> db.createUser({user: "admin", pwd: "admin", roles: ["userAdminAnyDatabase", "readWriteAnyDatabase"]})
Successfully added user: {
"user" : "admin",
"roles" : [
"userAdminAnyDatabase",
"readWriteAnyDatabase"
]
}
> db.getUser("admin")
{
"_id" : "admin.admin",
"userId" : UUID("e62da4de-bb44-4bc8-b57e-3bd810d7bd4c"),
"user" : "admin",
"db" : "admin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
},
{
"role" : "readWriteAnyDatabase",
"db" : "admin"
}
],
...
}
> use abc
switched to db abc
> db.createUser({user: "read", pwd: "read", roles: ["read"]})
Successfully added user: { "user" : "read", "roles" : [ "read" ] }
>
用这个普通用户创建用户,或者读取其他数据库数据都会失败,
[root@localhost ~]# mongo -u read -p --host localhost:27017 --quiet --authenticationDatabase abc
Enter password:
> use abc
switched to db abc
> db.createUser({user: "write", pwd: "write", roles: ["write"]})
2020-06-18T09:23:01.370-0400 E QUERY [js] uncaught exception: Error: couldn't add user: not authorized on abc to execute command { createUser: "write", pwd: "xxx", roles: [ "write" ], digestPassword: true, writeConcern: { w: "majority", wtimeout: 600000.0 }, lsid: { id: UUID("ce601eec-d1dd-489b-be3d-7364accf1423") }, $db: "abc" } :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype.createUser@src/mongo/shell/db.js:1370:11
@(shell):1:1
> use test
switched to db test
> show collections
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
> use abc
switched to db abc
> show collections
bb
> db.createUser({user: "hello", pwd: "hello", roles: []})
Successfully added user: { "user" : "hello", "roles" : [ ] }
> db.getUser("hello")
{
"_id" : "admin.hello",
"userId" : UUID("d8fb4612-4b05-4571-9746-9f4b7d62f27d"),
"user" : "hello",
"db" : "admin",
"roles" : [ ],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
> db.grantRolesToUser("hello", ["read", {role: "readWrite", db: "abc"}])
> db.getUser("hello")
{
"_id" : "admin.hello",
"userId" : UUID("d8fb4612-4b05-4571-9746-9f4b7d62f27d"),
"user" : "hello",
"db" : "admin",
"roles" : [
{
"role" : "read",
"db" : "admin"
},
{
"role" : "readWrite",
"db" : "abc"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
我们开始时创建了一个没有任何角色的用户,然后授予admin数据库的read角色,以及abc数据库的读写角色。
角色能授予,自然也能收回,
> db.getUser("hello")
{
"_id" : "admin.hello",
"userId" : UUID("d8fb4612-4b05-4571-9746-9f4b7d62f27d"),
"user" : "hello",
"db" : "admin",
"roles" : [
{
"role" : "read",
"db" : "admin"
},
{
"role" : "readWrite",
"db" : "abc"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
> db.revokeRolesFromUser("hello", [{role: "readWrite", db: "abc"}])
> db.getUser("hello")
{
"_id" : "admin.hello",
"userId" : UUID("d8fb4612-4b05-4571-9746-9f4b7d62f27d"),
"user" : "hello",
"db" : "admin",
"roles" : [
{
"role" : "read",
"db" : "admin"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
这里我们收回了hello用户对admin数据库的read角色。
很多时候我们需要的权限比较复杂,系统自带的角色无法满足我们的要求,这是我们就可以自己动手,创建定制角色。
> db.createRole({role: "myAdmin", privileges: [{resource: {db: "test", collection: "aa"}, actions: ["find", "update"]}], roles: [{role: "read", db: "admin"},{role: "readWrite", db: "abc"}]})
{
"role" : "myAdmin",
...
}
> db.getRole("myAdmin")
{
"role" : "myAdmin",
"db" : "admin",
"isBuiltin" : false,
"roles" : [
{
"role" : "read",
"db" : "admin"
},
{
"role" : "readWrite",
"db" : "abc"
}
],
"inheritedRoles" : [
{
"role" : "read",
"db" : "admin"
},
{
"role" : "readWrite",
"db" : "abc"
}
]
}
这里我们创建了一个角色myAdmin,拥有对test数据库aa集合的find和update操作,同时还拥有admin数据库的read角色,以及abc数据库readWrite角色。因此通过自己创建角色,可以实现多元化的权限需求和更精细的权限控制。
可以创建角色,当然也可以删除角色,不过只能删除用户创建的角色,无法删除系统自带的角色,
> use admin
switched to db admin
> db.dropRole("myTest")
true
> db.dropRole("read")
2020-06-20T23:12:43.872-0400 E QUERY [js] uncaught exception: Error: read@admin is a built-in role and cannot be modified. :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype.dropRole@src/mongo/shell/db.js:1681:11
@(shell):1:1
>
更多角色管理操作可以阅读MongoDB文档:https://docs.mongodb.com/manual/reference/method/js-role-management/
参考资料:
1、https://docs.mongodb.com/manual/reference/built-in-roles/#built-in-roles