This is an automated email from the ASF dual-hosted git repository.
abhay pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new bc596e627 RANGER-4820: Support authorization of multiple accesses
grouped by access groups in one policy engine call - #2
bc596e627 is described below
commit bc596e627f394d6d8a683fc7a8e09260ebecc3ac
Author: Abhay Kulkarni <[email protected]>
AuthorDate: Fri Sep 13 15:18:49 2024 -0700
RANGER-4820: Support authorization of multiple accesses grouped by access
groups in one policy engine call - #2
---
.../RangerDefaultPolicyEvaluator.java | 39 +++++--
.../plugin/util/RangerAccessRequestUtil.java | 124 +++++++++++++--------
.../authorization/hadoop/RangerHdfsAuthorizer.java | 6 +
3 files changed, 108 insertions(+), 61 deletions(-)
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
index be6cd5584..621b65137 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
@@ -887,7 +887,7 @@ public class RangerDefaultPolicyEvaluator extends
RangerAbstractPolicyEvaluator
}
}
- RangerAccessResult compositeAccessResult =
getCompositeAccessResult(request);
+ RangerAccessResult compositeAccessResult =
getCompositeAccessResult(request, result);
if (compositeAccessResult != null) {
result.setAccessResultFrom(compositeAccessResult);
}
@@ -937,39 +937,54 @@ public class RangerDefaultPolicyEvaluator extends
RangerAbstractPolicyEvaluator
return ret;
}
- private RangerAccessResult getCompositeAccessResult(RangerAccessRequest
request) {
- RangerAccessResult ret = null;
- Set<Set<String>> allAccessTypeGroups =
RangerAccessRequestUtil.getAllRequestedAccessTypeGroups(request);
- Set<String> allAccessTypes =
RangerAccessRequestUtil.getAllRequestedAccessTypes(request);
+ private RangerAccessResult getCompositeAccessResult(RangerAccessRequest
request, RangerAccessResult result) {
+ RangerAccessResult ret = null;
+ Set<Set<String>> allAccessTypeGroups =
RangerAccessRequestUtil.getAllRequestedAccessTypeGroups(request);
+ Set<String> allAccessTypes =
RangerAccessRequestUtil.getAllRequestedAccessTypes(request);
+ Set<String> ignoreIfNotDeniedAccessTypes =
RangerAccessRequestUtil.getIgnoreIfNotDeniedAccessTypes(request);
if (CollectionUtils.isEmpty(allAccessTypeGroups)) {
ret = deriveAccessResultFromGroup(request,
allAccessTypes);
+ if (ret == null &&
CollectionUtils.isNotEmpty(ignoreIfNotDeniedAccessTypes) &&
ignoreIfNotDeniedAccessTypes.containsAll(allAccessTypes)) {
+ // group does not allow/deny access and this
group's all access-types are also in the ignore-if-not-denied access-type list
+ ret = new
RangerAccessResult(result.getPolicyType(), result.getServiceName(),
result.getServiceDef(), request);
+ ret.setAuditResultFrom(result);
+ ret.setIsAllowed(true);
+ }
} else {
- boolean isAccessDetermined
= true;
- boolean isAccessAllowed
= false;
- RangerAccessResult allowResult
= null;
+ boolean isAccessDetermined = true;
+ boolean isAccessAllowed = false;
+ RangerAccessResult allowResult = null;
for (Set<String> accessesInGroup : allAccessTypeGroups)
{
RangerAccessResult groupResult =
deriveAccessResultFromGroup(request, accessesInGroup);
if (groupResult != null) {
if (!groupResult.getIsAllowed()) {
// Deny
- isAccessAllowed = false;
- ret
= groupResult;
+ isAccessAllowed = false;
+ ret = groupResult;
break;
} else {
- isAccessAllowed = true;
+ isAccessAllowed = true;
if (allowResult == null) {
allowResult =
groupResult;
}
}
} else {
// Some group is not completely
authorized yet
- isAccessDetermined = false;
+ if
(!(CollectionUtils.isNotEmpty(ignoreIfNotDeniedAccessTypes) &&
ignoreIfNotDeniedAccessTypes.containsAll(accessesInGroup))) {
+ // group does not allow/deny
access and this group's all access-types are also in the ignore-if-not-denied
access-type list
+ isAccessDetermined = false;
+ }
}
}
+
if (isAccessDetermined && isAccessAllowed) {
ret = allowResult;
+ } else if (isAccessDetermined && ret == null) { // If
none of the groups allowed/denied access and every group's all access-type
results are to be ignored unless denied
+ ret = new
RangerAccessResult(result.getPolicyType(), result.getServiceName(),
result.getServiceDef(), request);
+ ret.setAuditResultFrom(result);
+ ret.setIsAllowed(true);
}
}
return ret;
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
index de31737d6..6546e287c 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
@@ -34,29 +34,30 @@ import org.slf4j.LoggerFactory;
public class RangerAccessRequestUtil {
private static final Logger LOG =
LoggerFactory.getLogger(RangerAccessRequestUtil.class);
- public static final String KEY_CONTEXT_TAGS
= "TAGS";
- public static final String KEY_CONTEXT_TAG_OBJECT
= "TAG_OBJECT";
- public static final String KEY_CONTEXT_RESOURCE
= "RESOURCE";
- public static final String KEY_CONTEXT_REQUESTED_RESOURCES =
"REQUESTED_RESOURCES";
- public static final String KEY_CONTEXT_USERSTORE
= "USERSTORE";
- public static final String KEY_TOKEN_NAMESPACE
= "token:";
- public static final String KEY_USER
= "USER";
- public static final String KEY_OWNER
= "OWNER";
- public static final String KEY_ROLES
= "ROLES";
- public static final String KEY_CONTEXT_IS_ANY_ACCESS =
"ISANYACCESS";
- public static final String KEY_CONTEXT_ALL_ACCESSTYPE_GROUPS =
"ALLACCESSTYPEGROUPS";
- public static final String KEY_CONTEXT_ALL_ACCESSTYPES =
"ALLACCESSTYPES";
- public static final String KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS =
"ALL_ACCESS_TYPE_RESULTS";
- public static final String KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS
= "ALL_ACCESS_TYPE_ACL_RESULTS";
-
- public static final String KEY_CONTEXT_REQUEST
= "_REQUEST";
- public static final String KEY_CONTEXT_GDS_RESULT = "_GDS_RESULT";
- public static final String KEY_CONTEXT_IS_REQUEST_PREPROCESSED =
"ISREQUESTPREPROCESSED";
- public static final String KEY_CONTEXT_RESOURCE_ZONE_NAMES
= "RESOURCE_ZONE_NAMES";
- public static final String KEY_CONTEXT_IS_SKIP_CHAINED_PLUGINS =
"_IS_SKIP_CHAINED_PLUGINS";
+ public static final String KEY_CONTEXT_TAGS
= "TAGS";
+ public static final String KEY_CONTEXT_TAG_OBJECT
= "TAG_OBJECT";
+ public static final String KEY_CONTEXT_RESOURCE
= "RESOURCE";
+ public static final String KEY_CONTEXT_REQUESTED_RESOURCES
= "REQUESTED_RESOURCES";
+ public static final String KEY_CONTEXT_USERSTORE
= "USERSTORE";
+ public static final String KEY_TOKEN_NAMESPACE
= "token:";
+ public static final String KEY_USER
= "USER";
+ public static final String KEY_OWNER
= "OWNER";
+ public static final String KEY_ROLES
= "ROLES";
+ public static final String KEY_CONTEXT_IS_ANY_ACCESS
= "ISANYACCESS";
+ public static final String KEY_CONTEXT_ALL_ACCESSTYPE_GROUPS
= "ALLACCESSTYPEGROUPS";
+ public static final String KEY_CONTEXT_ALL_ACCESSTYPES
= "ALLACCESSTYPES";
+ public static final String KEY_CONTEXT_IGNORE_IF_NOT_DENIED_ACCESSTYPES
= "IGNOREIFNOTDENIEDACCESSTYPES";
+ public static final String KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS
= "ALL_ACCESS_TYPE_RESULTS";
+ public static final String KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS
= "ALL_ACCESS_TYPE_ACL_RESULTS";
+
+ public static final String KEY_CONTEXT_REQUEST =
"_REQUEST";
+ public static final String KEY_CONTEXT_GDS_RESULT =
"_GDS_RESULT";
+ public static final String KEY_CONTEXT_IS_REQUEST_PREPROCESSED =
"ISREQUESTPREPROCESSED";
+ public static final String KEY_CONTEXT_RESOURCE_ZONE_NAMES =
"RESOURCE_ZONE_NAMES";
+ public static final String KEY_CONTEXT_IS_SKIP_CHAINED_PLUGINS =
"_IS_SKIP_CHAINED_PLUGINS";
public static void setRequestTagsInContext(Map<String, Object> context,
Set<RangerTagForEval> tags) {
- if(CollectionUtils.isEmpty(tags)) {
+ if (CollectionUtils.isEmpty(tags)) {
context.remove(KEY_CONTEXT_TAGS);
} else {
context.put(KEY_CONTEXT_TAGS, tags);
@@ -65,12 +66,11 @@ public class RangerAccessRequestUtil {
public static Set<RangerTagForEval>
getRequestTagsFromContext(Map<String, Object> context) {
Set<RangerTagForEval> ret = null;
- Object val =
context.get(RangerAccessRequestUtil.KEY_CONTEXT_TAGS);
+ Object val =
context.get(RangerAccessRequestUtil.KEY_CONTEXT_TAGS);
if (val instanceof Set<?>) {
try {
- @SuppressWarnings("unchecked")
- Set<RangerTagForEval> tags =
(Set<RangerTagForEval>) val;
+ @SuppressWarnings("unchecked")
Set<RangerTagForEval> tags = (Set<RangerTagForEval>) val;
ret = tags;
} catch (Throwable t) {
@@ -87,10 +87,10 @@ public class RangerAccessRequestUtil {
public static RangerTagForEval getCurrentTagFromContext(Map<String,
Object> context) {
RangerTagForEval ret = null;
- Object val = context.get(KEY_CONTEXT_TAG_OBJECT);
+ Object val = context.get(KEY_CONTEXT_TAG_OBJECT);
- if(val instanceof RangerTagForEval) {
- ret = (RangerTagForEval)val;
+ if (val instanceof RangerTagForEval) {
+ ret = (RangerTagForEval) val;
}
return ret;
@@ -104,8 +104,8 @@ public class RangerAccessRequestUtil {
RangerRequestedResources ret = null;
Object val =
context.get(KEY_CONTEXT_REQUESTED_RESOURCES);
- if(val instanceof RangerRequestedResources) {
- ret = (RangerRequestedResources)val;
+ if (val instanceof RangerRequestedResources) {
+ ret = (RangerRequestedResources) val;
}
return ret;
@@ -119,8 +119,8 @@ public class RangerAccessRequestUtil {
RangerAccessResource ret = null;
Object val = MapUtils.isNotEmpty(context) ?
context.get(KEY_CONTEXT_RESOURCE) : null;
- if(val instanceof RangerAccessResource) {
- ret = (RangerAccessResource)val;
+ if (val instanceof RangerAccessResource) {
+ ret = (RangerAccessResource) val;
}
return ret;
@@ -129,7 +129,7 @@ public class RangerAccessRequestUtil {
public static Map<String, Object> copyContext(Map<String, Object>
context) {
final Map<String, Object> ret;
- if(MapUtils.isEmpty(context)) {
+ if (MapUtils.isEmpty(context)) {
ret = new HashMap<>();
} else {
ret = new HashMap<>(context);
@@ -145,6 +145,7 @@ public class RangerAccessRequestUtil {
ret.remove(KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS);
ret.remove(KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS);
ret.remove(KEY_CONTEXT_IS_REQUEST_PREPROCESSED);
+
ret.remove(KEY_CONTEXT_IGNORE_IF_NOT_DENIED_ACCESSTYPES);
// don't remove REQUESTED_RESOURCES
}
@@ -154,9 +155,11 @@ public class RangerAccessRequestUtil {
public static void setCurrentUserInContext(Map<String, Object> context,
String user) {
setTokenInContext(context, KEY_USER, user);
}
+
public static void setOwnerInContext(Map<String, Object> context,
String owner) {
setTokenInContext(context, KEY_OWNER, owner);
}
+
public static String getCurrentUserFromContext(Map<String, Object>
context) {
Object ret = getTokenFromContext(context, KEY_USER);
return ret != null ? ret.toString() : "";
@@ -166,21 +169,22 @@ public class RangerAccessRequestUtil {
String tokenNameWithNamespace = KEY_TOKEN_NAMESPACE + tokenName;
context.put(tokenNameWithNamespace, tokenValue);
}
+
public static Object getTokenFromContext(Map<String, Object> context,
String tokenName) {
String tokenNameWithNamespace = KEY_TOKEN_NAMESPACE + tokenName;
return MapUtils.isNotEmpty(context) ?
context.get(tokenNameWithNamespace) : null;
}
- public static void setCurrentUserRolesInContext(Map<String, Object>
context, Set<String> roles) {
- setTokenInContext(context, KEY_ROLES, roles);
- }
+ public static void setCurrentUserRolesInContext(Map<String, Object>
context, Set<String> roles) {
+ setTokenInContext(context, KEY_ROLES, roles);
+ }
- public static Set<String> getCurrentUserRolesFromContext(Map<String,
Object> context) {
- Object ret = getTokenFromContext(context, KEY_ROLES);
- return ret != null ? (Set<String>) ret : Collections.EMPTY_SET;
- }
+ public static Set<String> getCurrentUserRolesFromContext(Map<String,
Object> context) {
+ Object ret = getTokenFromContext(context, KEY_ROLES);
+ return ret != null ? (Set<String>) ret : Collections.EMPTY_SET;
+ }
- public static Set<String> getUserRoles(RangerAccessRequest request) {
+ public static Set<String> getUserRoles(RangerAccessRequest request) {
Set<String> ret = Collections.EMPTY_SET;
if (request != null) {
@@ -200,9 +204,9 @@ public class RangerAccessRequestUtil {
public static RangerUserStore
getRequestUserStoreFromContext(Map<String, Object> context) {
RangerUserStore ret = null;
- Object val = context.get(KEY_CONTEXT_USERSTORE);
+ Object val = context.get(KEY_CONTEXT_USERSTORE);
- if(val instanceof RangerUserStore) {
+ if (val instanceof RangerUserStore) {
ret = (RangerUserStore) val;
}
@@ -214,7 +218,7 @@ public class RangerAccessRequestUtil {
}
public static boolean getIsAnyAccessInContext(Map<String, Object>
context) {
- Boolean value = (Boolean)context.get(KEY_CONTEXT_IS_ANY_ACCESS);
+ Boolean value = (Boolean)
context.get(KEY_CONTEXT_IS_ANY_ACCESS);
return value != null && value;
}
@@ -223,7 +227,7 @@ public class RangerAccessRequestUtil {
}
public static boolean getIsRequestPreprocessed(Map<String, Object>
context) {
- Boolean value =
(Boolean)context.get(KEY_CONTEXT_IS_REQUEST_PREPROCESSED);
+ Boolean value = (Boolean)
context.get(KEY_CONTEXT_IS_REQUEST_PREPROCESSED);
return value != null && value;
}
@@ -231,6 +235,28 @@ public class RangerAccessRequestUtil {
context.put(KEY_CONTEXT_ALL_ACCESSTYPES, accessTypes);
}
+ public static void setIgnoreIfNotDeniedAccessTypes(Map<String, Object>
context, Set<String> accessTypes) {
+ context.put(KEY_CONTEXT_IGNORE_IF_NOT_DENIED_ACCESSTYPES,
accessTypes);
+ }
+
+ public static Set<String>
getIgnoreIfNotDeniedAccessTypes(RangerAccessRequest request) {
+ Set<String> ret = Collections.emptySet();
+
+ Object val =
request.getContext().get(KEY_CONTEXT_IGNORE_IF_NOT_DENIED_ACCESSTYPES);
+
+ if (val != null) {
+ if (val instanceof Set<?>) {
+ ret = (Set<String>) val;
+ } else if (val instanceof List<?>) {
+ ret = new TreeSet<>((List<String>) val);
+ } else {
+ LOG.error("getNotDeniedRequestedAccessTypes():
failed to get NOTDENIEDACCESSTYPES from context");
+ }
+ }
+ return ret;
+ }
+
+
@SuppressWarnings("unchecked")
public static Set<String>
getAllRequestedAccessTypes(RangerAccessRequest request) {
Set<String> ret = null;
@@ -251,7 +277,7 @@ public class RangerAccessRequestUtil {
}
public static Set<Set<String>>
getAllRequestedAccessTypeGroups(RangerAccessRequest request) {
- Object val =
request.getContext().get(KEY_CONTEXT_ALL_ACCESSTYPE_GROUPS);
+ Object val =
request.getContext().get(KEY_CONTEXT_ALL_ACCESSTYPE_GROUPS);
return (Set<Set<String>>) val;
}
@@ -265,7 +291,7 @@ public class RangerAccessRequestUtil {
public static Map<String, RangerAccessResult>
getAccessTypeResults(RangerAccessRequest request) {
Map<String, RangerAccessResult> ret;
- Object val =
request.getContext().get(KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS);
+ Object val =
request.getContext().get(KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS);
if (val == null) {
ret = new HashMap<>();
request.getContext().put(KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS, ret);
@@ -277,7 +303,7 @@ public class RangerAccessRequestUtil {
public static Map<String, Integer>
getAccessTypeACLResults(RangerAccessRequest request) {
Map<String, Integer> ret;
- Object val =
request.getContext().get(KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS);
+ Object val =
request.getContext().get(KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS);
if (val == null) {
ret = new HashMap<>();
request.getContext().put(KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS, ret);
@@ -400,7 +426,7 @@ public class RangerAccessRequestUtil {
if (context != null) {
Object o =
context.get(KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS);
if (o != null) {
- ret = (Map<String, RangerAccessResult>)o;
+ ret = (Map<String, RangerAccessResult>) o;
}
}
@@ -426,7 +452,7 @@ public class RangerAccessRequestUtil {
}
public static boolean getIsSkipChainedPlugins(Map<String, Object>
context) {
- Boolean value =
(Boolean)context.get(KEY_CONTEXT_IS_SKIP_CHAINED_PLUGINS);
+ Boolean value = (Boolean)
context.get(KEY_CONTEXT_IS_SKIP_CHAINED_PLUGINS);
return value != null && value;
}
}
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 aa59e3ad6..9ce25695c 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
@@ -899,6 +899,9 @@ public class RangerHdfsAuthorizer extends
INodeAttributeProvider {
RangerAccessRequestUtil.setAllRequestedAccessTypeGroups(request,
allAccessTypeGroups);
RangerAccessRequestUtil.setAllRequestedAccessTypes(request.getContext(),
accessTypes);
+ if
(accessTypes.contains(EXECUTE_ACCCESS_TYPE)) {
+
RangerAccessRequestUtil.setIgnoreIfNotDeniedAccessTypes(request.getContext(),
access2ActionListMapper.get(FsAction.EXECUTE));
+ }
}
// if the request was already allowed by a
Ranger policy (for ancestor/parent/node/child), skip chained plugin evaluations
in subsequent calls
@@ -979,6 +982,9 @@ public class RangerHdfsAuthorizer extends
INodeAttributeProvider {
RangerAccessRequestUtil.setAllRequestedAccessTypeGroups(request,
allAccessTypeGroups);
RangerAccessRequestUtil.setAllRequestedAccessTypes(request.getContext(),
accessTypes);
+ if
(accessTypes.contains(EXECUTE_ACCCESS_TYPE)) {
+
RangerAccessRequestUtil.setIgnoreIfNotDeniedAccessTypes(request.getContext(),
access2ActionListMapper.get(FsAction.EXECUTE));
+ }
}
RangerAccessResult result =
context.plugin.isAccessAllowed(request, null);