Skip to content

Commit

Permalink
RANGER-5004: GDS masking to support use of a single mask for multiple…
Browse files Browse the repository at this point in the history
… columns
  • Loading branch information
mneethiraj committed Nov 25, 2024
1 parent 806fd9d commit dd5b5aa
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 163 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ranger.plugin.model.AuditFilter;
import org.apache.ranger.plugin.model.RangerGds.RangerTagDataMaskInfo;
import org.apache.ranger.plugin.model.RangerGds.RangerGdsMaskInfo;
import org.apache.ranger.plugin.model.RangerPrincipal;
import org.apache.ranger.plugin.model.RangerTag;
import org.apache.ranger.plugin.model.RangerValidityRecurrence;
import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -55,8 +54,7 @@ public class JsonUtils {
private static final TypeReference TYPE_LIST_AUDIT_FILTER = new TypeReference<List<AuditFilter>>() {};
private static final TypeReference TYPE_LIST_RANGER_VALIDITY_RECURRENCE = new TypeReference<List<RangerValidityRecurrence>>() {};
private static final TypeReference TYPE_LIST_RANGER_PRINCIPAL = new TypeReference<List<RangerPrincipal>>() {};
private static final TypeReference TYPE_LIST_RANGER_TAG_MASK_INFO = new TypeReference<List<RangerTagDataMaskInfo>>() {};
private static final TypeReference TYPE_MAP_RANGER_MASK_INFO = new TypeReference<Map<String, RangerPolicyItemDataMaskInfo>>() {};
private static final TypeReference TYPE_LIST_RANGER_GDS_MASK_INFO = new TypeReference<List<RangerGdsMaskInfo>>() {};
private static final TypeReference TYPE_MAP_RANGER_POLICY_RESOURCE = new TypeReference<Map<String, RangerPolicyResource>>() {};
private static final TypeReference TYPE_LIST_RANGER_TAG = new TypeReference<List<RangerTag>>() {};

Expand Down Expand Up @@ -263,24 +261,15 @@ public static List<RangerTag> jsonToRangerTagList(String jsonStr) {
}
}

