下面列出了怎么用org.apache.hadoop.hbase.security.AccessDeniedException的API类实例代码及写法,或者点击链接到github查看源代码。
boolean canSkipAccessCheck(User user, final String operation, String access, final RegionCoprocessorEnvironment regionServerEnv) throws AccessDeniedException {
// read access to metadata tables is always allowed and isn't audited.
if (isAccessForMetaTables(regionServerEnv) && _authUtils.isReadAccess(access)) {
LOG.debug("isKnownAccessPattern: exiting: Read access for metadata tables allowed, not audited!");
return true;
}
// if write access is desired to metatables then global create access is sufficient
if (_authUtils.isWriteAccess(access) && isAccessForMetaTables(regionServerEnv)) {
String createAccess = _authUtils.getAccess(Action.CREATE);
AuthorizationSession session = new AuthorizationSession(hbasePlugin)
.operation(operation)
.remoteAddress(getRemoteAddress())
.user(user)
.access(createAccess)
.buildRequest()
.authorize();
if (session.isAuthorized()) {
// NOTE: this access isn't logged
LOG.debug("isKnownAccessPattern: exiting: User has global create access, allowed!");
return true;
}
}
return false;
}
/**
* Authorizes that the current user has any of the given permissions to access the table.
*
* @param user Active user to which authorization checks should be applied
* @param request Request type.
* @param tableName Table requested
* @param permissions Actions being requested
* @throws IOException if obtaining the current user fails
* @throws AccessDeniedException if user has no authorization
*/
public void requireAccess(User user, String request, TableName tableName,
Action... permissions) throws IOException {
AuthResult result = null;
for (Action permission : permissions) {
if (authManager.accessUserTable(user, tableName, permission)) {
result = AuthResult.allow(request, "Table permission granted",
user, permission, tableName, null, null);
break;
} else {
// rest of the world
result = AuthResult.deny(request, "Insufficient permissions",
user, permission, tableName, null, null);
}
}
logResult(result);
if (!result.isAllowed()) {
throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
}
}
/**
* Checks that the user has the given global permission. The generated
* audit log message will contain context information for the operation
* being authorized, based on the given parameters.
*
* @param user Active user to which authorization checks should be applied
* @param request Request type
* @param perm Action being requested
* @param tableName Affected table name.
* @param familyMap Affected column families.
* @param filterUser User name to be filtered from permission as requested
*/
public void requireGlobalPermission(User user, String request,
Action perm, TableName tableName,
Map<byte[], ? extends Collection<byte[]>> familyMap, String filterUser) throws IOException {
AuthResult result;
if (authManager.authorizeUserGlobal(user, perm)) {
result = AuthResult.allow(request, "Global check allowed", user, perm, tableName, familyMap);
} else {
result = AuthResult.deny(request, "Global check failed", user, perm, tableName, familyMap);
}
result.getParams().setTableName(tableName).setFamilies(familyMap);
result.getParams().addExtraParam("filterUser", filterUser);
logResult(result);
if (!result.isAllowed()) {
throw new AccessDeniedException(
"Insufficient permissions for user '" + (user != null ? user.getShortName() : "null")
+ "' (global, action=" + perm.toString() + ")");
}
}
/**
* Checks that the user has the given global permission. The generated
* audit log message will contain context information for the operation
* being authorized, based on the given parameters.
*
* @param user Active user to which authorization checks should be applied
* @param request Request type
* @param perm Action being requested
* @param namespace The given namespace
*/
public void requireGlobalPermission(User user, String request, Action perm,
String namespace) throws IOException {
AuthResult authResult;
if (authManager.authorizeUserGlobal(user, perm)) {
authResult = AuthResult.allow(request, "Global check allowed", user, perm, null);
authResult.getParams().setNamespace(namespace);
logResult(authResult);
} else {
authResult = AuthResult.deny(request, "Global check failed", user, perm, null);
authResult.getParams().setNamespace(namespace);
logResult(authResult);
throw new AccessDeniedException(
"Insufficient permissions for user '" + (user != null ? user.getShortName() : "null")
+ "' (global, action=" + perm.toString() + ")");
}
}
/**
* Checks that the user has the given global or namespace permission.
* @param user Active user to which authorization checks should be applied
* @param request Request type
* @param namespace Name space as requested
* @param filterUser User name to be filtered from permission as requested
* @param permissions Actions being requested
*/
public void requireNamespacePermission(User user, String request, String namespace,
String filterUser, Action... permissions) throws IOException {
AuthResult result = null;
for (Action permission : permissions) {
if (authManager.authorizeUserNamespace(user, namespace, permission)) {
result =
AuthResult.allow(request, "Namespace permission granted", user, permission, namespace);
break;
} else {
// rest of the world
result = AuthResult.deny(request, "Insufficient permissions", user, permission, namespace);
}
}
result.getParams().addExtraParam("filterUser", filterUser);
logResult(result);
if (!result.isAllowed()) {
throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
}
}
/**
* Checks that the user has the given global or namespace permission.
*
* @param user Active user to which authorization checks should be applied
* @param request Request type
* @param namespace The given namespace
* @param tableName Table requested
* @param familyMap Column family map requested
* @param permissions Actions being requested
*/
public void requireNamespacePermission(User user, String request, String namespace,
TableName tableName, Map<byte[], ? extends Collection<byte[]>> familyMap,
Action... permissions) throws IOException {
AuthResult result = null;
for (Action permission : permissions) {
if (authManager.authorizeUserNamespace(user, namespace, permission)) {
result =
AuthResult.allow(request, "Namespace permission granted", user, permission, namespace);
result.getParams().setTableName(tableName).setFamilies(familyMap);
break;
} else {
// rest of the world
result = AuthResult.deny(request, "Insufficient permissions", user, permission, namespace);
result.getParams().setTableName(tableName).setFamilies(familyMap);
}
}
logResult(result);
if (!result.isAllowed()) {
throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
}
}
/**
* Authorizes that the current user has any of the given permissions for the
* given table, column family and column qualifier.
*
* @param user Active user to which authorization checks should be applied
* @param request Request type
* @param tableName Table requested
* @param family Column family requested
* @param qualifier Column qualifier requested
* @param filterUser User name to be filtered from permission as requested
* @param permissions Actions being requested
* @throws IOException if obtaining the current user fails
* @throws AccessDeniedException if user has no authorization
*/
public void requirePermission(User user, String request, TableName tableName, byte[] family,
byte[] qualifier, String filterUser, Action... permissions) throws IOException {
AuthResult result = null;
for (Action permission : permissions) {
if (authManager.authorizeUserTable(user, tableName, family, qualifier, permission)) {
result = AuthResult.allow(request, "Table permission granted",
user, permission, tableName, family, qualifier);
break;
} else {
// rest of the world
result = AuthResult.deny(request, "Insufficient permissions",
user, permission, tableName, family, qualifier);
}
}
result.getParams().addExtraParam("filterUser", filterUser);
logResult(result);
if (!result.isAllowed()) {
throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
}
}
/**
* Authorizes that the current user has any of the given permissions for the
* given table, column family and column qualifier.
*
* @param user Active user to which authorization checks should be applied
* @param request Request type
* @param tableName Table requested
* @param family Column family param
* @param qualifier Column qualifier param
* @throws IOException if obtaining the current user fails
* @throws AccessDeniedException if user has no authorization
*/
public void requireTablePermission(User user, String request,
TableName tableName,byte[] family, byte[] qualifier,
Action... permissions) throws IOException {
AuthResult result = null;
for (Action permission : permissions) {
if (authManager.authorizeUserTable(user, tableName, permission)) {
result = AuthResult.allow(request, "Table permission granted",
user, permission, tableName, null, null);
result.getParams().setFamily(family).setQualifier(qualifier);
break;
} else {
// rest of the world
result = AuthResult.deny(request, "Insufficient permissions",
user, permission, tableName, family, qualifier);
result.getParams().setFamily(family).setQualifier(qualifier);
}
}
logResult(result);
if (!result.isAllowed()) {
throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
}
}
/**
* Check if caller is granting or revoking superusers's or supergroups's permissions.
* @param request request name
* @param caller caller
* @param userToBeChecked target user or group
* @throws IOException AccessDeniedException if target user is superuser
*/
public void performOnSuperuser(String request, User caller, String userToBeChecked)
throws IOException {
List<String> userGroups = new ArrayList<>();
userGroups.add(userToBeChecked);
if (!AuthUtil.isGroupPrincipal(userToBeChecked)) {
for (String group : getUserGroups(userToBeChecked)) {
userGroups.add(AuthUtil.toGroupEntry(group));
}
}
for (String name : userGroups) {
if (Superusers.isSuperUser(name)) {
AuthResult result = AuthResult.deny(
request,
"Granting or revoking superusers's or supergroups's permissions is not allowed",
caller,
Action.ADMIN,
NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR);
logResult(result);
throw new AccessDeniedException(result.getReason());
}
}
}
private void checkForReservedTagPresence(User user, Mutation m) throws IOException {
// No need to check if we're not going to throw
if (!authorizationEnabled) {
m.setAttribute(TAG_CHECK_PASSED, TRUE);
return;
}
// Superusers are allowed to store cells unconditionally.
if (Superusers.isSuperUser(user)) {
m.setAttribute(TAG_CHECK_PASSED, TRUE);
return;
}
// We already checked (prePut vs preBatchMutation)
if (m.getAttribute(TAG_CHECK_PASSED) != null) {
return;
}
for (CellScanner cellScanner = m.cellScanner(); cellScanner.advance();) {
Iterator<Tag> tagsItr = PrivateCellUtil.tagsIterator(cellScanner.current());
while (tagsItr.hasNext()) {
if (tagsItr.next().getType() == PermissionStorage.ACL_TAG_TYPE) {
throw new AccessDeniedException("Mutation contains cell with reserved type tag");
}
}
}
m.setAttribute(TAG_CHECK_PASSED, TRUE);
}
@Override
public void postListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
List<NamespaceDescriptor> descriptors) throws IOException {
// Retains only those which passes authorization checks, as the checks weren't done as part
// of preGetTableDescriptors.
Iterator<NamespaceDescriptor> itr = descriptors.iterator();
User user = getActiveUser(ctx);
while (itr.hasNext()) {
NamespaceDescriptor desc = itr.next();
try {
accessChecker.requireNamespacePermission(user, "listNamespaces", desc.getName(), null,
Action.ADMIN);
} catch (AccessDeniedException e) {
itr.remove();
}
}
}
@Override
public Result preAppendAfterRowLock(final ObserverContext<RegionCoprocessorEnvironment> c,
final Append append) throws IOException {
if (append.getAttribute(CHECK_COVERING_PERM) != null) {
// We had failure with table, cf and q perm checks and now giving a chance for cell
// perm check
TableName table = c.getEnvironment().getRegion().getRegionInfo().getTable();
AuthResult authResult = null;
User user = getActiveUser(c);
if (checkCoveringPermission(user, OpType.APPEND, c.getEnvironment(), append.getRow(),
append.getFamilyCellMap(), append.getTimeRange().getMax(), Action.WRITE)) {
authResult = AuthResult.allow(OpType.APPEND.toString(),
"Covering cell set", user, Action.WRITE, table, append.getFamilyCellMap());
} else {
authResult = AuthResult.deny(OpType.APPEND.toString(),
"Covering cell set", user, Action.WRITE, table, append.getFamilyCellMap());
}
AccessChecker.logResult(authResult);
if (authorizationEnabled && !authResult.isAllowed()) {
throw new AccessDeniedException("Insufficient permissions " +
authResult.toContextString());
}
}
return null;
}
@Override
public Result preIncrementAfterRowLock(final ObserverContext<RegionCoprocessorEnvironment> c,
final Increment increment) throws IOException {
if (increment.getAttribute(CHECK_COVERING_PERM) != null) {
// We had failure with table, cf and q perm checks and now giving a chance for cell
// perm check
TableName table = c.getEnvironment().getRegion().getRegionInfo().getTable();
AuthResult authResult = null;
User user = getActiveUser(c);
if (checkCoveringPermission(user, OpType.INCREMENT, c.getEnvironment(), increment.getRow(),
increment.getFamilyCellMap(), increment.getTimeRange().getMax(), Action.WRITE)) {
authResult = AuthResult.allow(OpType.INCREMENT.toString(), "Covering cell set",
user, Action.WRITE, table, increment.getFamilyCellMap());
} else {
authResult = AuthResult.deny(OpType.INCREMENT.toString(), "Covering cell set",
user, Action.WRITE, table, increment.getFamilyCellMap());
}
AccessChecker.logResult(authResult);
if (authorizationEnabled && !authResult.isAllowed()) {
throw new AccessDeniedException("Insufficient permissions " +
authResult.toContextString());
}
}
return null;
}
@Override
public void postGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
List<TableName> tableNamesList, List<TableDescriptor> descriptors,
String regex) throws IOException {
// Skipping as checks in this case are already done by preGetTableDescriptors.
if (regex == null && tableNamesList != null && !tableNamesList.isEmpty()) {
return;
}
// Retains only those which passes authorization checks, as the checks weren't done as part
// of preGetTableDescriptors.
Iterator<TableDescriptor> itr = descriptors.iterator();
while (itr.hasNext()) {
TableDescriptor htd = itr.next();
try {
requirePermission(ctx, "getTableDescriptors", htd.getTableName(), null, null,
Action.ADMIN, Action.CREATE);
} catch (AccessDeniedException e) {
itr.remove();
}
}
}
@Override
public AttemptingUserProvidingSaslServer createServer(
SecretManager<TokenIdentifier> secretManager,
Map<String, String> saslProps) throws IOException {
UserGroupInformation current = UserGroupInformation.getCurrentUser();
String fullName = current.getUserName();
LOG.debug("Server's Kerberos principal name is {}", fullName);
String[] names = SaslUtil.splitKerberosName(fullName);
if (names.length != 3) {
throw new AccessDeniedException(
"Kerberos principal does NOT contain an instance (hostname): " + fullName);
}
try {
return current.doAs(new PrivilegedExceptionAction<AttemptingUserProvidingSaslServer>() {
@Override
public AttemptingUserProvidingSaslServer run() throws SaslException {
return new AttemptingUserProvidingSaslServer(Sasl.createSaslServer(
getSaslAuthMethod().getSaslMechanism(), names[0], names[1], saslProps,
new SaslGssCallbackHandler()), () -> null);
}
});
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Failed to construct GSS SASL server");
}
}
public void processOneRpc(ByteBuff buf) throws IOException,
InterruptedException {
if (connectionHeaderRead) {
processRequest(buf);
} else {
processConnectionHeader(buf);
this.connectionHeaderRead = true;
if (!authorizeConnection()) {
// Throw FatalConnectionException wrapping ACE so client does right thing and closes
// down the connection instead of trying to read non-existent retun.
throw new AccessDeniedException("Connection from " + this + " for service " +
connectionHeader.getServiceName() + " is unauthorized for user: " + ugi);
}
this.user = this.rpcServer.userProvider.create(this.ugi);
}
}
private boolean authorizeConnection() throws IOException {
try {
// If auth method is DIGEST, the token was obtained by the
// real user for the effective user, therefore not required to
// authorize real user. doAs is allowed only for simple or kerberos
// authentication
if (ugi != null && ugi.getRealUser() != null
&& provider.supportsProtocolAuthentication()) {
ProxyUsers.authorize(ugi, this.getHostAddress(), this.rpcServer.conf);
}
this.rpcServer.authorize(ugi, connectionHeader, getHostInetAddress());
this.rpcServer.metrics.authorizationSuccess();
} catch (AuthorizationException ae) {
if (RpcServer.LOG.isDebugEnabled()) {
RpcServer.LOG.debug("Connection authorization failed: " + ae.getMessage(), ae);
}
this.rpcServer.metrics.authorizationFailure();
doRespond(getErrorResponse(ae.getMessage(), new AccessDeniedException(ae)));
return false;
}
return true;
}
@Test
public void test() throws Exception {
try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
Table table = conn.getTable(TableName.META_TABLE_NAME)) {
CoprocessorRpcChannel rpcChannel = table.coprocessorService(HConstants.EMPTY_START_ROW);
AuthenticationProtos.AuthenticationService.BlockingInterface service =
AuthenticationProtos.AuthenticationService.newBlockingStub(rpcChannel);
WhoAmIResponse response = service.whoAmI(null, WhoAmIRequest.getDefaultInstance());
assertEquals(USERNAME, response.getUsername());
assertEquals(AuthenticationMethod.TOKEN.name(), response.getAuthMethod());
try {
service.getAuthenticationToken(null, GetAuthenticationTokenRequest.getDefaultInstance());
} catch (ServiceException e) {
IOException ioe = ProtobufUtil.getRemoteException(e);
assertThat(ioe, instanceOf(AccessDeniedException.class));
assertThat(ioe.getMessage(),
containsString("Token generation only allowed for Kerberos authenticated clients"));
}
}
}
/** This fails only in case of ADE or empty list for any of the actions. */
public static void verifyAllowed(User user, AccessTestAction... actions) throws Exception {
for (AccessTestAction action : actions) {
try {
Object obj = user.runAs(action);
if (obj != null && obj instanceof List<?>) {
List<?> results = (List<?>) obj;
if (results != null && results.isEmpty()) {
fail("Empty non null results from action for user '" + user.getShortName() + "'");
}
}
} catch (AccessDeniedException ade) {
fail("Expected action to pass for user '" + user.getShortName() + "' but was denied");
}
}
}
/** This passes only in case of empty list for all users. */
public static void verifyIfEmptyList(AccessTestAction action, User... users) throws Exception {
for (User user : users) {
try {
Object obj = user.runAs(action);
if (obj != null && obj instanceof List<?>) {
List<?> results = (List<?>) obj;
if (results != null && !results.isEmpty()) {
fail("Unexpected action results: " + results + " for user '"
+ user.getShortName() + "'");
}
} else {
fail("Unexpected results for user '" + user.getShortName() + "'");
}
} catch (AccessDeniedException ade) {
fail("Expected action to pass for user '" + user.getShortName() + "' but was denied");
}
}
}
private void verifiedDeniedServiceException(User user, Action action) throws Exception {
user.runAs((PrivilegedExceptionAction<?>) () -> {
boolean accessDenied = false;
try (Connection conn = ConnectionFactory.createConnection(conf);
Admin admin = conn.getAdmin()) {
action.run(admin);
} catch (ServiceException e) {
// For MasterRpcServices.execService.
if (e.getCause() instanceof AccessDeniedException) {
accessDenied = true;
}
}
assertTrue("Expected access to be denied", accessDenied);
return null;
});
}
@Override
public UserGroupInformation getAuthorizedUgi(String authzId,
SecretManager<TokenIdentifier> secretManager) throws IOException {
UserGroupInformation authorizedUgi;
byte[] encodedId = SaslUtil.decodeIdentifier(authzId);
PasswordAuthTokenIdentifier tokenId = new PasswordAuthTokenIdentifier();
try {
tokenId.readFields(new DataInputStream(new ByteArrayInputStream(encodedId)));
} catch (IOException e) {
throw new IOException("Can't de-serialize PasswordAuthTokenIdentifier", e);
}
authorizedUgi = tokenId.getUser();
if (authorizedUgi == null) {
throw new AccessDeniedException("Can't retrieve username from tokenIdentifier.");
}
authorizedUgi.addTokenIdentifier(tokenId);
authorizedUgi.setAuthenticationMethod(getSaslAuthMethod().getAuthMethod());
return authorizedUgi;
}
@Test
public void testNoEnableAfterDisablePolicy() throws Exception {
Put p = new Put(Bytes.toBytes("to_reject"));
p.addColumn(Bytes.toBytes(SpaceQuotaHelperForTests.F1), Bytes.toBytes("to"),
Bytes.toBytes("reject"));
final TableName tn = helper.writeUntilViolation(SpaceViolationPolicy.DISABLE);
final Admin admin = TEST_UTIL.getAdmin();
// Disabling a table relies on some external action (over the other policies), so wait a bit
// more than the other tests.
for (int i = 0; i < NUM_RETRIES * 2; i++) {
if (admin.isTableEnabled(tn)) {
LOG.info(tn + " is still enabled, expecting it to be disabled. Will wait and re-check.");
Thread.sleep(2000);
}
}
assertFalse(tn + " is still enabled but it should be disabled", admin.isTableEnabled(tn));
try {
admin.enableTable(tn);
} catch (AccessDeniedException e) {
String exceptionContents = StringUtils.stringifyException(e);
final String expectedText = "violated space quota";
assertTrue(
"Expected the exception to contain " + expectedText + ", but was: " + exceptionContents,
exceptionContents.contains(expectedText));
}
}
@Test
public void testFailCreateTable() throws Exception {
conf.set(MASTER_COPROCESSOR_CONF_KEY, CreateFailObserver.class.getName());
TEST_UTIL.startMiniCluster(3);
try {
TEST_UTIL.createTable(TABLE, FAMILY);
} catch (AccessDeniedException e) {
LOG.debug("Ignoring exception: ", e);
Thread.sleep(evictionDelay * 3);
}
List<Procedure<MasterProcedureEnv>> procedureInfos =
TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor().getProcedures();
for (Procedure procedureInfo : procedureInfos) {
if (procedureInfo.getProcName().equals("CreateTableProcedure")
&& procedureInfo.getState() == ProcedureProtos.ProcedureState.ROLLEDBACK) {
fail("Found procedure " + procedureInfo + " that hasn't been cleaned up");
}
}
}
@Test
public void testFailCreateTableAction() throws Exception {
conf.set(MASTER_COPROCESSOR_CONF_KEY, CreateFailObserverHandler.class.getName());
TEST_UTIL.startMiniCluster(3);
try {
TEST_UTIL.createTable(TABLE, FAMILY);
fail("Table shouldn't be created");
} catch (AccessDeniedException e) {
LOG.debug("Ignoring exception: ", e);
Thread.sleep(evictionDelay * 3);
}
List<Procedure<MasterProcedureEnv>> procedureInfos =
TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor().getProcedures();
for (Procedure procedureInfo : procedureInfos) {
if (procedureInfo.getProcName().equals("CreateTableProcedure")
&& procedureInfo.getState() == ProcedureProtos.ProcedureState.ROLLEDBACK) {
fail("Found procedure " + procedureInfo + " that hasn't been cleaned up");
}
}
}
/**
* Authorizes that the current user has all the given permissions for the
* given table and for the hbase namespace of the table
* @param tableName Table requested
* @throws IOException if obtaining the current user fails
* @throws AccessDeniedException if user has no authorization
*/
private void requireAccess(String request, TableName tableName, Action... permissions) throws IOException {
User user = getActiveUser();
AuthResult result = null;
List<Action> requiredAccess = new ArrayList<Action>();
for (Action permission : permissions) {
if (hasAccess(getUserPermissions(tableName), tableName, permission, user)) {
result = AuthResult.allow(request, "Table permission granted", user, permission, tableName, null, null);
} else {
result = AuthResult.deny(request, "Insufficient permissions", user, permission, tableName, null, null);
requiredAccess.add(permission);
}
logResult(result);
}
if (!requiredAccess.isEmpty()) {
result = AuthResult.deny(request, "Insufficient permissions", user, requiredAccess.get(0), tableName, null,
null);
}
if (!result.isAllowed()) { throw new AccessDeniedException("Insufficient permissions "
+ authString(user.getName(), tableName, new HashSet<Permission.Action>(Arrays.asList(permissions)))); }
}
/**
* Verify that READ and EXECUTE permissions are required on SYSTEM tables to get a Phoenix Connection
* Tests grant revoke permissions per user 1. if NS enabled -> on namespace 2. If NS disabled -> on tables
*/
@Test
// this test needs to be run first
public void aTestRXPermsReqdForPhoenixConn() throws Exception {
if(isNamespaceMapped) {
// NS is enabled, CQSI tries creating SYSCAT, we get NamespaceNotFoundException exception for "SYSTEM" NS
// We create custom ADE and throw it (and ignore NamespaceNotFoundException)
// This is because we didn't had CREATE perms to create "SYSTEM" NS
verifyDenied(getConnectionAction(), AccessDeniedException.class, regularUser1);
} else {
// NS is disabled, CQSI tries creating SYSCAT, Two cases here
// 1. First client ever --> Gets ADE, runs client server compatibility check again and gets TableNotFoundException since SYSCAT doesn't exist
// 2. Any other client --> Gets ADE, runs client server compatibility check again and gets AccessDeniedException since it doesn't have EXEC perms
verifyDenied(getConnectionAction(), TableNotFoundException.class, regularUser1);
}
// Phoenix Client caches connection per user
// If we grant permissions, get a connection and then revoke it, we can still get the cached connection
// However it will fail for other read queries
// Thus this test grants and revokes for 2 users, so that both functionality can be tested.
grantSystemTableAccess(superUser1, regularUser1, regularUser2);
verifyAllowed(getConnectionAction(), regularUser1);
revokeSystemTableAccess(superUser1, regularUser2);
verifyDenied(getConnectionAction(), AccessDeniedException.class, regularUser2);
}
/**
* Superuser grants admin perms to user1, who will in-turn grant admin perms to user2
* Not affected with namespace props
* Tests grant revoke permissions on per user global level
*/
@Test
public void testSuperUserCanChangePerms() throws Exception {
// Grant System Table access to all users, else they can't create a Phoenix connection
grantSystemTableAccess(superUser1, regularUser1, regularUser2, unprivilegedUser);
verifyAllowed(grantPermissions("A", regularUser1), superUser1);
verifyAllowed(readTableWithoutVerification(PhoenixDatabaseMetaData.SYSTEM_CATALOG), regularUser1);
verifyAllowed(grantPermissions("A", regularUser2), regularUser1);
verifyAllowed(revokePermissions(regularUser1), superUser1);
verifyDenied(grantPermissions("A", regularUser3), AccessDeniedException.class, regularUser1);
// Don't grant ADMIN perms to unprivilegedUser, thus unprivilegedUser is unable to control other permissions.
verifyAllowed(getConnectionAction(), unprivilegedUser);
verifyDenied(grantPermissions("ARX", regularUser4), AccessDeniedException.class, unprivilegedUser);
}
/**
* Verifies permissions for users present inside a group
*/
@Test
public void testGroupUserPerms() throws Exception {
if(isNamespaceMapped) {
verifyAllowed(createSchema(schemaName), superUser1);
}
verifyAllowed(createTable(fullTableName), superUser1);
// Grant SYSTEM table access to GROUP_SYSTEM_ACCESS and regularUser1
verifyAllowed(grantPermissions("RX", GROUP_SYSTEM_ACCESS, PHOENIX_SYSTEM_TABLES_IDENTIFIERS, false), superUser1);
grantSystemTableAccess(superUser1, regularUser1);
// Grant Permissions to Groups (Should be automatically applicable to all users inside it)
verifyAllowed(grantPermissions("ARX", GROUP_SYSTEM_ACCESS, fullTableName, false), superUser1);
verifyAllowed(readTable(fullTableName), groupUser);
// GroupUser is an admin and can grant perms to other users
verifyDenied(readTable(fullTableName), AccessDeniedException.class, regularUser1);
verifyAllowed(grantPermissions("RX", regularUser1, fullTableName, false), groupUser);
verifyAllowed(readTable(fullTableName), regularUser1);
// Revoke the perms and try accessing data again
verifyAllowed(revokePermissions(GROUP_SYSTEM_ACCESS, fullTableName, false), superUser1);
verifyDenied(readTable(fullTableName), AccessDeniedException.class, groupUser);
}
@Test
public void testListTablesAsRWUserWithOriginalHBaseAdmin() throws Exception {
createAdditionalTable(tableName + "2");
final HTableDescriptor[] hTableDescriptors;
if (securedCluster) {
PrivilegedExceptionAction listTables = new PrivilegedExceptionAction() {
@Override
public Object run() throws Exception {
try {
return new HBaseAdmin(conf).listTables();
} catch (AccessDeniedException e) {
return new HTableDescriptor[0];
}
}
};
hTableDescriptors = (HTableDescriptor[]) USER_RW.runAs(listTables);
} else {
hTableDescriptors = new HBaseAdmin(conf).listTables();
}
int tableCount = 0;
for (HTableDescriptor hTableDescriptor : hTableDescriptors) {
System.out.println(hTableDescriptor);
tableCount++;
}
if (miniCluster) {
if (securedCluster)
Assert.assertEquals(0, tableCount);
else
Assert.assertEquals(2, tableCount);
}
}