RANGER-608: fix - denied access due to lack of traverse access does not generate audit
Signed-off-by: sneethiraj <[email protected]> (cherry picked from commit 0158e1a1c7ca7997e3865693f599e5caaa69f505) Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/e1153307 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/e1153307 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/e1153307 Branch: refs/heads/tag-policy Commit: e1153307922475ae70766d72ca9e189e9150f59e Parents: 3fdcfc4 Author: Madhan Neethiraj <[email protected]> Authored: Wed Nov 4 19:25:47 2015 -0800 Committer: Madhan Neethiraj <[email protected]> Committed: Thu Nov 5 14:00:42 2015 -0800 ---------------------------------------------------------------------- .../hadoop/RangerHdfsAuthorizer.java | 86 ++++++++++++++------ 1 file changed, 59 insertions(+), 27 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/e1153307/hdfs-agent/src/main/java/org/apache/ranger/authorization/hadoop/RangerHdfsAuthorizer.java ---------------------------------------------------------------------- diff --git a/hdfs-agent/src/main/java/org/apache/ranger/authorization/hadoop/RangerHdfsAuthorizer.java b/hdfs-agent/src/main/java/org/apache/ranger/authorization/hadoop/RangerHdfsAuthorizer.java index f8008cb..47577d6 100644 --- a/hdfs-agent/src/main/java/org/apache/ranger/authorization/hadoop/RangerHdfsAuthorizer.java +++ b/hdfs-agent/src/main/java/org/apache/ranger/authorization/hadoop/RangerHdfsAuthorizer.java @@ -199,9 +199,12 @@ public class RangerHdfsAuthorizer extends INodeAttributeProvider { } try { - if(plugin != null && !ArrayUtils.isEmpty(inodes)) { - auditHandler = new RangerHdfsAuditHandler(path); + boolean isTraverseOnlyCheck = access == null && parentAccess == null && ancestorAccess == null && subAccess == null; + INode ancestor = null; + INode parent = null; + INode inode = null; + if(plugin != null && !ArrayUtils.isEmpty(inodes)) { if(ancestorIndex >= inodes.length) { ancestorIndex = inodes.length - 1; } @@ -210,26 +213,28 @@ public class RangerHdfsAuthorizer extends INodeAttributeProvider { authzStatus = AuthzStatus.ALLOW; - INode ancestor = inodes.length > ancestorIndex && ancestorIndex >= 0 ? inodes[ancestorIndex] : null; - INode parent = inodes.length > 1 ? inodes[inodes.length - 2] : null; - INode inode = inodes[inodes.length - 1]; + ancestor = inodes.length > ancestorIndex && ancestorIndex >= 0 ? inodes[ancestorIndex] : null; + parent = inodes.length > 1 ? inodes[inodes.length - 2] : null; + inode = inodes[inodes.length - 1]; // could be null while creating a new file - boolean noAccessToCheck = access == null && parentAccess == null && ancestorAccess == null && subAccess == null; + auditHandler = new RangerHdfsAuditHandler(path, isTraverseOnlyCheck); - if(noAccessToCheck) { // check for traverse (EXECUTE) access on the path (if path is a directory) or its parent (if path is a file) - INode node = null; - INodeAttributes nodeAttribs = null; + if(isTraverseOnlyCheck) { + INode nodeToCheck = inode; + INodeAttributes nodeAttribs = inodeAttrs.length > 0 ? inodeAttrs[inodeAttrs.length - 1] : null; - if(inode != null && inode.isDirectory()) { - node = inode; - nodeAttribs = inodeAttrs.length > 0 ? inodeAttrs[inodeAttrs.length - 1] : null; - } else if(parent != null) { - node = parent; - nodeAttribs = inodeAttrs.length > 1 ? inodeAttrs[inodeAttrs.length - 2] : null; + if(nodeToCheck == null || nodeToCheck.isFile()) { + if(parent != null) { + nodeToCheck = parent; + nodeAttribs = inodeAttrs.length > 1 ? inodeAttrs[inodeAttrs.length - 2] : null; + } else if(ancestor != null) { + nodeToCheck = ancestor; + nodeAttribs = inodeAttrs.length > ancestorIndex ? inodeAttrs[ancestorIndex] : null; + } } - if(node != null) { - authzStatus = isAccessAllowed(node, nodeAttribs, FsAction.EXECUTE, user, groups, fsOwner, superGroup, plugin, null); + if(nodeToCheck != null) { + authzStatus = isAccessAllowed(nodeToCheck, nodeAttribs, FsAction.EXECUTE, user, groups, fsOwner, superGroup, plugin, auditHandler); } } @@ -306,27 +311,52 @@ public class RangerHdfsAuthorizer extends INodeAttributeProvider { authzStatus = AuthzStatus.ALLOW; } finally { if(auditHandler != null) { - FsAction action = access; + INode nodeChecked = inode; + FsAction action = access; + + if(isTraverseOnlyCheck) { + if(nodeChecked == null || nodeChecked.isFile()) { + if(parent != null) { + nodeChecked = parent; + } else if(ancestor != null) { + nodeChecked = ancestor; + } + } - if(action == null) { + action = FsAction.EXECUTE; + } else if(action == null) { if(parentAccess != null) { - action = parentAccess; + nodeChecked = parent; + action = parentAccess; } else if(ancestorAccess != null) { - action = ancestorAccess; + nodeChecked = ancestor; + action = ancestorAccess; } else if(subAccess != null) { action = subAccess; - } else { - action = FsAction.NONE; } } - auditHandler.logHadoopEvent(path, action, authzStatus == AuthzStatus.ALLOW); + String pathChecked = nodeChecked != null ? nodeChecked.getFullPathName() : path; + + auditHandler.logHadoopEvent(pathChecked, action, authzStatus == AuthzStatus.ALLOW); } } } if(authzStatus != AuthzStatus.ALLOW) { - throw new RangerAccessControlException("Permission denied: principal{user=" + user + ",groups: " + groups + "}, access=" + access + ", " + path) ; + FsAction action = access; + + if(action == null) { + if(parentAccess != null) { + action = parentAccess; + } else if(ancestorAccess != null) { + action = ancestorAccess; + } else { + action = FsAction.EXECUTE; + } + } + + throw new RangerAccessControlException("Permission denied: user=" + user + ", access=" + action + ", inode=\"" + path + "\"") ; } } finally { if(auditHandler != null) { @@ -451,6 +481,7 @@ class RangerHdfsAuditHandler extends RangerDefaultAuditHandler { private boolean isAuditEnabled = false; private AuthzAuditEvent auditEvent = null; private final String pathToBeValidated; + private final boolean auditOnlyIfDenied; private static final String HadoopModuleName = RangerConfiguration.getInstance().get(RangerHadoopConstants.AUDITLOG_HADOOP_MODULE_ACL_NAME_PROP , RangerHadoopConstants.DEFAULT_HADOOP_MODULE_ACL_NAME) ; private static final String excludeUserList = RangerConfiguration.getInstance().get(RangerHadoopConstants.AUDITLOG_HDFS_EXCLUDE_LIST_PROP, RangerHadoopConstants.AUDITLOG_EMPTY_STRING) ; @@ -469,8 +500,9 @@ class RangerHdfsAuditHandler extends RangerDefaultAuditHandler { } } - public RangerHdfsAuditHandler(String pathToBeValidated) { + public RangerHdfsAuditHandler(String pathToBeValidated, boolean auditOnlyIfDenied) { this.pathToBeValidated = pathToBeValidated; + this.auditOnlyIfDenied = auditOnlyIfDenied; } @Override @@ -527,7 +559,7 @@ class RangerHdfsAuditHandler extends RangerDefaultAuditHandler { if(isAuditEnabled && auditEvent != null && !StringUtils.isEmpty(auditEvent.getAccessType())) { String username = auditEvent.getUser(); - boolean skipLog = (username != null && excludeUsers != null && excludeUsers.contains(username)) ; + boolean skipLog = (username != null && excludeUsers != null && excludeUsers.contains(username)) || (auditOnlyIfDenied && auditEvent.getAccessResult() != 0); if (! skipLog) { super.logAuthzAudit(auditEvent);
