Repository: hbase Updated Branches: refs/heads/branch-1 9621debfa -> a2d8b0e52
HBASE-12831 Changing the set of vis labels a user has access to doesn't generate an audit log event Signed-off-by: Sean Busbey <bus...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/a2d8b0e5 Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/a2d8b0e5 Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/a2d8b0e5 Branch: refs/heads/branch-1 Commit: a2d8b0e52bc412ed857a0b16abef34a243ffefd0 Parents: 9621deb Author: Ashish Singhi <ashish.sin...@huawei.com> Authored: Fri Jan 16 08:43:58 2015 +0530 Committer: Sean Busbey <bus...@apache.org> Committed: Wed Jan 28 21:30:02 2015 -0600 ---------------------------------------------------------------------- conf/log4j.properties | 1 + .../visibility/VisibilityController.java | 88 +++++++++++++++++--- 2 files changed, 77 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/a2d8b0e5/conf/log4j.properties ---------------------------------------------------------------------- diff --git a/conf/log4j.properties b/conf/log4j.properties index 4e8f145..472fc03 100644 --- a/conf/log4j.properties +++ b/conf/log4j.properties @@ -55,6 +55,7 @@ log4j.appender.RFAS.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n log4j.category.SecurityLogger=${hbase.security.logger} log4j.additivity.SecurityLogger=false #log4j.logger.SecurityLogger.org.apache.hadoop.hbase.security.access.AccessController=TRACE +#log4j.logger.SecurityLogger.org.apache.hadoop.hbase.security.visibility.VisibilityController=TRACE # # Null Appender http://git-wip-us.apache.org/repos/asf/hbase/blob/a2d8b0e5/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java index 0fbef44..d219ed2 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java @@ -24,6 +24,7 @@ import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LA import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABELS_TABLE_NAME; import java.io.IOException; +import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -38,15 +39,16 @@ import org.apache.hadoop.hbase.CellScanner; import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.CoprocessorEnvironment; import org.apache.hadoop.hbase.DoNotRetryIOException; -import org.apache.hadoop.hbase.classification.InterfaceAudience; +import org.apache.hadoop.hbase.HBaseInterfaceAudience; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HTableDescriptor; -import org.apache.hadoop.hbase.TagRewriteCell; +import org.apache.hadoop.hbase.MetaTableAccessor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.Tag; -import org.apache.hadoop.hbase.MetaTableAccessor; +import org.apache.hadoop.hbase.TagRewriteCell; import org.apache.hadoop.hbase.TagType; +import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.client.Append; import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.Get; @@ -97,7 +99,6 @@ import org.apache.hadoop.hbase.replication.ReplicationEndpoint; import org.apache.hadoop.hbase.security.AccessDeniedException; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.security.access.AccessControlLists; -import org.apache.hadoop.hbase.HBaseInterfaceAudience; import org.apache.hadoop.hbase.security.access.AccessController; import org.apache.hadoop.hbase.util.ByteStringer; import org.apache.hadoop.hbase.util.Bytes; @@ -119,6 +120,8 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements VisibilityLabelsService.Interface, CoprocessorService { private static final Log LOG = LogFactory.getLog(VisibilityController.class); + private static final Log AUDITLOG = LogFactory.getLog("SecurityLogger." + + VisibilityController.class.getName()); // flags if we are running on a region of the 'labels' table private boolean labelsRegion = false; // Flag denoting whether AcessController is available or not. @@ -727,9 +730,9 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements new VisibilityControllerNotReadyException("VisibilityController not yet initialized!"), response); } else { + List<byte[]> labels = new ArrayList<byte[]>(visLabels.size()); try { checkCallingUserAuth(); - List<byte[]> labels = new ArrayList<byte[]>(visLabels.size()); RegionActionResult successResult = RegionActionResult.newBuilder().build(); for (VisibilityLabel visLabel : visLabels) { byte[] label = visLabel.getLabel().toByteArray(); @@ -740,6 +743,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements } if (!labels.isEmpty()) { OperationStatus[] opStatus = this.visibilityLabelService.addLabels(labels); + logResult(true, "addLabels", "Adding labels allowed", null, labels, null); int i = 0; for (OperationStatus status : opStatus) { while (response.getResult(i) != successResult) @@ -753,6 +757,10 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements i++; } } + } catch (AccessDeniedException e) { + logResult(false, "addLabels", e.getMessage(), null, labels, null); + LOG.error("User is not having required permissions to add labels", e); + setExceptionResults(visLabels.size(), e, response); } catch (IOException e) { LOG.error(e); setExceptionResults(visLabels.size(), e, response); @@ -781,14 +789,17 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements new VisibilityControllerNotReadyException("VisibilityController not yet initialized!"), response); } else { + byte[] user = request.getUser().toByteArray(); + List<byte[]> labelAuths = new ArrayList<byte[]>(auths.size()); try { checkCallingUserAuth(); - List<byte[]> labelAuths = new ArrayList<byte[]>(auths.size()); + for (ByteString authBS : auths) { labelAuths.add(authBS.toByteArray()); } - OperationStatus[] opStatus = this.visibilityLabelService.setAuths(request.getUser() - .toByteArray(), labelAuths); + OperationStatus[] opStatus = this.visibilityLabelService.setAuths(user, labelAuths); + logResult(true, "setAuths", "Setting authorization for labels allowed", user, labelAuths, + null); RegionActionResult successResult = RegionActionResult.newBuilder().build(); for (OperationStatus status : opStatus) { if (status.getOperationStatusCode() == SUCCESS) { @@ -800,6 +811,10 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements response.addResult(failureResultBuilder.build()); } } + } catch (AccessDeniedException e) { + logResult(false, "setAuths", e.getMessage(), user, labelAuths, null); + LOG.error("User is not having required permissions to set authorization", e); + setExceptionResults(auths.size(), e, response); } catch (IOException e) { LOG.error(e); setExceptionResults(auths.size(), e, response); @@ -808,6 +823,39 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements done.run(response.build()); } + private void logResult(boolean isAllowed, String request, String reason, byte[] user, + List<byte[]> labelAuths, String regex) { + if (AUDITLOG.isTraceEnabled()) { + RequestContext ctx = RequestContext.get(); + InetAddress remoteAddr = null; + if (ctx != null) { + remoteAddr = ctx.getRemoteAddress(); + } + + List<String> labelAuthsStr = new ArrayList<>(); + if (labelAuths != null) { + int labelAuthsSize = labelAuths.size(); + labelAuthsStr = new ArrayList<>(labelAuthsSize); + for (int i = 0; i < labelAuthsSize; i++) { + labelAuthsStr.add(Bytes.toString(labelAuths.get(i))); + } + } + + User requestingUser = null; + try { + requestingUser = VisibilityUtils.getActiveUser(); + } catch (IOException e) { + LOG.warn("Failed to get active system user."); + LOG.debug("Details on failure to get active system user.", e); + } + AUDITLOG.trace("Access " + (isAllowed ? "allowed" : "denied") + " for user " + + (requestingUser != null ? requestingUser.getShortName() : "UNKNOWN") + "; reason: " + + reason + "; remote address: " + (remoteAddr != null ? remoteAddr : "") + "; request: " + + request + "; user: " + (user != null ? Bytes.toShort(user) : "null") + "; labels: " + + labelAuthsStr + "; regex: " + regex); + } + } + @Override public synchronized void getAuths(RpcController controller, GetAuthsRequest request, RpcCallback<GetAuthsResponse> done) { @@ -843,6 +891,10 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements } else { labels = this.visibilityLabelService.getAuths(user, false); } + logResult(true, "getAuths", "Get authorizations for user allowed", user, null, null); + } catch (AccessDeniedException e) { + logResult(false, "getAuths", e.getMessage(), user, null, null); + ResponseConverter.setControllerException(controller, e); } catch (IOException e) { ResponseConverter.setControllerException(controller, e); } @@ -865,6 +917,8 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements setExceptionResults(auths.size(), new CoprocessorException( "VisibilityController not yet initialized"), response); } else { + byte[] requestUser = request.getUser().toByteArray(); + List<byte[]> labelAuths = new ArrayList<byte[]>(auths.size()); try { // When AC is ON, do AC based user auth check if (this.acOn && !isSystemOrSuperUser()) { @@ -874,12 +928,14 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements } checkCallingUserAuth(); // When AC is not in place the calling user should have SYSTEM_LABEL // auth to do this action. - List<byte[]> labelAuths = new ArrayList<byte[]>(auths.size()); for (ByteString authBS : auths) { labelAuths.add(authBS.toByteArray()); } - OperationStatus[] opStatus = this.visibilityLabelService.clearAuths(request.getUser() - .toByteArray(), labelAuths); + + OperationStatus[] opStatus = + this.visibilityLabelService.clearAuths(requestUser, labelAuths); + logResult(true, "clearAuths", "Removing authorization for labels allowed", requestUser, + labelAuths, null); RegionActionResult successResult = RegionActionResult.newBuilder().build(); for (OperationStatus status : opStatus) { if (status.getOperationStatusCode() == SUCCESS) { @@ -891,6 +947,10 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements response.addResult(failureResultBuilder.build()); } } + } catch (AccessDeniedException e) { + logResult(false, "clearAuths", e.getMessage(), requestUser, labelAuths, null); + LOG.error("User is not having required permissions to clear authorization", e); + setExceptionResults(auths.size(), e, response); } catch (IOException e) { LOG.error(e); setExceptionResults(auths.size(), e, response); @@ -907,6 +967,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements controller.setFailed("VisibilityController not yet initialized"); } else { List<String> labels = null; + String regex = request.hasRegex() ? request.getRegex() : null; try { // We do ACL check here as we create scanner directly on region. It will not make calls to // AccessController CP methods. @@ -916,8 +977,11 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements + (requestingUser != null ? requestingUser.getShortName() : "null") + "' is not authorized to perform this action."); } - String regex = request.hasRegex() ? request.getRegex() : null; labels = this.visibilityLabelService.listLabels(regex); + logResult(false, "listLabels", "Listing labels allowed", null, null, regex); + } catch (AccessDeniedException e) { + logResult(false, "listLabels", e.getMessage(), null, null, regex); + ResponseConverter.setControllerException(controller, e); } catch (IOException e) { ResponseConverter.setControllerException(controller, e); }