diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerGrant.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerGrant.java index d6c358fd7f..37a1ff6cc9 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerGrant.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerGrant.java @@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -34,16 +35,16 @@ public class RangerGrant implements java.io.Serializable { private RangerPrincipal principal; private List accessTypes; - private List conditions; + private List conditions; public RangerGrant() { this(null, null, null); } - public RangerGrant(RangerPrincipal principal, List accessTypes, List conditions) { - this.principal = principal; - this.accessTypes = accessTypes; - this.conditions = conditions; + public RangerGrant(RangerPrincipal principal, List accessTypes, List conditions) { + setPrincipal(principal); + setAccessTypes(accessTypes); + setConditions(conditions); } public RangerPrincipal getPrincipal() { @@ -59,15 +60,39 @@ public List getAccessTypes() { } public void setAccessTypes(List accessTypes) { - this.accessTypes = accessTypes; + if (this.accessTypes == null) { + this.accessTypes = new ArrayList<>(); + } + + if (this.accessTypes == accessTypes) { + return; + } + + this.accessTypes.clear(); + + if (accessTypes != null) { + this.accessTypes.addAll(accessTypes); + } } - public List getConditions() { + public List getConditions() { return conditions; } - public void setConditions(List conditions) { - this.conditions = conditions; + public void setConditions(List conditions) { + if (this.conditions == null) { + this.conditions = new ArrayList<>(); + } + + if (this.conditions == conditions) { + return; + } + + this.conditions.clear(); + + if (conditions != null) { + this.conditions.addAll(conditions); + } } @Override @@ -100,4 +125,76 @@ public String toString() { ", conditions=" + conditions + '}'; } -} + + @JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.ANY) + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Condition implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String type; + private List values; + + public Condition() { + this(null, null); + } + + public Condition(String type, List values) { + setType(type); + setValues(values); + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getValues() { + return values; + } + + public void setValues(List values) { + if (this.values == null) { + this.values = new ArrayList<>(); + } + + if (this.values == values) { + return; + } + + this.values.clear(); + + if (values != null) { + this.values.addAll(values); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Condition that = (Condition) o; + return Objects.equals(type, that.type) && Objects.equals(values, that.values); + } + + @Override + public int hashCode() { + return Objects.hash(type, values); + } + + @Override + public String toString() { + return "Conditions{" + + "type='" + type + '\'' + + ", values=" + values + + '}'; + } + } +} \ No newline at end of file diff --git a/security-admin/src/main/java/org/apache/ranger/rest/GdsREST.java b/security-admin/src/main/java/org/apache/ranger/rest/GdsREST.java index 0d3ef3d767..98d642833f 100755 --- a/security-admin/src/main/java/org/apache/ranger/rest/GdsREST.java +++ b/security-admin/src/main/java/org/apache/ranger/rest/GdsREST.java @@ -108,8 +108,6 @@ public class GdsREST { private static final Logger LOG = LoggerFactory.getLogger(GdsREST.class); private static final Logger PERF_LOG = RangerPerfTracer.getPerfLogger("rest.GdsREST"); - public static final String GDS_POLICY_EXPR_CONDITION = "expression"; - private static final String PRINCIPAL_TYPE_USER = RangerPrincipal.PrincipalType.USER.name().toLowerCase(); private static final String PRINCIPAL_TYPE_GROUP = RangerPrincipal.PrincipalType.GROUP.name().toLowerCase(); private static final String PRINCIPAL_TYPE_ROLE = RangerPrincipal.PrincipalType.ROLE.name().toLowerCase(); @@ -1900,29 +1898,29 @@ List transformPolicyItemsToGrants(List policyItem return null; } - List ret = new ArrayList<>(); + List ret = new ArrayList<>(); for (RangerPolicyItem policyItem : policyItems) { List policyItemUsers = policyItem.getUsers(); List policyItemGroups = policyItem.getGroups(); List policyItemRoles = policyItem.getRoles(); - List policyItemAccesses = policyItem.getAccesses(); - List policyItemConditions = policyItem.getConditions(); + List policyItemAccesses = policyItem.getAccesses(); + List policyItemConditions = policyItem.getConditions(); + List policyItemAccessTypes = policyItemAccesses.stream().map(RangerPolicyItemAccess::getType).collect(Collectors.toList()); - List policyItemAccessTypes = policyItemAccesses.stream().map(RangerPolicyItemAccess::getType).collect(Collectors.toList()); - List policyItemConditionValues = policyItemConditions.stream().flatMap(x -> x.getValues().stream()).collect(Collectors.toList()); + List conditions = getGrantConditions(policyItemConditions); if (CollectionUtils.isNotEmpty(policyItemUsers)) { - policyItemUsers.forEach(x -> ret.add(new RangerGrant(new RangerPrincipal(RangerPrincipal.PrincipalType.USER, x), policyItemAccessTypes, policyItemConditionValues))); + policyItemUsers.forEach(x -> ret.add(new RangerGrant(new RangerPrincipal(PrincipalType.USER, x), policyItemAccessTypes, conditions))); } if (CollectionUtils.isNotEmpty(policyItemGroups)) { - policyItemGroups.forEach(x -> ret.add(new RangerGrant(new RangerPrincipal(RangerPrincipal.PrincipalType.GROUP, x), policyItemAccessTypes, policyItemConditionValues))); + policyItemGroups.forEach(x -> ret.add(new RangerGrant(new RangerPrincipal(PrincipalType.GROUP, x), policyItemAccessTypes, conditions))); } if (CollectionUtils.isNotEmpty(policyItemRoles)) { - policyItemRoles.forEach(x -> ret.add(new RangerGrant(new RangerPrincipal(RangerPrincipal.PrincipalType.ROLE, x), policyItemAccessTypes, policyItemConditionValues))); + policyItemRoles.forEach(x -> ret.add(new RangerGrant(new RangerPrincipal(PrincipalType.ROLE, x), policyItemAccessTypes, conditions))); } } @@ -1974,6 +1972,17 @@ RangerPolicy updatePolicyWithModifiedGrants(RangerPolicy policy, List getGrantConditions(List policyItemConditions) { + List ret = new ArrayList<>(); + + if (CollectionUtils.isNotEmpty(policyItemConditions)) { + policyItemConditions.stream().collect(Collectors.toMap(RangerPolicyItemCondition::getType, RangerPolicyItemCondition::getValues)) + .entrySet().stream().map(expr -> new RangerGrant.Condition(expr.getKey(), expr.getValue())).forEach(ret::add); + } + + return ret; + } + private Long getOrCreateDataShare(Long datasetId, Long serviceId, Long zoneId, String serviceName) throws Exception { LOG.debug("==> GdsREST.getOrCreateDataShare(dataSetId={} serviceId={} zoneId={} serviceName={})", datasetId, serviceId, zoneId, serviceName); @@ -2125,18 +2134,23 @@ private RangerPolicyItem transformGrantToPolicyItem(RangerGrant grant) { return null; } - RangerPolicyItem policyItem = new RangerPolicyItem(); - List permissions = grant.getAccessTypes(); - List conditions = grant.getConditions(); + RangerPolicyItem policyItem = new RangerPolicyItem(); + List permissions = grant.getAccessTypes(); + List conditions = grant.getConditions(); if (CollectionUtils.isNotEmpty(permissions)) { - policyItem.setAccesses(permissions.stream().map(accessType -> new RangerPolicyItemAccess(accessType, true)).collect(Collectors.toList())); + policyItem.setAccesses(permissions.stream() + .map(accessType -> new RangerPolicyItemAccess(accessType, true)) + .collect(Collectors.toList())); } + List policyItemConditions = new ArrayList<>(); if (CollectionUtils.isNotEmpty(conditions)) { - policyItem.setConditions(conditions.stream().map(condition -> new RangerPolicyItemCondition(GDS_POLICY_EXPR_CONDITION, Collections.singletonList(condition))).collect(Collectors.toList())); + conditions.stream().map(condition -> new RangerPolicyItemCondition(condition.getType(), condition.getValues())).forEach(policyItemConditions::add); } + policyItem.setConditions(policyItemConditions); + switch (grant.getPrincipal().getType()) { case USER: policyItem.setUsers(Collections.singletonList(grant.getPrincipal().getName())); diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestGdsREST.java b/security-admin/src/test/java/org/apache/ranger/rest/TestGdsREST.java index 68d62fc31a..11df009a46 100644 --- a/security-admin/src/test/java/org/apache/ranger/rest/TestGdsREST.java +++ b/security-admin/src/test/java/org/apache/ranger/rest/TestGdsREST.java @@ -238,7 +238,19 @@ private RangerPolicy createPolicyForDataSet(RangerGds.RangerDataset dataset) { } private List createAndGetSampleGrantData() { - RangerGrant grant1 = new RangerGrant(new RangerPrincipal(RangerPrincipal.PrincipalType.USER, "hive"), Collections.singletonList("_READ"), Collections.singletonList("IS_ACCESSED_BEFORE('2024/12/12')")); + List conditions = new ArrayList<>(); + + RangerGrant.Condition condition1 = new RangerGrant.Condition(null, null); + condition1.setType("expression"); + condition1.setValues(Arrays.asList("IS_ACCESSED_BEFORE('2024/12/12')", "_STATE == 'CA'")); + conditions.add(condition1); + + RangerGrant.Condition condition2 = new RangerGrant.Condition(null, null); + condition2.setType("validitySchedule"); + condition2.setValues(Arrays.asList("{\"startTime\":\"1970/01/01 00:00:00\",\"endTime\":\"2025/03/08 00:35:28\",\"timeZone\":\"UTC\"}")); + conditions.add(condition2); + + RangerGrant grant1 = new RangerGrant(new RangerPrincipal(RangerPrincipal.PrincipalType.USER, "hive"), Collections.singletonList("_READ"), conditions); RangerGrant grant2 = new RangerGrant(new RangerPrincipal(RangerPrincipal.PrincipalType.GROUP, "hdfs"), Collections.singletonList("_MANAGE"), Collections.emptyList()); return Arrays.asList(grant1, grant2);