########################################

MongoDB 作为一个分布式文件存储的数据库使用的人越来越多。它里面包含很多内置的角色和权限,本文来介绍一下它的权限设计和使用。在介绍 MongoDB 的权限管理之前,我们先来回顾一下目前比较流行的权限管理方案。

mongodb创建普通角色和普通用户_用户名

 

 

MongoDB 2.6 从版本开始,MongoDB 已经开始尝试引入相对精细的权限控制,不过直到 MongoDB3.0 版本权限体系才算相对完善,所以本文将主要介绍 MongoDB3.0 版本的权限控制机制。

MongoDB 中的权限

MongoDB 的权限设计与上面类似。MongoDB 中的权限主要有下面 6 个对象组成。

  • user:用户,用于提供客户端连接 MongoDB 的认证账户
  • role:角色,数据权限的集合,创建用户的时候必须要指定对应的角色,否则用户无法操作数据库
  • resource:4种资源:

                            包括database或collection也可以是database和collection的组合。例如:{ db: <database>, collection: <collection> }

                            当然你也可能看到一种特殊的资源:{"cluster" : true},它其实表示的是全局资源

                            内部资源​​anyResource​​​可访问系统中的每个资源,仅供内部使用。除特殊情况外,请勿使用此资源。此资源的语法为 。​​{ anyResource: true }​

  • actions:权限操作,"actions" 定义了"user"能够对 "resource document"执行的操作。例如,增删改查包括如下操作:find、insert、remove、update。以及其他 serverStatus、killop、inprog、killCursors 等更高级权限
  • privilege:权限,"privilege" 是一组"resource" 和 "actions" 的组合
  • authenticationDatabase:认证库,即创建角色或用户时所在的库。例如,在 admin 下创建了 MongoDB 用户那么登陆的时候需要指定认证库

MongoDB 创建角色

MongoDB 里角色分为 ”内建角色“ 和 ”用户自定义“ 角色两种。内建角色是 MongoDB 为了方便用户管理和内部操作进行的预定义的一些权限。多数时候为了精细化权限控制 MongoDB 的内建角色无法满足我们的需求,因此需要 DBA 自定义角色来进行更加详细的权限控制。

use xttblog //进入 xttblog 数据库

db.createRole(
{
role:"testrole",//角色名称
privileges: [ // 权限集
{
resource: //资源
{
db:"jhr", //创建的testrole角色具有对xttblog库的操作权限,具体权限建actions
collection:"" //xttblog库下对应的集合名.如果为""表示所有集合
},
actions: [ "find", "insert", "remove","update" ] //角色可进行的操作,注意这里是一个数组
}
],
roles: [] // 是否继承其他的角色,如果指定了其他角色那么新创建的角色自动继承对应其他角色的所有权限,该参数必须显示指定
}
)

上述语句在 xttblog 库里创建了一个名为 testrole 的角色,该角色具有对数据库 xttblog 下的所有集合进行 find、insert、remove、update 的操作的权限。

角色创建完毕后 MongoDB 会在系统库 admin 下创建一个系统 collection 名叫 system.roles 里面存储的即是角色相关的信息。

可以使用下面的语句对创建的角色进行查看。

db.getCollection('system.roles').find({})

db.system.roles.find();

也可以使用下面的查询语句查看角色信息。

db.getRole("testrole", //要查看角色的名字
{
showPrivileges: true //指定查看角色信息的时候是否显示它所拥有的权限信息,也可不指定
}
)
db.getRoles(
{
rolesInfo: 1,
showPrivileges:true,
showBuiltinRoles: true
}
)

角色权限的继承和角色权限回收。

//角色继承
db.grantRolesToRole(
"testrole",
[ "otherrole1","otherrole2" ] // 将 otherrole1、otherrole2 两个角色(假设之前已经创建好)的权限授予testrole角色
)
//角色权限回收
db.revokeRolesFromRole(
"testrole" ,
[ "otherrole2" ] // 撤销testrole角色从otherrole2角色所继承的所有权限
)

角色授权

db.grantPrivilegesToRole(
"testrole",
[
{
resource: //权限可操作的资源
{
db:"xttblog", // 授予testrole角色具有操作xttblog库的权限
collection:"" // lidan_1库下的集合 如果为"" 表示所有集合
},
actions: // 权限允许的操作
[ "createCollection", "dropCollection","convertToCapped"] //权限可进行的操作
}
]
)

执行完操作后 testrole 角色便可以对库 xttblog 下的所有集合进行 "createCollection", "dropCollection","convertToCapped" 操作。

角色权限回收