public static Map<String, RangerPolicyItemDataMaskInfo> jsonToMapMaskInfo(String jsonStr) {
public static List<RangerGdsMaskInfo> jsonToListGdsMaskInfo(String jsonStr) {
try {
return (Map<String, RangerPolicyItemDataMaskInfo>) getMapper().readValue(jsonStr, TYPE_MAP_RANGER_MASK_INFO);
return (List<RangerGdsMaskInfo>) getMapper().readValue(jsonStr, TYPE_LIST_RANGER_GDS_MASK_INFO);
} catch (Exception e) {
LOG.error("Cannot get Map<String, RangerPolicyItemDataMaskInfo> from " + jsonStr, e);
return null;
}
}

public static List<RangerTagDataMaskInfo> jsonToListTagMaskInfo(String jsonStr) {
try {
return (List<RangerTagDataMaskInfo>) getMapper().readValue(jsonStr, TYPE_LIST_RANGER_TAG_MASK_INFO);
} catch (Exception e) {
LOG.error("Cannot get List<RangerTagDataMaskInfo> from " + jsonStr, e);
return null;
}
}

public static Map<String, RangerPolicyResource> jsonToMapPolicyResource(String jsonStr) {
try {
return (Map<String, RangerPolicyResource>) getMapper().readValue(jsonStr, TYPE_MAP_RANGER_POLICY_RESOURCE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,14 @@ public StringBuilder toString(StringBuilder sb) {
public static class RangerDataShare extends RangerGdsBaseModelObject implements java.io.Serializable {
private static final long serialVersionUID = 1L;

private String name;
private RangerGdsObjectACL acl;
private String service;
private String zone;
private String conditionExpr;
private Set<String> defaultAccessTypes;
private List<RangerTagDataMaskInfo> defaultTagMasks;
private String termsOfUse;
private String name;
private RangerGdsObjectACL acl;
private String service;
private String zone;
private String conditionExpr;
private Set<String> defaultAccessTypes;
private List<RangerGdsMaskInfo> defaultTagMasks;
private String termsOfUse;

public RangerDataShare() { }

Expand Down Expand Up @@ -242,11 +242,11 @@ public void setDefaultAccessTypes(Set<String> defaultAccessTypes) {
this.defaultAccessTypes = defaultAccessTypes;
}

public List<RangerTagDataMaskInfo> getDefaultTagMasks() {
public List<RangerGdsMaskInfo> getDefaultTagMasks() {
return defaultTagMasks;
}

public void setDefaultTagMasks(List<RangerTagDataMaskInfo> defaultTagMasks) {
public void setDefaultTagMasks(List<RangerGdsMaskInfo> defaultTagMasks) {
this.defaultTagMasks = defaultTagMasks;
}

Expand Down Expand Up @@ -274,19 +274,24 @@ public StringBuilder toString(StringBuilder sb) {
}
}

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(ignoreUnknown = true)
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class RangerSharedResource extends RangerGdsBaseModelObject implements java.io.Serializable {
private static final long serialVersionUID = 1L;

private String name;
private Long dataShareId;
private Map<String, RangerPolicyResource> resource;
private RangerPolicyResource subResource;
private String subResourceType;
private String conditionExpr;
private Set<String> accessTypes;
private RangerPolicyItemRowFilterInfo rowFilter;
private Map<String, RangerPolicyItemDataMaskInfo> subResourceMasks;
private Set<String> profiles;
private String name;
private Long dataShareId;
private Map<String, RangerPolicyResource> resource;
private RangerPolicyResource subResource;
private String subResourceType;
private String conditionExpr;
private Set<String> accessTypes;
private RangerPolicyItemRowFilterInfo rowFilter;
private List<RangerGdsMaskInfo> subResourceMasks;
private Set<String> profiles;

public RangerSharedResource() { }

Expand Down Expand Up @@ -326,9 +331,9 @@ public void setAccessTypes(Set<String> accessTypes) {

public void setRowFilter(RangerPolicyItemRowFilterInfo rowFilter) { this.rowFilter = rowFilter; }

public Map<String, RangerPolicyItemDataMaskInfo> getSubResourceMasks() { return subResourceMasks; }
public List<RangerGdsMaskInfo> getSubResourceMasks() { return subResourceMasks; }

public void setSubResourceMasks(Map<String, RangerPolicyItemDataMaskInfo> subResourceMasks) { this.subResourceMasks = subResourceMasks; }
public void setSubResourceMasks(List<RangerGdsMaskInfo> subResourceMasks) {this.subResourceMasks = subResourceMasks; }

public Set<String> getProfiles() { return profiles; }

Expand All @@ -355,6 +360,49 @@ public StringBuilder toString(StringBuilder sb) {
}
}


@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(ignoreUnknown = true)
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class RangerGdsMaskInfo implements java.io.Serializable {
private static final long serialVersionUID = 1L;

private List<String> values;
private RangerPolicyItemDataMaskInfo maskInfo;

public List<String> getValues() {
return values;
}

public void setValues(List<String> values) {
this.values = values;
}

public RangerPolicyItemDataMaskInfo getMaskInfo() {
return maskInfo;
}

public void setMaskInfo(RangerPolicyItemDataMaskInfo maskInfo) {
this.maskInfo = maskInfo;
}

@Override
public String toString() {
return toString(new StringBuilder()).toString();
}

public StringBuilder toString(StringBuilder sb) {
sb.append("RangerGdsMaskInfo={")
.append("values=").append(values).append(" ")
.append("maskInfo=").append(maskInfo)
.append("}");

return sb;
}
}

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(ignoreUnknown = true)
Expand Down Expand Up @@ -519,61 +567,6 @@ public StringBuilder toString(StringBuilder sb) {
}
}

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(ignoreUnknown = true)
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class RangerTagDataMaskInfo implements java.io.Serializable {
private static final long serialVersionUID = 1L;

private String tagName;
private String conditionExpr;
private RangerPolicyItemDataMaskInfo maskInfo;

public RangerTagDataMaskInfo() { }

public String getTagName() {
return tagName;
}

public void setTagName(String tagName) {
this.tagName = tagName;
}

public String getConditionExpr() {
return conditionExpr;
}

public void setConditionExpr(String conditionExpr) {
this.conditionExpr = conditionExpr;
}

public RangerPolicyItemDataMaskInfo getMaskInfo() {
return maskInfo;
}

public void setMaskInfo(RangerPolicyItemDataMaskInfo maskInfo) {
this.maskInfo = maskInfo;
}

@Override
public String toString() {
return toString(new StringBuilder()).toString();
}

public StringBuilder toString(StringBuilder sb) {
sb.append("RangerTagDataMaskInfo={");

sb.append("tagName={").append(tagName).append("} ")
.append("conditionExpr={").append(conditionExpr).append("} ")
.append("maskInfo={").append(maskInfo).append("} ")
.append("}");

return sb;
}
}

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(ignoreUnknown = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator;
import org.apache.ranger.plugin.model.RangerGds.RangerGdsMaskInfo;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo;
Expand All @@ -36,12 +37,14 @@
import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher.MatchType;
import org.apache.ranger.plugin.policyresourcematcher.RangerResourceEvaluator;
import org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher;
import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
import org.apache.ranger.plugin.util.ServiceDefUtil;
import org.apache.ranger.plugin.util.ServiceGdsInfo.SharedResourceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
Expand All @@ -61,6 +64,7 @@ public class GdsSharedResourceEvaluator implements RangerResourceEvaluator {
private final RangerPolicyResourceMatcher policyResourceMatcher;
private final RangerResourceDef leafResourceDef;
private final Set<String> allowedAccessTypes;
private final List<GdsMaskEvaluator> maskEvaluators;

public GdsSharedResourceEvaluator(SharedResourceInfo resource, Set<String> defaultAccessTypes, RangerServiceDefHelper serviceDefHelper, RangerPluginContext pluginContext) {
this.resource = resource;
Expand All @@ -82,6 +86,25 @@ public GdsSharedResourceEvaluator(SharedResourceInfo resource, Set<String> defau
this.leafResourceDef = ServiceDefUtil.getLeafResourceDef(serviceDefHelper.getServiceDef(), policyResource);
this.allowedAccessTypes = serviceDefHelper.expandImpliedAccessGrants(resource.getAccessTypes() != null ? resource.getAccessTypes() : defaultAccessTypes);

if (serviceDefHelper.isDataMaskSupported(policyResource.keySet()) && CollectionUtils.isNotEmpty(resource.getSubResourceMasks())) {
this.maskEvaluators = new ArrayList<>(resource.getSubResourceMasks().size());

RangerResourceDef maskResourceDef = serviceDefHelper.getResourceDef(resource.getSubResourceType(), RangerPolicy.POLICY_TYPE_DATAMASK);

for (RangerGdsMaskInfo maskInfo : resource.getSubResourceMasks()) {
RangerDefaultResourceMatcher resourceMatcher = new RangerDefaultResourceMatcher();

resourceMatcher.setResourceDef(maskResourceDef);
resourceMatcher.setPolicyResource(new RangerPolicyResource(maskInfo.getValues(), Boolean.FALSE, Boolean.FALSE));

resourceMatcher.init();

this.maskEvaluators.add(new GdsMaskEvaluator(resourceMatcher, maskInfo.getMaskInfo()));
}
} else {
this.maskEvaluators = Collections.emptyList();
}

LOG.debug("GdsSharedResourceEvaluator: resource={}, conditionEvaluator={}, policyResource={}, leafResourceDef={}, allowedAccessTypes={}",
resource, conditionEvaluator, policyResource, leafResourceDef, allowedAccessTypes);
}
Expand All @@ -90,6 +113,7 @@ private GdsSharedResourceEvaluator(GdsSharedResourceEvaluator other, RangerServi
this.resource = other.resource;
this.conditionEvaluator = other.conditionEvaluator;
this.allowedAccessTypes = other.allowedAccessTypes;
this.maskEvaluators = policyType == RangerPolicy.POLICY_TYPE_DATAMASK ? other.maskEvaluators : Collections.emptyList();

if (policyType == RangerPolicy.POLICY_TYPE_ROWFILTER && other.policyResource != other.resource.getResource()) {
this.policyResource = new HashMap<>(resource.getResource()); // ignore resource.subResource
Expand Down Expand Up @@ -194,7 +218,9 @@ public RangerPolicyItemRowFilterInfo getRowFilter() {
}

public RangerPolicyItemDataMaskInfo getDataMask(String subResourceName) {
return resource.getSubResourceMasks() != null ? resource.getSubResourceMasks().get(subResourceName) : null;
GdsMaskEvaluator maskEvaluator = maskEvaluators.stream().filter(e -> e.isMatch(subResourceName)).findFirst().orElse(null);

return maskEvaluator != null ? maskEvaluator.maskInfo : null;
}

GdsSharedResourceEvaluator createDataMaskEvaluator(RangerServiceDefHelper serviceDefHelper) {
Expand Down Expand Up @@ -228,6 +254,24 @@ private static RangerPolicyResourceMatcher initPolicyResourceMatcher(Map<String,
return matcher;
}

private static class GdsMaskEvaluator {
private final RangerDefaultResourceMatcher resourceMatcher;
private final RangerPolicyItemDataMaskInfo maskInfo;

public GdsMaskEvaluator(RangerDefaultResourceMatcher resourceMatcher, RangerPolicyItemDataMaskInfo maskInfo) {
this.resourceMatcher = resourceMatcher;
this.maskInfo = maskInfo;
}

public boolean isMatch(String value) {
return resourceMatcher.isMatch(value, RangerAccessRequest.ResourceElementMatchingScope.SELF, null);
}

public RangerPolicyItemDataMaskInfo getMaskInfo() {
return maskInfo;
}
}

public static class GdsSharedResourceEvalOrderComparator implements Comparator<GdsSharedResourceEvaluator> {
@Override
public int compare(GdsSharedResourceEvaluator me, GdsSharedResourceEvaluator other) {
Expand Down
Loading

0 comments on commit dd5b5aa

Please sign in to comment.