You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2021/05/26 04:12:00 UTC
[ranger] branch ranger-2.2 updated: RANGER-3296: updated
getResourceACLs() to include row-filter and column-masking details as well
This is an automated email from the ASF dual-hosted git repository.
madhan pushed a commit to branch ranger-2.2
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.2 by this push:
new c33d74a RANGER-3296: updated getResourceACLs() to include row-filter and column-masking details as well
c33d74a is described below
commit c33d74a80dd2e75296458e40e28fe32d98e8e520
Author: Madhan Neethiraj <ma...@apache.org>
AuthorDate: Mon May 24 16:49:26 2021 -0700
RANGER-3296: updated getResourceACLs() to include row-filter and column-masking details as well
(cherry picked from commit 09eb8ba7fb52239e0019832cb1e58cf310140809)
---
.../apache/ranger/plugin/model/RangerPolicy.java | 4 -
.../policyengine/RangerPolicyEngineImpl.java | 220 ++++++++-----
.../plugin/policyengine/RangerResourceACLs.java | 263 +++++++++++++++-
.../RangerDefaultPolicyEvaluator.java | 9 +
.../policyevaluator/RangerPolicyEvaluator.java | 71 ++++-
.../ranger/plugin/policyengine/TestPolicyACLs.java | 52 +++-
.../resources/policyengine/ACLResourceTags.json | 44 ++-
.../policyengine/test_aclprovider_mask_filter.json | 341 +++++++++++++++++++++
8 files changed, 907 insertions(+), 97 deletions(-)
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
index 3a6f416..15fbacc 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
@@ -1588,8 +1588,6 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
@Override
public boolean equals(Object obj) {
- if(! super.equals(obj))
- return false;
if (this == obj)
return true;
if (obj == null)
@@ -1671,8 +1669,6 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
@Override
public boolean equals(Object obj) {
- if(! super.equals(obj))
- return false;
if (this == obj)
return true;
if (obj == null)
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 75811b8..ecfc9ad 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
@@ -31,9 +31,11 @@ import org.apache.ranger.authorization.utils.StringUtil;
import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyengine.RangerResourceACLs.DataMaskResult;
+import org.apache.ranger.plugin.policyengine.RangerResourceACLs.RowFilterResult;
import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator.PolicyACLSummary;
-import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
+import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher.MatchType;
import org.apache.ranger.plugin.service.RangerDefaultRequestProcessor;
import org.apache.ranger.plugin.util.GrantRevokeRequest;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
@@ -266,15 +268,20 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
if (LOG.isDebugEnabled()) {
LOG.debug("zoneName:[" + zoneName + "]");
}
- List<RangerPolicyEvaluator> allEvaluators = new ArrayList<>();
- Map<Long, RangerPolicyResourceMatcher.MatchType> tagMatchTypeMap = new HashMap<>();
- Set<Long> policyIdForTemporalTags = new HashSet<>();
- getResourceACLEvaluatorsForZone(request, zoneName, allEvaluators, tagMatchTypeMap, policyIdForTemporalTags);
+ for (int policyType : RangerPolicy.POLICY_TYPES) {
+ List<RangerPolicyEvaluator> allEvaluators = new ArrayList<>();
+ Map<Long, MatchType> tagMatchTypeMap = new HashMap<>();
+ Set<Long> policyIdForTemporalTags = new HashSet<>();
- allEvaluators.sort(RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR);
+ getResourceACLEvaluatorsForZone(request, zoneName, policyType, allEvaluators, tagMatchTypeMap, policyIdForTemporalTags);
+
+ allEvaluators.sort(RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR);
+
+ if (CollectionUtils.isEmpty(allEvaluators)) {
+ continue;
+ }
- if (CollectionUtils.isNotEmpty(allEvaluators)) {
Integer policyPriority = null;
for (RangerPolicyEvaluator evaluator : allEvaluators) {
@@ -283,12 +290,14 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
}
if (policyPriority != evaluator.getPolicyPriority()) {
- ret.finalizeAcls();
+ if (policyType == RangerPolicy.POLICY_TYPE_ACCESS) {
+ ret.finalizeAcls();
+ }
policyPriority = evaluator.getPolicyPriority();
}
- RangerPolicyResourceMatcher.MatchType matchType = tagMatchTypeMap.get(evaluator.getId());
+ MatchType matchType = tagMatchTypeMap.get(evaluator.getId());
if (matchType == null) {
matchType = evaluator.getPolicyResourceMatcher().getMatchType(request.getResource(), request.getContext());
@@ -297,80 +306,21 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
final boolean isMatched;
if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) {
- isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE;
+ isMatched = matchType != MatchType.NONE;
} else {
- isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.SELF_AND_ALL_DESCENDANTS;
+ isMatched = matchType == MatchType.SELF || matchType == MatchType.SELF_AND_ALL_DESCENDANTS;
}
if (!isMatched) {
continue;
}
- PolicyACLSummary aclSummary = evaluator.getPolicyACLSummary();
-
- if (aclSummary != null) {
- boolean isConditional = policyIdForTemporalTags.contains(evaluator.getId()) || evaluator.getValidityScheduleEvaluatorsCount() != 0;
- Integer accessResult;
-
- for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> userAccessInfo : aclSummary.getUsersAccessInfo().entrySet()) {
- final String userName = userAccessInfo.getKey();
-
- for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : userAccessInfo.getValue().entrySet()) {
- if (isConditional) {
- accessResult = ACCESS_CONDITIONAL;
- } else {
- accessResult = accessInfo.getValue().getResult();
-
- if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
- accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
- }
- }
-
- RangerPolicy policy = evaluator.getPolicy();
-
- ret.setUserAccessInfo(userName, accessInfo.getKey(), accessResult, policy);
- }
- }
-
- for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> groupAccessInfo : aclSummary.getGroupsAccessInfo().entrySet()) {
- final String groupName = groupAccessInfo.getKey();
-
- for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : groupAccessInfo.getValue().entrySet()) {
- if (isConditional) {
- accessResult = ACCESS_CONDITIONAL;
- } else {
- accessResult = accessInfo.getValue().getResult();
-
- if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
- accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
- }
- }
-
- RangerPolicy policy = evaluator.getPolicy();
-
- ret.setGroupAccessInfo(groupName, accessInfo.getKey(), accessResult, policy);
- }
- }
-
- for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> roleAccessInfo : aclSummary.getRolesAccessInfo().entrySet()) {
- final String roleName = roleAccessInfo.getKey();
-
- for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : roleAccessInfo.getValue().entrySet()) {
- if (isConditional) {
- accessResult = ACCESS_CONDITIONAL;
- } else {
- accessResult = accessInfo.getValue().getResult();
-
- if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
- accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
- }
- }
-
- RangerPolicy policy = evaluator.getPolicy();
-
- ret.setRoleAccessInfo(roleName, accessInfo.getKey(), accessResult, policy);
- }
- }
+ if (policyType == RangerPolicy.POLICY_TYPE_ACCESS) {
+ updateFromPolicyACLs(evaluator, policyIdForTemporalTags, ret);
+ } else if (policyType == RangerPolicy.POLICY_TYPE_ROWFILTER) {
+ updateRowFiltersFromPolicy(evaluator, policyIdForTemporalTags, ret);
+ } else if (policyType == RangerPolicy.POLICY_TYPE_DATAMASK) {
+ updateDataMasksFromPolicy(evaluator, policyIdForTemporalTags, ret);
}
}
@@ -929,14 +879,14 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
return ret;
}
- private void getResourceACLEvaluatorsForZone(RangerAccessRequest request, String zoneName, List<RangerPolicyEvaluator> allEvaluators, Map<Long, RangerPolicyResourceMatcher.MatchType> tagMatchTypeMap, Set<Long> policyIdForTemporalTags) {
+ private void getResourceACLEvaluatorsForZone(RangerAccessRequest request, String zoneName, int policyType, List<RangerPolicyEvaluator> allEvaluators, Map<Long, MatchType> tagMatchTypeMap, Set<Long> policyIdForTemporalTags) {
final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForZone(zoneName);
if (matchedRepository == null) {
LOG.error("policyRepository for zoneName:[" + zoneName + "], serviceName:[" + policyEngine.getPolicyRepository().getServiceName() + "], policyVersion:[" + getPolicyVersion() + "] is null!! ERROR!");
} else {
Set<RangerTagForEval> tags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext());
- List<PolicyEvaluatorForTag> tagPolicyEvaluators = policyEngine.getTagPolicyRepository() == null ? null : policyEngine.getTagPolicyRepository().getLikelyMatchPolicyEvaluators(request, tags, RangerPolicy.POLICY_TYPE_ACCESS, null);
+ List<PolicyEvaluatorForTag> tagPolicyEvaluators = policyEngine.getTagPolicyRepository() == null ? null : policyEngine.getTagPolicyRepository().getLikelyMatchPolicyEvaluators(request, tags, policyType, null);
if (CollectionUtils.isNotEmpty(tagPolicyEvaluators)) {
@@ -975,7 +925,7 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
}
}
- List<RangerPolicyEvaluator> resourcePolicyEvaluators = matchedRepository.getLikelyMatchPolicyEvaluators(request, RangerPolicy.POLICY_TYPE_ACCESS);
+ List<RangerPolicyEvaluator> resourcePolicyEvaluators = matchedRepository.getLikelyMatchPolicyEvaluators(request, policyType);
allEvaluators.addAll(resourcePolicyEvaluators);
}
@@ -1113,6 +1063,118 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
return ret;
}
+ private void updateFromPolicyACLs(RangerPolicyEvaluator evaluator, Set<Long> policyIdForTemporalTags, RangerResourceACLs resourceACLs) {
+ PolicyACLSummary aclSummary = evaluator.getPolicyACLSummary();
+
+ if (aclSummary == null) {
+ return;
+ }
+
+ boolean isConditional = policyIdForTemporalTags.contains(evaluator.getId()) || evaluator.getValidityScheduleEvaluatorsCount() != 0;
+
+ for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> userAccessInfo : aclSummary.getUsersAccessInfo().entrySet()) {
+ final String userName = userAccessInfo.getKey();
+
+ for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : userAccessInfo.getValue().entrySet()) {
+ Integer accessResult;
+
+ if (isConditional) {
+ accessResult = ACCESS_CONDITIONAL;
+ } else {
+ accessResult = accessInfo.getValue().getResult();
+
+ if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
+ accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
+ }
+ }
+
+ RangerPolicy policy = evaluator.getPolicy();
+
+ resourceACLs.setUserAccessInfo(userName, accessInfo.getKey(), accessResult, policy);
+ }
+ }
+
+ for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> groupAccessInfo : aclSummary.getGroupsAccessInfo().entrySet()) {
+ final String groupName = groupAccessInfo.getKey();
+
+ for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : groupAccessInfo.getValue().entrySet()) {
+ Integer accessResult;
+
+ if (isConditional) {
+ accessResult = ACCESS_CONDITIONAL;
+ } else {
+ accessResult = accessInfo.getValue().getResult();
+
+ if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
+ accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
+ }
+ }
+
+ RangerPolicy policy = evaluator.getPolicy();
+
+ resourceACLs.setGroupAccessInfo(groupName, accessInfo.getKey(), accessResult, policy);
+ }
+ }
+
+ for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> roleAccessInfo : aclSummary.getRolesAccessInfo().entrySet()) {
+ final String roleName = roleAccessInfo.getKey();
+
+ for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : roleAccessInfo.getValue().entrySet()) {
+ Integer accessResult;
+
+ if (isConditional) {
+ accessResult = ACCESS_CONDITIONAL;
+ } else {
+ accessResult = accessInfo.getValue().getResult();
+
+ if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
+ accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
+ }
+ }
+
+ RangerPolicy policy = evaluator.getPolicy();
+
+ resourceACLs.setRoleAccessInfo(roleName, accessInfo.getKey(), accessResult, policy);
+ }
+ }
+ }
+
+ private void updateRowFiltersFromPolicy(RangerPolicyEvaluator evaluator, Set<Long> policyIdForTemporalTags, RangerResourceACLs resourceACLs) {
+ PolicyACLSummary aclSummary = evaluator.getPolicyACLSummary();
+
+ if (aclSummary != null) {
+ boolean isConditional = policyIdForTemporalTags.contains(evaluator.getId()) || evaluator.getValidityScheduleEvaluatorsCount() != 0;
+
+ for (RowFilterResult rowFilterResult : aclSummary.getRowFilters()) {
+ if (isConditional && !rowFilterResult.getIsConditional()) {
+ rowFilterResult = new RowFilterResult(rowFilterResult);
+
+ rowFilterResult.setIsConditional(true);
+ }
+
+ resourceACLs.getRowFilters().add(rowFilterResult);
+ }
+ }
+ }
+
+ private void updateDataMasksFromPolicy(RangerPolicyEvaluator evaluator, Set<Long> policyIdForTemporalTags, RangerResourceACLs resourceACLs) {
+ PolicyACLSummary aclSummary = evaluator.getPolicyACLSummary();
+
+ if (aclSummary != null) {
+ boolean isConditional = policyIdForTemporalTags.contains(evaluator.getId()) || evaluator.getValidityScheduleEvaluatorsCount() != 0;
+
+ for (DataMaskResult dataMaskResult : aclSummary.getDataMasks()) {
+ if (isConditional && !dataMaskResult.getIsConditional()) {
+ dataMaskResult = new DataMaskResult(dataMaskResult);
+
+ dataMaskResult.setIsConditional(true);
+ }
+
+ resourceACLs.getDataMasks().add(dataMaskResult);
+ }
+ }
+ }
+
private static class ServiceConfig {
private final Set<String> auditExcludedUsers;
private final Set<String> auditExcludedGroups;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceACLs.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceACLs.java
index a0def54..2d08b0b 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceACLs.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceACLs.java
@@ -21,6 +21,8 @@ package org.apache.ranger.plugin.policyengine;
import org.apache.commons.lang.StringUtils;
import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
@@ -33,14 +35,19 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
import static org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator.ACCESS_ALLOWED;
import static org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator.ACCESS_DENIED;
public class RangerResourceACLs {
- final private Map<String, Map<String, AccessResult>> userACLs = new HashMap<>();
- final private Map<String, Map<String, AccessResult>> groupACLs = new HashMap<>();
- final private Map<String, Map<String, AccessResult>> roleACLs = new HashMap<>();
+ final private Map<String, Map<String, AccessResult>> userACLs = new HashMap<>();
+ final private Map<String, Map<String, AccessResult>> groupACLs = new HashMap<>();
+ final private Map<String, Map<String, AccessResult>> roleACLs = new HashMap<>();
+ final private List<RowFilterResult> rowFilters = new ArrayList<>();
+ final private List<DataMaskResult> dataMasks = new ArrayList<>();
+
public RangerResourceACLs() {
}
@@ -54,6 +61,10 @@ public class RangerResourceACLs {
public Map<String, Map<String, AccessResult>> getRoleACLs() { return roleACLs; }
+ public List<RowFilterResult> getRowFilters() { return rowFilters; }
+
+ public List<DataMaskResult> getDataMasks() { return dataMasks; }
+
public void finalizeAcls() {
Map<String, AccessResult> publicGroupAccessInfo = groupACLs.get(RangerPolicyEngine.GROUP_PUBLIC);
if (publicGroupAccessInfo != null) {
@@ -154,7 +165,7 @@ public class RangerResourceACLs {
@Override
public String toString() {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
sb.append("{");
@@ -196,6 +207,20 @@ public class RangerResourceACLs {
sb.append("}");
+ sb.append(", rowFilters=[");
+ for (RowFilterResult rowFilter : rowFilters) {
+ rowFilter.toString(sb);
+ sb.append(" ");
+ }
+ sb.append("]");
+
+ sb.append(", dataMasks=[");
+ for (DataMaskResult dataMask : dataMasks) {
+ dataMask.toString(sb);
+ sb.append(" ");
+ }
+ sb.append("]");
+
return sb.toString();
}
@@ -286,4 +311,234 @@ public class RangerResourceACLs {
return "CONDITIONAL_ALLOWED, final=" + isFinal;
}
}
+
+ @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
+ @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+ @JsonIgnoreProperties(ignoreUnknown=true)
+ @XmlRootElement
+ @XmlAccessorType(XmlAccessType.FIELD)
+ public static class DataMaskResult {
+ private final Set<String> users;
+ private final Set<String> groups;
+ private final Set<String> roles;
+ private final Set<String> accessTypes;
+ private final RangerPolicyItemDataMaskInfo maskInfo;
+ private boolean isConditional = false;
+
+ public DataMaskResult(Set<String> users, Set<String> groups, Set<String> roles, Set<String> accessTypes, RangerPolicyItemDataMaskInfo maskInfo) {
+ this.users = users;
+ this.groups = groups;
+ this.roles = roles;
+ this.accessTypes = accessTypes;
+ this.maskInfo = maskInfo;
+ }
+
+ public DataMaskResult(DataMaskResult that) {
+ this.users = that.users;
+ this.groups = that.groups;
+ this.roles = that.roles;
+ this.accessTypes = that.accessTypes;
+ this.maskInfo = that.maskInfo;
+ this.isConditional = that.isConditional;
+ }
+
+ public Set<String> getUsers() { return users; }
+
+ public Set<String> getGroups() { return groups; }
+
+ public Set<String> getRoles() { return roles; }
+
+ public Set<String> getAccessTypes() { return accessTypes; }
+
+ public RangerPolicyItemDataMaskInfo getMaskInfo() { return maskInfo; }
+
+ public boolean getIsConditional() { return isConditional; }
+
+ public void setIsConditional(boolean isConditional) { this.isConditional = isConditional; }
+
+ @Override
+ public int hashCode() { return Objects.hash(users, groups, roles, accessTypes, maskInfo, isConditional); }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other == null || getClass() != other.getClass()) {
+ return false;
+ } else {
+ DataMaskResult that = (DataMaskResult) other;
+
+ return Objects.equals(users, that.users) &&
+ Objects.equals(groups, that.groups) &&
+ Objects.equals(roles, that.roles) &&
+ Objects.equals(accessTypes, that.accessTypes) &&
+ Objects.equals(maskInfo, that.maskInfo) &&
+ isConditional == that.isConditional;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return toString(new StringBuilder()).toString();
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ sb.append("{");
+
+ if (users != null && !users.isEmpty()) {
+ sb.append("users:[");
+ for (String user : users) {
+ sb.append(user).append(' ');
+ }
+ sb.append("] ");
+ }
+
+ if (groups != null && !groups.isEmpty()) {
+ sb.append("groups:[");
+ for (String group : groups) {
+ sb.append(group).append(' ');
+ }
+ sb.append("] ");
+ }
+
+ if (roles != null && !roles.isEmpty()) {
+ sb.append("roles:[");
+ for (String role : roles) {
+ sb.append(role).append(' ');
+ }
+ sb.append("] ");
+ }
+
+ if (accessTypes != null && !accessTypes.isEmpty()) {
+ sb.append("accessTypes:[");
+ for (String accessType : accessTypes) {
+ sb.append(accessType).append(' ');
+ }
+ sb.append("] ");
+ }
+
+ sb.append("maskInfo=");
+ maskInfo.toString(sb);
+ sb.append(" isConditional=").append(isConditional);
+
+ sb.append("}");
+
+ return sb;
+ }
+ }
+
+ @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
+ @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+ @JsonIgnoreProperties(ignoreUnknown=true)
+ @XmlRootElement
+ @XmlAccessorType(XmlAccessType.FIELD)
+ public static class RowFilterResult {
+ private final Set<String> users;
+ private final Set<String> groups;
+ private final Set<String> roles;
+ private final Set<String> accessTypes;
+ private final RangerPolicyItemRowFilterInfo filterInfo;
+ private boolean isConditional = false;
+
+ public RowFilterResult(Set<String> users, Set<String> groups, Set<String> roles, Set<String> accessTypes, RangerPolicyItemRowFilterInfo filterInfo) {
+ this.users = users;
+ this.groups = groups;
+ this.roles = roles;
+ this.accessTypes = accessTypes;
+ this.filterInfo = filterInfo;
+ }
+
+ public RowFilterResult(RowFilterResult that) {
+ this.users = that.users;
+ this.groups = that.groups;
+ this.roles = that.roles;
+ this.accessTypes = that.accessTypes;
+ this.filterInfo = that.filterInfo;
+ this.isConditional = that.isConditional;
+ }
+
+ public Set<String> getUsers() { return users; }
+
+ public Set<String> getGroups() { return groups; }
+
+ public Set<String> getRoles() { return roles; }
+
+ public Set<String> getAccessTypes() { return accessTypes; }
+
+ public RangerPolicyItemRowFilterInfo getFilterInfo() { return filterInfo; }
+
+ public boolean getIsConditional() { return isConditional; }
+
+ public void setIsConditional(boolean isConditional) { this.isConditional = isConditional; }
+
+ @Override
+ public int hashCode() { return Objects.hash(users, groups, roles, accessTypes, filterInfo, isConditional); }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other == null || getClass() != other.getClass()) {
+ return false;
+ } else {
+ RowFilterResult that = (RowFilterResult) other;
+
+ return Objects.equals(users, that.users) &&
+ Objects.equals(groups, that.groups) &&
+ Objects.equals(roles, that.roles) &&
+ Objects.equals(accessTypes, that.accessTypes) &&
+ Objects.equals(filterInfo, that.filterInfo) &&
+ isConditional == that.isConditional;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return toString(new StringBuilder()).toString();
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ sb.append("{");
+
+ if (users != null && !users.isEmpty()) {
+ sb.append("users:[");
+ for (String user : users) {
+ sb.append(user).append(' ');
+ }
+ sb.append("] ");
+ }
+
+ if (groups != null && !groups.isEmpty()) {
+ sb.append("groups:[");
+ for (String group : groups) {
+ sb.append(group).append(' ');
+ }
+ sb.append("] ");
+ }
+
+ if (roles != null && !roles.isEmpty()) {
+ sb.append("roles:[");
+ for (String role : roles) {
+ sb.append(role).append(' ');
+ }
+ sb.append("] ");
+ }
+
+ if (accessTypes != null && !accessTypes.isEmpty()) {
+ sb.append("accessTypes:[");
+ for (String accessType : accessTypes) {
+ sb.append(accessType).append(' ');
+ }
+ sb.append("] ");
+ }
+
+ sb.append("filterInfo=");
+ filterInfo.toString(sb);
+ sb.append(" isConditional=").append(isConditional);
+
+ sb.append("}");
+
+ return sb;
+ }
+ }
}
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 2edd992..03e37fe 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
@@ -571,6 +571,15 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS, false);
}
}
+
+ for (RangerRowFilterPolicyItem policyItem : getPolicy().getRowFilterPolicyItems()) {
+ ret.processRowFilterPolicyItem(policyItem);
+ }
+
+ for (RangerDataMaskPolicyItem policyItem : getPolicy().getDataMaskPolicyItems()) {
+ ret.processDataMaskPolicyItem(policyItem);
+ }
+
final boolean isDenyAllElse = Boolean.TRUE.equals(getPolicy().getIsDenyAllElse());
final Set<String> allAccessTypeNames;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
index c611b5e..0157c00 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -32,19 +33,26 @@ import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerDataMaskPolicyItem;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerRowFilterPolicyItem;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerAccessResult;
import org.apache.ranger.plugin.policyengine.RangerAccessResource;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
+import org.apache.ranger.plugin.policyengine.RangerResourceACLs.DataMaskResult;
+import org.apache.ranger.plugin.policyengine.RangerResourceACLs.RowFilterResult;
import org.apache.ranger.plugin.policyengine.RangerResourceAccessInfo;
import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceEvaluator;
import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
+
import static org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW;
import static org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS;
import static org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY;
@@ -155,12 +163,12 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
return true;
}
}
- for (RangerPolicy.RangerDataMaskPolicyItem policyItem : policy.getDataMaskPolicyItems()) {
+ for (RangerDataMaskPolicyItem policyItem : policy.getDataMaskPolicyItems()) {
if (hasRoles(policyItem)) {
return true;
}
}
- for (RangerPolicy.RangerRowFilterPolicyItem policyItem : policy.getRowFilterPolicyItems()) {
+ for (RangerRowFilterPolicyItem policyItem : policy.getRowFilterPolicyItems()) {
if (hasRoles(policyItem)) {
return true;
}
@@ -223,14 +231,16 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
}
class PolicyACLSummary {
- private final Map<String, Map<String, AccessResult>> usersAccessInfo = new HashMap<>();
+ private final Map<String, Map<String, AccessResult>> usersAccessInfo = new HashMap<>();
private final Map<String, Map<String, AccessResult>> groupsAccessInfo = new HashMap<>();
private final Map<String, Map<String, AccessResult>> rolesAccessInfo = new HashMap<>();
+ private final List<RowFilterResult> rowFilters = new ArrayList<>();
+ private final List<DataMaskResult> dataMasks = new ArrayList<>();
private enum AccessorType { USER, GROUP, ROLE }
public static class AccessResult {
- private int result;
+ private int result;
private final boolean hasSeenDeny;
public AccessResult(int result) {
@@ -238,8 +248,8 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
}
public AccessResult(int result, boolean hasSeenDeny) {
+ this.result = result;
this.hasSeenDeny = hasSeenDeny;
- setResult(result);
}
public int getResult() {
@@ -253,6 +263,7 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
public boolean getHasSeenDeny() {
return hasSeenDeny;
}
+
@Override
public String toString() {
if (result == RangerPolicyEvaluator.ACCESS_ALLOWED)
@@ -280,6 +291,10 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
return rolesAccessInfo;
}
+ public List<RowFilterResult> getRowFilters() { return rowFilters; }
+
+ public List<DataMaskResult> getDataMasks() { return dataMasks; }
+
void processPolicyItem(RangerPolicyItem policyItem, int policyItemType, boolean isConditional) {
final Integer result;
final boolean hasContextSensitiveSpecification = RangerPolicyEvaluator.hasContextSensitiveSpecification(policyItem);
@@ -355,6 +370,52 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
}
}
+ void processRowFilterPolicyItem(RangerRowFilterPolicyItem policyItem) {
+ Set<String> users = new HashSet<>(policyItem.getUsers());
+ Set<String> groups = new HashSet<>(policyItem.getGroups());
+ Set<String> roles = new HashSet<>(policyItem.getRoles());
+ Set<String> accessTypes = new HashSet<>();
+
+ policyItem.getAccesses().forEach(accessType -> accessTypes.add(accessType.getType()));
+
+ if (users.contains(RangerPolicyEngine.USER_CURRENT)) { // replace with public group
+ users.remove(RangerPolicyEngine.USER_CURRENT);
+
+ groups.add(RangerPolicyEngine.GROUP_PUBLIC);
+ }
+
+ RowFilterResult filterResult = new RowFilterResult(users, groups, roles, accessTypes, policyItem.getRowFilterInfo());
+
+ if (RangerPolicyEvaluator.hasContextSensitiveSpecification(policyItem)) {
+ filterResult.setIsConditional(true);
+ }
+
+ rowFilters.add(filterResult);
+ }
+
+ void processDataMaskPolicyItem(RangerDataMaskPolicyItem policyItem) {
+ Set<String> users = new HashSet<>(policyItem.getUsers());
+ Set<String> groups = new HashSet<>(policyItem.getGroups());
+ Set<String> roles = new HashSet<>(policyItem.getRoles());
+ Set<String> accessTypes = new HashSet<>();
+
+ policyItem.getAccesses().forEach(accessType -> accessTypes.add(accessType.getType()));
+
+ if (users.contains(RangerPolicyEngine.USER_CURRENT)) { // replace with public group
+ users.remove(RangerPolicyEngine.USER_CURRENT);
+
+ groups.add(RangerPolicyEngine.GROUP_PUBLIC);
+ }
+
+ DataMaskResult dataMaskResult = new DataMaskResult(users, groups, roles, accessTypes, policyItem.getDataMaskInfo());
+
+ if (RangerPolicyEvaluator.hasContextSensitiveSpecification(policyItem)) {
+ dataMaskResult.setIsConditional(true);
+ }
+
+ dataMasks.add(dataMaskResult);
+ }
+
void finalizeAcls(final boolean isDenyAllElse, final Set<String> allAccessTypeNames) {
Map<String, AccessResult> publicGroupAccessInfo = groupsAccessInfo.get(RangerPolicyEngine.GROUP_PUBLIC);
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyACLs.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyACLs.java
index e1709ad..f8eba5f 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyACLs.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyACLs.java
@@ -35,6 +35,8 @@ import com.google.gson.JsonParseException;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
+import org.apache.ranger.plugin.policyengine.RangerResourceACLs.DataMaskResult;
+import org.apache.ranger.plugin.policyengine.RangerResourceACLs.RowFilterResult;
import org.apache.ranger.plugin.util.ServicePolicies;
import org.junit.After;
import org.junit.AfterClass;
@@ -45,6 +47,7 @@ import org.junit.Test;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+
public class TestPolicyACLs {
private static Gson gsonBuilder;
@@ -76,6 +79,13 @@ public class TestPolicyACLs {
runTestsFromResourceFiles(tests);
}
+ @Test
+ public void testResourceACLs_dataMask() throws Exception {
+ String[] tests = {"/policyengine/test_aclprovider_mask_filter.json"};
+
+ runTestsFromResourceFiles(tests);
+ }
+
private void runTestsFromResourceFiles(String[] resourceNames) throws Exception {
for(String resourceName : resourceNames) {
InputStream inStream = this.getClass().getResourceAsStream(resourceName);
@@ -102,7 +112,7 @@ public class TestPolicyACLs {
RangerAccessRequestImpl request = new RangerAccessRequestImpl(oneTest.resource, RangerPolicyEngine.ANY_ACCESS, null, null, null);
RangerResourceACLs acls = policyEngine.getResourceACLs(request);
- boolean userACLsMatched = true, groupACLsMatched = true, roleACLsMatched = true;
+ boolean userACLsMatched = true, groupACLsMatched = true, roleACLsMatched = true, rowFiltersMatched = true, dataMaskingMatched = true;
if (MapUtils.isNotEmpty(acls.getUserACLs()) && MapUtils.isNotEmpty(oneTest.userPermissions)) {
@@ -142,6 +152,40 @@ public class TestPolicyACLs {
userACLsMatched = false;
}
+ if (acls.getDataMasks().isEmpty()) {
+ dataMaskingMatched = (oneTest.dataMasks == null || oneTest.dataMasks.isEmpty());
+ } else if (acls.getDataMasks().size() != (oneTest.dataMasks == null ? 0 : oneTest.dataMasks.size())) {
+ dataMaskingMatched = false;
+ } else {
+ for (int i = 0; i < acls.getDataMasks().size(); i++) {
+ DataMaskResult found = acls.getDataMasks().get(i);
+ DataMaskResult expected = oneTest.dataMasks.get(i);
+
+ dataMaskingMatched = found.equals(expected);
+
+ if (!dataMaskingMatched) {
+ break;
+ }
+ }
+ }
+
+ if (acls.getRowFilters().isEmpty()) {
+ rowFiltersMatched = (oneTest.rowFilters == null || oneTest.rowFilters.isEmpty());
+ } else if (acls.getRowFilters().size() != (oneTest.rowFilters == null ? 0 : oneTest.rowFilters.size())) {
+ rowFiltersMatched = false;
+ } else {
+ for (int i = 0; i < acls.getRowFilters().size(); i++) {
+ RowFilterResult found = acls.getRowFilters().get(i);
+ RowFilterResult expected = oneTest.rowFilters.get(i);
+
+ rowFiltersMatched = found.equals(expected);
+
+ if (!rowFiltersMatched) {
+ break;
+ }
+ }
+ }
+
if (MapUtils.isNotEmpty(acls.getGroupACLs()) && MapUtils.isNotEmpty(oneTest.groupPermissions)) {
for (Map.Entry<String, Map<String, RangerResourceACLs.AccessResult>> entry :
acls.getGroupACLs().entrySet()) {
@@ -215,7 +259,7 @@ public class TestPolicyACLs {
} else if (!(MapUtils.isEmpty(acls.getRoleACLs()) && MapUtils.isEmpty(oneTest.rolePermissions))) {
roleACLsMatched = false;
}
- assertTrue("getResourceACLs() failed! " + testCase.name + ":" + oneTest.name, userACLsMatched && groupACLsMatched && roleACLsMatched);
+ assertTrue("getResourceACLs() failed! " + testCase.name + ":" + oneTest.name, userACLsMatched && groupACLsMatched && roleACLsMatched && rowFiltersMatched && dataMaskingMatched);
}
}
}
@@ -230,10 +274,12 @@ public class TestPolicyACLs {
class OneTest {
String name;
- RangerAccessResource resource;
+ RangerAccessResource resource;
Map<String, Map<String, RangerResourceACLs.AccessResult>> userPermissions;
Map<String, Map<String, RangerResourceACLs.AccessResult>> groupPermissions;
Map<String, Map<String, RangerResourceACLs.AccessResult>> rolePermissions;
+ List<RowFilterResult> rowFilters;
+ List<DataMaskResult> dataMasks;
}
}
}
diff --git a/agents-common/src/test/resources/policyengine/ACLResourceTags.json b/agents-common/src/test/resources/policyengine/ACLResourceTags.json
index 711190c..1fa7e89 100644
--- a/agents-common/src/test/resources/policyengine/ACLResourceTags.json
+++ b/agents-common/src/test/resources/policyengine/ACLResourceTags.json
@@ -32,6 +32,12 @@
"attributeDefs": [ { "name": "activation_date", "type": "datetime" } ],
"id": 5,
"guid": "tagdefinition-restricted-final-guid"
+ },
+ "6": {
+ "name": "DATA_QUALITY",
+ "attributeDefs": [ { "name": "score", "type": "float" } ],
+ "id": 5,
+ "guid": "tagdefinition-data_quality-guid"
}
},
"tags": {
@@ -70,6 +76,18 @@
"attributes": { "expiry": "2026/06/15" },
"id": 6,
"guid": "tag-pii-final-6-guid"
+ },
+ "7": {
+ "type": "DATA_QUALITY",
+ "attributes": { "score": "0.8" },
+ "id": 7,
+ "guid": "tag-data_quality-7-guid"
+ },
+ "8": {
+ "type": "RESTRICTED",
+ "validityPeriods": [{"startTime": "2018/01/12 14:32:00", "endTime": "2030/01/12 14:32:00"}],
+ "id": 8,
+ "guid": "tag-restricted-8-guid"
}
},
"serviceResources": [
@@ -188,7 +206,27 @@
},
"id": 12,
"guid": "finance.sales.invoice_id-guid"
- }
+ },
+ {
+ "serviceName": "cl1_hive",
+ "resourceElements": {
+ "database": { "values": [ "employee" ] },
+ "table": { "values": [ "personal" ] },
+ "column": { "values": [ "mrn" ] }
+ },
+ "id": 13,
+ "guid": "employee.personal.mrn-guid"
+ },
+ {
+ "serviceName": "cl1_hive",
+ "resourceElements": {
+ "database": { "values": [ "finance" ] },
+ "table": { "values": [ "forecast" ] },
+ "column": { "values": [ "revenue" ] }
+ },
+ "id": 14,
+ "guid": "finance.forecast.revenue-guid"
+ }
],
"resourceToTagIds": {
"1": [ 1 ],
@@ -201,7 +239,9 @@
"9": [ 5 ],
"10": [ 6 ],
"11": [ 6 ],
- "12": [ 5 ]
+ "12": [ 5 ],
+ "13": [ 7 ],
+ "14": [ 8 ]
}
}
diff --git a/agents-common/src/test/resources/policyengine/test_aclprovider_mask_filter.json b/agents-common/src/test/resources/policyengine/test_aclprovider_mask_filter.json
new file mode 100644
index 0000000..f6ebaf5
--- /dev/null
+++ b/agents-common/src/test/resources/policyengine/test_aclprovider_mask_filter.json
@@ -0,0 +1,341 @@
+{
+ "testCases": [
+ {
+ "name": "Test-ACL-Provider-DataMask",
+
+ "servicePolicies": {
+ "serviceName": "hivedev",
+ "serviceDef": {
+ "name": "hive", "id": 3,
+ "resources": [
+ { "name": "database", "level": 1, "mandatory": true, "lookupSupported": true,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": { "wildCard": true, "ignoreCase": true },
+ "label": "Hive Database", "description": "Hive Database"
+ },
+ {
+ "name": "table", "level": 2, "parent": "database", "mandatory": true, "lookupSupported": true,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": { "wildCard": true, "ignoreCase": true },
+ "label": "Hive Table", "description": "Hive Table"
+ },
+ {
+ "name": "udf", "level": 2, "parent": "database", "mandatory": true, "lookupSupported": true,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": { "wildCard": true, "ignoreCase": true },
+ "label": "Hive UDF", "description": "Hive UDF"
+ },
+ {
+ "name": "column", "level": 3, "parent": "table", "mandatory": true, "lookupSupported": true,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": { "wildCard": true, "ignoreCase": true },
+ "label": "Hive Column", "description": "Hive Column"
+ }
+ ],
+ "accessTypes": [
+ { "name": "select", "label": "Select" },
+ { "name": "update", "label": "Update" },
+ { "name": "create", "label": "Create" },
+ { "name": "drop", "label": "Drop" },
+ { "name": "alter", "label": "Alter" },
+ { "name": "index", "label": "Index" },
+ { "name": "lock", "label": "Lock" },
+ { "name": "all", "label": "All" }
+ ],
+ "policyConditions": [
+ { "itemId": 1, "name": "expression",
+ "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator",
+ "evaluatorOptions": { "engineName": "JavaScript", "ui.isMultiline": "true" },
+ "label": "Enter boolean expression", "description": "Boolean expression"
+ }
+ ],
+ "dataMaskDef": {
+ "maskTypes": [
+ {
+ "itemId": 1,
+ "name": "MASK",
+ "label": "Mask",
+ "description": "Replace lowercase with 'x', uppercase with 'X', digits with '0'"
+ },
+ {
+ "itemId": 2,
+ "name": "SHUFFLE",
+ "label": "Shuffle",
+ "description": "Randomly shuffle the contents"
+ },
+ {
+ "itemId": 10,
+ "name": "NULL",
+ "label": "NULL",
+ "description": "Replace with NULL"
+ }
+
+ ],
+ "accessTypes":[
+ {"name":"select","label":"Select"}
+ ],
+ "resources":[
+ {"name":"database","matcherOptions":{"wildCard":false}},
+ {"name":"table","matcherOptions":{"wildCard":false}},
+ {"name":"column","matcherOptions":{"wildCard":false}}
+ ]
+ },
+ "rowFilterDef": {
+ "accessTypes":[
+ {"name":"select","label":"Select"}
+ ],
+ "resources":[
+ {"name":"database","matcherOptions":{"wildCard":false}},
+ {"name":"table","matcherOptions":{"wildCard":false}}
+ ]
+ }
+ },
+ "policies": [
+ {"id":101,"name":"db=employee, table=personal, column=ssn: mask","isEnabled":true,"isAuditEnabled":true,"policyType":1,
+ "resources":{"database":{"values":["employee"]},"table":{"values":["personal"]},"column":{"values":["ssn"]}},
+ "dataMaskPolicyItems":[
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"MASK"}
+ },
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"SHUFFLE"}
+ }
+ ]
+ },
+ {"id":102,"name":"db=hr, table=employee, column=date_of_birth: mask","isEnabled":true,"isAuditEnabled":true,"policyType":1,
+ "resources":{"database":{"values":["hr"]},"table":{"values":["employee"]},"column":{"values":["date_of_birth"]}},
+ "dataMaskPolicyItems":[
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"MASK"}
+ },
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"SHUFFLE"}
+ },
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user3"],"groups":[],"conditions":[{"type": "expression", "values": ["test"]}],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"LAST_4"}
+ }
+ ]
+ },
+ {"id":103,"name":"db=hr, table=employee, column=project: conditional-mask: validity-schedule","isEnabled":true,"isAuditEnabled":true,"policyType":1,
+ "resources":{"database":{"values":["hr"]},"table":{"values":["employee"]},"column":{"values":["project"]}},
+ "validitySchedules": [{"startTime": "2018/01/12 14:32:00", "endTime": "2020/01/12 14:32:00"}],
+ "dataMaskPolicyItems":[
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"MASK"}
+ },
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"HASH"}
+ }
+ ]
+ },
+ {"id":201,"name":"db=employee, table=personal: row-filter","isEnabled":true,"isAuditEnabled":true,"policyType":2,
+ "resources":{"database":{"values":["employee"]},"table":{"values":["personal"]}},
+ "rowFilterPolicyItems":[
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
+ "rowFilterInfo": {"filterExpr":"location='US'"}
+ },
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false,
+ "rowFilterInfo": {"filterExpr":"location='CA'"}
+ }
+ ]
+ },
+ {"id":202,"name":"db=hr, table=employee: row-filter","isEnabled":true,"isAuditEnabled":true,"policyType":2,
+ "resources":{"database":{"values":["hr"]},"table":{"values":["employee"]}},
+ "rowFilterPolicyItems":[
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
+ "rowFilterInfo": {"filterExpr":"dept='production'"}
+ },
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false,
+ "rowFilterInfo": {"filterExpr":"dept='purchase'"}
+ },
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user3"],"groups":[],"conditions":[{"type": "expression", "values": ["test"]}],"delegateAdmin":false,
+ "rowFilterInfo": {"filterExpr":"location='GR'"}
+ }
+ ]
+ },
+ {"id":203,"name":"db=hr, table=employee2: conditional-row-filter: validity-schedule","isEnabled":true,"isAuditEnabled":true,"policyType":2,
+ "resources":{"database":{"values":["hr"]},"table":{"values":["employee2"]}},
+ "validitySchedules": [{"startTime": "2018/01/12 14:32:00", "endTime": "2020/01/12 14:32:00"}],
+ "rowFilterPolicyItems":[
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
+ "rowFilterInfo": {"filterExpr":"dept='production'"}
+ },
+ {"accesses":[{"type":"select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false,
+ "rowFilterInfo": {"filterExpr":"dept='purchase'"}
+ }
+ ]
+ }
+ ],
+ "tagPolicies": {
+ "serviceName": "tagdev",
+ "serviceDef": {
+ "name": "tag", "id": 100,
+ "resources": [
+ { "itemId": 1, "name": "tag", "type": "string", "level": 1, "parent": "", "mandatory": true,
+ "lookupSupported": true, "recursiveSupported": false, "excludesSupported": false,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": { "wildCard": true, "ignoreCase": false },
+ "label": "TAG", "description": "TAG"
+ }
+ ],
+ "accessTypes": [
+ { "itemId": 1, "name": "hive:select", "label": "hive:select" },
+ { "itemId": 2, "name": "hive:update", "label": "hive:update" },
+ { "itemId": 3, "name": "hive:create", "label": "hive:create" },
+ { "itemId": 4, "name": "hive:drop", "label": "hive:drop" },
+ { "itemId": 5, "name": "hive:alter", "label": "hive:alter" },
+ { "itemId": 6, "name": "hive:index", "label": "hive:index" },
+ { "itemId": 7, "name": "hive:lock", "label": "hive:lock" },
+ { "itemId": 8, "name": "hive:all", "label": "hive:all",
+ "impliedGrants": [ "hive:select", "hive:update", "hive:create", "hive:drop", "hive:alter", "hive:index", "hive:lock" ] }
+ ],
+ "contextEnrichers": [
+ { "itemId": 1, "name": "TagEnricher",
+ "enricher": "org.apache.ranger.plugin.contextenricher.RangerTagEnricher",
+ "enricherOptions": {
+ "tagRetrieverClassName": "org.apache.ranger.plugin.contextenricher.RangerFileBasedTagRetriever",
+ "tagRefresherPollingInterval": 60000,
+ "serviceTagsFileName": "/policyengine/ACLResourceTags.json"
+ }
+ }
+ ],
+ "policyConditions": [
+ { "itemId": 1, "name": "expression",
+ "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator",
+ "evaluatorOptions": { "engineName": "JavaScript", "ui.isMultiline": "true" },
+ "label": "Enter boolean expression", "description": "Boolean expression"
+ },
+ {
+ "itemId": 2, "name": "enforce-expiry",
+ "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptTemplateConditionEvaluator",
+ "evaluatorOptions": { "scriptTemplate": "ctx.isAccessedAfter('expiry_date');" },
+ "label": "Deny access after expiry_date?", "description": "Deny access after expiry_date? (yes/no)"
+ },
+ {
+ "itemId": 3, "name": "ip-range",
+ "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerIpMatcher", "evaluatorOptions": { },
+ "label": "IP Address Range", "description": "IP Address Range"
+ }
+ ]
+ },
+ "policies": [
+ { "id": 101, "name": "RESTRICTED", "isEnabled": true, "isAuditEnabled": true,"policyType":1,
+ "resources": {
+ "tag": { "values": [ "RESTRICTED" ], "isRecursive": false }
+ },
+ "dataMaskPolicyItems":[
+ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"MASK"}
+ },
+ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"HASH"}
+ }
+ ]
+ },
+ { "id": 102, "name": "DATA_QUALITY", "isEnabled": true, "isAuditEnabled": true,"policyType":1,
+ "resources": {
+ "tag": { "values": [ "DATA_QUALITY" ], "isRecursive": false }
+ },
+ "dataMaskPolicyItems":[
+ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"MASK"}, "conditions": [{ "type": "expression", "values": [ "tag.score > 0.6" ] }]
+ },
+ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"HASH"}, "conditions": [{ "type": "expression", "values": [ "tag.score > 0.6" ] }]
+ }
+ ]
+ },
+ { "id": 103, "name": "RESTRICTED-FINAL: conditional mask - validity schedule", "isEnabled": true, "isAuditEnabled": true,"policyType":1,
+ "resources": {
+ "tag": { "values": [ "RESTRICTED-FINAL" ], "isRecursive": false }
+ },
+ "validitySchedules": [{"startTime": "2018/01/12 14:32:00", "endTime": "2020/01/12 14:32:00"}],
+ "dataMaskPolicyItems":[
+ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"MASK"}
+ },
+ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false,
+ "dataMaskInfo": {"dataMaskType":"HASH"}
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "tests": [
+ {"name":"mask: employee.personal.ssn",
+ "resource":{"elements":{"database":"employee", "table":"personal", "column":"ssn"}},
+ "dataMasks": [
+ {"users":["user1"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"MASK"}},
+ {"users":["user2"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"SHUFFLE"}}
+ ]
+ },
+ {"name":"mask: hr.employee.date_of_birth",
+ "resource":{"elements":{"database":"hr", "table":"employee", "column":"date_of_birth"}},
+ "dataMasks": [
+ {"users":["user1"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"MASK"}},
+ {"users":["user2"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"SHUFFLE"}},
+ {"users":["user3"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"LAST_4"}, "isConditional": true}
+ ]
+ },
+ {"name":"mask: hr.employee.project - conditional: validity-schedule",
+ "resource":{"elements":{"database":"hr", "table":"employee", "column":"project"}},
+ "dataMasks": [
+ {"users":["user1"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"MASK"}, "isConditional": true},
+ {"users":["user2"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"HASH"}, "isConditional": true}
+ ]
+ },
+ {"name":"mask: employee.personal.city - tag-based: RESTRICTED",
+ "resource":{"elements":{"database":"employee", "table":"personal", "column":"city"}},
+ "dataMasks": [
+ {"users":["user1"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"MASK"}},
+ {"users":["user2"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"HASH"}}
+ ]
+ },
+ {"name":"mask: employee.personal.mrn - tag-based: DATA_QUALITY; conditional",
+ "resource":{"elements":{"database":"employee", "table":"personal", "column":"mrn"}},
+ "dataMasks": [
+ {"users":["user1"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"MASK"}, "isConditional": true},
+ {"users":["user2"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"HASH"}, "isConditional": true}
+ ]
+ },
+ {"name":"mask: employee.personal.address - tag-based: RESTRICTED-FINAL; conditional: validity-schedule",
+ "resource":{"elements":{"database":"employee", "table":"personal", "column":"address"}},
+ "dataMasks": [
+ {"users":["user1"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"MASK"}, "isConditional": true},
+ {"users":["user2"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"HASH"}, "isConditional": true}
+ ]
+ },
+ {"name":"mask: finance.forecast.revenue - tag-based: RESTRICTED; conditional: tag-validity-period",
+ "resource":{"elements":{"database":"finance", "table":"forecast", "column":"revenue"}},
+ "dataMasks": [
+ {"users":["user1"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"MASK"}, "isConditional": true},
+ {"users":["user2"], "groups":[], "roles":[], "accessTypes":["select"], "maskInfo":{"dataMaskType":"HASH"}, "isConditional": true}
+ ]
+ },
+ {"name":"row-filter: employee.personal",
+ "resource":{"elements":{"database":"employee", "table":"personal"}},
+ "rowFilters":[
+ {"users":["user1"], "groups":[], "roles":[], "accessTypes":["select"], "filterInfo":{"filterExpr":"location='US'"}},
+ {"users":["user2"], "groups":[], "roles":[], "accessTypes":["select"], "filterInfo":{"filterExpr":"location='CA'"}}
+ ]
+ },
+ {"name":"row-filter: hr.employee",
+ "resource":{"elements":{"database":"hr", "table":"employee"}},
+ "rowFilters":[
+ {"users":["user1"], "groups":[], "roles":[], "accessTypes":["select"], "filterInfo":{"filterExpr":"dept='production'"}},
+ {"users":["user2"], "groups":[], "roles":[], "accessTypes":["select"], "filterInfo":{"filterExpr":"dept='purchase'"}},
+ {"users":["user3"], "groups":[], "roles":[], "accessTypes":["select"], "filterInfo":{"filterExpr":"location='GR'"}, "isConditional": true}
+ ]
+ },
+ {"name":"row-filter: hr.employee2 - conditional: validity-schedule",
+ "resource":{"elements":{"database":"hr", "table":"employee2"}},
+ "rowFilters":[
+ {"users":["user1"], "groups":[], "roles":[], "accessTypes":["select"], "filterInfo":{"filterExpr":"dept='production'"}, "isConditional": true},
+ {"users":["user2"], "groups":[], "roles":[], "accessTypes":["select"], "filterInfo":{"filterExpr":"dept='purchase'"}, "isConditional": true}
+ ]
+ }
+ ]
+ }
+ ]
+}