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 2012/12/14 22:12:51 UTC

svn commit: r1422094 - in /hbase/trunk/hbase-server/src: main/java/org/apache/hadoop/hbase/coprocessor/ main/java/org/apache/hadoop/hbase/regionserver/ main/java/org/apache/hadoop/hbase/security/access/ test/java/org/apache/hadoop/hbase/security/access/

Author: apurtell
Date: Fri Dec 14 21:12:36 2012
New Revision: 1422094

URL: http://svn.apache.org/viewvc?rev=1422094&view=rev
Log:
HBASE-7331. Add access control for region open and close, and stopping the regionserver (Vandana Ayyalasomayajula)

Added:
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessorEnvironment.java
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerCoprocessorHost.java
Modified:
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserver.java
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
    hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java

Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserver.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserver.java?rev=1422094&r1=1422093&r2=1422094&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserver.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserver.java Fri Dec 14 21:12:36 2012
@@ -62,14 +62,14 @@ public abstract class BaseRegionObserver
   public void stop(CoprocessorEnvironment e) throws IOException { }
 
   @Override
-  public void preOpen(ObserverContext<RegionCoprocessorEnvironment> e) { }
+  public void preOpen(ObserverContext<RegionCoprocessorEnvironment> e) throws IOException { }
 
   @Override
   public void postOpen(ObserverContext<RegionCoprocessorEnvironment> e) { }
 
   @Override
-  public void preClose(ObserverContext<RegionCoprocessorEnvironment> e,
-      boolean abortRequested) { }
+  public void preClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested)
+      throws IOException { }
 
   @Override
   public void postClose(ObserverContext<RegionCoprocessorEnvironment> e,

Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java?rev=1422094&r1=1422093&r2=1422094&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java Fri Dec 14 21:12:36 2012
@@ -64,6 +64,8 @@ import java.util.jar.JarFile;
 public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
   public static final String REGION_COPROCESSOR_CONF_KEY =
       "hbase.coprocessor.region.classes";
+  public static final String REGIONSERVER_COPROCESSOR_CONF_KEY =
+      "hbase.coprocessor.regionserver.classes";
   public static final String USER_REGION_COPROCESSOR_CONF_KEY =
       "hbase.coprocessor.user.region.classes";
   public static final String MASTER_COPROCESSOR_CONF_KEY =

Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java?rev=1422094&r1=1422093&r2=1422094&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java Fri Dec 14 21:12:36 2012
@@ -58,8 +58,9 @@ public interface RegionObserver extends 
   /**
    * Called before the region is reported as open to the master.
    * @param c the environment provided by the region server
+   * @throws IOException if an error occurred on the coprocessor
    */
-  void preOpen(final ObserverContext<RegionCoprocessorEnvironment> c);
+  void preOpen(final ObserverContext<RegionCoprocessorEnvironment> c) throws IOException;
 
   /**
    * Called after the region is reported as open to the master.
@@ -261,9 +262,10 @@ public interface RegionObserver extends 
    * Called before the region is reported as closed to the master.
    * @param c the environment provided by the region server
    * @param abortRequested true if the region server is aborting
+   * @throws IOException 
    */
   void preClose(final ObserverContext<RegionCoprocessorEnvironment> c,
-      boolean abortRequested);
+      boolean abortRequested) throws IOException;
 
   /**
    * Called after the region is reported as closed to the master.

Added: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessorEnvironment.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessorEnvironment.java?rev=1422094&view=auto
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessorEnvironment.java (added)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessorEnvironment.java Fri Dec 14 21:12:36 2012
@@ -0,0 +1,31 @@
+/**
+ *
+ * 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.coprocessor;
+
+import org.apache.hadoop.hbase.CoprocessorEnvironment;
+import org.apache.hadoop.hbase.regionserver.RegionServerServices;
+
+public interface RegionServerCoprocessorEnvironment extends CoprocessorEnvironment {
+  /**
+   * Gets the region server services.
+   *
+   * @return the region server services
+   */
+  RegionServerServices getRegionServerServices();
+}