db.revokePrivilegesFromRole(
"testrole",
[
{
resource: //权限可操作的资源
{
db:"xttblog", // 回收角色对库 xttblog 的 actions 操作权限
collection:"" // xttblog 库下所有的集合 如果为"" 表示所有集合
},
actions: // 权限允许的操作
[ "createCollection", "dropCollection","convertToCapped"] //需要回收的权限
}
]
)

执行完操作后 testrole 角色对库 xttblog 下的所有集合无法进行 "createCollection", "dropCollection","convertToCapped" 操作。

删除角色

db.dropRole("testrole") // 删除角色比较简单直接指定要删除角色的名称即可

创建用户

// 指定内建角色来创建用户
db.createUser(
{
user:'mongo', // 用户名
pwd:'123', // 密码
roles:[
{
role:'root',// 通过指定内建角色root 来创建用户
db:'admin' // 指定角色对应的认证数据库,内建角色通常认证库为admin
}
]
}
);
// 指定自定义角色来创建用户,这里是在admin下创建的用户故认证库也是admin
db.createUser(
{
user:"mongo",// 用户名
pwd:"123", // 密码
roles:["testrole"] //通过指定用户自定义角色来创建用户,注意这里是数组
}
)

查看用户

db.getUser("mongo") // 查看用户比较简单只需要指定用户名即可

为用户添加/回收角色

use admin
//为用户添加角色
db.grantRolesToUser(
"mongo", // 用户名
[
{
role: "testrole", // 需要添加的角色名
db: "admin" // 角色对应的认证库,即角色创建时所在的数据库
}
]
)
//对用户的角色进行回收,如果将用户所有的角色都回收完毕,那么用户只有对所属库的连接权限
db.revokeRolesFromUser(
"mongo", // 用户名
[
{
role: "testrole", // 需要回收的角色名
db: "admin" // 角色对应的认证库,即角色创建时所在的数据库
}
]
)

删除用户

db.dropUser("mongo"); // 删除用户比较简单直接指定用户名即可

好了,MongoDB 的角色权限就这么简单。最后强调一点,在 MongoDB 中删除库和集合并不会级联删除对应的角色和用户。因此如果想彻底删除对应的业务库因该先删除库及其对应的角色和用户。

 

假设业务的数据库名称为:apple,那么一般需要给业务提供一个读写角色和一个只读角色:

###################################

创建只读角色:

use admin;
db.createRole(
{
role: "apple_r",
privileges: [
{ resource: { db: "apple", collection: "" }, actions: [ "find", "listCollections","listIndexes"] }
],
roles: []
}
);

##################################

创建读写角色:
use admin;
db.createRole(
{
role: "apple_rw",
privileges: [
{ resource: { db: "apple", collection: "" }, actions: [ "find", "listCollections","listIndexes","insert","remove","update"] }
],
roles: []
}
);

 

 

##############################

创建只读账号:

use admin;
db.createUser({user:"apple_r",
pwd:"123456",
roles:[{role:"apple_r",db:"admin"}]});

###############################

创建读写账号:

use admin;
db.createUser({user:"apple_rw",
pwd:"123456",
roles:[{role:"apple_rw",db:"admin"}]});

 

 

角色管理:

 

mongodb安装完后默认是不开启auth模块的,普通用户和超级管理员均不通过认证就可操作。当然裸奔有风险,安全起见还是开启auth模块。业务测试库通常是这样运行的。
首先需要了解下面几点:
1、mongodb是没有默认管理员账号,所以要先添加管理员账号,然后开启权限认证。
2、切换到admin数据库,添加的账号才是管理员账号。
3、用户只能在用户所在数据库登录,包括管理员账号。
4、管理员可以管理所有数据库,但是不能直接管理其他数据库,要先在admin数据库认证后才可以。这一点比较怪。

MongoDB将所有角色信息存储在admin数据库的admin.system.roles集合中

内置角色只能控制User在DB级别上执行的操作,管理员可以创建自定义角色,控制用户在集合级别(Collection-Level)上执行的操作,即,控制User在当前DB的特定集合上执行特定的操作。

下面是mongodb系统内置的角色:

普通数据库用户的角色:
1,read:授予User只读数据的权限
2,readWrite:授予User读写数据的权限

跨库角色:admin中,且除config和local之外所有的数据库:
1,readAnyDatabase:授予在所有数据库上读取数据的权限
2,readWriteAnyDatabase:授予在所有数据库上读写数据的权限
3,userAdminAnyDatabase:授予在所有数据库上管理User的权限
4,dbAdminAnyDatabase:授予管理所有数据库的权限

数据库管理角色:
1,userAdmin:在当前DB中管理User
2,dbAdmin:在当前dB中执行管理操作
3,dbOwner:在当前DB中执行任意操作

超级角色:
1,userAdmin
2,userAdminAnyDatabase
3,root

