Skip to content

Commit

Permalink
RANGER-4745: Enhance handling of subAccess authorization in Ranger HD…
Browse files Browse the repository at this point in the history
…FS plugin
  • Loading branch information
kulkabhay committed Apr 4, 2024
1 parent 2d875da commit 4abb993
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public class RangerHadoopConstants {
public static final String RANGER_OPTIMIZE_SUBACCESS_AUTHORIZATION_PROP = "ranger.optimize-subaccess-authorization" ;
public static final boolean RANGER_ADD_HDFS_PERMISSION_DEFAULT = false;
public static final boolean RANGER_OPTIMIZE_SUBACCESS_AUTHORIZATION_DEFAULT = false ;

public static final String RANGER_USE_LEGACY_SUBACCESS_AUTHORIZATION_PROP = "ranger.plugin.hdfs.use.legacy.subaccess.authorization";
public static final boolean RANGER_USE_LEGACY_SUBACCESS_AUTHORIZATION_DEFAULT = true;

public static final String READ_ACCCESS_TYPE = "read";
public static final String WRITE_ACCCESS_TYPE = "write";
public static final String EXECUTE_ACCCESS_TYPE = "execute";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ public void start() {
LOG.info(RangerHadoopConstants.RANGER_OPTIMIZE_SUBACCESS_AUTHORIZATION_PROP + " is enabled");
}

LOG.info("Legacy way of authorizing sub-access requests will " + (plugin.isUseLegacySubAccessAuthorization() ? "" : "not ") + "be used");

access2ActionListMapper.put(FsAction.NONE, new HashSet<String>());
access2ActionListMapper.put(FsAction.ALL, Sets.newHashSet(READ_ACCCESS_TYPE, WRITE_ACCCESS_TYPE, EXECUTE_ACCCESS_TYPE));
access2ActionListMapper.put(FsAction.READ, Sets.newHashSet(READ_ACCCESS_TYPE));
Expand Down Expand Up @@ -219,10 +221,14 @@ public RangerAccessControlEnforcer(AccessControlEnforcer defaultEnforcer) {
class SubAccessData {
final INodeDirectory dir;
final String resourcePath;
final INode[] inodes;
final INodeAttributes[] iNodeAttributes;

SubAccessData(INodeDirectory dir, String resourcePath) {
SubAccessData(INodeDirectory dir, String resourcePath, INode[] inodes, INodeAttributes[] iNodeAttributes) {
this.dir = dir;
this.resourcePath = resourcePath;
this.iNodeAttributes = iNodeAttributes;
this.inodes = inodes;
}
}

Expand Down Expand Up @@ -429,7 +435,7 @@ private void checkRangerPermission(String fsOwner, String superGroup, UserGroupI
if(authzStatus == AuthzStatus.ALLOW && subAccess != null && inode != null && inode.isDirectory()) {
Stack<SubAccessData> directories = new Stack<>();

for(directories.push(new SubAccessData(inode.asDirectory(), resourcePath)); !directories.isEmpty(); ) {
for(directories.push(new SubAccessData(inode.asDirectory(), resourcePath, inodes, inodeAttrs)); !directories.isEmpty(); ) {
SubAccessData data = directories.pop();
ReadOnlyList<INode> cList = data.dir.getChildrenList(snapshotId);

Expand All @@ -438,7 +444,75 @@ private void checkRangerPermission(String fsOwner, String superGroup, UserGroupI

authzStatus = isAccessAllowed(data.dir, dirAttribs, data.resourcePath, subAccess, context);

if(authzStatus != AuthzStatus.ALLOW) {
INodeDirectory dirINode;
int dirAncestorIndex;
INodeAttributes[] dirINodeAttrs;
INode[] dirINodes;
INode dirAncestor;
INode dirParent;
byte[][] dirComponents;

if (data.dir.equals(inode)) {
dirINode = inode.asDirectory();
dirINodeAttrs = inodeAttrs;
dirINodes = inodes;
dirAncestorIndex = ancestorIndex;
dirAncestor = ancestor;
dirParent = parent;
dirComponents = pathByNameArr;
} else {
INodeAttributes[] curINodeAttributes;
INode[] curINodes;

dirINode = data.dir;
curINodeAttributes = data.iNodeAttributes;
curINodes = data.inodes;
int idx;

dirINodes = new INode[curINodes.length + 1];
for (idx = 0; idx < curINodes.length; idx++) {
dirINodes[idx] = curINodes[idx];
}
dirINodes[idx] = dirINode;

dirINodeAttrs = new INodeAttributes[curINodeAttributes.length + 1];
for (idx = 0; idx < curINodeAttributes.length; idx++) {
dirINodeAttrs[idx] = curINodeAttributes[idx];
}
dirINodeAttrs[idx] = dirAttribs;

for (dirAncestorIndex = dirINodes.length - 1; dirAncestorIndex >= 0 && dirINodes[dirAncestorIndex] == null; dirAncestorIndex--)
;

dirAncestor = dirINodes.length > dirAncestorIndex && dirAncestorIndex >= 0 ? dirINodes[dirAncestorIndex] : null;
dirParent = dirINodes.length > 1 ? dirINodes[dirINodes.length - 2] : null;

dirComponents = dirINode.getPathComponents();
}

if (authzStatus == AuthzStatus.NOT_DETERMINED && !rangerPlugin.isUseLegacySubAccessAuthorization()) {
if (LOG.isDebugEnabled()) {
if (data.dir.equals(inode)) {
LOG.debug("Top level directory being processed for default authorizer call, [" + data.resourcePath + "]");
} else {
LOG.debug("Sub directory being processed for default authorizer call, [" + data.resourcePath + "]");
}
LOG.debug("Calling default authorizer for hierarchy/subaccess with the following parameters");
LOG.debug("fsOwner=" + fsOwner + "; superGroup=" + superGroup + ", inodesCount=" + (dirINodes != null ? dirINodes.length : 0)
+ ", snapshotId=" + snapshotId + ", user=" + (ugi != null ? ugi.getShortUserName() : null) + ", provided-path=" + data.resourcePath + ", ancestorIndex=" + dirAncestorIndex
+ ", doCheckOwner=" + doCheckOwner + ", ancestorAccess=null" + ", parentAccess=null"
+ ", access=null" + ", subAccess=null" + ", ignoreEmptyDir=" + ignoreEmptyDir + ", operationName=" + operationName
+ ", callerContext=null");
}
authzStatus = checkDefaultEnforcer(fsOwner, superGroup, ugi, dirINodeAttrs, dirINodes,
dirComponents, snapshotId, data.resourcePath, dirAncestorIndex, doCheckOwner,
null, null, null, null, ignoreEmptyDir,
dirAncestor, dirParent, dirINode, context);
if (LOG.isDebugEnabled()) {
LOG.debug("Default authorizer call returned : [" + authzStatus + "]");
}
}
if (authzStatus != AuthzStatus.ALLOW) {
break;
}

Expand All @@ -454,9 +528,9 @@ private void checkRangerPermission(String fsOwner, String superGroup, UserGroupI
for(INode child : cList) {
if (child.isDirectory()) {
if (data.resourcePath.endsWith(Path.SEPARATOR)) {
directories.push(new SubAccessData(child.asDirectory(), data.resourcePath + child.getLocalName()));
directories.push(new SubAccessData(child.asDirectory(), data.resourcePath + child.getLocalName(), dirINodes, dirINodeAttrs));
} else {
directories.push(new SubAccessData(child.asDirectory(), data.resourcePath + Path.SEPARATOR_CHAR + child.getLocalName()));
directories.push(new SubAccessData(child.asDirectory(), data.resourcePath + Path.SEPARATOR_CHAR + child.getLocalName(), dirINodes, dirINodeAttrs));
}
}
}
Expand Down Expand Up @@ -828,6 +902,7 @@ class RangerHdfsPlugin extends RangerBasePlugin {
private final String randomizedWildcardPathName;
private final String hadoopModuleName;
private final Set<String> excludeUsers = new HashSet<>();
private final boolean useLegacySubAccessAuthorization;

public RangerHdfsPlugin(Path addlConfigFile) {
super("hdfs", "hdfs");
Expand All @@ -851,6 +926,9 @@ public RangerHdfsPlugin(Path addlConfigFile) {

String excludeUserList = config.get(RangerHadoopConstants.AUDITLOG_HDFS_EXCLUDE_LIST_PROP, RangerHadoopConstants.AUDITLOG_EMPTY_STRING);

this.useLegacySubAccessAuthorization = config.getBoolean(RangerHadoopConstants.RANGER_USE_LEGACY_SUBACCESS_AUTHORIZATION_PROP, RangerHadoopConstants.RANGER_USE_LEGACY_SUBACCESS_AUTHORIZATION_DEFAULT);


if (excludeUserList != null && excludeUserList.trim().length() > 0) {
for(String excludeUser : excludeUserList.trim().split(",")) {
excludeUser = excludeUser.trim();
Expand Down Expand Up @@ -899,6 +977,9 @@ public String getRandomizedWildcardPathName() {
}
public String getHadoopModuleName() { return hadoopModuleName; }
public Set<String> getExcludedUsers() { return excludeUsers; }
public boolean isUseLegacySubAccessAuthorization() {
return useLegacySubAccessAuthorization;
}
}

class RangerHdfsResource extends RangerAccessResourceImpl {
Expand Down

0 comments on commit 4abb993

Please sign in to comment.