You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by rm...@apache.org on 2026/05/26 16:41:48 UTC
(ranger) 01/01: RANGER-5610:getResourceACLs for a principal should consider validitySchedule of principal for ACL creation
This is an automated email from the ASF dual-hosted git repository.
rameeshm pushed a commit to branch RANGER-5610-patch
in repository https://gitbox.apache.org/repos/asf/ranger.git
commit eb67dfbdfe7d784d89374076e036f01576c20867
Author: Ramesh Mani <rm...@apache.org>
AuthorDate: Tue May 26 09:41:06 2026 -0700
RANGER-5610:getResourceACLs for a principal should consider validitySchedule of principal for ACL creation
---
.../RangerAbstractPolicyEvaluator.java | 128 +++++++++++++++++++++
.../policyengine/gds/gds_info_hive_access.json | 13 +++
.../gds/test_gds_policy_hive_access.json | 23 ++++
3 files changed, 164 insertions(+)
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java
index 7c45f6dfb..a55f8535f 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java
@@ -20,8 +20,12 @@
package org.apache.ranger.plugin.policyevaluator;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.plugin.conditionevaluator.RangerValidityScheduleConditionEvaluator;
import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
@@ -32,6 +36,7 @@
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceMatchingScope;
import org.apache.ranger.plugin.policyengine.RangerPluginContext;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
import org.apache.ranger.plugin.policyengine.RangerResourceACLs;
import org.apache.ranger.plugin.policyengine.RangerResourceACLs.DataMaskResult;
@@ -199,6 +204,7 @@ public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls
if (policyType == RangerPolicy.POLICY_TYPE_ACCESS) {
updateFromPolicyACLs(isConditionalMatch, acls, targetAccessTypes);
+ filterAclResultsByValiditySchedule(request, acls);
} else if (policyType == RangerPolicy.POLICY_TYPE_ROWFILTER) {
updateRowFiltersFromPolicy(isConditionalMatch, acls, targetAccessTypes);
} else if (policyType == RangerPolicy.POLICY_TYPE_DATAMASK) {
@@ -412,6 +418,128 @@ private void updateFromPolicyACLs(boolean isConditional, RangerResourceACLs reso
}
}
+ private void filterAclResultsByValiditySchedule(RangerAccessRequest request, RangerResourceACLs resourceACLs) {
+ if (request == null || resourceACLs == null || request.getAccessTime() == null) {
+ return;
+ }
+
+ String user = request.getUser();
+ Set<String> groups = request.getUserGroups();
+ Set<String> roles = request.getUserRoles();
+
+ if (StringUtils.isBlank(user) && CollectionUtils.isEmpty(groups) && CollectionUtils.isEmpty(roles)) {
+ return;
+ }
+
+ RangerPolicy policy = getPolicy();
+ if (policy == null) {
+ return;
+ }
+
+ List<RangerPolicyItem> policyItems = new ArrayList<>();
+ policyItems.addAll(policy.getPolicyItems());
+ policyItems.addAll(policy.getDenyPolicyItems());
+ policyItems.addAll(policy.getAllowExceptions());
+ policyItems.addAll(policy.getDenyExceptions());
+
+ if (CollectionUtils.isEmpty(policyItems)) {
+ return;
+ }
+
+ Map<String, Collection<String>> impliedAccessGrants = ServiceDefUtil.getExpandedImpliedGrants(getServiceDef());
+
+ for (RangerPolicyItem policyItem : policyItems) {
+ if (!isPolicyItemValidityActive(policyItem, request)) {
+ removeAccessesForPrincipal(policyItem, impliedAccessGrants, user, groups, roles, resourceACLs);
+ }
+ }
+ }
+
+ private boolean isPolicyItemValidityActive(RangerPolicyItem policyItem, RangerAccessRequest request) {
+ if (policyItem == null || request == null || CollectionUtils.isEmpty(policyItem.getConditions())) {
+ return true;
+ }
+
+ for (RangerPolicy.RangerPolicyItemCondition condition : policyItem.getConditions()) {
+ if (!StringUtils.equalsIgnoreCase(condition.getType(), "validitySchedule")) {
+ continue;
+ }
+
+ RangerValidityScheduleConditionEvaluator evaluator = new RangerValidityScheduleConditionEvaluator();
+ evaluator.setPolicyItemCondition(condition);
+ evaluator.init();
+
+ if (!evaluator.isMatched(request)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void removeAccessesForPrincipal(RangerPolicyItem policyItem,
+ Map<String, Collection<String>> impliedAccessGrants,
+ String user,
+ Set<String> groups,
+ Set<String> roles,
+ RangerResourceACLs resourceACLs) {
+ if (policyItem == null || CollectionUtils.isEmpty(policyItem.getAccesses())) {
+ return;
+ }
+
+ for (RangerPolicyItemAccess access : policyItem.getAccesses()) {
+ Collection<String> accessTypes = impliedAccessGrants.get(access.getType());
+ if (CollectionUtils.isEmpty(accessTypes)) {
+ accessTypes = Collections.singleton(access.getType());
+ }
+
+ if (StringUtils.isNotBlank(user) && CollectionUtils.isNotEmpty(policyItem.getUsers())) {
+ if (policyItem.getUsers().contains(user) || policyItem.getUsers().contains(RangerPolicyEngine.USER_CURRENT)) {
+ removeAccessTypes(resourceACLs.getUserACLs(), user, accessTypes);
+ }
+ }
+
+ if (CollectionUtils.isNotEmpty(groups) && CollectionUtils.isNotEmpty(policyItem.getGroups())) {
+ if (policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC)) {
+ removeAccessTypes(resourceACLs.getGroupACLs(), RangerPolicyEngine.GROUP_PUBLIC, accessTypes);
+ } else {
+ for (String group : groups) {
+ if (policyItem.getGroups().contains(group)) {
+ removeAccessTypes(resourceACLs.getGroupACLs(), group, accessTypes);
+ }
+ }
+ }
+ }
+
+ if (CollectionUtils.isNotEmpty(roles) && CollectionUtils.isNotEmpty(policyItem.getRoles())) {
+ for (String role : roles) {
+ if (policyItem.getRoles().contains(role)) {
+ removeAccessTypes(resourceACLs.getRoleACLs(), role, accessTypes);
+ }
+ }
+ }
+ }
+ }
+
+ private void removeAccessTypes(Map<String, Map<String, RangerResourceACLs.AccessResult>> aclMap, String principal, Collection<String> accessTypes) {
+ if (MapUtils.isEmpty(aclMap) || StringUtils.isBlank(principal) || CollectionUtils.isEmpty(accessTypes)) {
+ return;
+ }
+
+ Map<String, RangerResourceACLs.AccessResult> accessInfo = aclMap.get(principal);
+ if (MapUtils.isEmpty(accessInfo)) {
+ return;
+ }
+
+ for (String accessType : accessTypes) {
+ accessInfo.remove(accessType);
+ }
+
+ if (accessInfo.isEmpty()) {
+ aclMap.remove(principal);
+ }
+ }
+
private void updateRowFiltersFromPolicy(boolean isConditional, RangerResourceACLs resourceACLs, Set<String> targetAccessTypes) {
PolicyACLSummary aclSummary = getPolicyACLSummary();
diff --git a/agents-common/src/test/resources/policyengine/gds/gds_info_hive_access.json b/agents-common/src/test/resources/policyengine/gds/gds_info_hive_access.json
index 96b399c85..ded51dea1 100644
--- a/agents-common/src/test/resources/policyengine/gds/gds_info_hive_access.json
+++ b/agents-common/src/test/resources/policyengine/gds/gds_info_hive_access.json
@@ -8,6 +8,19 @@
"policyItems":[
{ "accesses":[ { "type": "_ALL", "isAllowed": true } ], "users": [ "ds-user", "ds1-user" ], "groups": []}
]
+ },
+ { "id": 2010, "name": "dataset-1-expired", "isEnabled": true, "isAuditEnabled": true,
+ "resources": { "dataset-id": { "values": ["1"] } },
+ "policyItems":[
+ {
+ "accesses":[ { "type": "_READ", "isAllowed": true } ],
+ "users": [ "expired-user" ],
+ "groups": [],
+ "conditions": [
+ { "type": "validitySchedule", "values": [ "{\"startTime\":\"2000/01/01 00:00:00\",\"endTime\":\"2000/01/02 00:00:00\",\"timeZone\":\"UTC\"}" ] }
+ ]
+ }
+ ]
}
]
},
diff --git a/agents-common/src/test/resources/policyengine/gds/test_gds_policy_hive_access.json b/agents-common/src/test/resources/policyengine/gds/test_gds_policy_hive_access.json
index 6ae15d4a1..ddbd3a8be 100644
--- a/agents-common/src/test/resources/policyengine/gds/test_gds_policy_hive_access.json
+++ b/agents-common/src/test/resources/policyengine/gds/test_gds_policy_hive_access.json
@@ -303,6 +303,25 @@
{
"name": "ACLs: table: sales.prospects",
"request": { "resource": { "elements": { "database": "sales", "table": "prospects" } } },
+ "acls": {
+ "userACLs": {
+ "ds-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2001 } } },
+ "ds1-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2001 } } },
+ "expired-user": { "select": { "result": 2, "isFinal": true, "policy": { "id": 2010 } } },
+ "proj-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 3001 } } },
+ "proj1-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 3001 } } }
+ },
+ "datasets": [ "dataset-1" ],
+ "projects": [ "project-1" ]
+ }
+ },
+ {
+ "name": "ACLs: table: sales.prospects, user: expired-user, expired validitySchedule",
+ "request": {
+ "resource": { "elements": { "database": "sales", "table": "prospects" } },
+ "user": "expired-user",
+ "userGroups": []
+ },
"acls": {
"userACLs": {
"ds-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2001 } } },
@@ -321,6 +340,7 @@
"userACLs": {
"ds-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2001 } } },
"ds1-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2001 } } },
+ "expired-user": { "select": { "result": 2, "isFinal": true, "policy": { "id": 2010 } } },
"proj-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 3001 } } },
"proj1-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 3001 } } }
},
@@ -340,6 +360,7 @@
"userACLs": {
"ds-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2001 } } },
"ds1-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2001 } } },
+ "expired-user": { "select": { "result": 2, "isFinal": true, "policy": { "id": 2010 } } },
"proj-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 3001 } } },
"proj1-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 3001 } } }
},
@@ -360,6 +381,7 @@
"ds-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2002 } } },
"ds1-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2001 } } },
"ds2-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2002 } } },
+ "expired-user": { "select": { "result": 2, "isFinal": true, "policy": { "id": 2010 } } },
"proj-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 3001 } } },
"proj1-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 3001 } } }
},
@@ -375,6 +397,7 @@
"ds-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2002 } } },
"ds1-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2001 } } },
"ds2-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 2002 } } },
+ "expired-user": { "select": { "result": 2, "isFinal": true, "policy": { "id": 2010 } } },
"proj-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 3001 } } },
"proj1-user": { "select": { "result": 1, "isFinal": true, "policy": { "id": 3001 } } }
},