集群管理角色:
1,clusterMonitor:授予监控集群的权限,对监控工具具有readonly的权限
2,clusterAdmin:授予管理集群的最高权限
3,clusterManager:授予管理和监控集群的权限
4,hostManager:管理Server

备份恢复角色:
1,backup
2,restore

内部角色:
1,__system
2,__queryableBackup
分片角色:
1,enableSharding
############################################
############################################
在创建角色时,必须明确Role的四个特性:
1,Scope:角色作用的范围,创建在Admin中的角色,能够在其他DB中使用;在其他DB中创建的角色,只能在当前DB中使用;在admin 数据库中创建的角色,Scope是全局的,能够在admin,
其他DB和集群中使用,并且能够继承其他DB的Role;而在非admin中创建的角色,Scope是当前数据库,只能在当前DB中使用,只能继承当前数据库的角色。因此创建角色,一般都在admin库中创建:
2,Resource:角色控制的资源,表示授予在该资源上执行特定操作的权限;
3,Privilege Actions:定义了User能够在资源上执行的操作,系统定义Action是:Privilege Actions;
4,Inherit:角色能够继承其他角色权限;

资源:
1,集群级别:{ cluster: true };
2,数据库级别:{ db: "apple", collection: "" };
3,表级别:{ db: "apple", collection: "iphone" };
MongoDB的权限包由:资源(Resource)和操作(Action)两部分组成,Privilege Actions 定义User能够在资源上执行的操作,例如:MongoDB在文档级别(Document-Level)上执行的读写操作列表是:find,insert,remove,update;
在roles数组中:
指定被继承的role,即,新建的new_role从roles数组中继承权限:
1,如果被继承的role在当前DB中,定义的格式是:roles:["one","two"];
2,如果被继承的role不在当前DB中,需要使用doc,指定该role所在的DB,定义的格式是:roles:[{role:"role_name", db:"db_name"}];


查找角色:
db.getRole() :
db.getRoles() :

// 查看具体某个角色
use admin;
db.getRole("read",{showPrivileges:true});
use admin
db.getRole( "associate", { showPrivileges: true,showBuiltinRoles:true } );

// 查看当前库的所有角色:
show roles;
db.getRoles({rolesInfo: 1,
showPrivileges:true,
showBuiltinRoles: true
});


创建角色:
db.createRole() :

use admin;
db.createRole(
{
role: "google",
privileges: [
{ resource: { cluster: true }, actions: [ "addShard" ] },
{ resource: { db: "config", collection: "" }, actions: [ "find", "update", "insert", "remove" ] },
{ resource: { db: "users", collection: "xiaomi" }, actions: [ "update", "insert", "remove" ] },
{ resource: { db: "", collection: "" }, actions: [ "find" ] }
],
roles: [
{ role: "read", db: "admin" }
]
},
{ w: "majority" , wtimeout: 5000 }
);

//
use admin;
db.createRole(
{
role: "myClusterwideAdmin",
privileges: [
{ resource: { cluster: true }, actions: [ "addShard" ] },
{ resource: { db: "config", collection: "" }, actions: [ "find", "update", "insert", "remove" ] },
{ resource: { db: "users", collection: "usersCollection" }, actions: [ "update", "insert", "remove" ] },
{ resource: { db: "", collection: "" }, actions: [ "find" ] }
],
roles: [
{ role: "read", db: "admin" }
]
},
{ w: "majority" , wtimeout: 5000 });

//
use admin;
db.createRole(
{
role: "apple",
privileges: [
{ resource: { cluster: true }, actions: [ "killop", "inprog" ] },
{ resource: { db: "", collection: "" }, actions: [ "killCursors" ] }
],
roles: []
}
);

db.createRole({ "role": "perconabakcupAnyAction",
"privileges": [{ "resource": { "anyResource": true },"actions": [ "anyAction" ]}],
"roles": []}
);

删除角色:
db.dropRole() :
db.dropAllRoles() :

更新角色:
db.updateRole() :
use admin;
db.updateRole(
"my_role",
{
privileges:
[
{
resource: { db:"products", collection:"clothing" },
actions: [ "update", "createCollection", "createIndex"]
}
],
roles:
[
{
role: "read",
db: "products"
}
]
},
{ w:"majority" });


添指定的继承角色:
db.grantRolesToRole() :
use admin;
db.grantRolesToRole(
"productsReaderWriter",
[ "productsReader" ],
{ w: "majority" , wtimeout: 5000 });

撤销指定继承的角色:
db.revokeRolesFromRole() :
use admin;
db.revokeRolesFromRole( "my_role",
[
"writeOrdersCollection",
"readOrdersCollection"
],
{ w: "majority" , wtimeout: 5000 }
);


