MongoDB 4.x 的權(quán)限管理說(shuō)明

MongoDB是一款高性能的nosql數(shù)據(jù)庫(kù)荞膘,因?yàn)樵跀?shù)據(jù)結(jié)構(gòu)的定義上有著極大的靈活性,所以在獲取個(gè)人信息玉工、社交網(wǎng)絡(luò)羽资、地理位置、行為日志等互聯(lián)網(wǎng)場(chǎng)景中有著廣泛的應(yīng)用遵班。默認(rèn)情況下屠升,MongoDB實(shí)例啟動(dòng)運(yùn)行時(shí)是沒(méi)有啟用用戶訪問(wèn)權(quán)限控制的,也就是說(shuō)MongoDB不會(huì)對(duì)連接客戶端進(jìn)行用戶驗(yàn)證狭郑,用戶可以以root權(quán)限執(zhí)行任何操作腹暖,這顯然在生產(chǎn)環(huán)境下是不行的,本篇文章討論MongoDB的認(rèn)證及權(quán)限控制功能的配置翰萨。

之前的一篇文章深入理解Kubernetes的認(rèn)證與授權(quán)機(jī)制其實(shí)已經(jīng)提到微服,任何系統(tǒng)的權(quán)限管理的核心是認(rèn)證和授權(quán),mongodb自然也不例外缨历。認(rèn)證方面,我們考慮最簡(jiǎn)單的用戶名密碼方式實(shí)現(xiàn)(其實(shí)mongo還支持x509證書糙麦、kerberos辛孵、LDAP等方式)。權(quán)限管理方面赡磅,mongo使用的也是rbac模型魄缚,通過(guò)將用戶和一組角色進(jìn)行綁定,來(lái)進(jìn)行數(shù)據(jù)庫(kù)各類操作的權(quán)限控制焚廊。

角色設(shè)計(jì)

mongo對(duì)于數(shù)據(jù)庫(kù)的各項(xiàng)操作我總結(jié)抽象為以下幾類:

  • 對(duì)于數(shù)據(jù)庫(kù)數(shù)據(jù)的讀冶匹、寫操作
  • 對(duì)于數(shù)據(jù)庫(kù)管理的各類操作,例如與schema相關(guān)咆瘟、索引嚼隘、收集統(tǒng)計(jì)信息,對(duì)數(shù)據(jù)庫(kù)進(jìn)行清理袒餐、修改飞蛹、壓縮谤狡、獲取統(tǒng)計(jì)信息、執(zhí)行檢查等操作卧檐。
  • 對(duì)于數(shù)據(jù)庫(kù)用戶和角色的管理操作墓懂,可以分配scope范圍內(nèi)的角色給指定用戶

所謂的權(quán)限管理就是對(duì)上述操作進(jìn)行各種排列組合,定義出一組角色霉囚,并且賦予給對(duì)應(yīng)的用戶捕仔。為了方便用戶使用,mongodb已經(jīng)內(nèi)置了一組角色盈罐,在絕大部分場(chǎng)景下已經(jīng)足夠用了榜跌。需要注意的是,MongoDB在每個(gè)數(shù)據(jù)庫(kù)上都提供內(nèi)置的數(shù)據(jù)庫(kù)用戶角色數(shù)據(jù)庫(kù)管理角色暖呕,但只在admin數(shù)據(jù)庫(kù)中提供其它的內(nèi)置角色斜做。同時(shí),角色有scope(作用域)的概念湾揽,一般有指定數(shù)據(jù)庫(kù)和所有數(shù)據(jù)庫(kù)兩種瓤逼。官方內(nèi)置的角色列表如下:

數(shù)據(jù)庫(kù)用戶角色(Database User Roles)

  • read:可以讀取指定數(shù)據(jù)庫(kù)中任何數(shù)據(jù)。
  • readWrite:可以讀寫指定數(shù)據(jù)庫(kù)中任何數(shù)據(jù)库物,包括創(chuàng)建霸旗、重命名、刪除集合戚揭。

數(shù)據(jù)庫(kù)管理角色(Database Administration Roles)

  • dbAdmin:包含執(zhí)行某些管理任務(wù)(與schema相關(guān)诱告、索引、收集統(tǒng)計(jì)信息)的權(quán)限民晒,該角色不包含用戶和角色管理的權(quán)限精居。
  • dbOwner:包含對(duì)指定數(shù)據(jù)庫(kù)所有的管理操作權(quán)限。即角色readWrite潜必、dbAdmin和userAdmin的集合靴姿。
  • userAdmin:包含對(duì)當(dāng)前數(shù)據(jù)庫(kù)創(chuàng)建和修改角色和用戶的權(quán)限。該角色允許向其它任何用戶(包括自身)授予任何權(quán)限磁滚,所以這個(gè)角色也提供間接對(duì)超級(jí)用戶(root)的訪問(wèn)權(quán)限佛吓,如果限定在admin數(shù)據(jù)中,也包括集群管理的權(quán)限垂攘。

