1. 安全認證概述
MongoDB 預設是沒有賬号的,可以直接連接配接,無須身份驗證。實際項目中肯定是要權限驗證的,否則 後果不堪設想。是以對MongoDB進行安全認證 是必須要做的。
為了能保障mongodb的安全可以做以下幾個步驟:
1、使用新的端口,預設的27017端口如果一旦知道了ip就能連接配接上,不太安全
2、設定mongodb的網絡環境,最好将mongodb部署到公司伺服器内網,這樣外網是通路不到的。公司内部通路使用vpn等
3、開啟安全認證。認證要同時設定伺服器之間的内部認證方式,同時要設定用戶端連接配接到叢集的賬号密碼認證方式
環境準備
最簡單的叢集是3*3,即三個分片和三個副本集,可以保證高可用,即使一台機器全當機了,服務仍然能夠正常通路。
2. 使用者相關操作
2.1 切換到admin資料庫對使用者的添加
use admin;
db.createUser(userDocument):用于建立 MongoDB 登入使用者以及配置設定權限的方法
db.createUser(
{
user: "賬号",
pwd: "密碼",
roles: [
{ role: "角色", db: "安全認證的資料庫" },
{ role: "角色", db: "安全認證的資料庫" }
]
}
)
- user:建立的使用者名稱,如 admin、root 、lagou
- pwd:使用者登入的密碼
- roles:為使用者配置設定的角色,不同的角色擁有不同的權限,參數是數組,可以同時設定多個
- role:角色,MonngoDB 已經約定好的角色,不同的角色對應不同的權限
- db:資料庫執行個體名稱,如 MongoDB 4.0.2 預設自帶的有 admin、local、config、test 等,即為哪個資料庫執行個體設定使用者
db.createUser({
user:"root",
pwd:"123456",
roles:[{role:"root",db:"admin"}]
})
2.2 修改密碼
db.changeUserPassword( 'rootNew' );
2.3 使用者添加角色
db.grantRolesToUser( '使用者名' , [{ role: '角色名' , db: '資料庫名'}])
2.4 以auth方式啟動mongod
./bin/mongod -f conf/mongo.conf --auth
(也可以在mongo.conf 中添加auth=true 參數)
2.5 驗證使用者
db.auth("賬号","密碼")
2.6 删除使用者
db.dropUser("使用者名")
3. 角色
3.1 資料庫内置的角色
read:允許使用者讀取指定資料庫
readWrite:允許使用者讀寫指定資料庫
dbAdmin:允許使用者在指定資料庫中執行管理函數,如索引建立、删除,檢視統計或通路 system.profile
userAdmin:允許使用者向system.users集合寫入,可以找指定資料庫裡建立、删除和管理使用者
clusterAdmin:隻在admin資料庫中可用,賦予使用者所有分片和複制集相關函數的管理權限
readAnyDatabase:隻在admin資料庫中可用,賦予使用者所有資料庫的讀權限
readWriteAnyDatabase:隻在admin資料庫中可用,賦予使用者所有資料庫的讀寫權限
userAdminAnyDatabase:隻在admin資料庫中可用,賦予使用者所有資料庫的userAdmin權限
dbAdminAnyDatabase:隻在admin資料庫中可用,賦予使用者所有資料庫的dbAdmin權限
root:隻在admin資料庫中可用。超級賬号,超級權限
dbOwner:庫擁有者權限,即readWrite、dbAdmin、userAdmin角色的合體
3.2 各個類型使用者對應的角色
資料庫使用者角色:read、readWrite
資料庫管理角色:dbAdmin、dbOwner、userAdmin
叢集管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager
備份恢複角色:backup、restore;
所有資料庫角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
超級使用者角色:root
這裡還有幾個角色間接或直接提供了系統超級使用者的通路(dbOwner 、userAdmin、 userAdminAnyDatabase)
4. 單機安全認證實作流程
建立 mydb1 資料庫并建立了兩個使用者,zhangsan 擁有讀寫權限,lisi 擁有隻讀權限測試這兩個賬戶的權限。
以超級管理者登入測試權限。
4.1 建立管理者
MongoDB 服務端開啟安全檢查之前,至少需要有一個管理者賬号,admin 資料庫中的使用者都被視為管理者
如果 admin 庫沒有任何使用者的話,即使在其他資料庫中建立了使用者,啟用身份驗證,預設的連接配接方式依然會有超級權限,即仍然可以不驗證賬号密碼照樣能進行 CRUD,安全認證相當于無效。
shard1:PRIMARY> use admin
switched to db admin
shard1:PRIMARY> db.createUser({
... user:"root",
... pwd:"123456",
... roles:[{role:"root",db:"admin"}]
... })
Successfully added user: {
"user" : "root",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
shard1:PRIMARY>
4.2 建立普通使用者
如下所示 rpp_resume 是自己建立的資料庫,沒安全認證之前可以随意 CRUD,其餘的都是 mongoDB4.0.2 自帶的資料庫
shard1:PRIMARY> show dbs
admin 0.000GB
config 0.001GB
local 0.001GB
rpp_resume 0.000GB
- 為 admin 庫建立管理者之後,現在來為普通資料庫建立普通使用者,以 rpp_resume 為例,方式與建立管理者一緻,切換到指定資料庫進行建立即可。
- 如下所示,為 rpp_resume 資料庫建立了兩個使用者,zhangsan 擁有讀寫權限,lisi 擁有隻讀權限,密碼 都是 123456.
shard1:PRIMARY> show dbs
admin 0.000GB
config 0.001GB
local 0.001GB
rpp_resume 0.000GB
shard1:PRIMARY> use rpp_resume
switched to db rpp_resume
shard1:PRIMARY> db
rpp_resume
shard1:PRIMARY> db.createUser({
... user:"zhangsan",
... pwd:"123456",
... roles:[{role:"readWrite",db:"rpp_resume"}]
... })
Successfully added user: {
"user" : "zhangsan",
"roles" : [
{
"role" : "readWrite",
"db" : "rpp_resume"
}
]
}
shard1:PRIMARY> db.createUser({
... user:"lisi",
... pwd:"123456",
... roles:[{role:"read",db:"rpp_resume"}]
... })
Successfully added user: {
"user" : "lisi",
"roles" : [
{
"role" : "read",
"db" : "rpp_resume"
}
]
}
shard1:PRIMARY>
接着從用戶端關閉 MongoDB 服務端,之後以安全認證方式進行啟動
> use admin
switched to db admin
> db.shutdownServer()
> server should be down...
4.3 MongoDB 安全認證方式啟動
./bin/mongod -f conf/mongo.conf --auth
(也可以在mongo.conf 中添加auth=true 參數)
4.4 以普通使用者登入驗證權限
普通使用者現在仍然像以前一樣進行登入,如下所示直接登入進入 rpp_resume 資料庫中,登入是成功的,隻是登入後日志少了很多東西,而且執行 show dbs 指令,以及 show tables 等指令都是失敗的,即使沒有被安全認證的資料庫,使用者同樣操作不了,這都是因為權限不足,一句話:使用者隻能在自己權限範圍 内的資料庫中進行操作
[root@rpp mongodb]# ./bin/mongo localhost:37017/rpp_resume
MongoDB shell version v4.2.9
connecting to: mongodb://localhost:37017/rpp_resume?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("2450aa2a-b830-40fb-a568-9b22d205bb3e") }
MongoDB server version: 4.2.9
shard1:SECONDARY> show dbs
如下所示,登入之後必須使用 db.auth(“賬号”,“密碼”) 方法進行安全認證,認證通過,才能進行權限範圍内的操作
shard1:SECONDARY> db.auth("zhangsan","123456")
1
shard1:SECONDARY> show dbs
2020-10-11T12:13:30.423+0800 E QUERY [js] uncaught exception: Error: listDatabases failed:{
"operationTime" : Timestamp(1602389608, 1),
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk",
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("000000000000000000000000")
},
"lastCommittedOpTime" : Timestamp(1602389608, 1),
"$configServerState" : {
"opTime" : {
"ts" : Timestamp(1602389597, 2),
"t" : NumberLong(1)
}
},
"$clusterTime" : {
"clusterTime" : Timestamp(1602389608, 1),
"signature" : {
"hash" : BinData(0,"MxDcKpZdPP+t62G0PiLfmgaSJMk="),
"keyId" : NumberLong("6881926690809839647")
}
}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:135:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:87:12
shellHelper.show@src/mongo/shell/utils.js:906:13
shellHelper@src/mongo/shell/utils.js:790:15
@(shellhelp2):1:1
shard1:SECONDARY> rs.slaveOk()
shard1:SECONDARY> show dbs
rpp_resume 0.000GB
shard1:SECONDARY>
4.5 以管理者登入驗證權限
用戶端管理者登入如下所示,管理者 root 登入,安全認證通過後,擁有對所有資料庫的所有權限。
[root@rpp mongodb]# ./bin/mongo localhost:37017
MongoDB shell version v4.2.9
connecting to: mongodb://localhost:37017/test?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("7d54c6fa-bb32-450e-874e-03af43ffc375") }
MongoDB server version: 4.2.9
shard1:SECONDARY> use admin
switched to db admin
shard1:SECONDARY> db.auth("root","123456")
1
shard1:SECONDARY> show dbs
admin 0.000GB
config 0.001GB
local 0.001GB
rpp_resume 0.000GB
5. 分片叢集安全認證
5.1 開啟安全認證之前進入路由建立管理者和普通使用者
參考上面的單機安全認證實作流程
5.2 關閉所有的配置節點 分片節點 和 路由節點
安裝psmisc
yum install psmisc
安裝完之後可以使用killall 指令 快速關閉多個程序
killall mongod
5.3 生成密鑰檔案 并修改權限
openssl rand -base64 756 > /data/mongodb/testKeyFile.file
chmod 600 /data/mongodb/testKeyFile.file
5.4 配置節點叢集和分片節點叢集開啟安全認證和指定密鑰檔案
auth=true
keyFile=/data/mongodb/testKeyFile.file
5.5 在路由配置檔案中 設定密鑰檔案
keyFile=data/mongodb/testKeyFile.file
5.6 啟動所有的配置節點 分片節點 和 路由節點 使用路由進行權限驗證
可以編寫一個shell 腳本 批量啟動
./bin/mongod -f config/config-17017.conf
./bin/mongod -f config/config-17018.conf
./bin/mongod -f config/config-17019.conf
./bin/mongod -f shard/shard1/shard1-37017.conf
./bin/mongod -f shard/shard1/shard1-37018.conf
./bin/mongod -f shard/shard1/shard1-37019.conf
./bin/mongod -f shard/shard2/shard2-47017.conf
./bin/mongod -f shard/shard2/shard2-47018.conf
./bin/mongod -f shard/shard2/shard2-47019.conf
./bin/mongos -f route/route-27017.conf
5.7 Spring boot 連接配接安全認證的分片叢集
spring.data.mongodb.username=賬号
spring.data.mongodb.password=密碼
spring.data.mongodb.uri=mongodb://賬号:密碼@IP:端口/資料庫名