You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ap...@apache.org on 2010/02/26 04:00:47 UTC

svn commit: r916545 - in /hadoop/hbase/trunk: CHANGES.txt contrib/stargate/src/main/java/org/apache/hadoop/hbase/stargate/auth/ZooKeeperAuthenticator.java contrib/stargate/src/test/java/org/apache/hadoop/hbase/stargate/auth/TestZooKeeperAuthenticator.java

Author: apurtell
Date: Fri Feb 26 03:00:47 2010
New Revision: 916545

URL: http://svn.apache.org/viewvc?rev=916545&view=rev
Log:
HBASE-2263 [stargate] multiuser mode: authenticator for zookeeper

Added:
    hadoop/hbase/trunk/contrib/stargate/src/main/java/org/apache/hadoop/hbase/stargate/auth/ZooKeeperAuthenticator.java
    hadoop/hbase/trunk/contrib/stargate/src/test/java/org/apache/hadoop/hbase/stargate/auth/TestZooKeeperAuthenticator.java
Modified:
    hadoop/hbase/trunk/CHANGES.txt

Modified: hadoop/hbase/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/CHANGES.txt?rev=916545&r1=916544&r2=916545&view=diff
==============================================================================
--- hadoop/hbase/trunk/CHANGES.txt (original)
+++ hadoop/hbase/trunk/CHANGES.txt Fri Feb 26 03:00:47 2010
@@ -411,6 +411,7 @@
    HBASE-2070  Collect HLogs and delete them after a period of time
    HBASE-2221  MR to copy a table
    HBASE-2257  [stargate] multiuser mode
+   HBASE-2263  [stargate] multiuser mode: authenticator for zookeeper
 
   OPTIMIZATIONS
    HBASE-410   [testing] Speed up the test suite

Added: hadoop/hbase/trunk/contrib/stargate/src/main/java/org/apache/hadoop/hbase/stargate/auth/ZooKeeperAuthenticator.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/contrib/stargate/src/main/java/org/apache/hadoop/hbase/stargate/auth/ZooKeeperAuthenticator.java?rev=916545&view=auto
==============================================================================
--- hadoop/hbase/trunk/contrib/stargate/src/main/java/org/apache/hadoop/hbase/stargate/auth/ZooKeeperAuthenticator.java (added)
+++ hadoop/hbase/trunk/contrib/stargate/src/main/java/org/apache/hadoop/hbase/stargate/auth/ZooKeeperAuthenticator.java Fri Feb 26 03:00:47 2010
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.stargate.auth;
+
+import java.io.IOException;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.zookeeper.ZooKeeperWrapper;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.data.Stat;
+
+import org.json.JSONObject;
+
+/**
+ * A simple authenticator module for ZooKeeper.
+ * <pre>
+ *   /stargate/
+ *     users/
+ *       &lt;token&gt;</pre> 
+ * Where <tt>&lt;token&gt;</tt> is a JSON formatted user record with the keys
+ * 'name' (String, required), 'token' (String, optional), 'admin' (boolean,
+ * optional), and 'disabled' (boolean, optional).
+ */
+public class ZooKeeperAuthenticator extends Authenticator {
+
+  static final String USERS_ROOT_ZNODE = "/stargate/users";
+
+  ZooKeeperWrapper wrapper;
+
+  private boolean ensureParentExists(final String znode) {
+    int index = znode.lastIndexOf("/");
+    if (index <= 0) {   // Parent is root, which always exists.
+      return true;
+    }
+    return ensureExists(znode.substring(0, index));
+  }
+
+  private boolean ensureExists(final String znode) {
+    ZooKeeper zk = wrapper.getZooKeeper();
+    try {
+      Stat stat = zk.exists(znode, false);
+      if (stat != null) {
+        return true;
+      }
+      zk.create(znode, new byte[0], Ids.OPEN_ACL_UNSAFE, 
+        CreateMode.PERSISTENT);
+      return true;
+    } catch (KeeperException.NodeExistsException e) {
+      return true;      // ok, move on.
+    } catch (KeeperException.NoNodeException e) {
+      return ensureParentExists(znode) && ensureExists(znode);
+    } catch (KeeperException e) {
+    } catch (InterruptedException e) {
+    }
+    return false;
+  }
+
+  /**
+   * Constructor
+   * @param conf
+   * @throws IOException
+   */
+  public ZooKeeperAuthenticator(Configuration conf) throws IOException {
+    this(new ZooKeeperWrapper(conf, new Watcher() {
+      public void process(WatchedEvent event) { }
+    }));
+    ensureExists(USERS_ROOT_ZNODE);
+  }
+
+  /**
+   * Constructor
+   * @param wrapper
+   */
+  public ZooKeeperAuthenticator(ZooKeeperWrapper wrapper) {
+    this.wrapper = wrapper;
+  }
+
+  @Override
+  public User getUserForToken(String token) throws IOException {
+    ZooKeeper zk = wrapper.getZooKeeper();
+    try {
+      byte[] data = zk.getData(USERS_ROOT_ZNODE + "/" + token, null, null);
+      if (data == null) {
+        return null;
+      }
+      JSONObject o = new JSONObject(Bytes.toString(data));
+      if (!o.has("name")) {
+        throw new IOException("invalid record, missing 'name'");
+      }
+      String name = o.getString("name");
+      boolean admin = false;
+      if (o.has("admin")) { admin = o.getBoolean("admin"); }
+      boolean disabled = false;
+      if (o.has("disabled")) { disabled = o.getBoolean("disabled"); }
+      return new User(name, token, admin, disabled);
+    } catch (KeeperException.NoNodeException e) {
+      return null;
+    } catch (Exception e) {
+      throw new IOException(e);
+    }
+  }
+
+}

