相关文章推荐
温文尔雅的圣诞树  ·  DAY25 MongoDB ...·  3 周前    · 
刀枪不入的马铃薯  ·  mongodb "errmsg" : ...·  3 周前    · 
鬼畜的饼干  ·  .NET Core ...·  1 年前    · 
聪明伶俐的肉夹馍  ·  How to fix ...·  1 年前    · 
留胡子的煎饼  ·  R可视乎 | ...·  1 年前    · 
成熟的柳树  ·  Android ...·  1 年前    · 

DAY25 MongoDB 自訂角色與使用者

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

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
    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

    use admin
    db.auth("root", "pass.123")
    

    Step1 建立 Role

    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

    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
    > 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

  •