diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.java index 4de83b5..b96f99d 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.java @@ -79,6 +79,7 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService private HRegion labelsRegion; private VisibilityLabelsCache labelsCache; private List scanLabelGenerators; + private List superUsers; static { ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -115,6 +116,7 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService throw ioe; } this.scanLabelGenerators = VisibilityUtils.getScanLabelGenerators(this.conf); + this.superUsers = getSystemAndSuperUsers(); if (e.getRegion().getRegionInfo().getTable().equals(LABELS_TABLE_NAME)) { this.labelsRegion = e.getRegion(); Pair, Map>> labelsAndUserAuths = @@ -195,22 +197,8 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService if (!labels.containsKey(SYSTEM_LABEL)) { Put p = new Put(Bytes.toBytes(SYSTEM_LABEL_ORDINAL)); p.addImmutable(LABELS_TABLE_FAMILY, LABEL_QUALIFIER, Bytes.toBytes(SYSTEM_LABEL)); - // Set auth for "system" label for all super users. - List superUsers = getSystemAndSuperUsers(); - for (String superUser : superUsers) { - p.addImmutable(LABELS_TABLE_FAMILY, Bytes.toBytes(superUser), DUMMY_VALUE, - LABELS_TABLE_TAGS); - } region.put(p); labels.put(SYSTEM_LABEL, SYSTEM_LABEL_ORDINAL); - for (String superUser : superUsers) { - List auths = userAuths.get(superUser); - if (auths == null) { - auths = new ArrayList(1); - userAuths.put(superUser, auths); - } - auths.add(SYSTEM_LABEL_ORDINAL); - } } } @@ -394,9 +382,11 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService if (labelAddition) { byte[] serialized = VisibilityUtils.getDataToWriteToZooKeeper(existingLabels); this.labelsCache.writeToZookeeper(serialized, true); + this.labelsCache.refreshLabelsCache(serialized); } else { byte[] serialized = VisibilityUtils.getUserAuthsDataToWriteToZooKeeper(userAuths); this.labelsCache.writeToZookeeper(serialized, false); + this.labelsCache.refreshUserAuthsCache(serialized); } } @@ -405,7 +395,7 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService throws IOException { // If a super user issues a get/scan, he should be able to scan the cells // irrespective of the Visibility labels - if (isReadFromSuperUser()) { + if (isReadFromSystemAuthUser()) { return new VisibilityExpEvaluator() { @Override public boolean evaluate(Cell cell) throws IOException { @@ -484,19 +474,28 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService }; } - protected boolean isReadFromSuperUser() throws IOException { + protected boolean isReadFromSystemAuthUser() throws IOException { byte[] user = Bytes.toBytes(VisibilityUtils.getActiveUser().getShortName()); return havingSystemAuth(user); } @Override public boolean havingSystemAuth(byte[] user) throws IOException { + // A super user has 'system' auth. + if (isSystemOrSuperUser(user)) { + return true; + } + // A user can also be explicitly granted 'system' auth. List auths = this.getAuths(user, true); if (LOG.isTraceEnabled()) { LOG.trace("The auths for user " + Bytes.toString(user) + " are " + auths); } return auths.contains(SYSTEM_LABEL); } + + protected boolean isSystemOrSuperUser(byte[] user) throws IOException { + return this.superUsers.contains(Bytes.toString(user)); + } @Override public boolean matchVisibility(List putVisTags, Byte putTagsFormat, List deleteVisTags, diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.java index 285757a..7681fe0 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.java @@ -79,6 +79,7 @@ public class ExpAsStringVisibilityLabelServiceImpl implements VisibilityLabelSer private Configuration conf; private HRegion labelsRegion; private List scanLabelGenerators; + private List superUsers; @Override public OperationStatus[] addLabels(List labels) throws IOException { @@ -197,7 +198,7 @@ public class ExpAsStringVisibilityLabelServiceImpl implements VisibilityLabelSer throws IOException { // If a super user issues a get/scan, he should be able to scan the cells // irrespective of the Visibility labels - if (isReadFromSuperUser()) { + if (isReadFromSystemAuthUser()) { return new VisibilityExpEvaluator() { @Override public boolean evaluate(Cell cell) throws IOException { @@ -267,7 +268,7 @@ public class ExpAsStringVisibilityLabelServiceImpl implements VisibilityLabelSer }; } - protected boolean isReadFromSuperUser() throws IOException { + protected boolean isReadFromSystemAuthUser() throws IOException { byte[] user = Bytes.toBytes(VisibilityUtils.getActiveUser().getShortName()); return havingSystemAuth(user); } @@ -333,19 +334,9 @@ public class ExpAsStringVisibilityLabelServiceImpl implements VisibilityLabelSer @Override public void init(RegionCoprocessorEnvironment e) throws IOException { this.scanLabelGenerators = VisibilityUtils.getScanLabelGenerators(this.conf); + this.superUsers = getSystemAndSuperUsers(); if (e.getRegion().getRegionInfo().getTable().equals(LABELS_TABLE_NAME)) { this.labelsRegion = e.getRegion(); - // Set auth for "system" label for all super users. - List superUsers = getSystemAndSuperUsers(); - for (String superUser : superUsers) { - byte[] user = Bytes.toBytes(superUser); - List auths = this.getAuths(user, true); - if (auths == null || auths.isEmpty()) { - Put p = new Put(user); - p.addImmutable(LABELS_TABLE_FAMILY, Bytes.toBytes(SYSTEM_LABEL), DUMMY_VALUE); - labelsRegion.put(p); - } - } } } @@ -364,8 +355,15 @@ public class ExpAsStringVisibilityLabelServiceImpl implements VisibilityLabelSer return superUsers; } + protected boolean isSystemOrSuperUser(byte[] user) throws IOException { + return this.superUsers.contains(Bytes.toString(user)); + } + @Override public boolean havingSystemAuth(byte[] user) throws IOException { + if (isSystemOrSuperUser(user)) { + return true; + } List auths = this.getAuths(user, true); return auths.contains(SYSTEM_LABEL); } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestDefaultScanLabelGeneratorStack.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestDefaultScanLabelGeneratorStack.java index df2a61c..5a74c7a 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestDefaultScanLabelGeneratorStack.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestDefaultScanLabelGeneratorStack.java @@ -31,6 +31,8 @@ import org.apache.hadoop.hbase.CellScanner; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Connection; +import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.client.Put; @@ -124,6 +126,46 @@ public class TestDefaultScanLabelGeneratorStack { } }); + // Test that super user can see all the cells. + SUPERUSER.runAs(new PrivilegedExceptionAction() { + public Void run() throws Exception { + Connection connection = ConnectionFactory.createConnection(conf); + Table table = connection.getTable(tableName); + try { + Scan s = new Scan(); + ResultScanner scanner = table.getScanner(s); + Result[] next = scanner.next(1); + + // Test that super user can see all the cells. + assertTrue(next.length == 1); + CellScanner cellScanner = next[0].cellScanner(); + cellScanner.advance(); + Cell current = cellScanner.current(); + assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(), + current.getRowLength(), ROW_1, 0, ROW_1.length)); + assertTrue(Bytes.equals(current.getQualifier(), Q1)); + assertTrue(Bytes.equals(current.getValue(), value1)); + cellScanner.advance(); + current = cellScanner.current(); + assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(), + current.getRowLength(), ROW_1, 0, ROW_1.length)); + assertTrue(Bytes.equals(current.getQualifier(), Q2)); + assertTrue(Bytes.equals(current.getValue(), value2)); + cellScanner.advance(); + current = cellScanner.current(); + assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(), + current.getRowLength(), ROW_1, 0, ROW_1.length)); + assertTrue(Bytes.equals(current.getQualifier(), Q3)); + assertTrue(Bytes.equals(current.getValue(), value3)); + + return null; + } finally { + table.close(); + connection.close(); + } + } + }); + TESTUSER.runAs(new PrivilegedExceptionAction() { public Void run() throws Exception { Table table = new HTable(conf, tableName); @@ -193,7 +235,6 @@ public class TestDefaultScanLabelGeneratorStack { assertFalse(cellScanner2.advance()); - return null; } finally { table.close(); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestEnforcingScanLabelGenerator.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestEnforcingScanLabelGenerator.java index 916f730..a06f03d 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestEnforcingScanLabelGenerator.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestEnforcingScanLabelGenerator.java @@ -28,6 +28,8 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Connection; +import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.client.Put; @@ -119,6 +121,26 @@ public class TestEnforcingScanLabelGenerator { } }); + // Test that super user can see all the cells. + SUPERUSER.runAs(new PrivilegedExceptionAction() { + public Void run() throws Exception { + Connection connection = ConnectionFactory.createConnection(conf); + Table table = connection.getTable(tableName); + try { + // Test that super user can see all the cells. + Get get = new Get(ROW_1); + Result result = table.get(get); + assertTrue("Missing authorization", result.containsColumn(CF, Q1)); + assertTrue("Missing authorization", result.containsColumn(CF, Q2)); + assertTrue("Missing authorization", result.containsColumn(CF, Q3)); + return null; + } finally { + table.close(); + connection.close(); + } + } + }); + TESTUSER.runAs(new PrivilegedExceptionAction() { public Void run() throws Exception { Table table = new HTable(conf, tableName);