分散式文件儲存資料庫之MongoDB訪問控制

1874發表於2020-11-14

  上一篇部落格主要聊了下mongodb的分片機制以及分片叢集的搭建,回顧請參考https://www.cnblogs.com/qiuhom-1874/p/13958295.html;今天我們來了解下mongodb的訪問控制;

  什麼是訪問控制?

  簡單講訪問控制就是指,哪些使用者可以訪問哪些資源,對資源有哪些操作(許可權);在mongodb中我們把資料庫、或者集合叫做資源;也就說訪問控制是用來限制某些使用者對資料庫或集合的操作;我們在mysql資料庫中,我們通過給賬號授權的方式達到控制哪些使用者可以從哪些主機訪問資料庫,對資料庫有哪些操作;其中賬號由使用者名稱稱和主機地址構成;在mongodb中採用的不是使用者+主機地址的方式,而是通過給使用者賦予一個或多個角色,這個角色或多個角色的所有許可權就是這個使用者擁有的許可權;預設情況mongodb是沒有啟用訪問控制的,所以只要能夠連線上mongodb例項,我們就可以在其上做任何操作,在某種程度上,這是一種極為不安全的方式,為了杜絕這種不安全的訪問方式,我們需要對mongodb進行訪問控制;

  mongodb中的角色許可權說明

  mongodb預設內建了一些角色,不同的角色擁有不同的許可權,如下圖

  檢視mongodb中某個資料庫所有內建角色

> db.runCommand({rolesInfo:1,showBuiltinRoles:true})
{
        "roles" : [
                {
                        "role" : "dbAdmin",
                        "db" : "test",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "dbOwner",
                        "db" : "test",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "enableSharding",
                        "db" : "test",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "read",
                        "db" : "test",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "readWrite",
                        "db" : "test",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "userAdmin",
                        "db" : "test",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                }
        ],
        "ok" : 1
}
> 

  提示:以上是mongodb中test庫的預設角色;如果要檢視其它庫,我們需要切換到其他庫,然後執行上述命令檢視即可;

  查詢當前資料中的某個角色

> db
test
> db.runCommand({rolesInfo:"userAdmin"})
{
        "roles" : [
                {
                        "role" : "userAdmin",
                        "db" : "test",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                }
        ],
        "ok" : 1
}
> 

  查詢其他資料庫中指定的角色許可權

> db.runCommand({rolesInfo:{role:"userAdmin",db:"config"}})
{
        "roles" : [
                {
                        "role" : "userAdmin",
                        "db" : "config",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                }
        ],
        "ok" : 1
}
> db.runCommand({rolesInfo:{role:"root",db:"config"}})
{ "roles" : [ ], "ok" : 1 }
> db.runCommand({rolesInfo:{role:"root",db:"admin"}})
{
        "roles" : [
                {
                        "role" : "root",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                }
        ],
        "ok" : 1
}
> 

  建立一個使用者名稱為tom,其角色為超級管理員角色root

> use admin
switched to db admin
> db.createUser({user:"tom",pwd:"admin123.com",roles:[{"role":"root","db":"admin"}]})
Successfully added user: {
        "user" : "tom",
        "roles" : [
                {
                        "role" : "root",
                        "db" : "admin"
                }
        ]
}
>

  檢視當前庫使用者列表

> db
admin
> db.getUsers()
[
        {
                "_id" : "admin.tom",
                "userId" : UUID("67bf434a-49fc-4ed5-9e9b-23c443a2fc93"),
                "user" : "tom",
                "db" : "admin",
                "roles" : [
                        {
                                "role" : "root",
                                "db" : "admin"
                        }
                ],
                "mechanisms" : [
                        "SCRAM-SHA-1",
                        "SCRAM-SHA-256"
                ]
        }
]
> 

  建立資料庫管理員使用者

> db.createUser({user:"jerry",pwd:"admin123.com",roles:["userAdminAnyDatabase"]})
Successfully added user: { "user" : "jerry", "roles" : [ "userAdminAnyDatabase" ] }
> db.getUsers()
[
        {
                "_id" : "admin.jerry",
                "userId" : UUID("5d0b77f2-b7f1-40cd-8149-f08b2e1e6a80"),
                "user" : "jerry",
                "db" : "admin",
                "roles" : [
                        {
                                "role" : "userAdminAnyDatabase",
                                "db" : "admin"
                        }
                ],
                "mechanisms" : [
                        "SCRAM-SHA-1",
                        "SCRAM-SHA-256"
                ]
        },
        {
                "_id" : "admin.tom",
                "userId" : UUID("67bf434a-49fc-4ed5-9e9b-23c443a2fc93"),
                "user" : "tom",
                "db" : "admin",
                "roles" : [
                        {
                                "role" : "root",
                                "db" : "admin"
                        }
                ],
                "mechanisms" : [
                        "SCRAM-SHA-1",
                        "SCRAM-SHA-256"
                ]
        }
]
> 

  提示:如果建立使用者時,未指定db,則表示當前該使用者對當前所在db生效;

  刪除使用者

> db.dropUser("jerry")
true
> db.getUsers()
[
        {
                "_id" : "admin.tom",
                "userId" : UUID("67bf434a-49fc-4ed5-9e9b-23c443a2fc93"),
                "user" : "tom",
                "db" : "admin",
                "roles" : [
                        {
                                "role" : "root",
                                "db" : "admin"
                        }
                ],
                "mechanisms" : [
                        "SCRAM-SHA-1",
                        "SCRAM-SHA-256"
                ]
        }
]
> 

  提示:刪除使用者,需切換到對應資料下,指定對應使用者名稱稱即可;在mongodb中使用者是對應資料庫的,一個使用者可以對應一個或多個資料庫,在指定資料庫刪除使用者,就表示刪除指定使用者對指定資料庫的訪問許可權;

  修改指定使用者的密碼

