You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by te...@apache.org on 2018/01/05 19:18:20 UTC

[1/3] hbase git commit: HBASE-19483 Add proper privilege check for rsgroup commands

Repository: hbase
Updated Branches:
  refs/heads/master 032fdc53d -> fc7736eb0


http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift2/TestThriftHBaseServiceHandlerWithLabels.java
----------------------------------------------------------------------
diff --git a/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift2/TestThriftHBaseServiceHandlerWithLabels.java b/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift2/TestThriftHBaseServiceHandlerWithLabels.java
index 89a48bd..4a9c8cd 100644
--- a/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift2/TestThriftHBaseServiceHandlerWithLabels.java
+++ b/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift2/TestThriftHBaseServiceHandlerWithLabels.java
@@ -47,7 +47,7 @@ import org.apache.hadoop.hbase.security.visibility.ScanLabelGenerator;
 import org.apache.hadoop.hbase.security.visibility.SimpleScanLabelGenerator;
 import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
 import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
 import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
 import org.apache.hadoop.hbase.testclassification.ClientTests;
 import org.apache.hadoop.hbase.testclassification.MediumTests;
@@ -78,389 +78,386 @@ public class TestThriftHBaseServiceHandlerWithLabels {
 
   private static final Logger LOG = LoggerFactory
     .getLogger(TestThriftHBaseServiceHandlerWithLabels.class);
-private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
-
-// Static names for tables, columns, rows, and values
-private static byte[] tableAname = Bytes.toBytes("tableA");
-private static byte[] familyAname = Bytes.toBytes("familyA");
-private static byte[] familyBname = Bytes.toBytes("familyB");
-private static byte[] qualifierAname = Bytes.toBytes("qualifierA");
-private static byte[] qualifierBname = Bytes.toBytes("qualifierB");
-private static byte[] valueAname = Bytes.toBytes("valueA");
-private static byte[] valueBname = Bytes.toBytes("valueB");
-private static HColumnDescriptor[] families = new HColumnDescriptor[] {
-    new HColumnDescriptor(familyAname).setMaxVersions(3),
-    new HColumnDescriptor(familyBname).setMaxVersions(2) };
-
-private final static String TOPSECRET = "topsecret";
-private final static String PUBLIC = "public";
-private final static String PRIVATE = "private";
-private final static String CONFIDENTIAL = "confidential";
-private final static String SECRET = "secret";
-private static User SUPERUSER;
-
-private static Configuration conf;
-
-public void assertTColumnValuesEqual(List<TColumnValue> columnValuesA,
+  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
+
+  // Static names for tables, columns, rows, and values
+  private static byte[] tableAname = Bytes.toBytes("tableA");
+  private static byte[] familyAname = Bytes.toBytes("familyA");
+  private static byte[] familyBname = Bytes.toBytes("familyB");
+  private static byte[] qualifierAname = Bytes.toBytes("qualifierA");
+  private static byte[] qualifierBname = Bytes.toBytes("qualifierB");
+  private static byte[] valueAname = Bytes.toBytes("valueA");
+  private static byte[] valueBname = Bytes.toBytes("valueB");
+  private static HColumnDescriptor[] families = new HColumnDescriptor[] {
+      new HColumnDescriptor(familyAname).setMaxVersions(3),
+      new HColumnDescriptor(familyBname).setMaxVersions(2) };
+
+  private final static String TOPSECRET = "topsecret";
+  private final static String PUBLIC = "public";
+  private final static String PRIVATE = "private";
+  private final static String CONFIDENTIAL = "confidential";
+  private final static String SECRET = "secret";
+  private static User SUPERUSER;
+
+  private static Configuration conf;
+
+  public void assertTColumnValuesEqual(List<TColumnValue> columnValuesA,
     List<TColumnValue> columnValuesB) {
-  assertEquals(columnValuesA.size(), columnValuesB.size());
-  Comparator<TColumnValue> comparator = new Comparator<TColumnValue>() {
-    @Override
-    public int compare(TColumnValue o1, TColumnValue o2) {
-      return Bytes.compareTo(Bytes.add(o1.getFamily(), o1.getQualifier()),
+    assertEquals(columnValuesA.size(), columnValuesB.size());
+    Comparator<TColumnValue> comparator = new Comparator<TColumnValue>() {
+      @Override
+      public int compare(TColumnValue o1, TColumnValue o2) {
+        return Bytes.compareTo(Bytes.add(o1.getFamily(), o1.getQualifier()),
           Bytes.add(o2.getFamily(), o2.getQualifier()));
+      }
+    };
+    Collections.sort(columnValuesA, comparator);
+    Collections.sort(columnValuesB, comparator);
+
+    for (int i = 0; i < columnValuesA.size(); i++) {
+      TColumnValue a = columnValuesA.get(i);
+      TColumnValue b = columnValuesB.get(i);
+      assertArrayEquals(a.getFamily(), b.getFamily());
+      assertArrayEquals(a.getQualifier(), b.getQualifier());
+      assertArrayEquals(a.getValue(), b.getValue());
     }
-  };
-  Collections.sort(columnValuesA, comparator);
-  Collections.sort(columnValuesB, comparator);
-
-  for (int i = 0; i < columnValuesA.size(); i++) {
-    TColumnValue a = columnValuesA.get(i);
-    TColumnValue b = columnValuesB.get(i);
-    assertArrayEquals(a.getFamily(), b.getFamily());
-    assertArrayEquals(a.getQualifier(), b.getQualifier());
-    assertArrayEquals(a.getValue(), b.getValue());
   }
-}
 
-@BeforeClass
-public static void beforeClass() throws Exception {
-  SUPERUSER = User.createUserForTesting(conf, "admin",
-      new String[] { "supergroup" });
-  conf = UTIL.getConfiguration();
-  conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS,
-      SimpleScanLabelGenerator.class, ScanLabelGenerator.class);
-  conf.set("hbase.superuser", SUPERUSER.getShortName());
-  conf.set("hbase.coprocessor.master.classes",
-      VisibilityController.class.getName());
-  conf.set("hbase.coprocessor.region.classes",
-      VisibilityController.class.getName());
-  conf.setInt("hfile.format.version", 3);
-  UTIL.startMiniCluster(1);
-  // Wait for the labels table to become available
-  UTIL.waitTableEnabled(VisibilityConstants.LABELS_TABLE_NAME.getName(), 50000);
-  createLabels();
-  Admin admin = UTIL.getAdmin();
-  HTableDescriptor tableDescriptor = new HTableDescriptor(
-      TableName.valueOf(tableAname));
-  for (HColumnDescriptor family : families) {
-    tableDescriptor.addFamily(family);
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    SUPERUSER = User.createUserForTesting(conf, "admin",
+        new String[] { "supergroup" });
+    conf = UTIL.getConfiguration();
+    conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS,
+        SimpleScanLabelGenerator.class, ScanLabelGenerator.class);
+    conf.set("hbase.superuser", SUPERUSER.getShortName());
+    VisibilityTestUtil.enableVisiblityLabels(conf);
+    UTIL.startMiniCluster(1);
+    // Wait for the labels table to become available
+    UTIL.waitTableEnabled(VisibilityConstants.LABELS_TABLE_NAME.getName(), 50000);
+    createLabels();
+    Admin admin = UTIL.getAdmin();
+    HTableDescriptor tableDescriptor = new HTableDescriptor(
+        TableName.valueOf(tableAname));
+    for (HColumnDescriptor family : families) {
+      tableDescriptor.addFamily(family);
+    }
+    admin.createTable(tableDescriptor);
+    admin.close();
+    setAuths();
   }
-  admin.createTable(tableDescriptor);
-  admin.close();
-  setAuths();
-}
 
-private static void createLabels() throws IOException, InterruptedException {
-  PrivilegedExceptionAction<VisibilityLabelsResponse> action =
-      new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
-    public VisibilityLabelsResponse run() throws Exception {
-      String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, PUBLIC, TOPSECRET };
-      try (Connection conn = ConnectionFactory.createConnection(conf)) {
-        VisibilityClient.addLabels(conn, labels);
-      } catch (Throwable t) {
-        throw new IOException(t);
+  private static void createLabels() throws IOException, InterruptedException {
+    PrivilegedExceptionAction<VisibilityLabelsResponse> action =
+        new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
+      public VisibilityLabelsResponse run() throws Exception {
+        String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, PUBLIC, TOPSECRET };
+        try (Connection conn = ConnectionFactory.createConnection(conf)) {
+          VisibilityClient.addLabels(conn, labels);
+        } catch (Throwable t) {
+          throw new IOException(t);
+        }
+        return null;
       }
-      return null;
+    };
+    SUPERUSER.runAs(action);
+  }
+
+  private static void setAuths() throws IOException {
+    String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, PUBLIC, TOPSECRET };
+    try {
+      VisibilityClient.setAuths(UTIL.getConnection(), labels, User.getCurrent().getShortName());
+    } catch (Throwable t) {
+      throw new IOException(t);
     }
-  };
-  SUPERUSER.runAs(action);
-}
+  }
 
-private static void setAuths() throws IOException {
-  String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, PUBLIC, TOPSECRET };
-  try {
-    VisibilityClient.setAuths(UTIL.getConnection(), labels, User.getCurrent().getShortName());
-  } catch (Throwable t) {
-    throw new IOException(t);
+  @AfterClass
+  public static void afterClass() throws Exception {
+    UTIL.shutdownMiniCluster();
   }
-}
 
-@AfterClass
-public static void afterClass() throws Exception {
-  UTIL.shutdownMiniCluster();
-}
+  @Before
+  public void setup() throws Exception {
 
-@Before
-public void setup() throws Exception {
+  }
 
-}
+  private ThriftHBaseServiceHandler createHandler() throws IOException {
+    return new ThriftHBaseServiceHandler(conf, UserProvider.instantiate(conf));
+  }
 
-private ThriftHBaseServiceHandler createHandler() throws IOException {
-  return new ThriftHBaseServiceHandler(conf, UserProvider.instantiate(conf));
-}
+  @Test
+  public void testScanWithVisibilityLabels() throws Exception {
+    ThriftHBaseServiceHandler handler = createHandler();
+    ByteBuffer table = wrap(tableAname);
+
+    // insert data
+    TColumnValue columnValue = new TColumnValue(wrap(familyAname),
+        wrap(qualifierAname), wrap(valueAname));
+    List<TColumnValue> columnValues = new ArrayList<>(1);
+    columnValues.add(columnValue);
+    for (int i = 0; i < 10; i++) {
+      TPut put = new TPut(wrap(("testScan" + i).getBytes()), columnValues);
+      if (i == 5) {
+        put.setCellVisibility(new TCellVisibility().setExpression(PUBLIC));
+      } else {
+        put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET
+            + "|" + CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
+      }
+      handler.put(table, put);
+    }
 
-@Test
-public void testScanWithVisibilityLabels() throws Exception {
-  ThriftHBaseServiceHandler handler = createHandler();
-  ByteBuffer table = wrap(tableAname);
-
-  // insert data
-  TColumnValue columnValue = new TColumnValue(wrap(familyAname),
-      wrap(qualifierAname), wrap(valueAname));
-  List<TColumnValue> columnValues = new ArrayList<>(1);
-  columnValues.add(columnValue);
-  for (int i = 0; i < 10; i++) {
-    TPut put = new TPut(wrap(("testScan" + i).getBytes()), columnValues);
-    if (i == 5) {
-      put.setCellVisibility(new TCellVisibility().setExpression(PUBLIC));
-    } else {
-      put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET
-          + "|" + CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
+    // create scan instance
+    TScan scan = new TScan();
+    List<TColumn> columns = new ArrayList<>(1);
+    TColumn column = new TColumn();
+    column.setFamily(familyAname);
+    column.setQualifier(qualifierAname);
+    columns.add(column);
+    scan.setColumns(columns);
+    scan.setStartRow("testScan".getBytes());
+    scan.setStopRow("testScan\uffff".getBytes());
+
+    TAuthorization tauth = new TAuthorization();
+    List<String> labels = new ArrayList<>(2);
+    labels.add(SECRET);
+    labels.add(PRIVATE);
+    tauth.setLabels(labels);
+    scan.setAuthorizations(tauth);
+    // get scanner and rows
+    int scanId = handler.openScanner(table, scan);
+    List<TResult> results = handler.getScannerRows(scanId, 10);
+    assertEquals(9, results.size());
+    Assert.assertFalse(Bytes.equals(results.get(5).getRow(),
+        ("testScan" + 5).getBytes()));
+    for (int i = 0; i < 9; i++) {
+      if (i < 5) {
+        assertArrayEquals(("testScan" + i).getBytes(), results.get(i).getRow());
+      } else if (i == 5) {
+        continue;
+      } else {
+        assertArrayEquals(("testScan" + (i + 1)).getBytes(), results.get(i)
+            .getRow());
+      }
     }
-    handler.put(table, put);
-  }
 
-  // create scan instance
-  TScan scan = new TScan();
-  List<TColumn> columns = new ArrayList<>(1);
-  TColumn column = new TColumn();
-  column.setFamily(familyAname);
-  column.setQualifier(qualifierAname);
-  columns.add(column);
-  scan.setColumns(columns);
-  scan.setStartRow("testScan".getBytes());
-  scan.setStopRow("testScan\uffff".getBytes());
-
-  TAuthorization tauth = new TAuthorization();
-  List<String> labels = new ArrayList<>(2);
-  labels.add(SECRET);
-  labels.add(PRIVATE);
-  tauth.setLabels(labels);
-  scan.setAuthorizations(tauth);
-  // get scanner and rows
-  int scanId = handler.openScanner(table, scan);
-  List<TResult> results = handler.getScannerRows(scanId, 10);
-  assertEquals(9, results.size());
-  Assert.assertFalse(Bytes.equals(results.get(5).getRow(),
-      ("testScan" + 5).getBytes()));
-  for (int i = 0; i < 9; i++) {
-    if (i < 5) {
-      assertArrayEquals(("testScan" + i).getBytes(), results.get(i).getRow());
-    } else if (i == 5) {
-      continue;
-    } else {
-      assertArrayEquals(("testScan" + (i + 1)).getBytes(), results.get(i)
-          .getRow());
+    // check that we are at the end of the scan
+    results = handler.getScannerRows(scanId, 9);
+    assertEquals(0, results.size());
+
+    // close scanner and check that it was indeed closed
+    handler.closeScanner(scanId);
+    try {
+      handler.getScannerRows(scanId, 9);
+      fail("Scanner id should be invalid");
+    } catch (TIllegalArgument e) {
     }
   }
 
-  // check that we are at the end of the scan
-  results = handler.getScannerRows(scanId, 9);
-  assertEquals(0, results.size());
+  @Test
+  public void testGetScannerResultsWithAuthorizations() throws Exception {
+    ThriftHBaseServiceHandler handler = createHandler();
+    ByteBuffer table = wrap(tableAname);
+
+    // insert data
+    TColumnValue columnValue = new TColumnValue(wrap(familyAname),
+        wrap(qualifierAname), wrap(valueAname));
+    List<TColumnValue> columnValues = new ArrayList<>(1);
+    columnValues.add(columnValue);
+    for (int i = 0; i < 20; i++) {
+      TPut put = new TPut(
+          wrap(("testGetScannerResults" + pad(i, (byte) 2)).getBytes()),
+          columnValues);
+      if (i == 3) {
+        put.setCellVisibility(new TCellVisibility().setExpression(PUBLIC));
+      } else {
+        put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET
+            + "|" + CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
+      }
+      handler.put(table, put);
+    }
 
-  // close scanner and check that it was indeed closed
-  handler.closeScanner(scanId);
-  try {
-    handler.getScannerRows(scanId, 9);
-    fail("Scanner id should be invalid");
-  } catch (TIllegalArgument e) {
+    // create scan instance
+    TScan scan = new TScan();
+    List<TColumn> columns = new ArrayList<>(1);
+    TColumn column = new TColumn();
+    column.setFamily(familyAname);
+    column.setQualifier(qualifierAname);
+    columns.add(column);
+    scan.setColumns(columns);
+    scan.setStartRow("testGetScannerResults".getBytes());
+
+    // get 5 rows and check the returned results
+    scan.setStopRow("testGetScannerResults05".getBytes());
+    TAuthorization tauth = new TAuthorization();
+    List<String> labels = new ArrayList<>(2);
+    labels.add(SECRET);
+    labels.add(PRIVATE);
+    tauth.setLabels(labels);
+    scan.setAuthorizations(tauth);
+    List<TResult> results = handler.getScannerResults(table, scan, 5);
+    assertEquals(4, results.size());
+    for (int i = 0; i < 4; i++) {
+      if (i < 3) {
+        assertArrayEquals(
+            ("testGetScannerResults" + pad(i, (byte) 2)).getBytes(),
+            results.get(i).getRow());
+      } else if (i == 3) {
+        continue;
+      } else {
+        assertArrayEquals(
+            ("testGetScannerResults" + pad(i + 1, (byte) 2)).getBytes(), results
+                .get(i).getRow());
+      }
+    }
   }
-}
 
-@Test
-public void testGetScannerResultsWithAuthorizations() throws Exception {
-  ThriftHBaseServiceHandler handler = createHandler();
-  ByteBuffer table = wrap(tableAname);
-
-  // insert data
-  TColumnValue columnValue = new TColumnValue(wrap(familyAname),
-      wrap(qualifierAname), wrap(valueAname));
-  List<TColumnValue> columnValues = new ArrayList<>(1);
-  columnValues.add(columnValue);
-  for (int i = 0; i < 20; i++) {
-    TPut put = new TPut(
-        wrap(("testGetScannerResults" + pad(i, (byte) 2)).getBytes()),
-        columnValues);
-    if (i == 3) {
-      put.setCellVisibility(new TCellVisibility().setExpression(PUBLIC));
-    } else {
-      put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET
-          + "|" + CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
-    }
+  @Test
+  public void testGetsWithLabels() throws Exception {
+    ThriftHBaseServiceHandler handler = createHandler();
+    byte[] rowName = "testPutGet".getBytes();
+    ByteBuffer table = wrap(tableAname);
+
+    List<TColumnValue> columnValues = new ArrayList<>(2);
+    columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
+        wrap(valueAname)));
+    columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname),
+        wrap(valueBname)));
+    TPut put = new TPut(wrap(rowName), columnValues);
+
+    put.setColumnValues(columnValues);
+    put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET + "|"
+        + CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
     handler.put(table, put);
+    TGet get = new TGet(wrap(rowName));
+    TAuthorization tauth = new TAuthorization();
+    List<String> labels = new ArrayList<>(2);
+    labels.add(SECRET);
+    labels.add(PRIVATE);
+    tauth.setLabels(labels);
+    get.setAuthorizations(tauth);
+    TResult result = handler.get(table, get);
+    assertArrayEquals(rowName, result.getRow());
+    List<TColumnValue> returnedColumnValues = result.getColumnValues();
+    assertTColumnValuesEqual(columnValues, returnedColumnValues);
   }
 
-  // create scan instance
-  TScan scan = new TScan();
-  List<TColumn> columns = new ArrayList<>(1);
-  TColumn column = new TColumn();
-  column.setFamily(familyAname);
-  column.setQualifier(qualifierAname);
-  columns.add(column);
-  scan.setColumns(columns);
-  scan.setStartRow("testGetScannerResults".getBytes());
-
-  // get 5 rows and check the returned results
-  scan.setStopRow("testGetScannerResults05".getBytes());
-  TAuthorization tauth = new TAuthorization();
-  List<String> labels = new ArrayList<>(2);
-  labels.add(SECRET);
-  labels.add(PRIVATE);
-  tauth.setLabels(labels);
-  scan.setAuthorizations(tauth);
-  List<TResult> results = handler.getScannerResults(table, scan, 5);
-  assertEquals(4, results.size());
-  for (int i = 0; i < 4; i++) {
-    if (i < 3) {
-      assertArrayEquals(
-          ("testGetScannerResults" + pad(i, (byte) 2)).getBytes(),
-          results.get(i).getRow());
-    } else if (i == 3) {
-      continue;
-    } else {
-      assertArrayEquals(
-          ("testGetScannerResults" + pad(i + 1, (byte) 2)).getBytes(), results
-              .get(i).getRow());
-    }
+  @Test
+  public void testIncrementWithTags() throws Exception {
+    ThriftHBaseServiceHandler handler = createHandler();
+    byte[] rowName = "testIncrementWithTags".getBytes();
+    ByteBuffer table = wrap(tableAname);
+
+    List<TColumnValue> columnValues = new ArrayList<>(1);
+    columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
+        wrap(Bytes.toBytes(1L))));
+    TPut put = new TPut(wrap(rowName), columnValues);
+    put.setColumnValues(columnValues);
+    put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
+    handler.put(table, put);
+
+    List<TColumnIncrement> incrementColumns = new ArrayList<>(1);
+    incrementColumns.add(new TColumnIncrement(wrap(familyAname),
+        wrap(qualifierAname)));
+    TIncrement increment = new TIncrement(wrap(rowName), incrementColumns);
+    increment.setCellVisibility(new TCellVisibility().setExpression(SECRET));
+    handler.increment(table, increment);
+
+    TGet get = new TGet(wrap(rowName));
+    TAuthorization tauth = new TAuthorization();
+    List<String> labels = new ArrayList<>(1);
+    labels.add(SECRET);
+    tauth.setLabels(labels);
+    get.setAuthorizations(tauth);
+    TResult result = handler.get(table, get);
+
+    assertArrayEquals(rowName, result.getRow());
+    assertEquals(1, result.getColumnValuesSize());
+    TColumnValue columnValue = result.getColumnValues().get(0);
+    assertArrayEquals(Bytes.toBytes(2L), columnValue.getValue());
   }