集群管理角色(Cluster Administration Roles)

此類角色僅在mongo運(yùn)行在集群模式(包含但不限于replica set或者sharded cluster)時(shí)使用维雇,只有admin數(shù)據(jù)庫(kù)中含有這些角色:

  • clusterManager:包含對(duì)集群監(jiān)控和管理操作的權(quán)限。擁有此角色的用戶能夠訪問(wèn)集群中的config數(shù)據(jù)庫(kù)和local數(shù)據(jù)庫(kù)(集群模式為sharding或者replication)晒他。
  • clusterMonitor:clusterMonitor角色包含針對(duì)監(jiān)控工具具有只讀操作的權(quán)限吱型。如MongoDB Cloud Manager和Ops Manager。
  • hostManager:hostManager角色包含針對(duì)數(shù)據(jù)庫(kù)服務(wù)器的監(jiān)控和管理操作權(quán)限陨仅。
  • clusterAdmin:clusterAdmin角色包含MongoDB集群管理最高的操作權(quán)限唁影。該角色包含clusterManager耕陷、clusterMonitor和hostManager三個(gè)角色的所有權(quán)限,并且還擁有dropDatabase操作命令的權(quán)限据沈。

備份和恢復(fù)角色(Backup and Restoration Roles)

  • backup:包含備份MongoDB數(shù)據(jù)最小的權(quán)限哟沫。
  • restore:包含從備份文件中還原恢復(fù)MongoDB數(shù)據(jù)(除了system.profile集合)的權(quán)限。

全數(shù)據(jù)庫(kù)級(jí)角色(All-Database Roles)

以下角色只存在于admin數(shù)據(jù)庫(kù)锌介,全局級(jí)別嗜诀,并且適用于除了configlocal之外所有的數(shù)據(jù)庫(kù)。

  • readAnyDatabase:包含對(duì)所有數(shù)據(jù)庫(kù)的只讀權(quán)限孔祸。同時(shí)對(duì)于整個(gè)集群包含listDatabases命令操作隆敢。
  • readWriteAnyDatabase:包含對(duì)所有數(shù)據(jù)庫(kù)的讀寫權(quán)限。同時(shí)對(duì)于整個(gè)集群包含listDatabases命令操作崔慧。
  • userAdminAnyDatabase:包含類似于userAdmin角色對(duì)于所有數(shù)據(jù)庫(kù)的用戶管理權(quán)限拂蝎。
  • dbAdminAnyDatabase:包含類似于dbAdmin角色對(duì)于所有數(shù)據(jù)庫(kù)管理權(quán)限。

超級(jí)用戶角色(Superuser Roles)

  • root:包含角色readWriteAnyDatabase惶室、dbAdminAnyDatabase温自、userAdminAnyDatabase、clusterAdmin皇钞、restore和backup聯(lián)合之后所有的權(quán)限悼泌。

內(nèi)部角色(Internal Role)

  • __system:MongoDB將此角色授予代表集群成員的用戶對(duì)象,如副本集(replica set)成員或mongos實(shí)例夹界。該角色允許用戶對(duì)于需要的數(shù)據(jù)庫(kù)操作都具有相應(yīng)的權(quán)限馆里,不要將該角色授予應(yīng)用程序用戶或其它管理員用戶。

創(chuàng)建自定義角色

雖然MongoDB提供了一系列內(nèi)置角色可柿,但有時(shí)內(nèi)置角色所包含的權(quán)限并不滿足所有需求鸠踪,所以MongoDB也提供了創(chuàng)建自定義角色的方法。當(dāng)創(chuàng)建一個(gè)自定義角色時(shí)需要進(jìn)入指定數(shù)據(jù)庫(kù)進(jìn)行操作复斥,因?yàn)镸ongoDB通過(guò)數(shù)據(jù)庫(kù)和角色名稱對(duì)角色進(jìn)行唯一標(biāo)識(shí)营密。

