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 <[email protected]>
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) {