From 1725cdbb5435586452b163d6e762b6a30ba7b9d3 Mon Sep 17 00:00:00 2001 From: Madhan Neethiraj Date: Fri, 13 Oct 2023 17:17:27 -0700 Subject: [PATCH] RANGER-4472: getResourceACLs() handling of tags associated with resource and its desencent - #2 --- .../contextenricher/RangerTagEnricher.java | 2 +- .../policyengine/PolicyEvaluatorForTag.java | 16 ++ .../policyengine/RangerPolicyEngineImpl.java | 44 +--- .../policyengine/RangerPolicyRepository.java | 11 +- .../RangerPolicyResourceMatcher.java | 45 ++++ .../contextenricher/TestTagEnricher.java | 23 ++ .../plugin/policyengine/TestPolicyEngine.java | 7 + .../policyengine/resource_hierarchy_tags.json | 91 ++----- ...t_aclprovider_resource_hierarchy_tags.json | 76 ++++-- ..._policyengine_resource_hierarchy_tags.json | 239 ++++++++++++++++++ 10 files changed, 427 insertions(+), 127 deletions(-) create mode 100644 agents-common/src/test/resources/policyengine/test_policyengine_resource_hierarchy_tags.json diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java index b5428cfdf3..c5f5fc3be6 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java @@ -718,7 +718,7 @@ private Set findMatchingTags(final RangerAccessRequest request } else if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) { isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE; } else { - isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.ANCESTOR; + isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.SELF_AND_ALL_DESCENDANTS || matchType == RangerPolicyResourceMatcher.MatchType.ANCESTOR; } if (isMatched) { diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEvaluatorForTag.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEvaluatorForTag.java index 1d961a197a..f1646c96f1 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEvaluatorForTag.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEvaluatorForTag.java @@ -21,13 +21,16 @@ import org.apache.ranger.plugin.contextenricher.RangerTagForEval; import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator; +import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher; import java.io.Serializable; import java.util.Comparator; + public class PolicyEvaluatorForTag { public static final Comparator EVAL_ORDER_COMPARATOR = new PolicyEvalOrderComparator(); public static final Comparator NAME_COMPARATOR = new PolicyNameComparator(); + public static final Comparator MATCH_TYPE_COMPARATOR = new MatchTypeComparator(); private final RangerPolicyEvaluator evaluator; private final RangerTagForEval tag; @@ -58,4 +61,17 @@ public int compare(PolicyEvaluatorForTag me, PolicyEvaluatorForTag other) { return RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR.compare(me.getEvaluator(), other.getEvaluator()); } } + + static class MatchTypeComparator implements Comparator, Serializable { + @Override + public int compare(PolicyEvaluatorForTag me, PolicyEvaluatorForTag other) { + int ret = RangerPolicyResourceMatcher.MATCH_TYPE_COMPARATOR.compare(me.getTag().getMatchType(), other.getTag().getMatchType()); + + if (ret == 0) { + ret = RangerPolicyEvaluator.NAME_COMPARATOR.compare(me.getEvaluator(), other.getEvaluator()); + } + + return ret; + } + } } 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 20400fdfa7..fd78fd8e06 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 @@ -59,6 +59,7 @@ import java.util.Map; import java.util.Set; +import static org.apache.ranger.plugin.policyengine.PolicyEvaluatorForTag.MATCH_TYPE_COMPARATOR; import static org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator.ACCESS_CONDITIONAL; public class RangerPolicyEngineImpl implements RangerPolicyEngine { @@ -333,7 +334,7 @@ public RangerResourceACLs getResourceACLs(RangerAccessRequest request, Integer r isMatched = isMatch(matchType, request.getResourceMatchingScope()); if (isMatched) { - isConditionalMatch = false; + isConditionalMatch = evaluator.getPolicyConditionsCount() > 0; break; } else if (matcher.getNeedsDynamicEval() && !isConditionalMatch) { @@ -990,6 +991,7 @@ private void getResourceACLEvaluatorsForZone(RangerAccessRequest request, String List tagPolicyEvaluators = policyEngine.getTagPolicyRepository() == null ? null : policyEngine.getTagPolicyRepository().getLikelyMatchPolicyEvaluators(request, tags, policyType, null); if (CollectionUtils.isNotEmpty(tagPolicyEvaluators)) { + tagPolicyEvaluators.sort(MATCH_TYPE_COMPARATOR); final boolean useTagPoliciesFromDefaultZone = !policyEngine.isResourceZoneAssociatedWithTagService(zoneName); @@ -1017,9 +1019,11 @@ private void getResourceACLEvaluatorsForZone(RangerAccessRequest request, String RangerTagForEval tag = tagEvaluator.getTag(); - allEvaluators.add(evaluator); - - updateMatchTypeForTagEvaluator(tagEvaluator, tagMatchTypeMap); + // avoid an evaluator making into the list multiple times when the same tag is associated with the resource multiple times + // highest precedence matchType will be recorded in tagMatchTypeMap, since tagPolicyEvaluators is sorted by matchType + if (tagMatchTypeMap.putIfAbsent(evaluator.getPolicyId(), tag.getMatchType()) == null) { + allEvaluators.add(evaluator); + } if (CollectionUtils.isNotEmpty(tag.getValidityPeriods())) { policyIdForTemporalTags.add(evaluator.getPolicyId()); @@ -1033,38 +1037,6 @@ private void getResourceACLEvaluatorsForZone(RangerAccessRequest request, String } } - // 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 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/policyengine/RangerPolicyRepository.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java index 68f4b5dfdc..e02d3a32d5 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java @@ -632,7 +632,7 @@ List getLikelyMatchPolicyEvaluators(RangerAccessRequest r Collections.sort(ret, PolicyEvaluatorForTag.EVAL_ORDER_COMPARATOR); break; case RangerPolicy.POLICY_TYPE_DATAMASK: - Collections.sort(ret, PolicyEvaluatorForTag.NAME_COMPARATOR); + Collections.sort(ret, PolicyEvaluatorForTag.MATCH_TYPE_COMPARATOR); break; case RangerPolicy.POLICY_TYPE_ROWFILTER: Collections.sort(ret, PolicyEvaluatorForTag.NAME_COMPARATOR); @@ -931,14 +931,13 @@ private void init(RangerPolicyEngineOptions options) { } } LOG.info("This policy engine contains " + (policyEvaluators.size()+dataMaskPolicyEvaluators.size()+rowFilterPolicyEvaluators.size()) + " policy evaluators"); - RangerPolicyEvaluator.PolicyEvalOrderComparator comparator = new RangerPolicyEvaluator.PolicyEvalOrderComparator(); - Collections.sort(policyEvaluators, comparator); + Collections.sort(policyEvaluators, RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR); this.policyEvaluators = policyEvaluators; - Collections.sort(dataMaskPolicyEvaluators, comparator); + Collections.sort(dataMaskPolicyEvaluators, RangerPolicyEvaluator.NAME_COMPARATOR); this.dataMaskPolicyEvaluators = dataMaskPolicyEvaluators; - Collections.sort(rowFilterPolicyEvaluators, comparator); + Collections.sort(rowFilterPolicyEvaluators, RangerPolicyEvaluator.NAME_COMPARATOR); this.rowFilterPolicyEvaluators = rowFilterPolicyEvaluators; this.policyEvaluatorsMap = createPolicyEvaluatorsMap(); @@ -1175,7 +1174,7 @@ private List getReorderedPolicyEvaluators(List(evaluators); - Collections.sort(ret, new RangerPolicyEvaluator.PolicyEvalOrderComparator()); + Collections.sort(ret, RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR); } return ret; diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java index 052e2df78f..3ad870b1d5 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java @@ -19,6 +19,7 @@ package org.apache.ranger.plugin.policyresourcematcher; +import java.util.Comparator; import java.util.Map; import org.apache.ranger.plugin.model.RangerPolicy; @@ -27,12 +28,15 @@ import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper; import org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope; import org.apache.ranger.plugin.policyengine.RangerAccessResource; +import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator; import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher; public interface RangerPolicyResourceMatcher { enum MatchScope { SELF, SELF_OR_DESCENDANT, SELF_OR_ANCESTOR, DESCENDANT, ANCESTOR, ANY, SELF_AND_ALL_DESCENDANTS} enum MatchType { NONE, SELF, DESCENDANT, ANCESTOR, SELF_AND_ALL_DESCENDANTS} + Comparator MATCH_TYPE_COMPARATOR = new MatchTypeComparator(); + void init(); void setServiceDef(RangerServiceDef serviceDef); @@ -76,4 +80,45 @@ enum MatchType { NONE, SELF, DESCENDANT, ANCESTOR, SELF_AND_ALL_DESCENDANTS} boolean getNeedsDynamicEval(); StringBuilder toString(StringBuilder sb); + + // order: SELF, SELF_AND_ALL_DESCENDANTS, ANCESTOR, DESCENDANT, NONE + class MatchTypeComparator implements Comparator { + @Override + public int compare(MatchType o1, MatchType o2) { + final int ret; + + if (o1 == o2) { + ret = 0; + } else if (o1 == null) { + return 1; + } else if (o2 == null) { + return -1; + } else { + switch (o1) { + case SELF: + ret = -1; + break; + + case SELF_AND_ALL_DESCENDANTS: + ret = o2 == MatchType.SELF ? 1 : -1; + break; + + case ANCESTOR: + ret = (o2 == MatchType.SELF || o2 == MatchType.SELF_AND_ALL_DESCENDANTS) ? 1 : -1; + break; + + case DESCENDANT: + ret = o2 == MatchType.NONE ? -1 : 1; + break; + + case NONE: + default: + ret = 1; + break; + } + } + + return ret; + } + } } diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/contextenricher/TestTagEnricher.java b/agents-common/src/test/java/org/apache/ranger/plugin/contextenricher/TestTagEnricher.java index 799787c4e3..86985177ac 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/contextenricher/TestTagEnricher.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/contextenricher/TestTagEnricher.java @@ -31,6 +31,8 @@ import org.apache.ranger.plugin.model.RangerTag; import org.apache.ranger.plugin.model.RangerTagDef; import org.apache.ranger.plugin.policyengine.*; +import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher.MatchType; import org.apache.ranger.plugin.util.RangerAccessRequestUtil; import org.apache.ranger.plugin.util.ServiceTags; import org.junit.AfterClass; @@ -64,6 +66,27 @@ public static void setUpBeforeClass() throws Exception { public static void tearDownAfterClass() throws Exception { } + @Test + public void testRangerTagsForEvalSort() { + List matchTypes = new ArrayList<>(); + + matchTypes.add(null); + matchTypes.add(MatchType.NONE); + matchTypes.add(MatchType.DESCENDANT); + matchTypes.add(MatchType.ANCESTOR); + matchTypes.add(MatchType.SELF_AND_ALL_DESCENDANTS); + matchTypes.add(MatchType.SELF); + + matchTypes.sort(RangerPolicyResourceMatcher.MATCH_TYPE_COMPARATOR); + + assertEquals(matchTypes.get(0), MatchType.SELF); + assertEquals(matchTypes.get(1), MatchType.SELF_AND_ALL_DESCENDANTS); + assertEquals(matchTypes.get(2), MatchType.ANCESTOR); + assertEquals(matchTypes.get(3), MatchType.DESCENDANT); + assertEquals(matchTypes.get(4), MatchType.NONE); + assertEquals(matchTypes.get(5), null); + } + @Test public void testTagEnricher_hive() { String[] hiveTestResourceFiles = { "/contextenricher/test_tagenricher_hive.json" }; diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java index 6a3875ad54..ba2e6439e9 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java @@ -496,6 +496,13 @@ public void testAnyResourceAccess_S3() throws Exception { runTestsFromResourceFiles(resourceFiles); } + @Test + public void testResourceHierarchyTags() throws Exception { + String[] resourceFiles = {"/policyengine/test_policyengine_resource_hierarchy_tags.json"}; + + runTestsFromResourceFiles(resourceFiles); + } + private void runTestsFromResourceFiles(String[] resourceNames) { 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 index 33c7204afa..268bdf95e4 100644 --- a/agents-common/src/test/resources/policyengine/resource_hierarchy_tags.json +++ b/agents-common/src/test/resources/policyengine/resource_hierarchy_tags.json @@ -3,83 +3,40 @@ "tagModel": "resource_private", "serviceName": "cl1_hive", "tagDefinitions": { - "1": { - "id": 1, - "guid": "tag-def-1", - "name": "SENSITIVE", - "attributeDefs": [ { "name": "level", "type": "string" } ] - } + "1": { "id": 1, "guid": "tag-def-1", "name": "SENSITIVE", "attributeDefs": [ { "name": "level", "type": "string" } ] }, + "2": { "id": 2, "guid": "tag-def-2", "name": "ORDER" }, + "3": { "id": 3, "guid": "tag-def-3", "name": "CUSTOMER" }, + "4": { "id": 4, "guid": "tag-def-4", "name": "ADDRESS" } }, "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" } - } + "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" } }, + "6": { "id": 6, "guid": "tag-6", "type": "ORDER" }, + "7": { "id": 7, "guid": "tag-7", "type": "CUSTOMER" }, + "8": { "id": 8, "guid": "tag-8", "type": "ADDRESS" } }, "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": [ "*" ] } } - } + { "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": [ "*" ] } } }, + { "id": 6, "guid": "resource-6", "serviceName": "cl1_hive", "resourceElements": { "database": { "values": [ "order" ] }, "table": { "values": [ "*" ] }, "column": { "values": [ "*" ] } } }, + { "id": 7, "guid": "resource-7", "serviceName": "cl1_hive", "resourceElements": { "database": { "values": [ "order" ] }, "table": { "values": [ "customer" ] } } }, + { "id": 8, "guid": "resource-8", "serviceName": "cl1_hive", "resourceElements": { "database": { "values": [ "order" ] }, "table": { "values": [ "customer" ] }, "column": { "values": [ "address" ] } } } ], "resourceToTagIds": { "1": [ 1 ], "2": [ 2 ], "3": [ 3 ], "4": [ 4 ], - "5": [ 5 ] + "5": [ 5 ], + "6": [ 6 ], + "7": [ 7 ], + "8": [ 8 ] } } 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 index 27152ba42d..dac583c4a5 100644 --- 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 @@ -87,32 +87,62 @@ ] }, "policies": [ - { "id": 101, "name": "SENSITIVE", "isEnabled": true, "isAuditEnabled": true, "policyType": 0, + { "id": 1, "name": "1: access: 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, + { "id": 2, "name": "2: access: ORDER", "isEnabled": true, "isAuditEnabled": true, "policyType": 0, + "resources": { "tag": { "values": [ "ORDER" ], "isRecursive": false } }, + "policyItems": [ + {"accesses": [{"type": "hive:create", "isAllowed": true}], "users": [ "dba"] } + ] + }, + { "id": 3, "name": "2: access: CUSTOMER", "isEnabled": true, "isAuditEnabled": true, "policyType": 0, + "resources": { "tag": { "values": [ "CUSTOMER" ], "isRecursive": false } }, + "policyItems": [ + {"accesses": [{"type": "hive:select", "isAllowed": true}], "users": [ "test-user"] } + ] + }, + { "id": 4, "name": "3: access: ADDRESS", "isEnabled": true, "isAuditEnabled": true, "policyType": 0, + "resources": { "tag": { "values": [ "ADDRESS" ], "isRecursive": false } }, + "policyItems": [ + {"accesses": [{"type": "hive:select", "isAllowed": true}], "users": [ "test-user"] } + ] + }, + { "id": 101, "name": "101: 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, + { "id": 102, "name": "102: 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, + { "id": 103, "name": "103: 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"}} ] + }, + { "id": 104, "name": "104: mask: CUSTOMER", "isEnabled": true, "isAuditEnabled": true, "policyType": 1, + "resources": { "tag": { "values": [ "CUSTOMER" ], "isRecursive": false } }, + "dataMaskPolicyItems": [ + { "accesses": [ { "type": "hive:select", "isAllowed": true } ], "users": [ "test-user"], "dataMaskInfo": { "dataMaskType": "MASK_NONE"}} + ] + }, + { "id": 105, "name": "105: mask: ADDRESS", "isEnabled": true, "isAuditEnabled": true, "policyType": 1, + "resources": { "tag": { "values": [ "ADDRESS" ], "isRecursive": false } }, + "dataMaskPolicyItems": [ + { "accesses": [ { "type": "hive:select", "isAllowed": true } ], "users": [ "test-user"], "dataMaskInfo": { "dataMaskType": "MASK_HASH"}} + ] } ] } @@ -126,11 +156,8 @@ "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" }, "isConditional": true }, {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true } ] }, @@ -138,11 +165,8 @@ "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" }, "isConditional": true }, {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true } ] }, @@ -150,11 +174,8 @@ "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" }, "isConditional": true }, {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true } ] }, @@ -170,10 +191,31 @@ "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" }, "isConditional": true }, {"users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": true } ] + }, + { "name": "database: order", + "resource": { "elements": { "database": "order" } }, + "userPermissions": { "dba": { "create": { "result": 1, "isFinal": true } } } + }, + { "name": "table: order.customer", + "resource": { "elements": { "database": "order", "table": "customer" } }, + "userPermissions": { + "test-user": { "select": { "result": 1, "isFinal": true } }, + "dba": { "create": { "result": 1, "isFinal": true } } + } + }, + { "name": "column: order.customer.address", + "resource": { "elements": { "database": "order", "table": "customer", "column": "address" } }, + "userPermissions": { + "test-user": { "select": { "result": 1, "isFinal": true } }, + "dba": { "create": { "result": 1, "isFinal": true } } + }, + "dataMasks": [ + { "users": [ "test-user" ], "groups": [], "roles": [], "accessTypes": [ "select" ], "maskInfo": { "dataMaskType": "MASK_HASH" }, "isConditional": false } + ] } ] } diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_resource_hierarchy_tags.json b/agents-common/src/test/resources/policyengine/test_policyengine_resource_hierarchy_tags.json new file mode 100644 index 0000000000..2380dadd13 --- /dev/null +++ b/agents-common/src/test/resources/policyengine/test_policyengine_resource_hierarchy_tags.json @@ -0,0 +1,239 @@ +{ + "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": [ + ], + "tagPolicyInfo": { + "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" } + ] + }, + "tagPolicies": [ + { "id": 1, "name": "1: access: SENSITIVE", "isEnabled": true, "isAuditEnabled": true, "policyType": 0, + "resources": { "tag": { "values": [ "SENSITIVE" ], "isRecursive": false } }, + "policyItems": [ + {"accesses": [{"type": "hive:select", "isAllowed": true}], "users": [ "test-user"] } + ] + }, + { "id": 2, "name": "2: access: ORDER", "isEnabled": true, "isAuditEnabled": true, "policyType": 0, + "resources": { "tag": { "values": [ "ORDER" ], "isRecursive": false } }, + "policyItems": [ + {"accesses": [{"type": "hive:create", "isAllowed": true}], "users": [ "dba"] } + ] + }, + { "id": 3, "name": "3: access: CUSTOMER", "isEnabled": true, "isAuditEnabled": true, "policyType": 0, + "resources": { "tag": { "values": [ "CUSTOMER" ], "isRecursive": false } }, + "policyItems": [ + {"accesses": [{"type": "hive:select", "isAllowed": true}], "users": [ "test-user"] } + ] + }, + { "id": 4, "name": "4: access: ADDRESS", "isEnabled": true, "isAuditEnabled": true, "policyType": 0, + "resources": { "tag": { "values": [ "ADDRESS" ], "isRecursive": false } }, + "policyItems": [ + {"accesses": [{"type": "hive:select", "isAllowed": true}], "users": [ "test-user"] } + ] + }, + { "id": 101, "name": "101: 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": 102, "name": "102: 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": 103, "name": "103: 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"}} + ] + }, + { "id": 104, "name": "104: mask: CUSTOMER", "isEnabled": true, "isAuditEnabled": true, "policyType": 1, + "resources": { "tag": { "values": [ "CUSTOMER" ], "isRecursive": false } }, + "dataMaskPolicyItems": [ + { "accesses": [ { "type": "hive:select", "isAllowed": true } ], "users": [ "test-user"], "dataMaskInfo": { "dataMaskType": "MASK_NONE"}} + ] + }, + { "id": 105, "name": "105: mask: ADDRESS", "isEnabled": true, "isAuditEnabled": true, "policyType": 1, + "resources": { "tag": { "values": [ "ADDRESS" ], "isRecursive": false } }, + "dataMaskPolicyItems": [ + { "accesses": [ { "type": "hive:select", "isAllowed": true } ], "users": [ "test-user"], "dataMaskInfo": { "dataMaskType": "MASK_HASH"}} + ] + } + ] + }, + "tests": [ + { "name": "table: db1.tbl1, user=test-user", + "request": { + "resource": { "elements": { "database": "db1", "table": "tbl1" } }, + "accessType": "select", "user": "test-user", "userGroups": [], "requestData": "select * from db1.tbl1" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 1 }, + "dataMaskResult": { "additionalInfo": { "maskType": "SHUFFLE", "maskCondition": null, "maskValue": null }, "policyId": 101 } + }, + { "name": "column: db1.tbl1.SSN, user=test-user", + "request": { + "resource": { "elements": { "database": "db1", "table": "tbl1", "column": "SSN" } }, + "accessType": "select", "user": "test-user", "userGroups": [], "requestData": "select SSN from db1.tbl1" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 1 }, + "dataMaskResult": { "additionalInfo": { "maskType": "MASK", "maskCondition": null, "maskValue": null }, "policyId": 102 } + }, + { "name": "column: db1.tbl1.Age, user=test-user", + "request": { + "resource": { "elements": { "database": "db1", "table": "tbl1", "column": "Age" } }, + "accessType": "select", "user": "test-user", "userGroups": [], "requestData": "select Age from db1.tbl1" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 1 }, + "dataMaskResult": { "additionalInfo": { "maskType": "MASK_HASH", "maskCondition": null, "maskValue": null }, "policyId": 103 } + }, + { "name": "column: db1.tbl1.Name, user=test-user", + "request": { + "resource": { "elements": { "database": "db1", "table": "tbl1", "column": "Name" } }, + "accessType": "select", "user": "test-user", "userGroups": [], "requestData": "select Name from db1.tbl1" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 1 }, + "dataMaskResult": { "additionalInfo": { "maskType": "MASK_HASH", "maskCondition": null, "maskValue": null }, "policyId": 103 } + }, + { "name": "database: db2, user=test-user", + "request": { + "resource": { "elements": { "database": "db2" } }, + "accessType": "_any", "user": "test-user", "userGroups": [], "requestData": "use db2" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 1 }, + "dataMaskResult": { "additionalInfo": { "maskType": "MASK_HASH", "maskCondition": null, "maskValue": null }, "policyId": 103 } + }, + { "name": "table: db2.tbl1, user=test-user", + "request": { + "resource": { "elements": { "database": "db2", "table": "tbl1" } }, + "accessType": "select", "user": "test-user", "userGroups": [], "requestData": "select * from db2.tbl1" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 1 }, + "dataMaskResult": { "additionalInfo": { "maskType": "MASK_HASH", "maskCondition": null, "maskValue": null }, "policyId": 103 } + }, + { "name": "column: db2.tbl1.Name, user=test-user", + "request": { + "resource": { "elements": { "database": "db2", "table": "tbl1", "column": "Name" } }, + "accessType": "select", "user": "test-user", "userGroups": [], "requestData": "select Name from db2.tbl1" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 1 }, + "dataMaskResult": { "additionalInfo": { "maskType": "MASK_HASH", "maskCondition": null, "maskValue": null }, "policyId": 103 } + }, + { "name": "database: order", + "request": { + "resource": { "elements": { "database": "order" } }, + "accessType": "create", "user": "dba", "userGroups": [], "requestData": "create table order.t1" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 2 } + }, + { "name": "table: order.customer", + "request": { + "resource": { "elements": { "database": "order", "table": "customer" } }, + "accessType": "select", "user": "test-user", "userGroups": [], "requestData": "select * from order.customer" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 3 }, + "dataMaskResult": { "additionalInfo": { "maskType": "MASK_NONE", "maskCondition": null, "maskValue": null }, "policyId": 104 } + }, + { "name": "table: order.customer", + "request": { + "resource": { "elements": { "database": "order", "table": "customer" } }, + "accessType": "create", "user": "dba", "userGroups": [], "requestData": "create table order.t1" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 2 } + }, + { "name": "column: order.customer.address", + "request": { + "resource": { "elements": { "database": "order", "table": "customer", "column": "address" } }, + "accessType": "select", "user": "test-user", "userGroups": [], "requestData": "select address from order.customer" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 4 }, + "dataMaskResult": { "additionalInfo": { "maskType": "MASK_HASH", "maskCondition": null, "maskValue": null }, "policyId": 105 } + }, + { "name": "column: order.customer.address", + "request": { + "resource": { "elements": { "database": "order", "table": "customer", "column": "address" } }, + "accessType": "create", "user": "dba", "userGroups": [], "requestData": "create table order.t1" + }, + "result": { "isAudited": true, "isAllowed": true, "policyId": 2 } + } + ] + }