########################################
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 //指定查看角色信息的時候是否顯示它所擁有的權限信息,也可不指定 } ) // 業余草:www.xttblog.com db.getRoles( { rolesInfo: 1, showPrivileges:true, showBuiltinRoles: true } )
角色權限的繼承和角色權限回收。
//角色繼承 db.grantRolesToRole( "testrole", [ "otherrole1","otherrole2" ] // 將 otherrole1、otherrole2 兩個角色(假設之前已經創建好)的權限授予testrole角色 ) // 業余草:www.xttblog.com //角色權限回收 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角色與權限:
角色是權限的集合,權限是某資源上能執行的操作的集合
查看某個角色權限詳情:
#####################################