Repository: incubator-ranger Updated Branches: refs/heads/master a50fcf116 -> 164d46fd1
RANGER-873: Ranger policy model update to support data masking Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/164d46fd Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/164d46fd Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/164d46fd Branch: refs/heads/master Commit: 164d46fd188789fdae8f3f1f28e08941a1dc530e Parents: a50fcf1 Author: Madhan Neethiraj <[email protected]> Authored: Wed Mar 30 18:30:11 2016 -0700 Committer: Madhan Neethiraj <[email protected]> Committed: Thu Mar 31 15:18:07 2016 -0700 ---------------------------------------------------------------------- .../ranger/plugin/model/RangerPolicy.java | 2 + .../ranger/plugin/model/RangerServiceDef.java | 115 ++++++++++------- .../model/validation/RangerPolicyValidator.java | 2 +- .../validation/RangerServiceDefHelper.java | 111 ++++++++++------ .../validation/RangerServiceDefValidator.java | 13 +- .../model/validation/RangerValidator.java | 4 +- .../policyengine/RangerPolicyRepository.java | 11 +- .../RangerDefaultPolicyEvaluator.java | 8 +- .../RangerOptimizedPolicyEvaluator.java | 3 +- .../RangerDefaultPolicyResourceMatcher.java | 14 ++- .../RangerPolicyResourceMatcher.java | 3 + .../RangerAbstractResourceMatcher.java | 12 +- .../ranger/plugin/service/RangerBasePlugin.java | 12 ++ .../ranger/plugin/util/ServiceDefUtil.java | 125 +++++++++++++++++++ .../service-defs/ranger-servicedef-hive.json | 80 +++++++++++- .../TestRangerPolicyResourceSignature.java | 6 +- .../validation/TestRangerServiceDefHelper.java | 7 +- .../test_policyengine_hive_masking.json | 26 ++-- .../db/mysql/patches/020-datamask-policy.sql | 28 ++--- .../db/postgres/patches/020-datamask-policy.sql | 97 ++++++++++++++ .../org/apache/ranger/biz/ServiceDBStore.java | 91 +++++++++----- .../java/org/apache/ranger/common/JSONUtil.java | 25 +++- .../apache/ranger/entity/XXAccessTypeDef.java | 22 ++-- .../org/apache/ranger/entity/XXResourceDef.java | 22 ++-- .../service/RangerServiceDefServiceBase.java | 48 ++++++- 25 files changed, 689 insertions(+), 198 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java index 522d130..f022707 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java @@ -43,6 +43,8 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria public static final int POLICY_TYPE_ACCESS = 0; public static final int POLICY_TYPE_DATAMASK = 1; + public static final int[] POLICY_TYPES = new int[] { POLICY_TYPE_ACCESS, POLICY_TYPE_DATAMASK }; + // For future use private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java index 8b919d0..febd85b 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java @@ -1248,6 +1248,28 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S this(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); } + public RangerResourceDef(RangerResourceDef other) { + setItemId(other.getItemId()); + setName(other.getName()); + setType(other.getType()); + setLevel(other.getLevel()); + setParent(other.getParent()); + setMandatory(other.getMandatory()); + setLookupSupported(other.getLookupSupported()); + setRecursiveSupported(other.getRecursiveSupported()); + setExcludesSupported(other.getExcludesSupported()); + setMatcher(other.getMatcher()); + setMatcherOptions(other.getMatcherOptions()); + setValidationRegEx(other.getValidationRegEx()); + setValidationMessage(other.getValidationMessage()); + setUiHint(other.getUiHint()); + setLabel(other.getLabel()); + setDescription(other.getDescription()); + setRbKeyLabel(other.getRbKeyLabel()); + setRbKeyDescription(other.getRbKeyDescription()); + setRbKeyValidationMessage(other.getRbKeyValidationMessage()); + } + public RangerResourceDef(Long itemId, String name, String type, Integer level, String parent, Boolean mandatory, Boolean lookupSupported, Boolean recursiveSupported, Boolean excludesSupported, String matcher, Map<String, String> matcherOptions, String validationRegEx, String validationMessage, String uiHint, String label, String description, String rbKeyLabel, String rbKeyDescription, String rbKeyValidationMessage) { setItemId(itemId); setName(name); @@ -1421,7 +1443,7 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S * @param matcherOptions the matcherOptions to set */ public void setMatcherOptions(Map<String, String> matcherOptions) { - this.matcherOptions = matcherOptions == null ? new HashMap<String, String>() : matcherOptions; + this.matcherOptions = matcherOptions == null ? new HashMap<String, String>() : new HashMap<String, String>(matcherOptions); } /** @@ -1759,6 +1781,7 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S } public RangerAccessTypeDef(RangerAccessTypeDef other) { + this.setItemId(other.getItemId()); this.setName(other.getName()); this.setLabel(other.getLabel()); this.setRbKeyLabel(other.getRbKeyLabel()); @@ -2451,26 +2474,26 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S private static final long serialVersionUID = 1L; private List<RangerDataMaskTypeDef> maskTypes; - private List<String> supportedAccessTypes; - private List<String> supportedResources; + private List<RangerAccessTypeDef> accessTypes; + private List<RangerResourceDef> resources; public RangerDataMaskDef() { setMaskTypes(null); - setSupportedAccessTypes(null); - setSupportedResources(null); + setAccessTypes(null); + setResources(null); } - public RangerDataMaskDef(List<RangerDataMaskTypeDef> maskTypes, List<String> supportedAccessTypes, List<String> supportedResources) { + public RangerDataMaskDef(List<RangerDataMaskTypeDef> maskTypes, List<RangerAccessTypeDef> accessTypes, List<RangerResourceDef> resources) { setMaskTypes(maskTypes); - setSupportedAccessTypes(supportedAccessTypes); - setSupportedResources(supportedResources); + setAccessTypes(accessTypes); + setResources(resources); } public RangerDataMaskDef(RangerDataMaskDef other) { setMaskTypes(other.getMaskTypes()); - setSupportedAccessTypes(other.getSupportedAccessTypes()); - setSupportedResources(other.getSupportedResources()); + setAccessTypes(other.getAccessTypes()); + setResources(other.getResources()); } public List<RangerDataMaskTypeDef> getMaskTypes() { @@ -2495,46 +2518,46 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S } } - public List<String> getSupportedAccessTypes() { - return supportedAccessTypes; + public List<RangerAccessTypeDef> getAccessTypes() { + return accessTypes; } - public void setSupportedAccessTypes(List<String> supportedAccessTypes) { - if(this.supportedAccessTypes == null) { - this.supportedAccessTypes = new ArrayList<String>(); + public void setAccessTypes(List<RangerAccessTypeDef> accessTypes) { + if(this.accessTypes == null) { + this.accessTypes = new ArrayList<RangerAccessTypeDef>(); } - if(this.supportedAccessTypes == supportedAccessTypes) { + if(this.accessTypes == accessTypes) { return; } - this.supportedAccessTypes.clear(); + this.accessTypes.clear(); - if(supportedAccessTypes != null) { - for(String accessType : supportedAccessTypes) { - this.supportedAccessTypes.add(accessType); + if(accessTypes != null) { + for(RangerAccessTypeDef accessType : accessTypes) { + this.accessTypes.add(accessType); } } } - public List<String> getSupportedResources() { - return supportedResources; + public List<RangerResourceDef> getResources() { + return resources; } - public void setSupportedResources(List<String> supportedResources) { - if(this.supportedResources == null) { - this.supportedResources = new ArrayList<String>(); + public void setResources(List<RangerResourceDef> resources) { + if(this.resources == null) { + this.resources = new ArrayList<RangerResourceDef>(); } - if(this.supportedResources == supportedResources) { + if(this.resources == resources) { return; } - this.supportedResources.clear(); + this.resources.clear(); - if(supportedResources != null) { - for(String resource : supportedResources) { - this.supportedResources.add(resource); + if(resources != null) { + for(RangerResourceDef resource : resources) { + this.resources.add(resource); } } } @@ -2561,21 +2584,21 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S } sb.append("} "); - sb.append("supportedAccessTypes={"); - if(supportedAccessTypes != null) { - for(String accessType : supportedAccessTypes) { + sb.append("accessTypes={"); + if(accessTypes != null) { + for(RangerAccessTypeDef accessType : accessTypes) { if(accessType != null) { - sb.append(accessType).append(" "); + accessType.toString(sb).append(" "); } } } sb.append("} "); - sb.append("supportedResources={"); - if(supportedResources != null) { - for(String resource : supportedResources) { + sb.append("resources={"); + if(resources != null) { + for(RangerResourceDef resource : resources) { if(resource != null) { - sb.append(resource).append(" "); + resource.toString(sb).append(" "); } } } @@ -2591,8 +2614,8 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S final int prime = 31; int result = 1; result = prime * result + ((maskTypes == null) ? 0 : maskTypes.hashCode()); - result = prime * result + ((supportedAccessTypes == null) ? 0 : supportedAccessTypes.hashCode()); - result = prime * result + ((supportedResources == null) ? 0 : supportedResources.hashCode()); + result = prime * result + ((accessTypes == null) ? 0 : accessTypes.hashCode()); + result = prime * result + ((resources == null) ? 0 : resources.hashCode()); return result; } @@ -2611,15 +2634,15 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S } else if (other.maskTypes == null || !maskTypes.equals(other.maskTypes)) return false; - if (supportedAccessTypes == null) { - if (other.supportedAccessTypes != null) + if (accessTypes == null) { + if (other.accessTypes != null) return false; - } else if (!supportedAccessTypes.equals(other.supportedAccessTypes)) + } else if (!accessTypes.equals(other.accessTypes)) return false; - if (supportedResources == null) { - if (other.supportedResources != null) + if (resources == null) { + if (other.resources != null) return false; - } else if (!supportedResources.equals(other.supportedResources)) + } else if (!resources.equals(other.resources)) return false; return true; } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java index cab7006..0bdaf87 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java @@ -368,7 +368,7 @@ public class RangerPolicyValidator extends RangerValidator { Set<String> policyResources = getPolicyResources(policy); RangerServiceDefHelper defHelper = new RangerServiceDefHelper(serviceDef); - Set<List<RangerResourceDef>> hierarchies = defHelper.getResourceHierarchies(); // this can be empty but not null! + Set<List<RangerResourceDef>> hierarchies = defHelper.getResourceHierarchies(policy.getPolicyType()); // this can be empty but not null! if (hierarchies.isEmpty()) { LOG.warn("RangerPolicyValidator.isValidResourceNames: serviceDef does not have any resource hierarchies, possibly due to a old/migrated service def! Skipping this check!"); } else { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java ---------------------------------------------------------------------- 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 53df193..101d911 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 @@ -30,9 +30,11 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; @@ -97,18 +99,10 @@ public class RangerServiceDefHelper { * * @return */ - public Set<List<RangerResourceDef>> getResourceHierarchies() { - return _delegate.getResourceHierarchies(); + public Set<List<RangerResourceDef>> getResourceHierarchies(Integer policyType) { + return _delegate.getResourceHierarchies(policyType); } - - /** - * Converts service-def resources from list to a map for constant time lookup - * @return - */ - public Map<String, RangerResourceDef> getResorceMap() { - return _delegate.getResourceMap(); - } - + public Set<String> getMandatoryResourceNames(List<RangerResourceDef> hierarchy) { Set<String> result = new HashSet<String>(hierarchy.size()); for (RangerResourceDef resourceDef : hierarchy) { @@ -144,7 +138,7 @@ public class RangerServiceDefHelper { } return result; } - + public boolean isResourceGraphValid() { return _delegate.isResourceGraphValid(); } @@ -154,30 +148,36 @@ public class RangerServiceDefHelper { */ static class Delegate { - final Set<List<RangerResourceDef>> _hierarchies; + final Map<Integer, Set<List<RangerResourceDef>>> _hierarchies = new HashMap<Integer, Set<List<RangerResourceDef>>>(); final Date _serviceDefFreshnessDate; final String _serviceName; - final Map<String, RangerResourceDef> _resourceMap; final boolean _valid; - - public Delegate(RangerServiceDef serviceDef) { + final static Set<List<RangerResourceDef>> EMPTY_RESOURCE_HIERARCHY = Collections.unmodifiableSet(new HashSet<List<RangerResourceDef>>()); + + public Delegate(RangerServiceDef serviceDef) { // NOTE: we assume serviceDef, its name and update time are can never by null. _serviceName = serviceDef.getName(); _serviceDefFreshnessDate = serviceDef.getUpdateTime(); - // NOTE: we assume resource collection on a service def would never be null - List<RangerResourceDef> resourceDefs = serviceDef.getResources(); - _resourceMap = Collections.unmodifiableMap(getResourcesAsMap(resourceDefs)); - - DirectedGraph graph = createGraph(resourceDefs); - _valid = isValid(graph); - if (_valid) { - Set<List<String>> hierarchies = getHierarchies(graph); - _hierarchies = Collections.unmodifiableSet(convertHierarchies(hierarchies, _resourceMap)); - } else { - _hierarchies = Collections.unmodifiableSet(new HashSet<List<RangerResourceDef>>()); + boolean isValid = true; + for(Integer policyType : RangerPolicy.POLICY_TYPES) { + List<RangerResourceDef> resources = getResourceDefs(serviceDef, policyType); + DirectedGraph graph = createGraph(resources); + + if(graph != null) { + if (isValid(graph)) { + Set<List<String>> hierarchies = getHierarchies(graph); + _hierarchies.put(policyType, Collections.unmodifiableSet(convertHierarchies(hierarchies, getResourcesAsMap(resources)))); + } else { + isValid = false; + _hierarchies.put(policyType, EMPTY_RESOURCE_HIERARCHY); + } + } else { + _hierarchies.put(policyType, EMPTY_RESOURCE_HIERARCHY); + } } + _valid = isValid; if (LOG.isDebugEnabled()) { String message = String.format("Found [%d] resource hierarchies for service [%s] update-date[%s]: %s", _hierarchies.size(), _serviceName, _serviceDefFreshnessDate == null ? null : _serviceDefFreshnessDate.toString(), _hierarchies); @@ -185,12 +185,18 @@ public class RangerServiceDefHelper { } } - public Set<List<RangerResourceDef>> getResourceHierarchies() { - return _hierarchies; - } - - public Map<String, RangerResourceDef> getResourceMap() { - return _resourceMap; + public Set<List<RangerResourceDef>> getResourceHierarchies(Integer policyType) { + if(policyType == null) { + policyType = RangerPolicy.POLICY_TYPE_ACCESS; + } + + Set<List<RangerResourceDef>> ret = _hierarchies.get(policyType); + + if(ret == null) { + ret = EMPTY_RESOURCE_HIERARCHY; + } + + return ret; } public String getServiceName() { @@ -211,21 +217,45 @@ public class RangerServiceDefHelper { * @return */ DirectedGraph createGraph(List<RangerResourceDef> resourceDefs) { - DirectedGraph graph = new DirectedGraph(); - for (RangerResourceDef resourceDef : resourceDefs) { - String name = resourceDef.getName(); - graph.add(name); - String parent = resourceDef.getParent(); - if (StringUtils.isNotEmpty(parent)) { - graph.addArc(parent, name); + DirectedGraph graph = null; + + if(CollectionUtils.isNotEmpty(resourceDefs)) { + graph = new DirectedGraph(); + + for (RangerResourceDef resourceDef : resourceDefs) { + String name = resourceDef.getName(); + + graph.add(name); + String parent = resourceDef.getParent(); + if (StringUtils.isNotEmpty(parent)) { + graph.addArc(parent, name); + } } } + if (LOG.isDebugEnabled()) { LOG.debug("Created graph for resources: " + graph); } return graph; } + List<RangerResourceDef> getResourceDefs(RangerServiceDef serviceDef, Integer policyType) { + final List<RangerResourceDef> resourceDefs; + + if(policyType == null || policyType == RangerPolicy.POLICY_TYPE_ACCESS) { + resourceDefs = serviceDef.getResources(); + } else if(policyType == RangerPolicy.POLICY_TYPE_DATAMASK) { + if(serviceDef.getDataMaskDef() != null) { + resourceDefs = serviceDef.getDataMaskDef().getResources(); + } else { + resourceDefs = null; + } + } else { // unknown policyType; use all resources + resourceDefs = serviceDef.getResources(); + } + + return resourceDefs; + } /** * A valid resource graph is a forest, i.e. a disjoint union of trees. In our case, given that node can have only one "parent" node, we can detect this validity simply by ensuring that * the resource graph has: @@ -249,7 +279,6 @@ public class RangerServiceDefHelper { /** * Returns all valid resource hierarchies for the configured resource-defs. Behavior is undefined if it is called on and invalid graph. Use <code>isValid</code> to check validation first. * - * @param resourceDefs * @param graph * @return */ http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java index 0507fc4..0ed563a 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java @@ -32,6 +32,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ranger.plugin.errors.ValidationErrorCode; +import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef; @@ -496,11 +497,13 @@ public class RangerServiceDefValidator extends RangerValidator { valid = false; } // resource level should be unique within a hierarchy - Set<List<RangerResourceDef>> hierarchies = defHelper.getResourceHierarchies(); - for (List<RangerResourceDef> aHierarchy : hierarchies) { - Set<Integer> levels = new HashSet<Integer>(aHierarchy.size()); - for (RangerResourceDef resourceDef : aHierarchy) { - valid = isUnique(resourceDef.getLevel(), levels, "resource level", "resources", failures) && valid; + for(int policyType : RangerPolicy.POLICY_TYPES) { + Set<List<RangerResourceDef>> hierarchies = defHelper.getResourceHierarchies(policyType); + for (List<RangerResourceDef> aHierarchy : hierarchies) { + Set<Integer> levels = new HashSet<Integer>(aHierarchy.size()); + for (RangerResourceDef resourceDef : aHierarchy) { + valid = isUnique(resourceDef.getLevel(), levels, "resource level", "resources", failures) && valid; + } } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java index 075a374..381864d 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java @@ -292,7 +292,7 @@ public abstract class RangerValidator { Set<String> getAccessTypes(RangerServiceDef serviceDef) { if(LOG.isDebugEnabled()) { - LOG.debug("==> RangerValidator.getSupportedAccessTypes(" + serviceDef + ")"); + LOG.debug("==> RangerValidator.getAccessTypes(" + serviceDef + ")"); } Set<String> accessTypes = new HashSet<String>(); @@ -316,7 +316,7 @@ public abstract class RangerValidator { } if(LOG.isDebugEnabled()) { - LOG.debug("<== RangerValidator.getSupportedAccessTypes(" + serviceDef + "): " + accessTypes); + LOG.debug("<== RangerValidator.getAccessTypes(" + serviceDef + "): " + accessTypes); } return accessTypes; } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java index 4a394d4..b1463bc 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java @@ -32,6 +32,7 @@ import org.apache.ranger.plugin.policyevaluator.RangerOptimizedPolicyEvaluator; import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator; import org.apache.ranger.plugin.store.AbstractServiceStore; import org.apache.ranger.plugin.util.RangerPerfTracer; +import org.apache.ranger.plugin.util.ServiceDefUtil; import org.apache.ranger.plugin.util.ServicePolicies; import java.util.*; @@ -58,7 +59,7 @@ public class RangerPolicyRepository { super(); this.componentServiceName = this.serviceName = servicePolicies.getServiceName(); - this.componentServiceDef = this.serviceDef = servicePolicies.getServiceDef(); + this.componentServiceDef = this.serviceDef = ServiceDefUtil.normalize(servicePolicies.getServiceDef()); this.appId = appId; @@ -91,7 +92,7 @@ public class RangerPolicyRepository { this.serviceName = tagPolicies.getServiceName(); this.componentServiceName = componentServiceName; - this.serviceDef = normalizeAccessTypeDefs(tagPolicies.getServiceDef(), componentServiceDef.getName()); + this.serviceDef = normalizeAccessTypeDefs(ServiceDefUtil.normalize(tagPolicies.getServiceDef()), componentServiceDef.getName()); this.componentServiceDef = componentServiceDef; this.appId = appId; @@ -203,12 +204,14 @@ public class RangerPolicyRepository { normalizeAndPrunePolicyItems(policy.getDenyPolicyItems(), componentType); normalizeAndPrunePolicyItems(policy.getAllowExceptions(), componentType); normalizeAndPrunePolicyItems(policy.getDenyExceptions(), componentType); + normalizeAndPrunePolicyItems(policy.getDataMaskPolicyItems(), componentType); if (!policy.getIsAuditEnabled() && CollectionUtils.isEmpty(policy.getPolicyItems()) && CollectionUtils.isEmpty(policy.getDenyPolicyItems()) && CollectionUtils.isEmpty(policy.getAllowExceptions()) && - CollectionUtils.isEmpty(policy.getDenyExceptions())) { + CollectionUtils.isEmpty(policy.getDenyExceptions()) && + CollectionUtils.isEmpty(policy.getDataMaskPolicyItems())) { if(policiesToPrune == null) { policiesToPrune = new ArrayList<RangerPolicy>(); @@ -226,7 +229,7 @@ public class RangerPolicyRepository { return rangerPolicies; } - private List<RangerPolicy.RangerPolicyItem> normalizeAndPrunePolicyItems(List<RangerPolicy.RangerPolicyItem> policyItems, final String componentType) { + private List<? extends RangerPolicy.RangerPolicyItem> normalizeAndPrunePolicyItems(List<? extends RangerPolicy.RangerPolicyItem> policyItems, final String componentType) { if(CollectionUtils.isNotEmpty(policyItems)) { final String prefix = componentType + AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR; List<RangerPolicy.RangerPolicyItem> itemsToPrune = null; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java ---------------------------------------------------------------------- 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 c48fb72..b87891f 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 @@ -97,7 +97,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator resourceMatcher = new RangerDefaultPolicyResourceMatcher(); resourceMatcher.setServiceDef(serviceDef); - resourceMatcher.setPolicyResources(policy == null ? null : policy.getResources()); + resourceMatcher.setPolicy(policy); resourceMatcher.init(); if(policy != null) { @@ -118,7 +118,10 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator Collections.sort(denyEvaluators); Collections.sort(allowExceptionEvaluators); Collections.sort(denyExceptionEvaluators); + + /* dataMask policyItems must be evaulated in the order given in the policy; hence no sort Collections.sort(dataMaskEvaluators); + */ RangerPerfTracer.log(perf); @@ -536,9 +539,10 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator preprocessPolicyItems(policy.getDenyPolicyItems(), impliedAccessGrants); preprocessPolicyItems(policy.getAllowExceptions(), impliedAccessGrants); preprocessPolicyItems(policy.getDenyExceptions(), impliedAccessGrants); + preprocessPolicyItems(policy.getDataMaskPolicyItems(), impliedAccessGrants); } - private void preprocessPolicyItems(List<RangerPolicyItem> policyItems, Map<String, Collection<String>> impliedAccessGrants) { + private void preprocessPolicyItems(List<? extends RangerPolicyItem> policyItems, Map<String, Collection<String>> impliedAccessGrants) { for(RangerPolicyItem policyItem : policyItems) { if(CollectionUtils.isEmpty(policyItem.getAccesses())) { continue; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java index 710d0c5..2e777ae 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java @@ -74,6 +74,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator preprocessPolicyItems(policy.getDenyPolicyItems()); preprocessPolicyItems(policy.getAllowExceptions()); preprocessPolicyItems(policy.getDenyExceptions()); + preprocessPolicyItems(policy.getDataMaskPolicyItems()); hasAllPerms = checkIfHasAllPerms(); @@ -264,7 +265,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator return ret; } - private void preprocessPolicyItems(List<RangerPolicy.RangerPolicyItem> policyItems) { + private void preprocessPolicyItems(List<? extends RangerPolicy.RangerPolicyItem> policyItems) { if(CollectionUtils.isNotEmpty(policyItems)) { for (RangerPolicy.RangerPolicyItem item : policyItems) { delegateAdmin = delegateAdmin || item.getDelegateAdmin(); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java index 4742850..6ea194d 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java @@ -29,6 +29,7 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; import org.apache.ranger.plugin.model.RangerServiceDef; @@ -42,7 +43,8 @@ import com.google.common.collect.Sets; public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceMatcher { private static final Log LOG = LogFactory.getLog(RangerDefaultPolicyResourceMatcher.class); - protected RangerServiceDef serviceDef = null; + protected RangerServiceDef serviceDef = null; + protected RangerPolicy policy = null; protected Map<String, RangerPolicyResource> policyResources = null; private Map<String, RangerResourceMatcher> matchers = null; @@ -54,6 +56,13 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM } @Override + public void setPolicy(RangerPolicy policy) { + this.policy = policy; + + setPolicyResources(policy == null ? null : policy.getResources()); + } + + @Override public void setPolicyResources(Map<String, RangerPolicyResource> policyResources) { this.policyResources = policyResources; } @@ -71,7 +80,8 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM Set<String> policyResourceKeySet = policyResources.keySet(); RangerServiceDefHelper serviceDefHelper = new RangerServiceDefHelper(serviceDef, false); - Set<List<RangerResourceDef>> validResourceHierarchies = serviceDefHelper.getResourceHierarchies(); + int policyType = policy != null && policy.getPolicyType() != null ? policy.getPolicyType() : RangerPolicy.POLICY_TYPE_ACCESS; + Set<List<RangerResourceDef>> validResourceHierarchies = serviceDefHelper.getResourceHierarchies(policyType); for (List<RangerResourceDef> validResourceHierarchy : validResourceHierarchies) { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java index f743d55..54b9586 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java @@ -21,6 +21,7 @@ package org.apache.ranger.plugin.policyresourcematcher; import java.util.Map; +import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.policyengine.RangerAccessResource; @@ -28,6 +29,8 @@ import org.apache.ranger.plugin.policyengine.RangerAccessResource; public interface RangerPolicyResourceMatcher { void setServiceDef(RangerServiceDef serviceDef); + void setPolicy(RangerPolicy policy); + void setPolicyResources(Map<String, RangerPolicyResource> policyResources); void init(); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java index 5063eea..cd725c9 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java @@ -75,16 +75,18 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat policyIsExcludes = policyResource == null ? false : policyResource.getIsExcludes(); if(policyResource != null && policyResource.getValues() != null) { - boolean isWildCardPresent = !optWildCard; + boolean isWildCardPresent = false; for(String policyValue : policyResource.getValues()) { if(StringUtils.isEmpty(policyValue)) { continue; } - if(StringUtils.containsOnly(policyValue, WILDCARD_ASTERISK)) { - isMatchAny = true; - } else if (!isWildCardPresent && StringUtils.containsAny(policyValue, WILDCARDS)) { - isWildCardPresent = true; + if(optWildCard) { + if (StringUtils.containsOnly(policyValue, WILDCARD_ASTERISK)) { + isMatchAny = true; + } else if (!isWildCardPresent && StringUtils.containsAny(policyValue, WILDCARDS)) { + isWildCardPresent = true; + } } policyValues.add(policyValue); } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java index 1ec88d5..aef7bcb 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java @@ -182,6 +182,18 @@ public class RangerBasePlugin { return null; } + public RangerDataMaskResult evalDataMaskPolicies(RangerAccessRequest request, RangerAccessResultProcessor resultProcessor) { + RangerPolicyEngine policyEngine = this.policyEngine; + + if(policyEngine != null) { + policyEngine.preProcess(request); + + return policyEngine.evalDataMaskPolicies(request, resultProcessor); + } + + return null; + } + public RangerResourceAccessInfo getResourceAccessInfo(RangerAccessRequest request) { RangerPolicyEngine policyEngine = this.policyEngine; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java index 90242da..fa04816 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java @@ -19,11 +19,18 @@ package org.apache.ranger.plugin.util; +import org.apache.commons.collections.ArrayStack; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; import java.util.Map; public class ServiceDefUtil { @@ -40,6 +47,124 @@ public class ServiceDefUtil { return ret; } + public static RangerServiceDef normalize(RangerServiceDef serviceDef) { + normalizeDataMaskDef(serviceDef); + + return serviceDef; + } + + private static void normalizeDataMaskDef(RangerServiceDef serviceDef) { + if(serviceDef != null && serviceDef.getDataMaskDef() != null) { + List<RangerResourceDef> dataMaskResources = serviceDef.getDataMaskDef().getResources(); + List<RangerAccessTypeDef> dataMaskAccessTypes = serviceDef.getDataMaskDef().getAccessTypes(); + + if(CollectionUtils.isNotEmpty(dataMaskResources)) { + List<RangerResourceDef> resources = serviceDef.getResources(); + List<RangerResourceDef> processedDefs = new ArrayList<RangerResourceDef>(dataMaskResources.size()); + + for(RangerResourceDef dataMaskResource : dataMaskResources) { + RangerResourceDef processedDef = dataMaskResource; + + for(RangerResourceDef resourceDef : resources) { + if(StringUtils.equals(resourceDef.getName(), dataMaskResource.getName())) { + processedDef = ServiceDefUtil.mergeResourceDef(resourceDef, dataMaskResource); + break; + } + } + + processedDefs.add(processedDef); + } + + serviceDef.getDataMaskDef().setResources(processedDefs); + } + + if(CollectionUtils.isNotEmpty(dataMaskAccessTypes)) { + List<RangerAccessTypeDef> accessTypes = serviceDef.getAccessTypes(); + List<RangerAccessTypeDef> processedDefs = new ArrayList<RangerAccessTypeDef>(accessTypes.size()); + + for(RangerAccessTypeDef dataMaskAccessType : dataMaskAccessTypes) { + RangerAccessTypeDef processedDef = dataMaskAccessType; + + for(RangerAccessTypeDef accessType : accessTypes) { + if(StringUtils.equals(accessType.getName(), dataMaskAccessType.getName())) { + processedDef = ServiceDefUtil.mergeAccessTypeDef(accessType, dataMaskAccessType); + break; + } + } + + processedDefs.add(processedDef); + } + + serviceDef.getDataMaskDef().setAccessTypes(processedDefs); + } + } + } + + private static RangerResourceDef mergeResourceDef(RangerResourceDef base, RangerResourceDef delta) { + RangerResourceDef ret = new RangerResourceDef(base); + + // retain base values for: itemId, name, type, level, parent, mandatory, lookupSupported + + if(delta.getRecursiveSupported() != null) + ret.setRecursiveSupported(delta.getRecursiveSupported()); + + if(delta.getExcludesSupported() != null) + ret.setExcludesSupported(delta.getExcludesSupported()); + + if(StringUtils.isNotEmpty(delta.getMatcher())) + ret.setMatcher(delta.getMatcher()); + + if(MapUtils.isNotEmpty(delta.getMatcherOptions())) { + if(ret.getMatcherOptions() == null) { + ret.setMatcherOptions(new HashMap<String, String>()); + } + + for(Map.Entry<String, String> e : delta.getMatcherOptions().entrySet()) { + ret.getMatcherOptions().put(e.getKey(), e.getValue()); + } + } + + if(StringUtils.isNotEmpty(delta.getValidationRegEx())) + ret.setValidationRegEx(delta.getValidationRegEx()); + + if(StringUtils.isNotEmpty(delta.getValidationMessage())) + ret.setValidationMessage(delta.getValidationMessage()); + + if(StringUtils.isNotEmpty(delta.getUiHint())) + ret.setUiHint(delta.getUiHint()); + + if(StringUtils.isNotEmpty(delta.getLabel())) + ret.setLabel(delta.getLabel()); + + if(StringUtils.isNotEmpty(delta.getDescription())) + ret.setDescription(delta.getDescription()); + + if(StringUtils.isNotEmpty(delta.getRbKeyLabel())) + ret.setRbKeyLabel(delta.getRbKeyLabel()); + + if(StringUtils.isNotEmpty(delta.getRbKeyDescription())) + ret.setRbKeyDescription(delta.getRbKeyDescription()); + + if(StringUtils.isNotEmpty(delta.getRbKeyValidationMessage())) + ret.setRbKeyValidationMessage(delta.getRbKeyValidationMessage()); + + return ret; + } + + private static RangerAccessTypeDef mergeAccessTypeDef(RangerAccessTypeDef base, RangerAccessTypeDef delta) { + RangerAccessTypeDef ret = new RangerAccessTypeDef(base); + + // retain base values for: itemId, name, impliedGrants + + if(StringUtils.isNotEmpty(delta.getLabel())) + ret.setLabel(delta.getLabel()); + + if(StringUtils.isNotEmpty(delta.getRbKeyLabel())) + ret.setRbKeyLabel(delta.getRbKeyLabel()); + + return ret; + } + private static boolean getBooleanValue(Map<String, String> map, String elementName, boolean defaultValue) { boolean ret = defaultValue; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json ---------------------------------------------------------------------- diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json index b966be9..77167c4 100644 --- a/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json @@ -222,5 +222,83 @@ "label":"Hive Resources Accessed Together?", "description": "List of Hive resources" } - ] + ], + + "dataMaskDef": { + "accessTypes": [ + { + "name": "select" + } + ], + "resources": [ + { + "name": "database", + "matcherOptions": { + "wildCard": "false" + }, + "lookupSupported": true, + "uiHint":"{ \"singleValue\":true }" + }, + { + "name": "table", + "matcherOptions": { + "wildCard": "false" + }, + "lookupSupported": true, + "uiHint":"{ \"singleValue\":true }" + }, + { + "name": "column", + "matcherOptions": { + "wildCard": "false" + }, + "lookupSupported": true, + "uiHint":"{ \"singleValue\":true }" + } + ], + "maskTypes": [ + { + "itemId": 1, + "name": "MASK", + "label": "Mask", + "description": "Replace lowercase with 'x', uppercase with 'X', digits with '0'", + "dataMaskOptions": { } + }, + { + "itemId": 2, + "name": "SHUFFLE", + "label": "Shuffle", + "description": "Shuffle the value of the column", + "dataMaskOptions": { } + }, + { + "itemId": 3, + "name": "MASK_x_SHOW_LAST_4", + "label": "Partial mask: show last 4", + "description": "Show last 4 characters; replace rest with 'x'", + "dataMaskOptions": { } + }, + { + "itemId": 4, + "name": "MASK_x_SHOW_FIRST_4", + "label": "Partial mask: show first 4", + "description": "Show first 4 characters; replace rest with 'x'", + "dataMaskOptions": { } + }, + { + "itemId": 10, + "name": "NULL", + "label": "NULL", + "description": "Replace with NULL", + "dataMaskOptions": { } + }, + { + "itemId": 11, + "name": "NONE", + "label": "No masking", + "description": "No masking", + "dataMaskOptions": { } + } + ] + } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java ---------------------------------------------------------------------- diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java index 7cc2831..8c8c4c0 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java @@ -86,19 +86,19 @@ public class TestRangerPolicyResourceSignature { rangerPolicy = mock(RangerPolicy.class); when(rangerPolicy.getResources()).thenReturn(null); policySerializer = new PolicySerializer(rangerPolicy); - assertFalse("policy.getSupportedResources()==null", policySerializer.isPolicyValidForResourceSignatureComputation()); + assertFalse("policy.getResources()==null", policySerializer.isPolicyValidForResourceSignatureComputation()); // empty resources map is ok! Map<String, RangerPolicyResource> policyResources = new HashMap<String, RangerPolicyResource>(); when(rangerPolicy.getResources()).thenReturn(policyResources); policySerializer = new PolicySerializer(rangerPolicy); - assertTrue("policy.getSupportedResources().isEmpty()", policySerializer.isPolicyValidForResourceSignatureComputation()); + assertTrue("policy.getResources().isEmpty()", policySerializer.isPolicyValidForResourceSignatureComputation()); // but having a resource map with null key is not ok! RangerPolicyResource aPolicyResource = mock(RangerPolicyResource.class); policyResources.put(null, aPolicyResource); policySerializer = new PolicySerializer(rangerPolicy); - assertFalse("policy.getSupportedResources().contains(null)", policySerializer.isPolicyValidForResourceSignatureComputation()); + assertFalse("policy.getResources().contains(null)", policySerializer.isPolicyValidForResourceSignatureComputation()); } @Test http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java ---------------------------------------------------------------------- diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java index d9e50e4..af158b0 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java @@ -31,6 +31,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper.Delegate; @@ -79,7 +80,7 @@ public class TestRangerServiceDefHelper { // now assert the behavior _helper = new RangerServiceDefHelper(_serviceDef); assertTrue(_helper.isResourceGraphValid()); - Set<List<RangerResourceDef>> hierarchies = _helper.getResourceHierarchies(); + Set<List<RangerResourceDef>> hierarchies = _helper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS); // there should be List<RangerResourceDef> hierarchy = Lists.newArrayList(Database, UDF); assertTrue(hierarchies.contains(hierarchy)); @@ -136,7 +137,7 @@ public class TestRangerServiceDefHelper { when(_serviceDef.getResources()).thenReturn(resourceDefs); _helper = new RangerServiceDefHelper(_serviceDef); assertTrue(_helper.isResourceGraphValid()); - Set<List<RangerResourceDef>> hierarchies = _helper.getResourceHierarchies(); + Set<List<RangerResourceDef>> hierarchies = _helper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS); Set<List<String>> expectedHierarchies = new HashSet<List<String>>(); expectedHierarchies.add(Lists.newArrayList("database", "table-space")); @@ -177,7 +178,7 @@ public class TestRangerServiceDefHelper { when(_serviceDef.getResources()).thenReturn(resourceDefs); _helper = new RangerServiceDefHelper(_serviceDef); assertTrue(_helper.isResourceGraphValid()); - Set<List<RangerResourceDef>> hierarchies = _helper.getResourceHierarchies(); + Set<List<RangerResourceDef>> hierarchies = _helper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS); Set<List<String>> expectedHierarchies = new HashSet<List<String>>(); expectedHierarchies.add(Lists.newArrayList("database")); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json ---------------------------------------------------------------------- diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json b/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json index 92b21aa..b0e4557 100644 --- a/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json +++ b/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json @@ -43,16 +43,22 @@ "name": "SHUFFLE", "label": "Shuffle", "description": "Randomly shuffle the contents" + }, + { + "itemId": 10, + "name": "NULL", + "label": "NULL", + "description": "Replace with NULL" } ], - "supportedAccessTypes": [ - "select" + "accessTypes":[ + {"name":"select","label":"Select"} ], - "supportedResources": [ - "database", - "table", - "column" + "resources":[ + {"name":"database","matcherOptions":{"wildCard":false}}, + {"name":"table","matcherOptions":{"wildCard":false}}, + {"name":"column","matcherOptions":{"wildCard":false}} ] } }, @@ -65,7 +71,7 @@ ] }, {"id":101,"name":"db=*, table=*, column=ssn: mask ssn column in all tables, databases","isEnabled":true,"isAuditEnabled":true,"policyType":1, - "resources":{"database":{"values":["*"]},"table":{"values":["*"]},"column":{"values":["ssn"]}}, + "resources":{"database":{"values":["employee"]},"table":{"values":["personal"]},"column":{"values":["ssn"]}}, "dataMaskPolicyItems":[ {"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false, "dataMaskInfo": {"dataMaskType":"MASK"} @@ -76,7 +82,7 @@ ] }, {"id":102,"name":"db=hr, table=*, column=date_of_birth: mask date_of_birth column in all tables in hr database","isEnabled":true,"isAuditEnabled":true,"policyType":1, - "resources":{"database":{"values":["hr"]},"table":{"values":["*"]},"column":{"values":["date_of_birth"]}}, + "resources":{"database":{"values":["hr"]},"table":{"values":["employee"]},"column":{"values":["date_of_birth"]}}, "dataMaskPolicyItems":[ {"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false, "dataMaskInfo": {"dataMaskType":"MASK"} @@ -124,9 +130,9 @@ }, "dataMaskResult":{"maskType":"MASK","maskCondition":null,"maskValue":null,"policyId":102} }, - {"name":"'select date_of_birth from hr.employee2;' for user2 - maskType=SHUFFLE", + {"name":"'select date_of_birth from hr.employee;' for user2 - maskType=SHUFFLE", "request":{ - "resource":{"elements":{"database":"hr", "table":"employee2", "column":"date_of_birth"}}, + "resource":{"elements":{"database":"hr", "table":"employee", "column":"date_of_birth"}}, "accessType":"select","user":"user2","userGroups":[],"requestData":"select date_of_birth from hr.employee2;' for user2" }, "dataMaskResult":{"maskType":"SHUFFLE","maskCondition":null,"maskValue":null,"policyId":102} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/db/mysql/patches/020-datamask-policy.sql ---------------------------------------------------------------------- diff --git a/security-admin/db/mysql/patches/020-datamask-policy.sql b/security-admin/db/mysql/patches/020-datamask-policy.sql index 43d9395..32e8a3e 100644 --- a/security-admin/db/mysql/patches/020-datamask-policy.sql +++ b/security-admin/db/mysql/patches/020-datamask-policy.sql @@ -13,37 +13,37 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -/* add datamasking_supported column in x_access_type_def table if not exist */ -drop procedure if exists add_datamasking_supported_to_x_access_type_def_table; +/* add datamask_options column in x_access_type_def table if not exist */ +drop procedure if exists add_datamask_options_to_x_access_type_def_table; delimiter ;; - create procedure add_datamasking_supported_to_x_access_type_def_table() begin + create procedure add_datamask_options_to_x_access_type_def_table() begin if exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_access_type_def') then - if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_access_type_def' and column_name = 'datamasking_supported') then - ALTER TABLE `x_access_type_def` ADD `datamasking_supported` tinyint NOT NULL DEFAULT 0; + if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_access_type_def' and column_name = 'datamask_options') then + ALTER TABLE `x_access_type_def` ADD `datamask_options` varchar(1024) DEFAULT NULL; end if; end if; end;; delimiter ; -call add_datamasking_supported_to_x_access_type_def_table(); -drop procedure if exists add_datamasking_supported_to_x_access_type_def_table; +call add_datamask_options_to_x_access_type_def_table(); +drop procedure if exists add_datamask_options_to_x_access_type_def_table; -/* add datamasking_supported column in x_resource_def table if not exist */ -drop procedure if exists add_datamasking_supported_to_x_resource_def_table; +/* add datamask_options column in x_resource_def table if not exist */ +drop procedure if exists add_datamask_options_to_x_resource_def_table; delimiter ;; - create procedure add_datamasking_supported_to_x_resource_def_table() begin + create procedure add_datamask_options_to_x_resource_def_table() begin if exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_resource_def') then - if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_resource_def' and column_name = 'datamasking_supported') then - ALTER TABLE `x_resource_def` ADD `datamasking_supported` tinyint NOT NULL DEFAULT 0; + if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_resource_def' and column_name = 'datamask_options') then + ALTER TABLE `x_resource_def` ADD `datamask_options` varchar(1024) DEFAULT NULL; end if; end if; end;; delimiter ; -call add_datamasking_supported_to_x_resource_def_table(); -drop procedure if exists add_datamasking_supported_to_x_resource_def_table; +call add_datamask_options_to_x_resource_def_table(); +drop procedure if exists add_datamask_options_to_x_resource_def_table; DROP TABLE IF EXISTS `x_datamask_type_def`; CREATE TABLE `x_datamask_type_def` ( http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/db/postgres/patches/020-datamask-policy.sql ---------------------------------------------------------------------- diff --git a/security-admin/db/postgres/patches/020-datamask-policy.sql b/security-admin/db/postgres/patches/020-datamask-policy.sql new file mode 100644 index 0000000..4387e02 --- /dev/null +++ b/security-admin/db/postgres/patches/020-datamask-policy.sql @@ -0,0 +1,97 @@ +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +select 'delimiter start'; + +/* add x_access_type_def.datamask_options column if it does not exist */ +CREATE OR REPLACE FUNCTION add_datamask_options_to_x_access_type_def_table() +RETURNS void AS $$ +DECLARE + exists_access_type_def_datamask_options integer := 0; +BEGIN + select count(*) into exists_access_type_def_datamask_options from pg_attribute where attrelid in(select oid from pg_class where relname='x_access_type_def') and attname='datamask_options'; + IF exists_access_type_def_datamask_options = 0 THEN + ALTER TABLE x_access_type_def ADD COLUMN datamask_options VARCHAR(1024) DEFAULT NULL; + END IF; +END; +$$ LANGUAGE plpgsql; + +/* add x_resource_def.datamask_options column if it does not exist */ +CREATE OR REPLACE FUNCTION add_datamask_options_to_x_resource_def_table() +RETURNS void AS $$ +DECLARE + exists_resource_def_datamask_options integer := 0; +BEGIN + select count(*) into exists_resource_def_datamask_options from pg_attribute where attrelid in(select oid from pg_class where relname='x_resource_def') and attname='datamask_options'; + IF exists_resource_def_datamask_options = 0 THEN + ALTER TABLE x_resource_def ADD COLUMN datamask_options VARCHAR(1024) DEFAULT NULL; + END IF; +END; +$$ LANGUAGE plpgsql; + +select 'delimiter end'; + + +SELECT add_datamask_options_to_x_access_type_def_table(); +SELECT add_datamask_options_to_x_resource_def_table(); + +DROP TABLE IF EXISTS x_datamask_type_def; +DROP TABLE IF EXISTS x_policy_item_datamask; +DROP SEQUENCE IF EXISTS x_datamask_type_def_seq; +DROP SEQUENCE IF EXISTS x_policy_item_datamask_def_seq; + +CREATE SEQUENCE x_datamask_type_def_seq; +CREATE TABLE x_datamask_type_def ( + id BIGINT DEFAULT nextval('x_datamask_type_def_seq'::regclass), + guid VARCHAR(1024) DEFAULT NULL, + create_time TIMESTAMP DEFAULT NULL, + update_time TIMESTAMP DEFAULT NULL, + added_by_id BIGINT DEFAULT NULL, + upd_by_id BIGINT DEFAULT NULL, + def_id BIGINT NOT NULL, + item_id BIGINT NOT NULL, + name VARCHAR(1024) NOT NULL, + label VARCHAR(1024) NOT NULL, + description VARCHAR(1024) DEFAULT NULL, + datamask_options VARCHAR(1024) DEFAULT NULL, + rb_key_label VARCHAR(1024) DEFAULT NULL, + rb_key_description VARCHAR(1024) DEFAULT NULL, + sort_order SMALLINT DEFAULT '0', + primary key (id), + CONSTRAINT x_datamask_type_def_FK_def_id FOREIGN KEY (def_id) REFERENCES x_service_def (id) , + CONSTRAINT x_datamask_type_def_FK_added_by_id FOREIGN KEY (added_by_id) REFERENCES x_portal_user (id), + CONSTRAINT x_datamask_type_def_FK_upd_by_id FOREIGN KEY (upd_by_id) REFERENCES x_portal_user (id) +); +CREATE INDEX x_datamask_type_def_IDX_def_id ON x_datamask_type_def(def_id); + +CREATE SEQUENCE x_policy_item_datamask_seq; +CREATE TABLE x_policy_item_datamask ( + id BIGINT DEFAULT nextval('x_policy_item_datamask_seq'::regclass), + guid VARCHAR(1024) DEFAULT NULL, + create_time TIMESTAMP DEFAULT NULL, + update_time TIMESTAMP DEFAULT NULL, + added_by_id BIGINT DEFAULT NULL, + upd_by_id BIGINT DEFAULT NULL, + policy_item_id BIGINT NOT NULL, + type BIGINT NOT NULL, + condition_expr VARCHAR(1024) DEFAULT NULL, + value_expr VARCHAR(1024) DEFAULT NULL, + primary key (id), + CONSTRAINT x_policy_item_datamask_FK_policy_item_id FOREIGN KEY (policy_item_id) REFERENCES x_policy_item (id) , + CONSTRAINT x_policy_item_datamask_FK_type FOREIGN KEY (type) REFERENCES x_datamask_type_def (id), + CONSTRAINT x_policy_item_datamask_FK_added_by_id FOREIGN KEY (added_by_id) REFERENCES x_portal_user (id), + CONSTRAINT x_policy_item_datamask_FK_upd_by_id FOREIGN KEY (upd_by_id) REFERENCES x_portal_user (id) +); +CREATE INDEX x_policy_item_datamask_IDX_policy_item_id ON x_policy_item_datamask(policy_item_id); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java index 77203dc..c4a823c 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java @@ -326,9 +326,9 @@ public class ServiceDBStore extends AbstractServiceStore { } if(dataMaskDef != null) { - List<RangerDataMaskTypeDef> dataMaskTypes = dataMaskDef.getMaskTypes(); - List<String> supportedAccessTypes = dataMaskDef.getSupportedAccessTypes(); - List<String> supportedResources = dataMaskDef.getSupportedResources(); + List<RangerDataMaskTypeDef> dataMaskTypes = dataMaskDef.getMaskTypes(); + List<RangerAccessTypeDef> dataMaskAccessTypes = dataMaskDef.getAccessTypes(); + List<RangerResourceDef> dataMaskResources = dataMaskDef.getResources(); if(CollectionUtils.isNotEmpty(dataMaskTypes)) { XXDataMaskTypeDefDao xxDataMaskDefDao = daoMgr.getXXDataMaskTypeDef(); @@ -343,14 +343,15 @@ public class ServiceDBStore extends AbstractServiceStore { } } - if(CollectionUtils.isNotEmpty(supportedAccessTypes)) { + if(CollectionUtils.isNotEmpty(dataMaskAccessTypes)) { List<XXAccessTypeDef> xxAccessTypeDefs = xxATDDao.findByServiceDefId(xServiceDef.getId()); - for(String accessType : supportedAccessTypes) { + for(RangerAccessTypeDef accessType : dataMaskAccessTypes) { boolean found = false; for(XXAccessTypeDef xxAccessTypeDef : xxAccessTypeDefs) { - if(StringUtils.equals(xxAccessTypeDef.getName(), accessType)) { + if(StringUtils.equals(xxAccessTypeDef.getName(), accessType.getName())) { found = true; + break; } } @@ -362,22 +363,29 @@ public class ServiceDBStore extends AbstractServiceStore { } for(XXAccessTypeDef xxAccessTypeDef : xxAccessTypeDefs) { - boolean isDatamaskingSupported = supportedAccessTypes.contains(xxAccessTypeDef.getName()); + String dataMaskOptions = null; + + for(RangerAccessTypeDef dataMaskAccessType : dataMaskAccessTypes) { + if(StringUtils.equals(dataMaskAccessType.getName(), xxAccessTypeDef.getName())) { + dataMaskOptions = svcDefServiceWithAssignedId.objectToJson(dataMaskAccessType); + break; + } + } - if(xxAccessTypeDef.isDatamaskingSupported() != isDatamaskingSupported) { - xxAccessTypeDef.setDatamaskingSupported(isDatamaskingSupported); + if(! StringUtils.equals(dataMaskOptions, xxAccessTypeDef.getDataMaskOptions())) { + xxAccessTypeDef.setDataMaskOptions(dataMaskOptions); xxATDDao.update(xxAccessTypeDef); } } } - if(CollectionUtils.isNotEmpty(supportedResources)) { + if(CollectionUtils.isNotEmpty(dataMaskResources)) { List<XXResourceDef> xxResourceDefs = xxResDefDao.findByServiceDefId(xServiceDef.getId()); - for(String resource : supportedResources) { + for(RangerResourceDef resource : dataMaskResources) { boolean found = false; for(XXResourceDef xxResourceDef : xxResourceDefs) { - if(StringUtils.equals(xxResourceDef.getName(), resource)) { + if(StringUtils.equals(xxResourceDef.getName(), resource.getName())) { found = true; break; } @@ -390,10 +398,17 @@ public class ServiceDBStore extends AbstractServiceStore { } for(XXResourceDef xxResourceDef : xxResourceDefs) { - boolean isDatamaskingSupported = supportedResources.contains(xxResourceDef.getName()); + String dataMaskOptions = null; + + for(RangerResourceDef dataMaskResource : dataMaskResources) { + if(StringUtils.equals(dataMaskResource.getName(), xxResourceDef.getName())) { + dataMaskOptions = svcDefServiceWithAssignedId.objectToJson(dataMaskResource); + break; + } + } - if(xxResourceDef.isDatamaskingSupported() != isDatamaskingSupported) { - xxResourceDef.setDatamaskingSupported(isDatamaskingSupported); + if(! StringUtils.equals(dataMaskOptions, xxResourceDef.getDataMaskOptions())) { + xxResourceDef.setDataMaskOptions(dataMaskOptions); xxResDefDao.update(xxResourceDef); } } @@ -807,11 +822,11 @@ public class ServiceDBStore extends AbstractServiceStore { } } - List<RangerDataMaskTypeDef> dataMasks = dataMaskDef == null || dataMaskDef.getMaskTypes() == null ? new ArrayList<RangerDataMaskTypeDef>() : dataMaskDef.getMaskTypes(); - List<String> supportedAccessTypes = dataMaskDef == null || dataMaskDef.getSupportedAccessTypes() == null ? new ArrayList<String>() : dataMaskDef.getSupportedAccessTypes(); - List<String> supportedResources = dataMaskDef == null || dataMaskDef.getSupportedResources() == null ? new ArrayList<String>() : dataMaskDef.getSupportedResources(); - XXDataMaskTypeDefDao dataMaskTypeDao = daoMgr.getXXDataMaskTypeDef(); - List<XXDataMaskTypeDef> xxDataMaskTypes = dataMaskTypeDao.findByServiceDefId(serviceDefId); + List<RangerDataMaskTypeDef> dataMasks = dataMaskDef == null || dataMaskDef.getMaskTypes() == null ? new ArrayList<RangerDataMaskTypeDef>() : dataMaskDef.getMaskTypes(); + List<RangerAccessTypeDef> dataMaskAccessTypes = dataMaskDef == null || dataMaskDef.getAccessTypes() == null ? new ArrayList<RangerAccessTypeDef>() : dataMaskDef.getAccessTypes(); + List<RangerResourceDef> dataMaskResources = dataMaskDef == null || dataMaskDef.getResources() == null ? new ArrayList<RangerResourceDef>() : dataMaskDef.getResources(); + XXDataMaskTypeDefDao dataMaskTypeDao = daoMgr.getXXDataMaskTypeDef(); + List<XXDataMaskTypeDef> xxDataMaskTypes = dataMaskTypeDao.findByServiceDefId(serviceDefId); // create or update dataMasks for (RangerServiceDef.RangerDataMaskTypeDef dataMask : dataMasks) { boolean found = false; @@ -861,10 +876,10 @@ public class ServiceDBStore extends AbstractServiceStore { List<XXAccessTypeDef> xxAccessTypeDefs = xxATDDao.findByServiceDefId(serviceDefId); - for(String accessType : supportedAccessTypes) { + for(RangerAccessTypeDef accessType : dataMaskAccessTypes) { boolean found = false; for(XXAccessTypeDef xxAccessTypeDef : xxAccessTypeDefs) { - if(StringUtils.equals(xxAccessTypeDef.getName(), accessType)) { + if(StringUtils.equals(xxAccessTypeDef.getName(), accessType.getName())) { found = true; break; } @@ -877,20 +892,27 @@ public class ServiceDBStore extends AbstractServiceStore { } for(XXAccessTypeDef xxAccessTypeDef : xxAccessTypeDefs) { - boolean isDatamaskingSupported = supportedAccessTypes.contains(xxAccessTypeDef.getName()); + String dataMaskOptions = null; - if(xxAccessTypeDef.isDatamaskingSupported() != isDatamaskingSupported) { - xxAccessTypeDef.setDatamaskingSupported(isDatamaskingSupported); + for(RangerAccessTypeDef dataMaskAccessType : dataMaskAccessTypes) { + if(StringUtils.equals(dataMaskAccessType.getName(), xxAccessTypeDef.getName())) { + dataMaskOptions = svcDefServiceWithAssignedId.objectToJson(dataMaskAccessType); + break; + } + } + + if(! StringUtils.equals(dataMaskOptions, xxAccessTypeDef.getDataMaskOptions())) { + xxAccessTypeDef.setDataMaskOptions(dataMaskOptions); xxATDDao.update(xxAccessTypeDef); } } List<XXResourceDef> xxResourceDefs = xxResDefDao.findByServiceDefId(serviceDefId); - for(String resource : supportedResources) { + for(RangerResourceDef resource : dataMaskResources) { boolean found = false; for(XXResourceDef xxResourceDef : xxResourceDefs) { - if(StringUtils.equals(xxResourceDef.getName(), resource)) { + if(StringUtils.equals(xxResourceDef.getName(), resource.getName())) { found = true; break; } @@ -903,10 +925,17 @@ public class ServiceDBStore extends AbstractServiceStore { } for(XXResourceDef xxResourceDef : xxResourceDefs) { - boolean isDatamaskingSupported = supportedResources.contains(xxResourceDef.getName()); + String dataMaskOptions = null; + + for(RangerResourceDef dataMaskResource : dataMaskResources) { + if(StringUtils.equals(dataMaskResource.getName(), xxResourceDef.getName())) { + dataMaskOptions = svcDefServiceWithAssignedId.objectToJson(dataMaskResource); + break; + } + } - if(xxResourceDef.isDatamaskingSupported() != isDatamaskingSupported) { - xxResourceDef.setDatamaskingSupported(isDatamaskingSupported); + if(! StringUtils.equals(dataMaskOptions, xxResourceDef.getDataMaskOptions())) { + xxResourceDef.setDataMaskOptions(dataMaskOptions); xxResDefDao.update(xxResourceDef); } } @@ -2016,7 +2045,7 @@ public class ServiceDBStore extends AbstractServiceStore { // we need to create one policy for each resource hierarchy RangerServiceDefHelper serviceDefHelper = new RangerServiceDefHelper(serviceDef); int i = 1; - for (List<RangerResourceDef> aHierarchy : serviceDefHelper.getResourceHierarchies()) { + for (List<RangerResourceDef> aHierarchy : serviceDefHelper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS)) { createDefaultPolicy(createdService, vXUser, aHierarchy, i); i++; } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/src/main/java/org/apache/ranger/common/JSONUtil.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/common/JSONUtil.java b/security-admin/src/main/java/org/apache/ranger/common/JSONUtil.java index 38a1659..db4c9c6 100644 --- a/security-admin/src/main/java/org/apache/ranger/common/JSONUtil.java +++ b/security-admin/src/main/java/org/apache/ranger/common/JSONUtil.java @@ -24,6 +24,7 @@ package org.apache.ranger.common; import java.io.File; import java.io.IOException; +import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -34,6 +35,7 @@ import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.ser.StdSerializers; import org.codehaus.jackson.type.TypeReference; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -130,12 +132,12 @@ public class JSONUtil { return jsonString; } - public String writeObjectAsString(ViewBaseBean vObj) { + public String writeObjectAsString(Serializable obj) { ObjectMapper mapper = new ObjectMapper(); String jsonStr; try { - jsonStr = mapper.writeValueAsString(vObj); + jsonStr = mapper.writeValueAsString(obj); return jsonStr; } catch (JsonParseException e) { throw restErrorUtil.createRESTException( @@ -151,5 +153,22 @@ public class JSONUtil { MessageEnums.INVALID_INPUT_DATA); } } - + + public <T> T writeJsonToJavaObject(String json, Class<T> tClass) { + ObjectMapper mapper = new ObjectMapper(); + + try { + return mapper.readValue(json, tClass); + } catch (JsonParseException e) { + throw restErrorUtil.createRESTException("Invalid input data: " + e.getMessage(), + MessageEnums.INVALID_INPUT_DATA); + } catch (JsonMappingException e) { + throw restErrorUtil.createRESTException("Invalid input data: " + e.getMessage(), + MessageEnums.INVALID_INPUT_DATA); + } catch (IOException e) { + throw restErrorUtil.createRESTException("Invalid input data: " + e.getMessage(), + MessageEnums.INVALID_INPUT_DATA); + } + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/src/main/java/org/apache/ranger/entity/XXAccessTypeDef.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXAccessTypeDef.java b/security-admin/src/main/java/org/apache/ranger/entity/XXAccessTypeDef.java index 62b11ce..5bc22e0 100644 --- a/security-admin/src/main/java/org/apache/ranger/entity/XXAccessTypeDef.java +++ b/security-admin/src/main/java/org/apache/ranger/entity/XXAccessTypeDef.java @@ -94,13 +94,13 @@ public class XXAccessTypeDef extends XXDBBase implements java.io.Serializable { protected Integer order; /** - * datamaskingSupported of the XXAccessTypeDef + * dataMaskOptions of the XXAccessTypeDef * <ul> * </ul> * */ - @Column(name = "datamasking_supported") - protected boolean datamaskingSupported; + @Column(name = "datamask_options") + protected String dataMaskOptions; /** * This method sets the value to the member attribute <b> id</b> . You @@ -242,12 +242,12 @@ public class XXAccessTypeDef extends XXDBBase implements java.io.Serializable { return this.order; } - public boolean isDatamaskingSupported() { - return datamaskingSupported; + public String getDataMaskOptions() { + return dataMaskOptions; } - public void setDatamaskingSupported(boolean datamaskingSupported) { - this.datamaskingSupported = datamaskingSupported; + public void setDataMaskOptions(String dataMaskOptions) { + this.dataMaskOptions = dataMaskOptions; } /* @@ -319,7 +319,11 @@ public class XXAccessTypeDef extends XXDBBase implements java.io.Serializable { } else if (!rbKeyLabel.equals(other.rbKeyLabel)) { return false; } - if (datamaskingSupported != other.datamaskingSupported) { + if (dataMaskOptions == null) { + if (other.dataMaskOptions != null) { + return false; + } + } else if (!dataMaskOptions.equals(other.dataMaskOptions)) { return false; } return true; @@ -334,7 +338,7 @@ public class XXAccessTypeDef extends XXDBBase implements java.io.Serializable { public String toString() { return "XXAccessTypeDef [" + super.toString() + " id=" + id + ", defId=" + defId + ", itemId=" + itemId + ", name=" + name + ", label=" + label - + ", rbKeyLabel=" + rbKeyLabel + ", datamaskingSupported=" + datamaskingSupported + ", order=" + order + "]"; + + ", rbKeyLabel=" + rbKeyLabel + ", dataMaskOptions=" + dataMaskOptions + ", order=" + order + "]"; } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/src/main/java/org/apache/ranger/entity/XXResourceDef.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXResourceDef.java b/security-admin/src/main/java/org/apache/ranger/entity/XXResourceDef.java index 8a2b6e0..6679c35 100644 --- a/security-admin/src/main/java/org/apache/ranger/entity/XXResourceDef.java +++ b/security-admin/src/main/java/org/apache/ranger/entity/XXResourceDef.java @@ -229,13 +229,13 @@ public class XXResourceDef extends XXDBBase implements java.io.Serializable { protected Integer order; /** - * datamaskingSupported of the XXResourceDef + * dataMaskOptions of the XXResourceDef * <ul> * </ul> * */ - @Column(name = "datamasking_supported") - protected boolean datamaskingSupported; + @Column(name = "datamask_options") + protected String dataMaskOptions; /** * This method sets the value to the member attribute <b> id</b> . You @@ -653,12 +653,12 @@ public class XXResourceDef extends XXDBBase implements java.io.Serializable { return this.order; } - public boolean isDatamaskingSupported() { - return datamaskingSupported; + public String getDataMaskOptions() { + return dataMaskOptions; } - public void setDatamaskingSupported(boolean datamaskingSupported) { - this.datamaskingSupported = datamaskingSupported; + public void setDataMaskOptions(String dataMaskOptions) { + this.dataMaskOptions = dataMaskOptions; } /* @@ -796,7 +796,11 @@ public class XXResourceDef extends XXDBBase implements java.io.Serializable { } else if (!type.equals(other.type)) { return false; } - if (datamaskingSupported != other.datamaskingSupported) { + if (dataMaskOptions == null) { + if (other.dataMaskOptions != null) { + return false; + } + } else if (!dataMaskOptions.equals(other.dataMaskOptions)) { return false; } return true; @@ -824,7 +828,7 @@ public class XXResourceDef extends XXDBBase implements java.io.Serializable { + ", rbKeyDescription=" + rbKeyDescription + ", rbKeyValidationMessage=" + rbKeyValidationMessage + ", order=" + order - + ", datamaskingSupported=" + datamaskingSupported + + ", dataMaskOptions=" + dataMaskOptions + "]"; } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java index 7a172d4..9e2e9f5 100644 --- a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java @@ -17,6 +17,7 @@ package org.apache.ranger.service; +import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -45,6 +46,7 @@ import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef; import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.plugin.util.ServiceDefUtil; import org.apache.ranger.view.RangerServiceDefList; import org.springframework.beans.factory.annotation.Autowired; @@ -156,24 +158,30 @@ public abstract class RangerServiceDefServiceBase<T extends XXServiceDefBase, V if (!stringUtil.isEmpty(xResources)) { for (XXResourceDef xResource : xResources) { - if (xResource.isDatamaskingSupported()) { - dataMaskDef.getSupportedResources().add(xResource.getName()); + if (StringUtils.isNotEmpty(xResource.getDataMaskOptions())) { + RangerResourceDef dataMaskResource = jsonToObject(xResource.getDataMaskOptions(), RangerResourceDef.class); + + dataMaskDef.getResources().add(dataMaskResource); } } } if (!stringUtil.isEmpty(xAccessTypes)) { for (XXAccessTypeDef xAtd : xAccessTypes) { - if(xAtd.isDatamaskingSupported()) { - dataMaskDef.getSupportedAccessTypes().add(xAtd.getName()); + if(StringUtils.isNotEmpty(xAtd.getDataMaskOptions())) { + RangerAccessTypeDef dataMaskAccessType = jsonToObject(xAtd.getDataMaskOptions(), RangerAccessTypeDef.class); + + dataMaskDef.getAccessTypes().add(dataMaskAccessType); } } } serviceDef.setDataMaskDef(dataMaskDef); + ServiceDefUtil.normalize(serviceDef); + return serviceDef; } - + @SuppressWarnings("unchecked") @Override protected XXServiceDefBase mapViewToEntityBean(RangerServiceDef vObj, XXServiceDefBase xObj, int operationContext) { @@ -537,7 +545,7 @@ public abstract class RangerServiceDefServiceBase<T extends XXServiceDefBase, V retList.setResultSize(onePageList.size()); retList.setTotalCount(xxObjList.size()); } - + private String mapToJsonString(Map<String, String> map) { String ret = null; @@ -585,4 +593,32 @@ public abstract class RangerServiceDefServiceBase<T extends XXServiceDefBase, V return ret; } + + public String objectToJson(Serializable obj) { + String ret = null; + + if(obj != null) { + try { + ret = jsonUtil.writeObjectAsString(obj); + } catch(Exception excp) { + LOG.warn("objectToJson() failed to convert object to json: " + obj, excp); + } + } + + return ret; + } + + public <T> T jsonToObject(String jsonStr, Class<T> clz) { + T ret = null; + + if(StringUtils.isNotEmpty(jsonStr)) { + try { + ret = jsonUtil.writeJsonToJavaObject(jsonStr, clz); + } catch(Exception excp) { + LOG.warn("jsonToObject() failed to convert json to object: " + jsonStr, excp); + } + } + + return ret; + } }
