MongoDB--安全認證

MongoDB的用戶和角色權限簡介

默認狀況下,MongoDB實例啓動運行時是沒有啓用用戶訪問權限控制的,也就是說,在實例本機服務器上均可以隨意鏈接到實例進行各類操做,MongoDB不會對鏈接客戶端進行用戶驗證。mongodb

爲了強制開啓用戶訪問控制(用戶驗證),則須要在MongoDB實例啓動時使用選項--auth或在指定啓動配置文件中添加auth=trueshell

  • 啓用訪問控制:MongoDB使用的是基於角色的訪問控制(Role-Based Access Control,RBAC)來管理用戶對實例的訪問。經過對用戶授予一個或多個角色來控制用戶訪問數據庫資源的權限和數據庫操做的權限,在對用戶分配角色以前,用戶沒法訪問實例。
  • 角色:在MongoDB中經過角色對用戶授予相應數據庫資源的操做權限,每一個角色當中的權限能夠顯示指定,也能夠經過集成其餘角色的權限,或者二者都存在的權限。
  • 權限:權限由指定的數據庫(resource)以及容許在運行資源上進行的操做(action)組成。
    • 資源(resource)包括:數據庫、集合、部分集合和集羣;
    • 操做(action)包括:對資源的增、刪、改、查(CRUD)操做。

在角色定義時能夠包含一個或多個已存在的角色,新建立的角色會繼承包含的角色全部的權限。在同一個數據庫中,新建立角色能夠繼承其餘角色的權限,在admin數據庫中建立的角色能夠繼承在其它任意數據庫中的角色的權限。數據庫

角色權限的查看,能夠經過以下的命令進行查看:vim

# 查詢全部角色權限(僅用戶自定義角色) 
> db.runCommand({ rolesInfo: 1 })

# 查詢全部角色權限(包含內置角色)
> db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })

# 查詢當前數據庫中的某角色的權限 
> db.runCommand({ rolesInfo: "<rolename>" })

# 查詢其它數據庫中指定的角色權限
> db.runCommand({ rolesInfo: { role: "<rolename>", db: "<database>" } }

# 查詢多個角色權限
> db.runCommand({ 
	rolesInfo: [ 
		"<rolename>", { role: "<rolename>", db: "<database>" },
		...
	] 
})

示例:api

查看全部內置角色:安全

> db.runCommand({rolesInfo:1, showBuiltinRoles:true})
{
	"roles" : [
		{
			"role" : "__queryableBackup",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "__system",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "backup",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "clusterAdmin",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "clusterManager",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "clusterMonitor",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "dbAdmin",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "dbAdminAnyDatabase",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "dbOwner",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "enableSharding",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "hostManager",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "read",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "readAnyDatabase",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "readWrite",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "readWriteAnyDatabase",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "restore",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "root",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "userAdmin",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		}
	],
	"ok" : 1
}

 

常見的內置角色

  • 數據庫用戶角色:readreadWrite
  • 數據庫管理角色:dbAdmindbOwneruserAdmin
  • 集羣管理角色:clusterAdminclusterManagerclusterMonitor
  • 全部數據庫用戶角色:readAnyDatabasereadWriteAnyDatabaseuserAdminAnyDatabasedbAdminAnyDatabase
  • 備份恢復角色:backuprestore
  • 超級用戶角色:root
  • 內部角色:system

📝 角色說明:bash

角色 權限描述
read 能夠讀取指定數據庫中任何數據。
readWrite 能夠讀寫指定數據庫中任何數據,包括建立、重命名、刪除集合
readAnyDatabase 能夠讀取全部數據庫中任何數據(除了數據庫configlocal以外)
readWriteAnyDatabase 能夠讀寫全部數據庫中任何數據(除了數據庫configlocal以外)
userAdminAnyDatabase 能夠在指定數據庫建立和修改用戶(除了數據庫configlocal以外)
dbAdminAnyDatabase 能夠讀取任何數據庫以及對數據庫進行清理、修改、壓縮、獲取統計信息、執行檢查等操做(除了數據庫configlocal以外)
dbAdmin 能夠讀取指定數據庫以及對數據庫進行清理、修改、壓縮、獲取統計信息、執行檢查等操做
userAdmin 能夠在指定數據庫建立和修改用戶
clusterAdmin 能夠對整個集羣或數據庫系統進行管理操做
backup 備份MongoDB數據最小的權限
restore 從備份文件中還原恢復MongoDB數據(除了system.profile集合)的權限
root 超級帳戶,超級權限

 

單實例環境

建立用戶

✏️ 建立用戶格式以下:服務器

db.createUser({
	user:"<name>",
	pwd:"<password>",
	customData:{<any Object Data},
	roles:[
		{role:"<role>",db:"database"},
		...
	]
})

備註:
1)user:新建用戶名
2)pwd:新建用戶密碼
3)customData:存放一些用戶相關的自定義數據,可忽略
4)roles:數據類型,配置用戶的權限

