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 <ab...@apache.org>
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}
+    }
+  ]
+}
+

Reply via email to