HBASE-12402 ZKPermissionWatcher race condition in refreshing the cache leaving stale ACLs and causing AccessDenied

This commit is contained in:
Enis Soztutar 2014-11-03 20:09:55 -08:00
parent f7adec0548
commit 71f73fcd0b
1 changed files with 25 additions and 6 deletions

View File

@ -31,6 +31,7 @@ import org.apache.zookeeper.KeeperException;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch;
/** /**
* Handles synchronization of access control list entries and updates * Handles synchronization of access control list entries and updates
@ -48,6 +49,7 @@ public class ZKPermissionWatcher extends ZooKeeperListener {
static final String ACL_NODE = "acl"; static final String ACL_NODE = "acl";
TableAuthManager authManager; TableAuthManager authManager;
String aclZNode; String aclZNode;
CountDownLatch initialized = new CountDownLatch(1);
public ZKPermissionWatcher(ZooKeeperWatcher watcher, public ZKPermissionWatcher(ZooKeeperWatcher watcher,
TableAuthManager authManager, Configuration conf) { TableAuthManager authManager, Configuration conf) {
@ -58,18 +60,32 @@ public class ZKPermissionWatcher extends ZooKeeperListener {
} }
public void start() throws KeeperException { public void start() throws KeeperException {
watcher.registerListener(this); try {
if (ZKUtil.watchAndCheckExists(watcher, aclZNode)) { watcher.registerListener(this);
List<ZKUtil.NodeAndData> existing = if (ZKUtil.watchAndCheckExists(watcher, aclZNode)) {
ZKUtil.getChildDataAndWatchForNewChildren(watcher, aclZNode); List<ZKUtil.NodeAndData> existing =
if (existing != null) { ZKUtil.getChildDataAndWatchForNewChildren(watcher, aclZNode);
refreshNodes(existing); if (existing != null) {
refreshNodes(existing);
}
} }
} finally {
initialized.countDown();
}
}
private void waitUntilStarted() {
try {
initialized.await();
} catch (InterruptedException e) {
LOG.warn("Interrupted while waiting", e);
Thread.currentThread().interrupt();
} }
} }
@Override @Override
public void nodeCreated(String path) { public void nodeCreated(String path) {
waitUntilStarted();
if (path.equals(aclZNode)) { if (path.equals(aclZNode)) {
try { try {
List<ZKUtil.NodeAndData> nodes = List<ZKUtil.NodeAndData> nodes =
@ -85,6 +101,7 @@ public class ZKPermissionWatcher extends ZooKeeperListener {
@Override @Override
public void nodeDeleted(String path) { public void nodeDeleted(String path) {
waitUntilStarted();
if (aclZNode.equals(ZKUtil.getParent(path))) { if (aclZNode.equals(ZKUtil.getParent(path))) {
String table = ZKUtil.getNodeName(path); String table = ZKUtil.getNodeName(path);
if(AccessControlLists.isNamespaceEntry(table)) { if(AccessControlLists.isNamespaceEntry(table)) {
@ -97,6 +114,7 @@ public class ZKPermissionWatcher extends ZooKeeperListener {
@Override @Override
public void nodeDataChanged(String path) { public void nodeDataChanged(String path) {
waitUntilStarted();
if (aclZNode.equals(ZKUtil.getParent(path))) { if (aclZNode.equals(ZKUtil.getParent(path))) {
// update cache on an existing table node // update cache on an existing table node
String entry = ZKUtil.getNodeName(path); String entry = ZKUtil.getNodeName(path);
@ -115,6 +133,7 @@ public class ZKPermissionWatcher extends ZooKeeperListener {
@Override @Override
public void nodeChildrenChanged(String path) { public void nodeChildrenChanged(String path) {
waitUntilStarted();
if (path.equals(aclZNode)) { if (path.equals(aclZNode)) {
// table permissions changed // table permissions changed
try { try {