zookeeper集群认证功能
需求背景
当前zookeeper集群支持动态伸缩,基础配置文件会动态同步,只要待加入节点配置信息满足集群基本要求,可以自动或者手动添加到某个集群里。因此存在如下几个问题:
- 安全性问题,由于基础配置信息(主要是ip和端口)是公共信息,容易获取。可能存在非法节点加入集群获取集群数据。
- 不同集群可能无法独立隔离,造成不同集群同步混乱。
- 新旧集群混用,可能存在新旧数据错误同步,造成数据异常。
目前zookeeper在3.5.0及以上版本开始支持集群选举认证功能,而我们项目中实际未开启该功能,需要对该功能的应用必要性进行评估。
评估要点
- 安全性
集群选举认证是指,对待加入新集群的节点进行身份认证,只有通过认证的节点才能加入成功,区别于之前只要基础配置信息(IP和端口)满足规则要求即可动态加入。从而认证机制能更好地解决集群数据安全性问题。
- 业务性能
集群选举认证功能不影响业务数据读写性能。集群选举认证只在某节点待加入集群的选举阶段才会进行认证,认证成功后,方可继续参与后续的角色选举。选举结束后,数据读写不会在进行鉴权认证,因而不会影响使用性能。
- 集群隔离
当前同一个网络中的集群隔离仅仅依赖基础配置文件(IP加端口),无法解决新旧集群或者多个集群的配置管理问题。而利用认证信息(账户和密码)的唯一性可实现集群命令空间隔离,避免不同集群,新旧集群混用问题。
- 认证管理
对于zookeeper的集群认证信息,是多个节点共享的重要数据。目前zookeeper支持的认证方案两种:
第一种是基于Kerberos的认证机制,中心化认证方案,优点是安全性高,但实现复杂。
第二种是基于DIGEST-MD5本地认证。优势是设计简单,轻量化,但安全性不如Kerberos。目前而言DIGEST-MD认证方式能满足需求。
设计方案
基于DIGEST-MD5的认证方案
第一步,集群名称和密钥获取
集群账户和密码需要具备集群唯一性,并尽可能与时间,版本等信息相关(可取关键信息的哈希值)。在部署时,生成一组具备唯一性的名称和密码,或者由用户通过业务控制面指定集群名称和密码(改动较大)。
账户集群和密码需要保存在集群外部的配置服务点上,由PD服务去获取对应的集群信息。不同zookeeper节点启动时,先去该服务点获取集群信息(可以包括不限于ip,集群数量,名称,密码等)。
根据集群信息,生成认证文件,如/path/to/server/jaas/file.conf。由于认证文件是zookeeper服务本地保存管理的,需要对齐进行权限限制和管理,这个依赖linux系统权限管理来保证其安全性。
第二步,配置Zookeeper使能集群选举认证功能。
配置具体步骤如下:
- 创建认证信息配置文件,如/path/to/server/jaas/file.conf
其内容如下,其中namespace是集群名,quorum_pwd是对应的密码。
QuorumServer {
org.apache.zookeeper.server.auth.DigestLoginModule required
user_$namespace=\"$quorum_pwd\";
};
QuorumLearner {
org.apache.zookeeper.server.auth.DigestLoginModule required
username=\"$namespace\"
password=\"$quorum_pwd\";
};
- 新增zoo.cfg配置项,使能认证功能,配置如下:
quorum.auth.enableSasl=true
quorum.auth.learnerRequireSasl=true
quorum.auth.serverRequireSasl=true
quorum.auth.learner.saslLoginContext=QuorumLearner
quorum.auth.server.saslLoginContext=QuorumServer
- 新增java.env配置项,指定认证配置文件路径
SERVER_JVMFLAGS="-Djava.security.auth.login.config=/path/to/server/jaas/file.conf"
第三步,加入集群
按添加原来的配置项,生成配置文件,并启动zookeeper,加入集群。
参考资料
https://cwiki.apache.org/confluence/display/ZOOKEEPER/Server-Server+mutual+authentication