示例:建立一個管理員帳戶session

# mongo --host=10.10.10.11 --port=27017
> show dbs;
admin       0.000GB
collectest  0.000GB
config      0.000GB
local       0.000GB
> 
> use admin
switched to db admin
> 
> db.createUser({"user":"root","pwd":"123456","roles":[{"role":"root","db":"admin"}]});
Successfully added user: {
	"user" : "root",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}

✏️ 查看用戶app

# 方法一
> use admin;
switched to db admin
> 
> show users;
{
	"_id" : "admin.root",
	"userId" : UUID("d7280144-2886-45eb-95f3-1965be4eb7fe"),
	"user" : "root",
	"db" : "admin",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}

# 方法二
> use admin;
switched to db admin
> 
> show tables;
system.users
system.version
> 
> db.system.users.find()
{ "_id" : "admin.root", "userId" : UUID("d7280144-2886-45eb-95f3-1965be4eb7fe"), "user" : "root", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "u2nQBHuC2P367Qo5mLhcRw==", "storedKey" : "0ccLsqhpWUyCdAoQKZQNNHwvj9g=", "serverKey" : "9Qxfsw+GCQMwUuyz9AlKRAX6zx0=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "rxajlRAv8zteEMm6r2Wx8GFY1ShBeLjHUqJ7iA==", "storedKey" : "T9z/0GJ21cxJ4CvnNL+PBGkTYwdPu9YxmRo1CQ2tGp0=", "serverKey" : "UBVuzHOxfKADUdpxIhRBab2HwPdLhNL2yUZzyTXFRt0=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ]

 

服務端開啓認證

✏️ 修改配置文件

# vim /usr/local/mongodb/conf/mongodb.conf
dbpath=/usr/local/mongodb/data
logpath=/usr/local/mongodb/log/mongodb.log
bind_ip=0.0.0.0
port=27017
logappend=1
fork=1
auth=true    #開啓認證

✏️ 重啓服務

# ps -ef |grep mongod
root       6991      1  0 19:46 ?        00:00:10 mongod -f /usr/local/mongodb/conf/mongodb.conf
root       7438   6395  0 20:14 pts/1    00:00:00 grep --color=auto mongod
# kill -2 6991 
# 
# mongod -f /usr/local/mongodb/conf/mongodb.conf

✏️ 登錄測試

# mongo --host=10.10.10.11 --port=27017
MongoDB shell version v4.4.1
connecting to: mongodb://10.10.10.11:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("cb337048-a9c8-45ae-99aa-b0cb8cc7a163") }
MongoDB server version: 4.4.1
> show dbs   #查看
> 
> use admin   #切換到admin庫
switched to db admin
> db.auth("root","123456")	#進行認證
1
> show dbs;
admin       0.000GB
collectest  0.000GB
config      0.000GB
local       0.000GB

✏️ 添加一個普通用戶

建立普通用戶能夠在沒有開啓認證的時候添加,也能夠在開啓認證以後添加,但開啓認證以後,必須使用有操做admin庫的用戶登陸認證後才能操做。底層是將用戶信息保存在了admin數據庫的集合system.users中。

# 建立(切換)未來要操做的數據庫articledb
> use articledb
switched to db articledb
> 
> db.createUser({user:"user1",pwd:"1234",roles:[{role:"readWrite",db:"articledb"}]})
Successfully added user: {
	"user" : "user1",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "articledb"
		}
	]
}
# 測試是否可用
> db.auth("user1","1234")
1

 

客戶端登陸認證

✏️ 方法1

先鏈接,在認證

# mongo --host 10.10.10.11 --port 27017
MongoDB shell version v4.4.1
connecting to: mongodb://10.10.10.11:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("4efbbc03-31b7-45ff-8b3a-5ce6f76ff1ca") }
MongoDB server version: 4.4.1
> use admin
switched to db admin
> db.auth("root","123456")
1
> show dbs
admin       0.000GB
collectest  0.000GB
config      0.000GB
local       0.000GB

✏️ 方法2

鏈接時進行認證

