HBASE-10326 Super user should be able scan all the cells irrespective of the visibility labels(Ram)
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1557792 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
634b1a4f1a
commit
721147acf5
|
@ -855,6 +855,11 @@ public class VisibilityController extends BaseRegionObserver implements MasterOb
|
|||
RegionScanner s) throws IOException {
|
||||
HRegion region = e.getEnvironment().getRegion();
|
||||
Authorizations authorizations = null;
|
||||
// If a super user issues a scan, he should be able to scan the cells
|
||||
// irrespective of the Visibility labels
|
||||
if (checkIfScanOrGetFromSuperUser()) {
|
||||
return s;
|
||||
}
|
||||
try {
|
||||
authorizations = scan.getAuthorizations();
|
||||
} catch (DeserializationException de) {
|
||||
|
@ -872,6 +877,15 @@ public class VisibilityController extends BaseRegionObserver implements MasterOb
|
|||
return s;
|
||||
}
|
||||
|
||||
private boolean checkIfScanOrGetFromSuperUser() throws IOException {
|
||||
User user = getActiveUser();
|
||||
if (user != null && user.getShortName() != null) {
|
||||
List<String> auths = this.visibilityManager.getAuths(user.getShortName());
|
||||
return (auths.contains(SYSTEM_LABEL));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionScanner postScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
|
||||
final Scan scan, final RegionScanner s) throws IOException {
|
||||
|
@ -921,6 +935,11 @@ public class VisibilityController extends BaseRegionObserver implements MasterOb
|
|||
public void preGetOp(ObserverContext<RegionCoprocessorEnvironment> e, Get get, List<Cell> results)
|
||||
throws IOException {
|
||||
Authorizations authorizations = null;
|
||||
// If a super user issues a get, he should be able to scan the cells
|
||||
// irrespective of the Visibility labels
|
||||
if (checkIfScanOrGetFromSuperUser()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
authorizations = get.getAuthorizations();
|
||||
} catch (DeserializationException de) {
|
||||
|
|
|
@ -101,7 +101,7 @@ public class TestVisibilityLabels {
|
|||
conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
|
||||
ScanLabelGenerator.class);
|
||||
String currentUser = User.getCurrent().getName();
|
||||
conf.set("hbase.superuser", "admin,"+currentUser);
|
||||
conf.set("hbase.superuser", "admin");
|
||||
TEST_UTIL.startMiniCluster(2);
|
||||
SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
|
||||
|
||||
|
@ -367,12 +367,19 @@ public class TestVisibilityLabels {
|
|||
// Start one new RS
|
||||
RegionServerThread rs = TEST_UTIL.getHBaseCluster().startRegionServer();
|
||||
waitForLabelsRegionAvailability(rs.getRegionServer());
|
||||
PrivilegedExceptionAction<VisibilityLabelsResponse> action =
|
||||
new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
|
||||
public VisibilityLabelsResponse run() throws Exception {
|
||||
String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, "ABC", "XYZ" };
|
||||
try {
|
||||
VisibilityClient.addLabels(conf, labels);
|
||||
} catch (Throwable t) {
|
||||
throw new IOException(t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SUPERUSER.runAs(action);
|
||||
// Scan the visibility label
|
||||
Scan s = new Scan();
|
||||
s.setAuthorizations(new Authorizations(VisibilityUtils.SYSTEM_LABEL));
|
||||
|
@ -437,24 +444,45 @@ public class TestVisibilityLabels {
|
|||
|
||||
@Test
|
||||
public void testAddLabels() throws Throwable {
|
||||
PrivilegedExceptionAction<VisibilityLabelsResponse> action =
|
||||
new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
|
||||
public VisibilityLabelsResponse run() throws Exception {
|
||||
String[] labels = { "L1", SECRET, "L2", "invalid~", "L3" };
|
||||
VisibilityLabelsResponse response = VisibilityClient.addLabels(conf, labels);
|
||||
VisibilityLabelsResponse response = null;
|
||||
try {
|
||||
response = VisibilityClient.addLabels(conf, labels);
|
||||
} catch (Throwable e) {
|
||||
fail("Should not have thrown exception");
|
||||
}
|
||||
List<RegionActionResult> resultList = response.getResultList();
|
||||
assertEquals(5, resultList.size());
|
||||
assertTrue(resultList.get(0).getException().getValue().isEmpty());
|
||||
assertEquals("org.apache.hadoop.hbase.security.visibility.LabelAlreadyExistsException",
|
||||
resultList.get(1).getException().getName());
|
||||
assertTrue(resultList.get(2).getException().getValue().isEmpty());
|
||||
assertEquals("org.apache.hadoop.hbase.security.visibility.InvalidLabelException", resultList
|
||||
.get(3).getException().getName());
|
||||
assertEquals("org.apache.hadoop.hbase.security.visibility.InvalidLabelException",
|
||||
resultList.get(3).getException().getName());
|
||||
assertTrue(resultList.get(4).getException().getValue().isEmpty());
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SUPERUSER.runAs(action);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndGetUserAuths() throws Throwable {
|
||||
final String user = "user1";
|
||||
PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws Exception {
|
||||
String[] auths = { SECRET, CONFIDENTIAL };
|
||||
String user = "user1";
|
||||
try {
|
||||
VisibilityClient.setAuths(conf, auths, user);
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SUPERUSER.runAs(action);
|
||||
HTable ht = null;
|
||||
try {
|
||||
ht = new HTable(conf, LABELS_TABLE_NAME);
|
||||
|
@ -477,7 +505,15 @@ public class TestVisibilityLabels {
|
|||
ht.close();
|
||||
}
|
||||
}
|
||||
GetAuthsResponse authsResponse = VisibilityClient.getAuths(conf, user);
|
||||
|
||||
action = new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws Exception {
|
||||
GetAuthsResponse authsResponse = null;
|
||||
try {
|
||||
authsResponse = VisibilityClient.getAuths(conf, user);
|
||||
} catch (Throwable e) {
|
||||
fail("Should not have failed");
|
||||
}
|
||||
List<String> authsList = new ArrayList<String>();
|
||||
for (ByteString authBS : authsResponse.getAuthList()) {
|
||||
authsList.add(Bytes.toString(authBS.toByteArray()));
|
||||
|
@ -485,31 +521,58 @@ public class TestVisibilityLabels {
|
|||
assertEquals(2, authsList.size());
|
||||
assertTrue(authsList.contains(SECRET));
|
||||
assertTrue(authsList.contains(CONFIDENTIAL));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SUPERUSER.runAs(action);
|
||||
|
||||
// Try doing setAuths once again and there should not be any duplicates
|
||||
action = new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws Exception {
|
||||
String[] auths1 = { SECRET, CONFIDENTIAL };
|
||||
user = "user1";
|
||||
GetAuthsResponse authsResponse = null;
|
||||
try {
|
||||
VisibilityClient.setAuths(conf, auths1, user);
|
||||
|
||||
try {
|
||||
authsResponse = VisibilityClient.getAuths(conf, user);
|
||||
authsList = new ArrayList<String>();
|
||||
} catch (Throwable e) {
|
||||
fail("Should not have failed");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
List<String> authsList = new ArrayList<String>();
|
||||
for (ByteString authBS : authsResponse.getAuthList()) {
|
||||
authsList.add(Bytes.toString(authBS.toByteArray()));
|
||||
}
|
||||
assertEquals(2, authsList.size());
|
||||
assertTrue(authsList.contains(SECRET));
|
||||
assertTrue(authsList.contains(CONFIDENTIAL));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SUPERUSER.runAs(action);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearUserAuths() throws Throwable {
|
||||
PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws Exception {
|
||||
String[] auths = { SECRET, CONFIDENTIAL, PRIVATE };
|
||||
String user = "testUser";
|
||||
try {
|
||||
VisibilityClient.setAuths(conf, auths, user);
|
||||
} catch (Throwable e) {
|
||||
fail("Should not have failed");
|
||||
}
|
||||
// Removing the auths for SECRET and CONFIDENTIAL for the user.
|
||||
// Passing a non existing auth also.
|
||||
auths = new String[] { SECRET, PUBLIC, CONFIDENTIAL };
|
||||
VisibilityLabelsResponse response = VisibilityClient.clearAuths(conf, auths, user);
|
||||
VisibilityLabelsResponse response = null;
|
||||
try {
|
||||
response = VisibilityClient.clearAuths(conf, auths, user);
|
||||
} catch (Throwable e) {
|
||||
fail("Should not have failed");
|
||||
}
|
||||
List<RegionActionResult> resultList = response.getResultList();
|
||||
assertEquals(3, resultList.size());
|
||||
assertTrue(resultList.get(0).getException().getValue().isEmpty());
|
||||
|
@ -524,8 +587,8 @@ public class TestVisibilityLabels {
|
|||
while ((result = scanner.next()) != null) {
|
||||
Cell label = result.getColumnLatestCell(LABELS_TABLE_FAMILY, LABEL_QUALIFIER);
|
||||
Cell userAuth = result.getColumnLatestCell(LABELS_TABLE_FAMILY, user.getBytes());
|
||||
if (Bytes.equals(PRIVATE.getBytes(), 0, PRIVATE.getBytes().length, label.getValueArray(),
|
||||
label.getValueOffset(), label.getValueLength())) {
|
||||
if (Bytes.equals(PRIVATE.getBytes(), 0, PRIVATE.getBytes().length,
|
||||
label.getValueArray(), label.getValueOffset(), label.getValueLength())) {
|
||||
assertNotNull(userAuth);
|
||||
} else {
|
||||
assertNull(userAuth);
|
||||
|
@ -537,13 +600,22 @@ public class TestVisibilityLabels {
|
|||
}
|
||||
}
|
||||
|
||||
GetAuthsResponse authsResponse = VisibilityClient.getAuths(conf, user);
|
||||
GetAuthsResponse authsResponse = null;
|
||||
try {
|
||||
authsResponse = VisibilityClient.getAuths(conf, user);
|
||||
} catch (Throwable e) {
|
||||
fail("Should not have failed");
|
||||
}
|
||||
List<String> authsList = new ArrayList<String>();
|
||||
for (ByteString authBS : authsResponse.getAuthList()) {
|
||||
authsList.add(Bytes.toString(authBS.toByteArray()));
|
||||
}
|
||||
assertEquals(1, authsList.size());
|
||||
assertTrue(authsList.contains(PRIVATE));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SUPERUSER.runAs(action);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.apache.hadoop.hbase.security.access.AccessController;
|
|||
import org.apache.hadoop.hbase.security.access.Permission;
|
||||
import org.apache.hadoop.hbase.security.access.SecureTestUtil;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
|
@ -75,7 +74,8 @@ public class TestVisibilityLabelsWithACL {
|
|||
@Rule
|
||||
public final TestName TEST_NAME = new TestName();
|
||||
private static User SUPERUSER;
|
||||
private static User NORMAL_USER;
|
||||
private static User NORMAL_USER1;
|
||||
private static User NORMAL_USER2;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupBeforeClass() throws Exception {
|
||||
|
@ -95,7 +95,8 @@ public class TestVisibilityLabelsWithACL {
|
|||
|
||||
// Create users for testing
|
||||
SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
|
||||
NORMAL_USER = User.createUserForTesting(conf, "user1", new String[] {});
|
||||
NORMAL_USER1 = User.createUserForTesting(conf, "user1", new String[] {});
|
||||
NORMAL_USER2 = User.createUserForTesting(conf, "user2", new String[] {});
|
||||
// Grant NORMAL_USER EXEC privilege on the labels table. For the purposes of this
|
||||
// test, we want to insure that access is denied even with the ability to access
|
||||
// the endpoint.
|
||||
|
@ -104,7 +105,9 @@ public class TestVisibilityLabelsWithACL {
|
|||
BlockingRpcChannel service = acl.coprocessorService(LABELS_TABLE_NAME.getName());
|
||||
AccessControlService.BlockingInterface protocol =
|
||||
AccessControlService.newBlockingStub(service);
|
||||
ProtobufUtil.grant(protocol, NORMAL_USER.getShortName(), LABELS_TABLE_NAME, null, null,
|
||||
ProtobufUtil.grant(protocol, NORMAL_USER1.getShortName(), LABELS_TABLE_NAME, null, null,
|
||||
Permission.Action.EXEC);
|
||||
ProtobufUtil.grant(protocol, NORMAL_USER2.getShortName(), LABELS_TABLE_NAME, null, null,
|
||||
Permission.Action.EXEC);
|
||||
} finally {
|
||||
acl.close();
|
||||
|
@ -119,11 +122,21 @@ public class TestVisibilityLabelsWithACL {
|
|||
@Test
|
||||
public void testScanForUserWithFewerLabelAuthsThanLabelsInScanAuthorizations() throws Throwable {
|
||||
String[] auths = { SECRET };
|
||||
String user = "admin";
|
||||
String user = "user2";
|
||||
VisibilityClient.setAuths(conf, auths, user);
|
||||
TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
|
||||
final HTable table = createTableAndWriteDataWithLabels(tableName, SECRET + "&" + CONFIDENTIAL
|
||||
+ "&!" + PRIVATE, SECRET + "&!" + PRIVATE);
|
||||
HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
|
||||
try {
|
||||
BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
|
||||
AccessControlService.BlockingInterface protocol = AccessControlService
|
||||
.newBlockingStub(service);
|
||||
ProtobufUtil.grant(protocol, NORMAL_USER2.getShortName(), tableName, null, null,
|
||||
Permission.Action.READ);
|
||||
} finally {
|
||||
acl.close();
|
||||
}
|
||||
PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws Exception {
|
||||
Scan s = new Scan();
|
||||
|
@ -142,6 +155,57 @@ public class TestVisibilityLabelsWithACL {
|
|||
return null;
|
||||
}
|
||||
};
|
||||
NORMAL_USER2.runAs(scanAction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanForSuperUserWithFewerLabelAuths() throws Throwable {
|
||||
String[] auths = { SECRET };
|
||||
String user = "admin";
|
||||
VisibilityClient.setAuths(conf, auths, user);
|
||||
TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
|
||||
final HTable table = createTableAndWriteDataWithLabels(tableName, SECRET + "&" + CONFIDENTIAL
|
||||
+ "&!" + PRIVATE, SECRET + "&!" + PRIVATE);
|
||||
PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws Exception {
|
||||
Scan s = new Scan();
|
||||
s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
|
||||
HTable t = new HTable(conf, table.getTableName());
|
||||
try {
|
||||
ResultScanner scanner = t.getScanner(s);
|
||||
Result[] result = scanner.next(5);
|
||||
assertTrue(result.length == 2);
|
||||
} finally {
|
||||
t.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SUPERUSER.runAs(scanAction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetForSuperUserWithFewerLabelAuths() throws Throwable {
|
||||
String[] auths = { SECRET };
|
||||
String user = "admin";
|
||||
VisibilityClient.setAuths(conf, auths, user);
|
||||
TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
|
||||
final HTable table = createTableAndWriteDataWithLabels(tableName, SECRET + "&" + CONFIDENTIAL
|
||||
+ "&!" + PRIVATE, SECRET + "&!" + PRIVATE);
|
||||
PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws Exception {
|
||||
Get g = new Get(row1);
|
||||
g.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
|
||||
HTable t = new HTable(conf, table.getTableName());
|
||||
try {
|
||||
Result result = t.get(g);
|
||||
assertTrue(!result.isEmpty());
|
||||
} finally {
|
||||
t.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SUPERUSER.runAs(scanAction);
|
||||
}
|
||||
|
||||
|
@ -153,6 +217,19 @@ public class TestVisibilityLabelsWithACL {
|
|||
VisibilityClient.setAuths(conf, auths, "user1");
|
||||
TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
|
||||
final HTable table = createTableAndWriteDataWithLabels(tableName, SECRET);
|
||||
HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
|
||||
try {
|
||||
BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
|
||||
AccessControlService.BlockingInterface protocol = AccessControlService
|
||||
.newBlockingStub(service);
|
||||
ProtobufUtil.grant(protocol, NORMAL_USER1.getShortName(), tableName, null, null,
|
||||
Permission.Action.READ);
|
||||
ProtobufUtil.grant(protocol, NORMAL_USER2.getShortName(), tableName, null, null,
|
||||
Permission.Action.READ);
|
||||
} finally {
|
||||
acl.close();
|
||||
}
|
||||
|
||||
PrivilegedExceptionAction<Void> getAction = new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws Exception {
|
||||
Get g = new Get(row1);
|
||||
|
@ -167,7 +244,7 @@ public class TestVisibilityLabelsWithACL {
|
|||
return null;
|
||||
}
|
||||
};
|
||||
SUPERUSER.runAs(getAction);
|
||||
NORMAL_USER2.runAs(getAction);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -182,7 +259,7 @@ public class TestVisibilityLabelsWithACL {
|
|||
return null;
|
||||
}
|
||||
};
|
||||
VisibilityLabelsResponse response = NORMAL_USER.runAs(action);
|
||||
VisibilityLabelsResponse response = NORMAL_USER1.runAs(action);
|
||||
assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response
|
||||
.getResult(0).getException().getName());
|
||||
assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response
|
||||
|
@ -197,7 +274,7 @@ public class TestVisibilityLabelsWithACL {
|
|||
return null;
|
||||
}
|
||||
};
|
||||
response = NORMAL_USER.runAs(action);
|
||||
response = NORMAL_USER1.runAs(action);
|
||||
assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response
|
||||
.getResult(0).getException().getName());
|
||||
assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response
|
||||
|
@ -225,7 +302,7 @@ public class TestVisibilityLabelsWithACL {
|
|||
return null;
|
||||
}
|
||||
};
|
||||
response = NORMAL_USER.runAs(action);
|
||||
response = NORMAL_USER1.runAs(action);
|
||||
assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response.getResult(0)
|
||||
.getException().getName());
|
||||
assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response.getResult(1)
|
||||
|
@ -235,18 +312,18 @@ public class TestVisibilityLabelsWithACL {
|
|||
assertTrue(response.getResult(0).getException().getValue().isEmpty());
|
||||
assertTrue(response.getResult(1).getException().getValue().isEmpty());
|
||||
|
||||
VisibilityClient.setAuths(conf, new String[] { CONFIDENTIAL, PRIVATE }, "user2");
|
||||
VisibilityClient.setAuths(conf, new String[] { CONFIDENTIAL, PRIVATE }, "user3");
|
||||
PrivilegedExceptionAction<GetAuthsResponse> action1 =
|
||||
new PrivilegedExceptionAction<GetAuthsResponse>() {
|
||||
public GetAuthsResponse run() throws Exception {
|
||||
try {
|
||||
return VisibilityClient.getAuths(conf, "user2");
|
||||
return VisibilityClient.getAuths(conf, "user3");
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
GetAuthsResponse authsResponse = NORMAL_USER.runAs(action1);
|
||||
GetAuthsResponse authsResponse = NORMAL_USER1.runAs(action1);
|
||||
assertNull(authsResponse);
|
||||
authsResponse = SUPERUSER.runAs(action1);
|
||||
List<String> authsList = new ArrayList<String>();
|
||||
|
|
Loading…
Reference in New Issue