Zookeeper 和 SASL

介绍
这是一个描述ZooKeeper和SASL(Simple Authentication and Security Layer)整合建议的设计文档。
JIRA 和 源代码
JIRA问题ZOOKEEPER-938,来自JIRA的可用补丁
请注意:这个JIRA文章只描述了客户端-服务器的相互认证。服务器-服务器的相互认证存在单独的JIRA:ZOOKEEPER-1045
Zookeeper ACLs 和 SASL
这个功能是在Zookeeper已有的认证和授权设计上的最直接的实现。简要的回顾,Zookeeper支持的可插拔的认证方案(authentication scheme)。一个Node有任意数量的对。对的左边成员为认证方案(authentication scheme)指定认证类型和认证的主体。对的右边成员是表示授权给认证主体的权限。例如,在指定Node的一个ACL对可能是
<ip:19.22.0.0/16 , READ>
左边的ip:19.22.0.0/16,意思是 使用互联网地址认证,ipv4地址以"19.22"开头的客户端,拥有右边指定任意权限。右边的READ表示在指定Node上用户"读"的权限。
SASL认证方案标示名是"sasl",因此如果你使用Kerberos协议,你可以如下设置Node:
<sasl:myclient@EXAMPLE.COM , READ>
意思是 Kerberos协议主体是 myclient@EXAMPLE.COM 的客户端 拥有指定Node的读权限。
Zookeeper 命令的差异
1.create
在非SASL认证的Zookeeper,当你创建Node时可能添加认证条件,例如:使用org.apache.zookeeper.server.auth.DigestAuthenticationProvider,你可以:
# create a digest form of the password "password":
$ java -cp build/classes:build/lib/log4j-1.2.15.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider user:password
user:password->user:tpUq/4Pn5A64fVZyQ0gOJ8ZWqkY=
之后再连接Zookeeper,你可以按如下代码使用 密码"password" 将所有权限赋给 用户"user" :
create /mynode content digest:user:tpUq/4Pn5A64fVZyQ0gOJ8ZWqkY=:cdrwa
2.addauth
SASL的认证方案不同于其他的方案,在命令"addauth "中,如果scheme是”sasl”,命令无效。这是因为SASL认证在建立后会立即启用令牌交换,而不是在链接后的任意时间执行addauth。
3.addAcl
因为在create时,不会包含认证信息。因此使用DigestAuthenticationProvider时你需要:
addAcl /mynode digest:user:tpUq/4Pn5A64fVZyQ0gOJ8ZWqkY=:cdrwa
在使用SaslAuthenticationProvider,替换为:
addAcl /mynode sasl:user@EXAMPLE.COM:cdrwa
SASL 和 现有的authProviders
你可能会继续使用 现有的ZooKeeper authentication providers,例如:DigestAuthenticationProvider 配合着SaslAuthenticationProvider。如果你愿意,现有的单元测试的authentication providers使用这些 authentication providers 依然可以正常工作。
org.apache.zookeeper.LoginThread
LoginThread 是一个新类,会启动一下新线程,用于定期刷新zookeeper的server和client 上的javax.security.auth.Subject 证书。如果zookeeper 配置使用 Kerberos (下面的 “服务器配置” ,会教怎么配置),client和server会缓存缓存秘钥或证书。LoginThread 将会刷新 Subject 的证书。
Zookeeper Client 的改进
org.apache.zookeeper.ZooKeeper
如果定义了系统环境变量java.security.auth.login.config,ZooKeeper的构造器会初始化成员变量 org.apache.zookeeper.LoginThread loginThread:
LoginThread loginThread = null;
if (System.getProperty("java.security.auth.login.config") != null) {
// zookeeper.client.ticket.renewal defaults to 19 hours (about 80% of 24 hours, which is a typical ticket expiry interval).
loginThread = new LoginThread("Client",new ClientCallbackHandler(null),Integer.getInteger("zookeeper.client.ticket.renewal",19*60*60*1000));
}
cnxn = new ClientCnxn(connectStringParser.getChrootPath(),
hostProvider, sessionTimeout, this, watchManager,
getClientCnxnSocket(), canBeReadOnly, loginThread);
cnxn.start();
正如上面展示的,loginThread之后传递到类ClientCnxn 的构造器,下一小节中会继续讨论。
未完待续
原英文页:https://cwiki.apache.org/confluence/display/ZOOKEEPER/Zookeeper+and+SASL