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 a664de553 RANGER-4655: Execute and read permissions granted to a user
in different HDFS policies does not take effect
a664de553 is described below
commit a664de553120f165d927e962e3677fe1abd0d722
Author: Abhay Kulkarni <[email protected]>
AuthorDate: Mon Jan 15 17:02:43 2024 -0800
RANGER-4655: Execute and read permissions granted to a user in different
HDFS policies does not take effect
---
.../policyengine/RangerPolicyEngineImpl.java | 16 ++++
.../RangerDefaultPolicyEvaluator.java | 35 +++++---
.../plugin/util/RangerAccessRequestUtil.java | 39 +++++++++
.../plugin/policyengine/TestPolicyEngine.java | 7 ++
.../test_policyengine_hdfs_multiple_accesses.json | 92 ++++++++++++++++++++++
5 files changed, 179 insertions(+), 10 deletions(-)
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
index 252482c8e..df39467ba 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
@@ -763,6 +763,22 @@ public class RangerPolicyEngineImpl implements
RangerPolicyEngine {
}
}
+ if (!request.isAccessTypeAny()) {
+ Set<String> allRequestedAccesses =
RangerAccessRequestUtil.getAllRequestedAccessTypes(request);
+ if (CollectionUtils.size(allRequestedAccesses)
> 1 && !RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext())) {
+ Map<String, RangerAccessResult>
accessTypeResults =
RangerAccessRequestUtil.getAccessTypeResults(request.getContext());
+ if (accessTypeResults != null) {
+ if
(accessTypeResults.keySet().containsAll(allRequestedAccesses)) {
+ // Allow
+ RangerAccessResult
result = accessTypeResults.values().iterator().next(); // Pick one result
randomly
+
ret.setAccessResultFrom(result);
+
ret.setIsAccessDetermined(true);
+ }
+
RangerAccessRequestUtil.setAccessTypeResults(request.getContext(), null);
+ }
+ }
+ }
+
if (!ret.getIsAccessDetermined()) {
if (isDeniedByTags) {
ret.setIsAllowed(false);
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 7fe2a2eb3..ded8d0993 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
@@ -818,11 +818,29 @@ public class RangerDefaultPolicyEvaluator extends
RangerAbstractPolicyEvaluator
} else {
Set<String> allRequestedAccesses =
RangerAccessRequestUtil.getAllRequestedAccessTypes(request);
- if
(CollectionUtils.isNotEmpty(allRequestedAccesses)) {
+ if (CollectionUtils.size(allRequestedAccesses)
> 1) {
for (String accessType :
allRequestedAccesses) {
- accessResult =
lookupPolicyACLSummary(request.getUser(), request.getUserGroups(),
request.getUserRoles(), accessType);
- if (accessResult == null) {
- break;
+ Integer oneAccessResult =
lookupPolicyACLSummary(request.getUser(), request.getUserGroups(),
request.getUserRoles(), accessType);
+ if (oneAccessResult != null) {
+ if
(oneAccessResult.equals(RangerPolicyEvaluator.ACCESS_DENIED)) {
+ accessResult =
oneAccessResult;
+
RangerAccessRequestUtil.setAccessTypeResults(request.getContext(), null);
+
+ break;
+ }
+ if
(oneAccessResult.equals(RangerPolicyEvaluator.ACCESS_ALLOWED)) {
+ if
(!result.getIsAllowed()) { // if access is not yet allowed by another policy
+ if
(matchType != RangerPolicyResourceMatcher.MatchType.ANCESTOR) {
+
RangerAccessResult oneResult = new RangerAccessResult(result.getPolicyType(),
result.getServiceName(), result.getServiceDef(), result.getAccessRequest());
+
oneResult.setIsAllowed(true);
+
oneResult.setPolicyPriority(getPolicyPriority());
+
oneResult.setPolicyId(getPolicyId());
+
oneResult.setPolicyVersion(getPolicy().getVersion());
+
+
RangerAccessRequestUtil.setAccessTypeResult(request.getContext(), accessType,
oneResult);
+ }
+ }
+ }
}
}
} else {
@@ -865,7 +883,7 @@ public class RangerDefaultPolicyEvaluator extends
RangerAbstractPolicyEvaluator
updateAccessResult(oneResult,
matchType, false, "matched deny-all-else policy");
}
- if (request.isAccessTypeAny() ||
RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext())) {
+ if (request.isAccessTypeAny() ||
allRequestedAccesses.size() == 1 ||
RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext())) {
// Implement OR logic
if (oneResult.getIsAllowed()) {
allowResult = oneResult;
@@ -886,14 +904,11 @@ public class RangerDefaultPolicyEvaluator extends
RangerAbstractPolicyEvaluator
// Implement AND logic
if
(oneResult.getIsAccessDetermined() && !oneResult.getIsAllowed()) {
denyResult = oneResult;
- allowResult = null;
+
RangerAccessRequestUtil.setAccessTypeResults(request.getContext(), null);
break;
} else if
(oneResult.getIsAllowed()) {
- allowResult = noResult
? null : oneResult;
- } else {
- noResult = true;
- allowResult = null;
+
RangerAccessRequestUtil.setAccessTypeResult(request.getContext(), accessType,
oneResult);
}
}
}
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 92a4fe02e..a56ecb268 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
@@ -29,6 +29,7 @@ import org.apache.commons.collections.MapUtils;
import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerAccessResource;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
import org.apache.ranger.plugin.policyengine.gds.GdsAccessResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,6 +52,7 @@ public class RangerAccessRequestUtil {
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_ACCESS_TYPE_RESULTS =
"_ACCESS_TYPE_RESULTS";
public static void setRequestTagsInContext(Map<String, Object> context,
Set<RangerTagForEval> tags) {
if(CollectionUtils.isEmpty(tags)) {
@@ -322,4 +324,41 @@ public class RangerAccessRequestUtil {
return ret != null && ret.size() == 1 ? ret.iterator().next() :
null;
}
+
+ public static void setAccessTypeResults(Map<String, Object> context,
Map<String, RangerAccessResult> accessTypeResults) {
+ if (context != null) {
+ if (accessTypeResults != null) {
+ context.put(KEY_CONTEXT_ACCESS_TYPE_RESULTS,
accessTypeResults);
+ } else {
+ context.remove(KEY_CONTEXT_ACCESS_TYPE_RESULTS);
+ }
+ }
+ }
+
+ public static Map<String, RangerAccessResult>
getAccessTypeResults(Map<String, Object> context) {
+ Map<String, RangerAccessResult> ret = null;
+
+ if (context != null) {
+ Object o = context.get(KEY_CONTEXT_ACCESS_TYPE_RESULTS);
+ if (o != null) {
+ ret = (Map<String, RangerAccessResult>)o;
+ }
+ }
+
+ return ret;
+ }
+
+ public static void setAccessTypeResult(Map<String, Object> context,
String accessType, RangerAccessResult result) {
+ if (context != null) {
+ Map<String, RangerAccessResult> results =
getAccessTypeResults(context);
+
+ if (results == null) {
+ results = new HashMap<>();
+
+ setAccessTypeResults(context, results);
+ }
+
+ results.putIfAbsent(accessType, result);
+ }
+ }
}
diff --git
a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
index 2afbfebd4..64563b84e 100644
---
a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
+++
b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
@@ -509,6 +509,13 @@ public class TestPolicyEngine {
runTestsFromResourceFiles(resourceFiles);
}
+ @Test
+ public void testMultipleAccessAuthorization() throws Exception {
+ String[] resourceFiles =
{"/policyengine/test_policyengine_hdfs_multiple_accesses.json"};
+
+ runTestsFromResourceFiles(resourceFiles);
+ }
+
private void runTestsFromResourceFiles(String[] resourceNames) {
for(String resourceName : resourceNames) {
InputStream inStream =
this.getClass().getResourceAsStream(resourceName);
diff --git
a/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_multiple_accesses.json
b/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_multiple_accesses.json
new file mode 100644
index 000000000..6b53d2e02
--- /dev/null
+++
b/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_multiple_accesses.json
@@ -0,0 +1,92 @@
+{
+ "serviceName":"hdfsdev",
+
+ "serviceDef":{
+ "name":"hdfs",
+ "id":1,
+ "resources":[
+
{"name":"path","type":"path","level":1,"mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher","matcherOptions":{"wildCard":true,
"ignoreCase":true},"label":"Resource Path","description":"HDFS file or
directory path"}
+ ],
+ "accessTypes":[
+ {"name":"read","label":"Read"},
+ {"name":"write","label":"Write"},
+ {"name":"execute","label":"Execute"}
+ ],
+ "contextEnrichers":
+ [
+ {
+ "itemId":1,
+ "name" : "GeolocationEnricher",
+ "enricher" :
"org.apache.ranger.plugin.contextenricher.RangerFileBasedGeolocationProvider",
+ "enricherOptions" : {
+ "FilePath":"/etc/ranger/geo/geo.txt", "ForceRead":"false",
"IPInDotFormat":"true"
+ ,"geolocation.meta.prefix": "TEST_"
+ }
+ }
+ ],
+ "policyConditions": [
+ {
+ "itemId":1,
+ "name":"ScriptConditionEvaluator",
+ "evaluator":
"org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator",
+ "evaluatorOptions" : {"engineName":"JavaScript"},
+ "label":"Script",
+ "description": "Script to execute"
+ }
+ ]
+ },
+
+ "policies":[
+ {"id":1,"name":"audit-all-access under
/public","isEnabled":true,"isAuditEnabled":true,
+ "resources":{"path":{"values":["/public"],"isRecursive":true}},
+ "policyItems":[
+ {"accesses":[],"users":[],"groups":["public"],"delegateAdmin":false}
+ ]
+ }
+ ,
+ {"id":2,"name":"allow-execute-to-all under
/public/","isEnabled":true,"isAuditEnabled":false,
+ "resources":{"path":{"values":["/public/*"],"isRecursive":true}},
+ "policyItems":[
+
{"accesses":[{"type":"execute","isAllowed":true}],"users":[],"groups":["public"],"delegateAdmin":false}
+ ]
+ }
+ ,
+ {"id":3,"name":"allow-read-to-finance under
/public/finance","isEnabled":true,"isAuditEnabled":true,
+ "resources":{"path":{"values":["/public/finance"],"isRecursive":true}},
+ "policyItems":[
+
{"accesses":[{"type":"read","isAllowed":true}],"users":["finance"],"groups":[],"delegateAdmin":false}
+ ]
+ }
+ ],
+
+ "tests":[
+ {"name":"ALLOW 'read_execute /public/finance' for user finance",
+ "request":{
+ "resource":{"elements":{"path":"/public/finance"}},
+
"accessType":"read","user":"finance","userGroups":[],"requestData":"read_execute
/public/finance",
+ "context": {"ACCESSTYPES": [ "read", "execute" ]}
+
+ },
+ "result":{"isAudited":true,"isAllowed":true,"policyId":3}
+ }
+ ,
+ {"name":"DENY 'read_execute /public/finance' for user hr",
+ "request":{
+ "resource":{"elements":{"path":"/public/finance"}},
+
"accessType":"read","user":"hr","userGroups":[],"requestData":"read_execute
/public/finance",
+ "context": {"ACCESSTYPES": [ "read", "execute" ]}
+
+ },
+ "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+ }
+ ,
+ {"name":"ALLOW 'execute /public/finance' for user hr",
+ "request":{
+ "resource":{"elements":{"path":"/public/finance"}},
+
"accessType":"execute","user":"hr","userGroups":[],"requestData":"execute
/public/finance"
+ },
+ "result":{"isAudited":true,"isAllowed":true,"policyId":2}
+ }
+ ]
+}
+