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 c942cb4..16b2f76 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); - } } } @@ -421,7 +409,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 { @@ -500,13 +488,18 @@ 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); @@ -514,6 +507,10 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService 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, Byte deleteTagsFormat) throws IOException { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/ZKVisibilityLabelWatcher.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/ZKVisibilityLabelWatcher.java index 5c12d86..4941a54 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/ZKVisibilityLabelWatcher.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/ZKVisibilityLabelWatcher.java @@ -59,17 +59,15 @@ public class ZKVisibilityLabelWatcher extends ZooKeeperListener { public void start() throws KeeperException { watcher.registerListener(this); - if (ZKUtil.watchAndCheckExists(watcher, labelZnode)) { - byte[] data = ZKUtil.getDataAndWatch(watcher, labelZnode); - if (data != null) { - refreshVisibilityLabelsCache(data); - } + ZKUtil.createWithParents(watcher, labelZnode); + ZKUtil.createWithParents(watcher, userAuthsZnode); + byte[] data = ZKUtil.getDataAndWatch(watcher, labelZnode); + if (data != null && data.length > 0) { + refreshVisibilityLabelsCache(data); } - if (ZKUtil.watchAndCheckExists(watcher, userAuthsZnode)) { - byte[] data = ZKUtil.getDataAndWatch(watcher, userAuthsZnode); - if (data != null) { - refreshUserAuthsCache(data); - } + data = ZKUtil.getDataAndWatch(watcher, userAuthsZnode); + if (data != null && data.length > 0) { + refreshUserAuthsCache(data); } } @@ -143,7 +141,6 @@ public class ZKVisibilityLabelWatcher extends ZooKeeperListener { znode = this.userAuthsZnode; } try { - ZKUtil.createWithParents(watcher, znode); ZKUtil.updateExistingNodeData(watcher, znode, data, -1); } catch (KeeperException e) { LOG.error("Failed writing to " + znode, e); 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 c9ef5f0..0e0fcba 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 @@ -78,6 +78,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 { @@ -202,7 +203,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 { @@ -272,7 +273,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); } @@ -338,19 +339,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); - } - } } } @@ -369,8 +360,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 16c4f93..b767d70 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 @@ -121,6 +121,44 @@ public class TestDefaultScanLabelGeneratorStack { } }); + // Test that super user can see all the cells. + SUPERUSER.runAs(new PrivilegedExceptionAction() { + public Void run() throws Exception { + HTable table = new HTable(conf, 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(); + } + } + }); + TESTUSER.runAs(new PrivilegedExceptionAction() { public Void run() throws Exception { HTable table = new HTable(conf, tableName); @@ -190,7 +228,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 08912d9..7e1094c 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 @@ -117,6 +117,24 @@ public class TestEnforcingScanLabelGenerator { } }); + // Test that super user can see all the cells. + SUPERUSER.runAs(new PrivilegedExceptionAction() { + public Void run() throws Exception { + HTable table = new HTable(conf, 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(); + } + } + }); + TESTUSER.runAs(new PrivilegedExceptionAction() { public Void run() throws Exception { HTable table = new HTable(conf, tableName);