@Override public void preStopMaster(ObserverContext<MasterCoprocessorEnvironment> c) throws IOException { if (!hasAccess) { throw new AccessDeniedException("Insufficient permissions to stop master"); } }
@Override public void preStopRegionServer(ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException { if (!hasAccess) { throw new AccessDeniedException("Insufficient permissions to stop region server."); } }
@Override public void preShutdown(ObserverContext<MasterCoprocessorEnvironment> c) throws IOException { if (!hasAccess) { throw new AccessDeniedException("Insufficient permissions to shut down cluster."); } }
/** * Verify, when servicing an RPC, that the caller is the scanner owner. If so, we assume that * access control is correctly enforced based on the checks performed in preScannerOpen() */ private void requireScannerOwner(InternalScanner s) throws AccessDeniedException { if (!RpcServer.isInRpcCallContext()) return; String requestUName = RpcServer.getRequestUserName().orElse(null); String owner = scannerOwners.get(s); if (authorizationEnabled && owner != null && !owner.equals(requestUName)) { throw new AccessDeniedException("User '" + requestUName + "' is not the scanner owner!"); } }
/** * Verify, when servicing an RPC, that the caller is the scanner owner. * If so, we assume that access control is correctly enforced based on * the checks performed in preScannerOpen() */ private void requireScannerOwner(InternalScanner s) throws AccessDeniedException { if (!RpcServer.isInRpcCallContext()) { return; } String requestUserName = RpcServer.getRequestUserName().orElse(null); String owner = scannerOwners.get(s); if (authorizationEnabled && owner != null && !owner.equals(requestUserName)) { throw new AccessDeniedException("User '"+ requestUserName +"' is not the scanner owner!"); } }
private static void checkAuths(Set<Integer> auths, int labelOrdinal, String identifier, boolean checkAuths) throws IOException { if (checkAuths) { if (auths == null || (!auths.contains(labelOrdinal))) { throw new AccessDeniedException("Visibility label " + identifier + " not authorized for the user " + VisibilityUtils.getActiveUser().getShortName()); } } } }
private void checkSystemOrSuperUser(User activeUser) throws IOException { // No need to check if we're not going to throw if (!authorizationEnabled) { return; } if (!Superusers.isSuperUser(activeUser)) { throw new AccessDeniedException("User '" + (activeUser != null ? activeUser.getShortName() : "null") + "' is not system or super user."); } }
private void checkCallingUserAuth() throws IOException { if (!authorizationEnabled) { // Redundant, but just in case return; } if (!accessControllerAvailable) { User user = VisibilityUtils.getActiveUser(); if (user == null) { throw new IOException("Unable to retrieve calling user"); } if (!(this.visibilityLabelService.havingSystemAuth(user))) { throw new AccessDeniedException("User '" + user.getShortName() + "' is not authorized to perform this action."); } } }
@Override public void preDisableTable(ObserverContext<MasterCoprocessorEnvironment> c, TableName tableName) throws IOException { if (Bytes.equals(tableName.getName(), AccessControlLists.ACL_GLOBAL_NAME)) { // We have to unconditionally disallow disable of the ACL table when we are installed, // even if not enforcing authorizations. We are still allowing grants and revocations, // checking permissions and logging audit messages, etc. If the ACL table is not // available we will fail random actions all over the place. throw new AccessDeniedException("Not allowed to disable " + AccessControlLists.ACL_TABLE_NAME + " table with AccessController installed"); } requirePermission(c, "disableTable", tableName, null, null, Action.ADMIN, Action.CREATE); }
@Override public void preCreateTable(ObserverContext<MasterCoprocessorEnvironment> env, TableDescriptor desc, RegionInfo[] regions) throws IOException { if (desc.getTableName().equals(TABLE)) { throw new AccessDeniedException("Don't allow creation of table"); } }
@Override public void preCreateTableAction( final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableDescriptor desc, final RegionInfo[] regions) throws IOException { if (desc.getTableName().equals(TABLE)) { throw new AccessDeniedException("Don't allow creation of table"); } }
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); } }
/** * Throw an exception if an action is not permitted by a user on a file. * * @param ugi * the user * @param file * the file * @param action * the action */ public static void checkAccess(UserGroupInformation ugi, FileStatus file, FsAction action) throws AccessDeniedException { if (ugi.getShortUserName().equals(file.getOwner())) { if (file.getPermission().getUserAction().implies(action)) { return; } } else if (contains(ugi.getGroupNames(), file.getGroup())) { if (file.getPermission().getGroupAction().implies(action)) { return; } } else if (file.getPermission().getOtherAction().implies(action)) { return; } throw new AccessDeniedException("Permission denied:" + " action=" + action + " path=" + file.getPath() + " user=" + ugi.getShortUserName()); }
private UserGroupInformation getAuthorizedUgi(String authorizedId) throws IOException { UserGroupInformation authorizedUgi; if (authMethod == AuthMethod.DIGEST) { TokenIdentifier tokenId = HBaseSaslRpcServer.getIdentifier(authorizedId, this.rpcServer.secretManager); authorizedUgi = tokenId.getUser(); if (authorizedUgi == null) { throw new AccessDeniedException( "Can't retrieve username from tokenIdentifier."); } authorizedUgi.addTokenIdentifier(tokenId); } else { authorizedUgi = UserGroupInformation.createRemoteUser(authorizedId); } authorizedUgi.setAuthenticationMethod(authMethod.authenticationMethod.getAuthMethod()); return authorizedUgi; }
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 && (authMethod != AuthMethod.DIGEST)) { 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; }
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() == AccessControlLists.ACL_TAG_TYPE) { throw new AccessDeniedException("Mutation contains cell with reserved type tag"); } } } m.setAttribute(TAG_CHECK_PASSED, TRUE); }
@Override public boolean preCheckAndPutAfterRowLock(final ObserverContext<RegionCoprocessorEnvironment> c, final byte[] row, final byte[] family, final byte[] qualifier, final CompareOperator opp, final ByteArrayComparable comparator, final Put put, final boolean result) throws IOException { if (put.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(); Map<byte[], ? extends Collection<byte[]>> families = makeFamilyMap(family, qualifier); AuthResult authResult = null; User user = getActiveUser(c); if (checkCoveringPermission(user, OpType.CHECK_AND_PUT, c.getEnvironment(), row, families, HConstants.LATEST_TIMESTAMP, Action.READ)) { authResult = AuthResult.allow(OpType.CHECK_AND_PUT.toString(), "Covering cell set", user, Action.READ, table, families); } else { authResult = AuthResult.deny(OpType.CHECK_AND_PUT.toString(), "Covering cell set", user, Action.READ, table, families); } AccessChecker.logResult(authResult); if (authorizationEnabled && !authResult.isAllowed()) { throw new AccessDeniedException("Insufficient permissions " + authResult.toContextString()); } } return result; }
@Override public boolean preCheckAndDeleteAfterRowLock( final ObserverContext<RegionCoprocessorEnvironment> c, final byte[] row, final byte[] family, final byte[] qualifier, final CompareOperator op, final ByteArrayComparable comparator, final Delete delete, final boolean result) throws IOException { if (delete.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(); Map<byte[], ? extends Collection<byte[]>> families = makeFamilyMap(family, qualifier); AuthResult authResult = null; User user = getActiveUser(c); if (checkCoveringPermission(user, OpType.CHECK_AND_DELETE, c.getEnvironment(), row, families, HConstants.LATEST_TIMESTAMP, Action.READ)) { authResult = AuthResult.allow(OpType.CHECK_AND_DELETE.toString(), "Covering cell set", user, Action.READ, table, families); } else { authResult = AuthResult.deny(OpType.CHECK_AND_DELETE.toString(), "Covering cell set", user, Action.READ, table, families); } AccessChecker.logResult(authResult); if (authorizationEnabled && !authResult.isAllowed()) { throw new AccessDeniedException("Insufficient permissions " + authResult.toContextString()); } } return result; }
@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; }