Added: hadoop/hbase/trunk/contrib/stargate/src/test/java/org/apache/hadoop/hbase/stargate/auth/TestZooKeeperAuthenticator.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/contrib/stargate/src/test/java/org/apache/hadoop/hbase/stargate/auth/TestZooKeeperAuthenticator.java?rev=916545&view=auto
==============================================================================
--- hadoop/hbase/trunk/contrib/stargate/src/test/java/org/apache/hadoop/hbase/stargate/auth/TestZooKeeperAuthenticator.java (added)
+++ hadoop/hbase/trunk/contrib/stargate/src/test/java/org/apache/hadoop/hbase/stargate/auth/TestZooKeeperAuthenticator.java Fri Feb 26 03:00:47 2010
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.stargate.auth;
+
+import org.apache.hadoop.hbase.stargate.MiniClusterTestBase;
+import org.apache.hadoop.hbase.util.Bytes;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.ZooDefs.Ids;
+
+import org.json.JSONStringer;
+
+public class TestZooKeeperAuthenticator extends MiniClusterTestBase {
+
+  static final String UNKNOWN_TOKEN = "00000000000000000000000000000000";
+  static final String ADMIN_TOKEN = "e998efffc67c49c6e14921229a51b7b3";
+  static final String ADMIN_USERNAME = "testAdmin";
+  static final String USER_TOKEN = "da4829144e3a2febd909a6e1b4ed7cfa";
+  static final String USER_USERNAME = "testUser";
+  static final String DISABLED_TOKEN = "17de5b5db0fd3de0847bd95396f36d92";
+  static final String DISABLED_USERNAME = "disabledUser";
+
+  ZooKeeperAuthenticator authenticator;
+
+  @Override
+  public void setUp() throws Exception {
+    authenticator = new ZooKeeperAuthenticator(conf);
+    ZooKeeper zk = authenticator.wrapper.getZooKeeper();
+    if (zk.exists(ZooKeeperAuthenticator.USERS_ROOT_ZNODE + "/" + 
+          ADMIN_TOKEN, null) == null) {
+      zk.create(ZooKeeperAuthenticator.USERS_ROOT_ZNODE + "/" + ADMIN_TOKEN, 
+        Bytes.toBytes(new JSONStringer()
+          .object()
+            .key("name").value(ADMIN_USERNAME)
+            .key("admin").value(true)
+          .endObject().toString()),
+        Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+    }
+    if (zk.exists(ZooKeeperAuthenticator.USERS_ROOT_ZNODE + "/" + 
+          USER_TOKEN, null) == null) {
+      zk.create(ZooKeeperAuthenticator.USERS_ROOT_ZNODE + "/" + USER_TOKEN, 
+        Bytes.toBytes(new JSONStringer()
+          .object()
+            .key("name").value(USER_USERNAME)
+            .key("disabled").value(false)
+          .endObject().toString()),
+        Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+    }
+    if (zk.exists(ZooKeeperAuthenticator.USERS_ROOT_ZNODE + "/" + 
+          DISABLED_TOKEN, null) == null) {
+      zk.create(ZooKeeperAuthenticator.USERS_ROOT_ZNODE + "/" +DISABLED_TOKEN,
+        Bytes.toBytes(new JSONStringer()
+          .object()
+            .key("name").value(DISABLED_USERNAME)
+            .key("admin").value(false)
+            .key("disabled").value(true)
+          .endObject().toString()),
+        Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+    }
+  }
+
+  public void testGetUserUnknown() throws Exception {
+    User user = authenticator.getUserForToken(UNKNOWN_TOKEN);
+    assertNull(user);
+  }
+
+  public void testGetAdminUser() throws Exception {
+    User user = authenticator.getUserForToken(ADMIN_TOKEN);
+    assertNotNull(user);
+    assertEquals(user.getName(), ADMIN_USERNAME);
+    assertTrue(user.isAdmin());
+    assertFalse(user.isDisabled());
+  }
+
+  public void testGetPlainUser() throws Exception {
+    User user = authenticator.getUserForToken(USER_TOKEN);
+    assertNotNull(user);
+    assertEquals(user.getName(), USER_USERNAME);
+    assertFalse(user.isAdmin());
+    assertFalse(user.isDisabled());
+  }
+
+  public void testGetDisabledUser() throws Exception {
+    User user = authenticator.getUserForToken(DISABLED_TOKEN);
+    assertNotNull(user);
+    assertEquals(user.getName(), DISABLED_USERNAME);
+    assertFalse(user.isAdmin());
+    assertTrue(user.isDisabled());
+  }
+
+}