This is an automated email from the ASF dual-hosted git repository. madhan pushed a commit to branch RANGER-3923 in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/RANGER-3923 by this push: new 515a5098b RANGER-4531: updated GdsPolicyEngine with methods to find datasets/projects for principals 515a5098b is described below commit 515a5098b9553d87ceae3af03bcdf47d7d259501 Author: Madhan Neethiraj <mad...@apache.org> AuthorDate: Tue Nov 14 18:31:08 2023 -0800 RANGER-4531: updated GdsPolicyEngine with methods to find datasets/projects for principals --- .../policyengine/gds/GdsDataShareEvaluator.java | 52 ++++- .../policyengine/gds/GdsDatasetEvaluator.java | 38 ++- .../plugin/policyengine/gds/GdsDipEvaluator.java | 28 +-- .../plugin/policyengine/gds/GdsDshidEvaluator.java | 31 ++- .../plugin/policyengine/gds/GdsPolicyEngine.java | 228 ++++++++++++++++-- .../policyengine/gds/GdsProjectEvaluator.java | 16 +- .../gds/GdsSharedResourceEvaluator.java | 4 +- .../policyevaluator/RangerPolicyEvaluator.java | 43 +++- .../policyengine/gds/TestGdsPolicyEngine.java | 75 ++++-- .../resources/policyengine/gds/gds_info_hive.json | 153 ------------ .../gds/test_gds_policy_engine_hive.json | 259 ++++++++++++++++----- 11 files changed, 638 insertions(+), 289 deletions(-) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDataShareEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDataShareEvaluator.java index 4936a86ed..95f06209d 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDataShareEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDataShareEvaluator.java @@ -43,9 +43,10 @@ public class GdsDataShareEvaluator { private final DataShareInfo dsh; private final String name; private final String zoneName; - private final Map<String, RangerResourceTrie<GdsSharedResourceEvaluator>> resourceTries = new HashMap<>(); - private final List<GdsDshidEvaluator> dsidEvaluators = new ArrayList<>(); private final RangerConditionEvaluator conditionEvaluator; + private final List<GdsSharedResourceEvaluator> evaluators; + private final Map<String, RangerResourceTrie<GdsSharedResourceEvaluator>> resourceTries; + private final List<GdsDshidEvaluator> dsidEvaluators = new ArrayList<>(); public GdsDataShareEvaluator(DataShareInfo dsh, List<SharedResourceInfo> resources, RangerServiceDefHelper serviceDefHelper) { LOG.debug("==> GdsDataShareEvaluator({}, {})", dsh, resources); @@ -56,8 +57,10 @@ public class GdsDataShareEvaluator { this.conditionEvaluator = RangerCustomConditionEvaluator.getInstance().getExpressionEvaluator(dsh.getConditionExpr(), serviceDefHelper.getServiceDef()); if (resources != null) { - Set<String> resourceKeys = new HashSet<>(); - List<GdsSharedResourceEvaluator> evaluators = new ArrayList<>(resources.size()); + Set<String> resourceKeys = new HashSet<>(); + + evaluators = new ArrayList<>(resources.size()); + resourceTries = new HashMap<>(); for (SharedResourceInfo resource : resources) { GdsSharedResourceEvaluator evaluator = new GdsSharedResourceEvaluator(resource, dsh.getDefaultAccessTypes(), serviceDefHelper); @@ -73,6 +76,9 @@ public class GdsDataShareEvaluator { resourceTries.put(resourceKey, resourceTrie); } + } else { + evaluators = Collections.emptyList(); + resourceTries = Collections.emptyMap(); } LOG.debug("<== GdsDataShareEvaluator({}, {})", dsh, resources); @@ -90,8 +96,34 @@ public class GdsDataShareEvaluator { return zoneName; } - public void addDshidEvaluator(GdsDshidEvaluator dhidEvaluator) { - dsidEvaluators.add(dhidEvaluator); + public List<GdsSharedResourceEvaluator> getSharedResourceEvaluators() { return evaluators; } + + public boolean isInDataset(long datasetId) { + boolean ret = false; + + for (GdsDshidEvaluator dsidEvaluator : dsidEvaluators) { + if (dsidEvaluator.getDatasetId().equals(datasetId)) { + ret = true; + + break; + } + } + + return ret; + } + + public boolean isInProject(long projectId) { + boolean ret = false; + + for (GdsDshidEvaluator dsidEvaluator : dsidEvaluators) { + if (dsidEvaluator.getDatasetEvaluator().isInProject(projectId)) { + ret = true; + + break; + } + } + + return ret; } public void evaluate(RangerAccessRequest request, GdsAccessResult result, Set<Long> datasetIds) { @@ -141,7 +173,7 @@ public class GdsDataShareEvaluator { LOG.debug("<== GdsDataShareEvaluator.evaluate({}, {})", request, result); } - public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls, Map<Long, GdsDatasetEvaluator> datasets, Map<Long, GdsProjectEvaluator> projects) { + public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls) { LOG.debug("==> GdsDataShareEvaluator.getResourceACLs({}, {})", request, acls); List<GdsSharedResourceEvaluator> evaluators = getResourceEvaluators(request); @@ -150,13 +182,17 @@ public class GdsDataShareEvaluator { boolean isConditional = conditionEvaluator != null; for (GdsSharedResourceEvaluator evaluator : evaluators) { - evaluator.getResourceACLs(request, acls, isConditional, dsidEvaluators, datasets, projects); + evaluator.getResourceACLs(request, acls, isConditional, dsidEvaluators); } } LOG.debug("<== GdsDataShareEvaluator.getResourceACLs({}, {})", request, acls); } + void addDshidEvaluator(GdsDshidEvaluator dhidEvaluator) { + dsidEvaluators.add(dhidEvaluator); + } + private List<GdsSharedResourceEvaluator> getResourceEvaluators(RangerAccessRequest request) { final List<GdsSharedResourceEvaluator> ret; diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDatasetEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDatasetEvaluator.java index aa9fbea7c..4b5ef755e 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDatasetEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDatasetEvaluator.java @@ -77,8 +77,18 @@ public class GdsDatasetEvaluator { return name; } - public void addDipEvaluator(GdsDipEvaluator dipEvaluator) { - dipEvaluators.add(dipEvaluator); + public boolean isInProject(long projectId) { + boolean ret = false; + + for (GdsDipEvaluator dipEvaluator : dipEvaluators) { + if (dipEvaluator.getProjectId().equals(projectId)) { + ret = true; + + break; + } + } + + return ret; } public void evaluate(RangerAccessRequest request, GdsAccessResult result, Set<Long> projectIds) { @@ -118,7 +128,7 @@ public class GdsDatasetEvaluator { LOG.debug("<== GdsDatasetEvaluator.evaluate({}, {})", request, result); } - public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls, boolean isConditional, Set<String> allowedAccessTypes, Map<Long, GdsProjectEvaluator> projects) { + public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls, boolean isConditional, Set<String> allowedAccessTypes) { acls.getDatasets().add(getName()); if (!policyEvaluators.isEmpty()) { @@ -130,11 +140,29 @@ public class GdsDatasetEvaluator { } for (GdsDipEvaluator dipEvaluator : dipEvaluators) { - dipEvaluator.getResourceACLs(request, acls, isConditional, allowedAccessTypes, projects); + dipEvaluator.getResourceACLs(request, acls, isConditional, allowedAccessTypes); } } - public static class GdsDatasetAccessRequest extends RangerAccessRequestImpl { + public boolean hasReference(Set<String> users, Set<String> groups, Set<String> roles) { + boolean ret = false; + + for (RangerPolicyEvaluator policyEvaluator : policyEvaluators) { + ret = policyEvaluator.hasReference(users, groups, roles); + + if (ret) { + break; + } + } + + return ret; + } + + void addDipEvaluator(GdsDipEvaluator dipEvaluator) { + dipEvaluators.add(dipEvaluator); + } + + private static class GdsDatasetAccessRequest extends RangerAccessRequestImpl { public GdsDatasetAccessRequest(Long datasetId, RangerServiceDef gdsServiceDef, RangerAccessRequest request) { super.setResource(new RangerDatasetResource(datasetId, gdsServiceDef, request.getResource().getOwnerUser())); diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDipEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDipEvaluator.java index a5256ca4c..ec81b4c3e 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDipEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDipEvaluator.java @@ -27,17 +27,18 @@ import org.apache.ranger.plugin.util.ServiceGdsInfo.DatasetInProjectInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Map; import java.util.Set; public class GdsDipEvaluator { private static final Logger LOG = LoggerFactory.getLogger(GdsDipEvaluator.class); private final DatasetInProjectInfo dip; + private final GdsProjectEvaluator projectEvaluator; private final RangerValidityScheduleEvaluator scheduleEvaluator; - public GdsDipEvaluator(DatasetInProjectInfo dip) { - this.dip = dip; + public GdsDipEvaluator(DatasetInProjectInfo dip, GdsProjectEvaluator projectEvaluator) { + this.dip = dip; + this.projectEvaluator = projectEvaluator; if (dip.getValiditySchedule() != null) { scheduleEvaluator = new RangerValidityScheduleEvaluator(dip.getValiditySchedule()); @@ -46,14 +47,16 @@ public class GdsDipEvaluator { } } - public long getDatasetId() { + public Long getDatasetId() { return dip.getDatasetId(); } - public long getProjectId() { + public Long getProjectId() { return dip.getProjectId(); } + public GdsProjectEvaluator getProjectEvaluator() { return projectEvaluator; } + public boolean isAllowed(RangerAccessRequest request) { boolean ret = isActive(); @@ -64,21 +67,12 @@ public class GdsDipEvaluator { return ret; } - - public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls, boolean isConditional, Set<String> allowedAccessTypes, Map<Long, GdsProjectEvaluator> projects) { + public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls, boolean isConditional, Set<String> allowedAccessTypes) { LOG.debug("==> GdsDipEvaluator.getResourceACLs({}, {})", request, acls); - if (dip.getStatus() == RangerGds.GdsShareStatus.ACTIVE) { - GdsProjectEvaluator evaluator = projects.get(dip.getProjectId()); + isConditional = isConditional || scheduleEvaluator != null; - if (evaluator != null) { - isConditional = isConditional || scheduleEvaluator != null; - - evaluator.getResourceACLs(request, acls, isConditional, allowedAccessTypes); - } else { - LOG.warn("GdsDipEvaluator.getResourceACLs({}): evaluator for projectId={} not found", request, dip.getProjectId()); - } - } + projectEvaluator.getResourceACLs(request, acls, isConditional, allowedAccessTypes); LOG.debug("<== GdsDipEvaluator.getResourceACLs({}, {})", request, acls); } diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDshidEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDshidEvaluator.java index c32f22b27..c56c55f77 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDshidEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsDshidEvaluator.java @@ -27,17 +27,18 @@ import org.apache.ranger.plugin.util.ServiceGdsInfo.DataShareInDatasetInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Map; import java.util.Set; public class GdsDshidEvaluator { private static final Logger LOG = LoggerFactory.getLogger(GdsDshidEvaluator.class); - private final DataShareInDatasetInfo dshid; + private final DataShareInDatasetInfo dshid; + private final GdsDatasetEvaluator datasetEvaluator;; private final RangerValidityScheduleEvaluator scheduleEvaluator; - public GdsDshidEvaluator(DataShareInDatasetInfo dshid) { - this.dshid = dshid; + public GdsDshidEvaluator(DataShareInDatasetInfo dshid, GdsDatasetEvaluator datasetEvaluator) { + this.dshid = dshid; + this.datasetEvaluator = datasetEvaluator; if (dshid.getValiditySchedule() != null) { scheduleEvaluator = new RangerValidityScheduleEvaluator(dshid.getValiditySchedule()); @@ -46,14 +47,18 @@ public class GdsDshidEvaluator { } } - public long getDataShareId() { + public Long getDataShareId() { return dshid.getDataShareId(); } - public long getDatasetId() { + public Long getDatasetId() { return dshid.getDatasetId(); } + public GdsDatasetEvaluator getDatasetEvaluator() { + return datasetEvaluator; + } + public boolean isAllowed(RangerAccessRequest request) { boolean ret = isActive(); @@ -64,20 +69,12 @@ public class GdsDshidEvaluator { return ret; } - public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls, boolean isConditional, Map<Long, GdsDatasetEvaluator> datasets, Map<Long, GdsProjectEvaluator> projects, Set<String> allowedAccessTypes) { + public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls, boolean isConditional, Set<String> allowedAccessTypes) { LOG.debug("==> GdsDshidEvaluator.getResourceACLs({}, {})", request, acls); - if (dshid.getStatus() == RangerGds.GdsShareStatus.ACTIVE) { - GdsDatasetEvaluator datasetEvaluator = datasets.get(dshid.getDatasetId()); + isConditional = isConditional || scheduleEvaluator != null; - if (datasetEvaluator != null) { - isConditional = isConditional || scheduleEvaluator != null; - - datasetEvaluator.getResourceACLs(request, acls, isConditional, allowedAccessTypes, projects); - } else { - LOG.warn("GdsDshidEvaluator.getResourceACLs({}): datasetEvaluator for datasetId={} not found", request, dshid.getDatasetId()); - } - } + datasetEvaluator.getResourceACLs(request, acls, isConditional, allowedAccessTypes); LOG.debug("<== GdsDshidEvaluator.getResourceACLs({}, {})", request, acls); } diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsPolicyEngine.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsPolicyEngine.java index 337134fe4..541f0754e 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsPolicyEngine.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsPolicyEngine.java @@ -114,7 +114,7 @@ public class GdsPolicyEngine { } for (GdsDataShareEvaluator dshEvaluator : dataShares) { - dshEvaluator.getResourceACLs(request, ret, datasets, projects); + dshEvaluator.getResourceACLs(request, ret); } } @@ -123,6 +123,57 @@ public class GdsPolicyEngine { return ret; } + public Set<String> getDatasetsForPrincipals(Set<String> users, Set<String> groups, Set<String> roles) { + Set<String> ret = new HashSet<>(); + + for (GdsDatasetEvaluator dataset : datasets.values()) { + if (dataset.hasReference(users, groups, roles)) { + ret.add(dataset.getName()); + } + } + + return ret; + } + + public Set<String> getProjectsForPrincipals(Set<String> users, Set<String> groups, Set<String> roles) { + Set<String> ret = new HashSet<>(); + + for (GdsProjectEvaluator project : projects.values()) { + if (project.hasReference(users, groups, roles)) { + ret.add(project.getName()); + } + } + + return ret; + } + + public long getDatasetId(String datasetName) { + GdsDatasetEvaluator evaluator = getDatasetEvaluator(datasetName); + + return evaluator == null ? -1 : evaluator.getId(); + } + + public long getProjectId(String projectName) { + GdsProjectEvaluator evaluator = getProjectEvaluator(projectName); + + return evaluator == null ? -1 : evaluator.getId(); + } + + public Iterator<GdsSharedResourceEvaluator> getDatasetResources(long datasetId) { + return new SharedResourceIter(getDataSharesForDataset(datasetId).listIterator()); + } + + public Iterator<GdsSharedResourceEvaluator> getProjectResources(long projectId) { + return new SharedResourceIter(getDataSharesForProject(projectId).listIterator()); + } + + public Iterator<GdsSharedResourceEvaluator> getDataShareResources(long dataShareId) { + GdsDataShareEvaluator evaluator = getDataShareEvaluator(dataShareId); + List<GdsDataShareEvaluator> evaluators = evaluator == null ? Collections.emptyList() : Collections.singletonList(evaluator); + + return new SharedResourceIter(evaluators.listIterator()); + } + private void init(RangerServiceDefHelper serviceDefHelper, RangerPluginContext pluginContext) { LOG.debug("==> RangerGdsPolicyEngine.init()"); @@ -180,7 +231,15 @@ public class GdsPolicyEngine { continue; } - GdsDshidEvaluator dshidEvaluator = new GdsDshidEvaluator(dshid); + GdsDatasetEvaluator datasetEvaluator = datasets.get(dshid.getDatasetId()); + + if (datasetEvaluator == null) { + LOG.error("RangerGdsPolicyEngine(): invalid datasetId in dshid: {}. Ignored", dshid); + + continue; + } + + GdsDshidEvaluator dshidEvaluator = new GdsDshidEvaluator(dshid, datasetEvaluator); dshEvaluator.addDshidEvaluator(dshidEvaluator); } @@ -202,7 +261,15 @@ public class GdsPolicyEngine { continue; } - GdsDipEvaluator dipEvaluator = new GdsDipEvaluator(dip); + GdsProjectEvaluator projectEvaluator = projects.get(dip.getProjectId()); + + if (projectEvaluator == null) { + LOG.error("RangerGdsPolicyEngine(): invalid projectId in dip: {}. Ignored", dip); + + continue; + } + + GdsDipEvaluator dipEvaluator = new GdsDipEvaluator(dip, projectEvaluator); datasetEvaluator.addDipEvaluator(dipEvaluator); } @@ -311,27 +378,162 @@ public class GdsPolicyEngine { evaluator.evaluate(request, result); } } + + private GdsDatasetEvaluator getDatasetEvaluator(String dsName) { + GdsDatasetEvaluator ret = null; + + for (GdsDatasetEvaluator evaluator : datasets.values()) { + if (StringUtils.equals(evaluator.getName(), dsName)) { + ret = evaluator; + + break; + } + } + + return ret; + } + + private GdsProjectEvaluator getProjectEvaluator(String projectName) { + GdsProjectEvaluator ret = null; + + for (GdsProjectEvaluator evaluator : projects.values()) { + if (StringUtils.equals(evaluator.getName(), projectName)) { + ret = evaluator; + + break; + } + } + + return ret; + } + + private GdsDataShareEvaluator getDataShareEvaluator(long dataShareId) { + GdsDataShareEvaluator ret = null; + + for (List<GdsDataShareEvaluator> dshEvaluators : zoneDataShares.values()) { + for (GdsDataShareEvaluator dshEvaluator : dshEvaluators) { + if (dshEvaluator.getId().equals(dataShareId)) { + ret = dshEvaluator; + + break; + } + } + } + + return ret; + } + + private List<GdsDataShareEvaluator> getDataSharesForDataset(long datasetId) { + Set<GdsDataShareEvaluator> evaluators = null; + + for (List<GdsDataShareEvaluator> dshEvaluators : zoneDataShares.values()) { + for (GdsDataShareEvaluator dshEvaluator : dshEvaluators) { + if (dshEvaluator.isInDataset(datasetId)) { + if (evaluators == null) { + evaluators = new HashSet<>(); + } + + evaluators.add(dshEvaluator); + } + } + } + + List<GdsDataShareEvaluator> ret = (evaluators == null) ? Collections.emptyList() : new ArrayList<>(evaluators); + + if (ret.size() > 1) { + ret.sort(GdsDataShareEvaluator.EVAL_ORDER_COMPARATOR); + } + + return ret; + } + + private List<GdsDataShareEvaluator> getDataSharesForProject(long projectId) { + Set<GdsDataShareEvaluator> evaluators = null; + + for (List<GdsDataShareEvaluator> dshEvaluators : zoneDataShares.values()) { + for (GdsDataShareEvaluator dshEvaluator : dshEvaluators) { + if (dshEvaluator.isInProject(projectId)) { + if (evaluators == null) { + evaluators = new HashSet<>(); + } + + evaluators.add(dshEvaluator); + } + } + } + + List<GdsDataShareEvaluator> ret = (evaluators == null) ? Collections.emptyList() : new ArrayList<>(evaluators); + + if (ret.size() > 1) { + ret.sort(GdsDataShareEvaluator.EVAL_ORDER_COMPARATOR); + } + + return ret; + } + + static class SharedResourceIter implements Iterator<GdsSharedResourceEvaluator> { + private final Iterator<GdsDataShareEvaluator> dataShareIter; + private Iterator<GdsSharedResourceEvaluator> sharedResourceIter; + private GdsSharedResourceEvaluator nextResource; + + SharedResourceIter(Iterator<GdsDataShareEvaluator> dataShareIter) { + this.dataShareIter = dataShareIter; + this.sharedResourceIter = Collections.emptyIterator(); + this.nextResource = null; + + setNext(); + } + + @Override + public boolean hasNext() { + return nextResource != null; + } + + @Override + public GdsSharedResourceEvaluator next() { + GdsSharedResourceEvaluator ret = nextResource; + + if (ret != null) { + setNext(); + } + + return ret; + } + + private void setNext() { + if (!sharedResourceIter.hasNext()) { + while (dataShareIter.hasNext()) { + GdsDataShareEvaluator dataShareEvaluator = dataShareIter.next(); + + sharedResourceIter = dataShareEvaluator.getSharedResourceEvaluators().iterator(); + + if (sharedResourceIter.hasNext()) { + break; + } + } + } + + nextResource = sharedResourceIter.hasNext() ? sharedResourceIter.next() : null; + } + } } /* dataShare-1 ----------------------- dataset-1 --- - resource-1 / \ - resource-2 / \ + resource-11 / \ + resource-12 / \ / \ dataShare-2 -------------------| | ---- project-1 - resource-3 \ / - \ / + resource-21 \ / + resource-22 \ / -- dataset-2--- / dataShare-3 --------------------- - resource-3 - resource-4 + resource-31 dataShare-4 ------------------------- dataset-3 --------- project-2 - resource-4 - resource-5 + resource-41 dataShare-5 ------------------------- dataset-4 - resource-6 - resource-7 + resource-51 */ \ No newline at end of file diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsProjectEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsProjectEvaluator.java index 17a86163b..87175ea5c 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsProjectEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsProjectEvaluator.java @@ -119,8 +119,22 @@ public class GdsProjectEvaluator { } } + public boolean hasReference(Set<String> users, Set<String> groups, Set<String> roles) { + boolean ret = false; - public static class GdsProjectAccessRequest extends RangerAccessRequestImpl { + for (RangerPolicyEvaluator policyEvaluator : policyEvaluators) { + ret = policyEvaluator.hasReference(users, groups, roles); + + if (ret) { + break; + } + } + + return ret; + } + + + private static class GdsProjectAccessRequest extends RangerAccessRequestImpl { public GdsProjectAccessRequest(Long projectId, RangerServiceDef gdsServiceDef, RangerAccessRequest request) { super.setResource(new RangerProjectResource(projectId, gdsServiceDef, request.getResource().getOwnerUser())); diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsSharedResourceEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsSharedResourceEvaluator.java index 726331271..2e073bb1c 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsSharedResourceEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsSharedResourceEvaluator.java @@ -137,7 +137,7 @@ public class GdsSharedResourceEvaluator implements RangerResourceEvaluator { return ret; } - public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls, boolean isConditional, List<GdsDshidEvaluator> dshidEvaluators, Map<Long, GdsDatasetEvaluator> datasets, Map<Long, GdsProjectEvaluator> projects) { + public void getResourceACLs(RangerAccessRequest request, RangerResourceACLs acls, boolean isConditional, List<GdsDshidEvaluator> dshidEvaluators) { LOG.debug("==> GdsSharedResourceEvaluator.getResourceACLs({}, {})", request, acls); boolean isResourceMatch = policyResourceMatcher.isMatch(request.getResource(), request.getResourceElementMatchingScopes(), request.getContext()); @@ -146,7 +146,7 @@ public class GdsSharedResourceEvaluator implements RangerResourceEvaluator { isConditional = isConditional || conditionEvaluator != null; for (GdsDshidEvaluator dshidEvaluator : dshidEvaluators) { - dshidEvaluator.getResourceACLs(request, acls, isConditional, datasets, projects, getAllowedAccessTypes()); + dshidEvaluator.getResourceACLs(request, acls, isConditional, getAllowedAccessTypes()); } } 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 2856ccc6b..e0a9aa987 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 @@ -39,6 +39,7 @@ import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; import org.apache.ranger.plugin.model.RangerPolicy.RangerRowFilterPolicyItem; +import org.apache.ranger.plugin.model.RangerPrincipal; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.policyengine.PolicyEngine; import org.apache.ranger.plugin.policyengine.RangerResourceAccessInfo; @@ -150,7 +151,37 @@ public interface RangerPolicyEvaluator { return false; } - default boolean hasRoles(final RangerPolicy policy) { + default boolean hasReference(Set<String> users, Set<String> groups, Set<String> roles) { + RangerPolicy policy = getPolicy(); + + for (RangerPolicyItem policyItem : policy.getPolicyItems()) { + if (hasReference(policyItem, users, groups, roles)) { + return true; + } + } + + for (RangerPolicyItem policyItem : policy.getDenyPolicyItems()) { + if (hasReference(policyItem, users, groups, roles)) { + return true; + } + } + + for (RangerPolicyItem policyItem : policy.getAllowExceptions()) { + if (hasReference(policyItem, users, groups, roles)) { + return true; + } + } + + for (RangerPolicyItem policyItem : policy.getDenyExceptions()) { + if (hasReference(policyItem, users, groups, roles)) { + return true; + } + } + return false; + + } + + default boolean hasRoles(final RangerPolicy policy) { for (RangerPolicyItem policyItem : policy.getPolicyItems()) { if (hasRoles(policyItem)) { return true; @@ -188,6 +219,12 @@ public interface RangerPolicyEvaluator { return CollectionUtils.isNotEmpty(policyItem.getConditions()) || policyItem.getUsers().contains(RangerPolicyEngine.RESOURCE_OWNER); /* || policyItem.getGroups().contains(RangerPolicyEngine.RESOURCE_GROUP_OWNER) */ } + static boolean hasReference(RangerPolicyItem policyItem, Set<String> users, Set<String> groups, Set<String> roles) { + return containsAny(policyItem.getUsers(), users) || + containsAny(policyItem.getGroups(), groups) || + containsAny(policyItem.getRoles(), roles); + } + static boolean hasRoles(RangerPolicyItem policyItem) { return CollectionUtils.isNotEmpty(policyItem.getRoles()); } @@ -200,6 +237,10 @@ public interface RangerPolicyEvaluator { } } + static boolean containsAny(Collection<String> coll1, Collection<String> coll2) { + return coll1 != null && coll2 != null && CollectionUtils.containsAny(coll1, coll2); + } + class PolicyEvalOrderComparator implements Comparator<RangerPolicyEvaluator>, Serializable { @Override public int compare(RangerPolicyEvaluator me, RangerPolicyEvaluator other) { diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/gds/TestGdsPolicyEngine.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/gds/TestGdsPolicyEngine.java index 9d1560562..fb6d593e9 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/gds/TestGdsPolicyEngine.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/gds/TestGdsPolicyEngine.java @@ -83,20 +83,62 @@ public class TestGdsPolicyEngine { GdsPolicyEngine policyEngine = new GdsPolicyEngine(testCase.gdsInfo, new RangerServiceDefHelper(testCase.serviceDef, false), pluginContext); for (TestData test : testCase.tests) { - Set<String> zoneNames = zoneMatcher.getZonesForResourceAndChildren(test.request.getResource()); + if (test.request != null) { + Set<String> zoneNames = zoneMatcher.getZonesForResourceAndChildren(test.request.getResource()); - RangerAccessRequestUtil.setResourceZoneNamesInContext(test.request, zoneNames); + RangerAccessRequestUtil.setResourceZoneNamesInContext(test.request, zoneNames); - if (test.result != null) { - GdsAccessResult result = policyEngine.evaluate(test.request); + if (test.result != null) { + GdsAccessResult result = policyEngine.evaluate(test.request); - assertEquals(test.name, test.result, result); - } + assertEquals(test.name, test.result, result); + } + + if (test.acls != null) { + RangerResourceACLs acls = policyEngine.getResourceACLs(test.request); + + assertEquals(test.name, test.acls, acls); + } + } else if (test.principals != null) { + Set<String> users = test.principals.get("users"); + Set<String> groups = test.principals.get("groups"); + Set<String> roles = test.principals.get("roles"); + + if (test.datasets != null) { + Set<String> datasets = policyEngine.getDatasetsForPrincipals(users, groups, roles); + + assertEquals(test.name, test.datasets, datasets); + } + + if (test.projects != null) { + Set<String> projects = policyEngine.getProjectsForPrincipals(users, groups, roles); + + assertEquals(test.name, test.projects, projects); + } + } else if (test.resourceIds != null) { + Set<Long> resourceIds = new HashSet<>(); + + if (test.datasetId != null) { + Iterator<GdsSharedResourceEvaluator> iter = policyEngine.getDatasetResources(test.datasetId); + + while (iter.hasNext()) { + resourceIds.add(iter.next().getId()); + } + } else if (test.projectId != null) { + Iterator<GdsSharedResourceEvaluator> iter = policyEngine.getProjectResources(test.projectId); + + while (iter.hasNext()) { + resourceIds.add(iter.next().getId()); + } + } else if (test.dataShareId != null) { + Iterator<GdsSharedResourceEvaluator> iter = policyEngine.getDataShareResources(test.dataShareId); - if (test.acls != null) { - RangerResourceACLs acls = policyEngine.getResourceACLs(test.request); + while (iter.hasNext()) { + resourceIds.add(iter.next().getId()); + } + } - assertEquals(test.name, test.acls, acls); + assertEquals(test.name, test.resourceIds, resourceIds); } } } @@ -110,10 +152,17 @@ public class TestGdsPolicyEngine { } static class TestData { - public String name; - public RangerAccessRequest request; - public GdsAccessResult result; - public RangerResourceACLs acls; + public String name; + public RangerAccessRequest request; + public GdsAccessResult result; + public RangerResourceACLs acls; + public Map<String, Set<String>> principals; + public Set<String> datasets; + public Set<String> projects; + public Long datasetId; + public Long projectId; + public Long dataShareId; + public Set<Long> resourceIds; } static class RangerAccessRequestDeserializer implements JsonDeserializer<RangerAccessRequest> { diff --git a/agents-common/src/test/resources/policyengine/gds/gds_info_hive.json b/agents-common/src/test/resources/policyengine/gds/gds_info_hive.json deleted file mode 100644 index 34fcc6290..000000000 --- a/agents-common/src/test/resources/policyengine/gds/gds_info_hive.json +++ /dev/null @@ -1,153 +0,0 @@ -{ - "serviceName": "dev_hive", - "dataShares": [ - { "id": 1, "name": "hive-sales-2023", "zoneName": "sales", "conditionExpr": "", "defaultAccessTypes": [ "_READ" ], "defaultTagMasks": [ ] }, - { "id": 2, "name": "hive-finance-2023", "zoneName": "finance", "conditionExpr": "", "defaultAccessTypes": [ "_READ" ], "defaultTagMasks": [ ] }, - { "id": 3, "name": "hive-shipping-2023", "zoneName": "shipping", "conditionExpr": "", "defaultAccessTypes": [ "_READ" ], "defaultTagMasks": [ ] }, - { "id": 4, "name": "hive-new-customers-2023", "zoneName": "", "conditionExpr": "", "defaultAccessTypes": [ "_READ" ], "defaultTagMasks": [ ] }, - { "id": 5, "name": "hive-facilities", "zoneName": "", "conditionExpr": "", "defaultAccessTypes": [ "_READ" ], "defaultTagMasks": [ ] } - ], - "dshids": [ - { "dataShareId": 1, "datasetId": 1, "status": "ACTIVE", "validitySchedule": null }, - { "dataShareId": 2, "datasetId": 1, "status": "ACTIVE", "validitySchedule": null }, - { "dataShareId": 2, "datasetId": 2, "status": "ACTIVE", "validitySchedule": null }, - { "dataShareId": 3, "datasetId": 2, "status": "ACTIVE", "validitySchedule": null }, - { "dataShareId": 4, "datasetId": 3, "status": "ACTIVE", "validitySchedule": null }, - { "dataShareId": 5, "datasetId": 4, "status": "ACTIVE", "validitySchedule": null } - ], - "dips": [ - { "datasetId": 1, "projectId": 1, "status": "ACTIVE", "validitySchedule": null }, - { "datasetId": 2, "projectId": 1, "status": "ACTIVE", "validitySchedule": null }, - { "datasetId": 3, "projectId": 2, "status": "ACTIVE", "validitySchedule": null } - ], - "resources": [ - { - "id": 11, "dataShareId": 1, "conditionExpr": "", "accessTypes": [ "select" ], - "resource": { "database": { "values": [ "sales" ] }, "table": { "values": [ "prospects" ] } }, "rowFilter": { "filterExpr": "created_time >= '2023-01-01' and created_time < '2024-01-01'" }, - "subResourceType": "column", "subResource": { "values": [ "*" ] }, "subResourceMasks": { } - }, - { - "id": 12, "dataShareId": 1, "conditionExpr": "", "accessTypes": [ "select" ], - "resource": { "database": { "values": [ "sales" ] }, "table": { "values": [ "orders" ] } }, "rowFilter": { "filterExpr": "created_time >= '2023-01-01' and created_time < '2024-01-01'" }, - "subResourceType": "column", "subResource": { "values": [ "*" ] }, "subResourceMasks": { } - }, - { - "id": 21, "dataShareId": 2, "conditionExpr": "", "accessTypes": [ "select" ], - "resource": { "database": { "values": [ "finance" ] }, "table": { "values": [ "invoices" ] } }, "rowFilter": { "filterExpr": "created_time >= '2023-01-01' and created_time < '2024-01-01'" }, - "subResourceType": "column", "subResource": { "values": [ "*" ] }, "subResourceMasks": { } - }, - { - "id": 22, "dataShareId": 2, "conditionExpr": "", "accessTypes": [ "select" ], - "resource": { "database": { "values": [ "finance" ] }, "table": { "values": [ "payments" ] } }, "rowFilter": { "filterExpr": "created_time >= '2023-01-01' and created_time < '2024-01-01'" }, - "subResourceType": "column", "subResource": { "values": [ "*" ] }, "subResourceMasks": { } - }, - { - "id": 31, "dataShareId": 3, "conditionExpr": "", "accessTypes": [ "select" ], - "resource": { "database": { "values": [ "shipping" ] }, "table": { "values": [ "shipments" ] } }, "rowFilter": { "filterExpr": "created_time >= '2023-01-01' and created_time < '2024-01-01'" }, - "subResourceType": "column", "subResource": { "values": [ "*" ] }, "subResourceMasks": { } - }, - { - "id": 41, "dataShareId": 4, "conditionExpr": "", "accessTypes": [ "select" ], - "resource": { "database": { "values": [ "customers" ] }, "table": { "values": [ "contact_info" ] } }, "rowFilter": { "filterExpr": "created_time >= '2023-01-01' and created_time < '2024-01-01'" }, - "subResourceType": "column", "subResource": { "values": [ "*" ] }, "subResourceMasks": null - }, - { - "id": 51, "dataShareId": 5, "conditionExpr": "", "accessTypes": [ "select" ], - "resource": { "database": { "values": [ "operations" ] }, "table": { "values": [ "facilities" ] } }, "rowFilter": null, - "subResourceType": "column", "subResource": { "values": [ "*" ] }, "subResourceMasks": null - } - ], - "datasets": [ - { - "id": 1, - "name": "dataset-1", - "policies": [ - { "id": 2001, "name": "dataset-1", "isEnabled": true, "isAuditEnabled": true, - "resources": { "dataset-id": { "values": ["1"] } }, - "policyItems":[ - { "accesses":[ { "type": "_ALL", "isAllowed": true } ], "users": [ "ds-user" ], "groups": []} - ] - } - ] - }, - { - "id": 2, - "name": "dataset-2", - "policies": [ - { "id": 2002, "name": "dataset-2", "isEnabled": true, "isAuditEnabled": true, - "resources": { "dataset-id": { "values": ["2"] } }, - "policyItems":[ - { "accesses":[ { "type": "_ALL", "isAllowed": true } ], "users": [ "ds-user" ], "groups": []} - ] - } - ] - }, - { - "id": 3, - "name": "dataset-3", - "policies": [ - { "id": 2003, "name": "dataset-3", "isEnabled": true, "isAuditEnabled": true, - "resources": { "dataset-id": { "values": ["3"] } }, - "policyItems":[ - { "accesses":[ { "type": "_ALL", "isAllowed": true } ], "users": [ "ds-user" ], "groups": []} - ] - } - ] - }, - { - "id": 4, - "name": "dataset-4", - "policies": [ - { "id": 2004, "name": "dataset-4", "isEnabled": true, "isAuditEnabled": true, - "resources": { "dataset-id": { "values": ["4"] } }, - "policyItems":[ - { "accesses":[ { "type": "_ALL", "isAllowed": true } ], "users": [ "ds-user" ], "groups": []} - ] - } - ] - } - ], - "projects": [ - { - "id": 1, - "name": "project-1", - "policies": [ - { "id": 3001, "name": "project-1", "isEnabled": true, "isAuditEnabled": true, - "resources": { "project-id": { "values": ["1"] } }, - "policyItems":[ - { "accesses":[ { "type": "_ALL", "isAllowed": true } ], "users": [ "proj-user" ], "groups": []} - ] - } - ] - }, - { - "id": 2, - "name": "project-2", - "policies": [ - { "id": 3002, "name": "project-2", "isEnabled": true, "isAuditEnabled": true, - "resources": { "project-id": { "values": ["2"] } }, - "policyItems":[ - { "accesses":[ { "type": "_ALL", "isAllowed": true } ], "users": [ "proj-user" ], "groups": []} - ] - } - ] - } - ], - "gdsServiceDef": { - "name": "gds", - "id": 3, - "resources": [ - { "name": "dataset-id", "level":1, "parent": "", "mandatory": true, "lookupSupported": false, "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", "matcherOptions":{ "wildCard": false, "ignoreCase": true }, "label": "Dataset ID", "description": "Dataset ID" }, - { "name": "project-id", "level":1, "parent": "", "mandatory": true, "lookupSupported": false, "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", "matcherOptions":{ "wildCard": false, "ignoreCase": true }, "label": "Project ID", "description": "Project ID" } - ], - "accessTypes":[ - { "itemId": 1, "name": "_CREATE", "label": "_CREATE" }, - { "itemId": 2, "name": "_READ", "label": "_READ" }, - { "itemId": 3, "name": "_UPDATE", "label": "_UPDATE" }, - { "itemId": 4, "name": "_DELETE", "label": "_DELETE" }, - { "itemId": 5, "name": "_MANAGE", "label": "_MANAGE" }, - { "itemId": 6, "name": "_ALL", "label": "_ALL" } - ] - }, - "gdsVersion": 1 -} \ No newline at end of file diff --git a/agents-common/src/test/resources/policyengine/gds/test_gds_policy_engine_hive.json b/agents-common/src/test/resources/policyengine/gds/test_gds_policy_engine_hive.json index 2ab93bde6..bcdf5a342 100644 --- a/agents-common/src/test/resources/policyengine/gds/test_gds_policy_engine_hive.json +++ b/agents-common/src/test/resources/policyengine/gds/test_gds_policy_engine_hive.json @@ -32,10 +32,10 @@ "finance": { "zoneName": "finance", "resources": [ { "database": [ "finance" ] } ] }, "shipping": { "zoneName": "shipping", "resources": [ { "database": [ "shipping" ] } ] } }, - "gdsInfoFilename": "/policyengine/gds/gds_info_hive.json", + "gdsInfoFilename": "/plugin/hive_gds_info.json", "tests": [ { - "name": "table: sales.prospects, user: ds-user, access: select", + "name": "table: sales.prospects, user: ds-user, access: select", "request": { "resource": { "elements": { "database": "sales", "table": "prospects" } }, "accessType": "select", "user": "ds-user", "userGroups": [] @@ -43,7 +43,7 @@ "result": { "datasets": [ "dataset-1" ], "projects": [ "project-1" ], "isAllowed": true, "isAudited": true, "policyId": 2001 } }, { - "name": "table: sales.orders, user: ds-user, access: select", + "name": "table: sales.orders, user: ds-user, access: select", "request": { "resource": { "elements": { "database": "sales", "table": "orders" } }, "accessType": "select", "user": "ds-user", "userGroups": [] @@ -51,7 +51,7 @@ "result": { "datasets": [ "dataset-1" ], "projects": [ "project-1" ], "isAllowed": true, "isAudited": true, "policyId": 2001 } }, { - "name": "table: finance.invoices, user: ds-user, access: select", + "name": "table: finance.invoices, user: ds-user, access: select", "request": { "resource": { "elements": { "database": "finance", "table": "invoices" } }, "accessType": "select", "user": "ds-user", "userGroups": [] @@ -59,7 +59,7 @@ "result": { "datasets": [ "dataset-1", "dataset-2" ], "projects": [ "project-1" ], "isAllowed": true, "isAudited": true, "policyId": 2001 } }, { - "name": "table: finance.payments, user: ds-user, access: select", + "name": "table: finance.payments, user: ds-user, access: select", "request": { "resource": { "elements": { "database": "finance", "table": "payments" } }, "accessType": "select", "user": "ds-user", "userGroups": [] @@ -67,7 +67,7 @@ "result": { "datasets": [ "dataset-1", "dataset-2" ], "projects": [ "project-1" ], "isAllowed": true, "isAudited": true, "policyId": 2001 } }, { - "name": "table: shipping.shipments, user: ds-user, access: select", + "name": "table: shipping.shipments, user: ds-user, access: select", "request": { "resource": { "elements": { "database": "shipping", "table": "shipments" } }, "accessType": "select", "user": "ds-user", "userGroups": [] @@ -75,7 +75,7 @@ "result": { "datasets": [ "dataset-2" ], "projects": [ "project-1" ], "isAllowed": true, "isAudited": true, "policyId": 2002 } }, { - "name": "table: customers.contact_info, user: ds-user, access: select", + "name": "table: customers.contact_info, user: ds-user, access: select", "request": { "resource": { "elements": { "database": "customers", "table": "contact_info" } }, "accessType": "select", "user": "ds-user", "userGroups": [] @@ -83,7 +83,7 @@ "result": { "datasets": [ "dataset-3" ], "projects": [ "project-2" ], "isAllowed": true, "isAudited": true, "policyId": 2003 } }, { - "name": "table: operations.facilities, user: ds-user, access: select", + "name": "table: operations.facilities, user: ds-user, access: select", "request": { "resource": { "elements": { "database": "operations", "table": "facilities" } }, "accessType": "select", "user": "ds-user", "userGroups": [] @@ -93,7 +93,7 @@ { - "name": "table: sales.prospects, user: proj-user, access: select", + "name": "table: sales.prospects, user: proj-user, access: select", "request": { "resource": { "elements": { "database": "sales", "table": "prospects" } }, "accessType": "select", "user": "proj-user", "userGroups": [] @@ -101,7 +101,7 @@ "result": { "datasets": [ "dataset-1" ], "projects": [ "project-1" ], "isAllowed": true, "isAudited": true, "policyId": 3001 } }, { - "name": "table: sales.orders, user: proj-user, access: select", + "name": "table: sales.orders, user: proj-user, access: select", "request": { "resource": { "elements": { "database": "sales", "table": "orders" } }, "accessType": "select", "user": "proj-user", "userGroups": [] @@ -109,7 +109,7 @@ "result": { "datasets": [ "dataset-1" ], "projects": [ "project-1" ], "isAllowed": true, "isAudited": true, "policyId": 3001 } }, { - "name": "table: finance.invoices, user: proj-user, access: select", + "name": "table: finance.invoices, user: proj-user, access: select", "request": { "resource": { "elements": { "database": "finance", "table": "invoices" } }, "accessType": "select", "user": "proj-user", "userGroups": [] @@ -117,7 +117,7 @@ "result": { "datasets": [ "dataset-1", "dataset-2" ], "projects": [ "project-1" ], "isAllowed": true, "isAudited": true, "policyId": 3001 } }, { - "name": "table: finance.payments, user: proj-user, access: select", + "name": "table: finance.payments, user: proj-user, access: select", "request": { "resource": { "elements": { "database": "finance", "table": "payments" } }, "accessType": "select", "user": "proj-user", "userGroups": [] @@ -125,7 +125,7 @@ "result": { "datasets": [ "dataset-1", "dataset-2" ], "projects": [ "project-1" ], "isAllowed": true, "isAudited": true, "policyId": 3001 } }, { - "name": "table: shipping.shipments, user: proj-user, access: select", + "name": "table: shipping.shipments, user: proj-user, access: select", "request": { "resource": { "elements": { "database": "shipping", "table": "shipments" } }, "accessType": "select", "user": "proj-user", "userGroups": [] @@ -133,7 +133,7 @@ "result": { "datasets": [ "dataset-2" ], "projects": [ "project-1" ], "isAllowed": true, "isAudited": true, "policyId": 3001 } }, { - "name": "table: customers.contact_info, user: proj-user, access: select", + "name": "table: customers.contact_info, user: proj-user, access: select", "request": { "resource": { "elements": { "database": "customers", "table": "contact_info" } }, "accessType": "select", "user": "proj-user", "userGroups": [] @@ -141,7 +141,7 @@ "result": { "datasets": [ "dataset-3" ], "projects": [ "project-2" ], "isAllowed": true, "isAudited": true, "policyId": 3002 } }, { - "name": "table: operations.facilities, user: proj-user, access: select", + "name": "table: operations.facilities, user: proj-user, access: select", "request": { "resource": { "elements": { "database": "operations", "table": "facilities" } }, "accessType": "select", "user": "proj-user", "userGroups": [] @@ -151,7 +151,7 @@ { - "name": "table: sales.prospects, user: scott, access: select", + "name": "table: sales.prospects, user: scott, access: select", "request": { "resource": { "elements": { "database": "sales", "table": "prospects" } }, "accessType": "select", "user": "scott", "userGroups": [] @@ -159,7 +159,7 @@ "result": { "datasets": [ "dataset-1" ], "projects": [ "project-1" ], "isAllowed": false, "isAudited": true, "policyId": -1 } }, { - "name": "table: sales.orders, user: scott, access: select", + "name": "table: sales.orders, user: scott, access: select", "request": { "resource": { "elements": { "database": "sales", "table": "orders" } }, "accessType": "select", "user": "scott", "userGroups": [] @@ -167,7 +167,7 @@ "result": { "datasets": [ "dataset-1" ], "projects": [ "project-1" ], "isAllowed": false, "isAudited": true, "policyId": -1 } }, { - "name": "table: finance.invoices, user: scott, access: select", + "name": "table: finance.invoices, user: scott, access: select", "request": { "resource": { "elements": { "database": "finance", "table": "invoices" } }, "accessType": "select", "user": "scott", "userGroups": [] @@ -175,7 +175,7 @@ "result": { "datasets": [ "dataset-1", "dataset-2" ], "projects": [ "project-1" ], "isAllowed": false, "isAudited": true, "policyId": -1 } }, { - "name": "table: finance.payments, user: scott, access: select", + "name": "table: finance.payments, user: scott, access: select", "request": { "resource": { "elements": { "database": "finance", "table": "payments" } }, "accessType": "select", "user": "scott", "userGroups": [] @@ -183,7 +183,7 @@ "result": { "datasets": [ "dataset-1", "dataset-2" ], "projects": [ "project-1" ], "isAllowed": false, "isAudited": true, "policyId": -1 } }, { - "name": "table: shipping.shipments, user: scott, access: select", + "name": "table: shipping.shipments, user: scott, access: select", "request": { "resource": { "elements": { "database": "shipping", "table": "shipments" } }, "accessType": "select", "user": "scott", "userGroups": [] @@ -191,7 +191,7 @@ "result": { "datasets": [ "dataset-2" ], "projects": [ "project-1" ], "isAllowed": false, "isAudited": true, "policyId": -1 } }, { - "name": "table: customers.contact_info, user: scott, access: select", + "name": "table: customers.contact_info, user: scott, access: select", "request": { "resource": { "elements": { "database": "customers", "table": "contact_info" } }, "accessType": "select", "user": "scott", "userGroups": [] @@ -199,7 +199,7 @@ "result": { "datasets": [ "dataset-3" ], "projects": [ "project-2" ], "isAllowed": false, "isAudited": true, "policyId": -1 } }, { - "name": "table: operations.facilities, user: scott, access: select", + "name": "table: operations.facilities, user: scott, access: select", "request": { "resource": { "elements": { "database": "operations", "table": "facilities" } }, "accessType": "select", "user": "scott", "userGroups": [] @@ -209,7 +209,7 @@ { - "name": "table: operations.facilities, user: scott, access: select", + "name": "table: operations.facilities, user: scott, access: select", "request": { "resource": { "elements": { "database": "operations", "table": "facilities" } }, "accessType": "select", "user": "scott", "userGroups": [] @@ -218,7 +218,7 @@ }, { - "name": "table: operations.facilities, user: ds-user, access: update", + "name": "table: operations.facilities, user: ds-user, access: update", "request": { "resource": { "elements": { "database": "operations", "table": "facilities" } }, "accessType": "update", "user": "ds-user", "userGroups": [] @@ -227,128 +227,269 @@ }, { - "name": "ACLs: database: sales", + "name": "ACLs: database: sales", "request": { "resource": { "elements": { "database": "sales" } } }, - "acls": { } + "acls": { } }, { - "name": "ACLs: table: sales.prospects", + "name": "ACLs: table: sales.prospects", "request": { "resource": { "elements": { "database": "sales", "table": "prospects" } } }, "acls": { "userACLs": { - "ds-user": { "select": { "result": 1, "isFinal": true } }, - "proj-user": { "select": { "result": 1, "isFinal": true } } + "ds-user": { "select": { "result": 1, "isFinal": true } }, + "ds1-user": { "select": { "result": 1, "isFinal": true } }, + "proj-user": { "select": { "result": 1, "isFinal": true } }, + "proj1-user": { "select": { "result": 1, "isFinal": true } } }, "datasets": [ "dataset-1" ], "projects": [ "project-1" ] } }, { - "name": "ACLs: table: sales.orders", + "name": "ACLs: table: sales.orders", "request": { "resource": { "elements": { "database": "sales", "table": "orders" } } }, "acls": { "userACLs": { - "ds-user": { "select": { "result": 1, "isFinal": true } }, - "proj-user": { "select": { "result": 1, "isFinal": true } } + "ds-user": { "select": { "result": 1, "isFinal": true } }, + "ds1-user": { "select": { "result": 1, "isFinal": true } }, + "proj-user": { "select": { "result": 1, "isFinal": true } }, + "proj1-user": { "select": { "result": 1, "isFinal": true } } }, "datasets": [ "dataset-1" ], "projects": [ "project-1" ] } }, { - "name": "ACLs: table: sales.non_existent_table", + "name": "ACLs: table: sales.non_existent_table", "request": { "resource": { "elements": { "database": "sales", "table": "non_existent_table" } } }, - "acls": { } + "acls": { } }, { - "name": "ACLs: column: sales.orders.created_time", + "name": "ACLs: column: sales.orders.created_time", "request": { "resource": { "elements": { "database": "sales", "table": "orders", "column": "created_time" } } }, "acls": { "userACLs": { - "ds-user": { "select": { "result": 1, "isFinal": true } }, - "proj-user": { "select": { "result": 1, "isFinal": true } } + "ds-user": { "select": { "result": 1, "isFinal": true } }, + "ds1-user": { "select": { "result": 1, "isFinal": true } }, + "proj-user": { "select": { "result": 1, "isFinal": true } }, + "proj1-user": { "select": { "result": 1, "isFinal": true } } }, "datasets": [ "dataset-1" ], "projects": [ "project-1" ] } }, { - "name": "ACLs: database: finance", + "name": "ACLs: database: finance", "request": { "resource": { "elements": { "database": "finance" } } }, - "acls": { } + "acls": { } }, { - "name": "ACLs: table: finance.invoices", + "name": "ACLs: table: finance.invoices", "request": { "resource": { "elements": { "database": "finance", "table": "invoices" } } }, "acls": { "userACLs": { - "ds-user": { "select": { "result": 1, "isFinal": true } }, - "proj-user": { "select": { "result": 1, "isFinal": true } } + "ds-user": { "select": { "result": 1, "isFinal": true } }, + "ds1-user": { "select": { "result": 1, "isFinal": true } }, + "ds2-user": { "select": { "result": 1, "isFinal": true } }, + "proj-user": { "select": { "result": 1, "isFinal": true } }, + "proj1-user": { "select": { "result": 1, "isFinal": true } } }, "datasets": [ "dataset-1", "dataset-2" ], "projects": [ "project-1" ] } }, { - "name": "ACLs: table: finance.payments", + "name": "ACLs: table: finance.payments", "request": { "resource": { "elements": { "database": "finance", "table": "payments" } } }, "acls": { "userACLs": { - "ds-user": { "select": { "result": 1, "isFinal": true } }, - "proj-user": { "select": { "result": 1, "isFinal": true } } + "ds-user": { "select": { "result": 1, "isFinal": true } }, + "ds1-user": { "select": { "result": 1, "isFinal": true } }, + "ds2-user": { "select": { "result": 1, "isFinal": true } }, + "proj-user": { "select": { "result": 1, "isFinal": true } }, + "proj1-user": { "select": { "result": 1, "isFinal": true } } }, "datasets": [ "dataset-1", "dataset-2" ], "projects": [ "project-1" ] } }, { - "name": "ACLs: database: shipping", + "name": "ACLs: database: shipping", "request": { "resource": { "elements": { "database": "shipping" } } }, - "acls": { } + "acls": { } }, { - "name": "ACLs: table: shipping.shipments", + "name": "ACLs: table: shipping.shipments", "request": { "resource": { "elements": { "database": "shipping", "table": "shipments" } } }, "acls": { "userACLs": { - "ds-user": { "select": { "result": 1, "isFinal": true } }, - "proj-user": { "select": { "result": 1, "isFinal": true } } + "ds-user": { "select": { "result": 1, "isFinal": true } }, + "ds2-user": { "select": { "result": 1, "isFinal": true } }, + "proj-user": { "select": { "result": 1, "isFinal": true } }, + "proj1-user": { "select": { "result": 1, "isFinal": true } } }, "datasets": [ "dataset-2" ], "projects": [ "project-1" ] } }, { - "name": "ACLs: database: customers", + "name": "ACLs: database: customers", "request": { "resource": { "elements": { "database": "customers" } } }, - "acls": { } + "acls": { } }, { - "name": "ACLs: table: customers.contact_info", + "name": "ACLs: table: customers.contact_info", "request": { "resource": { "elements": { "database": "customers", "table": "contact_info" } } }, "acls": { "userACLs": { - "ds-user": { "select": { "result": 1, "isFinal": true } }, - "proj-user": { "select": { "result": 1, "isFinal": true } } + "ds-user": { "select": { "result": 1, "isFinal": true } }, + "ds3-user": { "select": { "result": 1, "isFinal": true } }, + "proj-user": { "select": { "result": 1, "isFinal": true } }, + "proj2-user": { "select": { "result": 1, "isFinal": true } } }, "datasets": [ "dataset-3" ], "projects": [ "project-2" ] } }, { - "name": "ACLs: database: operations", + "name": "ACLs: database: operations", "request": { "resource": { "elements": { "database": "operations" } } }, - "acls": { } + "acls": { } }, { - "name": "ACLs: table: operations.facilities", + "name": "ACLs: table: operations.facilities", "request": { "resource": { "elements": { "database": "operations", "table": "facilities" } } }, "acls": { "userACLs": { - "ds-user": { "select": { "result": 1, "isFinal": true } } + "ds-user": { "select": { "result": 1, "isFinal": true } }, + "ds4-user": { "select": { "result": 1, "isFinal": true } } }, "datasets": [ "dataset-4" ] } + }, + + { + "name": "Datasets for principals: users[ ds-user ]", + "principals": { "users": [ "ds-user" ] }, + "datasets": [ "dataset-1", "dataset-2", "dataset-3", "dataset-4" ] + }, + { + "name": "Datasets for principals: users[ ds1-user ]", + "principals": { "users": [ "ds1-user" ] }, + "datasets": [ "dataset-1" ] + }, + { + "name": "Datasets for principals: users[ ds2-user ]", + "principals": { "users": [ "ds2-user" ] }, + "datasets": [ "dataset-2" ] + }, + { + "name": "Datasets for principals: users[ ds3-user ]", + "principals": { "users": [ "ds3-user" ] }, + "datasets": [ "dataset-3" ] + }, + { + "name": "Datasets for principals: users[ ds4-user ]", + "principals": { "users": [ "ds4-user" ] }, + "datasets": [ "dataset-4" ] + }, + { + "name": "Datasets for principals: users[ ds1-user, ds4-user ]", + "principals": { "users": [ "ds1-user","ds4-user" ] }, + "datasets": [ "dataset-1", "dataset-4" ] + }, + { + "name": "Projects for principals: users=[ proj-user ]", + "principals:": { "users": [ "proj-user" ] }, + "projects": [ "project-1", "project-2" ] + }, + { + "name": "Projects for principals: users[ proj1-user ]", + "principals": { "users": [ "proj1-user" ] }, + "projects": [ "project-1" ] + }, + { + "name": "Projects for principals: users[ proj2-user ]", + "principals": { "users": [ "proj2-user" ] }, + "projects": [ "project-2" ] + }, + { + "name": "Projects for principals: users[ proj1-user, proj2-user ]", + "principals": { "users": [ "proj1-user", "proj2-user" ] }, + "projects": [ "project-1", "project-2" ] + }, + + { + "name": "Resources for Dataset: id=1", + "datasetId": 1, + "resourceIds": [ 11, 12, 21, 22 ] + }, + { + "name": "Resources for Dataset: id=2", + "datasetId": 2, + "resourceIds": [ 21, 22, 31 ] + }, + { + "name": "Resources for Dataset: id=3", + "datasetId": 3, + "resourceIds": [ 41 ] + }, + { + "name": "Resources for Dataset: id=4", + "datasetId": 4, + "resourceIds": [ 51 ] + }, + { + "name": "Resources for Dataset: id=1234 (non_existent_dataset)", + "datasetId": 1234, + "resourceIds": [ ] + }, + + { + "name": "Resources for Project: id=1", + "projectId": 1, + "resourceIds": [ 11, 12, 21, 22, 31 ] + }, + { + "name": "Resources for Project: id=2", + "projectId": 2, + "resourceIds": [ 41 ] + }, + { + "name": "Resources for Project: id=1234 (non_existent_project)", + "projectId": 1234, + "resourceIds": [ ] + }, + + { + "name": "Resources for DataShare: id=1", + "dataShareId": 1, + "resourceIds": [ 11, 12 ] + }, + { + "name": "Resources for DataShare: id=2", + "dataShareId": 2, + "resourceIds": [ 21, 22 ] + }, + { + "name": "Resources for DataShare: id=3", + "dataShareId": 3, + "resourceIds": [ 31 ] + }, + { + "name": "Resources for DataShare: id=4", + "dataShareId": 4, + "resourceIds": [ 41 ] + }, + { + "name": "Resources for DataShare: id=5", + "dataShareId": 5, + "resourceIds": [ 51 ] + }, + { + "name": "Resources for DataShare: id=1234 (non_existent_data_share)", + "dataShareId": 1234, + "resourceIds": [ ] } ] }