-}
 
-@Test
-public void testGetsWithLabels() throws Exception {
-  ThriftHBaseServiceHandler handler = createHandler();
-  byte[] rowName = "testPutGet".getBytes();
-  ByteBuffer table = wrap(tableAname);
-
-  List<TColumnValue> columnValues = new ArrayList<>(2);
-  columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
-      wrap(valueAname)));
-  columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname),
-      wrap(valueBname)));
-  TPut put = new TPut(wrap(rowName), columnValues);
-
-  put.setColumnValues(columnValues);
-  put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET + "|"
-      + CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
-  handler.put(table, put);
-  TGet get = new TGet(wrap(rowName));
-  TAuthorization tauth = new TAuthorization();
-  List<String> labels = new ArrayList<>(2);
-  labels.add(SECRET);
-  labels.add(PRIVATE);
-  tauth.setLabels(labels);
-  get.setAuthorizations(tauth);
-  TResult result = handler.get(table, get);
-  assertArrayEquals(rowName, result.getRow());
-  List<TColumnValue> returnedColumnValues = result.getColumnValues();
-  assertTColumnValuesEqual(columnValues, returnedColumnValues);
-}
+  @Test
+  public void testIncrementWithTagsWithNotMatchLabels() throws Exception {
+    ThriftHBaseServiceHandler handler = createHandler();
+    byte[] rowName = "testIncrementWithTagsWithNotMatchLabels".getBytes();
+    ByteBuffer table = wrap(tableAname);
+
+    List<TColumnValue> columnValues = new ArrayList<>(1);
+    columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
+        wrap(Bytes.toBytes(1L))));
+    TPut put = new TPut(wrap(rowName), columnValues);
+    put.setColumnValues(columnValues);
+    put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
+    handler.put(table, put);
 
-@Test
-public void testIncrementWithTags() throws Exception {
-  ThriftHBaseServiceHandler handler = createHandler();
-  byte[] rowName = "testIncrementWithTags".getBytes();
-  ByteBuffer table = wrap(tableAname);
-
-  List<TColumnValue> columnValues = new ArrayList<>(1);
-  columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
-      wrap(Bytes.toBytes(1L))));
-  TPut put = new TPut(wrap(rowName), columnValues);
-  put.setColumnValues(columnValues);
-  put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
-  handler.put(table, put);
-
-  List<TColumnIncrement> incrementColumns = new ArrayList<>(1);
-  incrementColumns.add(new TColumnIncrement(wrap(familyAname),
-      wrap(qualifierAname)));
-  TIncrement increment = new TIncrement(wrap(rowName), incrementColumns);
-  increment.setCellVisibility(new TCellVisibility().setExpression(SECRET));
-  handler.increment(table, increment);
-
-  TGet get = new TGet(wrap(rowName));
-  TAuthorization tauth = new TAuthorization();
-  List<String> labels = new ArrayList<>(1);
-  labels.add(SECRET);
-  tauth.setLabels(labels);
-  get.setAuthorizations(tauth);
-  TResult result = handler.get(table, get);
-
-  assertArrayEquals(rowName, result.getRow());
-  assertEquals(1, result.getColumnValuesSize());
-  TColumnValue columnValue = result.getColumnValues().get(0);
-  assertArrayEquals(Bytes.toBytes(2L), columnValue.getValue());
-}
+    List<TColumnIncrement> incrementColumns = new ArrayList<>(1);
+    incrementColumns.add(new TColumnIncrement(wrap(familyAname),
+        wrap(qualifierAname)));
+    TIncrement increment = new TIncrement(wrap(rowName), incrementColumns);
+    increment.setCellVisibility(new TCellVisibility().setExpression(SECRET));
+    handler.increment(table, increment);
+
+    TGet get = new TGet(wrap(rowName));
+    TAuthorization tauth = new TAuthorization();
+    List<String> labels = new ArrayList<>(1);
+    labels.add(PUBLIC);
+    tauth.setLabels(labels);
+    get.setAuthorizations(tauth);
+    TResult result = handler.get(table, get);
+    assertNull(result.getRow());
+  }
 
-@Test
-public void testIncrementWithTagsWithNotMatchLabels() throws Exception {
-  ThriftHBaseServiceHandler handler = createHandler();
-  byte[] rowName = "testIncrementWithTagsWithNotMatchLabels".getBytes();
-  ByteBuffer table = wrap(tableAname);
-
-  List<TColumnValue> columnValues = new ArrayList<>(1);
-  columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
-      wrap(Bytes.toBytes(1L))));
-  TPut put = new TPut(wrap(rowName), columnValues);
-  put.setColumnValues(columnValues);
-  put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
-  handler.put(table, put);
-
-  List<TColumnIncrement> incrementColumns = new ArrayList<>(1);
-  incrementColumns.add(new TColumnIncrement(wrap(familyAname),
-      wrap(qualifierAname)));
-  TIncrement increment = new TIncrement(wrap(rowName), incrementColumns);
-  increment.setCellVisibility(new TCellVisibility().setExpression(SECRET));
-  handler.increment(table, increment);
-
-  TGet get = new TGet(wrap(rowName));
-  TAuthorization tauth = new TAuthorization();
-  List<String> labels = new ArrayList<>(1);
-  labels.add(PUBLIC);
-  tauth.setLabels(labels);
-  get.setAuthorizations(tauth);
-  TResult result = handler.get(table, get);
-  assertNull(result.getRow());
-}
+  @Test
+  public void testAppend() throws Exception {
+    ThriftHBaseServiceHandler handler = createHandler();
+    byte[] rowName = "testAppend".getBytes();
+    ByteBuffer table = wrap(tableAname);
+    byte[] v1 = Bytes.toBytes(1L);
+    byte[] v2 = Bytes.toBytes(5L);
+    List<TColumnValue> columnValues = new ArrayList<>(1);
+    columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
+        wrap(Bytes.toBytes(1L))));
+    TPut put = new TPut(wrap(rowName), columnValues);
+    put.setColumnValues(columnValues);
+    put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
+    handler.put(table, put);
 
-@Test
-public void testAppend() throws Exception {
-  ThriftHBaseServiceHandler handler = createHandler();
-  byte[] rowName = "testAppend".getBytes();
-  ByteBuffer table = wrap(tableAname);
-  byte[] v1 = Bytes.toBytes(1L);
-  byte[] v2 = Bytes.toBytes(5L);
-  List<TColumnValue> columnValues = new ArrayList<>(1);
-  columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
-      wrap(Bytes.toBytes(1L))));
-  TPut put = new TPut(wrap(rowName), columnValues);
-  put.setColumnValues(columnValues);
-  put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
-  handler.put(table, put);
-
-  List<TColumnValue> appendColumns = new ArrayList<>(1);
-  appendColumns.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
-      wrap(v2)));
-  TAppend append = new TAppend(wrap(rowName), appendColumns);
-  append.setCellVisibility(new TCellVisibility().setExpression(SECRET));
-  handler.append(table, append);
-
-  TGet get = new TGet(wrap(rowName));
-  TAuthorization tauth = new TAuthorization();
-  List<String> labels = new ArrayList<>(1);
-  labels.add(SECRET);
-  tauth.setLabels(labels);
-  get.setAuthorizations(tauth);
-  TResult result = handler.get(table, get);
-
-  assertArrayEquals(rowName, result.getRow());
-  assertEquals(1, result.getColumnValuesSize());
-  TColumnValue columnValue = result.getColumnValues().get(0);
-  assertArrayEquals(Bytes.add(v1, v2), columnValue.getValue());
-}
+    List<TColumnValue> appendColumns = new ArrayList<>(1);
+    appendColumns.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
+        wrap(v2)));
+    TAppend append = new TAppend(wrap(rowName), appendColumns);
+    append.setCellVisibility(new TCellVisibility().setExpression(SECRET));
+    handler.append(table, append);
+
+    TGet get = new TGet(wrap(rowName));
+    TAuthorization tauth = new TAuthorization();
+    List<String> labels = new ArrayList<>(1);
+    labels.add(SECRET);
+    tauth.setLabels(labels);
+    get.setAuthorizations(tauth);
+    TResult result = handler.get(table, get);
+
+    assertArrayEquals(rowName, result.getRow());
+    assertEquals(1, result.getColumnValuesSize());
+    TColumnValue columnValue = result.getColumnValues().get(0);
+    assertArrayEquals(Bytes.add(v1, v2), columnValue.getValue());
+  }
 
