Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -199,6 +204,7 @@ public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls

if (policyType == RangerPolicy.POLICY_TYPE_ACCESS) {
updateFromPolicyACLs(isConditionalMatch, acls, targetAccessTypes);
filterAclResultsByValiditySchedule(request, acls);
Comment thread
rameeshm marked this conversation as resolved.
} else if (policyType == RangerPolicy.POLICY_TYPE_ROWFILTER) {
updateRowFiltersFromPolicy(isConditionalMatch, acls, targetAccessTypes);
} else if (policyType == RangerPolicy.POLICY_TYPE_DATAMASK) {
Expand Down Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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\"}" ] }
]
}
]
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 } } },
Expand All @@ -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 } } }
},
Expand All @@ -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 } } }
},
Expand All @@ -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 } } }
},
Expand All @@ -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 } } }
},
Expand Down
Loading