This is an automated email from the ASF dual-hosted git repository. madhan pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ranger.git
commit b2b5c5bc7f587e70f82b956526a5e6b71f3f6a94 Author: Madhan Neethiraj <mad...@apache.org> AuthorDate: Thu Oct 12 08:58:51 2023 -0700 RANGER-4472: updated getResourceACLs() handling of tags associated with the resource and its descendent --- .../model/validation/RangerServiceDefHelper.java | 54 +++++- .../ranger/plugin/policyengine/PolicyEngine.java | 19 ++- .../policyengine/RangerPolicyEngineImpl.java | 48 +++++- .../RangerDefaultPolicyEvaluator.java | 5 + .../policyevaluator/RangerPolicyEvaluator.java | 2 + .../ranger/plugin/policyengine/TestPolicyACLs.java | 7 + .../policyengine/resource_hierarchy_tags.json | 85 ++++++++++ .../test_aclprovider_resource_hierarchy_tags.json | 181 +++++++++++++++++++++ 8 files changed, 394 insertions(+), 7 deletions(-) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java index c1388abc2..6cc93ad6d 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java @@ -188,6 +188,10 @@ public class RangerServiceDefHelper { return _delegate.getResourceHierarchies(policyType); } + public Set<Set<String>> getResourceHierarchyKeys(Integer policyType) { + return _delegate.getResourceHierarchyKeys(policyType); + } + public Set<List<RangerResourceDef>> filterHierarchies_containsOnlyMandatoryResources(Integer policyType) { Set<List<RangerResourceDef>> hierarchies = getResourceHierarchies(policyType); Set<List<RangerResourceDef>> result = new HashSet<List<RangerResourceDef>>(hierarchies.size()); @@ -200,6 +204,32 @@ public class RangerServiceDefHelper { return result; } + public boolean isValidHierarchy(Integer policyType, Collection<String> keys, boolean requireExactMatch) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> isValidHierarchy(policyType=" + policyType + ", keys=" + StringUtils.join(keys, ", ") + ", requireExactMatch=" + requireExactMatch + ")"); + } + + boolean ret = false; + + for (Set<String> hierarchyKeys : getResourceHierarchyKeys(policyType)) { + if (requireExactMatch) { + ret = hierarchyKeys.equals(keys); + } else { + ret = hierarchyKeys.containsAll(keys); + } + + if (ret) { + break; + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== isValidHierarchy(policyType=" + policyType + ", keys=" + StringUtils.join(keys, ", ") + ", requireExactMatch=" + requireExactMatch + "): ret=" + ret); + } + + return ret; + } + public Set<List<RangerResourceDef>> getResourceHierarchies(Integer policyType, Collection<String> keys) { if (LOG.isDebugEnabled()) { LOG.debug("==> getResourceHierarchies(policyType=" + policyType + ", keys=" + StringUtils.join(keys, ",") + ")"); @@ -265,7 +295,7 @@ public class RangerServiceDefHelper { * @param hierarchy * @return */ - public Set<String> getAllResourceNames(List<RangerResourceDef> hierarchy) { + public static Set<String> getAllResourceNames(List<RangerResourceDef> hierarchy) { Set<String> result = new HashSet<String>(hierarchy.size()); for (RangerResourceDef resourceDef : hierarchy) { result.add(resourceDef.getName()); @@ -322,6 +352,7 @@ public class RangerServiceDefHelper { static class Delegate { final RangerServiceDef _serviceDef; final Map<Integer, Set<List<RangerResourceDef>>> _hierarchies = new HashMap<>(); + final Map<Integer, Set<Set<String>>> _hierarchyKeys = new HashMap<>(); final Map<Integer, Map<String, RangerResourceDef>> _wildcardEnabledResourceDefs = new HashMap<>(); final Date _serviceDefFreshnessDate; final String _serviceName; @@ -347,14 +378,23 @@ public class RangerServiceDefHelper { if(graph != null) { Map<String, RangerResourceDef> resourceDefMap = getResourcesAsMap(resources); if (isValid(graph, resourceDefMap)) { - Set<List<RangerResourceDef>> hierarchies = getHierarchies(graph, resourceDefMap); + Set<List<RangerResourceDef>> hierarchies = getHierarchies(graph, resourceDefMap); + Set<Set<String>> hierachyKeys = new HashSet<>(hierarchies.size()); + + for (List<RangerResourceDef> hierarchy : hierarchies) { + hierachyKeys.add(Collections.unmodifiableSet(getAllResourceNames(hierarchy))); + } + _hierarchies.put(policyType, Collections.unmodifiableSet(hierarchies)); + _hierarchyKeys.put(policyType, Collections.unmodifiableSet(hierachyKeys)); } else { isValid = false; _hierarchies.put(policyType, EMPTY_RESOURCE_HIERARCHY); + _hierarchyKeys.put(policyType, Collections.emptySet()); } } else { _hierarchies.put(policyType, EMPTY_RESOURCE_HIERARCHY); + _hierarchyKeys.put(policyType, Collections.emptySet()); } } @@ -402,6 +442,16 @@ public class RangerServiceDefHelper { return ret; } + public Set<Set<String>> getResourceHierarchyKeys(Integer policyType) { + if (policyType == null || policyType == RangerPolicy.POLICY_TYPE_AUDIT) { + policyType = RangerPolicy.POLICY_TYPE_ACCESS; + } + + Set<Set<String>> ret = _hierarchyKeys.get(policyType); + + return ret != null ? ret : Collections.emptySet(); + } + public String getServiceName() { return _serviceName; } diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java index 04f010a03..3373dbae9 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java @@ -48,6 +48,7 @@ import org.apache.ranger.plugin.util.RangerPolicyDeltaUtil; import org.apache.ranger.plugin.util.RangerResourceEvaluatorsRetriever; import org.apache.ranger.plugin.util.RangerReadWriteLock; import org.apache.ranger.plugin.util.RangerRoles; +import org.apache.ranger.plugin.util.ServiceDefUtil; import org.apache.ranger.plugin.util.ServicePolicies; import org.apache.ranger.plugin.util.StringTokenReplacer; import org.slf4j.Logger; @@ -59,6 +60,7 @@ public class PolicyEngine { private static final Logger PERF_POLICYENGINE_INIT_LOG = RangerPerfTracer.getPerfLogger("policyengine.init"); private static final Logger PERF_POLICYENGINE_REBALANCE_LOG = RangerPerfTracer.getPerfLogger("policyengine.rebalance"); + private final RangerServiceDefHelper serviceDefHelper; private final RangerPolicyRepository policyRepository; private final RangerPolicyRepository tagPolicyRepository; private final List<RangerContextEnricher> allContextEnrichers; @@ -119,6 +121,8 @@ public class PolicyEngine { return policyRepository.getPolicyVersion(); } + public RangerServiceDefHelper getServiceDefHelper() { return serviceDefHelper; } + public RangerPolicyRepository getPolicyRepository() { return policyRepository; } @@ -229,6 +233,7 @@ public class PolicyEngine { } policyRepository = new RangerPolicyRepository(servicePolicies, this.pluginContext); + serviceDefHelper = new RangerServiceDefHelper(policyRepository.getServiceDef(), false); ServicePolicies.TagPolicies tagPolicies = servicePolicies.getTagPolicies(); @@ -482,9 +487,16 @@ public class PolicyEngine { } synchronized static private void buildImpliedAccessGrants(ServicePolicies servicePolicies) { - buildImpliedAccessGrants(servicePolicies.getServiceDef()); - if (servicePolicies.getTagPolicies() != null) { - buildImpliedAccessGrants(servicePolicies.getTagPolicies().getServiceDef()); + RangerServiceDef serviceDef = servicePolicies.getServiceDef(); + + if (serviceDef != null) { + buildImpliedAccessGrants(ServiceDefUtil.normalize(serviceDef)); + + RangerServiceDef tagServiceDef = servicePolicies.getTagPolicies() != null ? servicePolicies.getTagPolicies().getServiceDef() : null; + + if (tagServiceDef != null) { + buildImpliedAccessGrants(ServiceDefUtil.normalizeAccessTypeDefs(ServiceDefUtil.normalize(tagServiceDef), serviceDef.getName())); + } } } @@ -567,6 +579,7 @@ public class PolicyEngine { private PolicyEngine(final PolicyEngine other, ServicePolicies servicePolicies) { this.useForwardedIPAddress = other.useForwardedIPAddress; this.trustedProxyAddresses = other.trustedProxyAddresses; + this.serviceDefHelper = other.serviceDefHelper; this.pluginContext = other.pluginContext; this.lock = other.lock; 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 8ba0b1a7f..20400fdfa 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 @@ -282,6 +282,17 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { for (int policyType : policyTypes) { + // if resource isn't applicable for the policyType, skip evaluating policies and gathering ACLs + // for example, following resources are not applicable for listed policy-types + // - database: masking/row-filter policies + // - table: masking policies + // - column: row-filter policies + boolean requireExactMatch = (policyType == RangerPolicy.POLICY_TYPE_DATAMASK) || (policyType == RangerPolicy.POLICY_TYPE_ROWFILTER); + + if (!policyEngine.getServiceDefHelper().isValidHierarchy(policyType, request.getResource().getKeys(), requireExactMatch)) { + continue; + } + List<RangerPolicyEvaluator> allEvaluators = new ArrayList<>(); Map<Long, MatchType> tagMatchTypeMap = new HashMap<>(); Set<Long> policyIdForTemporalTags = new HashSet<>(); @@ -312,7 +323,7 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { MatchType matchType = tagMatchTypeMap.get(evaluator.getPolicyId()); boolean isMatched = false; - boolean isConditionalMatch = false; + boolean isConditionalMatch = evaluator.getPolicyConditionsCount() > 0; if (matchType == null) { for (RangerPolicyResourceEvaluator resourceEvaluator : evaluator.getResourceEvaluators()) { @@ -1007,7 +1018,8 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { RangerTagForEval tag = tagEvaluator.getTag(); allEvaluators.add(evaluator); - tagMatchTypeMap.put(evaluator.getPolicyId(), tag.getMatchType()); + + updateMatchTypeForTagEvaluator(tagEvaluator, tagMatchTypeMap); if (CollectionUtils.isNotEmpty(tag.getValidityPeriods())) { policyIdForTemporalTags.add(evaluator.getPolicyId()); @@ -1021,6 +1033,38 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { } } + // Multiple tags can be mapped to a tag-based policy. In such cases, use the match-type of the tag having the highest precedence + // Consider following tags: + // table table1 has tag SENSITIVE(level=normal) + // column table1.col1 has tag SENSITIVE(level=high) + // + // Following 2 tags will be matched for table1: + // SENSITIVE(level=normal) with MatchType.SELF + // SENSITIVE(level=high) with MatchType.DESCENDANT + // + // Following 2 tags will be matched for table1.col1: + // SENSITIVE(level=high) with MatchType.SELF + // SENSITIVE(level=normal) with MatchType.SELF_AND_ALL_DESCENDANTS + // + // In these cases, matchType SELF should be used for policy evaluation + // + private void updateMatchTypeForTagEvaluator(PolicyEvaluatorForTag tag, Map<Long, MatchType> tagMatchTypeMap) { + Long evaluatorId = tag.getEvaluator().getPolicyId(); + MatchType existing = tagMatchTypeMap.get(evaluatorId); + + if (existing != MatchType.SELF) { + MatchType matchType = tag.getTag().getMatchType(); + + if (existing == null || existing == MatchType.NONE || matchType == MatchType.SELF || matchType == MatchType.SELF_AND_ALL_DESCENDANTS) { + tagMatchTypeMap.put(evaluatorId, matchType); + } else if (matchType == MatchType.ANCESTOR) { + if (existing == MatchType.DESCENDANT) { + tagMatchTypeMap.put(evaluatorId, MatchType.SELF_AND_ALL_DESCENDANTS); + } + } + } + } + private void getResourceAccessInfoForZone(RangerAccessRequest request, RangerResourceAccessInfo ret, String zoneName) { final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForZone(zoneName); 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 bf7ebe86a..8e908f6a9 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 @@ -90,6 +90,11 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator boolean isUseAclSummaryForEvaluation() { return useAclSummaryForEvaluation; } + @Override + public int getPolicyConditionsCount() { + return conditionEvaluators.size(); + } + @Override public int getCustomConditionsCount() { return customConditionsCount; 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 dcaae9ff1..0d4886c57 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 @@ -92,6 +92,8 @@ public interface RangerPolicyEvaluator { int getEvalOrder(); + int getPolicyConditionsCount(); + int getCustomConditionsCount(); int getValidityScheduleEvaluatorsCount(); 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 196755c6e..9a69efcba 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 @@ -94,6 +94,13 @@ public class TestPolicyACLs { runTestsFromResourceFiles(tests); } + @Test + public void testResourceACLs_resource_hierarchy_tags() throws Exception { + String[] tests = {"/policyengine/test_aclprovider_resource_hierarchy_tags.json"}; + + runTestsFromResourceFiles(tests); + } + private void runTestsFromResourceFiles(String[] resourceNames) throws Exception { for(String resourceName : resourceNames) { InputStream inStream = this.getClass().getResourceAsStream(resourceName); diff --git a/agents-common/src/test/resources/policyengine/resource_hierarchy_tags.json b/agents-common/src/test/resources/policyengine/resource_hierarchy_tags.json new file mode 100644 index 000000000..33c7204af --- /dev/null +++ b/agents-common/src/test/resources/policyengine/resource_hierarchy_tags.json @@ -0,0 +1,85 @@ +{ + "op": "add_or_update", + "tagModel": "resource_private", + "serviceName": "cl1_hive", + "tagDefinitions": { + "1": { + "id": 1, + "guid": "tag-def-1", + "name": "SENSITIVE", + "attributeDefs": [ { "name": "level", "type": "string" } ] + } + }, + "tags": { + "1": { + "id": 1, + "guid": "tag-1", + "type": "SENSITIVE", + "attributes": { "level": "normal" } + }, + "2": { + "id": 2, + "guid": "tag-2", + "type": "SENSITIVE", + "attributes": { "level": "high" } + }, + "3": { + "id": 3, + "guid": "tag-3", + "type": "SENSITIVE", + "attributes": { "level": "top" } + }, + "4": { + "id": 4, + "guid": "tag-4", + "type": "SENSITIVE", + "attributes": { "level": "top" } + }, + "5": { + "id": 5, + "guid": "tag-5", + "type": "SENSITIVE", + "attributes": { "level": "top" } + } + }, + "serviceResources": [ + { + "id": 1, + "guid": "resource-1", + "serviceName": "cl1_hive", + "resourceElements": { "database": { "values": [ "db1" ] }, "table": { "values": [ "tbl1" ] } } + }, + { + "id": 2, + "guid": "resource-2", + "serviceName": "cl1_hive", + "resourceElements": { "database": { "values": [ "db1" ] }, "table": { "values": [ "tbl1" ] }, "column": { "values": [ "SSN" ] } } + }, + { + "id": 3, + "guid": "resource-3", + "serviceName": "cl1_hive", + "resourceElements": { "database": { "values": [ "db1" ] }, "table": { "values": [ "tbl1" ] }, "column": { "values": [ "Age" ] } } + }, + { + "id": 4, + "guid": "resource-4", + "serviceName": "cl1_hive", + "resourceElements": { "database": { "values": [ "db1" ] }, "table": { "values": [ "tbl1" ] }, "column": { "values": [ "Name" ] } } + }, + { + "id": 5, + "guid": "resource-5", + "serviceName": "cl1_hive", + "resourceElements": { "database": { "values": [ "db2" ] }, "table": { "values": [ "*" ] }, "column": { "values": [ "*" ] } } + } + ], + "resourceToTagIds": { + "1": [ 1 ], + "2": [ 2 ], + "3": [ 3 ], + "4": [ 4 ], + "5": [ 5 ] + } +} + diff --git a/agents-common/src/test/resources/policyengine/test_aclprovider_resource_hierarchy_tags.json b/agents-common/src/test/resources/policyengine/test_aclprovider_resource_hierarchy_tags.json new file mode 100644 index 000000000..27152ba42 --- /dev/null +++ b/agents-common/src/test/resources/policyengine/test_aclprovider_resource_hierarchy_tags.json @@ -0,0 +1,181 @@ +{ + "testCases": [ + { + "name": "Test multiple tag instances for resource hierarchy", + + "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": "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": 3, "name": "MASK_HASH", "label": "Hash", "description": "Hash value of the contents" }, + { "itemId": 4, "name": "MASK_NONE", "label": "No masking", "description": "Unmasked value of 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": [ + ], + "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" ] } + ], + "dataMaskDef": { + "resources":[ + { "name": "tag" } + ] + }, + "contextEnrichers": [ + { "itemId": 1, "name": "TagEnricher", "enricher": "org.apache.ranger.plugin.contextenricher.RangerTagEnricher", "enricherOptions": { "tagRetrieverClassName": "org.apache.ranger.plugin.contextenricher.RangerFileBasedTagRetriever", "tagRefresherPollingInterval": 60000, "serviceTagsFileName": "/policyengine/resource_hierarchy_tags.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": "SENSITIVE", "isEnabled": true, "isAuditEnabled": true, "policyType": 0, + "resources": { "tag": { "values": [ "SENSITIVE" ], "isRecursive": false } }, + "policyItems": [ + {"accesses": [{"type": "hive:select", "isAllowed": true}], "users": [ "test-user"] } + ] + }, + { "id": 102, "name": "mask: SENSITIVE(level=normal)", "isEnabled": true, "isAuditEnabled": true, "policyType": 1, + "resources": { "tag": { "values": [ "SENSITIVE" ], "isRecursive": false } }, + "conditions": [ { "type": "expression", "values": [ "TAG.level == 'normal'" ] } ], + "dataMaskPolicyItems": [ + { "accesses": [ { "type": "hive:select", "isAllowed": true } ], "users": [ "test-user"], "dataMaskInfo": { "dataMaskType": "SHUFFLE"}} + ] + }, + { "id": 103, "name": "mask: SENSITIVE(level=high)", "isEnabled": true, "isAuditEnabled": true, "policyType": 1, + "resources": { "tag": { "values": [ "SENSITIVE" ], "isRecursive": false } }, + "conditions": [ { "type": "expression", "values": [ "TAG.level == 'high'" ] } ], + "dataMaskPolicyItems": [ + { "accesses": [ { "type": "hive:select", "isAllowed": true } ], "users": [ "test-user"], "dataMaskInfo": { "dataMaskType": "MASK"}} + ] + }, + { "id": 104, "name": "mask: SENSITIVE(level=top)", "isEnabled": true, "isAuditEnabled": true, "policyType": 1, + "resources": { "tag": { "values": [ "SENSITIVE" ], "isRecursive": false } }, + "conditions": [ { "type": "expression", "values": [ "TAG.level == 'top'" ] } ], + "dataMaskPolicyItems": [ + { "accesses": [ { "type": "hive:select", "isAllowed": true } ], "users": [ "test-user"], "dataMaskInfo": { "dataMaskType": "MASK_HASH"}} + ] + } + ] + } + }, + "tests": [ + { "name": "table: db1.tbl1", + "resource": { "elements": { "database": "db1", "table": "tbl1" } }, + "userPermissions": { "test-user": { "select": { "result": 1, "isFinal": true } } } + }, + { "name": "column: db1.tbl1.SSN", + "resource": { "elements": { "database": "db1", "table": "tbl1", "column": "SSN" } }, + "userPermissions": { "test-user": { "select": { "result": 1, "isFinal": true } } }, + "dataMasks": [ + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "SHUFFLE" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "SHUFFLE" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true } + ] + }, + { "name": "column: db1.tbl1.Age", + "resource": { "elements": { "database": "db1", "table": "tbl1", "column": "Age" } }, + "userPermissions": { "test-user": { "select": { "result": 1, "isFinal": true } } }, + "dataMasks": [ + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "SHUFFLE" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "SHUFFLE" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true } + ] + }, + { "name": "column: db1.tbl1.Name", + "resource": { "elements": { "database": "db1", "table": "tbl1", "column": "Name" } }, + "userPermissions": { "test-user": { "select": { "result": 1, "isFinal": true } } }, + "dataMasks": [ + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "SHUFFLE" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "SHUFFLE" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true } + ] + }, + { "name": "database: db2", + "resource": { "elements": { "database": "db2" } }, + "userPermissions": { "test-user": { "select": { "result": 1, "isFinal": true } } } + }, + { "name": "table: db2.tbl1", + "resource": { "elements": { "database": "db2", "table": "tbl1" } }, + "userPermissions": { "test-user": { "select": { "result": 1, "isFinal": true } } } + }, + { "name": "column: db2.tbl1.Name", + "resource": { "elements": { "database": "db2", "table": "tbl1", "column": "Name" } }, + "userPermissions": { "test-user": { "select": { "result": 1, "isFinal": true } } }, + "dataMasks": [ + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "SHUFFLE" }, "isConditional": true }, + {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true } + ] + } + ] + } + ] +}