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

Reply via email to