Zookeeper acl超级用户
总体来说,ZK的节点有5种操作权限:CREATE、READ、WRITE、DELETE、ADMIN也就是增、删、改、查、管理权限,这5种权限简写为crwda。注:delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限。 Cli命令行下可这样测试:create /test 'test-data'getAcl /test通过getAcl命令可以发现,刚创建的...
总体来说,ZK的节点有5种操作权限:
CREATE、READ、WRITE、DELETE、ADMIN也就是增、删、改、查、管理权限,这5种权限简写为crwda。
注:
delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限。
Cli命令行下可这样测试:
- create /test 'test-data'
- getAcl /test
通过getAcl命令可以发现,刚创建的节点,默认是world, anyone的认证方式,具有cdrwa所有权限。
- setAcl /test digest:user1:UdxDQl4f9v5oITwcAsO9bmWgHSI=:r
- getAcl /test
- addauth digest user1:super123
- get /test
- delete /test
先给/test增加了user1:UdxDQl4f9v5oITwcAsO9bmWgHSI=的只读r权限控制,密码必须是加密后的内容,对应的原文是super123。
然后get /test时,提示认证无效,说明访问控制不起作用,接下来:
addauth...给“上下文”增加一个认证用户,接着get /test就能取到数据了。
最后 delete /test 成功了!原因是:根节点/默认是world:anyone:crdwa,所以也就是说任何人,都能对根节点/进行读写创建子节点、管理acl,以及删除子节点。
刚才也提到了,setAcl /path digest,必须输入加密后的密码,这个 cli控制台上很不方便,所以常用下面的方式:
- create /test 'test-data'
- addauth digest user1:UdxDQl4f9v5oITwcAsO9bmWgHSI=
- setAcl /test auth:user1:super123:r
加密的规则:
static public String generateDigest(String idPassword)
throws NoSuchAlgorithmException {
String parts[] = idPassword.split(":", 2);
byte digest[] = MessageDigest.getInstance("SHA1").digest(
idPassword.getBytes());
return parts[0] + ":" + base64Encode(digest);
}
就是SHA1加密,然后base64编码。
代码使用:
zookeeper有一个很好用的客户端开源项目:http://github.com/zkclient
package yjmyzz.zk;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Main {
private static final String zkAddress = "localhost:2181";
private static final String testNode = "/test";
private static final String readAuth = "read-user:123456";
private static final String writeAuth = "write-user:123456";
private static final String deleteAuth = "delete-user:123456";
private static final String allAuth = "super-user:123456";
private static final String adminAuth = "admin-user:123456";
private static final String digest = "digest";
private static void initNode() throws NoSuchAlgorithmException {
ZkClient zkClient = new ZkClient(zkAddress);
zkClient.addAuthInfo(digest, allAuth.getBytes());
if (zkClient.exists(testNode)) {
zkClient.delete(testNode);
System.out.println("节点删除成功!");
}
List<ACL> acls = new ArrayList<ACL>();
acls.add(new ACL(ZooDefs.Perms.ALL, new Id(digest, DigestAuthenticationProvider.generateDigest(allAuth))));
acls.add(new ACL(ZooDefs.Perms.READ, new Id(digest, DigestAuthenticationProvider.generateDigest(readAuth))));
acls.add(new ACL(ZooDefs.Perms.WRITE, new Id(digest, DigestAuthenticationProvider.generateDigest(writeAuth))));
acls.add(new ACL(ZooDefs.Perms.DELETE, new Id(digest, DigestAuthenticationProvider.generateDigest(deleteAuth))));
acls.add(new ACL(ZooDefs.Perms.ADMIN, new Id(digest, DigestAuthenticationProvider.generateDigest(adminAuth))));
zkClient.createPersistent(testNode, "test-data", acls);
System.out.println(zkClient.readData(testNode));
System.out.println("节点创建成功!");
zkClient.close();
}
private static void readTest() {
ZkClient zkClient = new ZkClient(zkAddress);
try {
System.out.println(zkClient.readData(testNode));//没有认证信息,读取会出错
} catch (Exception e) {
System.err.println(e.getMessage());
}
try {
zkClient.addAuthInfo(digest, adminAuth.getBytes());
System.out.println(zkClient.readData(testNode));//admin权限与read权限不匹配,读取也会出错
} catch (Exception e) {
System.err.println(e.getMessage());
}
try {
zkClient.addAuthInfo(digest, readAuth.getBytes());
System.out.println(zkClient.readData(testNode));//只有read权限的认证信息,才能正常读取
} catch (Exception e) {
System.err.println(e.getMessage());
}
zkClient.close();
}
private static void writeTest() {
ZkClient zkClient = new ZkClient(zkAddress);
try {
zkClient.writeData(testNode, "new-data");//没有认证信息,写入会失败
} catch (Exception e) {
System.err.println(e.getMessage());
}
try {
zkClient.addAuthInfo(digest, writeAuth.getBytes());
zkClient.writeData(testNode, "new-data");//加入认证信息后,写入正常
} catch (Exception e) {
System.err.println(e.getMessage());
}
try {
zkClient.addAuthInfo(digest, readAuth.getBytes());
System.out.println(zkClient.readData(testNode));//读取新值验证
} catch (Exception e) {
System.err.println(e.getMessage());
}
zkClient.close();
}
private static void deleteTest() {
ZkClient zkClient = new ZkClient(zkAddress);
//zkClient.addAuthInfo(digest, deleteAuth.getBytes());
try {
//System.out.println(zkClient.readData(testNode));
zkClient.delete(testNode);
System.out.println("节点删除成功!");
} catch (Exception e) {
System.err.println(e.getMessage());
}
zkClient.close();
}
// private static void deleteTest2() throws IOException, InterruptedException, KeeperException {
// //使用zookeeper原生的API进行删除(注:delete权限指有没有权限删除子节点)
// ZooKeeper zk = new ZooKeeper(zkAddress, 300000, new DemoWatcher());
// zk.delete(testNode, -1);
// System.out.println("节点删除成功");
// zk.close();
// }
//
// static class DemoWatcher implements Watcher {
// @Override
// public void process(WatchedEvent event) {
// System.out.println("----------->");
// System.out.println("path:" + event.getPath());
// System.out.println("type:" + event.getType());
// System.out.println("stat:" + event.getState());
// System.out.println("<-----------");
// }
// }
private static void changeACLTest() {
ZkClient zkClient = new ZkClient(zkAddress);
//注:zkClient.setAcl方法查看源码可以发现,调用了readData、setAcl二个方法
//所以要修改节点的ACL属性,必须同时具备read、admin二种权限
zkClient.addAuthInfo(digest, adminAuth.getBytes());
zkClient.addAuthInfo(digest, readAuth.getBytes());
try {
List<ACL> acls = new ArrayList<ACL>();
acls.add(new ACL(ZooDefs.Perms.ALL, new Id(digest, DigestAuthenticationProvider.generateDigest(adminAuth))));
zkClient.setAcl(testNode, acls);
Map.Entry<List<ACL>, Stat> aclResult = zkClient.getAcl(testNode);
System.out.println(aclResult.getKey());
} catch (Exception e) {
System.err.println(e.getMessage());
}
zkClient.close();
}
public static void main(String[] args) throws Exception {
initNode();
System.out.println("---------------------");
readTest();
System.out.println("---------------------");
writeTest();
System.out.println("---------------------");
changeACLTest();
System.out.println("---------------------");
deleteTest();
//deleteTest2();
}
}
要修改某个节点的ACL属性,必须具有read、admin二种权限。
要删除某个节点下的子节点,必须具有对父节点的read权限,以及父节点的delete权限。
Zookeeper超级用户
Zookeeper管理员会因为某些客户端对某些节点设置了权限,而导致在紧急的情况下无法修改这些节点。在这种情况下,管理员可以通过zookeeper超级用户模式访问这些节点,一旦设置了超级权限访问节点,后续的操作就不需要check ACL了。
使用超级用户模式,可以通过zookeeper的zookeeper.DigestAuthenticationProvider.superDigest参数开启。
在zkServer.sh配置启动参数:
nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:g9oN2HttPfn8MMWJZ2r45Np/LIA=" \
重新启动zookeeper服务
zkServer.sh restart
使用刚才设置的用户名就可以访问任意节点了及操作。
提醒,操作完成后,最好把zkServer.sh文件还原了,以免出安全问题。
最后欢迎大家访问我的个人网站:1024s
更多推荐
所有评论(0)