除了在admin數(shù)據(jù)庫(kù)中創(chuàng)建的角色之外,在其它數(shù)據(jù)庫(kù)中創(chuàng)建的自定義角色包含的權(quán)限只適用于角色所在的數(shù)據(jù)庫(kù)永票,并且只能繼承同數(shù)據(jù)庫(kù)其它角色的權(quán)限。在admin數(shù)據(jù)庫(kù)中創(chuàng)建的自定義角色則不受此限制滥沫。

MongoDB將所有的角色信息存儲(chǔ)在admin數(shù)據(jù)庫(kù)的system.roles集合中侣集,不建議直接訪問(wèn)此集合內(nèi)容,而是通過(guò)角色管理命令來(lái)查看和編輯自定義角色兰绣。

使用下面的命令可創(chuàng)建自定義角色:

db.createRole({
    "role" : "role1",
    "db" : "test",
    "isBuiltin" : true,
    "roles" : [ ],
    "inheritedRoles" : [ ],
    "privileges" : [
        {
            "resource" : {
                "db" : "bocsh",
                "collection" : ""
            },
            "actions" : [
                "changeStream",
                "collStats",
                "convertToCapped",
                "createCollection",
                "createIndex",
                "dbHash",
                "dbStats",
                "dropCollection",
                "dropIndex",
                "emptycapped",
                "find",
                "insert",
                "killCursors",
                "listCollections",
                "listIndexes",
                "planCacheRead",
                "remove",
                "renameCollectionSameDB",
                "update"
            ]
        }
    ]
})

上述命令在test這個(gè)db中創(chuàng)建了一個(gè)名為role1的角色世分,這個(gè)角色能進(jìn)行的操作在action中進(jìn)行了定義(可以創(chuàng)建集合,新增缀辩、修改文檔等)臭埋,可以根據(jù)自身的實(shí)際需要靈活定義踪央。

實(shí)際操作

添加用戶

mongo默認(rèn)是沒(méi)有用戶的,首先我們先來(lái)添加一些用戶用于測(cè)試權(quán)限:

1瓢阴、添加一個(gè)root用戶用于全局管理:

db.createUser(
   {
     user: "root",
     pwd: "password",     
     roles: [{"role":"root","db":"admin"}]
   }
)

2畅蹂、添加一個(gè)writer用戶用于操作bocsh數(shù)據(jù)庫(kù)(也可以在認(rèn)證開(kāi)啟后使用root用戶創(chuàng)建),這里我們創(chuàng)建readWrite類型的角色:

db.createUser(
   {
     user: "writer",
     pwd: "password",
     roles: [{"role":"readWrite","db":"bocsh"}]
   }
)

啟用認(rèn)證

首先要開(kāi)啟mongo的用戶認(rèn)證功能荣恐,可以通過(guò)如下方式啟用:

1液斜、在mongod啟動(dòng)命令中添加--auth,例如:

./mongod --dbpath /data/db/ --auth

2叠穆、在配置文件中啟用安全認(rèn)證:

security:
  authorization: enabled

3少漆、docker中啟用認(rèn)證:

docker run --name=mongo mongo:4.0.18 --auth

k8s中也是類似,在args字段中加入啟動(dòng)參數(shù)即可
關(guān)于docker的cmd和kubernetes的args參數(shù)說(shuō)明硼被,請(qǐng)參考k8s中的command和docker的entrypoint區(qū)別

啟動(dòng)數(shù)據(jù)庫(kù)以后示损,可以驗(yàn)證一下,執(zhí)行mongo命令連接數(shù)據(jù)庫(kù):

$ mongo
MongoDB shell version v4.2.3
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("9e273833-874e-48fa-a0e6-417ac78d041f") }
MongoDB server version: 4.2.3
> use bocsh
switched to db bocsh
> db.user.find({})
Error: error: {
    "ok" : 0,
    "errmsg" : "command find requires authentication",
    "code" : 13,
    "codeName" : "Unauthorized"
}
> 

可以看到嚷硫,因?yàn)闆](méi)有權(quán)限(匿名用戶)检访,所以mongo直接返回了Unauthorized

權(quán)限驗(yàn)證

使用我們剛才創(chuàng)建的writer用戶登陸數(shù)據(jù)庫(kù)

