001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.security.visibility; 019 020import java.io.IOException; 021 022import org.apache.hadoop.hbase.zookeeper.ZKListener; 023import org.apache.hadoop.hbase.zookeeper.ZKWatcher; 024import org.apache.yetus.audience.InterfaceAudience; 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.zookeeper.ZKUtil; 027import org.apache.hadoop.hbase.zookeeper.ZNodePaths; 028import org.apache.zookeeper.KeeperException; 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032/** 033 * A zk watcher that watches the labels table znode. This would create a znode 034 * /hbase/visibility_labels and will have a serialized form of a set of labels in the system. 035 */ 036@InterfaceAudience.Private 037public class ZKVisibilityLabelWatcher extends ZKListener { 038 039 private static final Logger LOG = LoggerFactory.getLogger(ZKVisibilityLabelWatcher.class); 040 private static final String VISIBILITY_LABEL_ZK_PATH = "zookeeper.znode.visibility.label.parent"; 041 private static final String DEFAULT_VISIBILITY_LABEL_NODE = "visibility/labels"; 042 private static final String VISIBILITY_USER_AUTHS_ZK_PATH = 043 "zookeeper.znode.visibility.user.auths.parent"; 044 private static final String DEFAULT_VISIBILITY_USER_AUTHS_NODE = "visibility/user_auths"; 045 046 private VisibilityLabelsCache labelsCache; 047 private String labelZnode; 048 private String userAuthsZnode; 049 050 public ZKVisibilityLabelWatcher(ZKWatcher watcher, VisibilityLabelsCache labelsCache, 051 Configuration conf) { 052 super(watcher); 053 this.labelsCache = labelsCache; 054 String labelZnodeParent = conf.get(VISIBILITY_LABEL_ZK_PATH, DEFAULT_VISIBILITY_LABEL_NODE); 055 String userAuthsZnodeParent = conf.get(VISIBILITY_USER_AUTHS_ZK_PATH, 056 DEFAULT_VISIBILITY_USER_AUTHS_NODE); 057 this.labelZnode = ZNodePaths.joinZNode(watcher.getZNodePaths().baseZNode, labelZnodeParent); 058 this.userAuthsZnode = ZNodePaths.joinZNode(watcher.getZNodePaths().baseZNode, 059 userAuthsZnodeParent); 060 } 061 062 public void start() throws KeeperException { 063 watcher.registerListener(this); 064 ZKUtil.createWithParents(watcher, labelZnode); 065 ZKUtil.createWithParents(watcher, userAuthsZnode); 066 byte[] data = ZKUtil.getDataAndWatch(watcher, labelZnode); 067 if (data != null && data.length > 0) { 068 refreshVisibilityLabelsCache(data); 069 } 070 data = ZKUtil.getDataAndWatch(watcher, userAuthsZnode); 071 if (data != null && data.length > 0) { 072 refreshUserAuthsCache(data); 073 } 074 } 075 076 private void refreshVisibilityLabelsCache(byte[] data) { 077 try { 078 this.labelsCache.refreshLabelsCache(data); 079 } catch (IOException ioe) { 080 LOG.error("Failed parsing data from labels table " + " from zk", ioe); 081 } 082 } 083 084 private void refreshUserAuthsCache(byte[] data) { 085 try { 086 this.labelsCache.refreshUserAuthsCache(data); 087 } catch (IOException ioe) { 088 LOG.error("Failed parsing data from labels table " + " from zk", ioe); 089 } 090 } 091 092 @Override 093 public void nodeCreated(String path) { 094 if (path.equals(labelZnode) || path.equals(userAuthsZnode)) { 095 try { 096 ZKUtil.watchAndCheckExists(watcher, path); 097 } catch (KeeperException ke) { 098 LOG.error("Error setting watcher on node " + path, ke); 099 // only option is to abort 100 watcher.abort("ZooKeeper error obtaining label node children", ke); 101 } 102 } 103 } 104 105 @Override 106 public void nodeDeleted(String path) { 107 // There is no case of visibility labels path to get deleted. 108 } 109 110 @Override 111 public void nodeDataChanged(String path) { 112 if (path.equals(labelZnode) || path.equals(userAuthsZnode)) { 113 try { 114 watcher.sync(path); 115 byte[] data = ZKUtil.getDataAndWatch(watcher, path); 116 if (path.equals(labelZnode)) { 117 refreshVisibilityLabelsCache(data); 118 } else { 119 refreshUserAuthsCache(data); 120 } 121 } catch (KeeperException ke) { 122 LOG.error("Error reading data from zookeeper for node " + path, ke); 123 // only option is to abort 124 watcher.abort("ZooKeeper error getting data for node " + path, ke); 125 } 126 } 127 } 128 129 @Override 130 public void nodeChildrenChanged(String path) { 131 // We are not dealing with child nodes under the label znode or userauths znode. 132 } 133 134 /** 135 * Write a labels mirror or user auths mirror into zookeeper 136 * 137 * @param data 138 * @param labelsOrUserAuths true for writing labels and false for user auths. 139 */ 140 public void writeToZookeeper(byte[] data, boolean labelsOrUserAuths) { 141 String znode = this.labelZnode; 142 if (!labelsOrUserAuths) { 143 znode = this.userAuthsZnode; 144 } 145 try { 146 ZKUtil.updateExistingNodeData(watcher, znode, data, -1); 147 } catch (KeeperException e) { 148 LOG.error("Failed writing to " + znode, e); 149 watcher.abort("Failed writing node " + znode + " to zookeeper", e); 150 } 151 } 152}