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:
anoopsamjohn 2014-01-13 17:53:40 +00:00
parent 634b1a4f1a
commit 721147acf5
3 changed files with 262 additions and 94 deletions

View File

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

View File

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

View File

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