1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.security.access;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hadoop.conf.Configuration;
24 import org.apache.hadoop.hbase.util.Bytes;
25 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
26 import org.apache.hadoop.hbase.zookeeper.ZooKeeperListener;
27 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
28 import org.apache.zookeeper.KeeperException;
29
30 import java.io.IOException;
31 import java.util.List;
32
33
34
35
36
37
38
39
40
41
42 public class ZKPermissionWatcher extends ZooKeeperListener {
43 private static Log LOG = LogFactory.getLog(ZKPermissionWatcher.class);
44
45 static final String ACL_NODE = "acl";
46 TableAuthManager authManager;
47 String aclZNode;
48
49 public ZKPermissionWatcher(ZooKeeperWatcher watcher,
50 TableAuthManager authManager, Configuration conf) {
51 super(watcher);
52 this.authManager = authManager;
53 String aclZnodeParent = conf.get("zookeeper.znode.acl.parent", ACL_NODE);
54 this.aclZNode = ZKUtil.joinZNode(watcher.baseZNode, aclZnodeParent);
55 }
56
57 public void start() throws KeeperException {
58 watcher.registerListener(this);
59 if (ZKUtil.watchAndCheckExists(watcher, aclZNode)) {
60 List<ZKUtil.NodeAndData> existing =
61 ZKUtil.getChildDataAndWatchForNewChildren(watcher, aclZNode);
62 if (existing != null) {
63 refreshNodes(existing);
64 }
65 }
66 }
67
68 @Override
69 public void nodeCreated(String path) {
70 if (path.equals(aclZNode)) {
71 try {
72 List<ZKUtil.NodeAndData> nodes =
73 ZKUtil.getChildDataAndWatchForNewChildren(watcher, aclZNode);
74 refreshNodes(nodes);
75 } catch (KeeperException ke) {
76 LOG.error("Error reading data from zookeeper", ke);
77
78 watcher.abort("Zookeeper error obtaining acl node children", ke);
79 }
80 }
81 }
82
83 @Override
84 public void nodeDeleted(String path) {
85 if (aclZNode.equals(ZKUtil.getParent(path))) {
86 String table = ZKUtil.getNodeName(path);
87 authManager.remove(Bytes.toBytes(table));
88 }
89 }
90
91 @Override
92 public void nodeDataChanged(String path) {
93 if (aclZNode.equals(ZKUtil.getParent(path))) {
94
95 String table = ZKUtil.getNodeName(path);
96 try {
97 byte[] data = ZKUtil.getDataAndWatch(watcher, path);
98 authManager.refreshCacheFromWritable(Bytes.toBytes(table), data);
99 } catch (KeeperException ke) {
100 LOG.error("Error reading data from zookeeper for node "+table, ke);
101
102 watcher.abort("Zookeeper error getting data for node " + table, ke);
103 } catch (IOException ioe) {
104 LOG.error("Error reading permissions writables", ioe);
105 }
106 }
107 }
108
109 @Override
110 public void nodeChildrenChanged(String path) {
111 if (path.equals(aclZNode)) {
112
113 try {
114 List<ZKUtil.NodeAndData> nodes =
115 ZKUtil.getChildDataAndWatchForNewChildren(watcher, aclZNode);
116 refreshNodes(nodes);
117 } catch (KeeperException ke) {
118 LOG.error("Error reading data from zookeeper for path "+path, ke);
119 watcher.abort("Zookeeper error get node children for path "+path, ke);
120 }
121 }
122 }
123
124 private void refreshNodes(List<ZKUtil.NodeAndData> nodes) {
125 for (ZKUtil.NodeAndData n : nodes) {
126 if (n.isEmpty()) continue;
127 String path = n.getNode();
128 String table = ZKUtil.getNodeName(path);
129 try {
130 byte[] nodeData = n.getData();
131 if (LOG.isDebugEnabled()) {
132 LOG.debug("Updating permissions cache from node "+table+" with data: "+
133 Bytes.toStringBinary(nodeData));
134 }
135 authManager.refreshCacheFromWritable(Bytes.toBytes(table), nodeData);
136 } catch (IOException ioe) {
137 LOG.error("Failed parsing permissions for table '" + table +
138 "' from zk", ioe);
139 }
140 }
141 }
142
143
144
145
146
147
148 public void writeToZookeeper(byte[] tableName, byte[] permsData) {
149 String zkNode = ZKUtil.joinZNode(watcher.baseZNode, ACL_NODE);
150 zkNode = ZKUtil.joinZNode(zkNode, Bytes.toString(tableName));
151
152 try {
153 ZKUtil.createWithParents(watcher, zkNode);
154 ZKUtil.updateExistingNodeData(watcher, zkNode, permsData, -1);
155 } catch (KeeperException e) {
156 LOG.error("Failed updating permissions for table '" +
157 Bytes.toString(tableName) + "'", e);
158 watcher.abort("Failed writing node "+zkNode+" to zookeeper", e);
159 }
160 }
161 }