$ mongo -u "writer" --authenticationDatabase "bocsh"
MongoDB shell version v4.2.3
Enter password: 
connecting to: mongodb://127.0.0.1:27017/?authSource=bocsh&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("b4c6e5b0-6062-4d81-a621-a8340cb9d004") }
MongoDB server version: 4.2.3
> show dbs
bocsh  0.002GB
> use bocsh
switched to db bocsh
> db.user.find({})
{ "_id" : ObjectId("5e4965d207d7692d8f29bfca"), "name" : "張三", "age" : 30, "sexy" : "male" }
{ "_id" : ObjectId("5e496600a3ae9e2e0c4f3331"), "name" : "李四", "age" : 32, "sexy" : "male" }

可以看到能夠正常查詢到bocsh數(shù)據(jù)庫(kù)中的數(shù)據(jù),執(zhí)行show dbs也只能看到bocsh這一個(gè)數(shù)據(jù)庫(kù)论巍,讓我們來(lái)實(shí)驗(yàn)一下使用這個(gè)用戶來(lái)創(chuàng)建一個(gè)包含read角色的用戶:

> db.createUser(
...    {
...      user: "reader",
...      pwd: "password",
...      roles: [{"role":"read","db":"bocsh"}],
...     
...    }
... )
2020-05-23T13:21:22.917+0800 E  QUERY    [js] uncaught exception: Error: couldn't add user: not authorized on bocsh to execute command { createUser: "reader", pwd: "xxx", roles: [ { role: "read", db: "bocsh" } ], digestPassword: true, writeConcern: { w: "majority", wtimeout: 600000.0 }, lsid: { id: UUID("b2c99a8f-0abf-4a3b-8336-ac09cef977c3") }, $db: "bocsh" } :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype.createUser@src/mongo/shell/db.js:1370:11
@(shell):1:1

可以看到報(bào)錯(cuò)權(quán)限不足烛谊,因?yàn)閳?zhí)行這個(gè)操作需要userAdmin角色中包含的權(quán)限,而writer用戶并沒(méi)有這個(gè)角色嘉汰,這是符合預(yù)期的丹禀。

接下來(lái)我們給writer用戶賦予userAdmin角色(使用之前創(chuàng)建的root用戶):

db.getSiblingDB("bocsh").updateUser(
    "writer",
    {
        customData: {},
        roles: [{ "role": "readWrite", "db": "bocsh" },
               { "role": "userAdmin", "db": "bocsh" }],
    }
)

writer用戶再次執(zhí)行添加用戶操作:

> db.createUser(
... ...    {
... ...      user: "reader",
... ...      pwd: "password",
... ...      roles: [{"role":"read","db":"bocsh"}],
... ...     
... ...    }
... ... )
Successfully added user: {
    "user" : "reader",
    "roles" : [
        {
            "role" : "read",
            "db" : "bocsh"
        }
    ]
}

試驗(yàn)成功!

參考資料

https://www.cnblogs.com/dbabd/p/10811523.html
https://docs.mongodb.com/manual/reference/built-in-roles/#database-user-roles

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鞋怀,一起剝皮案震驚了整個(gè)濱河市双泪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌密似,老刑警劉巖焙矛,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異残腌,居然都是意外死亡村斟,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門抛猫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蟆盹,“玉大人,你說(shuō)我怎么就攤上這事闺金∮饫模” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵败匹,是天一觀的道長(zhǎng)寨昙。 經(jīng)常有香客問(wèn)我讥巡,道長(zhǎng),這世上最難降的妖魔是什么舔哪? 我笑而不...
    開(kāi)封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任欢顷,我火速辦了婚禮,結(jié)果婚禮上尸红,老公的妹妹穿的比我還像新娘吱涉。我一直安慰自己,他們只是感情好外里,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布怎爵。 她就那樣靜靜地躺著,像睡著了一般盅蝗。 火紅的嫁衣襯著肌膚如雪鳖链。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天墩莫,我揣著相機(jī)與錄音芙委,去河邊找鬼。 笑死狂秦,一個(gè)胖子當(dāng)著我的面吹牛灌侣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播裂问,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼侧啼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了堪簿?” 一聲冷哼從身側(cè)響起痊乾,我...
    開(kāi)封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎椭更,沒(méi)想到半個(gè)月后哪审,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡虑瀑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年湿滓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舌狗。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叽奥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出把夸,到底是詐尸還是另有隱情而线,我是刑警寧澤铭污,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布恋日,位于F島的核電站膀篮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏岂膳。R本人自食惡果不足惜誓竿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谈截。 院中可真熱鬧筷屡,春花似錦、人聲如沸簸喂。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)喻鳄。三九已至扼倘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間除呵,已是汗流浹背再菊。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留颜曾,地道東北人纠拔。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像泛豪,于是被迫代替她去往敵國(guó)和親稠诲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360