HBASE-12644 Visibility Labels: issue with storing super users in labels table (Jerry He)

This commit is contained in:
tedyu 2014-12-13 09:13:49 -08:00
parent d4853f0379
commit 4d218bb2ed
5 changed files with 96 additions and 41 deletions

View File

@ -80,6 +80,7 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService
private HRegion labelsRegion;
private VisibilityLabelsCache labelsCache;
private List<ScanLabelGenerator> scanLabelGenerators;
private List<String> superUsers;
static {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@ -116,6 +117,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<String, Integer>, Map<String, List<Integer>>> labelsAndUserAuths =
@ -196,22 +198,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<String> 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<Integer> auths = userAuths.get(superUser);
if (auths == null) {
auths = new ArrayList<Integer>(1);
userAuths.put(superUser, auths);
}
auths.add(SYSTEM_LABEL_ORDINAL);
}
}
}
@ -426,7 +414,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 {
@ -505,13 +493,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<String> auths = this.getAuths(user, true);
if (LOG.isTraceEnabled()) {
LOG.trace("The auths for user " + Bytes.toString(user) + " are " + auths);
@ -519,6 +512,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<Tag> putVisTags, Byte putTagsFormat, List<Tag> deleteVisTags,
Byte deleteTagsFormat) throws IOException {

View File

@ -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);

View File

@ -79,6 +79,7 @@ public class ExpAsStringVisibilityLabelServiceImpl implements VisibilityLabelSer
private Configuration conf;
private HRegion labelsRegion;
private List<ScanLabelGenerator> scanLabelGenerators;
private List<String> superUsers;
@Override
public OperationStatus[] addLabels(List<byte[]> labels) throws IOException {
@ -203,7 +204,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 {
@ -273,7 +274,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);
}
@ -339,19 +340,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<String> superUsers = getSystemAndSuperUsers();
for (String superUser : superUsers) {
byte[] user = Bytes.toBytes(superUser);
List<String> 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);
}
}
}
}
@ -370,8 +361,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<String> auths = this.getAuths(user, true);
return auths.contains(SYSTEM_LABEL);
}

View File

@ -32,6 +32,8 @@ import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.testclassification.MediumTests;
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.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
@ -122,6 +124,46 @@ public class TestDefaultScanLabelGeneratorStack {
}
});
// Test that super user can see all the cells.
SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() {
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<Void>() {
public Void run() throws Exception {
Table table = new HTable(conf, tableName);
@ -191,7 +233,6 @@ public class TestDefaultScanLabelGeneratorStack {
assertFalse(cellScanner2.advance());
return null;
} finally {
table.close();

View File

@ -29,6 +29,8 @@ import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.testclassification.MediumTests;
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;
@ -118,6 +120,26 @@ public class TestEnforcingScanLabelGenerator {
}
});
// Test that super user can see all the cells.
SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() {
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<Void>() {
public Void run() throws Exception {
Table table = new HTable(conf, tableName);