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}
+          ]
+        }
+      ]
+    }
+  ]
+}