MongoDB使用keyfile访问控制来部署新的副本集

一、概述
在副本集中使用访问控制需要进行如下配置:
1、在副本集节点之间使用内部认证来确保安全
2、在客户端和副本集之间使用基于角色的访问控制来确保安全

实施内部认证的同时也启用了用户访问控制,连接到副本集,客户端(像 mongo shell)需要使用用户账户来连接。

二、考虑因素
1、IP绑定
从MongoDB3.6版本开始,mongod和mongos默认绑定localhost,如果部署的节点运行在不同的host或者希望远程客户端也能连接,就需要声明--bind_ip或者net.bindIp.

2、OS
这里主要介绍的是mongod进程的配置,Windows系统用户使用mongod.exe

3、keyfile 安全性
keyfile是最低限度形式的安全保证,适合于使用在测试或开发环境,如果是在生产环境则推荐使用x.509证书

4、用户和认证机制
这里仅仅介绍在admin数据库上创建最小化的管理员用户。使用默认的SCRAM认证机制来进行用户认证。挑战响应安全机制非常适合测试霍开发环境。对于生产环境推荐使用x.509证书或者LDAP代理认证或者Kerberos认证(后面两种仅仅在MongoDB企业版可用)

三、使用keyfile访问机制部署新的副本集
1、创建一个keyfile
如果使用keyfile认证,副本集里面每个mongod实例都使用keyfile的内容作为共享密码与其他的副本集的节点进行验证。只有使用正确keyfile的mongod实例才能加入到副本集
keyfile的内容必须在6到1024个字符长度之间,并且所有副本集节点的内容必须是一样的。

注意:在Unix系统,keyfile不能拥有group和world权限,在Windows系统,keyfile权限不能被检查

可以使用任意方法生成keyfile,例如:下面的操作使用OpenSSL来生成一个完全伪随机的1024个字符的字符串。然后使用chmod来改变文件的权限,仅仅为文件拥有者提供读权限。
openssl rand -base64 756 > <path-to-keyfile>
chmod 400 <path-to-keyfile>

2、复制keyfile到每个副本集节点
复制keyfile到每个副本集节点,确保运行mongod实例的用户是这个文件的拥有者并且可以访问这个文件
避免把keyfile存储在容易失去联系的硬盘上,比如USB硬盘或者网络可访问的存储设备

3、启用每个副本集节点的访问控制,然后启动
每个副本集的节点,使用security.keyFile配置文件设置或者--keyFile命令行选项启动。使用security.keyFile配置文件设置或者--keyFile命令行选项运行mongod会强制启用内部认证和基于角色的访问控制

配置文件:
security:
  keyFile: <path-to-keyfile>

4、通过localhost接口连接到副本集的一个节点上
通过localhost接口的mongo shell连接到一个mongod实例上,运行mongo shell的主机必须和mongod实例在同一个物理主机上
localhost 接口只有当部署的应用没有创建用户的时候可用,当创建了第一个用户之后,localhost接口就关闭了。

5、初始化副本集
通过mongo shell ,运行 rs.initiate()方法
rs.initiate()有一个可选的参数:副本集配置文件,副本集配置文件包括:
_id :设置副本集名称,此名称必须和replication.replSetName或者 --replSet一样
members:是副本集每个节点组成的数组文档
下面的例子初始化了三个成员的副本集

只能在副本集的一个且仅一个mongod实例上运行rs.initiate()

rs.initiate(
  {
    _id : <replicaSetName>,
    members: [
      { _id : 0, host : "mongo1.example.net:27017" },
      { _id : 1, host : "mongo2.example.net:27017" },
      { _id : 2, host : "mongo3.example.net:27017" }
    ]
  }
)

rs.initiate()触发选举,并选举一个节点作为主节点
在连接到主节点之前,使用rs.status()来找到主节点

6、创建管理员用户
重要:当你创建第一个用户之后,localhost exception 将不再可用了。
第一个用户应该有权限去创建其他的用户,比如userAdminAnyDatabase用户,这样能确保在localhost exception关闭之后你能创建其他的用户
如果一个用户没有创建其他用户的权限,一旦localhost exception 关闭之后,你将不能创建和修改用户,也不能进行必要的操作了。
使用db.createUser()方法来添加用户,在admin数据库上,用户应该至少拥有userAdminAnyDatabase角色
下面的例子是在admin数据库中创建一个拥有userAdminAnyDatabase角色的fred用户
重要:密码应该尽可能的随机、足够长和复杂,来确保系统安全,以阻止或延缓恶意访问

admin = db.getSiblingDB("admin")
admin.createUser(
{
user:"fred",
pwd:"changemel",
roles:[{role:"userAdminAnyDatabase",db:"admin"}]
}
)

7、通过管理员认证
对admin database进行验证

打开mongoshell,使用db.auth()进行验证,举例:下面使用管理员用户fred进行验证:
db.getSiblingDB("admin").auth("fred","changemel")

或者在副本集的主节点重新打开一个mongo shell,使用 -u <username>,-p <password>,和 --authenticationDatabase参数:
mongo -u "fred" -p "changeme1" --authenticationDatabase "admin"

8、创建集群管理员
clusterAdmin角色有进行副本集操作的权限,比如配置副本集
在admin 数据库创建一个集群管理员用户并赋予clusterAdmin角色
db.getSiblingDB("admin").createUser(
  {
    "user" : "ravi",
    "pwd" : "changeme2",
    roles: [ { "role" : "clusterAdmin", "db" : "admin" } ]
  }
)

实际样例:

1、副本集成员配置文件

processManagement:
   fork: true
net:
   bindIp: 127.0.0.1
   port: 27018
storage:
   dbPath: db27018
systemLog:
   destination: file
   path: log/mongo27018.log
   logAppend: true
storage:
   journal:
      enabled: true
security:
   authorization: enabled
   keyFile: keyfile
replication:
   replSetName: member

2、keyfile文件(直接使用vi生成一个文件即可)

123456789

3、启动mongod实例

[admin]$./start27017.sh

[admin]$./start27018.sh

[admin]$./start27019.sh

4、副本集配置文件:replsetConfig.js

config = {
	"_id" : "member",
	"members":[
		{"_id":0,"host":"10.101.93.131:27017"},
		{"_id":1,"host":"10.101.93.131:27018"},
		{"_id":2,"host":"10.101.93.131:27019"}
	]
}

5、后续操作:
[admin]$./bin/mongo 127.0.0.1:27017
MongoDB shell version: 3.2.20
connecting to: 127.0.0.1:27017/test
> load("replsetConfig.js")
true
> rs.initiate(config)
{ "ok" : 1 }
member:OTHER> admin = db.getSiblingDB("admin")
admin
member:PRIMARY> admin.createUser(
...   {
...     user: "admin",
...     pwd: "admin",
...     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
...   }
... )
Successfully added user: {
        "user" : "admin",
        "roles" : [
                {
                        "role" : "userAdminAnyDatabase",
                        "db" : "admin"
                }
        ]
}
member:PRIMARY> db.getSiblingDB("admin").auth("admin", "admin")
1
member:PRIMARY> ^C

猜你喜欢

转载自blog.csdn.net/duzm200542901104/article/details/81673653
今日推荐