Added: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java?rev=1422094&view=auto
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java (added)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java Fri Dec 14 21:12:36 2012
@@ -0,0 +1,35 @@
+/**
+ *
+ * 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.coprocessor;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hbase.Coprocessor;
+
+public interface RegionServerObserver extends Coprocessor {
+
+  /**
+   * Called before stopping region server.
+   * @param env An instance of RegionServerCoprocessorEnvironment
+   * @throws IOException Signals that an I/O exception has occurred.
+   */
+  void preStopRegionServer(
+    final ObserverContext<RegionServerCoprocessorEnvironment> env)
+    throws IOException;
+}

Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java?rev=1422094&r1=1422093&r2=1422094&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java Fri Dec 14 21:12:36 2012
@@ -432,6 +432,8 @@ public class  HRegionServer implements C
    * The reference to the QosFunction
    */
   private final QosFunction qosFunction;
+  
+  private RegionServerCoprocessorHost rsHost;
 
   /**
    * Starts a HRegionServer at the default location
@@ -517,6 +519,7 @@ public class  HRegionServer implements C
       "hbase.regionserver.kerberos.principal", this.isa.getHostName());
     regionServerAccounting = new RegionServerAccounting();
     cacheConfig = new CacheConfig(conf);
+    this.rsHost = new RegionServerCoprocessorHost(this, this.conf);
   }
 
   /**
@@ -1574,10 +1577,15 @@ public class  HRegionServer implements C
 
   @Override
   public void stop(final String msg) {
-    this.stopped = true;
-    LOG.info("STOPPED: " + msg);
-    // Wakes run() if it is sleeping
-    sleeper.skipSleepCycle();
+    try {
+      this.rsHost.preStop(msg);
+      this.stopped = true;
+      LOG.info("STOPPED: " + msg);
+      // Wakes run() if it is sleeping
+      sleeper.skipSleepCycle();
+    } catch (IOException exp) {
+      LOG.warn("The region server did not stop", exp);
+    }
   }
 
   public void waitForServerOnline(){
@@ -2097,6 +2105,10 @@ public class  HRegionServer implements C
   public ZooKeeperWatcher getZooKeeperWatcher() {
     return this.zooKeeper;
   }
+  
+  public RegionServerCoprocessorHost getCoprocessorHost(){
+    return this.rsHost;
+  }
 
 
   public ConcurrentSkipListMap<byte[], Boolean> getRegionsInTransitionInRS() {
@@ -2398,6 +2410,17 @@ public class  HRegionServer implements C
    */
   protected boolean closeRegion(HRegionInfo region, final boolean abort,
       final boolean zk, final int versionOfClosingNode, ServerName sn) {
+    //Check for permissions to close.
+    HRegion actualRegion = this.getFromOnlineRegions(region.getEncodedName());
+    if ((actualRegion != null) && (actualRegion.getCoprocessorHost() != null)) {
+      try {
+        actualRegion.getCoprocessorHost().preClose(false);
+      } catch (IOException exp) {
+        LOG.warn("Unable to close region", exp);
+        return false;
+      }
+    }
+
     if (this.regionsInTransitionInRS.containsKey(region.getEncodedNameAsBytes())) {
       LOG.warn("Received close for region we are already opening or closing; " +
         region.getEncodedName());
@@ -3380,6 +3403,10 @@ public class  HRegionServer implements C
         checkIfRegionInTransition(region.getEncodedNameAsBytes(), OPEN);
         HRegion onlineRegion = getFromOnlineRegions(region.getEncodedName());
         if (null != onlineRegion) {
+          //Check if the region can actually be opened. 
+          if( onlineRegion.getCoprocessorHost() != null){
+            onlineRegion.getCoprocessorHost().preOpen();
+          }
           // See HBASE-5094. Cross check with META if still this RS is owning
           // the region.
           Pair<HRegionInfo, ServerName> p = MetaReader.getRegion(
@@ -3459,6 +3486,10 @@ public class  HRegionServer implements C
       String encodedRegionName =
         ProtobufUtil.getRegionEncodedName(request.getRegion());
       byte[] encodedName = Bytes.toBytes(encodedRegionName);
+      HRegion region = getRegionByEncodedName(encodedRegionName);
+      if(region.getCoprocessorHost() != null){
+        region.getCoprocessorHost().preClose(false);
+      }
       Boolean openAction = regionsInTransitionInRS.get(encodedName);
       if (openAction != null) {
         if (openAction.booleanValue()) {
@@ -3466,7 +3497,7 @@ public class  HRegionServer implements C
         }
         checkIfRegionInTransition(encodedName, CLOSE);
       }
-      HRegion region = getRegionByEncodedName(encodedRegionName);
+           
       requestCount.increment();
       LOG.info("Received close region: " + region.getRegionNameAsString() +
         ". Version of ZK closing node:" + versionOfClosingNode +

Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java?rev=1422094&r1=1422093&r2=1422094&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java Fri Dec 14 21:12:36 2012
@@ -36,7 +36,6 @@ import org.apache.hadoop.conf.Configurat
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hbase.Coprocessor;
 import org.apache.hadoop.hbase.CoprocessorEnvironment;
-import org.apache.hadoop.hbase.HBaseConfiguration;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.HTableDescriptor;
@@ -53,8 +52,8 @@ import org.apache.hadoop.hbase.coprocess
 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
 import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
 import org.apache.hadoop.hbase.coprocessor.RegionObserver;
-import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 import org.apache.hadoop.hbase.filter.ByteArrayComparable;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.ipc.CoprocessorProtocol;
 import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
@@ -267,17 +266,19 @@ public class RegionCoprocessorHost
   }
 
   /**
-   * Invoked before a region open
+   * Invoked before a region open.
+   *
+   * @throws IOException Signals that an I/O exception has occurred.
    */
-  public void preOpen() {
+  public void preOpen() throws IOException {
     ObserverContext<RegionCoprocessorEnvironment> ctx = null;
     for (RegionEnvironment env: coprocessors) {
       if (env.getInstance() instanceof RegionObserver) {
         ctx = ObserverContext.createAndPrepare(env, ctx);
          try {
-          ((RegionObserver)env.getInstance()).preOpen(ctx);
+          ((RegionObserver) env.getInstance()).preOpen(ctx);
          } catch (Throwable e) {
-           handleCoprocessorThrowableNoRethrow(env, e);
+           handleCoprocessorThrowable(env, e);
          }
         if (ctx.shouldComplete()) {
           break;
@@ -295,7 +296,7 @@ public class RegionCoprocessorHost
       if (env.getInstance() instanceof RegionObserver) {
         ctx = ObserverContext.createAndPrepare(env, ctx);
         try {
-          ((RegionObserver)env.getInstance()).postOpen(ctx);
+          ((RegionObserver) env.getInstance()).postOpen(ctx);
         } catch (Throwable e) {
           handleCoprocessorThrowableNoRethrow(env, e);
         }
@@ -310,15 +311,15 @@ public class RegionCoprocessorHost
    * Invoked before a region is closed
    * @param abortRequested true if the server is aborting
    */
-  public void preClose(boolean abortRequested) {
+  public void preClose(boolean abortRequested) throws IOException {
     ObserverContext<RegionCoprocessorEnvironment> ctx = null;
     for (RegionEnvironment env: coprocessors) {
       if (env.getInstance() instanceof RegionObserver) {
         ctx = ObserverContext.createAndPrepare(env, ctx);
         try {
-          ((RegionObserver)env.getInstance()).preClose(ctx, abortRequested);
+          ((RegionObserver) env.getInstance()).preClose(ctx, abortRequested);
         } catch (Throwable e) {
-          handleCoprocessorThrowableNoRethrow(env, e);
+          handleCoprocessorThrowable(env, e);
         }
       }
     }
@@ -334,7 +335,7 @@ public class RegionCoprocessorHost
       if (env.getInstance() instanceof RegionObserver) {
         ctx = ObserverContext.createAndPrepare(env, ctx);
         try {
-          ((RegionObserver)env.getInstance()).postClose(ctx, abortRequested);
+          ((RegionObserver) env.getInstance()).postClose(ctx, abortRequested);
         } catch (Throwable e) {
           handleCoprocessorThrowableNoRethrow(env, e);
         }

Added: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerCoprocessorHost.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerCoprocessorHost.java?rev=1422094&view=auto
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerCoprocessorHost.java (added)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerCoprocessorHost.java Fri Dec 14 21:12:36 2012
@@ -0,0 +1,108 @@
+/**
+ *
+ * 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.regionserver;
+
+import java.io.IOException;
+import java.util.Comparator;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.Coprocessor;
+import org.apache.hadoop.hbase.CoprocessorEnvironment;
+import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
+import org.apache.hadoop.hbase.coprocessor.ObserverContext;
+import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
+import org.apache.hadoop.hbase.coprocessor.RegionServerObserver;
+
+public class RegionServerCoprocessorHost extends
+    CoprocessorHost<RegionServerCoprocessorHost.RegionServerEnvironment> {
+
+  private RegionServerServices rsServices;
+
+  public RegionServerCoprocessorHost(RegionServerServices rsServices,
+      Configuration conf) {
+    this.rsServices = rsServices;
+    this.conf = conf;
+    // load system default cp's from configuration.
+    loadSystemCoprocessors(conf, REGIONSERVER_COPROCESSOR_CONF_KEY);
+  }
+
+  @Override
+  public RegionServerEnvironment createEnvironment(Class<?> implClass,
+      Coprocessor instance, int priority, int sequence, Configuration conf) {
+    return new RegionServerEnvironment(implClass, instance, priority,
+      sequence, conf, this.rsServices);
+  }
+
+  public void preStop(String message) throws IOException {
+    ObserverContext<RegionServerCoprocessorEnvironment> ctx = null;
+    for (RegionServerEnvironment env : coprocessors) {
+      if (env.getInstance() instanceof RegionServerObserver) {
+        ctx = ObserverContext.createAndPrepare(env, ctx);
+        ((RegionServerObserver) env.getInstance()).preStopRegionServer(ctx);
+        if (ctx.shouldComplete()) {
+          break;
+        }
+      }
+    }
+  }
+
+  /**
+   * Coprocessor environment extension providing access to region server
+   * related services.
+   */
+  static class RegionServerEnvironment extends CoprocessorHost.Environment
+      implements RegionServerCoprocessorEnvironment {
+
+    private RegionServerServices regionServerServices;
+
+    public RegionServerEnvironment(final Class<?> implClass,
+        final Coprocessor impl, final int priority, final int seq,
+        final Configuration conf, final RegionServerServices services) {
+      super(impl, priority, seq, conf);
+      this.regionServerServices = services;
+    }
+
+    @Override
+    public RegionServerServices getRegionServerServices() {
+      return regionServerServices;
+    }
+  }
+
+  /**
+   * Environment priority comparator. Coprocessors are chained in sorted
+   * order.
+   */
+  static class EnvironmentPriorityComparator implements
+      Comparator<CoprocessorEnvironment> {
+    public int compare(final CoprocessorEnvironment env1,
+        final CoprocessorEnvironment env2) {
+      if (env1.getPriority() < env2.getPriority()) {
+        return -1;
+      } else if (env1.getPriority() > env2.getPriority()) {
+        return 1;
+      }
+      if (env1.getLoadSequence() < env2.getLoadSequence()) {
+        return -1;
+      } else if (env1.getLoadSequence() > env2.getLoadSequence()) {
+        return 1;
+      }
+      return 0;
+    }
+  }
+}
\ No newline at end of file

Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java?rev=1422094&r1=1422093&r2=1422094&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java Fri Dec 14 21:12:36 2012
@@ -64,6 +64,7 @@ import org.apache.hadoop.hbase.security.
 import org.apache.hadoop.hbase.security.User;
 import org.apache.hadoop.hbase.security.access.Permission.Action;
 import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
 
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Lists;
@@ -105,7 +106,7 @@ import static org.apache.hadoop.hbase.pr
  * </p>
  */
 public class AccessController extends BaseRegionObserver
-    implements MasterObserver, AccessControllerProtocol,
+    implements MasterObserver, RegionServerObserver, AccessControllerProtocol,
     AccessControlService.Interface, CoprocessorService {
   /**
    * Represents the result of an authorization check for logging and error
@@ -514,17 +515,31 @@ public class AccessController extends Ba
 
   /* ---- MasterObserver implementation ---- */
   public void start(CoprocessorEnvironment env) throws IOException {
-    // if running on HMaster
+
+    ZooKeeperWatcher zk = null;
     if (env instanceof MasterCoprocessorEnvironment) {
-      MasterCoprocessorEnvironment e = (MasterCoprocessorEnvironment)env;
-      this.authManager = TableAuthManager.get(
-          e.getMasterServices().getZooKeeper(),
-          e.getConfiguration());
+      // if running on HMaster
+      MasterCoprocessorEnvironment mEnv = (MasterCoprocessorEnvironment) env;
+      zk = mEnv.getMasterServices().getZooKeeper();      
+    } else if (env instanceof RegionServerCoprocessorEnvironment) {      
+      RegionServerCoprocessorEnvironment rsEnv = (RegionServerCoprocessorEnvironment) env;
+      zk = rsEnv.getRegionServerServices().getZooKeeper();      
+    } else if (env instanceof RegionCoprocessorEnvironment) {
+      // if running at region
+      regionEnv = (RegionCoprocessorEnvironment) env;
+      zk = regionEnv.getRegionServerServices().getZooKeeper();
     }
 
-    // if running at region
-    if (env instanceof RegionCoprocessorEnvironment) {
-      regionEnv = (RegionCoprocessorEnvironment)env;
+    // If zk is null or IOException while obtaining auth manager,
+    // throw RuntimeException so that the coprocessor is unloaded.
+    if (zk != null) {
+      try {
+        this.authManager = TableAuthManager.get(zk, env.getConfiguration());
+      } catch (IOException ioe) {
+        throw new RuntimeException("Error obtaining TableAuthManager", ioe);
+      }
+    } else {
+      throw new RuntimeException("Error obtaining TableAuthManager, zk found null.");
     }
   }
 
@@ -764,27 +779,35 @@ public class AccessController extends Ba
   /* ---- RegionObserver implementation ---- */
 
   @Override
-  public void postOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
-    RegionCoprocessorEnvironment e = c.getEnvironment();
-    final HRegion region = e.getRegion();
+  public void preOpen(ObserverContext<RegionCoprocessorEnvironment> e)
+      throws IOException {
+    RegionCoprocessorEnvironment env = e.getEnvironment();
+    final HRegion region = env.getRegion();
     if (region == null) {
-      LOG.error("NULL region from RegionCoprocessorEnvironment in postOpen()");
+      LOG.error("NULL region from RegionCoprocessorEnvironment in preOpen()");
       return;
+    } else {
+      HRegionInfo regionInfo = region.getRegionInfo();
+      if (isSpecialTable(regionInfo)) {
+        isSystemOrSuperUser(regionEnv.getConfiguration());
+      } else {
+        requirePermission(Action.ADMIN);
+      }
     }
+  }
 
-    try {
-      this.authManager = TableAuthManager.get(
-          e.getRegionServerServices().getZooKeeper(),
-          regionEnv.getConfiguration());
-    } catch (IOException ioe) {
-      // pass along as a RuntimeException, so that the coprocessor is unloaded
-      throw new RuntimeException("Error obtaining TableAuthManager", ioe);
+  @Override
+  public void postOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
+    RegionCoprocessorEnvironment env = c.getEnvironment();
+    final HRegion region = env.getRegion();
+    if (region == null) {
+      LOG.error("NULL region from RegionCoprocessorEnvironment in postOpen()");
+      return;
     }
-
     if (AccessControlLists.isAclRegion(region)) {
       aclRegion = true;
       try {
-        initialize(e);
+        initialize(env);
       } catch (IOException ex) {
         // if we can't obtain permissions, it's better to fail
         // than perform checks incorrectly
@@ -1269,4 +1292,43 @@ public class AccessController extends Ba
     }
     return tableName;
   }
+
+
+  @Override
+  public void preClose(ObserverContext<RegionCoprocessorEnvironment> e, boolean abortRequested)
+      throws IOException {
+    requirePermission(Action.ADMIN);
+  }
+
+  private void isSystemOrSuperUser(Configuration conf) throws IOException {
+    User user = User.getCurrent();
+    if (user == null) {
+      throw new IOException("Unable to obtain the current user, " +
+        "authorization checks for internal operations will not work correctly!");
+    }
+
+    String currentUser = user.getShortName();
+    List<String> superusers = Lists.asList(currentUser, conf.getStrings(
+      AccessControlLists.SUPERUSER_CONF_KEY, new String[0]));
+
+    User activeUser = getActiveUser();
+    if (!(superusers.contains(activeUser.getShortName()))) {
+      throw new AccessDeniedException("User '" + (user != null ? user.getShortName() : "null") +
+        "is not system or super user.");
+    }
+  }
+
+  private boolean isSpecialTable(HRegionInfo regionInfo) {
+    byte[] tableName = regionInfo.getTableName();
+    return tableName.equals(AccessControlLists.ACL_TABLE_NAME)
+        || tableName.equals(Bytes.toBytes("-ROOT-"))
+        || tableName.equals(Bytes.toBytes(".META."));
+  }
+
+  @Override
+  public void preStopRegionServer(
+      ObserverContext<RegionServerCoprocessorEnvironment> env)
+      throws IOException {
+    requirePermission(Permission.Action.ADMIN);
+  }
 }

Modified: hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java?rev=1422094&r1=1422093&r2=1422094&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java (original)
+++ hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java Fri Dec 14 21:12:36 2012
@@ -35,6 +35,7 @@ import org.apache.hadoop.hbase.HRegionIn
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.LargeTests;
 import org.apache.hadoop.hbase.ServerName;
+import org.apache.hadoop.hbase.UnknownRowLockException;
 import org.apache.hadoop.hbase.client.Append;
 import org.apache.hadoop.hbase.client.Delete;
 import org.apache.hadoop.hbase.client.Get;
@@ -49,6 +50,7 @@ import org.apache.hadoop.hbase.client.Sc
 import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
 import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
+import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
 import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
@@ -56,6 +58,7 @@ import org.apache.hadoop.hbase.protobuf.
 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest;
 import org.apache.hadoop.hbase.regionserver.HRegion;
 import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
+import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
 import org.apache.hadoop.hbase.security.AccessDeniedException;
 import org.apache.hadoop.hbase.security.User;
 import org.apache.hadoop.hbase.security.access.Permission.Action;
@@ -84,7 +87,7 @@ public class TestAccessController {
   private static User SUPERUSER;
   // user granted with all global permission
   private static User USER_ADMIN;
-  // user with rw permissions
+  // user with rw permissions on column family.
   private static User USER_RW;
   // user with read-only permissions
   private static User USER_RO;
@@ -100,6 +103,7 @@ public class TestAccessController {
 
   private static MasterCoprocessorEnvironment CP_ENV;
   private static RegionCoprocessorEnvironment RCP_ENV;
+  private static RegionServerCoprocessorEnvironment RSCP_ENV;
   private static AccessController ACCESS_CONTROLLER;
 
   @BeforeClass
@@ -114,6 +118,10 @@ public class TestAccessController {
     ACCESS_CONTROLLER = (AccessController) cpHost.findCoprocessor(AccessController.class.getName());
     CP_ENV = cpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
       Coprocessor.PRIORITY_HIGHEST, 1, conf);
+    RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
+        .getCoprocessorHost();
+    RSCP_ENV = rsHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER, 
+      Coprocessor.PRIORITY_HIGHEST, 1, conf);
 
     // Wait for the ACL table to become available
     TEST_UTIL.waitTableAvailable(AccessControlLists.ACL_TABLE_NAME, 5000);
@@ -1363,4 +1371,44 @@ public class TestAccessController {
     }
 
   }
+
+  @Test
+  public void testStopRegionServer() throws Exception {
+    PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preStopRegionServer(ObserverContext.createAndPrepare(RSCP_ENV, null));
+        return null;
+      }
+    };
+
+    verifyAllowed(action, SUPERUSER, USER_ADMIN);
+    verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE);
+  }
+
+  @Test
+  public void testOpenRegion() throws Exception {
+    PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preOpen(ObserverContext.createAndPrepare(RCP_ENV, null));
+        return null;
+      }
+    };
+
+    verifyAllowed(action, SUPERUSER, USER_ADMIN);
+    verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
+  }
+
+  @Test
+  public void testCloseRegion() throws Exception {
+    PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preClose(ObserverContext.createAndPrepare(RCP_ENV, null), false);
+        return null;
+      }
+    };
+
+    verifyAllowed(action, SUPERUSER, USER_ADMIN);
+    verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
+  }
+
 }