-/**
- * Padding numbers to make comparison of sort order easier in a for loop
- * 
- * @param n
- *          The number to pad.
- * @param pad
- *          The length to pad up to.
- * @return The padded number as a string.
- */
-private String pad(int n, byte pad) {
-  String res = Integer.toString(n);
-  while (res.length() < pad)
-    res = "0" + res;
-  return res;
-}
+  /**
+   * Padding numbers to make comparison of sort order easier in a for loop
+   *
+   * @param n
+   *          The number to pad.
+   * @param pad
+   *          The length to pad up to.
+   * @return The padded number as a string.
+   */
+  private String pad(int n, byte pad) {
+    String res = Integer.toString(n);
+    while (res.length() < pad) {
+      res = "0" + res;
+    }
+    return res;
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/src/main/asciidoc/_chapters/appendix_acl_matrix.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/_chapters/appendix_acl_matrix.adoc b/src/main/asciidoc/_chapters/appendix_acl_matrix.adoc
index 83043f7..d5ea076 100644
--- a/src/main/asciidoc/_chapters/appendix_acl_matrix.adoc
+++ b/src/main/asciidoc/_chapters/appendix_acl_matrix.adoc
@@ -164,6 +164,17 @@ In case the table goes out of date, the unit tests which check for accuracy of p
 |              | mergeRegions | superuser\|global(A)
 |              | rollWALWriterRequest | superuser\|global(A)
 |              | replicateLogEntries | superuser\|global(W)
+|RSGroup |addRSGroup           |superuser\|global(A)
+|        |balanceRSGroup       |superuser\|global(A)
+|        |getRSGroupInfo       |superuser\|global(A)
+|        |getRSGroupInfoOfTable|superuser\|global(A)
+|        |getRSGroupOfServer   |superuser\|global(A)
+|        |listRSGroups         |superuser\|global(A)
+|        |moveServers          |superuser\|global(A)
+|        |moveServersAndTables |superuser\|global(A)
+|        |moveTables           |superuser\|global(A)
+|        |removeRSGroup        |superuser\|global(A)
+|        |removeServers        |superuser\|global(A)
 |===
 
 :numbered:

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/src/main/asciidoc/_chapters/ops_mgt.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/_chapters/ops_mgt.adoc b/src/main/asciidoc/_chapters/ops_mgt.adoc
index f5fa456..508815f 100644
--- a/src/main/asciidoc/_chapters/ops_mgt.adoc
+++ b/src/main/asciidoc/_chapters/ops_mgt.adoc
@@ -2703,6 +2703,18 @@ Viewing the Master log will give you insight on rsgroup operation.
 
 If it appears stuck, restart the Master process.
 
+=== ACL
+To enable ACL, add the following to your hbase-site.xml and restart your Master:
+
+[source,xml]
+----
+<property>
+  <name>hbase.security.authorization</name>
+  <value>true</value>
+<property>
+----
+
+
 
 [[normalizer]]
 == Region Normalizer

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/src/main/asciidoc/_chapters/security.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/_chapters/security.adoc b/src/main/asciidoc/_chapters/security.adoc
index cca9364..ef7d6c4 100644
--- a/src/main/asciidoc/_chapters/security.adoc
+++ b/src/main/asciidoc/_chapters/security.adoc
@@ -807,6 +807,10 @@ For an example of using both together, see <<security.example.config>>.
 [source,xml]
 ----
 <property>
+  <name>hbase.security.authorization</name>
+  <value>true</value>
+</property>
+<property>
   <name>hbase.coprocessor.region.classes</name>
   <value>org.apache.hadoop.hbase.security.access.AccessController, org.apache.hadoop.hbase.security.token.TokenProvider</value>
 </property>
@@ -1187,6 +1191,10 @@ NOTE: Visibility labels are not currently applied for superusers.
 [source,xml]
 ----
 <property>
+  <name>hbase.security.authorization</name>
+  <value>true</value>
+</property>
+<property>
   <name>hbase.coprocessor.region.classes</name>
   <value>org.apache.hadoop.hbase.security.visibility.VisibilityController</value>
 </property>
@@ -1454,6 +1462,10 @@ As mentioned in the above sections, the interface `VisibilityLabelService` could
 [source,xml]
 ----
 <property>
+  <name>hbase.security.authorization</name>
+  <value>true</value>
+</property>
+<property>
   <name>hbase.coprocessor.regionserver.classes</name>
   <value>org.apache.hadoop.hbase.security.visibility.VisibilityController$VisibilityReplication</value>
 </property>
@@ -1672,6 +1684,10 @@ To enable secure bulk load, add the following properties to _hbase-site.xml_.
 [source,xml]
 ----
 <property>
+  <name>hbase.security.authorization</name>
+  <value>true</value>
+</property>
+<property>
   <name>hbase.bulkload.staging.dir</name>
   <value>/tmp/hbase-staging</value>
 </property>
@@ -1682,6 +1698,22 @@ To enable secure bulk load, add the following properties to _hbase-site.xml_.
 </property>
 ----
 
+[[hbase.secure.enable]]
+=== Secure Enable
+After hbase-2.x, the default 'hbase.security.authorization' changed.
+Before hbase-2.x, it defaulted to true, in later HBase versions, the
+default became false.
+So to enable hbase authorization, the following propertie must be configured in _hbase-site.xml_.
+See link:https://issues.apache.org/jira/browse/HBASE-19483[HBASE-19483];
+
+[source,xml]
+----
+<property>
+  <name>hbase.security.authorization</name>
+  <value>true</value>
+</property>
+----
+
 [[security.example.config]]
 == Security Configuration Example
 
@@ -1704,6 +1736,10 @@ All options have been discussed separately in the sections above.
 </property>
 <!-- Coprocessors for ACLs and Visibility Tags -->
 <property>
+  <name>hbase.security.authorization</name>
+  <value>true</value>
+</property>
+<property>
   <name>hbase.coprocessor.region.classes</name>
   <value>org.apache.hadoop.hbase.security.access.AccessController,
   org.apache.hadoop.hbase.security.visibility.VisibilityController,


[3/3] hbase git commit: HBASE-19483 Add proper privilege check for rsgroup commands

Posted by te...@apache.org.
HBASE-19483 Add proper privilege check for rsgroup commands

Signed-off-by: tedyu <yu...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/fc7736eb
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/fc7736eb
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/fc7736eb

Branch: refs/heads/master
Commit: fc7736eb00bb47d619a1345e32f0136751ea8c0b
Parents: 032fdc5
Author: Guangxu Cheng <gu...@gmail.com>
Authored: Fri Jan 5 23:22:32 2018 +0800
Committer: tedyu <yu...@gmail.com>
Committed: Fri Jan 5 11:18:07 2018 -0800

----------------------------------------------------------------------
 ...tegrationTestIngestWithVisibilityLabels.java |   7 +-
 ...egrationTestBigLinkedListWithVisibility.java |   7 +-
 ...tionTestWithCellVisibilityLoadAndVerify.java |   7 +-
 .../TestImportTSVWithVisibilityLabels.java      |   6 +-
 .../hbase/rest/TestScannersWithLabels.java      |   6 +-
 .../hbase/rsgroup/RSGroupAdminEndpoint.java     | 115 ++-
 .../hadoop/hbase/master/MasterRpcServices.java  |   3 +-
 .../hbase/security/access/AccessChecker.java    | 333 +++++++++
 .../hbase/security/access/AccessController.java | 697 ++++++------------
 .../visibility/VisibilityController.java        |  13 +-
 .../hbase/security/access/SecureTestUtil.java   |   6 +
 .../security/access/TestAccessController.java   |  75 --
 .../security/visibility/VisibilityTestUtil.java |   3 +-
 ...TestThriftHBaseServiceHandlerWithLabels.java | 703 +++++++++----------
 .../asciidoc/_chapters/appendix_acl_matrix.adoc |  11 +
 src/main/asciidoc/_chapters/ops_mgt.adoc        |  12 +
 src/main/asciidoc/_chapters/security.adoc       |  36 +
 17 files changed, 1080 insertions(+), 960 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.java
----------------------------------------------------------------------
diff --git a/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.java b/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.java
index b7d8dad..2928b6d 100644
--- a/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.java
+++ b/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.java
@@ -23,11 +23,10 @@ import java.util.Arrays;
 import java.util.List;
 
 import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.io.hfile.HFile;
 import org.apache.hadoop.hbase.security.User;
 import org.apache.hadoop.hbase.security.visibility.LoadTestDataGeneratorWithVisibilityLabels;
 import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
 import org.apache.hadoop.hbase.testclassification.IntegrationTests;
 import org.apache.hadoop.hbase.util.LoadTestTool;
 import org.junit.experimental.categories.Category;
@@ -76,9 +75,7 @@ public class IntegrationTestIngestWithVisibilityLabels extends IntegrationTestIn
   public void setUpCluster() throws Exception {
     util = getTestingUtil(null);
     Configuration conf = util.getConfiguration();
-    conf.setInt(HFile.FORMAT_VERSION_KEY, 3);
-    conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
-    conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
+    VisibilityTestUtil.enableVisiblityLabels(conf);
     conf.set("hbase.superuser", "admin," + User.getCurrent().getName());
     super.setUpCluster();
     addLabels();

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestBigLinkedListWithVisibility.java
----------------------------------------------------------------------
diff --git a/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestBigLinkedListWithVisibility.java b/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestBigLinkedListWithVisibility.java
index d0e6e52..9349f7b 100644
--- a/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestBigLinkedListWithVisibility.java
+++ b/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestBigLinkedListWithVisibility.java
@@ -47,7 +47,6 @@ import org.apache.hadoop.hbase.client.Put;
 import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-import org.apache.hadoop.hbase.io.hfile.HFile;
 import org.apache.hadoop.hbase.log.HBaseMarkers;
 import org.apache.hadoop.hbase.mapreduce.Import;
 import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
@@ -57,7 +56,7 @@ import org.apache.hadoop.hbase.security.access.Permission;
 import org.apache.hadoop.hbase.security.visibility.Authorizations;
 import org.apache.hadoop.hbase.security.visibility.CellVisibility;
 import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
 import org.apache.hadoop.hbase.testclassification.IntegrationTests;
 import org.apache.hadoop.hbase.util.AbstractHBaseTool;
 import org.apache.hadoop.hbase.util.Bytes;
@@ -373,9 +372,7 @@ public class IntegrationTestBigLinkedListWithVisibility extends IntegrationTestB
   public void setUpCluster() throws Exception {
     util = getTestingUtil(null);
     Configuration conf = util.getConfiguration();
-    conf.setInt(HFile.FORMAT_VERSION_KEY, 3);
-    conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
-    conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
+    VisibilityTestUtil.enableVisiblityLabels(conf);
     conf.set("hbase.superuser", User.getCurrent().getName());
     conf.setBoolean("dfs.permissions", false);
     USER = User.createUserForTesting(conf, userName, new String[] {});

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.java
----------------------------------------------------------------------
diff --git a/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.java b/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.java
index 3f97fbb..32c1ddd 100644
--- a/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.java
+++ b/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.java
@@ -40,7 +40,6 @@ import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.hadoop.hbase.client.ScannerCallable;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-import org.apache.hadoop.hbase.io.hfile.HFile;
 import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
 import org.apache.hadoop.hbase.mapreduce.TableMapper;
 import org.apache.hadoop.hbase.mapreduce.TableRecordReaderImpl;
@@ -48,7 +47,7 @@ import org.apache.hadoop.hbase.security.User;
 import org.apache.hadoop.hbase.security.visibility.Authorizations;
 import org.apache.hadoop.hbase.security.visibility.CellVisibility;
 import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
 import org.apache.hadoop.hbase.testclassification.IntegrationTests;
 import org.apache.hadoop.hbase.util.AbstractHBaseTool;
 import org.apache.hadoop.hbase.util.Bytes;
@@ -116,9 +115,7 @@ public class IntegrationTestWithCellVisibilityLoadAndVerify extends IntegrationT
   public void setUpCluster() throws Exception {
     util = getTestingUtil(null);
     Configuration conf = util.getConfiguration();
-    conf.setInt(HFile.FORMAT_VERSION_KEY, 3);
-    conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
-    conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
+    VisibilityTestUtil.enableVisiblityLabels(conf);
     conf.set("hbase.superuser", User.getCurrent().getName());
     conf.setBoolean("dfs.permissions", false);
     super.setUpCluster();

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestImportTSVWithVisibilityLabels.java
----------------------------------------------------------------------
diff --git a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestImportTSVWithVisibilityLabels.java b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestImportTSVWithVisibilityLabels.java
index 8d3f3df..6d6b729 100644
--- a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestImportTSVWithVisibilityLabels.java
+++ b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestImportTSVWithVisibilityLabels.java
@@ -58,7 +58,7 @@ import org.apache.hadoop.hbase.security.visibility.ScanLabelGenerator;
 import org.apache.hadoop.hbase.security.visibility.SimpleScanLabelGenerator;
 import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
 import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
 import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
 import org.apache.hadoop.hbase.testclassification.LargeTests;
 import org.apache.hadoop.hbase.testclassification.MapReduceTests;
@@ -121,9 +121,7 @@ public class TestImportTSVWithVisibilityLabels implements Configurable {
     conf = util.getConfiguration();
     SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
     conf.set("hbase.superuser", "admin,"+User.getCurrent().getName());
-    conf.setInt("hfile.format.version", 3);
-    conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
-    conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
+    VisibilityTestUtil.enableVisiblityLabels(conf);
     conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
         ScanLabelGenerator.class);
     util.startMiniCluster();

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithLabels.java
----------------------------------------------------------------------
diff --git a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithLabels.java b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithLabels.java
index 6ac8e87..8d738ed 100644
--- a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithLabels.java
+++ b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithLabels.java
@@ -43,7 +43,7 @@ import org.apache.hadoop.hbase.security.visibility.ScanLabelGenerator;
 import org.apache.hadoop.hbase.security.visibility.SimpleScanLabelGenerator;
 import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
 import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
 import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
 import org.apache.hadoop.hbase.testclassification.MediumTests;
 import org.apache.hadoop.hbase.testclassification.RestTests;
@@ -130,10 +130,8 @@ public class TestScannersWithLabels {
     conf = TEST_UTIL.getConfiguration();
     conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS,
         SimpleScanLabelGenerator.class, ScanLabelGenerator.class);
-    conf.setInt("hfile.format.version", 3);
     conf.set("hbase.superuser", SUPERUSER.getShortName());
-    conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
-    conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
+    VisibilityTestUtil.enableVisiblityLabels(conf);
     TEST_UTIL.startMiniCluster(1);
     // Wait for the labels table to become available
     TEST_UTIL.waitTableEnabled(VisibilityConstants.LABELS_TABLE_NAME.getName(), 50000);

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java
----------------------------------------------------------------------
diff --git a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java
index 7e148e0..964b5da 100644
--- a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java
+++ b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java
@@ -46,6 +46,7 @@ import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
 import org.apache.hadoop.hbase.coprocessor.MasterObserver;
 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
 import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
+import org.apache.hadoop.hbase.ipc.RpcServer;
 import org.apache.hadoop.hbase.master.MasterServices;
 import org.apache.hadoop.hbase.net.Address;
 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
@@ -74,6 +75,11 @@ import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveRSGro
 import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupResponse;
 import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest;
 import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersResponse;
+import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.security.UserProvider;
+import org.apache.hadoop.hbase.security.access.AccessChecker;
+import org.apache.hadoop.hbase.security.access.Permission.Action;
+import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
 import org.apache.yetus.audience.InterfaceAudience;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -92,12 +98,17 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
   private RSGroupInfoManager groupInfoManager;
   private RSGroupAdminServer groupAdminServer;
   private final RSGroupAdminService groupAdminService = new RSGroupAdminServiceImpl();
+  private AccessChecker accessChecker;
+
+  /** Provider for mapping principal names to Users */
+  private UserProvider userProvider;
 
   @Override
   public void start(CoprocessorEnvironment env) throws IOException {
     if (!(env instanceof HasMasterServices)) {
       throw new IOException("Does not implement HMasterServices");
     }
+
     master = ((HasMasterServices)env).getMasterServices();
     groupInfoManager = RSGroupInfoManagerImpl.getInstance(master);
     groupAdminServer = new RSGroupAdminServer(master, groupInfoManager);
@@ -106,6 +117,11 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
     if (!RSGroupableBalancer.class.isAssignableFrom(clazz)) {
       throw new IOException("Configured balancer does not support RegionServer groups.");
     }
+    ZKWatcher zk = ((HasMasterServices)env).getMasterServices().getZooKeeper();
+    accessChecker = new AccessChecker(env.getConfiguration(), zk);
+
+    // set the user-provider.
+    this.userProvider = UserProvider.instantiate(env.getConfiguration());
   }
 
   @Override
@@ -137,6 +153,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
       LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, group="
               + groupName);
       try {
+        checkPermission("getRSGroupInfo");
         RSGroupInfo rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName);
         if (rsGroupInfo != null) {
           builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(rsGroupInfo));
@@ -151,10 +168,11 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
     public void getRSGroupInfoOfTable(RpcController controller,
         GetRSGroupInfoOfTableRequest request, RpcCallback<GetRSGroupInfoOfTableResponse> done) {
       GetRSGroupInfoOfTableResponse.Builder builder = GetRSGroupInfoOfTableResponse.newBuilder();
+      TableName tableName = ProtobufUtil.toTableName(request.getTableName());
+      LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, table="
+          + tableName);
       try {
-        TableName tableName = ProtobufUtil.toTableName(request.getTableName());
-        LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, table="
-                + tableName);
+        checkPermission("getRSGroupInfoOfTable");
         RSGroupInfo RSGroupInfo = groupAdminServer.getRSGroupInfoOfTable(tableName);
         if (RSGroupInfo != null) {
           builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
@@ -169,13 +187,14 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
     public void moveServers(RpcController controller, MoveServersRequest request,
         RpcCallback<MoveServersResponse> done) {
       MoveServersResponse.Builder builder = MoveServersResponse.newBuilder();
+      Set<Address> hostPorts = Sets.newHashSet();
+      for (HBaseProtos.ServerName el : request.getServersList()) {
+        hostPorts.add(Address.fromParts(el.getHostName(), el.getPort()));
+      }
+      LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts +" to rsgroup "
+          + request.getTargetGroup());
       try {
-        Set<Address> hostPorts = Sets.newHashSet();
-        for (HBaseProtos.ServerName el : request.getServersList()) {
-          hostPorts.add(Address.fromParts(el.getHostName(), el.getPort()));
-        }
-        LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts +" to rsgroup "
-                + request.getTargetGroup());
+        checkPermission("moveServers");
         groupAdminServer.moveServers(hostPorts, request.getTargetGroup());
       } catch (IOException e) {
         CoprocessorRpcUtils.setControllerException(controller, e);
@@ -187,13 +206,14 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
     public void moveTables(RpcController controller, MoveTablesRequest request,
         RpcCallback<MoveTablesResponse> done) {
       MoveTablesResponse.Builder builder = MoveTablesResponse.newBuilder();
+      Set<TableName> tables = new HashSet<>(request.getTableNameList().size());
+      for (HBaseProtos.TableName tableName : request.getTableNameList()) {
+        tables.add(ProtobufUtil.toTableName(tableName));
+      }
+      LOG.info(master.getClientIdAuditPrefix() + " move tables " + tables +" to rsgroup "
+          + request.getTargetGroup());
       try {
-        Set<TableName> tables = new HashSet<>(request.getTableNameList().size());
-        for (HBaseProtos.TableName tableName : request.getTableNameList()) {
-          tables.add(ProtobufUtil.toTableName(tableName));
-        }
-        LOG.info(master.getClientIdAuditPrefix() + " move tables " + tables +" to rsgroup "
-                + request.getTargetGroup());
+        checkPermission("moveTables");
         groupAdminServer.moveTables(tables, request.getTargetGroup());
       } catch (IOException e) {
         CoprocessorRpcUtils.setControllerException(controller, e);
@@ -207,6 +227,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
       AddRSGroupResponse.Builder builder = AddRSGroupResponse.newBuilder();
       LOG.info(master.getClientIdAuditPrefix() + " add rsgroup " + request.getRSGroupName());
       try {
+        checkPermission("addRSGroup");
         groupAdminServer.addRSGroup(request.getRSGroupName());
       } catch (IOException e) {
         CoprocessorRpcUtils.setControllerException(controller, e);
@@ -221,6 +242,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
           RemoveRSGroupResponse.newBuilder();
       LOG.info(master.getClientIdAuditPrefix() + " remove rsgroup " + request.getRSGroupName());
       try {
+        checkPermission("removeRSGroup");
         groupAdminServer.removeRSGroup(request.getRSGroupName());
       } catch (IOException e) {
         CoprocessorRpcUtils.setControllerException(controller, e);
@@ -235,6 +257,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
       LOG.info(master.getClientIdAuditPrefix() + " balance rsgroup, group=" +
               request.getRSGroupName());
       try {
+        checkPermission("balanceRSGroup");
         builder.setBalanceRan(groupAdminServer.balanceRSGroup(request.getRSGroupName()));
       } catch (IOException e) {
         CoprocessorRpcUtils.setControllerException(controller, e);
@@ -249,6 +272,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
       ListRSGroupInfosResponse.Builder builder = ListRSGroupInfosResponse.newBuilder();
       LOG.info(master.getClientIdAuditPrefix() + " list rsgroup");
       try {
+        checkPermission("listRSGroup");
         for (RSGroupInfo RSGroupInfo : groupAdminServer.listRSGroups()) {
           builder.addRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
         }
@@ -262,11 +286,12 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
     public void getRSGroupInfoOfServer(RpcController controller,
         GetRSGroupInfoOfServerRequest request, RpcCallback<GetRSGroupInfoOfServerResponse> done) {
       GetRSGroupInfoOfServerResponse.Builder builder = GetRSGroupInfoOfServerResponse.newBuilder();
+      Address hp = Address.fromParts(request.getServer().getHostName(),
+          request.getServer().getPort());
+      LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, server="
+          + hp);
       try {
-        Address hp = Address.fromParts(request.getServer().getHostName(),
-            request.getServer().getPort());
-        LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, server=" +
-                hp);
+        checkPermission("getRSGroupInfoOfServer");
         RSGroupInfo RSGroupInfo = groupAdminServer.getRSGroupOfServer(hp);
         if (RSGroupInfo != null) {
           builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
@@ -281,17 +306,18 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
     public void moveServersAndTables(RpcController controller,
         MoveServersAndTablesRequest request, RpcCallback<MoveServersAndTablesResponse> done) {
       MoveServersAndTablesResponse.Builder builder = MoveServersAndTablesResponse.newBuilder();
+      Set<Address> hostPorts = Sets.newHashSet();
+      for (HBaseProtos.ServerName el : request.getServersList()) {
+        hostPorts.add(Address.fromParts(el.getHostName(), el.getPort()));
+      }
+      Set<TableName> tables = new HashSet<>(request.getTableNameList().size());
+      for (HBaseProtos.TableName tableName : request.getTableNameList()) {
+        tables.add(ProtobufUtil.toTableName(tableName));
+      }
+      LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts
+          + " and tables " + tables + " to rsgroup" + request.getTargetGroup());
       try {
-        Set<Address> hostPorts = Sets.newHashSet();
-        for (HBaseProtos.ServerName el : request.getServersList()) {
-          hostPorts.add(Address.fromParts(el.getHostName(), el.getPort()));
-        }
-        Set<TableName> tables = new HashSet<>(request.getTableNameList().size());
-        for (HBaseProtos.TableName tableName : request.getTableNameList()) {
-          tables.add(ProtobufUtil.toTableName(tableName));
-        }
-        LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts
-                + " and tables " + tables + " to rsgroup" + request.getTargetGroup());
+        checkPermission("moveServersAndTables");
         groupAdminServer.moveServersAndTables(hostPorts, tables, request.getTargetGroup());
       } catch (IOException e) {
         CoprocessorRpcUtils.setControllerException(controller, e);
@@ -305,13 +331,14 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
         RpcCallback<RemoveServersResponse> done) {
       RemoveServersResponse.Builder builder =
           RemoveServersResponse.newBuilder();
+      Set<Address> servers = Sets.newHashSet();
+      for (HBaseProtos.ServerName el : request.getServersList()) {
+        servers.add(Address.fromParts(el.getHostName(), el.getPort()));
+      }
+      LOG.info(master.getClientIdAuditPrefix()
+          + " remove decommissioned servers from rsgroup: " + servers);
       try {
-        Set<Address> servers = Sets.newHashSet();
-        for (HBaseProtos.ServerName el : request.getServersList()) {
-          servers.add(Address.fromParts(el.getHostName(), el.getPort()));
-        }
-        LOG.info(master.getClientIdAuditPrefix()
-            + " remove decommissioned servers from rsgroup: " + servers);
+        checkPermission("removeServers");
         groupAdminServer.removeServers(servers);
       } catch (IOException e) {
         CoprocessorRpcUtils.setControllerException(controller, e);
@@ -397,5 +424,21 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
     groupAdminServer.removeServers(clearedServer);
   }
 
-  /////////////////////////////////////////////////////////////////////////////
+  private void checkPermission(String request) throws IOException {
+    accessChecker.requirePermission(getActiveUser(), request, Action.ADMIN);
+  }
+
+  /**
+   * Returns the active user to which authorization checks should be applied.
+   * If we are in the context of an RPC call, the remote user is used,
+   * otherwise the currently logged in user is used.
+   */
+  public User getActiveUser() throws IOException {
+    // for non-rpc handling, fallback to system user
+    Optional<User> optionalUser = RpcServer.getRequestUser();
+    if (optionalUser.isPresent()) {
+      return optionalUser.get();
+    }
+    return userProvider.getCurrent();
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
index 8f41e4f..907ca9b 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
@@ -83,6 +83,7 @@ import org.apache.hadoop.hbase.replication.ReplicationException;
 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
 import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
 import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.security.access.AccessChecker;
 import org.apache.hadoop.hbase.security.access.AccessController;
 import org.apache.hadoop.hbase.security.visibility.VisibilityController;
 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
@@ -1810,7 +1811,7 @@ public class MasterRpcServices extends RSRpcServices
       // A coprocessor that implements AccessControlService can provide AUTHORIZATION and
       // CELL_AUTHORIZATION
       if (master.cpHost != null && hasAccessControlServiceCoprocessor(master.cpHost)) {
-        if (AccessController.isAuthorizationSupported(master.getConfiguration())) {
+        if (AccessChecker.isAuthorizationSupported(master.getConfiguration())) {
           capabilities.add(SecurityCapabilitiesResponse.Capability.AUTHORIZATION);
         }
         if (AccessController.isCellAuthorizationSupported(master.getConfiguration())) {

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java
new file mode 100644
index 0000000..2a7373e
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java
@@ -0,0 +1,333 @@
+/*
+ * 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.security.access;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.DoNotRetryIOException;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.RegionInfo;
+import org.apache.hadoop.hbase.ipc.RpcServer;
+import org.apache.hadoop.hbase.security.AccessDeniedException;
+import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.security.access.Permission.Action;
+import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@InterfaceAudience.Private
+public final class AccessChecker {
+  private static final Logger AUDITLOG =
+      LoggerFactory.getLogger("SecurityLogger." + AccessChecker.class.getName());
+  private TableAuthManager authManager;
+  /**
+   * if we are active, usually false, only true if "hbase.security.authorization"
+   * has been set to true in site configuration.see HBASE-19483.
+   */
+  private boolean authorizationEnabled;
+
+  public static boolean isAuthorizationSupported(Configuration conf) {
+    return conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false);
+  }
+
+  /**
+   * Constructor with existing configuration
+   *
+   * @param conf Existing configuration to use
+   * @param zkw reference to the {@link ZKWatcher}
+   * @return the AccessChecker instance
+   */
+  public AccessChecker(final Configuration conf, final ZKWatcher zkw)
+      throws RuntimeException {
+    // If zk is null or IOException while obtaining auth manager,
+    // throw RuntimeException so that the coprocessor is unloaded.
+    if (zkw != null) {
+      try {
+        this.authManager = TableAuthManager.getOrCreate(zkw, conf);
+      } catch (IOException ioe) {
+        throw new RuntimeException("Error obtaining AccessChecker", ioe);
+      }
+    } else {
+      throw new NullPointerException("Error obtaining AccessChecker, zk found null.");
+    }
+    authorizationEnabled = isAuthorizationSupported(conf);
+  }
+
+  public TableAuthManager getAuthManager() {
+    return authManager;
+  }
+
+  /**
+   * Authorizes that the current user has any of the given permissions to access the table.
+   *
+   * @param tableName   Table requested
+   * @param permissions Actions being requested
+   * @throws IOException           if obtaining the current user fails
+   * @throws AccessDeniedException if user has no authorization
+   */
+  public void requireAccess(User user, String request, TableName tableName,
+      Action... permissions) throws IOException {
+    AuthResult result = null;
+
+    for (Action permission : permissions) {
+      if (authManager.hasAccess(user, tableName, permission)) {
+        result = AuthResult.allow(request, "Table permission granted",
+            user, permission, tableName, null, null);
+        break;
+      } else {
+        // rest of the world
+        result = AuthResult.deny(request, "Insufficient permissions",
+            user, permission, tableName, null, null);
+      }
+    }
+    logResult(result);
+    if (authorizationEnabled && !result.isAllowed()) {
+      throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
+    }
+  }
+
+  /**
+   * Authorizes that the current user has global privileges for the given action.
+   *
+   * @param perm The action being requested
+   * @throws IOException           if obtaining the current user fails
+   * @throws AccessDeniedException if authorization is denied
+   */
+  public void requirePermission(User user, String request, Action perm)
+      throws IOException {
+    requireGlobalPermission(user, request, perm, null, null);
+  }
+
+  /**
+   * Checks that the user has the given global permission. The generated
+   * audit log message will contain context information for the operation
+   * being authorized, based on the given parameters.
+   *
+   * @param perm      Action being requested
+   * @param tableName Affected table name.
+   * @param familyMap Affected column families.
+   */
+  public void requireGlobalPermission(User user, String request,
+      Action perm, TableName tableName,
+      Map<byte[], ? extends Collection<byte[]>> familyMap)throws IOException {
+    AuthResult result;
+    if (authManager.authorize(user, perm)) {
+      result = AuthResult.allow(request, "Global check allowed",
+          user, perm, tableName, familyMap);
+      result.getParams().setTableName(tableName).setFamilies(familyMap);
+      logResult(result);
+    } else {
+      result = AuthResult.deny(request, "Global check failed",
+          user, perm, tableName, familyMap);
+      result.getParams().setTableName(tableName).setFamilies(familyMap);
+      logResult(result);
+      if (authorizationEnabled) {
+        throw new AccessDeniedException(
+            "Insufficient permissions for user '" + (user != null ? user.getShortName() : "null")
+                + "' (global, action=" + perm.toString() + ")");
+      }
+    }
+  }
+
+  /**
+   * Checks that the user has the given global permission. The generated
+   * audit log message will contain context information for the operation
+   * being authorized, based on the given parameters.
+   *
+   * @param perm      Action being requested
+   * @param namespace The given namespace
+   */
+  public void requireGlobalPermission(User user, String request, Action perm,
+      String namespace) throws IOException {
+    AuthResult authResult;
+    if (authManager.authorize(user, perm)) {
+      authResult = AuthResult.allow(request, "Global check allowed",
+          user, perm, null);
+      authResult.getParams().setNamespace(namespace);
+      logResult(authResult);
+    } else {
+      authResult = AuthResult.deny(request, "Global check failed",
+          user, perm, null);
+      authResult.getParams().setNamespace(namespace);
+      logResult(authResult);
+      if (authorizationEnabled) {
+        throw new AccessDeniedException(
+            "Insufficient permissions for user '" + (user != null ? user.getShortName() : "null")
+                + "' (global, action=" + perm.toString() + ")");
+      }
+    }
+  }
+
+  /**
+   * Checks that the user has the given global or namespace permission.
+   *
+   * @param namespace  The given namespace
+   * @param permissions Actions being requested
+   */
+  public void requireNamespacePermission(User user, String request, String namespace,
+      Action... permissions) throws IOException {
+    AuthResult result = null;
+
+    for (Action permission : permissions) {
+      if (authManager.authorize(user, namespace, permission)) {
+        result =
+            AuthResult.allow(request, "Namespace permission granted",
+                user, permission, namespace);
+        break;
+      } else {
+        // rest of the world
+        result = AuthResult.deny(request, "Insufficient permissions",
+            user, permission, namespace);
+      }
+    }
+    logResult(result);
+    if (authorizationEnabled && !result.isAllowed()) {
+      throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
+    }
+  }
+
+  /**
+   * Checks that the user has the given global or namespace permission.
+   *
+   * @param namespace  The given namespace
+   * @param permissions Actions being requested
+   */
+  public void requireNamespacePermission(User user, String request, String namespace,
+      TableName tableName, Map<byte[], ? extends Collection<byte[]>> familyMap,
+      Action... permissions) throws IOException {
+    AuthResult result = null;
+
+    for (Action permission : permissions) {
+      if (authManager.authorize(user, namespace, permission)) {
+        result =
+            AuthResult.allow(request, "Namespace permission granted",
+                user, permission, namespace);
+        result.getParams().setTableName(tableName).setFamilies(familyMap);
+        break;
+      } else {
+        // rest of the world
+        result = AuthResult.deny(request, "Insufficient permissions",
+            user, permission, namespace);
+        result.getParams().setTableName(tableName).setFamilies(familyMap);
+      }
+    }
+    logResult(result);
+    if (authorizationEnabled && !result.isAllowed()) {
+      throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
+    }
+  }
+
+  /**
+   * Authorizes that the current user has any of the given permissions for the
+   * given table, column family and column qualifier.
+   *
+   * @param tableName Table requested
+   * @param family    Column family requested
+   * @param qualifier Column qualifier requested
+   * @throws IOException           if obtaining the current user fails
+   * @throws AccessDeniedException if user has no authorization
+   */
+  public void requirePermission(User user, String request, TableName tableName, byte[] family,
+      byte[] qualifier, Action... permissions) throws IOException {
+    AuthResult result = null;
+
+    for (Action permission : permissions) {
+      if (authManager.authorize(user, tableName, family, qualifier, permission)) {
+        result = AuthResult.allow(request, "Table permission granted",
+            user, permission, tableName, family,
+                qualifier);
+        break;
+      } else {
+        // rest of the world
+        result = AuthResult.deny(request, "Insufficient permissions",
+                user, permission, tableName, family,
+                qualifier);
+      }
+    }
+    logResult(result);
+    if (authorizationEnabled && !result.isAllowed()) {
+      throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
+    }
+  }
+
+  /**
+   * Authorizes that the current user has any of the given permissions for the
+   * given table, column family and column qualifier.
+   *
+   * @param tableName Table requested
+   * @param family    Column family param
+   * @param qualifier Column qualifier param
+   * @throws IOException           if obtaining the current user fails
+   * @throws AccessDeniedException if user has no authorization
+   */
+  public void requireTablePermission(User user, String request,
+      TableName tableName,byte[] family, byte[] qualifier,
+      Action... permissions) throws IOException {
+    AuthResult result = null;
+
+    for (Action permission : permissions) {
+      if (authManager.authorize(user, tableName, null, null, permission)) {
+        result = AuthResult.allow(request, "Table permission granted",
+            user, permission, tableName, null, null);
+        result.getParams().setFamily(family).setQualifier(qualifier);
+        break;
+      } else {
+        // rest of the world
+        result = AuthResult.deny(request, "Insufficient permissions",
+                user, permission, tableName, family, qualifier);
+        result.getParams().setFamily(family).setQualifier(qualifier);
+      }
+    }
+    logResult(result);
+    if (authorizationEnabled && !result.isAllowed()) {
+      throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
+    }
+  }
+
+  public void checkLockPermissions(User user, String namespace,
+      TableName tableName, RegionInfo[] regionInfos, String reason)
+      throws IOException {
+    if (namespace != null && !namespace.isEmpty()) {
+      requireNamespacePermission(user, reason, namespace, Action.ADMIN, Action.CREATE);
+    } else if (tableName != null || (regionInfos != null && regionInfos.length > 0)) {
+      // So, either a table or regions op. If latter, check perms ons table.
+      TableName tn = tableName != null? tableName: regionInfos[0].getTable();
+      requireTablePermission(user, reason, tn, null, null,
+          Action.ADMIN, Action.CREATE);
+    } else {
+      throw new DoNotRetryIOException("Invalid lock level when requesting permissions.");
+    }
+  }
+
+  public static void logResult(AuthResult result) {
+    if (AUDITLOG.isTraceEnabled()) {
+      AUDITLOG.trace("Access " + (result.isAllowed() ? "allowed" : "denied") + " for user " + (
+          result.getUser() != null ?
+              result.getUser().getShortName() :
+              "UNKNOWN") + "; reason: " + result.getReason() + "; remote address: "
+          + RpcServer.getRemoteAddress().map(InetAddress::toString).orElse("")
+          + "; request: " + result.getRequest() + "; context: " + result.toContextString());
+    }
+  }
+}
\ No newline at end of file


[2/3] hbase git commit: HBASE-19483 Add proper privilege check for rsgroup commands

Posted by te...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
index 602af91..5a3c883 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
@@ -23,7 +23,6 @@ import com.google.protobuf.RpcCallback;
 import com.google.protobuf.RpcController;
 import com.google.protobuf.Service;
 import java.io.IOException;
-import java.net.InetAddress;
 import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -96,7 +95,6 @@ import org.apache.hadoop.hbase.filter.FilterList;
 import org.apache.hadoop.hbase.io.hfile.HFile;
 import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
 import org.apache.hadoop.hbase.ipc.RpcServer;
-import org.apache.hadoop.hbase.net.Address;
 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
@@ -186,10 +184,10 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   private static final String TAG_CHECK_PASSED = "tag_check_passed";
   private static final byte[] TRUE = Bytes.toBytes(true);
 
-  TableAuthManager authManager = null;
+  private AccessChecker accessChecker;
 
   /** flags if we are running on a region of the _acl_ table */
-  boolean aclRegion = false;
+  private boolean aclRegion = false;
 
   /** defined only for Endpoint implementation, so it can have way to
    access region services */
@@ -204,19 +202,19 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   /** Provider for mapping principal names to Users */
   private UserProvider userProvider;
 
-  /** if we are active, usually true, only not true if "hbase.security.authorization"
-   has been set to false in site configuration */
-  boolean authorizationEnabled;
+  /** if we are active, usually false, only true if "hbase.security.authorization"
+   has been set to true in site configuration */
+  private boolean authorizationEnabled;
 
   /** if we are able to support cell ACLs */
-  boolean cellFeaturesEnabled;
+  private boolean cellFeaturesEnabled;
 
   /** if we should check EXEC permissions */
-  boolean shouldCheckExecPermission;
+  private boolean shouldCheckExecPermission;
 
   /** if we should terminate access checks early as soon as table or CF grants
     allow access; pre-0.98 compatible behavior */
-  boolean compatibleEarlyTermination;
+  private boolean compatibleEarlyTermination;
 
   /** if we have been successfully initialized */
   private volatile boolean initialized = false;
@@ -224,12 +222,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   /** if the ACL table is available, only relevant in the master */
   private volatile boolean aclTabAvailable = false;
 
-  public static boolean isAuthorizationSupported(Configuration conf) {
-    return conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
-  }
-
   public static boolean isCellAuthorizationSupported(Configuration conf) {
-    return isAuthorizationSupported(conf) &&
+    return AccessChecker.isAuthorizationSupported(conf) &&
         (HFile.getFormatVersion(conf) >= HFile.MIN_FORMAT_VERSION_WITH_TAGS);
   }
 
@@ -238,10 +232,10 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   }
 
   public TableAuthManager getAuthManager() {
-    return authManager;
+    return accessChecker.getAuthManager();
   }
 
-  void initialize(RegionCoprocessorEnvironment e) throws IOException {
+  private void initialize(RegionCoprocessorEnvironment e) throws IOException {
     final Region region = e.getRegion();
     Configuration conf = e.getConfiguration();
     Map<byte[], ListMultimap<String,TablePermission>> tables =
@@ -253,7 +247,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       byte[] entry = t.getKey();
       ListMultimap<String,TablePermission> perms = t.getValue();
       byte[] serialized = AccessControlLists.writePermissionsAsBytes(perms, conf);
-      this.authManager.getZKPermissionWatcher().writeToZookeeper(entry, serialized);
+      getAuthManager().getZKPermissionWatcher().writeToZookeeper(entry, serialized);
     }
     initialized = true;
   }
@@ -263,7 +257,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
    * znodes.  This is called to synchronize ACL changes following {@code _acl_}
    * table updates.
    */
-  void updateACL(RegionCoprocessorEnvironment e,
+  private void updateACL(RegionCoprocessorEnvironment e,
       final Map<byte[], List<Cell>> familyMap) {
     Set<byte[]> entries = new TreeSet<>(Bytes.BYTES_RAWCOMPARATOR);
     for (Map.Entry<byte[], List<Cell>> f : familyMap.entrySet()) {
@@ -274,7 +268,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         }
       }
     }
-    ZKPermissionWatcher zkw = this.authManager.getZKPermissionWatcher();
+    ZKPermissionWatcher zkw = getAuthManager().getZKPermissionWatcher();
     Configuration conf = regionEnv.getConfiguration();
     byte [] currentEntry = null;
     // TODO: Here we are already on the ACL region. (And it is single
@@ -312,7 +306,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
    * the request
    * @return an authorization result
    */
-  AuthResult permissionGranted(String request, User user, Action permRequest,
+  private AuthResult permissionGranted(String request, User user, Action permRequest,
       RegionCoprocessorEnvironment e,
       Map<byte [], ? extends Collection<?>> families) {
     RegionInfo hri = e.getRegion().getRegionInfo();
@@ -333,7 +327,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     }
 
     // 2. check for the table-level, if successful we can short-circuit
-    if (authManager.authorize(user, tableName, (byte[])null, permRequest)) {
+    if (getAuthManager().authorize(user, tableName, (byte[])null, permRequest)) {
       return AuthResult.allow(request, "Table permission granted", user,
         permRequest, tableName, families);
     }
@@ -343,7 +337,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       // all families must pass
       for (Map.Entry<byte [], ? extends Collection<?>> family : families.entrySet()) {
         // a) check for family level access
-        if (authManager.authorize(user, tableName, family.getKey(),
+        if (getAuthManager().authorize(user, tableName, family.getKey(),
             permRequest)) {
           continue;  // family-level permission overrides per-qualifier
         }
@@ -354,7 +348,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
             // for each qualifier of the family
             Set<byte[]> familySet = (Set<byte[]>)family.getValue();
             for (byte[] qualifier : familySet) {
-              if (!authManager.authorize(user, tableName, family.getKey(),
+              if (!getAuthManager().authorize(user, tableName, family.getKey(),
                                          qualifier, permRequest)) {
                 return AuthResult.deny(request, "Failed qualifier check", user,
                     permRequest, tableName, makeFamilyMap(family.getKey(), qualifier));
@@ -363,7 +357,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
           } else if (family.getValue() instanceof List) { // List<Cell>
             List<Cell> cellList = (List<Cell>)family.getValue();
             for (Cell cell : cellList) {
-              if (!authManager.authorize(user, tableName, family.getKey(),
+              if (!getAuthManager().authorize(user, tableName, family.getKey(),
                 CellUtil.cloneQualifier(cell), permRequest)) {
                 return AuthResult.deny(request, "Failed qualifier check", user, permRequest,
                   tableName, makeFamilyMap(family.getKey(), CellUtil.cloneQualifier(cell)));
@@ -398,7 +392,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
    * @param actions the desired actions
    * @return an authorization result
    */
-  AuthResult permissionGranted(OpType opType, User user, RegionCoprocessorEnvironment e,
+  private AuthResult permissionGranted(OpType opType, User user, RegionCoprocessorEnvironment e,
       Map<byte [], ? extends Collection<?>> families, Action... actions) {
     AuthResult result = null;
     for (Action action: actions) {
@@ -410,241 +404,61 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     return result;
   }
 
-  private void logResult(AuthResult result) {
-    if (AUDITLOG.isTraceEnabled()) {
-      AUDITLOG.trace("Access " + (result.isAllowed() ? "allowed" : "denied") + " for user " +
-          (result.getUser() != null ? result.getUser().getShortName() : "UNKNOWN") + "; reason: " +
-          result.getReason() + "; remote address: " +
-          RpcServer.getRemoteAddress().map(InetAddress::toString).orElse("") + "; request: " +
-          result.getRequest() + "; context: " + result.toContextString());
-    }
+  public void requireAccess(ObserverContext<?> ctx, String request, TableName tableName,
+      Action... permissions) throws IOException {
+    accessChecker.requireAccess(getActiveUser(ctx), request, tableName, permissions);
   }
 
-  /**
-   * Returns the active user to which authorization checks should be applied.
-   * If we are in the context of an RPC call, the remote user is used,
-   * otherwise the currently logged in user is used.
-   */
-  private User getActiveUser(ObserverContext<?> ctx) throws IOException {
-    // for non-rpc handling, fallback to system user
-    Optional<User> optionalUser = ctx.getCaller();
-    User user;
-    if (optionalUser.isPresent()) {
-      return optionalUser.get();
-    }
-    return userProvider.getCurrent();
+  public void requirePermission(ObserverContext<?> ctx, String request,
+      Action perm) throws IOException {
+    accessChecker.requirePermission(getActiveUser(ctx), request, perm);
   }
 
-  /**
-   * Authorizes that the current user has any of the given permissions for the
-   * given table, column family and column qualifier.
-   * @param tableName Table requested
-   * @param family Column family requested
-   * @param qualifier Column qualifier requested
-   * @throws IOException if obtaining the current user fails
-   * @throws AccessDeniedException if user has no authorization
-   */
-  private void requirePermission(User user, String request, TableName tableName, byte[] family,
-      byte[] qualifier, Action... permissions) throws IOException {
-    AuthResult result = null;
-
-    for (Action permission : permissions) {
-      if (authManager.authorize(user, tableName, family, qualifier, permission)) {
-        result = AuthResult.allow(request, "Table permission granted", user,
-                                  permission, tableName, family, qualifier);
-        break;
-      } else {
-        // rest of the world
-        result = AuthResult.deny(request, "Insufficient permissions", user,
-                                 permission, tableName, family, qualifier);
-      }
-    }
-    logResult(result);
-    if (authorizationEnabled && !result.isAllowed()) {
-      throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
-    }
+  public void requireGlobalPermission(ObserverContext<?> ctx, String request,
+      Action perm, TableName tableName,
+      Map<byte[], ? extends Collection<byte[]>> familyMap) throws IOException {
+    accessChecker.requireGlobalPermission(getActiveUser(ctx),
+        request, perm,tableName, familyMap);
   }
 
-  /**
-   * Authorizes that the current user has any of the given permissions for the
-   * given table, column family and column qualifier.
-   * @param tableName Table requested
-   * @param family Column family param
-   * @param qualifier Column qualifier param
-   * @throws IOException if obtaining the current user fails
-   * @throws AccessDeniedException if user has no authorization
-   */
-  private void requireTablePermission(User user, String request, TableName tableName, byte[] family,
-      byte[] qualifier, Action... permissions) throws IOException {
-    AuthResult result = null;
-
-    for (Action permission : permissions) {
-      if (authManager.authorize(user, tableName, null, null, permission)) {
-        result = AuthResult.allow(request, "Table permission granted", user,
-            permission, tableName, null, null);
-        result.getParams().setFamily(family).setQualifier(qualifier);
-        break;
-      } else {
-        // rest of the world
-        result = AuthResult.deny(request, "Insufficient permissions", user,
-            permission, tableName, family, qualifier);
-        result.getParams().setFamily(family).setQualifier(qualifier);
-      }
-    }
-    logResult(result);
-    if (authorizationEnabled && !result.isAllowed()) {
-      throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
-    }
+  public void requireGlobalPermission(ObserverContext<?> ctx, String request,
+      Action perm, String namespace) throws IOException {
+    accessChecker.requireGlobalPermission(getActiveUser(ctx),
+        request, perm, namespace);
   }
 
-  /**
-   * Authorizes that the current user has any of the given permissions to access the table.
-   *
-   * @param tableName Table requested
-   * @param permissions Actions being requested
-   * @throws IOException if obtaining the current user fails
-   * @throws AccessDeniedException if user has no authorization
-   */
-  private void requireAccess(User user, String request, TableName tableName,
+  public void requireNamespacePermission(ObserverContext<?> ctx, String request, String namespace,
       Action... permissions) throws IOException {
-    AuthResult result = null;
-
-    for (Action permission : permissions) {
-      if (authManager.hasAccess(user, tableName, permission)) {
-        result = AuthResult.allow(request, "Table permission granted", user,
-                                  permission, tableName, null, null);
-        break;
-      } else {
-        // rest of the world
-        result = AuthResult.deny(request, "Insufficient permissions", user,
-                                 permission, tableName, null, null);
-      }
-    }
-    logResult(result);
-    if (authorizationEnabled && !result.isAllowed()) {
-      throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
-    }
+    accessChecker.requireNamespacePermission(getActiveUser(ctx),
+        request, namespace, permissions);
   }
 
-  /**
-   * Authorizes that the current user has global privileges for the given action.
-   * @param perm The action being requested
-   * @throws IOException if obtaining the current user fails
-   * @throws AccessDeniedException if authorization is denied
-   */
-  private void requirePermission(User user, String request, Action perm) throws IOException {
-    requireGlobalPermission(user, request, perm, null, null);
-  }
-
-  /**
-   * Checks that the user has the given global permission. The generated
-   * audit log message will contain context information for the operation
-   * being authorized, based on the given parameters.
-   * @param perm Action being requested
-   * @param tableName Affected table name.
-   * @param familyMap Affected column families.
-   */
-  private void requireGlobalPermission(User user, String request, Action perm, TableName tableName,
-      Map<byte[], ? extends Collection<byte[]>> familyMap) throws IOException {
-    AuthResult result = null;
-    if (authManager.authorize(user, perm)) {
-      result = AuthResult.allow(request, "Global check allowed", user, perm, tableName, familyMap);
-      result.getParams().setTableName(tableName).setFamilies(familyMap);
-      logResult(result);
-    } else {
-      result = AuthResult.deny(request, "Global check failed", user, perm, tableName, familyMap);
-      result.getParams().setTableName(tableName).setFamilies(familyMap);
-      logResult(result);
-      if (authorizationEnabled) {
-        throw new AccessDeniedException("Insufficient permissions for user '" +
-          (user != null ? user.getShortName() : "null") +"' (global, action=" +
-          perm.toString() + ")");
-      }
-    }
+  public void requireNamespacePermission(ObserverContext<?> ctx, String request, String namespace,
+      TableName tableName, Map<byte[], ? extends Collection<byte[]>> familyMap,
+      Action... permissions) throws IOException {
+    accessChecker.requireNamespacePermission(getActiveUser(ctx),
+        request, namespace, tableName, familyMap,
+        permissions);
   }
 
-  /**
-   * Checks that the user has the given global permission. The generated
-   * audit log message will contain context information for the operation
-   * being authorized, based on the given parameters.
-   * @param perm Action being requested
-   * @param namespace
-   */
-  private void requireGlobalPermission(User user, String request, Action perm,
-                                       String namespace) throws IOException {
-    AuthResult authResult = null;
-    if (authManager.authorize(user, perm)) {
-      authResult = AuthResult.allow(request, "Global check allowed", user, perm, null);
-      authResult.getParams().setNamespace(namespace);
-      logResult(authResult);
-    } else {
-      authResult = AuthResult.deny(request, "Global check failed", user, perm, null);
-      authResult.getParams().setNamespace(namespace);
-      logResult(authResult);
-      if (authorizationEnabled) {
-        throw new AccessDeniedException("Insufficient permissions for user '" +
-          (user != null ? user.getShortName() : "null") +"' (global, action=" +
-          perm.toString() + ")");
-      }
-    }
+  public void requirePermission(ObserverContext<?> ctx, String request, TableName tableName,
+      byte[] family, byte[] qualifier, Action... permissions) throws IOException {
+    accessChecker.requirePermission(getActiveUser(ctx), request,
+        tableName, family, qualifier, permissions);
   }
 
-  /**
-   * Checks that the user has the given global or namespace permission.
-   * @param namespace
-   * @param permissions Actions being requested
-   */
-  public void requireNamespacePermission(User user, String request, String namespace,
+  public void requireTablePermission(ObserverContext<?> ctx, String request,
+      TableName tableName,byte[] family, byte[] qualifier,
       Action... permissions) throws IOException {
-    AuthResult result = null;
-
-    for (Action permission : permissions) {
-      if (authManager.authorize(user, namespace, permission)) {
-        result = AuthResult.allow(request, "Namespace permission granted",
-            user, permission, namespace);
-        break;
-      } else {
-        // rest of the world
-        result = AuthResult.deny(request, "Insufficient permissions", user,
-            permission, namespace);
-      }
-    }
-    logResult(result);
-    if (authorizationEnabled && !result.isAllowed()) {
-      throw new AccessDeniedException("Insufficient permissions "
-          + result.toContextString());
-    }
+    accessChecker.requireTablePermission(getActiveUser(ctx),
+        request, tableName, family, qualifier, permissions);
   }
 
-  /**
-   * Checks that the user has the given global or namespace permission.
-   * @param namespace
-   * @param permissions Actions being requested
-   */
-  public void requireNamespacePermission(User user, String request, String namespace,
-      TableName tableName, Map<byte[], ? extends Collection<byte[]>> familyMap,
-      Action... permissions)
+  public void checkLockPermissions(ObserverContext<?> ctx, String namespace,
+      TableName tableName, RegionInfo[] regionInfos, String reason)
       throws IOException {
-    AuthResult result = null;
-
-    for (Action permission : permissions) {
-      if (authManager.authorize(user, namespace, permission)) {
-        result = AuthResult.allow(request, "Namespace permission granted",
-            user, permission, namespace);
-        result.getParams().setTableName(tableName).setFamilies(familyMap);
-        break;
-      } else {
-        // rest of the world
-        result = AuthResult.deny(request, "Insufficient permissions", user,
-            permission, namespace);
-        result.getParams().setTableName(tableName).setFamilies(familyMap);
-      }
-    }
-    logResult(result);
-    if (authorizationEnabled && !result.isAllowed()) {
-      throw new AccessDeniedException("Insufficient permissions "
-          + result.toContextString());
-    }
+    accessChecker.checkLockPermissions(getActiveUser(ctx),
+        namespace, tableName, regionInfos, reason);
   }
 
   /**
@@ -669,13 +483,13 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
           familyMap.entrySet()) {
         if (family.getValue() != null && !family.getValue().isEmpty()) {
           for (byte[] qualifier : family.getValue()) {
-            if (authManager.matchPermission(user, tableName,
+            if (getAuthManager().matchPermission(user, tableName,
                 family.getKey(), qualifier, perm)) {
               return true;
             }
           }
         } else {
-          if (authManager.matchPermission(user, tableName, family.getKey(),
+          if (getAuthManager().matchPermission(user, tableName, family.getKey(),
               perm)) {
             return true;
           }
@@ -865,7 +679,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
           foundColumn = true;
           for (Action action: actions) {
             // Are there permissions for this user for the cell?
-            if (!authManager.authorize(user, getTableName(e), cell, action)) {
+            if (!getAuthManager().authorize(user, getTableName(e), cell, action)) {
               // We can stop if the cell ACL denies access
               return false;
             }
@@ -940,7 +754,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     CompoundConfiguration conf = new CompoundConfiguration();
     conf.add(env.getConfiguration());
 
-    authorizationEnabled = isAuthorizationSupported(conf);
+    authorizationEnabled = AccessChecker.isAuthorizationSupported(conf);
     if (!authorizationEnabled) {
       LOG.warn("The AccessController has been loaded with authorization checks disabled.");
     }
@@ -980,27 +794,13 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
 
     // set the user-provider.
     this.userProvider = UserProvider.instantiate(env.getConfiguration());
-
-    // 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.getOrCreate(zk, env.getConfiguration());
-      } catch (IOException ioe) {
-        throw new RuntimeException("Error obtaining TableAuthManager", ioe);
-      }
-    } else {
-      throw new RuntimeException("Error obtaining TableAuthManager, zk found null.");
-    }
-
+    accessChecker = new AccessChecker(env.getConfiguration(), zk);
     tableAcls = new MapMaker().weakValues().makeMap();
   }
 
   @Override
   public void stop(CoprocessorEnvironment env) {
-    if (this.authManager != null) {
-      TableAuthManager.release(authManager);
-    }
+    TableAuthManager.release(getAuthManager());
   }
 
   /*********************************** Observer/Service Getters ***********************************/
@@ -1045,7 +845,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     for (byte[] family: families) {
       familyMap.put(family, null);
     }
-    requireNamespacePermission(getActiveUser(c), "createTable",
+    requireNamespacePermission(c, "createTable",
         desc.getTableName().getNamespaceAsString(), desc.getTableName(), familyMap, Action.CREATE);
   }
 
@@ -1102,8 +902,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> c, TableName tableName)
       throws IOException {
-    requirePermission(getActiveUser(c), "deleteTable", tableName, null, null,
-        Action.ADMIN, Action.CREATE);
+    requirePermission(c, "deleteTable",
+        tableName, null, null, Action.ADMIN, Action.CREATE);
   }
 
   @Override
@@ -1120,14 +920,14 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         return null;
       }
     });
-    this.authManager.getZKPermissionWatcher().deleteTableACLNode(tableName);
+    getAuthManager().getZKPermissionWatcher().deleteTableACLNode(tableName);
   }
 
   @Override
   public void preTruncateTable(ObserverContext<MasterCoprocessorEnvironment> c,
       final TableName tableName) throws IOException {
-    requirePermission(getActiveUser(c), "truncateTable", tableName, null, null,
-        Action.ADMIN, Action.CREATE);
+    requirePermission(c, "truncateTable",
+        tableName, null, null, Action.ADMIN, Action.CREATE);
 
     final Configuration conf = c.getEnvironment().getConfiguration();
     User.runAsLoginUser(new PrivilegedExceptionAction<Void>() {
@@ -1168,8 +968,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   public void preModifyTable(ObserverContext<MasterCoprocessorEnvironment> c, TableName tableName,
       TableDescriptor htd) throws IOException {
     // TODO: potentially check if this is a add/modify/delete column operation
-    requirePermission(getActiveUser(c), "modifyTable", tableName, null, null,
-        Action.ADMIN, Action.CREATE);
+    requirePermission(c, "modifyTable",
+        tableName, null, null, Action.ADMIN, Action.CREATE);
   }
 
   @Override
@@ -1196,8 +996,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void preEnableTable(ObserverContext<MasterCoprocessorEnvironment> c, TableName tableName)
       throws IOException {
-    requirePermission(getActiveUser(c), "enableTable", tableName, null, null,
-        Action.ADMIN, Action.CREATE);
+    requirePermission(c, "enableTable",
+        tableName, null, null, Action.ADMIN, Action.CREATE);
   }
 
   @Override
@@ -1211,14 +1011,14 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       throw new AccessDeniedException("Not allowed to disable "
           + AccessControlLists.ACL_TABLE_NAME + " table with AccessController installed");
     }
-    requirePermission(getActiveUser(c), "disableTable", tableName, null, null,
-        Action.ADMIN, Action.CREATE);
+    requirePermission(c, "disableTable",
+        tableName, null, null, Action.ADMIN, Action.CREATE);
   }
 
   @Override
   public void preAbortProcedure(ObserverContext<MasterCoprocessorEnvironment> ctx,
       final long procId) throws IOException {
-    requirePermission(getActiveUser(ctx), "abortProcedure", Action.ADMIN);
+    requirePermission(ctx, "abortProcedure", Action.ADMIN);
   }
 
   @Override
@@ -1230,74 +1030,73 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void preGetProcedures(ObserverContext<MasterCoprocessorEnvironment> ctx)
       throws IOException {
-    requirePermission(getActiveUser(ctx), "getProcedure", Action.ADMIN);
+    requirePermission(ctx, "getProcedure", Action.ADMIN);
   }
 
   @Override
   public void preGetLocks(ObserverContext<MasterCoprocessorEnvironment> ctx)
       throws IOException {
     User user = getActiveUser(ctx);
-    requirePermission(user, "getLocks", Action.ADMIN);
+    accessChecker.requirePermission(user, "getLocks", Action.ADMIN);
   }
 
   @Override
   public void preMove(ObserverContext<MasterCoprocessorEnvironment> c, RegionInfo region,
       ServerName srcServer, ServerName destServer) throws IOException {
-    requirePermission(getActiveUser(c), "move", region.getTable(), null, null, Action.ADMIN);
+    requirePermission(c, "move",
+        region.getTable(), null, null, Action.ADMIN);
   }
 
   @Override
   public void preAssign(ObserverContext<MasterCoprocessorEnvironment> c, RegionInfo regionInfo)
       throws IOException {
-    requirePermission(getActiveUser(c), "assign", regionInfo.getTable(), null, null, Action.ADMIN);
+    requirePermission(c, "assign",
+        regionInfo.getTable(), null, null, Action.ADMIN);
   }
 
   @Override
   public void preUnassign(ObserverContext<MasterCoprocessorEnvironment> c, RegionInfo regionInfo,
       boolean force) throws IOException {
-    requirePermission(getActiveUser(c), "unassign", regionInfo.getTable(), null, null, Action.ADMIN);
+    requirePermission(c, "unassign",
+        regionInfo.getTable(), null, null, Action.ADMIN);
   }
 
   @Override
   public void preRegionOffline(ObserverContext<MasterCoprocessorEnvironment> c,
       RegionInfo regionInfo) throws IOException {
-    requirePermission(getActiveUser(c), "regionOffline", regionInfo.getTable(), null, null,
-        Action.ADMIN);
+    requirePermission(c, "regionOffline",
+        regionInfo.getTable(), null, null, Action.ADMIN);
   }
 
   @Override
   public void preSetSplitOrMergeEnabled(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       final boolean newValue, final MasterSwitchType switchType) throws IOException {
-    requirePermission(getActiveUser(ctx), "setSplitOrMergeEnabled", Action.ADMIN);
-  }
-
-  @Override
-  public void postSetSplitOrMergeEnabled(final ObserverContext<MasterCoprocessorEnvironment> ctx,
-      final boolean newValue, final MasterSwitchType switchType) throws IOException {
+    requirePermission(ctx, "setSplitOrMergeEnabled",
+        Action.ADMIN);
   }
 
   @Override
   public void preBalance(ObserverContext<MasterCoprocessorEnvironment> c)
       throws IOException {
-    requirePermission(getActiveUser(c), "balance", Action.ADMIN);
+    requirePermission(c, "balance", Action.ADMIN);
   }
 
   @Override
   public void preBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> c,
       boolean newValue) throws IOException {
-    requirePermission(getActiveUser(c), "balanceSwitch", Action.ADMIN);
+    requirePermission(c, "balanceSwitch", Action.ADMIN);
   }
 
   @Override
   public void preShutdown(ObserverContext<MasterCoprocessorEnvironment> c)
       throws IOException {
-    requirePermission(getActiveUser(c), "shutdown", Action.ADMIN);
+    requirePermission(c, "shutdown", Action.ADMIN);
   }
 
   @Override
   public void preStopMaster(ObserverContext<MasterCoprocessorEnvironment> c)
       throws IOException {
-    requirePermission(getActiveUser(c), "stopMaster", Action.ADMIN);
+    requirePermission(c, "stopMaster", Action.ADMIN);
   }
 
   @Override
@@ -1335,8 +1134,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   public void preSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
       throws IOException {
-    requirePermission(getActiveUser(ctx), "snapshot " + snapshot.getName(), hTableDescriptor.getTableName(), null, null,
-      Permission.Action.ADMIN);
+    requirePermission(ctx, "snapshot " + snapshot.getName(),
+        hTableDescriptor.getTableName(), null, null, Permission.Action.ADMIN);
   }
 
   @Override
@@ -1347,9 +1146,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       // list it, if user is the owner of snapshot
       AuthResult result = AuthResult.allow("listSnapshot " + snapshot.getName(),
           "Snapshot owner check allowed", user, null, null, null);
-      logResult(result);
+      AccessChecker.logResult(result);
     } else {
-      requirePermission(user, "listSnapshot " + snapshot.getName(), Action.ADMIN);
+      accessChecker.requirePermission(user, "listSnapshot " + snapshot.getName(), Action.ADMIN);
     }
   }
 
@@ -1363,9 +1162,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       // Snapshot owner is allowed to create a table with the same name as the snapshot he took
       AuthResult result = AuthResult.allow("cloneSnapshot " + snapshot.getName(),
         "Snapshot owner check allowed", user, null, hTableDescriptor.getTableName(), null);
-      logResult(result);
+      AccessChecker.logResult(result);
     } else {
-      requirePermission(user, "cloneSnapshot " + snapshot.getName(), Action.ADMIN);
+      accessChecker.requirePermission(user, "cloneSnapshot " + snapshot.getName(), Action.ADMIN);
     }
   }
 
@@ -1375,10 +1174,10 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       throws IOException {
     User user = getActiveUser(ctx);
     if (SnapshotDescriptionUtils.isSnapshotOwner(snapshot, user)) {
-      requirePermission(user, "restoreSnapshot " + snapshot.getName(), hTableDescriptor.getTableName(), null, null,
-        Permission.Action.ADMIN);
+      accessChecker.requirePermission(user, "restoreSnapshot " + snapshot.getName(),
+          hTableDescriptor.getTableName(), null, null, Permission.Action.ADMIN);
     } else {
-      requirePermission(user, "restoreSnapshot " + snapshot.getName(), Action.ADMIN);
+      accessChecker.requirePermission(user, "restoreSnapshot " + snapshot.getName(), Action.ADMIN);
     }
   }
 
@@ -1390,22 +1189,24 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       // Snapshot owner is allowed to delete the snapshot
       AuthResult result = AuthResult.allow("deleteSnapshot " + snapshot.getName(),
           "Snapshot owner check allowed", user, null, null, null);
-      logResult(result);
+      AccessChecker.logResult(result);
     } else {
-      requirePermission(user, "deleteSnapshot " + snapshot.getName(), Action.ADMIN);
+      accessChecker.requirePermission(user, "deleteSnapshot " + snapshot.getName(), Action.ADMIN);
     }
   }
 
   @Override
   public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx,
       NamespaceDescriptor ns) throws IOException {
-    requireGlobalPermission(getActiveUser(ctx), "createNamespace", Action.ADMIN, ns.getName());
+    requireGlobalPermission(ctx, "createNamespace",
+        Action.ADMIN, ns.getName());
   }
 
   @Override
   public void preDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace)
       throws IOException {
-    requireGlobalPermission(getActiveUser(ctx), "deleteNamespace", Action.ADMIN, namespace);
+    requireGlobalPermission(ctx, "deleteNamespace",
+        Action.ADMIN, namespace);
   }
 
   @Override
@@ -1422,7 +1223,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         return null;
       }
     });
-    this.authManager.getZKPermissionWatcher().deleteNamespaceACLNode(namespace);
+    getAuthManager().getZKPermissionWatcher().deleteNamespaceACLNode(namespace);
     LOG.info(namespace + " entry deleted in " + AccessControlLists.ACL_TABLE_NAME + " table.");
   }
 
@@ -1431,13 +1232,15 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       NamespaceDescriptor ns) throws IOException {
     // We require only global permission so that
     // a user with NS admin cannot altering namespace configurations. i.e. namespace quota
-    requireGlobalPermission(getActiveUser(ctx), "modifyNamespace", Action.ADMIN, ns.getName());
+    requireGlobalPermission(ctx, "modifyNamespace",
+        Action.ADMIN, ns.getName());
   }
 
   @Override
   public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace)
       throws IOException {
-    requireNamespacePermission(getActiveUser(ctx), "getNamespaceDescriptor", namespace, Action.ADMIN);
+    requireNamespacePermission(ctx, "getNamespaceDescriptor",
+        namespace, Action.ADMIN);
   }
 
   @Override
@@ -1450,7 +1253,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     while (itr.hasNext()) {
       NamespaceDescriptor desc = itr.next();
       try {
-        requireNamespacePermission(user, "listNamespaces", desc.getName(), Action.ADMIN);
+        accessChecker.requireNamespacePermission(user, "listNamespaces",
+            desc.getName(), Action.ADMIN);
       } catch (AccessDeniedException e) {
         itr.remove();
       }
@@ -1460,8 +1264,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void preTableFlush(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       final TableName tableName) throws IOException {
-    requirePermission(getActiveUser(ctx), "flushTable", tableName, null, null,
-        Action.ADMIN, Action.CREATE);
+    requirePermission(ctx, "flushTable", tableName,
+        null, null, Action.ADMIN, Action.CREATE);
   }
 
   @Override
@@ -1469,29 +1273,33 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       final ObserverContext<MasterCoprocessorEnvironment> ctx,
       final TableName tableName,
       final byte[] splitRow) throws IOException {
-    requirePermission(getActiveUser(ctx), "split", tableName, null, null, Action.ADMIN);
+    requirePermission(ctx, "split", tableName,
+        null, null, Action.ADMIN);
   }
 
   @Override
-  public void preClearDeadServers(ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
-    requirePermission(getActiveUser(ctx), "clearDeadServers", Action.ADMIN);
+  public void preClearDeadServers(ObserverContext<MasterCoprocessorEnvironment> ctx)
+      throws IOException {
+    requirePermission(ctx, "clearDeadServers", Action.ADMIN);
   }
 
   @Override
   public void preDecommissionRegionServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
       List<ServerName> servers, boolean offload) throws IOException {
-    requirePermission(getActiveUser(ctx), "decommissionRegionServers", Action.ADMIN);
+    requirePermission(ctx, "decommissionRegionServers", Action.ADMIN);
   }
 
   @Override
-  public void preListDecommissionedRegionServers(ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
-    requirePermission(getActiveUser(ctx), "listDecommissionedRegionServers", Action.ADMIN);
+  public void preListDecommissionedRegionServers(ObserverContext<MasterCoprocessorEnvironment> ctx)
+      throws IOException {
+    requirePermission(ctx, "listDecommissionedRegionServers",
+        Action.ADMIN);
   }
 
   @Override
   public void preRecommissionRegionServer(ObserverContext<MasterCoprocessorEnvironment> ctx,
       ServerName server, List<byte[]> encodedRegionNames) throws IOException {
-    requirePermission(getActiveUser(ctx), "recommissionRegionServers", Action.ADMIN);
+    requirePermission(ctx, "recommissionRegionServers", Action.ADMIN);
   }
 
   /* ---- RegionObserver implementation ---- */
@@ -1508,7 +1316,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       if (regionInfo.getTable().isSystemTable()) {
         checkSystemOrSuperUser(getActiveUser(c));
       } else {
-        requirePermission(getActiveUser(c), "preOpen", Action.ADMIN);
+        requirePermission(c, "preOpen", Action.ADMIN);
       }
     }
   }
@@ -1538,16 +1346,16 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void preFlush(ObserverContext<RegionCoprocessorEnvironment> c,
       FlushLifeCycleTracker tracker) throws IOException {
-    requirePermission(getActiveUser(c), "flush", getTableName(c.getEnvironment()), null, null,
-      Action.ADMIN, Action.CREATE);
+    requirePermission(c, "flush", getTableName(c.getEnvironment()),
+        null, null, Action.ADMIN, Action.CREATE);
   }
 
   @Override
   public InternalScanner preCompact(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
       InternalScanner scanner, ScanType scanType, CompactionLifeCycleTracker tracker,
       CompactionRequest request) throws IOException {
-    requirePermission(getActiveUser(c), "compact", getTableName(c.getEnvironment()), null, null,
-      Action.ADMIN, Action.CREATE);
+    requirePermission(c, "compact", getTableName(c.getEnvironment()),
+        null, null, Action.ADMIN, Action.CREATE);
     return scanner;
   }
 
@@ -1594,7 +1402,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
           authResult.setReason("Access allowed with filter");
           // Only wrap the filter if we are enforcing authorizations
           if (authorizationEnabled) {
-            Filter ourFilter = new AccessControlFilter(authManager, user, table,
+            Filter ourFilter = new AccessControlFilter(getAuthManager(), user, table,
               AccessControlFilter.Strategy.CHECK_TABLE_AND_CF_ONLY,
               cfVsMaxVersions);
             // wrap any existing filter
@@ -1624,7 +1432,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         authResult.setReason("Access allowed with filter");
         // Only wrap the filter if we are enforcing authorizations
         if (authorizationEnabled) {
-          Filter ourFilter = new AccessControlFilter(authManager, user, table,
+          Filter ourFilter = new AccessControlFilter(getAuthManager(), user, table,
             AccessControlFilter.Strategy.CHECK_CELL_DEFAULT, cfVsMaxVersions);
           // wrap any existing filter
           if (filter != null) {
@@ -1646,7 +1454,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       }
     }
 
-    logResult(authResult);
+    AccessChecker.logResult(authResult);
     if (authorizationEnabled && !authResult.isAllowed()) {
       throw new AccessDeniedException("Insufficient permissions for user '"
           + (user != null ? user.getShortName() : "null")
@@ -1682,8 +1490,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     // security policy over time without requiring expensive updates.
     RegionCoprocessorEnvironment env = c.getEnvironment();
     Map<byte[],? extends Collection<Cell>> families = put.getFamilyCellMap();
-    AuthResult authResult = permissionGranted(OpType.PUT, user, env, families, Action.WRITE);
-    logResult(authResult);
+    AuthResult authResult = permissionGranted(OpType.PUT,
+        user, env, families, Action.WRITE);
+    AccessChecker.logResult(authResult);
     if (!authResult.isAllowed()) {
       if (cellFeaturesEnabled && !compatibleEarlyTermination) {
         put.setAttribute(CHECK_COVERING_PERM, TRUE);
@@ -1727,8 +1536,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     RegionCoprocessorEnvironment env = c.getEnvironment();
     Map<byte[],? extends Collection<Cell>> families = delete.getFamilyCellMap();
     User user = getActiveUser(c);
-    AuthResult authResult = permissionGranted(OpType.DELETE, user, env, families, Action.WRITE);
-    logResult(authResult);
+    AuthResult authResult = permissionGranted(OpType.DELETE,
+        user, env, families, Action.WRITE);
+    AccessChecker.logResult(authResult);
     if (!authResult.isAllowed()) {
       if (cellFeaturesEnabled && !compatibleEarlyTermination) {
         delete.setAttribute(CHECK_COVERING_PERM, TRUE);
@@ -1766,7 +1576,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
             authResult = AuthResult.deny(opType.toString(), "Covering cell set",
               user, Action.WRITE, table, m.getFamilyCellMap());
           }
-          logResult(authResult);
+          AccessChecker.logResult(authResult);
           if (authorizationEnabled && !authResult.isAllowed()) {
             throw new AccessDeniedException("Insufficient permissions "
               + authResult.toContextString());
@@ -1797,9 +1607,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     // Require READ and WRITE permissions on the table, CF, and KV to update
     RegionCoprocessorEnvironment env = c.getEnvironment();
     Map<byte[],? extends Collection<byte[]>> families = makeFamilyMap(family, qualifier);
-    AuthResult authResult = permissionGranted(OpType.CHECK_AND_PUT, user, env, families,
-      Action.READ, Action.WRITE);
-    logResult(authResult);
+    AuthResult authResult = permissionGranted(OpType.CHECK_AND_PUT,
+        user, env, families, Action.READ, Action.WRITE);
+    AccessChecker.logResult(authResult);
     if (!authResult.isAllowed()) {
       if (cellFeaturesEnabled && !compatibleEarlyTermination) {
         put.setAttribute(CHECK_COVERING_PERM, TRUE);
@@ -1822,10 +1632,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
 
   @Override
   public boolean preCheckAndPutAfterRowLock(final ObserverContext<RegionCoprocessorEnvironment> c,
-                                            final byte[] row, final byte[] family, final byte[] qualifier,
-                                            final CompareOperator opp, final ByteArrayComparable comparator, final Put put,
-                                            final boolean result)
-  throws IOException {
+      final byte[] row, final byte[] family, final byte[] qualifier,
+      final CompareOperator opp, final ByteArrayComparable comparator, final Put put,
+      final boolean result) throws IOException {
     if (put.getAttribute(CHECK_COVERING_PERM) != null) {
       // We had failure with table, cf and q perm checks and now giving a chance for cell
       // perm check
@@ -1835,13 +1644,13 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       User user = getActiveUser(c);
       if (checkCoveringPermission(user, OpType.CHECK_AND_PUT, c.getEnvironment(), row, families,
           HConstants.LATEST_TIMESTAMP, Action.READ)) {
-        authResult = AuthResult.allow(OpType.CHECK_AND_PUT.toString(), "Covering cell set",
-            user, Action.READ, table, families);
+        authResult = AuthResult.allow(OpType.CHECK_AND_PUT.toString(),
+            "Covering cell set", user, Action.READ, table, families);
       } else {
-        authResult = AuthResult.deny(OpType.CHECK_AND_PUT.toString(), "Covering cell set",
-            user, Action.READ, table, families);
+        authResult = AuthResult.deny(OpType.CHECK_AND_PUT.toString(),
+            "Covering cell set", user, Action.READ, table, families);
       }
-      logResult(authResult);
+      AccessChecker.logResult(authResult);
       if (authorizationEnabled && !authResult.isAllowed()) {
         throw new AccessDeniedException("Insufficient permissions " + authResult.toContextString());
       }
@@ -1865,9 +1674,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     RegionCoprocessorEnvironment env = c.getEnvironment();
     Map<byte[],? extends Collection<byte[]>> families = makeFamilyMap(family, qualifier);
     User user = getActiveUser(c);
-    AuthResult authResult = permissionGranted(OpType.CHECK_AND_DELETE, user, env, families,
-        Action.READ, Action.WRITE);
-    logResult(authResult);
+    AuthResult authResult = permissionGranted(
+        OpType.CHECK_AND_DELETE, user, env, families, Action.READ, Action.WRITE);
+    AccessChecker.logResult(authResult);
     if (!authResult.isAllowed()) {
       if (cellFeaturesEnabled && !compatibleEarlyTermination) {
         delete.setAttribute(CHECK_COVERING_PERM, TRUE);
@@ -1881,8 +1690,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
 
   @Override
   public boolean preCheckAndDeleteAfterRowLock(
-      final ObserverContext<RegionCoprocessorEnvironment> c, final byte[] row, final byte[] family,
-      final byte[] qualifier, final CompareOperator op,
+      final ObserverContext<RegionCoprocessorEnvironment> c, final byte[] row,
+      final byte[] family, final byte[] qualifier, final CompareOperator op,
       final ByteArrayComparable comparator, final Delete delete, final boolean result)
       throws IOException {
     if (delete.getAttribute(CHECK_COVERING_PERM) != null) {
@@ -1892,15 +1701,15 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       Map<byte[], ? extends Collection<byte[]>> families = makeFamilyMap(family, qualifier);
       AuthResult authResult = null;
       User user = getActiveUser(c);
-      if (checkCoveringPermission(user, OpType.CHECK_AND_DELETE, c.getEnvironment(), row, families,
-          HConstants.LATEST_TIMESTAMP, Action.READ)) {
-        authResult = AuthResult.allow(OpType.CHECK_AND_DELETE.toString(), "Covering cell set",
-            user, Action.READ, table, families);
+      if (checkCoveringPermission(user, OpType.CHECK_AND_DELETE, c.getEnvironment(),
+          row, families, HConstants.LATEST_TIMESTAMP, Action.READ)) {
+        authResult = AuthResult.allow(OpType.CHECK_AND_DELETE.toString(),
+            "Covering cell set", user, Action.READ, table, families);
       } else {
-        authResult = AuthResult.deny(OpType.CHECK_AND_DELETE.toString(), "Covering cell set",
-            user, Action.READ, table, families);
+        authResult = AuthResult.deny(OpType.CHECK_AND_DELETE.toString(),
+            "Covering cell set", user, Action.READ, table, families);
       }
-      logResult(authResult);
+      AccessChecker.logResult(authResult);
       if (authorizationEnabled && !authResult.isAllowed()) {
         throw new AccessDeniedException("Insufficient permissions " + authResult.toContextString());
       }
@@ -1917,8 +1726,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     // Require WRITE permission to the table, CF, and the KV to be appended
     RegionCoprocessorEnvironment env = c.getEnvironment();
     Map<byte[],? extends Collection<Cell>> families = append.getFamilyCellMap();
-    AuthResult authResult = permissionGranted(OpType.APPEND, user, env, families, Action.WRITE);
-    logResult(authResult);
+    AuthResult authResult = permissionGranted(OpType.APPEND, user,
+        env, families, Action.WRITE);
+    AccessChecker.logResult(authResult);
     if (!authResult.isAllowed()) {
       if (cellFeaturesEnabled && !compatibleEarlyTermination) {
         append.setAttribute(CHECK_COVERING_PERM, TRUE);
@@ -1951,13 +1761,13 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       User user = getActiveUser(c);
       if (checkCoveringPermission(user, OpType.APPEND, c.getEnvironment(), append.getRow(),
           append.getFamilyCellMap(), append.getTimeRange().getMax(), Action.WRITE)) {
-        authResult = AuthResult.allow(OpType.APPEND.toString(), "Covering cell set",
-            user, Action.WRITE, table, append.getFamilyCellMap());
+        authResult = AuthResult.allow(OpType.APPEND.toString(),
+            "Covering cell set", user, Action.WRITE, table, append.getFamilyCellMap());
       } else {
-        authResult = AuthResult.deny(OpType.APPEND.toString(), "Covering cell set",
-            user, Action.WRITE, table, append.getFamilyCellMap());
+        authResult = AuthResult.deny(OpType.APPEND.toString(),
+            "Covering cell set", user, Action.WRITE, table, append.getFamilyCellMap());
       }
-      logResult(authResult);
+      AccessChecker.logResult(authResult);
       if (authorizationEnabled && !authResult.isAllowed()) {
         throw new AccessDeniedException("Insufficient permissions " +
           authResult.toContextString());
@@ -1977,9 +1787,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     // the incremented value
     RegionCoprocessorEnvironment env = c.getEnvironment();
     Map<byte[],? extends Collection<Cell>> families = increment.getFamilyCellMap();
-    AuthResult authResult = permissionGranted(OpType.INCREMENT, user, env, families,
-      Action.WRITE);
-    logResult(authResult);
+    AuthResult authResult = permissionGranted(OpType.INCREMENT,
+        user, env, families, Action.WRITE);
+    AccessChecker.logResult(authResult);
     if (!authResult.isAllowed()) {
       if (cellFeaturesEnabled && !compatibleEarlyTermination) {
         increment.setAttribute(CHECK_COVERING_PERM, TRUE);
@@ -2018,7 +1828,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         authResult = AuthResult.deny(OpType.INCREMENT.toString(), "Covering cell set",
             user, Action.WRITE, table, increment.getFamilyCellMap());
       }
-      logResult(authResult);
+      AccessChecker.logResult(authResult);
       if (authorizationEnabled && !authResult.isAllowed()) {
         throw new AccessDeniedException("Insufficient permissions " +
           authResult.toContextString());
@@ -2156,7 +1966,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
       List<Pair<byte[], String>> familyPaths) throws IOException {
     User user = getActiveUser(ctx);
     for(Pair<byte[],String> el : familyPaths) {
-      requirePermission(user, "preBulkLoadHFile",
+      accessChecker.requirePermission(user, "preBulkLoadHFile",
           ctx.getEnvironment().getRegion().getTableDescriptor().getTableName(),
           el.getFirst(),
           null,
@@ -2173,7 +1983,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void prePrepareBulkLoad(ObserverContext<RegionCoprocessorEnvironment> ctx)
   throws IOException {
-    requireAccess(getActiveUser(ctx), "prePrepareBulkLoad",
+    requireAccess(ctx, "prePrepareBulkLoad",
         ctx.getEnvironment().getRegion().getTableDescriptor().getTableName(), Action.CREATE);
   }
 
@@ -2186,7 +1996,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void preCleanupBulkLoad(ObserverContext<RegionCoprocessorEnvironment> ctx)
   throws IOException {
-    requireAccess(getActiveUser(ctx), "preCleanupBulkLoad",
+    requireAccess(ctx, "preCleanupBulkLoad",
         ctx.getEnvironment().getRegion().getTableDescriptor().getTableName(), Action.CREATE);
   }
 
@@ -2198,7 +2008,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     // Don't intercept calls to our own AccessControlService, we check for
     // appropriate permissions in the service handlers
     if (shouldCheckExecPermission && !(service instanceof AccessControlService)) {
-      requirePermission(getActiveUser(ctx),
+      requirePermission(ctx,
           "invoke(" + service.getDescriptorForType().getName() + "." + methodName + ")",
           getTableName(ctx.getEnvironment()), null, null,
           Action.EXEC);
@@ -2215,8 +2025,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
 
   @Override
   public void grant(RpcController controller,
-                    AccessControlProtos.GrantRequest request,
-                    RpcCallback<AccessControlProtos.GrantResponse> done) {
+      AccessControlProtos.GrantRequest request,
+      RpcCallback<AccessControlProtos.GrantResponse> done) {
     final UserPermission perm = AccessControlUtil.toUserPermission(request.getUserPermission());
     AccessControlProtos.GrantResponse response = null;
     try {
@@ -2233,11 +2043,12 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         switch(request.getUserPermission().getPermission().getType()) {
           case Global :
           case Table :
-            requirePermission(caller, "grant", perm.getTableName(),
+            accessChecker.requirePermission(caller, "grant", perm.getTableName(),
                 perm.getFamily(), perm.getQualifier(), Action.ADMIN);
             break;
           case Namespace :
-            requireNamespacePermission(caller, "grant", perm.getNamespace(), Action.ADMIN);
+            accessChecker.requireNamespacePermission(caller, "grant", perm.getNamespace(),
+                Action.ADMIN);
            break;
         }
 
@@ -2272,8 +2083,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
 
   @Override
   public void revoke(RpcController controller,
-                     AccessControlProtos.RevokeRequest request,
-                     RpcCallback<AccessControlProtos.RevokeResponse> done) {
+      AccessControlProtos.RevokeRequest request,
+      RpcCallback<AccessControlProtos.RevokeResponse> done) {
     final UserPermission perm = AccessControlUtil.toUserPermission(request.getUserPermission());
     AccessControlProtos.RevokeResponse response = null;
     try {
@@ -2290,11 +2101,12 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         switch(request.getUserPermission().getPermission().getType()) {
           case Global :
           case Table :
-            requirePermission(caller, "revoke", perm.getTableName(), perm.getFamily(),
+            accessChecker.requirePermission(caller, "revoke", perm.getTableName(), perm.getFamily(),
               perm.getQualifier(), Action.ADMIN);
             break;
           case Namespace :
-            requireNamespacePermission(caller, "revoke", perm.getNamespace(), Action.ADMIN);
+            accessChecker.requireNamespacePermission(caller, "revoke", perm.getNamespace(),
+                Action.ADMIN);
             break;
         }
 
@@ -2328,8 +2140,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
 
   @Override
   public void getUserPermissions(RpcController controller,
-                                 AccessControlProtos.GetUserPermissionsRequest request,
-                                 RpcCallback<AccessControlProtos.GetUserPermissionsResponse> done) {
+      AccessControlProtos.GetUserPermissionsRequest request,
+      RpcCallback<AccessControlProtos.GetUserPermissionsResponse> done) {
     AccessControlProtos.GetUserPermissionsResponse response = null;
     try {
       // only allowed to be called on _acl_ region
@@ -2343,7 +2155,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         if (request.getType() == AccessControlProtos.Permission.Type.Table) {
           final TableName table = request.hasTableName() ?
             ProtobufUtil.toTableName(request.getTableName()) : null;
-          requirePermission(caller, "userPermissions", table, null, null, Action.ADMIN);
+          accessChecker.requirePermission(caller, "userPermissions",
+              table, null, null, Action.ADMIN);
           perms = User.runAsLoginUser(new PrivilegedExceptionAction<List<UserPermission>>() {
             @Override
             public List<UserPermission> run() throws Exception {
@@ -2352,7 +2165,8 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
           });
         } else if (request.getType() == AccessControlProtos.Permission.Type.Namespace) {
           final String namespace = request.getNamespaceName().toStringUtf8();
-          requireNamespacePermission(caller, "userPermissions", namespace, Action.ADMIN);
+          accessChecker.requireNamespacePermission(caller, "userPermissions",
+              namespace, Action.ADMIN);
           perms = User.runAsLoginUser(new PrivilegedExceptionAction<List<UserPermission>>() {
             @Override
             public List<UserPermission> run() throws Exception {
@@ -2361,7 +2175,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
             }
           });
         } else {
-          requirePermission(caller, "userPermissions", Action.ADMIN);
+          accessChecker.requirePermission(caller, "userPermissions", Action.ADMIN);
           perms = User.runAsLoginUser(new PrivilegedExceptionAction<List<UserPermission>>() {
             @Override
             public List<UserPermission> run() throws Exception {
@@ -2426,7 +2240,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
 
             AuthResult result = permissionGranted("checkPermissions", user, action, regionEnv,
               familyMap);
-            logResult(result);
+            AccessChecker.logResult(result);
             if (!result.isAllowed()) {
               // Even if passive we need to throw an exception here, we support checking
               // effective permissions, so throw unconditionally
@@ -2441,14 +2255,14 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
 
           for (Action action : permission.getActions()) {
             AuthResult result;
-            if (authManager.authorize(user, action)) {
+            if (getAuthManager().authorize(user, action)) {
               result = AuthResult.allow("checkPermissions", "Global action allowed", user,
                 action, null, null);
             } else {
               result = AuthResult.deny("checkPermissions", "Global action denied", user, action,
                 null, null);
             }
-            logResult(result);
+            AccessChecker.logResult(result);
             if (!result.isAllowed()) {
               // Even if passive we need to throw an exception here, we support checking
               // effective permissions, so throw unconditionally
@@ -2488,7 +2302,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void preClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested)
       throws IOException {
-    requirePermission(getActiveUser(c), "preClose", Action.ADMIN);
+    requirePermission(c, "preClose", Action.ADMIN);
   }
 
   private void checkSystemOrSuperUser(User activeUser) throws IOException {
@@ -2506,7 +2320,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   public void preStopRegionServer(
       ObserverContext<RegionServerCoprocessorEnvironment> ctx)
       throws IOException {
-    requirePermission(getActiveUser(ctx), "preStopRegionServer", Action.ADMIN);
+    requirePermission(ctx, "preStopRegionServer", Action.ADMIN);
   }
 
   private Map<byte[], ? extends Collection<byte[]>> makeFamilyMap(byte[] family,
@@ -2536,7 +2350,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
         for (TableName tableName: tableNamesList) {
           // Skip checks for a table that does not exist
           if (!admin.tableExists(tableName)) continue;
-          requirePermission(getActiveUser(ctx), "getTableDescriptors", tableName, null, null,
+          requirePermission(ctx, "getTableDescriptors", tableName, null, null,
             Action.ADMIN, Action.CREATE);
         }
       }
@@ -2558,7 +2372,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     while (itr.hasNext()) {
       TableDescriptor htd = itr.next();
       try {
-        requirePermission(getActiveUser(ctx), "getTableDescriptors", htd.getTableName(), null, null,
+        requirePermission(ctx, "getTableDescriptors", htd.getTableName(), null, null,
             Action.ADMIN, Action.CREATE);
       } catch (AccessDeniedException e) {
         itr.remove();
@@ -2574,7 +2388,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     while (itr.hasNext()) {
       TableDescriptor htd = itr.next();
       try {
-        requireAccess(getActiveUser(ctx), "getTableNames", htd.getTableName(), Action.values());
+        requireAccess(ctx, "getTableNames", htd.getTableName(), Action.values());
       } catch (AccessDeniedException e) {
         itr.remove();
       }
@@ -2584,14 +2398,14 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void preMergeRegions(final ObserverContext<MasterCoprocessorEnvironment> ctx,
                               final RegionInfo[] regionsToMerge) throws IOException {
-    requirePermission(getActiveUser(ctx), "mergeRegions", regionsToMerge[0].getTable(), null, null,
+    requirePermission(ctx, "mergeRegions", regionsToMerge[0].getTable(), null, null,
       Action.ADMIN);
   }
 
   @Override
   public void preRollWALWriterRequest(ObserverContext<RegionServerCoprocessorEnvironment> ctx)
       throws IOException {
-    requirePermission(getActiveUser(ctx), "preRollLogWriterRequest", Permission.Action.ADMIN);
+    requirePermission(ctx, "preRollLogWriterRequest", Permission.Action.ADMIN);
   }
 
   @Override
@@ -2601,33 +2415,33 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       final String userName, final GlobalQuotaSettings quotas) throws IOException {
-    requirePermission(getActiveUser(ctx), "setUserQuota", Action.ADMIN);
+    requirePermission(ctx, "setUserQuota", Action.ADMIN);
   }
 
   @Override
   public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       final String userName, final TableName tableName, final GlobalQuotaSettings quotas)
           throws IOException {
-    requirePermission(getActiveUser(ctx), "setUserTableQuota", tableName, null, null, Action.ADMIN);
+    requirePermission(ctx, "setUserTableQuota", tableName, null, null, Action.ADMIN);
   }
 
   @Override
   public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       final String userName, final String namespace, final GlobalQuotaSettings quotas)
           throws IOException {
-    requirePermission(getActiveUser(ctx), "setUserNamespaceQuota", Action.ADMIN);
+    requirePermission(ctx, "setUserNamespaceQuota", Action.ADMIN);
   }
 
   @Override
   public void preSetTableQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       final TableName tableName, final GlobalQuotaSettings quotas) throws IOException {
-    requirePermission(getActiveUser(ctx), "setTableQuota", tableName, null, null, Action.ADMIN);
+    requirePermission(ctx, "setTableQuota", tableName, null, null, Action.ADMIN);
   }
 
   @Override
   public void preSetNamespaceQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       final String namespace, final GlobalQuotaSettings quotas) throws IOException {
-    requirePermission(getActiveUser(ctx), "setNamespaceQuota", Action.ADMIN);
+    requirePermission(ctx, "setNamespaceQuota", Action.ADMIN);
   }
 
   @Override
@@ -2639,98 +2453,56 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
   @Override
   public void preReplicateLogEntries(ObserverContext<RegionServerCoprocessorEnvironment> ctx)
       throws IOException {
-    requirePermission(getActiveUser(ctx), "replicateLogEntries", Action.WRITE);
+    requirePermission(ctx, "replicateLogEntries", Action.WRITE);
   }
 
   @Override
   public void  preClearCompactionQueues(ObserverContext<RegionServerCoprocessorEnvironment> ctx)
           throws IOException {
-    requirePermission(getActiveUser(ctx), "preClearCompactionQueues", Permission.Action.ADMIN);
-  }
-
-  @Override
-  public void preMoveServersAndTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
-      Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
-    requirePermission(getActiveUser(ctx), "moveServersAndTables", Action.ADMIN);
-  }
-
-  @Override
-  public void preMoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
-                             Set<Address> servers, String targetGroup) throws IOException {
-    requirePermission(getActiveUser(ctx), "moveServers", Action.ADMIN);
-  }
-
-  @Override
-  public void preMoveTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
-                            Set<TableName> tables, String targetGroup) throws IOException {
-    requirePermission(getActiveUser(ctx), "moveTables", Action.ADMIN);
-  }
-
-  @Override
-  public void preAddRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
-                            String name) throws IOException {
-    requirePermission(getActiveUser(ctx), "addRSGroup", Action.ADMIN);
-  }
-
-  @Override
-  public void preRemoveRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
-                               String name) throws IOException {
-    requirePermission(getActiveUser(ctx), "removeRSGroup", Action.ADMIN);
-  }
-
-  @Override
-  public void preBalanceRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
-                                String groupName) throws IOException {
-    requirePermission(getActiveUser(ctx), "balanceRSGroup", Action.ADMIN);
-  }
-
-  @Override
-  public void preRemoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
-      Set<Address> servers) throws IOException {
-    requirePermission(getActiveUser(ctx), "removeServers", Action.ADMIN);
+    requirePermission(ctx, "preClearCompactionQueues", Permission.Action.ADMIN);
   }
 
   @Override
   public void preAddReplicationPeer(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       String peerId, ReplicationPeerConfig peerConfig) throws IOException {
-    requirePermission(getActiveUser(ctx), "addReplicationPeer", Action.ADMIN);
+    requirePermission(ctx, "addReplicationPeer", Action.ADMIN);
   }
 
   @Override
   public void preRemoveReplicationPeer(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       String peerId) throws IOException {
-    requirePermission(getActiveUser(ctx), "removeReplicationPeer", Action.ADMIN);
+    requirePermission(ctx, "removeReplicationPeer", Action.ADMIN);
   }
 
   @Override
   public void preEnableReplicationPeer(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       String peerId) throws IOException {
-    requirePermission(getActiveUser(ctx), "enableReplicationPeer", Action.ADMIN);
+    requirePermission(ctx, "enableReplicationPeer", Action.ADMIN);
   }
 
   @Override
   public void preDisableReplicationPeer(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       String peerId) throws IOException {
-    requirePermission(getActiveUser(ctx), "disableReplicationPeer", Action.ADMIN);
+    requirePermission(ctx, "disableReplicationPeer", Action.ADMIN);
   }
 
   @Override
   public void preGetReplicationPeerConfig(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       String peerId) throws IOException {
-    requirePermission(getActiveUser(ctx), "getReplicationPeerConfig", Action.ADMIN);
+    requirePermission(ctx, "getReplicationPeerConfig", Action.ADMIN);
   }
 
   @Override
   public void preUpdateReplicationPeerConfig(
       final ObserverContext<MasterCoprocessorEnvironment> ctx, String peerId,
       ReplicationPeerConfig peerConfig) throws IOException {
-    requirePermission(getActiveUser(ctx), "updateReplicationPeerConfig", Action.ADMIN);
+    requirePermission(ctx, "updateReplicationPeerConfig", Action.ADMIN);
   }
 
   @Override
   public void preListReplicationPeers(final ObserverContext<MasterCoprocessorEnvironment> ctx,
       String regex) throws IOException {
-    requirePermission(getActiveUser(ctx), "listReplicationPeers", Action.ADMIN);
+    requirePermission(ctx, "listReplicationPeers", Action.ADMIN);
   }
 
   @Override
@@ -2740,27 +2512,26 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
     // There are operations in the CREATE and ADMIN domain which may require lock, READ
     // or WRITE. So for any lock request, we check for these two perms irrespective of lock type.
     String reason = String.format("Description=%s", description);
-    checkLockPermissions(getActiveUser(ctx), namespace, tableName, regionInfos, reason);
+    checkLockPermissions(ctx, namespace, tableName, regionInfos, reason);
   }
 
   @Override
   public void preLockHeartbeat(ObserverContext<MasterCoprocessorEnvironment> ctx,
       TableName tableName, String description) throws IOException {
-    checkLockPermissions(getActiveUser(ctx), null, tableName, null, description);
+    checkLockPermissions(ctx, null, tableName, null, description);
   }
 
-  private void checkLockPermissions(User user, String namespace,
-      TableName tableName, RegionInfo[] regionInfos, String reason)
-  throws IOException {
-    if (namespace != null && !namespace.isEmpty()) {
-      requireNamespacePermission(user, reason, namespace, Action.ADMIN, Action.CREATE);
-    } else if (tableName != null || (regionInfos != null && regionInfos.length > 0)) {
-      // So, either a table or regions op. If latter, check perms ons table.
-      TableName tn = tableName != null? tableName: regionInfos[0].getTable();
-      requireTablePermission(user, reason, tn, null, null,
-          Action.ADMIN, Action.CREATE);
-    } else {
-      throw new DoNotRetryIOException("Invalid lock level when requesting permissions.");
+  /**
+   * Returns the active user to which authorization checks should be applied.
+   * If we are in the context of an RPC call, the remote user is used,
+   * otherwise the currently logged in user is used.
+   */
+  public User getActiveUser(ObserverContext<?> ctx) throws IOException {
+    // for non-rpc handling, fallback to system user
+    Optional<User> optionalUser = ctx.getCaller();
+    if (optionalUser.isPresent()) {
+      return optionalUser.get();
     }
+    return userProvider.getCurrent();
   }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java
index d4b8e58..1ba6029 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java
@@ -105,6 +105,7 @@ import org.apache.hadoop.hbase.regionserver.querymatcher.DeleteTracker;
 import org.apache.hadoop.hbase.security.AccessDeniedException;
 import org.apache.hadoop.hbase.security.Superusers;
 import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.security.access.AccessChecker;
 import org.apache.hadoop.hbase.security.access.AccessController;
 import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
 import org.apache.hbase.thirdparty.com.google.common.collect.MapMaker;
@@ -141,8 +142,8 @@ public class VisibilityController implements MasterCoprocessor, RegionCoprocesso
 
   private VisibilityLabelService visibilityLabelService;
 
-  /** if we are active, usually true, only not true if "hbase.security.authorization"
-    has been set to false in site configuration */
+  /** if we are active, usually false, only true if "hbase.security.authorization"
+    has been set to true in site configuration */
   boolean authorizationEnabled;
 
   // Add to this list if there are any reserved tag types
@@ -153,19 +154,15 @@ public class VisibilityController implements MasterCoprocessor, RegionCoprocesso
     RESERVED_VIS_TAG_TYPES.add(TagType.STRING_VIS_TAG_TYPE);
   }
 
-  public static boolean isAuthorizationSupported(Configuration conf) {
-    return conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
-  }
-
   public static boolean isCellAuthorizationSupported(Configuration conf) {
-    return isAuthorizationSupported(conf);
+    return AccessChecker.isAuthorizationSupported(conf);
   }
 
   @Override
   public void start(CoprocessorEnvironment env) throws IOException {
     this.conf = env.getConfiguration();
 
-    authorizationEnabled = isAuthorizationSupported(conf);
+    authorizationEnabled = AccessChecker.isAuthorizationSupported(conf);
     if (!authorizationEnabled) {
       LOG.warn("The VisibilityController has been loaded with authorization checks disabled.");
     }

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java
index 8bf792b..407ebf9 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java
@@ -106,6 +106,7 @@ public class SecureTestUtil {
     conf.set(CoprocessorHost.REGIONSERVER_COPROCESSOR_CONF_KEY, AccessController.class.getName());
     // Need HFile V3 for tags for security features
     conf.setInt(HFile.FORMAT_VERSION_KEY, 3);
+    conf.set(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, "true");
     configureSuperuser(conf);
   }
 
@@ -129,6 +130,11 @@ public class SecureTestUtil {
     if (conf.getInt(HFile.FORMAT_VERSION_KEY, 2) < HFile.MIN_FORMAT_VERSION_WITH_TAGS) {
       throw new RuntimeException("Post 0.96 security features require HFile version >= 3");
     }
+
+    if (!conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false)) {
+      throw new RuntimeException("Post 2.0.0 security features require set "
+          + User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY + " to true");
+    }
   }
 
   public static void checkTablePerms(Configuration conf, TableName table, byte[] family, byte[] column,

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
index 2435532..be1b0e4 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
@@ -2839,81 +2839,6 @@ public class TestAccessController extends SecureTestUtil {
   }
 
   @Test
-  public void testMoveServers() throws Exception {
-    AccessTestAction action1 = new AccessTestAction() {
-      @Override
-      public Object run() throws Exception {
-        ACCESS_CONTROLLER.preMoveServers(ObserverContextImpl.createAndPrepare(CP_ENV),
-            null, null);
-        return null;
-      }
-    };
-
-    verifyAllowed(action1, SUPERUSER, USER_ADMIN);
-    verifyDenied(action1, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
-  }
-
-  @Test
-  public void testMoveTables() throws Exception {
-    AccessTestAction action1 = new AccessTestAction() {
-      @Override
-      public Object run() throws Exception {
-        ACCESS_CONTROLLER.preMoveTables(ObserverContextImpl.createAndPrepare(CP_ENV),
-            null, null);
-        return null;
-      }
-    };
-
-    verifyAllowed(action1, SUPERUSER, USER_ADMIN);
-    verifyDenied(action1, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
-  }
-
-  @Test
-  public void testAddGroup() throws Exception {
-    AccessTestAction action1 = new AccessTestAction() {
-      @Override
-      public Object run() throws Exception {
-        ACCESS_CONTROLLER.preAddRSGroup(ObserverContextImpl.createAndPrepare(CP_ENV),
-            null);
-        return null;
-      }
-    };
-
-    verifyAllowed(action1, SUPERUSER, USER_ADMIN);
-    verifyDenied(action1, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
-  }
-
-  @Test
-  public void testRemoveGroup() throws Exception {
-    AccessTestAction action1 = new AccessTestAction() {
-      @Override
-      public Object run() throws Exception {
-        ACCESS_CONTROLLER.preRemoveRSGroup(ObserverContextImpl.createAndPrepare(CP_ENV),
-            null);
-        return null;
-      }
-    };
-
-    verifyAllowed(action1, SUPERUSER, USER_ADMIN);
-    verifyDenied(action1, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
-  }
-
-  @Test
-  public void testBalanceGroup() throws Exception {
-    AccessTestAction action1 = new AccessTestAction() {
-      @Override
-      public Object run() throws Exception {
-        ACCESS_CONTROLLER.preBalanceRSGroup(ObserverContextImpl.createAndPrepare(CP_ENV),
-            null);
-        return null;
-      }
-    };
-
-    verifyAllowed(action1, SUPERUSER, USER_ADMIN);
-    verifyDenied(action1, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
-  }
-
-  @Test
   public void testAddReplicationPeer() throws Exception {
     AccessTestAction action = new AccessTestAction() {
       @Override

http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/VisibilityTestUtil.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/VisibilityTestUtil.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/VisibilityTestUtil.java
index 7dbe256..4e2c4b7 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/VisibilityTestUtil.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/VisibilityTestUtil.java
@@ -14,7 +14,7 @@ import java.io.IOException;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
-
+import org.apache.hadoop.hbase.security.User;
 
 /**
  * Utility methods for testing visibility labels.
@@ -23,6 +23,7 @@ public class VisibilityTestUtil {
 
   public static void enableVisiblityLabels(Configuration conf) throws IOException {
     conf.setInt("hfile.format.version", 3);
+    conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
     appendCoprocessor(conf, CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
       VisibilityController.class.getName());
     appendCoprocessor(conf, CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,