# mongo --host 10.10.10.11 --port 27017 --authenticationDatabase admin -u root -p 123456
MongoDB shell version v4.4.1
connecting to: mongodb://10.10.10.11:27017/?authSource=admin&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("0848b5d0-fb56-40eb-9b37-542682fd6ada") }
MongoDB server version: 4.4.1
......
> 
> show dbs
admin       0.000GB
collectest  0.000GB
config      0.000GB
local       0.000GB

參數說明:

  • --host:鏈接的主機地址
  • --port:鏈接的端口
  • --authenticationDatabase:指定鏈接到哪一個庫。當登陸是指定用戶密碼時,必須指定對應的數據庫!
  • -u:用戶名
  • -p:密碼

 

副本集環境

對於搭建好的mongodb副本集,爲了安全,啓動安全認證,使用帳戶密碼登陸。

對副本集執行訪問控制須要配置兩個方面:

1)副本集和共享集羣的各個節點成員之間使用內部身份驗證,可使用祕鑰文件或x.509證書。祕鑰文件比較簡單。

2)使用客戶端鏈接到mongodb集羣時,可開啓訪問受權。對於集羣外部的訪問。如經過可視化客戶端、或者經過代碼鏈接的時候,須要開啓受權。

添加管理帳戶

在主節點添加管理帳戶,副本集會自動同步。

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

備註:

該步驟也能夠在開啓認證以後,但須要經過localhost登陸才容許添加用戶,用戶數據也會自動同步到副本集。後續再建立其餘用戶,都已使用該超管用戶建立。

 

建立副本集認證的key文件

✏️ 生成一個key文件到當前文件夾中。

可使用任何方法生成祕鑰文件,例如,一下使用openssl生成密碼文件,而後使用chmod來更改文件權限,僅爲文件全部這提供讀取權限。

# openssl rand -base64 90 -out ./mongo.keyfile
# chmod 400 ./mongo.keyfile 
# ll mongo.keyfile 
-r--------. 1 root root 122 Nov 17 16:27 mongo.keyfile

備註:

全部副本集節點都必須使用同一份keyfile,通常在一臺機器上生成,而後拷貝到其餘機器上,且必須有讀的權限,不然未來會報錯:permissions on /mongodb/replica_sets/myrs_27017/mongo.keyfile are too open

通常狀況下和配置文件放置在一塊兒,方便查找。這裏都copy到各個節點的配置文件目錄

# cp mongo.keyfile /data/replica_sets/myrs_27017/
# cp mongo.keyfile /data/replica_sets/myrs_27018/
# cp mongo.keyfile /data/replica_sets/myrs_27019/

 

修改配置文件指定keyfile

分別編輯幾個服務的mongod.conf文件,添加相關內容

# vim /data/replica_sets/myrs_27017/mongod.conf
security:
    #keyfile鑑權文件
    keyFile: /data/replica_sets/myrs_27017/mongo.keyfile
    #開啓認證方式運行
    authorization: enabled

# vim /data/replica_sets/myrs_27018/mongod.conf
security:
    #keyfile鑑權文件
    keyFile: /data/replica_sets/myrs_27018/mongo.keyfile
    #開啓認證方式運行
    authorization: enabled

# vim /data/replica_sets/myrs_27019/mongod.conf
security:
    #keyfile鑑權文件
    keyFile: /data/replica_sets/myrs_27019/mongo.keyfile
    #開啓認證方式運行
    authorization: enabled

 

重啓副本集

若是副本集是開啓狀態,則先分別關閉副本集中的每一個mongod,從次節點開始。直到副本集的全部成員都離線,包括任何仲裁者。主節點必須是最後一個成員關閉,以免潛在的回滾。

# ps -ef |grep mongod
root       2649      1  1 11:20 ?        00:04:44 mongod -f /data/replica_sets/myrs_27017/mongod.conf
root       2728      1  1 11:20 ?        00:05:21 mongod -f /data/replica_sets/myrs_27018/mongod.conf
root       4534      1  0 14:13 ?        00:01:07 mongod -f /data/replica_sets/myrs_27019/mongod.conf

# kill -2 2649 4534 2728

分別啓動副本集

# mongod -f /data/replica_sets/myrs_27017/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 6287
child process started successfully, parent exiting
# 
# mongod -f /data/replica_sets/myrs_27018/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 6365
child process started successfully, parent exiting
#
# mongod -f /data/replica_sets/myrs_27019/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 6456
child process started successfully, parent exiting

查看進程狀況

