RANGER-873: Ranger policy model 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/d242dd6e Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/d242dd6e Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/d242dd6e Branch: refs/heads/master Commit: d242dd6e9dea78586393e6a50b47944652502eb1 Parents: ca84cf7 Author: Madhan Neethiraj <[email protected]> Authored: Tue Mar 15 18:36:58 2016 -0700 Committer: Madhan Neethiraj <[email protected]> Committed: Tue Mar 22 16:43:50 2016 -0700 ---------------------------------------------------------------------- .../plugin/errors/ValidationErrorCode.java | 2 + .../ranger/plugin/model/RangerPolicy.java | 222 ++++++++- .../model/RangerPolicyResourceSignature.java | 2 +- .../ranger/plugin/model/RangerServiceDef.java | 443 +++++++++++++++++- .../model/validation/RangerPolicyValidator.java | 35 +- .../model/validation/RangerValidator.java | 4 +- .../policyengine/RangerDataMaskResult.java | 113 +++++ .../plugin/policyengine/RangerPolicyEngine.java | 1 + .../policyengine/RangerPolicyEngineImpl.java | 35 ++ .../policyengine/RangerPolicyRepository.java | 26 +- .../RangerDataMaskPolicyItemEvaluator.java | 34 ++ ...angerDefaultDataMaskPolicyItemEvaluator.java | 61 +++ .../RangerDefaultPolicyEvaluator.java | 118 ++++- .../policyevaluator/RangerPolicyEvaluator.java | 3 + .../RangerPolicyItemEvaluator.java | 1 + .../TestRangerPolicyResourceSignature.java | 6 +- .../validation/TestRangerPolicyValidator.java | 51 ++- .../plugin/policyengine/TestPolicyEngine.java | 33 +- .../test_policyengine_hive_masking.json | 150 ++++++ .../test_policyengine_tag_hive.json | 2 +- .../test_policyengine_tag_hive_filebased.json | 2 +- .../db/mysql/patches/020-datamask-policy.sql | 94 ++++ .../ranger/biz/RangerPolicyRetriever.java | 105 +++-- .../org/apache/ranger/biz/ServiceDBStore.java | 454 +++++++++++++------ .../org/apache/ranger/common/AppConstants.java | 10 +- .../apache/ranger/db/RangerDaoManagerBase.java | 20 +- .../apache/ranger/db/XXDataMaskTypeDefDao.java | 62 +++ .../ranger/db/XXPolicyItemDataMaskInfoDao.java | 85 ++++ .../apache/ranger/entity/XXAccessTypeDef.java | 22 +- .../apache/ranger/entity/XXDataMaskTypeDef.java | 403 ++++++++++++++++ .../ranger/entity/XXPolicyItemDataMaskInfo.java | 282 ++++++++++++ .../org/apache/ranger/entity/XXResourceDef.java | 24 +- .../ranger/service/RangerPolicyServiceBase.java | 4 +- .../service/RangerServiceDefServiceBase.java | 80 +++- .../resources/META-INF/jpa_named_queries.xml | 35 ++ .../apache/ranger/biz/TestServiceDBStore.java | 68 +-- .../service/TestRangerServiceDefService.java | 44 +- 37 files changed, 2859 insertions(+), 277 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java b/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java index 72f7205..6ac82f5 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java @@ -87,6 +87,8 @@ public enum ValidationErrorCode { POLICY_VALIDATION_ERR_POLICY_ITEM_ACCESS_TYPE_DENY(3023, "Currently deny access types are not supported. Access type is set to deny."), POLICY_VALIDATION_ERR_INVALID_RESOURCE_NO_COMPATIBLE_HIERARCHY_SINGLE(3024, "Invalid resources specified. {0} policy can specify values for the following resources: {1}"), POLICY_VALIDATION_ERR_INVALID_RESOURCE_MISSING_MANDATORY_SINGLE(3025, "Invalid resources specified. {0} policy must specify values for the following resources: {1}"), + POLICY_VALIDATION_ERR_POLICY_UPDATE_MOVE_SERVICE_NOT_ALLOWED(3026, "attempt to move policy id={0} from service={1} to service={2} is not allowed"), + POLICY_VALIDATION_ERR_POLICY_TYPE_CHANGE_NOT_ALLOWED(3027, "attempt to change type of policy id={0} from type={1} to type={2} is not allowed"), ; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/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 7354dfe..522d130 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 @@ -40,6 +40,8 @@ import org.codehaus.jackson.map.annotate.JsonSerialize; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class RangerPolicy extends RangerBaseModelObject implements java.io.Serializable { + public static final int POLICY_TYPE_ACCESS = 0; + public static final int POLICY_TYPE_DATAMASK = 1; // For future use private static final long serialVersionUID = 1L; @@ -55,6 +57,7 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria private List<RangerPolicyItem> denyPolicyItems = null; private List<RangerPolicyItem> allowExceptions = null; private List<RangerPolicyItem> denyExceptions = null; + private List<RangerDataMaskPolicyItem> dataMaskPolicyItems = null; /** @@ -87,6 +90,7 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria setDenyPolicyItems(null); setAllowExceptions(null); setDenyExceptions(null); + setDataMaskPolicyItems(null); } /** @@ -106,6 +110,8 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria setDenyPolicyItems(other.getDenyPolicyItems()); setAllowExceptions(other.getAllowExceptions()); setDenyExceptions(other.getDenyExceptions()); + setDataMaskPolicyItems(other.getDataMaskPolicyItems()); + } /** @@ -332,6 +338,28 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria } } + public List<RangerDataMaskPolicyItem> getDataMaskPolicyItems() { + return dataMaskPolicyItems; + } + + public void setDataMaskPolicyItems(List<RangerDataMaskPolicyItem> dataMaskPolicyItems) { + if(this.dataMaskPolicyItems == null) { + this.dataMaskPolicyItems = new ArrayList<RangerDataMaskPolicyItem>(); + } + + if(this.dataMaskPolicyItems == dataMaskPolicyItems) { + return; + } + + this.dataMaskPolicyItems.clear(); + + if(dataMaskPolicyItems != null) { + for(RangerDataMaskPolicyItem dataMaskPolicyItem : dataMaskPolicyItems) { + this.dataMaskPolicyItems.add(dataMaskPolicyItem); + } + } + } + @Override public String toString( ) { StringBuilder sb = new StringBuilder(); @@ -834,8 +862,95 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria } else if (!users.equals(other.users)) return false; return true; + + } + } + + @JsonAutoDetect(fieldVisibility=Visibility.ANY) + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown=true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataMaskPolicyItem extends RangerPolicyItem implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private RangerPolicyItemDataMaskInfo dataMaskInfo = null; + + public RangerDataMaskPolicyItem() { + this(null, null, null, null, null, null); + } + + public RangerDataMaskPolicyItem(List<RangerPolicyItemAccess> accesses, RangerPolicyItemDataMaskInfo dataMaskDetail, List<String> users, List<String> groups, List<RangerPolicyItemCondition> conditions, Boolean delegateAdmin) { + super(accesses, users, groups, conditions, delegateAdmin); + + setDataMaskInfo(dataMaskDetail); + } + + /** + * @return the dataMaskInfo + */ + public RangerPolicyItemDataMaskInfo getDataMaskInfo() { + return dataMaskInfo; + } + + /** + * @param dataMaskInfo the dataMaskInfo to set + */ + public void setDataMaskInfo(RangerPolicyItemDataMaskInfo dataMaskInfo) { + this.dataMaskInfo = dataMaskInfo; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((dataMaskInfo == null) ? 0 : dataMaskInfo.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if(! super.equals(obj)) + return false; + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerDataMaskPolicyItem other = (RangerDataMaskPolicyItem) obj; + if (dataMaskInfo == null) { + if (other.dataMaskInfo != null) + return false; + } else if (!dataMaskInfo.equals(other.dataMaskInfo)) + return false; + return true; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDataMaskPolicyItem={"); + + super.toString(sb); + + sb.append("dataMaskInfo={"); + if(dataMaskInfo != null) { + dataMaskInfo.toString(sb); + } + sb.append("} "); + + sb.append("}"); + + return sb; } - } @JsonAutoDetect(fieldVisibility=Visibility.ANY) @@ -1061,4 +1176,109 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria } } + + @JsonAutoDetect(fieldVisibility=Visibility.ANY) + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown=true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerPolicyItemDataMaskInfo implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String dataMaskType = null; + private String conditionExpr = null; + private String valueExpr = null; + + public RangerPolicyItemDataMaskInfo() { } + + public RangerPolicyItemDataMaskInfo(String dataMaskType, String conditionExpr, String valueExpr) { + setDataMaskType(dataMaskType); + setConditionExpr(conditionExpr); + setValueExpr(valueExpr); + } + + public String getDataMaskType() { + return dataMaskType; + } + + public void setDataMaskType(String dataMaskType) { + this.dataMaskType = dataMaskType; + } + + public String getConditionExpr() { + return conditionExpr; + } + + public void setConditionExpr(String conditionExpr) { + this.conditionExpr = conditionExpr; + } + + public String getValueExpr() { + return valueExpr; + } + + public void setValueExpr(String valueExpr) { + this.valueExpr = valueExpr; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((dataMaskType == null) ? 0 : dataMaskType.hashCode()); + result = prime * result + ((conditionExpr == null) ? 0 : conditionExpr.hashCode()); + result = prime * result + ((valueExpr == null) ? 0 : valueExpr.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if(! super.equals(obj)) + return false; + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerPolicyItemDataMaskInfo other = (RangerPolicyItemDataMaskInfo) obj; + if (dataMaskType == null) { + if (other.dataMaskType != null) + return false; + } else if (!dataMaskType.equals(other.dataMaskType)) + return false; + if (conditionExpr == null) { + if (other.conditionExpr != null) + return false; + } else if (!conditionExpr.equals(other.conditionExpr)) + return false; + if (valueExpr == null) { + if (other.valueExpr != null) + return false; + } else if (!valueExpr.equals(other.valueExpr)) + return false; + return true; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerPolicyItemDataMaskInfo={"); + + sb.append("dataMaskType={").append(dataMaskType).append("} "); + sb.append("conditionExpr={").append(conditionExpr).append("} "); + sb.append("valueExpr={").append(valueExpr).append("} "); + + sb.append("}"); + + return sb; + } + } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java index 76d853a..c12d62d 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java @@ -125,7 +125,7 @@ public class RangerPolicyResourceSignature { if (!isPolicyValidForResourceSignatureComputation()) { return ""; } - int type = 0; + int type = RangerPolicy.POLICY_TYPE_ACCESS; if (_policy.getPolicyType() != null) { type = _policy.getPolicyType(); } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/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 f66839e..cec12b6 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 @@ -58,14 +58,19 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S private List<RangerPolicyConditionDef> policyConditions = null; private List<RangerContextEnricherDef> contextEnrichers = null; private List<RangerEnumDef> enums = null; + private RangerDataMaskDef dataMaskDef = null; public RangerServiceDef() { - this(null, null, null, null, null, null, null, null, null, null, null); + this(null, null, null, null, null, null, null, null, null, null, null, null); + } + + public RangerServiceDef(String name, String implClass, String label, String description, Map<String, String> options, List<RangerServiceConfigDef> configs, List<RangerResourceDef> resources, List<RangerAccessTypeDef> accessTypes, List<RangerPolicyConditionDef> policyConditions, List<RangerContextEnricherDef> contextEnrichers, List<RangerEnumDef> enums) { + this(name, implClass, label, description, options, configs, resources, accessTypes, policyConditions, contextEnrichers, enums, null); } /** - * @param type + * @param name * @param implClass * @param label * @param description @@ -75,9 +80,10 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S * @param accessTypes * @param policyConditions * @param contextEnrichers + * @param dataMaskDef * @param enums */ - public RangerServiceDef(String name, String implClass, String label, String description, Map<String, String> options, List<RangerServiceConfigDef> configs, List<RangerResourceDef> resources, List<RangerAccessTypeDef> accessTypes, List<RangerPolicyConditionDef> policyConditions, List<RangerContextEnricherDef> contextEnrichers, List<RangerEnumDef> enums) { + public RangerServiceDef(String name, String implClass, String label, String description, Map<String, String> options, List<RangerServiceConfigDef> configs, List<RangerResourceDef> resources, List<RangerAccessTypeDef> accessTypes, List<RangerPolicyConditionDef> policyConditions, List<RangerContextEnricherDef> contextEnrichers, List<RangerEnumDef> enums, RangerDataMaskDef dataMaskDef) { super(); setName(name); @@ -91,6 +97,7 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S setPolicyConditions(policyConditions); setContextEnrichers(contextEnrichers); setEnums(enums); + setDataMaskDef(dataMaskDef); } /** @@ -108,6 +115,7 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S setAccessTypes(other.getAccessTypes()); setPolicyConditions(other.getPolicyConditions()); setEnums(other.getEnums()); + setDataMaskDef(other.getDataMaskDef()); } /** @@ -388,6 +396,14 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S } } + public RangerDataMaskDef getDataMaskDef() { + return dataMaskDef; + } + + public void setDataMaskDef(RangerDataMaskDef dataMaskDef) { + this.dataMaskDef = dataMaskDef == null ? new RangerDataMaskDef() : dataMaskDef; + } + @Override public String toString( ) { StringBuilder sb = new StringBuilder(); @@ -477,6 +493,12 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S } sb.append("} "); + sb.append("dataMaskDef={"); + if(dataMaskDef != null) { + dataMaskDef.toString(sb); + } + sb.append("} "); + sb.append("}"); return sb; @@ -892,14 +914,14 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S } /** - * @return the type + * @return the subType */ public String getSubType() { return subType; } /** - * @param type the type to set + * @param subType the subType to set */ public void setSubType(String subType) { this.subType = subType; @@ -1389,14 +1411,14 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S } /** - * @return the matcher + * @return the matcherOptions */ public Map<String, String> getMatcherOptions() { return matcherOptions; } /** - * @param matcher the matcher to set + * @param matcherOptions the matcherOptions to set */ public void setMatcherOptions(Map<String, String> matcherOptions) { this.matcherOptions = matcherOptions == null ? new HashMap<String, String>() : matcherOptions; @@ -2000,14 +2022,14 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S } /** - * @return the evaluator + * @return the evaluatorOptions */ public Map<String, String> getEvaluatorOptions() { return evaluatorOptions; } /** - * @param evaluator the evaluator to set + * @param evaluatorOptions the evaluatorOptions to set */ public void setEvaluatorOptions(Map<String, String> evaluatorOptions) { this.evaluatorOptions = evaluatorOptions == null ? new HashMap<String, String>() : evaluatorOptions; @@ -2336,14 +2358,14 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S } /** - * @return the evaluator + * @return the enricherOptions */ public Map<String, String> getEnricherOptions() { return enricherOptions; } /** - * @param evaluator the evaluator to set + * @param enricherOptions the enricherOptions to set */ public void setEnricherOptions(Map<String, String> enricherOptions) { this.enricherOptions = enricherOptions == null ? new HashMap<String, String>() : enricherOptions; @@ -2417,4 +2439,403 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S return true; } } + + + + @JsonAutoDetect(fieldVisibility=Visibility.ANY) + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown=true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataMaskDef { + private List<RangerDataMaskTypeDef> maskTypes; + private List<String> supportedAccessTypes; + private List<String> supportedResources; + + + public RangerDataMaskDef() { + setMaskTypes(null); + setSupportedAccessTypes(null); + setSupportedResources(null); + } + + public RangerDataMaskDef(List<RangerDataMaskTypeDef> maskTypes, List<String> supportedAccessTypes, List<String> supportedResources) { + setMaskTypes(maskTypes); + setSupportedAccessTypes(supportedAccessTypes); + setSupportedResources(supportedResources); + } + + public RangerDataMaskDef(RangerDataMaskDef other) { + setMaskTypes(other.getMaskTypes()); + setSupportedAccessTypes(other.getSupportedAccessTypes()); + setSupportedResources(other.getSupportedResources()); + } + + public List<RangerDataMaskTypeDef> getMaskTypes() { + return maskTypes; + } + + public void setMaskTypes(List<RangerDataMaskTypeDef> maskTypes) { + if(this.maskTypes == null) { + this.maskTypes = new ArrayList<RangerDataMaskTypeDef>(); + } + + if(this.maskTypes == maskTypes) { + return; + } + + this.maskTypes.clear(); + + if(maskTypes != null) { + for(RangerDataMaskTypeDef maskType : maskTypes) { + this.maskTypes.add(maskType); + } + } + } + + public List<String> getSupportedAccessTypes() { + return supportedAccessTypes; + } + + public void setSupportedAccessTypes(List<String> supportedAccessTypes) { + if(this.supportedAccessTypes == null) { + this.supportedAccessTypes = new ArrayList<String>(); + } + + if(this.supportedAccessTypes == supportedAccessTypes) { + return; + } + + this.supportedAccessTypes.clear(); + + if(supportedAccessTypes != null) { + for(String accessType : supportedAccessTypes) { + this.supportedAccessTypes.add(accessType); + } + } + } + + public List<String> getSupportedResources() { + return supportedResources; + } + + public void setSupportedResources(List<String> supportedResources) { + if(this.supportedResources == null) { + this.supportedResources = new ArrayList<String>(); + } + + if(this.supportedResources == supportedResources) { + return; + } + + this.supportedResources.clear(); + + if(supportedResources != null) { + for(String resource : supportedResources) { + this.supportedResources.add(resource); + } + } + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDataMaskDef={"); + + sb.append("maskTypes={"); + if(maskTypes != null) { + for(RangerDataMaskTypeDef maskType : maskTypes) { + if(maskType != null) { + sb.append(maskType).append(" "); + } + } + } + sb.append("} "); + + sb.append("supportedAccessTypes={"); + if(supportedAccessTypes != null) { + for(String accessType : supportedAccessTypes) { + if(accessType != null) { + sb.append(accessType).append(" "); + } + } + } + sb.append("} "); + + sb.append("supportedResources={"); + if(supportedResources != null) { + for(String resource : supportedResources) { + if(resource != null) { + sb.append(resource).append(" "); + } + } + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + 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()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerDataMaskDef other = (RangerDataMaskDef) obj; + if (maskTypes == null) { + if (other.maskTypes != null) + return false; + } else if (other.maskTypes == null || !maskTypes.equals(other.maskTypes)) + return false; + + if (supportedAccessTypes == null) { + if (other.supportedAccessTypes != null) + return false; + } else if (!supportedAccessTypes.equals(other.supportedAccessTypes)) + return false; + if (supportedResources == null) { + if (other.supportedResources != null) + return false; + } else if (!supportedResources.equals(other.supportedResources)) + return false; + return true; + } + } + + @JsonAutoDetect(fieldVisibility=Visibility.ANY) + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown=true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataMaskTypeDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long itemId = null; + private String name = null; + private String label = null; + private String description = null; + private Map<String, String> dataMaskOptions = null; + private String rbKeyLabel = null; + private String rbKeyDescription = null; + + + public RangerDataMaskTypeDef() { + this(null, null, null, null, null, null, null); + } + + public RangerDataMaskTypeDef(Long itemId, String name, String label, String description, Map<String, String> dataMaskOptions, String rbKeyLabel, String rbKeyDescription) { + setItemId(itemId); + setName(name); + setLabel(label); + setDescription(description); + setDataMaskOptions(dataMaskOptions); + setRbKeyLabel(rbKeyLabel); + setRbKeyDescription(rbKeyDescription); + } + + public RangerDataMaskTypeDef(RangerDataMaskTypeDef other) { + setItemId(other.getItemId()); + setName(other.getName()); + setLabel(other.getLabel()); + setDescription(other.getDescription()); + setDataMaskOptions(other.getDataMaskOptions()); + setRbKeyLabel(other.getRbKeyLabel()); + setRbKeyDescription(other.getRbKeyDescription()); + } + + /** + * @return the itemId + */ + public Long getItemId() { + return itemId; + } + + /** + * @param itemId the itemId to set + */ + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * @param label the label to set + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @return the dataMaskOptions + */ + public Map<String, String> getDataMaskOptions() { + return dataMaskOptions; + } + + /** + * @param dataMaskOptions the dataMaskOptions to set + */ + public void setDataMaskOptions(Map<String, String> dataMaskOptions) { + this.dataMaskOptions = dataMaskOptions == null ? new HashMap<String, String>() : dataMaskOptions; + } + + /** + * @return the rbKeyLabel + */ + public String getRbKeyLabel() { + return rbKeyLabel; + } + + /** + * @param rbKeyLabel the rbKeyLabel to set + */ + public void setRbKeyLabel(String rbKeyLabel) { + this.rbKeyLabel = rbKeyLabel; + } + + /** + * @return the rbKeyDescription + */ + public String getRbKeyDescription() { + return rbKeyDescription; + } + + /** + * @param rbKeyDescription the rbKeyDescription to set + */ + public void setRbKeyDescription(String rbKeyDescription) { + this.rbKeyDescription = rbKeyDescription; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDataMaskTypeDef={"); + sb.append("itemId={").append(itemId).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("label={").append(label).append("} "); + sb.append("description={").append(description).append("} "); + sb.append("dataMaskOptions={").append(dataMaskOptions).append("} "); + sb.append("rbKeyLabel={").append(rbKeyLabel).append("} "); + sb.append("rbKeyDescription={").append(rbKeyDescription).append("} "); + + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((itemId == null) ? 0 : itemId.hashCode()); + result = prime * result + + ((dataMaskOptions == null) ? 0 : dataMaskOptions.hashCode()); + result = prime * result + ((label == null) ? 0 : label.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((rbKeyLabel == null) ? 0 : rbKeyLabel.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerDataMaskTypeDef other = (RangerDataMaskTypeDef) obj; + if (itemId == null) { + if (other.itemId != null) + return false; + } else if (other.itemId == null || !itemId.equals(other.itemId)) + return false; + + if (dataMaskOptions == null) { + if (other.dataMaskOptions != null) + return false; + } else if (!dataMaskOptions.equals(other.dataMaskOptions)) + return false; + if (label == null) { + if (other.label != null) + return false; + } else if (!label.equals(other.label)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (rbKeyLabel == null) { + if (other.rbKeyLabel != null) + return false; + } else if (!rbKeyLabel.equals(other.rbKeyLabel)) + return false; + return true; + } + } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/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 307606f..d354ac7 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 @@ -121,6 +121,8 @@ public class RangerPolicyValidator extends RangerValidator { valid = false; } else { Long id = policy.getId(); + RangerPolicy existingPolicy = null; + if (action == Action.UPDATE) { // id is ignored for CREATE if (id == null) { ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_MISSING_FIELD; @@ -131,7 +133,11 @@ public class RangerPolicyValidator extends RangerValidator { .errorCode(error.getErrorCode()) .build()); valid = false; - } else if (getPolicy(id) == null) { + } + + existingPolicy = getPolicy(id); + + if (existingPolicy == null) { ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_INVALID_POLICY_ID; failures.add(new ValidationFailureDetailsBuilder() .field("id") @@ -213,6 +219,33 @@ public class RangerPolicyValidator extends RangerValidator { } } + if(existingPolicy != null) { + if(! StringUtils.equalsIgnoreCase(existingPolicy.getService(), policy.getService())) { + ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_POLICY_UPDATE_MOVE_SERVICE_NOT_ALLOWED; + failures.add(new ValidationFailureDetailsBuilder() + .field("service name") + .isSemanticallyIncorrect() + .becauseOf(error.getMessage(policy.getId(), existingPolicy.getService(), policy.getService())) + .errorCode(error.getErrorCode()) + .build()); + valid = false; + } + + int existingPolicyType = existingPolicy.getPolicyType() == null ? RangerPolicy.POLICY_TYPE_ACCESS : existingPolicy.getPolicyType(); + int policyType = policy.getPolicyType() == null ? RangerPolicy.POLICY_TYPE_ACCESS : policy.getPolicyType(); + + if(existingPolicyType != policyType) { + ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_POLICY_TYPE_CHANGE_NOT_ALLOWED; + failures.add(new ValidationFailureDetailsBuilder() + .field("policy type") + .isSemanticallyIncorrect() + .becauseOf(error.getMessage(policy.getId(), existingPolicyType, policyType)) + .errorCode(error.getErrorCode()) + .build()); + valid = false; + } + } + boolean isAuditEnabled = getIsAuditEnabled(policy); String serviceDefName = null; RangerServiceDef serviceDef = null; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/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 381864d..075a374 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.getAccessTypes(" + serviceDef + ")"); + LOG.debug("==> RangerValidator.getSupportedAccessTypes(" + serviceDef + ")"); } Set<String> accessTypes = new HashSet<String>(); @@ -316,7 +316,7 @@ public abstract class RangerValidator { } if(LOG.isDebugEnabled()) { - LOG.debug("<== RangerValidator.getAccessTypes(" + serviceDef + "): " + accessTypes); + LOG.debug("<== RangerValidator.getSupportedAccessTypes(" + serviceDef + "): " + accessTypes); } return accessTypes; } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java new file mode 100644 index 0000000..66d8eba --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerDataMaskResult.java @@ -0,0 +1,113 @@ +/* + * 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. + */ +package org.apache.ranger.plugin.policyengine; + +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; +import org.apache.ranger.plugin.model.RangerServiceDef; + + +public class RangerDataMaskResult extends RangerAccessResult { + private String maskType = null; + private String maskCondition = null; + private String maskedValue = null; + + + public RangerDataMaskResult(final String serviceName, final RangerServiceDef serviceDef, final RangerAccessRequest request) { + this(serviceName, serviceDef, request, null); + } + + public RangerDataMaskResult(final String serviceName, final RangerServiceDef serviceDef, final RangerAccessRequest request, final RangerPolicyItemDataMaskInfo dataMaskInfo) { + super(serviceName, serviceDef, request); + + if(dataMaskInfo != null) { + setMaskType(dataMaskInfo.getDataMaskType()); + setMaskCondition(dataMaskInfo.getConditionExpr()); + setMaskedValue(dataMaskInfo.getValueExpr()); + } + } + + /** + * @return the maskType + */ + public String getMaskType() { + return maskType; + } + + /** + * @param maskType the maskType to set + */ + public void setMaskType(String maskType) { + this.maskType = maskType; + } + + /** + * @return the maskCondition + */ + public String getMaskCondition() { + return maskCondition; + } + + /** + * @param maskCondition the maskCondition to set + */ + public void setMaskCondition(String maskCondition) { + this.maskCondition = maskCondition; + } + + /** + * @return the maskedValue + */ + public String getMaskedValue() { + return maskedValue; + } + /** + * @param maskedValue the maskedValue to set + */ + public void setMaskedValue(String maskedValue) { + this.maskedValue = maskedValue; + } + + public boolean isMaskEnabled() { + return StringUtils.isNotEmpty(this.getMaskType()); + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDataMaskResult={"); + + super.toString(sb); + + sb.append("maskType={").append(maskType).append("} "); + sb.append("maskCondition={").append(maskCondition).append("} "); + sb.append("maskedValue={").append(maskedValue).append("} "); + + sb.append("}"); + + return sb; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java index 02ad9e9..64870d9 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java @@ -49,6 +49,7 @@ public interface RangerPolicyEngine { Collection<RangerAccessResult> isAccessAllowed(Collection<RangerAccessRequest> requests, RangerAccessResultProcessor resultProcessor); + RangerDataMaskResult evalDataMaskPolicies(RangerAccessRequest request, RangerAccessResultProcessor resultProcessor); boolean isAccessAllowed(RangerAccessResource resource, String user, Set<String> userGroups, String accessType); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java index 92481f6..9e817d7 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java @@ -276,6 +276,41 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { } @Override + public RangerDataMaskResult evalDataMaskPolicies(RangerAccessRequest request, RangerAccessResultProcessor resultProcessor) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.evalDataMaskPolicies(" + request + ")"); + } + + RangerDataMaskResult ret = new RangerDataMaskResult(getServiceName(), getServiceDef(), request); + + if(request != null) { + List<RangerPolicyEvaluator> evaluators = policyRepository.getDataMaskPolicyEvaluators(); + for (RangerPolicyEvaluator evaluator : evaluators) { + evaluator.evaluate(request, ret); + + if (ret.getIsAccessDetermined() && ret.getIsAuditedDetermined()) { + break; + } + } + } + + // no need to audit if filter/mask is not enabled + if(! ret.isMaskEnabled()) { + ret.setIsAudited(false); + } + + if (resultProcessor != null) { + resultProcessor.processResult(ret); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.evalDataMaskPolicies(" + request + "): " + ret); + } + + return ret; + } + + @Override public boolean isAccessAllowed(RangerAccessResource resource, String user, Set<String> userGroups, String accessType) { if (LOG.isDebugEnabled()) { LOG.debug("==> RangerPolicyEngineImpl.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + accessType + ")"); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/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 d39dd52..4a394d4 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 @@ -48,6 +48,7 @@ public class RangerPolicyRepository { private final long policyVersion; private List<RangerContextEnricher> contextEnrichers; private List<RangerPolicyEvaluator> policyEvaluators; + private List<RangerPolicyEvaluator> dataMaskPolicyEvaluators; private final Map<String, Boolean> accessAuditCache; private final String componentServiceName; @@ -127,6 +128,10 @@ public class RangerPolicyRepository { return policyEvaluators; } + public List<RangerPolicyEvaluator> getDataMaskPolicyEvaluators() { + return dataMaskPolicyEvaluators; + } + private RangerServiceDef normalizeAccessTypeDefs(RangerServiceDef serviceDef, final String componentType) { if (serviceDef != null && StringUtils.isNotBlank(componentType)) { @@ -309,6 +314,7 @@ public class RangerPolicyRepository { private void init(RangerPolicyEngineOptions options) { List<RangerPolicyEvaluator> policyEvaluators = new ArrayList<RangerPolicyEvaluator>(); + List<RangerPolicyEvaluator> dataMaskPolicyEvaluators = new ArrayList<RangerPolicyEvaluator>(); for (RangerPolicy policy : policies) { if (skipBuildingPolicyEvaluator(policy, options)) { @@ -318,12 +324,21 @@ public class RangerPolicyRepository { RangerPolicyEvaluator evaluator = buildPolicyEvaluator(policy, serviceDef, options); if (evaluator != null) { - policyEvaluators.add(evaluator); + if(policy.getPolicyType() == null || policy.getPolicyType() == RangerPolicy.POLICY_TYPE_ACCESS) { + policyEvaluators.add(evaluator); + } else if(policy.getPolicyType() == RangerPolicy.POLICY_TYPE_DATAMASK) { + dataMaskPolicyEvaluators.add(evaluator); + } else { + LOG.warn("RangerPolicyEngine: ignoring policy id=" + policy.getId() + " - invalid policyType '" + policy.getPolicyType() + "'"); + } } } Collections.sort(policyEvaluators); this.policyEvaluators = Collections.unmodifiableList(policyEvaluators); + Collections.sort(dataMaskPolicyEvaluators); + this.dataMaskPolicyEvaluators = Collections.unmodifiableList(dataMaskPolicyEvaluators); + List<RangerContextEnricher> contextEnrichers = new ArrayList<RangerContextEnricher>(); if (CollectionUtils.isNotEmpty(this.policyEvaluators)) { if (!options.disableContextEnrichers && !CollectionUtils.isEmpty(serviceDef.getContextEnrichers())) { @@ -351,6 +366,15 @@ public class RangerPolicyRepository { LOG.debug("policy evaluation order: #" + (++order) + " - policy id=" + policy.getId() + "; name=" + policy.getName() + "; evalOrder=" + policyEvaluator.getEvalOrder()); } + + LOG.debug("datamasking policy evaluation order: " + this.dataMaskPolicyEvaluators.size() + " policies"); + + order = 0; + for(RangerPolicyEvaluator policyEvaluator : this.dataMaskPolicyEvaluators) { + RangerPolicy policy = policyEvaluator.getPolicy(); + + LOG.debug("datamasking policy evaluation order: #" + (++order) + " - policy id=" + policy.getId() + "; name=" + policy.getName() + "; evalOrder=" + policyEvaluator.getEvalOrder()); + } } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDataMaskPolicyItemEvaluator.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDataMaskPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDataMaskPolicyItemEvaluator.java new file mode 100644 index 0000000..62d624c --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDataMaskPolicyItemEvaluator.java @@ -0,0 +1,34 @@ +/* + * 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. + */ +package org.apache.ranger.plugin.policyevaluator; + +import org.apache.ranger.plugin.model.RangerPolicy.RangerDataMaskPolicyItem; + + +public interface RangerDataMaskPolicyItemEvaluator extends RangerPolicyItemEvaluator { + void init(); + + RangerDataMaskPolicyItem getPolicyItem(); + + String getMaskType(); + + String getMaskCondition(); + + String getMaskedValue(); +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java new file mode 100644 index 0000000..4583de9 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java @@ -0,0 +1,61 @@ +/* + * 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. + */ +package org.apache.ranger.plugin.policyevaluator; + + + +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerPolicy.RangerDataMaskPolicyItem; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; +import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; + + +public class RangerDefaultDataMaskPolicyItemEvaluator extends RangerDefaultPolicyItemEvaluator implements RangerDataMaskPolicyItemEvaluator { + + public RangerDefaultDataMaskPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerDataMaskPolicyItem policyItem, int policyItemIndex, RangerPolicyEngineOptions options) { + super(serviceDef, policy, policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DATA_MASKING, policyItemIndex, options); + } + + @Override + public RangerDataMaskPolicyItem getPolicyItem() { + return (RangerDataMaskPolicyItem)policyItem; + } + + @Override + public String getMaskType() { + RangerPolicyItemDataMaskInfo dataMaskInfo = getPolicyItem().getDataMaskInfo(); + + return dataMaskInfo != null ? dataMaskInfo.getDataMaskType() : null; + } + + @Override + public String getMaskCondition() { + RangerPolicyItemDataMaskInfo dataMaskInfo = getPolicyItem().getDataMaskInfo(); + + return dataMaskInfo != null ? dataMaskInfo.getConditionExpr() : null; + } + + @Override + public String getMaskedValue() { + RangerPolicyItemDataMaskInfo dataMaskInfo = getPolicyItem().getDataMaskInfo(); + + return dataMaskInfo != null ? dataMaskInfo.getValueExpr() : null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/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 1fa8644..2ce3a54 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 @@ -33,6 +33,7 @@ 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.RangerDataMaskPolicyItem; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; @@ -41,6 +42,7 @@ import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.policyengine.RangerAccessResource; import org.apache.ranger.plugin.policyengine.RangerAccessResult; +import org.apache.ranger.plugin.policyengine.RangerDataMaskResult; import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; import org.apache.ranger.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher; import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher; @@ -60,6 +62,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator private List<RangerPolicyItemEvaluator> allowExceptionEvaluators = null; private List<RangerPolicyItemEvaluator> denyExceptionEvaluators = null; private int customConditionsCount = 0; + private List<RangerDataMaskPolicyItemEvaluator> dataMaskEvaluators = null; private String perfTag; @Override @@ -101,17 +104,20 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator denyEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY); allowExceptionEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS); denyExceptionEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS); + dataMaskEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, policy.getDataMaskPolicyItems()); } else { allowEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); denyEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); allowExceptionEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); denyExceptionEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); + dataMaskEvaluators = Collections.<RangerDataMaskPolicyItemEvaluator>emptyList(); } Collections.sort(allowEvaluators); Collections.sort(denyEvaluators); Collections.sort(allowExceptionEvaluators); Collections.sort(denyExceptionEvaluators); + Collections.sort(dataMaskEvaluators); RangerPerfTracer.log(perf); @@ -587,7 +593,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator return ret; } - private RangerPolicyItemEvaluator getMatchingPolicyItem(RangerAccessRequest request, List<RangerPolicyItemEvaluator> evaluators, List<RangerPolicyItemEvaluator> exceptionEvaluators) { + private RangerPolicyItemEvaluator getMatchingPolicyItem(RangerAccessRequest request, List<? extends RangerPolicyItemEvaluator> evaluators, List<? extends RangerPolicyItemEvaluator> exceptionEvaluators) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + request + ")"); } @@ -678,4 +684,114 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator return ret; } + + @Override + public void evaluate(RangerAccessRequest request, RangerDataMaskResult result) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.evaluate(" + request + ", " + result + ")"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.evaluate(requestHashCode=" + Integer.toHexString(System.identityHashCode(request)) + "," + perfTag + ")"); + } + + if (request != null && result != null && CollectionUtils.isNotEmpty(dataMaskEvaluators)) { + boolean isResourceMatchAttempted = false; + boolean isResourceMatch = false; + + if (!result.getIsAuditedDetermined()) { + if (!isResourceMatchAttempted) { + isResourceMatch = isMatch(request.getResource()); + isResourceMatchAttempted = true; + } + + if (isResourceMatch) { + if (isAuditEnabled()) { + result.setIsAudited(true); + } + } + } + + if (!result.getIsAccessDetermined()) { + if (!isResourceMatchAttempted) { + isResourceMatch = isMatch(request.getResource()); + isResourceMatchAttempted = true; + } + + if (isResourceMatch) { + evaluatePolicyItems(request, result); + } + } + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.evaluate(" + request + ", " + result + ")"); + } + } + + protected void evaluatePolicyItems(RangerAccessRequest request, RangerDataMaskResult result) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.evaluatePolicyItems(" + request + ", " + result + ")"); + } + + RangerDataMaskPolicyItemEvaluator matchedPolicyItem = getMatchingPolicyItem(request, dataMaskEvaluators); + + if(matchedPolicyItem != null) { + RangerPolicy policy = getPolicy(); + + result.setIsAllowed(true); + result.setIsAccessDetermined(true); + + result.setMaskType(matchedPolicyItem.getMaskType()); + result.setMaskCondition(matchedPolicyItem.getMaskCondition()); + result.setMaskedValue(matchedPolicyItem.getMaskedValue()); + result.setPolicyId(policy.getId()); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.evaluatePolicyItems(" + request + ", " + result + ", " + ")"); + } + } + + protected RangerDataMaskPolicyItemEvaluator getMatchingPolicyItem(RangerAccessRequest request, List<RangerDataMaskPolicyItemEvaluator> evaluators) { + RangerDataMaskPolicyItemEvaluator ret = null; + + RangerPolicyItemEvaluator policyItem = getMatchingPolicyItem(request, dataMaskEvaluators, null); + + if(policyItem != null) { + ret = (RangerDataMaskPolicyItemEvaluator)policyItem; + } + + return ret; + } + + private List<RangerDataMaskPolicyItemEvaluator> createPolicyItemEvaluators(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options, List<RangerDataMaskPolicyItem> policyItems) { + List<RangerDataMaskPolicyItemEvaluator> ret = null; + + if(CollectionUtils.isNotEmpty(policyItems)) { + ret = new ArrayList<RangerDataMaskPolicyItemEvaluator>(); + + int policyItemCounter = 1; + + for(RangerDataMaskPolicyItem policyItem : policyItems) { + RangerDataMaskPolicyItemEvaluator itemEvaluator = new RangerDefaultDataMaskPolicyItemEvaluator(serviceDef, policy, policyItem, policyItemCounter++, options); + + itemEvaluator.init(); + + ret.add(itemEvaluator); + + if(CollectionUtils.isNotEmpty(itemEvaluator.getConditionEvaluators())) { + customConditionsCount += itemEvaluator.getConditionEvaluators().size(); + } + } + } else { + ret = Collections.<RangerDataMaskPolicyItemEvaluator>emptyList(); + } + + return ret; + } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java ---------------------------------------------------------------------- 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 3f76755..3c73082 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 @@ -29,6 +29,7 @@ import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.policyengine.RangerAccessResult; import org.apache.ranger.plugin.policyengine.RangerAccessResource; +import org.apache.ranger.plugin.policyengine.RangerDataMaskResult; import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; public interface RangerPolicyEvaluator extends Comparable<RangerPolicyEvaluator> { @@ -54,6 +55,8 @@ public interface RangerPolicyEvaluator extends Comparable<RangerPolicyEvaluator> void evaluate(RangerAccessRequest request, RangerAccessResult result); + void evaluate(RangerAccessRequest request, RangerDataMaskResult result); + boolean isMatch(RangerAccessResource resource); boolean isCompleteMatch(RangerAccessResource resource); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java index 1dfc8cf..9ac2f93 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java @@ -30,6 +30,7 @@ public interface RangerPolicyItemEvaluator extends Comparable<RangerPolicyItemEv public static final int POLICY_ITEM_TYPE_DENY = 1; public static final int POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS = 2; public static final int POLICY_ITEM_TYPE_DENY_EXCEPTIONS = 3; + public static final int POLICY_ITEM_TYPE_DATA_MASKING = 4; void init(); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/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 8c8c4c0..7cc2831 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.getResources()==null", policySerializer.isPolicyValidForResourceSignatureComputation()); + assertFalse("policy.getSupportedResources()==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.getResources().isEmpty()", policySerializer.isPolicyValidForResourceSignatureComputation()); + assertTrue("policy.getSupportedResources().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.getResources().contains(null)", policySerializer.isPolicyValidForResourceSignatureComputation()); + assertFalse("policy.getSupportedResources().contains(null)", policySerializer.isPolicyValidForResourceSignatureComputation()); } @Test http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java ---------------------------------------------------------------------- diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java index e0f3b0e..c757a0b 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java @@ -179,7 +179,51 @@ public class TestRangerPolicyValidator { _failures.clear(); assertTrue(_validator.isValid(3L, Action.DELETE, _failures)); assertTrue(_failures.isEmpty()); } - + + @Test + public final void testIsValid_errorPaths() throws Exception { + boolean isAdmin = true; + + // 1. create policy in a non-existing service + Action action = Action.CREATE; + when(_policy.getService()).thenReturn("non-existing-service-name"); + when(_store.getServiceByName("non-existing-service-name")).thenReturn(null); + + assertFalse(action.toString(), _validator.isValid(_policy, action, isAdmin, _failures)); + + // 2. update a policy to change the service-name + RangerPolicy existingPolicy = mock(RangerPolicy.class); + when(existingPolicy.getId()).thenReturn(8L); + when(existingPolicy.getService()).thenReturn("service-name"); + + RangerService service = mock(RangerService.class); + when(service.getType()).thenReturn("service-type"); + when(service.getName()).thenReturn("service-name"); + when(_store.getServiceByName("service-name")).thenReturn(service); + + RangerService service2 = mock(RangerService.class); + when(service2.getType()).thenReturn("service-type"); + when(service2.getName()).thenReturn("service-name2"); + when(_store.getServiceByName("service-name2")).thenReturn(service2); + + when(_policy.getService()).thenReturn("service-name2"); + when(_store.getServiceByName("service-name2")).thenReturn(service2); + action = Action.UPDATE; + + assertFalse(action.toString(), _validator.isValid(_policy, action, isAdmin, _failures)); + + // 3. update a policy to change the policy-type + when(existingPolicy.getId()).thenReturn(8L); + when(existingPolicy.getService()).thenReturn("service-name"); + when(existingPolicy.getPolicyType()).thenReturn(Integer.valueOf(0)); + + when(_policy.getId()).thenReturn(8L); + when(_policy.getService()).thenReturn("service-name"); + when(_policy.getPolicyType()).thenReturn(Integer.valueOf(1)); + + assertFalse(action.toString(), _validator.isValid(_policy, action, isAdmin, _failures)); + } + @Test public final void testIsValid_happyPath() throws Exception { // valid policy has valid non-empty name and service name @@ -196,14 +240,15 @@ public class TestRangerPolicyValidator { when(_store.getPolicy(7L)).thenReturn(null); RangerPolicy existingPolicy = mock(RangerPolicy.class); when(existingPolicy.getId()).thenReturn(8L); + when(existingPolicy.getService()).thenReturn("service-name"); when(_store.getPolicy(8L)).thenReturn(existingPolicy); SearchFilter createFilter = new SearchFilter(); - createFilter.setParam(SearchFilter.POLICY_NAME, "service-type"); + createFilter.setParam(SearchFilter.SERVICE_TYPE, "service-type"); createFilter.setParam(SearchFilter.POLICY_NAME, "policy-name-1"); // this name would be used for create when(_store.getPolicies(createFilter)).thenReturn(new ArrayList<RangerPolicy>()); // a matching policy should not exist for update. SearchFilter updateFilter = new SearchFilter(); - updateFilter.setParam(SearchFilter.POLICY_NAME, "service-type"); + updateFilter.setParam(SearchFilter.SERVICE_TYPE, "service-type"); updateFilter.setParam(SearchFilter.POLICY_NAME, "policy-name-2"); // this name would be used for update List<RangerPolicy> existingPolicies = new ArrayList<RangerPolicy>(); existingPolicies.add(existingPolicy); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java ---------------------------------------------------------------------- diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java index f9ba62b..cd81836 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java @@ -194,6 +194,13 @@ public class TestPolicyEngine { runTestsFromResourceFiles(conditionsTestResourceFiles); } + @Test + public void testPolicyEngine_hiveMasking() { + String[] resourceFiles = { "/policyengine/test_policyengine_hive_masking.json" }; + + runTestsFromResourceFiles(resourceFiles); + } + private void runTestsFromResourceFiles(String[] resourceNames) { for(String resourceName : resourceNames) { InputStream inStream = this.getClass().getResourceAsStream(resourceName); @@ -303,15 +310,28 @@ public class TestPolicyEngine { policyEngine.preProcess(request); } - RangerAccessResult expected = test.result; RangerAccessResultProcessor auditHandler = new RangerDefaultAuditHandler(); - RangerAccessResult result = policyEngine.isAccessAllowed(request, auditHandler); + if(test.result != null) { + RangerAccessResult expected = test.result; + RangerAccessResult result = policyEngine.isAccessAllowed(request, auditHandler); - assertNotNull("result was null! - " + test.name, result); - assertEquals("isAllowed mismatched! - " + test.name, expected.getIsAllowed(), result.getIsAllowed()); - assertEquals("isAudited mismatched! - " + test.name, expected.getIsAudited(), result.getIsAudited()); - assertEquals("policyId mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId()); + assertNotNull("result was null! - " + test.name, result); + assertEquals("isAllowed mismatched! - " + test.name, expected.getIsAllowed(), result.getIsAllowed()); + assertEquals("isAudited mismatched! - " + test.name, expected.getIsAudited(), result.getIsAudited()); + assertEquals("policyId mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId()); + } + + if(test.dataMaskResult != null) { + RangerDataMaskResult expected = test.dataMaskResult; + RangerDataMaskResult result = policyEngine.evalDataMaskPolicies(request, auditHandler); + + assertNotNull("result was null! - " + test.name, result); + assertEquals("maskType mismatched! - " + test.name, expected.getMaskType(), result.getMaskType()); + assertEquals("maskCondition mismatched! - " + test.name, expected.getMaskCondition(), result.getMaskCondition()); + assertEquals("maskedValue mismatched! - " + test.name, expected.getMaskedValue(), result.getMaskedValue()); + assertEquals("policyId mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId()); + } } } @@ -326,6 +346,7 @@ public class TestPolicyEngine { public String name; public RangerAccessRequest request; public RangerAccessResult result; + public RangerDataMaskResult dataMaskResult; } class TagPolicyInfo { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/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 new file mode 100644 index 0000000..92b21aa --- /dev/null +++ b/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json @@ -0,0 +1,150 @@ +{ + "serviceName":"hivedev", + + "serviceDef":{ + "name":"hive", + "id":3, + "resources":[ + {"name":"database","level":1,"mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Hive Database","description":"Hive Database"}, + {"name":"table","level":2,"parent":"database","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Hive Table","description":"Hive Table"}, + {"name":"udf","level":2,"parent":"database","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Hive UDF","description":"Hive UDF"}, + {"name":"column","level":3,"parent":"table","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Hive Column","description":"Hive Column"} + ], + "accessTypes":[ + {"name":"select","label":"Select"}, + {"name":"update","label":"Update"}, + {"name":"create","label":"Create"}, + {"name":"drop","label":"Drop"}, + {"name":"alter","label":"Alter"}, + {"name":"index","label":"Index"}, + {"name":"lock","label":"Lock"}, + {"name":"all","label":"All", + "impliedGrants": [ + "select", + "update", + "create", + "drop", + "alter", + "index", + "lock" + ] + } + ], + "dataMaskDef": { + "maskTypes": [ + { + "itemId": 1, + "name": "MASK", + "label": "Mask", + "description": "Replace lowercase with 'x', uppercase with 'X', digits with '0'" + }, + { + "itemId": 2, + "name": "SHUFFLE", + "label": "Shuffle", + "description": "Randomly shuffle the contents" + } + + ], + "supportedAccessTypes": [ + "select" + ], + "supportedResources": [ + "database", + "table", + "column" + ] + } + }, + + "policies":[ + {"id":1,"name":"db=*: audit-all-access","isEnabled":true,"isAuditEnabled":true, + "resources":{"database":{"values":["*"]},"table":{"values":["*"]},"column":{"values":["*"]}}, + "policyItems":[ + {"accesses":[{"type":"all","isAllowed":true}],"users":["hive", "user1", "user2"],"groups":["public"],"delegateAdmin":false} + ] + }, + {"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"]}}, + "dataMaskPolicyItems":[ + {"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false, + "dataMaskInfo": {"dataMaskType":"MASK"} + }, + {"accesses":[{"type":"select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false, + "dataMaskInfo": {"dataMaskType":"SHUFFLE"} + } + ] + }, + {"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"]}}, + "dataMaskPolicyItems":[ + {"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false, + "dataMaskInfo": {"dataMaskType":"MASK"} + }, + {"accesses":[{"type":"select","isAllowed":true}],"users":["user2"],"groups":[],"delegateAdmin":false, + "dataMaskInfo": {"dataMaskType":"SHUFFLE"} + } + ] + } + ], + + "tests":[ + {"name":"'select ssn from employee.personal;' for user1 - maskType=MASK", + "request":{ + "resource":{"elements":{"database":"employee", "table":"personal", "column":"ssn"}}, + "accessType":"select","user":"user1","userGroups":[],"requestData":"select ssn from employee.personal;' for user1" + }, + "dataMaskResult":{"maskType":"MASK","maskCondition":null,"maskValue":null,"policyId":101} + }, + {"name":"'select ssn from employee.personal;' for user2 - maskType=SHUFFLE", + "request":{ + "resource":{"elements":{"database":"employee", "table":"personal", "column":"ssn"}}, + "accessType":"select","user":"user2","userGroups":[],"requestData":"select ssn from employee.personal;' for user2" + }, + "dataMaskResult":{"maskType":"SHUFFLE","maskCondition":null,"maskValue":null,"policyId":101} + }, + {"name":"'select ssn from employee.personal;' for user3 - no-mask", + "request":{ + "resource":{"elements":{"database":"employee", "table":"personal", "column":"ssn"}}, + "accessType":"select","user":"user3","userGroups":[],"requestData":"select ssn from employee.personal;' for user3" + }, + "dataMaskResult":{"maskType":null,"maskCondition":null,"maskValue":null,"policyId":-1} + }, + {"name":"'select name from employee.personal;' for user1 - no-mask", + "request":{ + "resource":{"elements":{"database":"employee", "table":"personal", "column":"name"}}, + "accessType":"select","user":"user1","userGroups":[],"requestData":"select name from employee.personal;' for user1" + }, + "dataMaskResult":{"maskType":null,"maskCondition":null,"maskValue":null,"policyId":-1} + }, + {"name":"'select date_of_birth from hr.employee;' for user1 - maskType=MASK", + "request":{ + "resource":{"elements":{"database":"hr", "table":"employee", "column":"date_of_birth"}}, + "accessType":"select","user":"user1","userGroups":[],"requestData":"select date_of_birth from hr.employee;' for user1" + }, + "dataMaskResult":{"maskType":"MASK","maskCondition":null,"maskValue":null,"policyId":102} + }, + {"name":"'select date_of_birth from hr.employee2;' for user2 - maskType=SHUFFLE", + "request":{ + "resource":{"elements":{"database":"hr", "table":"employee2", "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} + }, + {"name":"'select date_of_birth1 from hr.employee;' for user1 - no-mask", + "request":{ + "resource":{"elements":{"database":"hr", "table":"employee", "column":"date_of_birth1"}}, + "accessType":"select","user":"user1","userGroups":[],"requestData":"select date_of_birth1 from hr.employee;' for user1" + }, + "dataMaskResult":{"maskType":null,"maskCondition":null,"maskValue":null,"policyId":-1} + }, + {"name":"'select date_of_birth from hr2.employee2;' for user2 - no-mask", + "request":{ + "resource":{"elements":{"database":"hr2", "table":"employee2", "column":"date_of_birth"}}, + "accessType":"select","user":"user2","userGroups":[],"requestData":"select date_of_birth from hr2.employee2;' for user2" + }, + "dataMaskResult":{"maskType":null,"maskCondition":null,"maskValue":null,"policyId":-1} + } + ] +} + http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive.json ---------------------------------------------------------------------- diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive.json b/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive.json index 9c9bc40..2628863 100644 --- a/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive.json +++ b/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive.json @@ -175,7 +175,7 @@ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["hive"],"groups":[],"delegateAdmin":false} ] }, - {"id":4,"name":"RESTRICTED_TAG_POLICY_FINAL","isEnabled":true,"isAuditEnabled":true,"policyType":1, + {"id":4,"name":"RESTRICTED_TAG_POLICY_FINAL","isEnabled":true,"isAuditEnabled":true, "resources":{"tag":{"values":["RESTRICTED-FINAL"],"isRecursive":false}}, "denyPolicyItems":[ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":[],"groups":["public"],"delegateAdmin":false} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive_filebased.json ---------------------------------------------------------------------- diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive_filebased.json b/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive_filebased.json index e9ee355..167a157 100644 --- a/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive_filebased.json +++ b/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive_filebased.json @@ -181,7 +181,7 @@ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["hive"],"groups":[],"delegateAdmin":false} ] }, - {"id":4,"name":"RESTRICTED_TAG_POLICY_FINAL","isEnabled":true,"isAuditEnabled":true,"policyType":1, + {"id":4,"name":"RESTRICTED_TAG_POLICY_FINAL","isEnabled":true,"isAuditEnabled":true, "resources":{"tag":{"values":["RESTRICTED-FINAL"],"isRecursive":false}}, "denyPolicyItems":[ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":[],"groups":["public"],"delegateAdmin":false} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d242dd6e/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 new file mode 100644 index 0000000..43d9395 --- /dev/null +++ b/security-admin/db/mysql/patches/020-datamask-policy.sql @@ -0,0 +1,94 @@ +-- 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. + +/* 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; +delimiter ;; + create procedure add_datamasking_supported_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; + 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; + +/* add datamasking_supported column in x_resource_def table if not exist */ +drop procedure if exists add_datamasking_supported_to_x_resource_def_table; +delimiter ;; + create procedure add_datamasking_supported_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; + 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; + +DROP TABLE IF EXISTS `x_datamask_type_def`; +CREATE TABLE `x_datamask_type_def` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT , +`guid` varchar(1024) DEFAULT NULL, +`create_time` datetime DEFAULT NULL, +`update_time` datetime DEFAULT NULL, +`added_by_id` bigint(20) DEFAULT NULL, +`upd_by_id` bigint(20) DEFAULT NULL, +`def_id` bigint(20) NOT NULL, +`item_id` bigint(20) 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` tinyint(3) DEFAULT '0', +primary key (`id`), +KEY `x_datamask_type_def_added_by_id` (`added_by_id`), +KEY `x_datamask_type_def_upd_by_id` (`upd_by_id`), +KEY `x_datamask_type_def_cr_time` (`create_time`), +KEY `x_datamask_type_def_up_time` (`update_time`), +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); + +DROP TABLE IF EXISTS `x_policy_item_datamask`; +CREATE TABLE `x_policy_item_datamask` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT , +`guid` varchar(1024) DEFAULT NULL, +`create_time` datetime DEFAULT NULL, +`update_time` datetime DEFAULT NULL, +`added_by_id` bigint(20) DEFAULT NULL, +`upd_by_id` bigint(20) DEFAULT NULL, +`policy_item_id` bigint(20) NOT NULL, +`type` bigint(20) 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);
