MongoDB安全认证

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:端口/数据库名
posted @ 2020-11-13 12:00  哈喽哈喽111111  阅读(497)  评论(0编辑  收藏  举报