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 56d5bf917 RANGER-3999: Implement more efficient way to handle _any 
access authorization
56d5bf917 is described below

commit 56d5bf9173dc2c6d04692a07e67eace5e5d98ed4
Author: Abhay Kulkarni <ab...@apache.org>
AuthorDate: Tue Dec 6 14:25:10 2022 -0800

    RANGER-3999: Implement more efficient way to handle _any access 
authorization
---
 .../policyengine/RangerAccessRequestWrapper.java   | 105 +++++++++++++++++++++
 .../policyengine/RangerPolicyEngineImpl.java       |  37 ++------
 .../RangerDefaultPolicyEvaluator.java              |  95 +++++++++++++++++--
 .../RangerOptimizedPolicyEvaluator.java            |   6 ++
 .../plugin/util/RangerAccessRequestUtil.java       |  13 ++-
 5 files changed, 218 insertions(+), 38 deletions(-)

diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
new file mode 100644
index 000000000..6aec330d7
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.policyengine;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class RangerAccessRequestWrapper implements RangerAccessRequest {
+
+    private final RangerAccessRequest request;
+    private final String              accessType;
+    private final boolean             isAccessTypeAny;
+    private final boolean             isAccessTypeDelegatedAdmin;
+
+
+    public RangerAccessRequestWrapper(RangerAccessRequest request, String 
accessType) {
+        this.request                    = request;
+        this.accessType                 = accessType;
+        this.isAccessTypeAny            = StringUtils.equals(accessType, 
RangerPolicyEngine.ANY_ACCESS);
+        this.isAccessTypeDelegatedAdmin = StringUtils.equals(accessType, 
RangerPolicyEngine.ADMIN_ACCESS);
+    }
+
+    @Override
+    public RangerAccessResource getResource() { return request.getResource(); }
+
+    @Override
+    public String getAccessType() { return accessType; }
+
+    @Override
+    public boolean isAccessTypeAny() { return isAccessTypeAny; }
+
+    @Override
+    public boolean isAccessTypeDelegatedAdmin() { return 
isAccessTypeDelegatedAdmin; }
+
+    @Override
+    public String getUser() { return request.getUser(); }
+
+    @Override
+    public Set<String> getUserGroups() { return request.getUserGroups(); }
+
+    @Override
+    public Set<String> getUserRoles() {return request.getUserRoles(); }
+
+    @Override
+    public Date getAccessTime() { return request.getAccessTime(); }
+
+    @Override
+    public String getClientIPAddress() { return request.getClientIPAddress(); }
+
+    @Override
+    public String getRemoteIPAddress() { return request.getRemoteIPAddress(); }
+
+    @Override
+    public List<String> getForwardedAddresses() { return 
request.getForwardedAddresses(); }
+
+    @Override
+    public String getClientType() { return request.getClientType(); }
+
+    @Override
+    public String getAction() { return request.getAction(); }
+
+    @Override
+    public String getRequestData() { return request.getRequestData(); }
+
+    @Override
+    public String getSessionId() { return request.getSessionId(); }
+
+    @Override
+    public String getClusterName() { return request.getClusterName(); }
+
+    @Override
+    public String getClusterType() { return request.getClusterType(); }
+
+    @Override
+    public Map<String, Object> getContext() { return request.getContext(); }
+
+    @Override
+    public RangerAccessRequest getReadOnlyCopy() { return 
request.getReadOnlyCopy(); }
+
+    @Override
+    public ResourceMatchingScope getResourceMatchingScope() { return 
request.getResourceMatchingScope(); }
+
+}
+
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 23db18f3a..8d80ad6a3 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
@@ -692,42 +692,19 @@ public class RangerPolicyEngineImpl implements 
RangerPolicyEngine {
                final RangerAccessResult ret;
 
                if (request.isAccessTypeAny()) {
-                       RangerAccessResult denyResult  = null;
-                       RangerAccessResult allowResult = null;
-
-                       ret = createAccessResult(request, policyType);
-
                        List<RangerServiceDef.RangerAccessTypeDef> 
allAccessDefs = getServiceDef().getAccessTypes();
 
+                       Set<String> allRequestedAccesses = new HashSet<>();
                        for (RangerServiceDef.RangerAccessTypeDef accessTypeDef 
: allAccessDefs) {
-                               RangerAccessRequestImpl requestForOneAccessType 
= new RangerAccessRequestImpl(request);
-                               
RangerAccessRequestUtil.setIsAnyAccessInContext(requestForOneAccessType.getContext(),
 Boolean.TRUE);
-
-                               
requestForOneAccessType.setAccessType(accessTypeDef.getName());
-
-                               RangerAccessResult resultForOneAccessType = 
evaluatePoliciesForOneAccessTypeNoAudit(requestForOneAccessType, policyType, 
zoneName, policyRepository, tagPolicyRepository);
-
-                               ret.setAuditResultFrom(resultForOneAccessType);
-
-                               if 
(resultForOneAccessType.getIsAccessDetermined()) {
-                                       if 
(resultForOneAccessType.getIsAllowed()) {
-                                               allowResult = 
resultForOneAccessType;
-                                               break;
-                                       } else if (denyResult == null) {
-                                               denyResult = 
resultForOneAccessType;
-                                       }
-                               }
-                       }
-
-                       if (allowResult != null) {
-                               ret.setAccessResultFrom(allowResult);
-                       } else if (denyResult != null) {
-                               ret.setAccessResultFrom(denyResult);
+                               String requestedAccess = 
accessTypeDef.getName();
+                               allRequestedAccesses.add(requestedAccess);
                        }
-               } else {
-                       ret = evaluatePoliciesForOneAccessTypeNoAudit(request, 
policyType, zoneName, policyRepository, tagPolicyRepository);
+                       
RangerAccessRequestUtil.setIsAnyAccessInContext(request.getContext(), 
Boolean.TRUE);
+                       
request.getContext().put(RangerAccessRequestUtil.KEY_CONTEXT_ACCESSTYPES, 
allRequestedAccesses);
                }
 
+               ret = evaluatePoliciesForOneAccessTypeNoAudit(request, 
policyType, zoneName, policyRepository, tagPolicyRepository);
+
                if (LOG.isDebugEnabled()) {
                        LOG.debug("<== 
RangerPolicyEngineImpl.evaluatePoliciesNoAudit(" + request + ", policyType =" + 
policyType + ", zoneName=" + zoneName + "): " + ret);
                }
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 520ddf865..55752e79c 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
@@ -43,6 +43,7 @@ import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
 import org.apache.ranger.plugin.model.RangerValiditySchedule;
 import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestWrapper;
 import org.apache.ranger.plugin.policyengine.RangerAccessResource;
 import org.apache.ranger.plugin.policyengine.RangerAccessResult;
 import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
@@ -241,7 +242,7 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
 
                                        final boolean isMatched;
 
-                                       if (request.isAccessTypeAny() || 
Boolean.TRUE.equals(RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext())))
 {
+                                       if (request.isAccessTypeAny() || 
RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext())) {
                                                isMatched = matchType != 
RangerPolicyResourceMatcher.MatchType.NONE;
                                        } else if 
(request.getResourceMatchingScope() == 
RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) {
                                                isMatched = matchType != 
RangerPolicyResourceMatcher.MatchType.NONE;
@@ -794,7 +795,25 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                        if (LOG.isDebugEnabled()) {
                                LOG.debug("Using ACL Summary for access 
evaluation. PolicyId=[" + getPolicyId() + "]");
                        }
-                       Integer accessResult = 
lookupPolicyACLSummary(request.getUser(), request.getUserGroups(), 
RangerAccessRequestUtil.getUserRoles(request), request.isAccessTypeAny() || 
Boolean.TRUE.equals(RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext()))
 ? RangerPolicyEngine.ANY_ACCESS : request.getAccessType());
+                       Integer accessResult = null;
+
+                       if (request.isAccessTypeAny() || 
RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext())) {
+                               accessResult = 
lookupPolicyACLSummary(request.getUser(), request.getUserGroups(), 
request.getUserRoles(), RangerPolicyEngine.ANY_ACCESS);
+                       } else {
+                               Set<String> allRequestedAccesses = 
RangerAccessRequestUtil.getAllRequestedAccessTypes(request);
+
+                               if 
(CollectionUtils.isNotEmpty(allRequestedAccesses)) {
+                                       for (String accessType : 
allRequestedAccesses) {
+                                               accessResult = 
lookupPolicyACLSummary(request.getUser(), request.getUserGroups(), 
request.getUserRoles(), accessType);
+                                               if (accessResult == null) {
+                                                       break;
+                                               }
+                                       }
+                               } else {
+                                       accessResult = 
lookupPolicyACLSummary(request.getUser(), request.getUserGroups(), 
request.getUserRoles(), request.getAccessType());
+                               }
+                       }
+
                        if (accessResult != null) {
                                updateAccessResult(result, matchType, 
accessResult.equals(RangerPolicyEvaluator.ACCESS_ALLOWED), null);
                        } else if (getPolicy().getIsDenyAllElse()) {
@@ -804,13 +823,75 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                        if (LOG.isDebugEnabled()) {
                                LOG.debug("Using policyItemEvaluators for 
access evaluation. PolicyId=[" + getPolicyId() + "]");
                        }
+                       Set<String> allRequestedAccesses = 
RangerAccessRequestUtil.getAllRequestedAccessTypes(request);
 
-                       RangerPolicyItemEvaluator matchedPolicyItem = 
getMatchingPolicyItem(request, result);
+                       if (CollectionUtils.isNotEmpty(allRequestedAccesses)) {
 
-                       if (matchedPolicyItem != null) {
-                               matchedPolicyItem.updateAccessResult(this, 
result, matchType);
-                       } else if (getPolicy().getIsDenyAllElse() && 
(getPolicy().getPolicyType() == null || getPolicy().getPolicyType() == 
RangerPolicy.POLICY_TYPE_ACCESS)) {
-                               updateAccessResult(result, matchType, false, 
"matched deny-all-else policy");
+                               RangerAccessResult denyResult  = null;
+                               RangerAccessResult allowResult = null;
+                               boolean            noResult    = false;
+
+                               for (String accessType : allRequestedAccesses) {
+
+                                       RangerAccessRequestWrapper  oneRequest 
= new RangerAccessRequestWrapper(request, accessType);
+                                       RangerAccessResult          oneResult  
= new RangerAccessResult(result.getPolicyType(), result.getServiceName(), 
result.getServiceDef(), oneRequest);
+
+                                       oneResult.setAuditResultFrom(result);
+
+                                       RangerPolicyItemEvaluator 
matchedPolicyItem = getMatchingPolicyItem(oneRequest, oneResult);
+
+                                       if (matchedPolicyItem != null) {
+                                               
matchedPolicyItem.updateAccessResult(this, oneResult, matchType);
+                                       } else if 
(getPolicy().getIsDenyAllElse() && (getPolicy().getPolicyType() == null || 
getPolicy().getPolicyType() == RangerPolicy.POLICY_TYPE_ACCESS)) {
+                                               updateAccessResult(oneResult, 
matchType, false, "matched deny-all-else policy");
+                                       }
+
+                                       if (request.isAccessTypeAny()) {
+                                               // Implement OR logic
+                                               if (oneResult.getIsAllowed()) {
+                                                       allowResult = oneResult;
+                                                       denyResult  = null;
+
+                                                       break;
+                                               } else if 
(oneResult.getIsAccessDetermined()) {
+                                                       if (!noResult) {
+                                                               if (denyResult 
== null) {
+                                                                       
denyResult = oneResult;
+                                                               }
+                                                       }
+                                               } else {
+                                                       noResult = true;
+                                                       denyResult = null;
+                                               }
+                                       } else {
+                                               // Implement AND logic
+                                               if 
(oneResult.getIsAccessDetermined() && !oneResult.getIsAllowed()) {
+                                                       denyResult = oneResult;
+                                                       allowResult = null;
+
+                                                       break;
+                                               } else if 
(oneResult.getIsAllowed()) {
+                                                       allowResult = noResult 
? null : oneResult;
+                                               } else {
+                                                       noResult = true;
+                                                       allowResult = null;
+                                               }
+                                       }
+                               }
+
+                               if (allowResult != null) {
+                                       result.setAccessResultFrom(allowResult);
+                               } else if (denyResult != null) {
+                                       result.setAccessResultFrom(denyResult);
+                               }
+
+                       } else {
+                               RangerPolicyItemEvaluator matchedPolicyItem = 
getMatchingPolicyItem(request, result);
+                               if (matchedPolicyItem != null) {
+                                       
matchedPolicyItem.updateAccessResult(this, result, matchType);
+                               } else if (getPolicy().getIsDenyAllElse() && 
(getPolicy().getPolicyType() == null || getPolicy().getPolicyType() == 
RangerPolicy.POLICY_TYPE_ACCESS)) {
+                                       updateAccessResult(result, matchType, 
false, "matched deny-all-else policy");
+                               }
                        }
                }
 
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
index d3fc27d7d..e50eb5f54 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
@@ -257,6 +257,12 @@ public class RangerOptimizedPolicyEvaluator extends 
RangerDefaultPolicyEvaluator
                 ret = true;
             } else {
                ret = accessPerms.contains(request.getAccessType());
+
+               if (!ret) {
+                   Set<String> allRequestedAccesses = 
RangerAccessRequestUtil.getAllRequestedAccessTypes(request);
+                   ret = CollectionUtils.containsAny(accessPerms, 
allRequestedAccesses);
+               }
+
                if (!ret) {
                    if (request.isAccessTypeDelegatedAdmin()) {
                        ret = delegateAdmin;
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 df03ed1c4..05d9a6007 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
@@ -199,7 +199,18 @@ public class RangerAccessRequestUtil {
        }
 
        public static Boolean getIsAnyAccessInContext(Map<String, Object> 
context) {
-               return (Boolean)context.get(KEY_CONTEXT_IS_ANY_ACCESS);
+               Boolean ret = (Boolean)context.get(KEY_CONTEXT_IS_ANY_ACCESS);
+               return ret == null ? Boolean.FALSE : ret;
+       }
+
+       public static void setAllRequestedAccessTypes(Map<String, Object> 
context, Set<String> accessTypes) {
+               context.put(KEY_CONTEXT_ACCESSTYPES, accessTypes);
+       }
+
+       public static Set<String> 
getAllRequestedAccessTypes(RangerAccessRequest request) {
+               Set<String> ret = (Set<String>) 
request.getContext().get(KEY_CONTEXT_ACCESSTYPES);
+
+               return ret != null ? ret : 
Collections.singleton(request.getAccessType());
        }
 
        public static void setRequestInContext(RangerAccessRequest request) {

Reply via email to