Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RANGER-5130:DatSet policies fail to authorize when condition expression is present #528

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -34,16 +35,16 @@ public class RangerGrant implements java.io.Serializable {

private RangerPrincipal principal;
private List<String> accessTypes;
private List<String> conditions;
private List<Condition> conditions;

public RangerGrant() {
this(null, null, null);
}

public RangerGrant(RangerPrincipal principal, List<String> accessTypes, List<String> conditions) {
this.principal = principal;
this.accessTypes = accessTypes;
this.conditions = conditions;
public RangerGrant(RangerPrincipal principal, List<String> accessTypes, List<Condition> conditions) {
setPrincipal(principal);
setAccessTypes(accessTypes);
setConditions(conditions);
}

public RangerPrincipal getPrincipal() {
Expand All @@ -59,15 +60,39 @@ public List<String> getAccessTypes() {
}

public void setAccessTypes(List<String> 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<String> getConditions() {
public List<Condition> getConditions() {
return conditions;
}

public void setConditions(List<String> conditions) {
this.conditions = conditions;
public void setConditions(List<Condition> 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
Expand Down Expand Up @@ -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<String> values;

public Condition() {
this(null, null);
}

public Condition(String type, List<String> values) {
setType(type);
setValues(values);
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

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

public void setValues(List<String> 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 +
'}';
}
}
}
44 changes: 29 additions & 15 deletions security-admin/src/main/java/org/apache/ranger/rest/GdsREST.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -1900,29 +1898,29 @@ List<RangerGrant> transformPolicyItemsToGrants(List<RangerPolicyItem> policyItem
return null;
}

List<RangerGrant> ret = new ArrayList<>();
List<RangerGrant> ret = new ArrayList<>();

for (RangerPolicyItem policyItem : policyItems) {
List<String> policyItemUsers = policyItem.getUsers();
List<String> policyItemGroups = policyItem.getGroups();
List<String> policyItemRoles = policyItem.getRoles();

List<RangerPolicyItemAccess> policyItemAccesses = policyItem.getAccesses();
List<RangerPolicyItemCondition> policyItemConditions = policyItem.getConditions();
List<RangerPolicyItemAccess> policyItemAccesses = policyItem.getAccesses();
List<RangerPolicyItemCondition> policyItemConditions = policyItem.getConditions();
List<String> policyItemAccessTypes = policyItemAccesses.stream().map(RangerPolicyItemAccess::getType).collect(Collectors.toList());

List<String> policyItemAccessTypes = policyItemAccesses.stream().map(RangerPolicyItemAccess::getType).collect(Collectors.toList());
List<String> policyItemConditionValues = policyItemConditions.stream().flatMap(x -> x.getValues().stream()).collect(Collectors.toList());
List<RangerGrant.Condition> 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)));
}
}

Expand Down Expand Up @@ -1974,6 +1972,17 @@ RangerPolicy updatePolicyWithModifiedGrants(RangerPolicy policy, List<RangerGran
return policy;
}

private List<RangerGrant.Condition> getGrantConditions(List<RangerPolicy.RangerPolicyItemCondition> policyItemConditions) {
List<RangerGrant.Condition> 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);

Expand Down Expand Up @@ -2125,18 +2134,23 @@ private RangerPolicyItem transformGrantToPolicyItem(RangerGrant grant) {
return null;
}

RangerPolicyItem policyItem = new RangerPolicyItem();
List<String> permissions = grant.getAccessTypes();
List<String> conditions = grant.getConditions();
RangerPolicyItem policyItem = new RangerPolicyItem();
List<String> permissions = grant.getAccessTypes();
List<RangerGrant.Condition> 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<RangerPolicyItemCondition> 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()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,19 @@ private RangerPolicy createPolicyForDataSet(RangerGds.RangerDataset dataset) {
}

private List<RangerGrant> createAndGetSampleGrantData() {
RangerGrant grant1 = new RangerGrant(new RangerPrincipal(RangerPrincipal.PrincipalType.USER, "hive"), Collections.singletonList("_READ"), Collections.singletonList("IS_ACCESSED_BEFORE('2024/12/12')"));
List<RangerGrant.Condition> 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);
Expand Down
Loading