MongoDB 內的登入需要輸入 使用者(user)
帳號密碼,而每個 使用者
都有其對應的角色(身份),我們稱為 Role
。在建立使用者的當下,必須指定他的角色,因此會先介紹如何建立 Role。
可以使用其他方法,但我習慣用 docker-compose 啟動,環境乾淨的且..我有設定快捷鍵XD
docker-compose.yml
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
最完整的當然還是參閱官方文章 Built-In Roles,要注意的是內建的角色都會在每一個資料庫中存在。
以下為常用的角色:
所有 DB 操作的角色:
最高等級角色:
一般來說 dbAdmin 以上的權限就應該不常使用到了,理論上不會時常新增這麼大權限的角色給 user,通常 DBA 也會用更高的權限。
那除了上述的內建角色,我們也能夠自己定義角色的權限,最小可以到 Collection
的粒度。
use admin
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
,的角色find, update, insert
testCollection
進行 remove
roles
的意思是,繼承 admin 資料庫中的 read 權限use admin
db.auth("root", "pass.123")
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 }
})
db.createUser(
{
user:"test1",
pwd:"pass.123",
roles:["test_role"]
});
Successfully added user: { "user" : "test1", "roles" : [ "test_role" ] }
mongo --host localhost --port 27117 -u test1 -p pass.123
分別在
a
b
> use testdb
switched to db testdb
> db.testCollection.insert({"field":"a"})
WriteResult({ "nInserted" : 1 })
> db.noRemoveCollection.insert({"field":"b"})
WriteResult({ "nInserted" : 1 })
>
先進行查詢測試
> db.testCollection.find()
{ "_id" : ObjectId("60e82a0a810f8c0cd303cf61"), "field" : "a" }
> db.noRemoveCollection.find()
{ "_id" : ObjectId("60e82a35810f8c0cd303cf62"), "field" : "b" }
>
都符合我們預期結果,接著試試看刪除,僅有 testCollection
能夠被刪除。
> 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,有人還是堅持能夠不輸入帳號密碼也能連線,於是當時我試了一下,先不使用帳號密碼連線看看
# mongo --host localhost --port 27117
MongoDB shell version v4.2.7
connecting to: mongodb://localhost:27117/?compressors=disabled&gssapiServiceName=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
> show dbs
>
得到一片空白,那我們再看看有哪些 user
> 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
本系列文章會同步發表於我個人的部落格 Pie Note