# ps -ef |grep mongo
root       6287      1  3 16:40 ?        00:00:02 mongod -f /data/replica_sets/myrs_27017/mongod.conf
root       6365      1  3 16:41 ?        00:00:02 mongod -f /data/replica_sets/myrs_27018/mongod.conf
root       6456      1  2 16:41 ?        00:00:01 mongod -f /data/replica_sets/myrs_27019/mongod.conf

 

鏈接測試

鏈接主節點測試

✏️ 先鏈接,再認證

# mongo --host 10.10.10.11 --port 27017
MongoDB shell version v4.4.1
connecting to: mongodb://10.10.10.11:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("e1218d07-5094-468d-bdfe-f1d3e3815281") }
MongoDB server version: 4.4.1
myrs:PRIMARY> show dbs
myrs:PRIMARY> db.auth("root","123456")
1
myrs:PRIMARY> show dbs
admin       0.000GB
collectest  0.000GB
config      0.000GB
local       0.001GB
test        0.000GB

✏️ 鏈接時進行認證

# mongo --host 10.10.10.11 --port 27017 --authenticationDatabase admin -u root -p 123456
---
myrs:PRIMARY> show dbs
admin       0.000GB
collectest  0.000GB
config      0.000GB
local       0.001GB
test        0.000GB

鏈接副本節點測試

# mongo --host 10.10.10.11 --port 27018 --authenticationDatabase admin -u root -p 123456
myrs:SECONDARY> show dbs	#查看數據庫,這裏不能查看是由於默認副本節點不能查詢數據,須要開啓查詢權限
uncaught exception: Error: listDatabases failed:{
	"topologyVersion" : {
		"processId" : ObjectId("5fb38ca9ae9c791f8008eb9a"),
		"counter" : NumberLong(4)
	},
	"operationTime" : Timestamp(1605603187, 1),
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1605603187, 1),
		"signature" : {
			"hash" : BinData(0,"hCt+wCrLo2uwZucZsLN0id+Rnh0="),
			"keyId" : NumberLong("6893051287466672133")
		}
	}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12
shellHelper.show@src/mongo/shell/utils.js:937:13
shellHelper@src/mongo/shell/utils.js:819:15
@(shellhelp2):1:1
myrs:SECONDARY> 
myrs:SECONDARY> rs.secondaryOk()	#開啓副本集讀取權限
myrs:SECONDARY> 
myrs:SECONDARY> show dbs	#再次查看
admin       0.000GB
collectest  0.000GB
config      0.000GB
local       0.001GB
test        0.000GB

添加普通用戶

✏️ 添加普通用戶對指定庫有讀寫權限

//鏈接主節點
# mongo --host 10.10.10.11 --port 27017 --authenticationDatabase admin -u root -p 123456
myrs:PRIMARY> use collectest	#切換到collectest庫
switched to db collectest
myrs:PRIMARY> 
myrs:PRIMARY> db.createUser({user:"u_test",pwd:"123",roles:[{role:"readWrite", db:"collectest"}]})	#建立用戶u_test對collectest庫有讀寫權限

Successfully added user: {
	"user" : "u_test",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "collectest"
		}
	]
}
myrs:PRIMARY>

✏️ 使用普通用戶登陸並查詢數據

# mongo --host 10.10.10.11 --port 27017 --authenticationDatabase collectest -u u_test -p 123
...
myrs:PRIMARY> 
myrs:PRIMARY> show dbs
collectest  0.000GB
myrs:PRIMARY> 
myrs:PRIMARY> use collectest
switched to db collectest
myrs:PRIMARY> 
myrs:PRIMARY> show collections
collectest
myrs:PRIMARY> 
myrs:PRIMARY> db.collectest.find()
{ "_id" : ObjectId("5faa3432f6e79c62c00e4d72"), "name" : "張三", "sex" : "男", "age" : 22, "userid" : 1001, "createdatetime" : ISODate("2020-11-10T06:33:22.459Z") }
{ "_id" : ObjectId("5facec10cca53c48154d261c"), "name" : "小白", "sex" : "女", "age" : 20, "userid" : 1002, "createdatetime" : ISODate("2020-11-12T08:02:24.915Z") }
{ "_id" : ObjectId("5facf32dfb5fe16aaf699d7d"), "name" : "小嘿", "sex" : "女", "age" : 21, "userid" : 1002, "createdatetime" : ISODate("2020-11-12T08:32:45.919Z") }
myrs:PRIMARY>

#查詢一個普通用戶沒有權限的庫,則會提示響應警告,並沒有法查當作功。
myrs:PRIMARY> use admin
switched to db admin
myrs:PRIMARY> show collections
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
相關文章
相關標籤/搜索