2021 iThome 鐵人賽 MongoDB披荊斬棘之路
DAY25 MongoDB 自訂角色與使用者 前言 MongoDB 內的登入需要輸入 使用者(user)
帳號密碼,而每個 使用者
都有其對應的角色(身份),我們稱為 Role
。在建立使用者的當下,必須指定他的角色,因此會先介紹如何建立 Role。
事前準備 可以使用其他方法,但我習慣用 docker-compose 啟動,可以使用乾淨的環境且我有設定快捷鍵XD
docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 version: "3.7" services: database: image: mongo container_name: mongodb-test environment: - MONGO_INITDB_ROOT_USERNAME=root - MONGO_INITDB_ROOT_PASSWORD=pass.123 command: mongod --auth ports: - "27117:27017"
我們設定 root 帳密為 root
/ pass.123
,以及啟動認證 mongod --auth
MongoDB 內建的角色 最完整的當然還是參閱官方文章 Built-In Roles ,要注意的是內建的角色都會在每一個 資料庫中存在。
以下為常用的角色:
read: 僅有閱讀權限
readWrite: 擁有修改權限(包含上述權限)
dbAdmin: 擁有 DB 的所有修改權限(包含上述權限),除了 role 的調整
dbOwner: 擁有允許(grant) role 的權限(包含上述權限)
userAdmin: 擁有修改 role 的權限(包含上述權限)
所有 DB 操作的角色:
readAnyDatabase
readWriteAnyDatabase
dbAdminAnyDatabase
userAdminAnyDatabase
最高等級角色:
一般來說 dbAdmin 以上的權限就應該不常使用到了,理論上不會時常新增這麼大權限的角色給 user,通常 DBA 也會用更高的權限。
那除了上述的內建角色,我們也能夠自己定義角色的權限,最小可以到 Collection
的粒度。
建立角色
切換至 admin DB。use admin
建立角色
1 2 3 4 5 6 7 8 9 db.adminCommand ( { createRole : "test_role" , privileges : [ { resource : { db : "testdb" , collection : "" }, actions : [ "find" , "update" , "insert" ] }, { resource : { db : "testdb" , collection : "testCollection" }, actions : [ "remove" ] } ], roles : [ { role : "read" , db : "admin" } ], writeConcern : { w : "majority" , wtimeout : 5000 } })
上面的語法是
在 admin
資料庫中,建立一個名為 test_role
,的角色
該角色可以在全部 Collection 進行 find, update, insert
該角色僅可在 testCollection
進行 remove
roles
的意思是,繼承 admin 資料庫中的 read 權限
實際演練 Step0 1 2 use admin db.auth ("root" , "pass.123" )
Step1 建立 Role 1 2 3 4 5 6 7 8 9 db.adminCommand ( { createRole : "test_role" , privileges : [ { resource : { db : "testdb" , collection : "" }, actions : [ "find" , "update" , "insert" ] }, { resource : { db : "testdb" , collection : "testCollection" }, actions : [ "remove" ] } ], roles : [ { role : "read" , db : "admin" } ], writeConcern : { w : "majority" , wtimeout : 5000 } })
Step2 建立 User 1 2 3 4 5 6 7 8 db.createUser ( { user :"test1" , pwd :"pass.123" , roles :["test_role" ] }); Successfully added user : { "user" : "test1" , "roles" : [ "test_role" ] }
Step3 以 test1 登入測試 mongo --host localhost --port 27117 -u test1 -p pass.123
分別在
testCollection 建立一筆資料,值為 a
noRemoveCollection 建立一筆資料,值為 b
1 2 3 4 5 6 7 8 9 > use testdb switched to db testdb > db.testCollection .insert ({"field" :"a" }) WriteResult ({ "nInserted" : 1 })> db.noRemoveCollection .insert ({"field" :"b" }) WriteResult ({ "nInserted" : 1 })>
先進行查詢測試
1 2 3 4 5 6 > db.testCollection .find ( ) { "_id" : ObjectId ("60e82a0a810f8c0cd303cf61" ), "field" : "a" } > db.noRemoveCollection .find ( ) { "_id" : ObjectId ("60e82a35810f8c0cd303cf62" ), "field" : "b" } >
都符合我們預期結果,接著試試看刪除,僅有 testCollection
能夠被刪除。
1 2 3 4 5 6 7 8 9 10 11 > db.testCollection .remove ({"field" :"a" }) WriteResult ({ "nRemoved" : 1 })> db.noRemoveCollection .remove ({"field" :"b" }) WriteCommandError ({ "ok" : 0 , "errmsg" : "not authorized on testdb to execute command { delete: \"noRemoveCollection\", ordered: true, lsid: { id: UUID(\"d095b383-e647-4429-88a0-0d03335ccab2\") }, $db: \"testdb\" }" , "code" : 13 , "codeName" : "Unauthorized" }) >
可以看到 noRemoveCollection
會因為沒有權限無法進行刪除,符合我們 test_role
的權限設定。
小插曲 之前遇過一個事件,即便設定了 auth,有人還是堅持能夠不輸入帳號密碼也能連線,於是當時我試了一下,先不使用帳號密碼連線看看
1 2 3 4 5 6 # mongo --host localhost --port 27117 MongoDB shell version v4.2 .7 connecting to : mongodb : Implicit session : session { "id" : UUID ("3ab7644a-66eb-452a-8b4e-6f569664cb81" ) }MongoDB server version : 4.4 .4 WARNING : shell and server versions do not match
確實是可以連線 ,我們看看有哪些 database
得到一片空白,那我們再看看有哪些 user
1 2 3 4 5 6 7 8 > show users 2021 -07 -08T00 :45 :42.807 +0800 E QUERY [js] uncaught exception : Error : command usersInfo requires authentication :_getErrorWithCode@src/mongo/shell/utils.js :25 :13 DB .prototype .getUsers @src/mongo/shell/db.js :1638 :15 shellHelper.show @src/mongo/shell/utils.js :883 :9 shellHelper@src/mongo/shell/utils.js :790 :15 @(shellhelp2):1 :1 >
這裡就很明顯告訴你沒有認證。 原來是他老兄以為第一個步驟就能夠連上線使用了XD