给角色添加新的权限:
db.grantPrivilegesToRole() :
use productsdb.grantPrivilegesToRole(
"my_role",
[
{
resource: { db: "products", collection: "" },
actions: [ "insert" ]
},
{
resource: { db: "products", collection: "system.js" },
actions: [ "find" ]
}
],
{ w: "majority" }
);

拿掉角色指定权限:
db.revokePrivilegesFromRole() :
db.revokePrivilegesFromRole(
"my_role",
[
{
resource: { db: "products", collection: "" },
actions: [ "createCollection", "createIndex", "find" ]
},
{
resource: { db: "products", collection: "orders" },
actions: [ "insert" ]
}
],
{ w: "majority" })


在当前DB中创建角色:

#########################
#########################




查看系统所有角色
db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })

#################################################################
#################################################################

 

给角色新增权限:db.grantPrivilegesToRole()

mivpn:PRIMARY> db.getRole("mivpn_admin_rl",{showPrivileges:true});
{
"role" : "mivpn_admin_rl",
"db" : "admin",
"isBuiltin" : false,
"roles" : [ ],
"inheritedRoles" : [ ],
"privileges" : [
{
"resource" : {
"db" : "mivpn_admin",
"collection" : ""
},
"actions" : [
"collStats",
"dbHash",
"dbStats",
"find",
"insert",
"killCursors",
"listCollections",
"listIndexes",
"remove",
"update"
]
}
],
"inheritedPrivileges" : [
{
"resource" : {
"db" : "mivpn_admin",
"collection" : ""
},
"actions" : [
"collStats",
"dbHash",
"dbStats",
"find",
"insert",
"killCursors",
"listCollections",
"listIndexes",
"remove",
"update"
]
}
]
}
mivpn:PRIMARY>
db.grantPrivilegesToRole("mivpn_admin_rl",[{resource: { db: "mivpn", collection: "" },actions: [ "insert", "collStats","dbHash","dbStats","find","killCursors","listCollections","listIndexes","remove","update" ]}])
mivpn:PRIMARY> db.getRole("mivpn_admin_rl",{showPrivileges:true});
{
"role" : "mivpn_admin_rl",
"db" : "admin",
"isBuiltin" : false,
"roles" : [ ],
"inheritedRoles" : [ ],
"privileges" : [
{
"resource" : {
"db" : "mivpn_admin",
"collection" : ""
},
"actions" : [
"collStats",
"dbHash",
"dbStats",
"find",
"insert",
"killCursors",
"listCollections",
"listIndexes",
"remove",
"update"
]
},
{
"resource" : {
"db" : "mivpn",
"collection" : ""
},
"actions" : [
"collStats",
"dbHash",
"dbStats",
"find",
"insert",
"killCursors",
"listCollections",
"listIndexes",
"remove",
"update"
]
}
],
"inheritedPrivileges" : [
{
"resource" : {
"db" : "mivpn_admin",
"collection" : ""
},
"actions" : [
"collStats",
"dbHash",
"dbStats",
"find",
"insert",
"killCursors",
"listCollections",
"listIndexes",
"remove",
"update"
]
},
{
"resource" : {
"db" : "mivpn",
"collection" : ""
},
"actions" : [
"collStats",
"dbHash",
"dbStats",
"find",
"insert",
"killCursors",
"listCollections",
"listIndexes",
"remove",
"update"
]
}
]
}
mivpn:PRIMARY>

 

 

 

 

系统所有角色:

 

glc-test:PRIMARY> show roles;
{
"role" : "__queryableBackup",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "__system",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "backup",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "clusterAdmin",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "clusterManager",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "clusterMonitor",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "dbAdmin",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "dbAdminAnyDatabase",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "dbOwner",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "enableSharding",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "hostManager",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "manageOpRole",
"db" : "admin",
"isBuiltin" : false,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "myClusterwideAdmin",
"db" : "admin",
"isBuiltin" : false,
"roles" : [
{
"role" : "read",
"db" : "admin"
}
],
"inheritedRoles" : [
{
"role" : "read",
"db" : "admin"
}
]
}
{
"role" : "read",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "readAnyDatabase",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "readWrite",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "readWriteAnyDatabase",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "restore",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "root",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "userAdmin",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "userAdminAnyDatabase",
"db" : "admin",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
{
"role" : "xmmgbakcupAnyAction",
"db" : "admin",
"isBuiltin" : false,
"roles" : [ ],
"inheritedRoles" : [ ]
}
glc-test:PRIMARY>

 

 

mongodb角色与权限:

 

角色是权限的集合,权限是某资源上能执行的操作的集合

 

查看某个角色权限详情:

 

 

 

#####################################