> db
admin
> db.changeUserPassword("tom","123456")
> 

  提示:修改使用者密碼,第一個是指定使用者的名稱,第二個是指定新密碼;

  驗證使用者名稱和密碼

  給錯誤的密碼

> db
admin
> db.auth("tom","admin")
Error: Authentication failed.
0
>

  給正確的密碼

> db
admin
> db.auth("tom","123456")
1
>

  建立一個普通使用者

> use testdb
switched to db testdb
> db.createUser({user:"test",pwd:"admin",roles:[{role:"readWrite",db:"testdb"}]})
Successfully added user: {
        "user" : "test",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "testdb"
                }
        ]
}
> db.getUsers()
[
        {
                "_id" : "testdb.test",
                "userId" : UUID("95ecb34c-46f4-44fa-8948-4f0875499d8e"),
                "user" : "test",
                "db" : "testdb",
                "roles" : [
                        {
                                "role" : "readWrite",
                                "db" : "testdb"
                        }
                ],
                "mechanisms" : [
                        "SCRAM-SHA-1",
                        "SCRAM-SHA-256"
                ]
        }
]
> 

  提示:以上就建立了一個名為test的使用者,它可對testdb這個庫下的所有collection做讀寫操作;

  建立一個多角色的使用者

> db
testdb
> db.createUser(
... {
... user:"jerry1",
... pwd:"admin123.com",
... roles:[
... {role:"clusterAdmin",db:"admin"},
... {role:"readWrite",db:"testdb"},
... {role:"read",db:"testdb1"}
... ]
... })
Successfully added user: {
        "user" : "jerry1",
        "roles" : [
                {
                        "role" : "clusterAdmin",
                        "db" : "admin"
                },
                {
                        "role" : "readWrite",
                        "db" : "testdb"
                },
                {
                        "role" : "read",
                        "db" : "testdb1"
                }
        ]
}
> db.getUsers()
[
        {
                "_id" : "testdb.jerry1",
                "userId" : UUID("43d66bf8-1e3a-4c14-ad73-5961b5a7660f"),
                "user" : "jerry1",
                "db" : "testdb",
                "roles" : [
                        {
                                "role" : "clusterAdmin",
                                "db" : "admin"
                        },
                        {
                                "role" : "readWrite",
                                "db" : "testdb"
                        },
                        {
                                "role" : "read",
                                "db" : "testdb1"
                        }
                ],
                "mechanisms" : [
                        "SCRAM-SHA-1",
                        "SCRAM-SHA-256"
                ]
        },
        {
                "_id" : "testdb.test",
                "userId" : UUID("95ecb34c-46f4-44fa-8948-4f0875499d8e"),
                "user" : "test",
                "db" : "testdb",
                "roles" : [
                        {
                                "role" : "readWrite",
                                "db" : "testdb"
                        }
                ],
                "mechanisms" : [
                        "SCRAM-SHA-1",
                        "SCRAM-SHA-256"
                ]
        }
]
> 

  提示:在mongodb中一個使用者可以授權擁有多個角色許可權;

  開啟mongodb服務端訪問控制配置

  重啟服務

[root@node12 ~]# systemctl restart mongod.service 
[root@node12 ~]# ss -tnl
State      Recv-Q Send-Q         Local Address:Port                        Peer Address:Port              
LISTEN     0      128                        *:22                                     *:*                  
LISTEN     0      100                127.0.0.1:25                                     *:*                  
LISTEN     0      128                        *:27017                                  *:*                  
LISTEN     0      128                       :::22                                    :::*                  
LISTEN     0      100                      ::1:25                                    :::*                  
[root@node12 ~]# 

  測試:現在連線mongodb,看看會發生什麼?

[root@node12 ~]# mongo
MongoDB shell version v4.4.1
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("68fa2f83-64a4-42c2-8d64-9ee73a77e883") }
MongoDB server version: 4.4.1
> show dbs
> db
test
> show tables
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
> 

  提示:現在我們直接連線mongodb是可以正常連線,但是我們沒法檢視資料列表以及collections了;這個時候我們就需要進行使用者認證了;

  認證使用者

> db
test
> db.auth("test","admin")
Error: Authentication failed.
0
> use testdb
switched to db testdb
> db.auth("test","admin")
1
> show dbs
> show collections
> 

  提示:認證使用者必須切換到對應的資料庫下做認證;我這裡test使用者只能對testdb庫下的所有collection進行讀寫,所以認證以後,我們在使用 show dbs命令就看不到系統admin和config庫了;除了上述連線資料庫以後使用db.auth()做使用者認證,我們也可直接在連線資料庫時指定使用者名稱和密碼,如下

[root@node12 ~]# mongo -utest -padmin testdb
MongoDB shell version v4.4.1
connecting to: mongodb://127.0.0.1:27017/testdb?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("60c43e94-04c6-46f4-be07-07ca8fa06b2f") }
MongoDB server version: 4.4.1
> show dbs
> exit
bye
[root@node12 ~]# mongo -utest -padmin 192.168.0.52:27017/testdb
MongoDB shell version v4.4.1
connecting to: mongodb://192.168.0.52:27017/testdb?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("a30dbd64-7b59-4a8e-b95d-02ff30e256f3") }
MongoDB server version: 4.4.1
> show dbs
> show tables
> 

  以上就是在mongodb中開啟訪問控制,建立使用者,授權的操作;我們只需要在配置檔案中指定開啟認證功能,然後使用具有建立使用者許可權的使用者登入資料庫建立使用者授權即可;

相關文章