MongoDB 6.0 單實(shí)例基于用戶角色實(shí)現(xiàn)授權(quán)登錄
現(xiàn)代數(shù)據(jù)庫(kù)系統(tǒng)能夠存儲(chǔ)和處理大量數(shù)據(jù)。因此,由任何一個(gè)用戶單獨(dú)負(fù)責(zé)處理與管理數(shù)據(jù)庫(kù)相關(guān)的所有活動(dòng)的情況相對(duì)較少。通常,不同的數(shù)據(jù)庫(kù)用戶需要對(duì)數(shù)據(jù)庫(kù)的某些部分具有不同級(jí)別的訪問(wèn)權(quán)限:某些用戶可能只需要讀取特定數(shù)據(jù)庫(kù)中的數(shù)據(jù),而其他用戶則必須能夠插入新文檔或修改現(xiàn)有文檔。同樣,應(yīng)用程序可能需要獨(dú)特的權(quán)限,僅允許其訪問(wèn)其運(yùn)行所需的數(shù)據(jù)庫(kù)部分。
MongoDB采用強(qiáng)大的機(jī)制來(lái)控制對(duì)數(shù)據(jù)庫(kù)系統(tǒng)的訪問(wèn)和權(quán)限,稱為基于角色的訪問(wèn)控制(RBAC)。在本文中,您將了解RBAC的工作原理、最小權(quán)限原則的含義和目的,以及如何在實(shí)踐中使用 MongoDB 的訪問(wèn)權(quán)限功能。
訪問(wèn)控制(也稱為授權(quán))是一種安全技術(shù),涉及確定誰(shuí)可以訪問(wèn)哪些資源。
為了更好地理解 MongoDB 中的訪問(wèn)控制,首先將其與另一個(gè)不同但密切相關(guān)的概念進(jìn)行區(qū)分:身份驗(yàn)證。身份驗(yàn)證是確認(rèn)用戶或客戶端是否確實(shí)是他們聲稱的身份的過(guò)程。另一方面,授權(quán)涉及為給定用戶或用戶組設(shè)置規(guī)則,以定義他們可以執(zhí)行哪些操作以及他們可以訪問(wèn)哪些資源。
MongoDB 中的身份驗(yàn)證
在許多數(shù)據(jù)庫(kù)管理系統(tǒng)中,用戶僅通過(guò)用戶名和密碼對(duì)進(jìn)行識(shí)別。當(dāng)使用有效憑據(jù)連接到數(shù)據(jù)庫(kù)時(shí),用戶將經(jīng)過(guò)身份驗(yàn)證并被授予與該用戶關(guān)聯(lián)的訪問(wèn)級(jí)別。在這種方法中,用戶目錄是扁平的,這意味著對(duì)于整個(gè)數(shù)據(jù)庫(kù)服務(wù)器,每個(gè)用戶名必須是唯一的。
相比之下,MongoDB 采用更復(fù)雜的用戶目錄結(jié)構(gòu)。在 MongoDB 中,用戶不僅可以通過(guò)用戶名來(lái)識(shí)別,還可以通過(guò)創(chuàng)建用戶的數(shù)據(jù)庫(kù)來(lái)識(shí)別。對(duì)于每個(gè)用戶,創(chuàng)建他們的數(shù)據(jù)庫(kù)稱為該用戶的身份驗(yàn)證數(shù)據(jù)庫(kù)。
這意味著在 MongoDB 中,可以有多個(gè)用戶具有相同的用戶名(例如sammy),只要它們是在不同的身份驗(yàn)證數(shù)據(jù)庫(kù)中創(chuàng)建的。要以用戶身份進(jìn)行身份驗(yàn)證,您不僅必須提供用戶名和密碼,還必須提供與該用戶關(guān)聯(lián)的身份驗(yàn)證數(shù)據(jù)庫(kù)的名稱。
人們可能會(huì)假設(shè)在給定身份驗(yàn)證數(shù)據(jù)庫(kù)中創(chuàng)建的用戶將具有僅對(duì)該特定數(shù)據(jù)庫(kù)可用的訪問(wèn)權(quán)限,但事實(shí)并非如此。每個(gè)用戶,無(wú)論是在哪個(gè)身份驗(yàn)證數(shù)據(jù)庫(kù)中創(chuàng)建的,都可以具有跨不同數(shù)據(jù)庫(kù)分配的權(quán)限。
MongoDB 中的授權(quán)(基于角色的訪問(wèn)控制)
在 MongoDB 中,您可以通過(guò)稱為基于角色的訪問(wèn)控制(通常縮寫(xiě)為RBAC)的機(jī)制來(lái)控制誰(shuí)有權(quán)訪問(wèn)數(shù)據(jù)庫(kù)上的哪些資源以及訪問(wèn)的程度。
在基于角色的訪問(wèn)控制中,用戶無(wú)權(quán)直接對(duì)資源執(zhí)行操作,例如將新文檔插入數(shù)據(jù)庫(kù)或查詢特定集合。這將使安全策略難以管理并與系統(tǒng)中的許多用戶保持一致。相反,允許對(duì)特定資源執(zhí)行操作的規(guī)則被分配給角色。
將角色視為給定用戶的工作或職責(zé)之一可能會(huì)有所幫助。例如,經(jīng)理可能對(duì)公司 MongoDB 實(shí)例中的每個(gè)文檔具有讀寫(xiě)訪問(wèn)權(quán)限,而銷(xiāo)售分析師可能僅對(duì)銷(xiāo)售記錄具有只讀訪問(wèn)權(quán)限。
角色是用一組一個(gè)或多個(gè)權(quán)限來(lái)定義的。每個(gè)權(quán)限都包含一個(gè)操作(例如創(chuàng)建新文檔、從文檔檢索數(shù)據(jù)或創(chuàng)建和刪除用戶)以及可以執(zhí)行該操作的資源(例如名為 的數(shù)據(jù)庫(kù)或名為 的集合reports)orders。就像在現(xiàn)實(shí)生活中一樣,一家公司可能有許多銷(xiāo)售分析師和員工,他們承擔(dān)多個(gè)職責(zé),在 MongoDB 中,許多用戶可以分配給同一角色,并且單個(gè)用戶可以被授予多個(gè)角色。
角色通過(guò)角色名稱和數(shù)據(jù)庫(kù)的組合來(lái)標(biāo)識(shí),因?yàn)槊總€(gè)角色(在數(shù)據(jù)庫(kù)中創(chuàng)建的角色除外admin)只能包含應(yīng)用于其自己數(shù)據(jù)庫(kù)的權(quán)限。通過(guò)向用戶授予在其身份驗(yàn)證數(shù)據(jù)庫(kù)之外的數(shù)據(jù)庫(kù)中定義的角色,可以向用戶授予對(duì)多個(gè)數(shù)據(jù)庫(kù)進(jìn)行操作的權(quán)限。可以在創(chuàng)建用戶時(shí)或此后的任何時(shí)間授予角色。還可以隨意撤銷(xiāo)角色成員資格,從而可以輕松地將用戶管理與訪問(wèn)權(quán)限管理分離。
MongoDB 提供了一組內(nèi)置角色,描述數(shù)據(jù)庫(kù)系統(tǒng)中常用的權(quán)限,例如read授予只讀訪問(wèn)權(quán)限、readWrite授予讀寫(xiě)權(quán)限或dbOwner授予對(duì)給定數(shù)據(jù)庫(kù)的完全管理權(quán)限。對(duì)于更具體的場(chǎng)景,還可以使用自定義權(quán)限集創(chuàng)建用戶定義的角色。
基于角色的訪問(wèn)控制可以為用戶分配執(zhí)行各自任務(wù)所需的最低、精確級(jí)別的訪問(wèn)權(quán)限。這是一種重要的安全實(shí)踐,稱為最小特權(quán)原則。
- 綁定IP地址
mongod 參數(shù):--bind_ip << ip address >>
默認(rèn)值是所有的IP地址都能訪問(wèn),該參數(shù)指定MongoDB對(duì)外提供服務(wù)的綁定IP地址,用于監(jiān)聽(tīng)客戶端Application的連接,客戶端只能使用綁定的IP地址才能訪問(wèn)mongod,其他IP地址是無(wú)法訪問(wèn)的。
- 設(shè)置監(jiān)聽(tīng)端口
mongod 參數(shù):--port
MongoDB默認(rèn)監(jiān)聽(tīng)的端口是27017,該參數(shù)顯式指定MongoDB實(shí)例監(jiān)聽(tīng)的TCP端口,只有當(dāng)客戶端Application連接的端口和MongoDB實(shí)例監(jiān)聽(tīng)的端口一致時(shí),才能連接到MongoDB實(shí)例。
- 啟用用戶驗(yàn)證
mongod 參數(shù):--auth
默認(rèn)值是不需要驗(yàn)證,即 --noauth,該參數(shù)啟用用戶訪問(wèn)權(quán)限控制;當(dāng)mongod使用該參數(shù)啟動(dòng)時(shí),MongoDB會(huì)驗(yàn)證客戶端連接的賬戶和密碼,以確定其是否有訪問(wèn)的權(quán)限。如果認(rèn)證不通過(guò),那么客戶端不能訪問(wèn)MongoDB的數(shù)據(jù)庫(kù)。
- 權(quán)限認(rèn)證
mongo 參數(shù):-u << username >> -p << password >>
mongo 參數(shù):--authenticationDatabase
在連接mongo時(shí),使用參數(shù) --authenticationDatabase,會(huì)認(rèn)證 -u 和 -p 參數(shù)指定的賬戶和密碼。如果沒(méi)有指定驗(yàn)證數(shù)據(jù)庫(kù),mongo使用連接字符串中指定的DB作為驗(yàn)證數(shù)據(jù)塊。
準(zhǔn)備環(huán)境
[root@MongoDB-Server ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
[root@MongoDB-Server ~]# uname -r
3.10.0-1160.el7.x86_64
[root@MongoDB-Server ~]# setenforce 0
[root@MongoDB-Server ~]# sed -i.bak '7s/enforcing/disabled/' /etc/selinux/config
[root@MongoDB-Server ~]# systemctl stop firewalld
[root@MongoDB-Server ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
Active: inactive (dead)
Docs: man:firewalld(1)
[root@MongoDB-Server ~]# firewall-cmd --state
not running
安裝 MongoDB 6.0
- 前文《MongoDB 基礎(chǔ)知識(shí)梳理》已使用過(guò)yum源安裝,則本文使用二進(jìn)制安裝包。
# 下載 MongoDB, Mongosh
[root@MongoDB-Server ~]# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-6.0.11.tgz
[root@MongoDB-Server ~]# wget https://downloads.mongodb.com/compass/mongosh-2.0.2-linux-x64.tgz
# 解壓縮
[root@MongoDB-Server ~]# mkdir /data/apps/ -p
[root@MongoDB-Server ~]# tar -xf mongodb-linux-x86_64-rhel70-6.0.11.tgz -C /data/apps/
[root@MongoDB-Server ~]# tar -xf mongosh-2.0.2-linux-x64.tgz -C /data/apps/
# 重命名目錄
[root@MongoDB-Server ~]# cd /data/apps/
[root@MongoDB-Server apps]# ls
mongodb-linux-x86_64-rhel70-6.0.11 mongosh-2.0.2-linux-x64
[root@MongoDB-Server apps]# mv mongodb-linux-x86_64-rhel70-6.0.11 mongodb
[root@MongoDB-Server apps]# mv mongosh-2.0.2-linux-x64 mongosh
[root@MongoDB-Server apps]# ls
mongodb mongosh
# 環(huán)境變量
[root@MongoDB-Server ~]# ln -s /data/apps/mongodb/bin/* /usr/local/bin/
[root@MongoDB-Server ~]# ln -s /data/apps/mongosh/bin/* /usr/local/bin/
[root@MongoDB-Server ~]# ls -l /usr/local/bin/
lrwxrwxrwx 1 root root 38 Nov 1 11:49 install_compass -> /data/apps/mongodb/bin/install_compass
lrwxrwxrwx 1 root root 29 Nov 1 11:49 mongod -> /data/apps/mongodb/bin/mongod
lrwxrwxrwx 1 root root 29 Nov 1 11:49 mongos -> /data/apps/mongodb/bin/mongos
lrwxrwxrwx 1 root root 30 Nov 1 11:49 mongosh -> /data/apps/mongosh/bin/mongosh
lrwxrwxrwx 1 root root 42 Nov 1 11:49 mongosh_crypt_v1.so -> /data/apps/mongosh/bin/mongosh_crypt_v1.so
# 創(chuàng)建Mongod相關(guān)目錄
[root@MongoDB-Server ~]# useradd -r -M /var/lib/mongo -s /bin/false
[root@MongoDB-Server ~]# install -d /var/lib/mongo /var/log/mongodb -o mongod -g mongod
[root@MongoDB-Server ~]# ls -dl /var/lib/mongo /var/log/mongodb
drwxr-xr-x 2 mongod mongod 6 Nov 1 12:22 /var/lib/mongo
drwxr-xr-x 2 mongod mongod 6 Nov 1 12:22 /var/log/mongodb
# 使用mongod用戶啟動(dòng)/停止mongod服務(wù)(命令行方式)
[root@MongoDB-Server ~]# su mongod -s /bin/bash -c "mongod -fork -dbpath /var/lib/mongo/ -logpath /var/log/mongodb/mongod.log -logappend"
[root@MongoDB-Server ~]# su mongod -s /bin/bash -c "mongod -fork -dbpath /var/lib/mongo/ -logpath /var/log/mongodb/mongod.log -logappend --shutdown"
登錄Mongodb,創(chuàng)建用戶
[root@MongoDB-Server ~]# mongosh
test> show dbs
admin 40.00 KiB
config 60.00 KiB
local 72.00 KiB
test> use admin
switched to db admin
admin> show collections
system.version
# 創(chuàng)建root用戶
admin> db.createUser({user:"root", pwd:"root@123", roles:[{role:"root", db:"admin"}]})
# 創(chuàng)建admin用戶
> db.createUser({
user: "myAdmin",
pwd: passwordPrompt(), // or cleartext password
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" }
]
})
開(kāi)啟認(rèn)證方式
# 方式一:?jiǎn)?dòng)時(shí)配置--auth參數(shù)開(kāi)啟
[root@MongoDB-Server ~]# su mongod -s /bin/bash -c "mongod -fork -dbpath /var/lib/mongo/ -logpath /var/log/mongodb/mongod.log -logappend --auth"
# 方式二:配置文件中開(kāi)啟
[root@MongoDB-Server ~]# cat /etc/mongod.conf
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
# Where and how to store data.
storage:
dbPath: /var/lib/mongo
journal:
enabled: true
# network interfaces
net:
port: 27017
bindIp: 127.0.0.1 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
# 如果你沒(méi)有可用的用戶,請(qǐng)勿配置該參數(shù)
security:
authorization: enabled
# 使用mongod用戶啟動(dòng)/停止mongod服務(wù)(配置文件方式)
[root@MongoDB-Server ~]# su mongod -s /bin/bash -c "nohup mongod -f /etc/mongod.conf &> /dev/null &"
[root@MongoDB-Server ~]# su mongod -s /bin/bash -c "mongod -f /etc/mongod.conf --shutdown &> /dev/null"
# 驗(yàn)證用戶賬號(hào)及其密碼
[root@MongoDB-Server ~]# mongosh
test> use admin # 切換至admin庫(kù)
switched to db admin
admin> show dbs # 提示需身份驗(yàn)證
MongoServerError: command listDatabases requires authentication
admin> db.system.users.find()
MongoServerError: command find requires authentication
admin> db.auth("root","root@123")
{ ok: 1 } # 認(rèn)證成功
admin> show dbs
admin 180.00 KiB
config 72.00 KiB
local 72.00 KiB
# 連接時(shí)進(jìn)行身份驗(yàn)證
[root@MongoDB-Server ~]# mongosh --port 27017 --authenticationDatabase "admin" -u "myAdmin" -p
# 連接后進(jìn)行身份驗(yàn)證
[root@MongoDB-Server ~]# mongosh --port 27017
> use admin
admin> db.auth("myAdmin", passwordPrompt()) // or cleartext password
MongoDB Roles(內(nèi)置角色)
- 數(shù)據(jù)庫(kù)用戶角色:read、readWrite;
- 數(shù)據(jù)庫(kù)管理角色:dbAdmin、dbOwner、userAdmin;
- 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
- 備份恢復(fù)角色:backup、restore;
- 所有數(shù)據(jù)庫(kù)角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
- 超級(jí)用戶角色:root
- 這里還有幾個(gè)角色間接或直接提供了系統(tǒng)超級(jí)用戶的訪問(wèn)(dbOwner 、userAdmin、userAdminAnyDatabase)
- 內(nèi)部角色:__system
具體角色
- Read:允許用戶讀取指定數(shù)據(jù)庫(kù)
- readWrite:允許用戶讀寫(xiě)指定數(shù)據(jù)庫(kù)
- dbAdmin:允許用戶在指定數(shù)據(jù)庫(kù)中執(zhí)行管理函數(shù),如索引創(chuàng)建、刪除,查看統(tǒng)計(jì)或訪問(wèn)system.profile
- userAdmin:允許用戶向system.users集合寫(xiě)入,可以找指定數(shù)據(jù)庫(kù)里創(chuàng)建、刪除和管理用戶
- clusterAdmin:只在admin數(shù)據(jù)庫(kù)中可用,賦予用戶所有分片和復(fù)制集相關(guān)函數(shù)的管理權(quán)限。
- readAnyDatabase:只在admin數(shù)據(jù)庫(kù)中可用,賦予用戶所有數(shù)據(jù)庫(kù)的讀權(quán)限
- readWriteAnyDatabase:只在admin數(shù)據(jù)庫(kù)中可用,賦予用戶所有數(shù)據(jù)庫(kù)的讀寫(xiě)權(quán)限
- userAdminAnyDatabase:只在admin數(shù)據(jù)庫(kù)中可用,賦予用戶所有數(shù)據(jù)庫(kù)的userAdmin權(quán)限
- dbAdminAnyDatabase:只在admin數(shù)據(jù)庫(kù)中可用,賦予用戶所有數(shù)據(jù)庫(kù)的dbAdmin權(quán)限。
- root:只在admin數(shù)據(jù)庫(kù)中可用。超級(jí)賬號(hào),超級(jí)權(quán)限
用戶管理
# 查詢單用戶
db.getUser("myUser")
db.system.users.find({user:"myUser"})
# 查詢所有用戶
show users
db.getUsers()
db.system.users.find()
# 身份驗(yàn)證
db.auth( <myUser>, passwordPrompt() ) # 提示輸入密碼
db.auth( <myUser>, <myUserpasswd> ) # 明文密碼
# 返回:1為身份驗(yàn)證成功
# 創(chuàng)建新用戶,授權(quán)myAdmin用戶所有數(shù)據(jù)庫(kù)的讀寫(xiě)及創(chuàng)建、刪除和管理用戶的權(quán)限
use admin
db.createUser(
{
user: "myAdmin",
pwd: passwordPrompt(), // Or "<cleartext password>"
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" }
}
)
# 普通用戶,授權(quán)myUser用戶對(duì)myDBName的讀寫(xiě)操作,該用戶只能從192.0.2.0段連接到198.51.100.0段
use admin
db.createUser(
{
user: "myUser",
pwd: passwordPrompt(), // Or "<cleartext password>"
roles: [ { role: "readWrite", db: "myDBName" } ],
authenticationRestrictions: [ {
clientSource: ["192.0.2.0"],
serverAddress: ["198.51.100.0"]
} ]
}
)
# 修改用戶密碼
use admin
db.changeUserPassword("myUser", passwordPrompt())
db.changeUserPassword("myUser", "myUserpasswd")
db.updateUser("myUser", {pwd:"myUserpasswd"})
# 刪除單個(gè)用戶
use admin
db.dropUser("myUser")
db.system.users.remove({user:"myUser"})
db.removeUser() // 舊版本,已棄用
# 刪除所有用戶
db.dropAllUsers()
db.system.users.remove({})
角色管理
# 授權(quán)myUser用戶對(duì)myDBName數(shù)據(jù)庫(kù)的讀寫(xiě)操作
db.grantRolesToUser("myUser", [{role: "readWrite", db: "myDBName"}])
# 撤銷(xiāo)myUser用戶對(duì)myDBName數(shù)據(jù)庫(kù)的讀寫(xiě)操作
db.revokeRolesFromUser("myUser", [{role: "readWrite", db: "myDBName"}])
# 修改myUser用戶僅對(duì)myDBName數(shù)據(jù)庫(kù)只讀操作
db.updateUser("myUser", {roles: [ {role: "read", db: "myDBName"} ]})
出處:http://www.rzrgm.cn/zhangwencheng
版權(quán):本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出 原文鏈接
浙公網(wǎng)安備 33010602011771號(hào)