diff --git a/agents-common/src/main/java/org/apache/ranger/authorization/utils/JsonUtils.java b/agents-common/src/main/java/org/apache/ranger/authorization/utils/JsonUtils.java index 08874d257a..e3c45c1ff6 100644 --- a/agents-common/src/main/java/org/apache/ranger/authorization/utils/JsonUtils.java +++ b/agents-common/src/main/java/org/apache/ranger/authorization/utils/JsonUtils.java @@ -24,18 +24,32 @@ 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.RangerPrincipal; 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; import java.lang.reflect.Type; import java.util.List; import java.util.Map; +import java.util.Set; public class JsonUtils { private static final Logger LOG = LoggerFactory.getLogger(JsonUtils.class); + private static final Type TYPE_MAP_STRING_STRING = new TypeToken>() {}.getType(); + private static final Type TYPE_SET_STRING = new TypeToken>() {}.getType(); + private static final Type TYPE_LIST_STRING = new TypeToken>() {}.getType(); + private static final Type TYPE_LIST_RANGER_VALIDITY_SCHEDULE = new TypeToken>() {}.getType(); + private static final Type TYPE_LIST_AUDIT_FILTER = new TypeToken>() {}.getType(); + private static final Type TYPE_LIST_RANGER_VALIDITY_RECURRENCE = new TypeToken>() {}.getType(); + private static final Type TYPE_LIST_RANGER_PRINCIPAL = new TypeToken>() {}.getType(); + private static final Type TYPE_MAP_RANGER_MASK_INFO = new TypeToken>() {}.getType(); + private static final Type TYPE_MAP_RANGER_POLICY_RESOURCE = new TypeToken>() {}.getType(); + private static final ThreadLocal gson = new ThreadLocal() { @Override protected Gson initialValue() { @@ -100,8 +114,7 @@ public static Map jsonToMapStringString(String jsonStr) { if(StringUtils.isNotEmpty(jsonStr)) { try { - Type mapType = new TypeToken>() {}.getType(); - ret = gson.get().fromJson(jsonStr, mapType); + ret = gson.get().fromJson(jsonStr, TYPE_MAP_STRING_STRING); } catch(Exception excp) { LOG.warn("jsonToObject() failed to convert json to object: " + jsonStr, excp); } @@ -110,10 +123,37 @@ public static Map jsonToMapStringString(String jsonStr) { return ret; } + public static Set jsonToSetString(String jsonStr) { + Set ret = null; + + if (StringUtils.isNotEmpty(jsonStr)) { + try { + ret = gson.get().fromJson(jsonStr, TYPE_SET_STRING); + } catch(Exception excp) { + LOG.warn("jsonToSetString() failed to convert json to object: " + jsonStr, excp); + } + } + + return ret; + } + + public static List jsonToListString(String jsonStr) { + List ret = null; + + if (StringUtils.isNotEmpty(jsonStr)) { + try { + ret = gson.get().fromJson(jsonStr, TYPE_LIST_STRING); + } catch(Exception excp) { + LOG.warn("jsonToListString() failed to convert json to object: " + jsonStr, excp); + } + } + + return ret; + } + public static List jsonToRangerValiditySchedule(String jsonStr) { try { - Type listType = new TypeToken>() {}.getType(); - return gson.get().fromJson(jsonStr, listType); + return gson.get().fromJson(jsonStr, TYPE_LIST_RANGER_VALIDITY_SCHEDULE); } catch (Exception e) { LOG.error("Cannot get List from " + jsonStr, e); return null; @@ -122,8 +162,7 @@ public static List jsonToRangerValiditySchedule(String j public static List jsonToAuditFilterList(String jsonStr) { try { - Type listType = new TypeToken>() {}.getType(); - return gson.get().fromJson(jsonStr, listType); + return gson.get().fromJson(jsonStr, TYPE_LIST_AUDIT_FILTER); } catch (Exception e) { LOG.error("failed to create audit filters from: " + jsonStr, e); return null; @@ -132,9 +171,34 @@ public static List jsonToAuditFilterList(String jsonStr) { public static List jsonToRangerValidityRecurringSchedule(String jsonStr) { try { - Type listType = new TypeToken>() { - }.getType(); - return gson.get().fromJson(jsonStr, listType); + return gson.get().fromJson(jsonStr, TYPE_LIST_RANGER_VALIDITY_RECURRENCE); + } catch (Exception e) { + LOG.error("Cannot get List from " + jsonStr, e); + return null; + } + } + + public static List jsonToRangerPrincipalList(String jsonStr) { + try { + return gson.get().fromJson(jsonStr, TYPE_LIST_RANGER_PRINCIPAL); + } catch (Exception e) { + LOG.error("Cannot get List from " + jsonStr, e); + return null; + } + } + + public static Map jsonToMapMaskInfo(String jsonStr) { + try { + return gson.get().fromJson(jsonStr, TYPE_MAP_RANGER_MASK_INFO); + } catch (Exception e) { + LOG.error("Cannot get List from " + jsonStr, e); + return null; + } + } + + public static Map jsonToMapPolicyResource(String jsonStr) { + try { + return gson.get().fromJson(jsonStr, TYPE_MAP_RANGER_POLICY_RESOURCE); } catch (Exception e) { LOG.error("Cannot get List from " + jsonStr, e); return null; 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 f44b9d9a1a..94e227ce6f 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 @@ -132,6 +132,32 @@ public enum ValidationErrorCode { ROLE_VALIDATION_ERR_INVALID_ROLE_NAME(4007, "No RangerRole found for name[{0}]"), ROLE_VALIDATION_ERR_UNSUPPORTED_ACTION(4008, "Internal error: method signature isValid(Long) is only supported for DELETE"), + GDS_VALIDATION_ERR_NON_EXISTING_USER(4101, "User [{0}] does not exist"), + GDS_VALIDATION_ERR_NON_EXISTING_GROUP(4102, "Group [{0}] does not exist"), + GDS_VALIDATION_ERR_NON_EXISTING_ROLE(4103, "Role [{0}] does not exist"), + GDS_VALIDATION_ERR_NON_EXISTING_SERVICE(4104, "Service [{0}] does not exist"), + GDS_VALIDATION_ERR_NON_EXISTING_ZONE(4105, "Zone [{0}] does not exist"), + GDS_VALIDATION_ERR_NOT_OWNER(4106, "User [{0}] is not an owner"), + GDS_VALIDATION_ERR_SERVICE_NAME_MISSING(4107, "Service name not provided"), + GDS_VALIDATION_ERR_DATASET_NAME_CONFLICT(4108, "Dataset with name [{0}] already exists. ID=[{1}]"), + GDS_VALIDATION_ERR_DATASET_NAME_NOT_FOUND(4109, "Dataset with name [{0}] does not exist"), + GDS_VALIDATION_ERR_DATASET_ID_NOT_FOUND(4110, "Dataset with ID [{0}] does not exist"), + GDS_VALIDATION_ERR_PROJECT_NAME_CONFLICT(4111, "Project with name [{0}] already exists. ID=[{1}]"), + GDS_VALIDATION_ERR_PROJECT_NAME_NOT_FOUND(4112, "Project with name [{0}] does not exist"), + GDS_VALIDATION_ERR_PROJECT_ID_NOT_FOUND(4113, "Project with ID [{0}] does not exist"), + GDS_VALIDATION_ERR_DATA_SHARE_NAME_CONFLICT(4114, "Data share with name [{0}] already exists. ID=[{1}]"), + GDS_VALIDATION_ERR_DATA_SHARE_NAME_NOT_FOUND(4115, "Data share with name [{0}] does not exist"), + GDS_VALIDATION_ERR_DATA_SHARE_ID_NOT_FOUND(4116, "Data share with ID [{0}] does not exist"), + GDS_VALIDATION_ERR_DATA_SHARE_NOT_SERVICE_ADMIN(4117, "Not a admin for service [{0}]"), + GDS_VALIDATION_ERR_DATA_SHARE_NOT_SERVICE_OR_ZONE_ADMIN(4118, "Not a admin for service [{0}] or zone [{1}]"), + GDS_VALIDATION_ERR_INVALID_ACCESS_TYPE(4119, "Not a valid access-type [{0}]"), + GDS_VALIDATION_ERR_INVALID_MASK_TYPE(4120, "Not a valid mask-type [{0}]"), + GDS_VALIDATION_ERR_SHARED_RESOURCE_NAME_CONFLICT(4121, "Shared resource with name [{0}] already exists in data share [{1}]. ID=[{2}]"), + GDS_VALIDATION_ERR_SHARED_RESOURCE_ID_NOT_FOUND(4122, "Shared resource with ID [{0}] does not exist"), + GDS_VALIDATION_ERR_ADD_DATA_SHARE_IN_DATASET_INVALID_STATUS(4123, "[{0}]: invalid status while adding data share into a dataset"), + GDS_VALIDATION_ERR_DATA_SHARE_IN_DATASET_ID_NOT_FOUND(4124, "Data share-in-dataset with ID [{0}] does not exist"), + GDS_VALIDATION_ERR_INVALID_STATUS_CHANGE(4125, "invalid status change from [{0}] to [{1}]"), + GDS_VALIDATION_ERR_UPDATE_IMMUTABLE_FIELD(4126, "[{0}] can't be updated"), ; diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerGds.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerGds.java new file mode 100644 index 0000000000..63e58411c8 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerGds.java @@ -0,0 +1,488 @@ +/* + * 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.model; + +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class RangerGds { + + public enum GdsPermission { NONE, LIST, VIEW, AUDIT, POLICY_ADMIN, ADMIN } + + public enum GdsShareStatus { NONE, REQUESTED, GRANTED, ACCEPTED } + + @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) + @JsonIgnoreProperties(ignoreUnknown = true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerGdsBaseModelObject extends RangerBaseModelObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String description; + private Map options; + private Map additionalInfo; + + + public RangerGdsBaseModelObject() { } + + public String getDescription() { return description; } + + public void setDescription(String description) { this.description = description; } + + public Map getOptions() { return options; } + + public void setOptions(Map options) { this.options = options; } + + public Map getAdditionalInfo() { return additionalInfo; } + + public void setAdditionalInfo(Map additionalInfo) { this.additionalInfo = additionalInfo; } + + @Override + public StringBuilder toString(StringBuilder sb) { + super.toString(sb); + + sb.append("description={").append(description).append("} ") + .append("options={").append(options).append("} ") + .append("additionalInfo={").append(additionalInfo).append("} "); + + return sb; + } + + } + + @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) + @JsonIgnoreProperties(ignoreUnknown = true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataset extends RangerGdsBaseModelObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String name; + private List owners; + private RangerGdsACL acl; + private String termsOfUse; + + public RangerDataset() { } + + public String getName() { return name; } + + public void setName(String name) { this.name = name; } + + public List getOwners() { return owners; } + + public void setOwners(List owners) { this.owners = owners; } + + public RangerGdsACL getAcl() { return acl; } + + public void setAcl(RangerGdsACL acl) { this.acl = acl; } + + public String getTermsOfUse() { return termsOfUse; } + + public void setTermsOfUse(String termsOfUse) { this.termsOfUse = termsOfUse; } + + @Override + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDataset={"); + + super.toString(sb); + + sb.append("name={").append(name).append("} ") + .append("owners={").append(owners).append("} ") + .append("acl={").append(acl).append("} ") + .append("termsOfUse={").append(termsOfUse).append("} ") + .append("}"); + + return sb; + } + } + + @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) + @JsonIgnoreProperties(ignoreUnknown = true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerProject extends RangerGdsBaseModelObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String name; + private List owners; + private RangerGdsACL acl; + private String termsOfUse; + + public RangerProject() { } + + public String getName() { return name; } + + public void setName(String name) { this.name = name; } + + public List getOwners() { return owners; } + + public void setOwners(List owners) { this.owners = owners; } + + public RangerGdsACL getAcl() { return acl; } + + public void setAcl(RangerGdsACL acl) { this.acl = acl; } + + public String getTermsOfUse() { return termsOfUse; } + + public void setTermsOfUse(String termsOfUse) { this.termsOfUse = termsOfUse; } + + @Override + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerProject={"); + + super.toString(sb); + + sb.append("name={").append(name).append("} ") + .append("owners={").append(owners).append("} ") + .append("acl={").append(acl).append("} ") + .append("termsOfUse={").append(termsOfUse).append("} ") + .append("}"); + + return sb; + } + } + + @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) + @JsonIgnoreProperties(ignoreUnknown = true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataShare extends RangerGdsBaseModelObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String name; + private List owners; + private String service; + private String zone; + private String condition; + private Set defaultAccessTypes; + private Map defaultMasks; + private String termsOfUse; + + public RangerDataShare() { } + + public String getName() { return name; } + + public void setName(String name) { this.name = name; } + + public List getOwners() { return owners; } + + public void setOwners(List owners) { this.owners = owners; } + + public String getService() { return service; } + + public void setService(String service) { this.service = service; } + + public String getZone() { return zone; } + + public void setZone(String zone) { this.zone = zone; } + + public String getCondition() { return condition; } + + public void setCondition(String condition) { this.condition = condition; } + + public Set getDefaultAccessTypes() { + return defaultAccessTypes; + } + + public void setDefaultAccessTypes(Set defaultAccessTypes) { + this.defaultAccessTypes = defaultAccessTypes; + } + + public Map getDefaultMasks() { + return defaultMasks; + } + + public void setDefaultMasks(Map defaultMasks) { + this.defaultMasks = defaultMasks; + } + + public String getTermsOfUse() { return termsOfUse; } + + public void setTermsOfUse(String termsOfUse) { this.termsOfUse = termsOfUse; } + + @Override + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDataShare={"); + + super.toString(sb); + + sb.append("name={").append(name).append("} ") + .append("owners={").append(owners).append("} ") + .append("service={").append(service).append("} ") + .append("zone={").append(zone).append("} ") + .append("condition={").append(condition).append("} ") + .append("defaultAccessTypes={").append(defaultAccessTypes).append("} ") + .append("defaultMasks={").append(defaultMasks).append("} ") + .append("termsOfUse={").append(termsOfUse).append("} ") + .append("}"); + + return sb; + } + } + + public static class RangerSharedResource extends RangerGdsBaseModelObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String name; + private Long dataShareId; + private Map resource; + private List subResourceNames; + private String resourceSignature; + private String condition; + private Set accessTypes; + private RangerPolicyItemRowFilterInfo rowFilter; + private Map subResourceMasks; + private Set profiles; + + public RangerSharedResource() { } + + public String getName() { return name; } + + public void setName(String name) { this.name = name; } + + public Long getDataShareId() { return dataShareId; } + + public void setDataShareId(Long dataShareId) { this.dataShareId = dataShareId; } + + public Map getResource() { return resource; } + + public void setResource(Map resource) { this.resource = resource; } + + public List getSubResourceNames() { return subResourceNames; } + + public void setSubResourceNames(List subResourceNames) { this.subResourceNames = subResourceNames; } + + public String getResourceSignature() { return resourceSignature; } + + public void setResourceSignature(String resourceSignature) { this.resourceSignature = resourceSignature; } + + public String getCondition() { return condition; } + + public void setCondition(String condition) { this.condition = condition; } + + public Set getAccessTypes() { + return accessTypes; + } + + public void setAccessTypes(Set accessTypes) { + this.accessTypes = accessTypes; + } + + public RangerPolicyItemRowFilterInfo getRowFilter() { return rowFilter; } + + public void setRowFilter(RangerPolicyItemRowFilterInfo rowFilter) { this.rowFilter = rowFilter; } + + public Map getSubResourceMasks() { return subResourceMasks; } + + public void setSubResourceMasks(Map subResourceMasks) { this.subResourceMasks = subResourceMasks; } + + public Set getProfiles() { return profiles; } + + public void setProfiles(Set profiles) { this.profiles = profiles; } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerSharedResource={"); + + super.toString(sb); + + sb.append("name").append(name).append("} ") + .append("dataShareId={").append(dataShareId).append("} ") + .append("resource={").append(resource).append("} ") + .append("subResourceNames={").append(subResourceNames).append("} ") + .append("resourceSignature={").append(resourceSignature).append("} ") + .append("conditions={").append(condition).append("} ") + .append("accessTypes={").append(accessTypes).append("} ") + .append("rowFilterInfo={").append(rowFilter).append("} ") + .append("subResourceMasks={").append(subResourceMasks).append("} ") + .append("profiles={").append(profiles).append("} ") + .append("}"); + + return sb; + } + } + + @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) + @JsonIgnoreProperties(ignoreUnknown = true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataShareInDataset extends RangerGdsBaseModelObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long dataShareId; + private Long datasetId; + private GdsShareStatus status; + private RangerValiditySchedule validitySchedule; + private Set profiles; + + + public RangerDataShareInDataset() { } + + public Long getDataShareId() { return dataShareId; } + + public void setDataShareId(Long dataShareId) { this.dataShareId = dataShareId; } + + public Long getDatasetId() { return datasetId; } + + public void setDatasetId(Long datasetId) { this.datasetId = datasetId; } + + public GdsShareStatus getStatus() { return status; } + + public void setStatus(GdsShareStatus status) { this.status = status; } + + public RangerValiditySchedule getValiditySchedule() { return validitySchedule; } + + public void setValiditySchedule(RangerValiditySchedule validitySchedule) { this.validitySchedule = validitySchedule; } + + public Set getProfiles() { return profiles; } + + public void setProfiles(Set profiles) { this.profiles = profiles; } + + @Override + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDataShareInDataset={"); + + super.toString(sb); + + sb.append("dataShareId={").append(dataShareId).append("} ") + .append("datasetId={").append(datasetId).append("} ") + .append("status={").append(status).append("} ") + .append("validitySchedule={").append(validitySchedule).append("} ") + .append("profiles={").append(profiles).append("} ") + .append("}"); + + return sb; + } + } + + @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) + @JsonIgnoreProperties(ignoreUnknown = true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDatasetInProject extends RangerGdsBaseModelObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long datasetId; + private Long projectId; + private GdsShareStatus status; + private RangerValiditySchedule validitySchedule; + private Set profiles; + + + public RangerDatasetInProject() { } + + public Long getDatasetId() { return datasetId; } + + public void setDatasetId(Long datasetId) { this.datasetId = datasetId; } + + public Long getProjectId() { return projectId; } + + public void setProjectId(Long projectId) { this.projectId = projectId; } + + public GdsShareStatus getStatus() { return status; } + + public void setStatus(GdsShareStatus status) { this.status = status; } + + public RangerValiditySchedule getValiditySchedule() { return validitySchedule; } + + public void setValiditySchedule(RangerValiditySchedule validitySchedule) { this.validitySchedule = validitySchedule; } + + public Set getProfiles() { return profiles; } + + public void setProfiles(Set profiles) { this.profiles = profiles; } + + @Override + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDatasetInProject={"); + + super.toString(sb); + + sb.append("datasetGuid={").append(datasetId).append("} ") + .append("projectGuid={").append(projectId).append("} ") + .append("status={").append(status).append("} ") + .append("validitySchedule={").append(validitySchedule).append("} ") + .append("profiles={").append(profiles).append("} ") + .append("}"); + + return sb; + } + } + + @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) + @JsonIgnoreProperties(ignoreUnknown = true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerGdsACL implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Map users; + private Map groups; + private Map roles; + + + public RangerGdsACL() { } + + public Map getUsers() { return users; } + + public void setUsers(Map users) { this.users = users; } + + public Map getGroups() { return groups; } + + public void setGroups(Map groups) { this.groups = groups; } + + public Map getRoles() { return roles; } + + public void setRoles(Map roles) { this.roles = roles; } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerGdsACL={"); + + sb.append("users={").append(users).append("} ") + .append("groups={").append(groups).append("} ") + .append("roles={").append(roles).append("} ") + .append("}"); + + return sb; + } + } +} diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPrincipal.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPrincipal.java new file mode 100644 index 0000000000..226dc4d7c3 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPrincipal.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.plugin.model; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Objects; + +@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY) +@JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerPrincipal implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + public enum PrincipalType { USER, GROUP, ROLE } + + private PrincipalType type; + private String name; + + public RangerPrincipal() { + this(null, null); + } + + public RangerPrincipal(PrincipalType type, String name) { + setType(type); + setName(name); + } + + public PrincipalType getType() { + return type; + } + + public void setType(PrincipalType type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public int hashCode() { + return Objects.hash(type, name); + } + + @Override + public boolean equals(Object obj) { + final boolean ret; + + if (this == obj) { + ret = true; + } else if (obj == null) { + ret = false; + } else if (getClass() != obj.getClass()) { + ret = false; + } else { + RangerPrincipal other = (RangerPrincipal) obj; + + ret = Objects.equals(type, other.type) && Objects.equals(name, other.name); + } + + return ret; + } + + @Override + public String toString() { + return "{type=" + type + ", name=" + name + "}"; + } +} diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java index 48d12bc4a1..6f6617a4a2 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java @@ -19,6 +19,7 @@ package org.apache.ranger.plugin.model.validation; +import org.apache.ranger.plugin.errors.ValidationErrorCode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,6 +37,10 @@ public class ValidationFailureDetails { final String _reason; final int _errorCode; + public ValidationFailureDetails(ValidationErrorCode errorCode, String fieldName, Object... errorCodeArgs) { + this(errorCode.getErrorCode(), fieldName, null, false, false, false, errorCode.getMessage(errorCodeArgs)); + } + public ValidationFailureDetails(int errorCode, String fieldName, String subFieldName, boolean missing, boolean semanticError, boolean internalError, String reason) { _errorCode = errorCode; _missing = missing; diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractGdsStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractGdsStore.java new file mode 100644 index 0000000000..0c9114aee7 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractGdsStore.java @@ -0,0 +1,162 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDatasetInProject; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShareInDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; +import org.apache.ranger.plugin.model.RangerGds.RangerSharedResource; +import org.apache.ranger.plugin.util.SearchFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public abstract class AbstractGdsStore implements GdsStore { + private static final Logger LOG = LoggerFactory.getLogger(AbstractGdsStore.class); + + protected ServiceStore svcStore; + + @Override + public void init() throws Exception { + LOG.info("==> AbstractGdsStore.init()"); + + LOG.info("<== AbstractGdsStore.init()"); + } + + @Override + public void setServiceStore(ServiceStore svcStore) { + LOG.info("==> AbstractGdsStore.setServiceStore()"); + + this.svcStore = svcStore; + + LOG.info("<== AbstractGdsStore.setServiceStore()"); + } + + @Override + public ServiceStore getServiceStore() { return svcStore; } + + @Override + public RangerDataset createDataset(RangerDataset dataset) throws Exception { return null; } + + @Override + public RangerDataset updateDataset(RangerDataset dataset) throws Exception { return null; } + + @Override + public void deleteDataset(Long datasetId) throws Exception { } + + @Override + public RangerDataset getDataset(Long datasetId) throws Exception { return null; } + + @Override + public RangerDataset getDatasetByName(String name) throws Exception { return null; } + + @Override + public PList getDatasetNames(SearchFilter filter) throws Exception { return null; } + + @Override + public PList searchDatasets(SearchFilter filter) throws Exception { return null; } + + + @Override + public RangerProject createProject(RangerProject dataset) throws Exception { return null; } + + @Override + public RangerProject updateProject(RangerProject dataset) throws Exception { return null; } + + @Override + public void deleteProject(Long datasetId) throws Exception { } + + @Override + public RangerProject getProject(Long projectId) throws Exception { return null; } + + @Override + public RangerProject getProjectByName(String name) throws Exception { return null; } + + @Override + public PList getProjectNames(SearchFilter filter) throws Exception { return null; } + + @Override + public PList searchProjects(SearchFilter filter) throws Exception { return null; } + + + @Override + public RangerDataShare createDataShare(RangerDataShare dataShare) throws Exception { return null; } + + @Override + public RangerDataShare updateDataShare(RangerDataShare dataShare) throws Exception { return null; } + + @Override + public void deleteDataShare(Long dataShareId) throws Exception { } + + @Override + public RangerDataShare getDataShare(Long dataShareId) throws Exception { return null; } + + @Override + public PList searchDataShares(SearchFilter filter) throws Exception { return null; } + + + @Override + public RangerSharedResource addSharedResource(RangerSharedResource resource) throws Exception { return null; } + + @Override + public RangerSharedResource updateSharedResource(RangerSharedResource resource) throws Exception { return null; } + + @Override + public void removeSharedResource(Long sharedResourceId) throws Exception { } + + @Override + public RangerSharedResource getSharedResource(Long sharedResourceId) throws Exception { return null; } + + @Override + public PList searchSharedResources(SearchFilter filter) throws Exception { return null; } + + + @Override + public RangerDataShareInDataset addDataShareInDataset(RangerDataShareInDataset dataShareInDataset) throws Exception { return null; } + + @Override + public RangerDataShareInDataset updateDataShareInDataset(RangerDataShareInDataset dataShareInDataset) throws Exception { return null; } + + @Override + public void removeDataShareInDataset(Long dataShareInDatasetId) throws Exception { } + + @Override + public RangerDataShareInDataset getDataShareInDataset(Long dataShareInDatasetId) throws Exception { return null; } + + @Override + public PList searchDataShareInDatasets(SearchFilter filter) throws Exception { return null; } + + + @Override + public RangerDatasetInProject addDatasetInProject(RangerDatasetInProject datasetInProject) throws Exception { return null; } + + @Override + public RangerDatasetInProject updateDatasetInProject(RangerDatasetInProject datasetInProject) throws Exception { return null; } + + @Override + public void removeDatasetInProject(Long datasetInProjectId) throws Exception { } + + @Override public RangerDatasetInProject getDatasetInProject(Long datasetInProjectId) throws Exception { return null; } + + @Override + public PList searchDatasetInProjects(SearchFilter filter) throws Exception { return null; } +} diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java index 79e09a1a24..75be1e70e8 100755 --- a/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java @@ -49,10 +49,11 @@ public class EmbeddedServiceDefsUtil { // following servicedef list should be reviewed/updated whenever a new embedded service-def is added - public static final String DEFAULT_BOOTSTRAP_SERVICEDEF_LIST = "tag,hdfs,hbase,hive,kms,knox,storm,yarn,kafka,solr,atlas,nifi,nifi-registry,sqoop,kylin,elasticsearch,presto,trino,ozone,kudu,schema-registry,nestedstructure"; + public static final String DEFAULT_BOOTSTRAP_SERVICEDEF_LIST = "tag,gds,hdfs,hbase,hive,kms,knox,storm,yarn,kafka,solr,atlas,nifi,nifi-registry,sqoop,kylin,elasticsearch,presto,trino,ozone,kudu,schema-registry,nestedstructure"; private static final String PROPERTY_SUPPORTED_SERVICE_DEFS = "ranger.supportedcomponents"; private Set supportedServiceDefs; public static final String EMBEDDED_SERVICEDEF_TAG_NAME = "tag"; + public static final String EMBEDDED_SERVICEDEF_GDS_NAME = "gds"; public static final String EMBEDDED_SERVICEDEF_HDFS_NAME = "hdfs"; public static final String EMBEDDED_SERVICEDEF_HBASE_NAME = "hbase"; public static final String EMBEDDED_SERVICEDEF_HIVE_NAME = "hive"; @@ -124,6 +125,7 @@ public class EmbeddedServiceDefsUtil { private RangerServiceDef nestedStructureServiveDef; private RangerServiceDef tagServiceDef; + private RangerServiceDef gdsServiceDef; private final Gson gsonBuilder; private final RangerAdminConfig config; @@ -162,8 +164,6 @@ public void init(ServiceStore store) { nifiServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_NIFI_NAME); nifiRegistryServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_NIFI_REGISTRY_NAME); atlasServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_ATLAS_NAME); - - tagServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_TAG_NAME); wasbServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_WASB_NAME); sqoopServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_SQOOP_NAME); kylinServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_KYLIN_NAME); @@ -175,6 +175,9 @@ public void init(ServiceStore store) { kuduServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_KUDU_NAME); nestedStructureServiveDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_NESTEDSTRUCTURE_NAME); + tagServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_TAG_NAME); + gdsServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_GDS_NAME); + // Ensure that tag service def is updated with access types of all service defs store.updateTagServiceDefForAccessTypes(); } catch(Throwable excp) { @@ -247,7 +250,6 @@ public long getKylinServiceDefId() { public long getElasticsearchServiceDefId() { return getId(elasticsearchServiceDef); } - public long getTagServiceDefId() { return getId(tagServiceDef); } public long getWasbServiceDefId() { return getId(wasbServiceDef); } @@ -263,6 +265,10 @@ public long getElasticsearchServiceDefId() { public long getNestedStructureServiceDefId() { return getId(nestedStructureServiveDef); } + public long getTagServiceDefId() { return getId(tagServiceDef); } + + public long getGdsServiceDefId() { return getId(gdsServiceDef); } + public RangerServiceDef getEmbeddedServiceDef(String defType) throws Exception { RangerServiceDef serviceDef=null; if(StringUtils.isNotEmpty(defType)){ diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/GdsStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/GdsStore.java new file mode 100644 index 0000000000..53fe55336c --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/GdsStore.java @@ -0,0 +1,114 @@ +/* + * 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.store; + +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShareInDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDatasetInProject; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; +import org.apache.ranger.plugin.model.RangerGds.RangerSharedResource; +import org.apache.ranger.plugin.util.SearchFilter; + +/** + * Interface to backing store for Data share model objects + */ + +public interface GdsStore { + void init() throws Exception; + + void setServiceStore(ServiceStore svcStore); + + ServiceStore getServiceStore(); + + + RangerDataset createDataset(RangerDataset dataset) throws Exception; + + RangerDataset updateDataset(RangerDataset dataset) throws Exception; + + void deleteDataset(Long datasetId) throws Exception; + + RangerDataset getDataset(Long datasetId) throws Exception; + + RangerDataset getDatasetByName(String name) throws Exception; + + PList getDatasetNames(SearchFilter filter) throws Exception; + + PList searchDatasets(SearchFilter filter) throws Exception; + + + RangerProject createProject(RangerProject dataset) throws Exception; + + RangerProject updateProject(RangerProject dataset) throws Exception; + + void deleteProject(Long datasetId) throws Exception; + + RangerProject getProject(Long projectId) throws Exception; + + RangerProject getProjectByName(String name) throws Exception; + + PList getProjectNames(SearchFilter filter) throws Exception; + + PList searchProjects(SearchFilter filter) throws Exception; + + + RangerDataShare createDataShare(RangerDataShare dataShare) throws Exception; + + RangerDataShare updateDataShare(RangerDataShare dataShare) throws Exception; + + void deleteDataShare(Long dataShareId) throws Exception; + + RangerDataShare getDataShare(Long dataShareId) throws Exception; + + PList searchDataShares(SearchFilter filter) throws Exception; + + + RangerSharedResource addSharedResource(RangerSharedResource resource) throws Exception; + + RangerSharedResource updateSharedResource(RangerSharedResource resource) throws Exception; + + void removeSharedResource(Long sharedResourceId) throws Exception; + + RangerSharedResource getSharedResource(Long sharedResourceId) throws Exception; + + PList searchSharedResources(SearchFilter filter) throws Exception; + + + RangerDataShareInDataset addDataShareInDataset(RangerDataShareInDataset dataShareInDataset) throws Exception; + + RangerDataShareInDataset updateDataShareInDataset(RangerDataShareInDataset dataShareInDataset) throws Exception; + + void removeDataShareInDataset(Long dataShareInDatasetId) throws Exception; + + RangerDataShareInDataset getDataShareInDataset(Long dataShareInDatasetId) throws Exception; + + PList searchDataShareInDatasets(SearchFilter filter) throws Exception; + + + RangerDatasetInProject addDatasetInProject(RangerDatasetInProject datasetInProject) throws Exception; + + RangerDatasetInProject updateDatasetInProject(RangerDatasetInProject datasetInProject) throws Exception; + + void removeDatasetInProject(Long datasetInProjectId) throws Exception; + + RangerDatasetInProject getDatasetInProject(Long datasetInProjectId) throws Exception; + + PList searchDatasetInProjects(SearchFilter filter) throws Exception; +} diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java index 4653dc31a9..c38bee9907 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java @@ -95,6 +95,20 @@ public class SearchFilter { public static final String SERVICE_DISPLAY_NAME_PARTIAL = "serviceDisplayNamePartial"; // search public static final String SERVICE_TYPE_DISPLAY_NAME = "serviceTypeDisplayName"; // search, sort + public static final String DATASET_NAME = "datasetName"; // search, sort + public static final String DATASET_ID = "datasetId"; // search, sort + public static final String PROJECT_NAME = "projectName"; // search, sort + public static final String PROJECT_ID = "projectId"; // search, sort + public static final String DATA_SHARE_NAME = "dataShareName"; // search, sort + public static final String DATA_SHARE_ID = "dataShareId"; // search, sort + public static final String SHARED_RESOURCE_NAME = "sharedResourceName"; // search, sort + public static final String SHARED_RESOURCE_ID = "sharedResourceId"; // search, sort + public static final String PROFILE_NAME = "profileName"; // search + public static final String OWNER_NAME = "ownerName"; // search + public static final String OWNER_TYPE = "ownerType"; // search: valid-values(user, group, role) + public static final String DATA_SHARE_IN_DATASET_ID = "dataShareInDatasetId"; // search, sort + public static final String DATASET_IN_PROJECT_ID = "datasetInProjectId"; // search, sort + private Map params; private int startIndex; private int maxRows = Integer.MAX_VALUE; diff --git a/agents-common/src/main/java/org/apache/ranger/services/gds/RangerServiceGds.java b/agents-common/src/main/java/org/apache/ranger/services/gds/RangerServiceGds.java new file mode 100644 index 0000000000..0f03c5a315 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/services/gds/RangerServiceGds.java @@ -0,0 +1,127 @@ +/* + * 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.services.gds; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.service.RangerBaseService; +import org.apache.ranger.plugin.service.ResourceLookupContext; +import org.apache.ranger.plugin.store.GdsStore; +import org.apache.ranger.plugin.store.PList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class RangerServiceGds extends RangerBaseService { + private static final Logger LOG = LoggerFactory.getLogger(RangerServiceGds.class); + + public static final String RESOURCE_NAME_DATASET = "dataset"; + public static final String RESOURCE_NAME_PROJECT = "project"; + + private GdsStore gdsStore; + + public RangerServiceGds() { + super(); + } + + @Override + public void init(RangerServiceDef serviceDef, RangerService service) { + super.init(serviceDef, service); + } + + public void setGdsStore(GdsStore gdsStore) { + this.gdsStore = gdsStore; + } + + @Override + public Map validateConfig() throws Exception { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceGds.validateConfig(" + serviceName + " )"); + } + + Map ret = new HashMap<>(); + + ret.put("connectivityStatus", true); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceGds.validateConfig(" + serviceName + " ): " + ret); + } + + return ret; + } + + @Override + public List lookupResource(ResourceLookupContext context) throws Exception { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceGds.lookupResource(" + context + ")"); + } + + List ret = new ArrayList<>(); + String resourceType = context != null ? context.getResourceName() : null; + List valuesToExclude = null; + List resourceNames = null; + + if (StringUtils.equals(resourceType, RESOURCE_NAME_DATASET)) { + PList datasets = gdsStore != null ? gdsStore.getDatasetNames(null) : null; + + resourceNames = datasets != null ? datasets.getList() : null; + valuesToExclude = context.getResources() != null ? context.getResources().get(RESOURCE_NAME_DATASET) : null; + } else if (StringUtils.equals(resourceType, RESOURCE_NAME_PROJECT)) { + PList projects = gdsStore != null ? gdsStore.getProjectNames(null) : null; + + resourceNames = projects != null ? projects.getList() : null; + valuesToExclude = context.getResources() != null ? context.getResources().get(RESOURCE_NAME_PROJECT) : null; + } + + if (resourceNames != null) { + if (valuesToExclude != null) { + resourceNames.removeAll(valuesToExclude); + } + + String valueToMatch = context.getUserInput(); + + if (StringUtils.isNotEmpty(valueToMatch)) { + if (!valueToMatch.endsWith("*")) { + valueToMatch += "*"; + } + + for (String resourceName : resourceNames) { + if (FilenameUtils.wildcardMatch(resourceName, valueToMatch)) { + ret.add(resourceName); + } + } + } + } + + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceGds.lookupResource(): {} count={}", resourceType, ret.size()); + } + + return ret; + } +} diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-gds.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-gds.json new file mode 100644 index 0000000000..06049183c9 --- /dev/null +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-gds.json @@ -0,0 +1,79 @@ +{ + "name": "gds", + "displayName": "Governed Data Sharing", + "implClass": "org.apache.ranger.services.gds.RangerServiceGds", + "label": "GDS", + "description": "GDS Service Definition", + "options": { + "enableDenyInPolicies": "false" + }, + "resources": [ + { + "itemId": 1, + "name": "dataset", + "type": "string", + "level": 1, + "parent": "", + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { "wildCard": false, "ignoreCase": false }, + "uiHint": "{ \"singleValue\": true }", + "label": "Dataset", + "description": "Dataset" + }, + { + "itemId": 2, + "name": "project", + "type": "string", + "level": 1, + "parent": "", + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { "wildCard": false, "ignoreCase": false }, + "uiHint": "{ \"singleValue\": true }", + "label": "Project", + "description": "Project" + } + ], + + "accessTypes": [ + { "itemId": 1, "name": "_CREATE", "label": "_CREATE" }, + { "itemId": 2, "name": "_READ", "label": "_READ" }, + { "itemId": 3, "name": "_UPDATE", "label": "_UPDATE" }, + { "itemId": 4, "name": "_DELETE", "label": "_DELETE" }, + { "itemId": 5, "name": "_MANAGE", "label": "_MANAGE" } + ], + + "configs": [ + { + "itemId": 1, + "name": "ranger.plugin.audit.filters", + "type": "string", + "mandatory": false, + "label": "Ranger Default Audit Filters", + "defaultValue": "[ {'accessResult': 'DENIED', 'isAudited': true} ]" + } + ], + + "enums": [ ], + + "contextEnrichers": [ ], + + "policyConditions": + [ + { + "itemId": 1, + "name": "expression", + "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator", + "evaluatorOptions": { "engineName":"JavaScript", "ui.isMultiline":"true" }, + "label": "Enter boolean expression", + "description": "Boolean expression" + } + ] +} diff --git a/intg/src/main/python/apache_ranger/client/ranger_gds_client.py b/intg/src/main/python/apache_ranger/client/ranger_gds_client.py new file mode 100644 index 0000000000..ea42b3e2a4 --- /dev/null +++ b/intg/src/main/python/apache_ranger/client/ranger_gds_client.py @@ -0,0 +1,254 @@ +#!/usr/bin/env python + +# +# 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. + + +import json +import logging +from apache_ranger.exceptions import RangerServiceException +from apache_ranger.client.ranger_client import RangerClient +from apache_ranger.model.ranger_base import RangerBase, PList +from apache_ranger.model.ranger_gds import * +from apache_ranger.model.ranger_policy import RangerPolicy +from apache_ranger.model.ranger_role import RangerRole +from apache_ranger.model.ranger_security_zone import RangerSecurityZone +from apache_ranger.model.ranger_service import RangerService +from apache_ranger.model.ranger_service_def import RangerServiceDef +from apache_ranger.model.ranger_service_tags import RangerServiceTags +from apache_ranger.utils import * +from requests import Session +from requests import Response +from requests.auth import AuthBase +from urllib.parse import urlencode +from urllib.parse import urljoin + +LOG = logging.getLogger(__name__) + + +class RangerGdsClient: + def __init__(self, ranger_client): + self.client_http = ranger_client.client_http + + # Data Sharing APIs + def create_dataset(self, dataset): + resp = self.client_http.call_api(RangerGdsClient.CREATE_DATASET, request_data=dataset) + + return type_coerce(resp, RangerDataset) + + def update_dataset(self, dataset_id, dataset): + resp = self.client_http.call_api(RangerGdsClient.UPDATE_DATASET_BY_ID.format_path({ 'id': dataset_id }), request_data=dataset) + + return type_coerce(resp, RangerDataset) + + def delete_dataset(self, dataset_id): + resp = self.client_http.call_api(RangerGdsClient.DELETE_DATASET_BY_ID.format_path({ 'id': dataset_id })) + + def get_dataset(self, dataset_id): + resp = self.client_http.call_api(RangerGdsClient.GET_DATASET_BY_ID.format_path({ 'id': dataset_id })) + + return type_coerce(resp, RangerDataset) + + def find_datasets(self, filter=None): + resp = self.client_http.call_api(RangerGdsClient.FIND_DATASETS, filter) + + return PList.type_coerce_plist(resp, RangerDataset) + + def get_dataset_names(self, filter=None): + resp = self.client_http.call_api(RangerGdsClient.GET_DATASET_NAMES, filter) + + return PList.type_coerce_plist(resp, str) + + def create_project(self, project): + resp = self.client_http.call_api(RangerGdsClient.CREATE_PROJECT, request_data=project) + + return type_coerce(resp, RangerDataset) + + def update_project(self, project_id, project): + resp = self.client_http.call_api(RangerGdsClient.UPDATE_PROJECT_BY_ID.format_path({ 'id': project_id }), request_data=project) + + return type_coerce(resp, RangerDataset) + + def delete_project(self, project_id): + resp = self.client_http.call_api(RangerGdsClient.DELETE_PROJECT_BY_ID.format_path({ 'id': project_id })) + + def get_project(self, project_id): + resp = self.client_http.call_api(RangerGdsClient.GET_PROJECT_BY_ID.format_path({ 'id': project_id })) + + return type_coerce(resp, RangerDataset) + + def find_projects(self, filter=None): + resp = self.client_http.call_api(RangerGdsClient.FIND_PROJECTS, filter) + + return PList.type_coerce_plist(resp, RangerDataset) + + def get_project_names(self, filter=None): + resp = self.client_http.call_api(RangerGdsClient.GET_PROJECT_NAMES, filter) + + return PList.type_coerce_plist(resp, str) + + def create_data_share(self, data_share): + resp = self.client_http.call_api(RangerGdsClient.CREATE_DATA_SHARE, request_data=data_share) + + return type_coerce(resp, RangerDataShare) + + def update_data_share(self, dsh_id, data_share): + resp = self.client_http.call_api(RangerGdsClient.UPDATE_DATA_SHARE_BY_ID.format_path({ 'id': dsh_id }), request_data=data_share) + + return type_coerce(resp, RangerDataShare) + + def delete_data_share(self, dsh_id): + resp = self.client_http.call_api(RangerGdsClient.DELETE_DATA_SHARE_BY_ID.format_path({ 'id': dsh_id })) + + def get_data_share(self, dsh_id): + resp = self.client_http.call_api(RangerGdsClient.GET_DATA_SHARE_BY_ID.format_path({ 'id': dsh_id })) + + return type_coerce(resp, RangerDataShare) + + def find_data_shares(self, filter=None): + resp = self.client_http.call_api(RangerGdsClient.FIND_DATA_SHARES, filter) + + return PList.type_coerce_plist(resp, RangerDataShare) + + def add_shared_resource(self, resource): + resp = self.client_http.call_api(RangerGdsClient.ADD_SHARED_RESOURCE, request_data=resource) + + return type_coerce(resp, RangerSharedResource) + + def update_shared_resource(self, resource_id, resource): + resp = self.client_http.call_api(RangerGdsClient.UPDATE_SHARED_RESOURCE_BY_ID.format_path({ 'id': resource_id }), request_data=resource) + + return type_coerce(resp, RangerSharedResource) + + def remove_shared_resource(self, resource_id): + resp = self.client_http.call_api(RangerGdsClient.REMOVE_SHARED_RESOURCE_BY_ID.format_path({ 'id': resource_id })) + + def get_shared_resource(self, resource_id): + resp = self.client_http.call_api(RangerGdsClient.GET_SHARED_RESOURCE_BY_ID.format_path({ 'id': resource_id })) + + return type_coerce(resp, RangerSharedResource) + + def find_shared_resources(self, filter=None): + resp = self.client_http.call_api(RangerGdsClient.FIND_SHARED_RESOURCES, filter) + + return PList.type_coerce_plist(resp, RangerSharedResource) + + def add_data_share_in_dataset(self, dshid): + resp = self.client_http.call_api(RangerGdsClient.ADD_DATA_SHARE_IN_DATASET, request_data=dshid) + + return type_coerce(resp, RangerDataShareInDataset) + + def update_data_share_in_dataset(self, dshid_id, dshid): + resp = self.client_http.call_api(RangerGdsClient.UPDATE_DATA_SHARE_IN_DATASET_BY_ID.format_path({ 'id': dshid_id }), request_data=dshid) + + return type_coerce(resp, RangerDataShareInDataset) + + def remove_data_share_in_dataset(self, dshid_id): + resp = self.client_http.call_api(RangerGdsClient.REMOVE_DATA_SHARE_IN_DATASET_BY_ID.format_path({ 'id': dshid_id })) + + def get_data_share_in_dataset(self, dshid_id): + resp = self.client_http.call_api(RangerGdsClient.GET_DATA_SHARE_IN_DATASET_BY_ID.format_path({ 'id': dshid_id })) + + return type_coerce(resp, RangerSharedResource) + + def find_data_share_in_datasets(self, filter=None): + resp = self.client_http.call_api(RangerGdsClient.FIND_DATA_SHARE_IN_DATASETS, filter) + + return PList.type_coerce_plist(resp, RangerDataShareInDataset) + + def add_dataset_in_project(self, dip): + resp = self.client_http.call_api(RangerGdsClient.ADD_DATASET_IN_PROJECT, request_data=dip) + + return type_coerce(resp, RangerDatasetInProject) + + def update_dataset_in_project(self, dip_id, dip): + resp = self.client_http.call_api(RangerGdsClient.UPDATE_DATASET_IN_PROJECT_BY_ID.format_path({ 'id': dip_id }), request_data=dip) + + return type_coerce(resp, RangerDatasetInProject) + + def remove_dataset_in_project(self, dip_id): + resp = self.client_http.call_api(RangerGdsClient.REMOVE_DATASET_IN_PROJECT_BY_ID.format_path({ 'id': dip_id })) + + def get_dataset_in_project(self, dip_id): + resp = self.client_http.call_api(RangerGdsClient.GET_DATASET_IN_PROJECT_BY_ID.format_path({ 'id': dip_id })) + + return type_coerce(resp, RangerDatasetInProject) + + def find_dataset_in_projects(self, filter=None): + resp = self.client_http.call_api(RangerGdsClient.FIND_DATASET_IN_PROJECTS, filter) + + return PList.type_coerce_plist(resp, RangerDatasetInProject) + + + # URIs + URI_GDS = "service/gds" + URI_DATASET = URI_GDS + "/dataset" + URI_DATASET_BY_ID = URI_DATASET + "/{id}" + URI_DATASET_NAMES = URI_DATASET + "/names" + URI_PROJECT = URI_GDS + "/project" + URI_PROJECT_BY_ID = URI_PROJECT + "/{id}" + URI_PROJECT_NAMES = URI_PROJECT + "/names" + URI_DATA_SHARE = URI_GDS + "/datashare" + URI_DATA_SHARE_BY_ID = URI_DATA_SHARE + "/{id}" + URI_SHARED_RESOURCE = URI_GDS + "/resource" + URI_SHARED_RESOURCE_BY_ID = URI_SHARED_RESOURCE + "/{id}" + + URI_DATA_SHARE_DATASET = URI_DATA_SHARE + "/dataset" + URI_DATA_SHARE_DATASET_BY_ID = URI_DATA_SHARE_DATASET + "/{id}" + URI_DATA_SHARE_PROJECT = URI_DATA_SHARE + "/project" + URI_DATA_SHARE_PROJECT_BY_ID = URI_DATA_SHARE_PROJECT + "/{id}" + URI_DATASET_PROJECT = URI_DATASET + "/project" + URI_DATASET_PROJECT_BY_ID = URI_DATASET_PROJECT + "/{id}" + + # APIs + + CREATE_DATASET = API(URI_DATASET, HttpMethod.POST, HTTPStatus.OK) + UPDATE_DATASET_BY_ID = API(URI_DATASET_BY_ID, HttpMethod.PUT, HTTPStatus.OK) + DELETE_DATASET_BY_ID = API(URI_DATASET_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT) + GET_DATASET_BY_ID = API(URI_DATASET_BY_ID, HttpMethod.GET, HTTPStatus.OK) + FIND_DATASETS = API(URI_DATASET, HttpMethod.GET, HTTPStatus.OK) + GET_DATASET_NAMES = API(URI_DATASET_NAMES, HttpMethod.GET, HTTPStatus.OK) + + CREATE_PROJECT = API(URI_PROJECT, HttpMethod.POST, HTTPStatus.OK) + UPDATE_PROJECT_BY_ID = API(URI_PROJECT_BY_ID, HttpMethod.PUT, HTTPStatus.OK) + DELETE_PROJECT_BY_ID = API(URI_PROJECT_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT) + GET_PROJECT_BY_ID = API(URI_PROJECT_BY_ID, HttpMethod.GET, HTTPStatus.OK) + FIND_PROJECTS = API(URI_PROJECT, HttpMethod.GET, HTTPStatus.OK) + GET_PROJECT_NAMES = API(URI_PROJECT_NAMES, HttpMethod.GET, HTTPStatus.OK) + + CREATE_DATA_SHARE = API(URI_DATA_SHARE, HttpMethod.POST, HTTPStatus.OK) + UPDATE_DATA_SHARE_BY_ID = API(URI_DATA_SHARE_BY_ID, HttpMethod.PUT, HTTPStatus.OK) + DELETE_DATA_SHARE_BY_ID = API(URI_DATA_SHARE_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT) + GET_DATA_SHARE_BY_ID = API(URI_DATA_SHARE_BY_ID, HttpMethod.GET, HTTPStatus.OK) + FIND_DATA_SHARES = API(URI_DATA_SHARE, HttpMethod.GET, HTTPStatus.OK) + + ADD_SHARED_RESOURCE = API(URI_SHARED_RESOURCE, HttpMethod.POST, HTTPStatus.OK) + UPDATE_SHARED_RESOURCE_BY_ID = API(URI_SHARED_RESOURCE_BY_ID, HttpMethod.PUT, HTTPStatus.OK) + REMOVE_SHARED_RESOURCE_BY_ID = API(URI_SHARED_RESOURCE_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT) + GET_SHARED_RESOURCE_BY_ID = API(URI_SHARED_RESOURCE_BY_ID, HttpMethod.GET, HTTPStatus.OK) + FIND_SHARED_RESOURCES = API(URI_SHARED_RESOURCE, HttpMethod.GET, HTTPStatus.OK) + + ADD_DATA_SHARE_IN_DATASET = API(URI_DATA_SHARE_DATASET, HttpMethod.POST, HTTPStatus.OK) + UPDATE_DATA_SHARE_IN_DATASET_BY_ID = API(URI_DATA_SHARE_DATASET_BY_ID, HttpMethod.PUT, HTTPStatus.OK) + REMOVE_DATA_SHARE_IN_DATASET_BY_ID = API(URI_DATA_SHARE_DATASET_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT) + GET_DATA_SHARE_IN_DATASET_BY_ID = API(URI_DATA_SHARE_DATASET_BY_ID, HttpMethod.GET, HTTPStatus.OK) + FIND_DATA_SHARE_IN_DATASETS = API(URI_DATA_SHARE_DATASET, HttpMethod.GET, HTTPStatus.OK) + + ADD_DATASET_IN_PROJECT = API(URI_DATASET_PROJECT, HttpMethod.POST, HTTPStatus.OK) + UPDATE_DATASET_IN_PROJECT_BY_ID = API(URI_DATASET_PROJECT_BY_ID, HttpMethod.PUT, HTTPStatus.OK) + REMOVE_DATASET_IN_PROJECT_BY_ID = API(URI_DATASET_PROJECT_BY_ID, HttpMethod.DELETE, HTTPStatus.NO_CONTENT) + GET_DATASET_IN_PROJECT_BY_ID = API(URI_DATASET_PROJECT_BY_ID, HttpMethod.GET, HTTPStatus.OK) + FIND_DATASET_IN_PROJECTS = API(URI_DATASET_PROJECT, HttpMethod.GET, HTTPStatus.OK) \ No newline at end of file diff --git a/intg/src/main/python/apache_ranger/model/ranger_base.py b/intg/src/main/python/apache_ranger/model/ranger_base.py index 2111534d01..afb28f0c71 100644 --- a/intg/src/main/python/apache_ranger/model/ranger_base.py +++ b/intg/src/main/python/apache_ranger/model/ranger_base.py @@ -71,3 +71,30 @@ def __init__(self, attrs=None): self.createTime = attrs.get('createTime') self.updateTime = attrs.get('updateTime') self.version = attrs.get('version') + +class PList(RangerBase): + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + + RangerBase.__init__(self, attrs) + + self.startIndex = attrs.get('startIndex') + self.pageSize = attrs.get('pageSize') + self.totalCount = attrs.get('totalCount') + self.resultSize = attrs.get('resultSize') + self.sortType = attrs.get('sortType') + self.sortBy = attrs.get('sortBy') + self.queryTimeMS = attrs.get('queryTimeMS') + self.list = attrs.get('list') + + @classmethod + def type_coerce_plist(cls, obj, objType): + if isinstance(obj, dict): + ret = PList(obj) + + ret.list = type_coerce_list(ret.list, objType) + else: + ret = None + + return ret diff --git a/intg/src/main/python/apache_ranger/model/ranger_gds.py b/intg/src/main/python/apache_ranger/model/ranger_gds.py new file mode 100644 index 0000000000..37a508f841 --- /dev/null +++ b/intg/src/main/python/apache_ranger/model/ranger_gds.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python + +# +# 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. + +from apache_ranger.model.ranger_base import RangerBase, RangerBaseModelObject +from apache_ranger.model.ranger_policy import * +from apache_ranger.model.ranger_principal import RangerPrincipal +from apache_ranger.utils import * + +class GdsPermission(StrEnum): + NONE = 'NONE' + LIST = 'LIST' + VIEW = 'VIEW' + AUDIT = 'AUDIT' + ADMIN = 'ADMIN' + + @classmethod + def value_of(cls, val): + if isinstance(val, GdsPermission): + return val + else: + for key, member in cls.__members__.items(): + if val == member.name or val == member.value: + return member + else: + raise ValueError(f"'{cls.__name__}' enum not found for '{val}'") + +class GdsShareStatus(StrEnum): + NONE = 'NONE' + REQUESTED = 'REQUESTED' + GRANTED = 'GRANTED' + ACCEPTED = 'ACCEPTED' + ACTIVE = 'ACTIVE' + + @classmethod + def value_of(cls, val): + if isinstance(val, GdsShareStatus): + return val + else: + for key, member in cls.__members__.items(): + if val == member.name or val == member.value: + return member + else: + raise ValueError(f"'{cls.__name__}' enum not found for '{val}'") + +class RangerGdsBaseModelObject(RangerBaseModelObject): + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + + RangerBaseModelObject.__init__(self, attrs) + + self.description = attrs.get('description') + self.options = attrs.get('options') + self.additionalInfo = attrs.get('additionalInfo') + + def type_coerce_attrs(self): + super(RangerGdsBaseModelObject, self).type_coerce_attrs() + + +class RangerDataset(RangerGdsBaseModelObject): + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + + RangerGdsBaseModelObject.__init__(self, attrs) + + self.name = attrs.get('name') + self.owners = attrs.get('owners') + self.acl = attrs.get('acl') + self.termsOfUse = attrs.get('termsOfUse') + + def type_coerce_attrs(self): + super(RangerDataset, self).type_coerce_attrs() + + self.owners = type_coerce_list(self.owners, RangerPrincipal) + self.acl = type_coerce_dict(self.acl, RangerGdsACL) + + +class RangerProject(RangerGdsBaseModelObject): + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + + RangerGdsBaseModelObject.__init__(self, attrs) + + self.name = attrs.get('name') + self.owners = attrs.get('owners') + self.acl = attrs.get('acl') + self.termsOfUse = attrs.get('termsOfUse') + + def type_coerce_attrs(self): + super(RangerProject, self).type_coerce_attrs() + + self.owners = type_coerce_list(self.owners, RangerPrincipal) + self.acl = type_coerce_dict(self.acl, RangerGdsACL) + + +class RangerDataShare(RangerGdsBaseModelObject): + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + + RangerGdsBaseModelObject.__init__(self, attrs) + + self.name = attrs.get('name') + self.owners = attrs.get('owners') + self.service = attrs.get('service') + self.zone = attrs.get('zone') + self.condition = attrs.get('condition') + self.defaultAccessTypes = attrs.get('defaultAccessTypes') + self.defaultMasks = attrs.get('defaultMasks') + self.termsOfUse = attrs.get('termsOfUse') + + def type_coerce_attrs(self): + super(RangerDataShare, self).type_coerce_attrs() + + self.owners = type_coerce_list(self.owners, RangerPrincipal) + self.defaultMasks = type_coerce_dict(self.defaultMasks, RangerPolicyItemDataMaskInfo) + + +class RangerSharedResource(RangerBaseModelObject): + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + + RangerBaseModelObject.__init__(self, attrs) + + self.name = attrs.get('name') + self.dataShareId = attrs.get('dataShareId') + self.resource = attrs.get('resource') + self.subResourceNames = attrs.get('subResourceNames') + self.resourceSignature = attrs.get('resourceSignature') + self.condition = attrs.get('condition') + self.accessTypes = attrs.get('accessTypes') + self.rowFilter = attrs.get('rowFilter') + self.subResourceMasks = attrs.get('subResourceMasks') + self.profiles = attrs.get('profiles') + + def type_coerce_attrs(self): + super(RangerSharedResource, self).type_coerce_attrs() + + self.resource = type_coerce_dict(self.resource, RangerPolicyResource) + self.rowFilter = type_coerce(self.rowFilter, RangerPolicyItemRowFilterInfo) + self.subResourceMasks = type_coerce_dict(self.subResourceMasks, RangerPolicyItemDataMaskInfo) + + +class RangerDataShareInDataset(RangerGdsBaseModelObject): + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + + RangerGdsBaseModelObject.__init__(self, attrs) + + self.dataShareId = attrs.get('dataShareId') + self.datasetId = attrs.get('datasetId') + self.status = attrs.get('status') + self.validitySchedule = attrs.get('validitySchedule') + self.profiles = attrs.get('profiles') + + def type_coerce_attrs(self): + super(RangerDataShareInDataset, self).type_coerce_attrs() + + self.status = type_coerce(self.status, GdsShareStatus) + self.validitySchedule = type_coerce(self.validitySchedule, RangerValiditySchedule) + + +class RangerDatasetInProject(RangerGdsBaseModelObject): + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + + RangerGdsBaseModelObject.__init__(self, attrs) + + self.datasetId = attrs.get('datasetId') + self.projectId = attrs.get('projectId') + self.status = attrs.get('status') + self.validitySchedule = attrs.get('validitySchedule') + self.profiles = attrs.get('profiles') + + def type_coerce_attrs(self): + super(RangerDatasetInProject, self).type_coerce_attrs() + + self.status = type_coerce(self.status, GdsShareStatus) + self.validitySchedule = type_coerce(self.validitySchedule, RangerValiditySchedule) + + +class RangerGdsACL(RangerBase): + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + + RangerBase.__init__(self, attrs) + + self.users = attrs.get('users') + self.groups = attrs.get('groups') + self.roles = attrs.get('roles') + + def type_coerce_attrs(self): + super(RangerGdsACL, self).type_coerce_attrs() + + self.users = type_coerce_dict(self.users, GdsPermission) + self.groups = type_coerce_dict(self.groups, GdsPermission) + self.roles = type_coerce_dict(self.roles, GdsPermission) diff --git a/intg/src/main/python/apache_ranger/model/ranger_policy.py b/intg/src/main/python/apache_ranger/model/ranger_policy.py index 3cd916a31e..3a8340c1bf 100644 --- a/intg/src/main/python/apache_ranger/model/ranger_policy.py +++ b/intg/src/main/python/apache_ranger/model/ranger_policy.py @@ -59,7 +59,7 @@ def type_coerce_attrs(self): super(RangerPolicy, self).type_coerce_attrs() self.resources = type_coerce_dict(self.resources, RangerPolicyResource) - self.additionalResources = type_coerce_list(self.additionalResources, dict) + self.additionalResources = type_coerce_list_dict(self.additionalResources, RangerPolicyResource) self.policyItems = type_coerce_list(self.policyItems, RangerPolicyItem) self.denyPolicyItems = type_coerce_list(self.denyPolicyItems, RangerPolicyItem) self.allowExceptions = type_coerce_list(self.allowExceptions, RangerPolicyItem) @@ -67,16 +67,7 @@ def type_coerce_attrs(self): self.dataMaskPolicyItems = type_coerce_list(self.dataMaskPolicyItems, RangerDataMaskPolicyItem) self.rowFilterPolicyItems = type_coerce_list(self.rowFilterPolicyItems, RangerRowFilterPolicyItem) self.validitySchedules = type_coerce_list(self.validitySchedules, RangerValiditySchedule) - - if isinstance(self.additionalResources, list): - additionalResources = [] - - for entry in self.additionalResources: - additionalResources.append(type_coerce_dict(entry, RangerPolicyResource)) - - self.additionalResources = additionalResources - else: - self.additionalResources = None + self.conditions = type_coerce_list(self.conditions, RangerPolicyItemCondition) def add_resource(self, resource): if resource is not None: @@ -128,7 +119,8 @@ def __init__(self, attrs=None): def type_coerce_attrs(self): super(RangerPolicyItem, self).type_coerce_attrs() - self.accesses = type_coerce_list(self.accesses, RangerPolicyItemAccess) + self.accesses = type_coerce_list(self.accesses, RangerPolicyItemAccess) + self.conditions = type_coerce_list(self.conditions, RangerPolicyItemCondition) class RangerDataMaskPolicyItem(RangerPolicyItem): diff --git a/intg/src/main/python/apache_ranger/model/ranger_principal.py b/intg/src/main/python/apache_ranger/model/ranger_principal.py new file mode 100644 index 0000000000..31db72e13c --- /dev/null +++ b/intg/src/main/python/apache_ranger/model/ranger_principal.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +# +# 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. + +from apache_ranger.model.ranger_base import RangerBase +from apache_ranger.utils import * + + +class PrincipalType(StrEnum): + USER = 'USER' + GROUP = 'GROUP' + ROLE = 'ROLE' + + @classmethod + def value_of(cls, val): + if isinstance(val, PrincipalType): + return val + else: + for key, member in cls.__members__.items(): + if val == member.name or val == member.value: + return member + else: + raise ValueError(f"'{cls.__name__}' enum not found for '{val}'") + + +class RangerPrincipal(RangerBase): + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + + RangerBase.__init__(self, attrs) + + self.type = attrs.get('type') + self.name = attrs.get('name') + + def type_coerce_attrs(self): + super(RangerPrincipal, self).type_coerce_attrs() + + self.type = type_coerce(self.type, PrincipalType) diff --git a/intg/src/main/python/apache_ranger/utils.py b/intg/src/main/python/apache_ranger/utils.py index 28e0e4b602..d5da7bef7f 100644 --- a/intg/src/main/python/apache_ranger/utils.py +++ b/intg/src/main/python/apache_ranger/utils.py @@ -32,6 +32,11 @@ def type_coerce(obj, objType): if callable(getattr(ret, 'type_coerce_attrs', None)): ret.type_coerce_attrs() + elif issubclass(objType, enum.Enum): + try: + ret = objType.value_of(obj) + except AttributeError: # value_of() method not defined in Enum class + ret = None else: ret = None @@ -85,6 +90,17 @@ class HttpMethod(enum.Enum): POST = "POST" DELETE = "DELETE" + @classmethod + def value_of(cls, val): + if isinstance(val, HttpMethod): + return val + else: + for key, member in cls.__members__.items(): + if val == member.name or val == member.value: + return member + else: + raise ValueError(f"'{cls.__name__}' enum not found for '{val}'") + class HTTPStatus: OK = 200 @@ -107,4 +123,5 @@ class HTTPStatus: INTERNAL_SERVER_ERROR = 500 SERVICE_UNAVAILABLE = 503 - +class StrEnum(str, enum.Enum): + """Enum where members are also (and must be) strings""" diff --git a/ranger-examples/sample-client/src/main/python/sample_gds_client.py b/ranger-examples/sample-client/src/main/python/sample_gds_client.py new file mode 100644 index 0000000000..6facd40407 --- /dev/null +++ b/ranger-examples/sample-client/src/main/python/sample_gds_client.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python + +# +# 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. + + +from apache_ranger.client.ranger_client import * +from apache_ranger.client.ranger_gds_client import * +from apache_ranger.model.ranger_gds import * +from apache_ranger.model.ranger_policy import * +from apache_ranger.model.ranger_principal import * + +ranger_url = 'http://localhost:6080' +ranger_auth = ('admin', 'rangerR0cks!') + +ranger = RangerClient(ranger_url, ranger_auth) +gds = RangerGdsClient(ranger) + + +dataset_1 = RangerDataset({ 'name': 'dataset-1', 'description': 'the first dataset!', 'owners': [ { 'type': PrincipalType.USER, 'name': 'John.Doe' } ], 'acl': {}, 'termsOfUse': None }) +dataset_2 = RangerDataset({ 'name': 'dataset-2', 'description': 'the second dataset!', 'owners': [ { 'type': PrincipalType.GROUP, 'name': 'sales' } ], 'acl': {}, 'termsOfUse': None }) + +project_1 = RangerProject({ 'name': 'project-1', 'description': 'the first project!', 'owners': [ { 'type': PrincipalType.USER, 'name': 'Diane.Scott' } ], 'acl': {}, 'termsOfUse': None }) +project_2 = RangerProject({ 'name': 'project-2', 'description': 'the second project!', 'owners': [ { 'type': PrincipalType.GROUP, 'name': 'marketing' } ], 'acl': {}, 'termsOfUse': None }) + +hive_share_1 = RangerDataShare({ 'name': 'datashare-1', 'description': 'the first datashare!', 'owners': [ { 'type': PrincipalType.USER, 'name': 'Sandy.Williams' } ], 'termsOfUse': None }) +hive_share_1.service = 'dev_hive' +hive_share_1.zone = None +hive_share_1.condition = "HAS_TAG('SCAN_COMPLETE')" +hive_share_1.defaultAccessTypes = [ '_READ' ] +hive_share_1.defaultMasks = { 'HAS_TAG("PII")': { 'dataMaskType': 'MASK' } } + +hdfs_share_1 = RangerDataShare({ 'name': 'datashare-2', 'description': 'the second datashare!', 'owners': [ { 'type': PrincipalType.GROUP, 'name': 'finance' } ], 'termsOfUse': None }) +hdfs_share_1.service = 'dev_hdfs' +hdfs_share_1.zone = None +hdfs_share_1.condition = "HAS_TAG('SCAN_COMPLETE')" +hdfs_share_1.defaultAccessTypes = [ '_READ' ] +hdfs_share_1.defaultMasks = None + +print(f'Creating dataset: name={dataset_1.name}') +dataset_1 = gds.create_dataset(dataset_1) +print(f' created dataset: {dataset_1}') + +print(f'Creating dataset: name={dataset_2.name}') +dataset_2 = gds.create_dataset(dataset_2) +print(f' created dataset: {dataset_2}') + +print(f'Creating project: name={project_1.name}') +project_1 = gds.create_project(project_1) +print(f' created project: {project_1}') + +print(f'Creating project: name={project_2.name}') +project_2 = gds.create_project(project_2) +print(f' created project: {project_2}') + +print(f'Creating data_share: name={hive_share_1.name}') +hive_share_1 = gds.create_data_share(hive_share_1) +print(f' created data_share: {hive_share_1}') + +print(f'Creating data_share: name={hdfs_share_1.name}') +hdfs_share_1 = gds.create_data_share(hdfs_share_1) +print(f' created data_share: {hdfs_share_1}') + + +hive_resource_1 = RangerSharedResource({ 'dataShareId': hive_share_1.id, 'name': 'db1.tbl1' }) +hive_resource_1.resource = { 'database': { 'values': ['db1'] }, 'table': { 'values': ['tbl1'] } } +hive_resource_1.subResourceNames = [ 'col1', 'col2' ] +hive_resource_1.condition = "HAS_TAG('SCAN_COMPLETE') && !HAS_TAG('PII') && TAGS['DATA_QUALITY'].score > 0.8" +hive_resource_1.accessTypes = [ '_READ' ] +hive_resource_1.rowFilter = { 'filterExpr': "country = 'US'" } +hive_resource_1.subResourceMasks = { 'col1': { 'dataMaskType': 'MASK' } } +hive_resource_1.profiles = [ 'GDPR', 'HIPPA' ] + +hive_resource_2 = RangerSharedResource({ 'dataShareId': hive_share_1.id, 'name': 'db2.tbl2' }) +hive_resource_2.resource = { 'database': { 'values': ['db2'] }, 'table': { 'values': ['tbl2'] } } +hive_resource_2.subResourceNames = [ '*' ] +hive_resource_2.accessTypes = [ '_READ', '_WRITE' ] +hive_resource_2.profiles = [ 'GDPR' ] + +hdfs_resource_1 = RangerSharedResource({ 'dataShareId': hdfs_share_1.id, 'name': '/home/dept/sales'}) +hdfs_resource_1.resource = { 'path': { 'values': [ '/home/dept/sales' ], 'isRecursive': True } } +hdfs_resource_1.profiles = [ 'GDPR' ] + +print(f'Adding shared resource: ') +hive_resource_1 = gds.add_shared_resource(hive_resource_1) +print(f' created shared resource: {hive_resource_1}') + +print(f'Adding shared resource: ') +hive_resource_2 = gds.add_shared_resource(hive_resource_2) +print(f' created shared resource: {hive_resource_2}') + +print(f'Adding shared resource: ') +hdfs_resource_1 = gds.add_shared_resource(hdfs_resource_1) +print(f' created shared resource: {hdfs_resource_1}') + + +dshid_1 = RangerDataShareInDataset({ 'dataShareId': hive_share_1.id, 'datasetId': dataset_1.id, 'status': GdsShareStatus.GRANTED, 'validitySchedule': { 'startTime': '2023/01/01', 'endTime': '2023/04/01' } }) +dshid_2 = RangerDataShareInDataset({ 'dataShareId': hdfs_share_1.id, 'datasetId': dataset_2.id, 'status': GdsShareStatus.REQUESTED }) + +print(f'Adding data_share_in_dataset: ') +dshid_1 = gds.add_data_share_in_dataset(dshid_1) +print(f' created data_share_in_dataset: {dshid_1}') + +print(f'Adding data_share_in_dataset: ') +dshid_2 = gds.add_data_share_in_dataset(dshid_2) +print(f' created data_share_in_dataset: {dshid_2}') + +print(f'Updating data_share_in_dataset: id={dshid_1.id}') +dshid_1.status = GdsShareStatus.ACCEPTED +dshid_1 = gds.update_data_share_in_dataset(dshid_1.id, dshid_1) +print(f' updated data_share_in_dataset: {dshid_1}') + +print(f'Updating data_share_in_dataset: id={dshid_2.id}') +dshid_2.status = GdsShareStatus.GRANTED +dshid_2.validitySchedule = { 'startTime': '2023/02/01', 'endTime': '2023/03/01' } +dshid_2 = gds.update_data_share_in_dataset(dshid_2.id, dshid_2) +print(f' updated data_share_in_dataset: {dshid_2}') + + +d1_in_p1 = RangerDatasetInProject({ 'datasetId': dataset_1.id, 'projectId': project_1.id, 'status': GdsShareStatus.GRANTED, 'validitySchedule': { 'startTime': '2023/01/01', 'endTime': '2023/04/01' }}) +d1_in_p2 = RangerDatasetInProject({ 'datasetId': dataset_1.id, 'projectId': project_2.id, 'status': GdsShareStatus.GRANTED, 'validitySchedule': { 'startTime': '2023/01/01', 'endTime': '2023/04/01' }}) +d2_in_p2 = RangerDatasetInProject({ 'datasetId': dataset_2.id, 'projectId': project_2.id, 'status': GdsShareStatus.REQUESTED }) + +print(f'Creating dataset_in_project: {d1_in_p1.name}') +d1_in_p1 = gds.add_dataset_in_project(d1_in_p1) +print(f' created dataset_in_project: {d1_in_p1}') + +print(f'Creating dataset_in_project: {d1_in_p2.name}') +d1_in_p2 = gds.add_dataset_in_project(d1_in_p2) +print(f' created dataset_in_project: {d1_in_p2}') + +print(f'Creating dataset_in_project: {d2_in_p2.name}') +d2_in_p2 = gds.add_dataset_in_project(d2_in_p2) +print(f' created dataset_in_project: {d2_in_p2}') + +print(f'Updating dataset_in_project: id={d2_in_p2.id}') +d2_in_p2.status = GdsShareStatus.GRANTED +d2_in_p2 = gds.update_dataset_in_project(d2_in_p2.id, d2_in_p2) +print(f' updated dataset_in_project: {d2_in_p2}') + + +print(f'Removing dataset_in_project: id={d1_in_p1.id}') +gds.remove_dataset_in_project(d1_in_p1.id) +print(f' deleted dataset_in_project: id={d1_in_p1.id}') + +print(f'Removing dataset_in_project: id={d1_in_p2.id}') +gds.remove_dataset_in_project(d1_in_p2.id) +print(f' deleted dataset_in_project: id={d1_in_p2.id}') + +print(f'Removing dataset_in_project: id={d2_in_p2.id}') +gds.remove_dataset_in_project(d2_in_p2.id) +print(f' deleted dataset_in_project: id={d2_in_p2.id}') + +print(f'Removing data_share_in_dataset: id={dshid_1.id}') +gds.remove_data_share_in_dataset(dshid_1.id) +print(f' deleted data_share_in_dataset: id={dshid_1.id}') + +print(f'Removing data_share_in_dataset: id={dshid_2.id}') +gds.remove_data_share_in_dataset(dshid_2.id) +print(f' deleted data_share_in_dataset: id={dshid_2.id}') + +print(f'Removing shared_resource: id={hive_resource_1.id}') +gds.remove_shared_resource(hive_resource_1.id) +print(f' removed shared_resource: id={hive_resource_1.id}') + +print(f'Removing shared_resource: id={hive_resource_2.id}') +gds.remove_shared_resource(hive_resource_2.id) +print(f' removed shared_resource: id={hive_resource_2.id}') + +print(f'Removing shared_resource: id={hdfs_resource_1.id}') +gds.remove_shared_resource(hdfs_resource_1.id) +print(f' removed shared_resource: id={hdfs_resource_1.id}') + +print(f'Deleting data_share: id={hive_share_1.id}') +gds.delete_data_share(hive_share_1.id) +print(f' deleted data_share: id={hive_share_1.id}') + +print(f'Deleting data_share: id={hdfs_share_1.id}') +gds.delete_data_share(hdfs_share_1.id) +print(f' deleted data_share: id={hdfs_share_1.id}') + +print(f'Deleting project: id={project_1.id}') +gds.delete_project(project_1.id) +print(f' deleted project: id={project_1.id}') + +print(f'Deleting project: id={project_2.id}') +gds.delete_project(project_2.id) +print(f' deleted project: id={project_2.id}') + +print(f'Deleting dataset: id={dataset_1.id}') +gds.delete_dataset(dataset_1.id) +print(f' deleted dataset: id={dataset_1.id}') + +print(f'Deleting dataset: id={dataset_2.id}') +gds.delete_dataset(dataset_2.id) +print(f' deleted dataset: id={dataset_2.id}') diff --git a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql index 8dd90c1b8f..1fb994b721 100644 --- a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql +++ b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql @@ -89,6 +89,12 @@ DROP TABLE IF EXISTS xa_access_audit CASCADE; DROP TABLE IF EXISTS x_portal_user_role CASCADE; DROP TABLE IF EXISTS x_portal_user CASCADE; DROP TABLE IF EXISTS x_db_version_h CASCADE; +DROP TABLE IF EXISTS x_gds_dataset CASCADE; +DROP TABLE IF EXISTS x_gds_project CASCADE; +DROP TABLE IF EXISTS x_gds_data_share CASCADE; +DROP TABLE IF EXISTS x_gds_shared_resource CASCADE; +DROP TABLE IF EXISTS x_gds_data_share_in_dataset CASCADE; +DROP TABLE IF EXISTS x_gds_dataset_in_project CASCADE; DROP SEQUENCE IF EXISTS x_sec_zone_ref_group_seq; DROP SEQUENCE IF EXISTS x_sec_zone_ref_user_seq; @@ -164,6 +170,12 @@ DROP SEQUENCE IF EXISTS X_RMS_SERVICE_RESOURCE_SEQ; DROP SEQUENCE IF EXISTS X_RMS_NOTIFICATION_SEQ; DROP SEQUENCE IF EXISTS X_RMS_RESOURCE_MAPPING_SEQ; DROP SEQUENCE IF EXISTS X_RMS_MAPPING_PROVIDER_SEQ; +DROP SEQUENCE IF EXISTS X_GDS_DATASET_SEQ; +DROP SEQUENCE IF EXISTS X_GDS_PROJECT_SEQ; +DROP SEQUENCE IF EXISTS X_GDS_DATA_SHARE_SEQ; +DROP SEQUENCE IF EXISTS X_GDS_SHARED_RESOURCE_SEQ; +DROP SEQUENCE IF EXISTS X_GDS_DATA_SHARE_IN_DATASET_SEQ; +DROP SEQUENCE IF EXISTS X_GDS_DATASET_IN_PROJECT_SEQ; create table x_db_version_h( id SERIAL primary key, @@ -1653,6 +1665,184 @@ CONSTRAINT x_rms_mapping_provider_UK_name UNIQUE(name) ); commit; +CREATE SEQUENCE X_GDS_DATASET_SEQ; +CREATE TABLE x_gds_dataset ( + id BIGINT NOT NULL DEFAULT nextval('X_GDS_DATASET_SEQ'::regclass) + , guid VARCHAR(64) NOT NULL + , create_time TIMESTAMP NULL DEFAULT NULL + , update_time TIMESTAMP NULL DEFAULT NULL + , added_by_id BIGINT NULL DEFAULT NULL + , upd_by_id BIGINT NULL DEFAULT NULL + , version BIGINT NOT NULL DEFAULT 1 + , is_enabled BOOLEAN NOT NULL DEFAULT '1' + , name VARCHAR(512) NOT NULL + , description TEXT NULL DEFAULT NULL + , owners TEXT NOT NULL + , acl TEXT NULL DEFAULT NULL + , terms_of_use TEXT NULL DEFAULT NULL + , options TEXT NULL DEFAULT NULL + , additional_info TEXT NULL DEFAULT NULL + , PRIMARY KEY(id) + , CONSTRAINT x_gds_dataset_UK_name UNIQUE(name) + , CONSTRAINT x_gds_dataset_FK_added_by_id FOREIGN KEY(added_by_id) REFERENCES x_portal_user(id) + , CONSTRAINT x_gds_dataset_FK_upd_by_id FOREIGN KEY(upd_by_id) REFERENCES x_portal_user(id) +); +CREATE INDEX x_gds_dataset_guid ON x_gds_dataset(guid); +commit; + +CREATE SEQUENCE X_GDS_PROJECT_SEQ; +CREATE TABLE x_gds_project ( + id BIGINT NOT NULL DEFAULT nextval('X_GDS_PROJECT_SEQ'::regclass) + , guid VARCHAR(64) NOT NULL + , create_time TIMESTAMP NULL DEFAULT NULL + , update_time TIMESTAMP NULL DEFAULT NULL + , added_by_id BIGINT NULL DEFAULT NULL + , upd_by_id BIGINT NULL DEFAULT NULL + , version BIGINT NOT NULL DEFAULT 1 + , is_enabled BOOLEAN NOT NULL DEFAULT '1' + , name VARCHAR(512) NOT NULL + , description TEXT NULL DEFAULT NULL + , owners TEXT NOT NULL + , acl TEXT NULL DEFAULT NULL + , terms_of_use TEXT NULL DEFAULT NULL + , options TEXT NULL DEFAULT NULL + , additional_info TEXT NULL DEFAULT NULL + , PRIMARY KEY(id) + , CONSTRAINT x_gds_project_UK_name UNIQUE(name) + , CONSTRAINT x_gds_project_FK_added_by_id FOREIGN KEY(added_by_id) REFERENCES x_portal_user(id) + , CONSTRAINT x_gds_project_FK_upd_by_id FOREIGN KEY(upd_by_id) REFERENCES x_portal_user(id) +); +CREATE INDEX x_gds_project_guid ON x_gds_project(guid); +commit; + +CREATE SEQUENCE X_GDS_DATA_SHARE_SEQ; +CREATE TABLE x_gds_data_share( + id BIGINT NOT NULL DEFAULT nextval('X_GDS_DATA_SHARE_SEQ'::regclass) + , guid VARCHAR(64) NOT NULL + , create_time TIMESTAMP NULL DEFAULT NULL + , update_time TIMESTAMP NULL DEFAULT NULL + , added_by_id BIGINT NULL DEFAULT NULL + , upd_by_id BIGINT NULL DEFAULT NULL + , version BIGINT NOT NULL DEFAULT 1 + , is_enabled BOOLEAN NOT NULL DEFAULT '1' + , name VARCHAR(512) NOT NULL + , description TEXT NULL DEFAULT NULL + , owners TEXT NOT NULL + , service_id BIGINT NOT NULL + , zone_id BIGINT NOT NULL + , condition TEXT NULL + , default_access_types TEXT NULL + , default_masks TEXT NULL + , terms_of_use TEXT NULL DEFAULT NULL + , options TEXT NULL DEFAULT NULL + , additional_info TEXT NULL DEFAULT NULL + , PRIMARY KEY(id) + , CONSTRAINT x_gds_data_share_UK_name UNIQUE(service_id, zone_id, name) + , CONSTRAINT x_gds_data_share_FK_added_by_id FOREIGN KEY(added_by_id) REFERENCES x_portal_user(id) + , CONSTRAINT x_gds_data_share_FK_upd_by_id FOREIGN KEY(upd_by_id) REFERENCES x_portal_user(id) + , CONSTRAINT x_gds_data_share_FK_service_id FOREIGN KEY(service_id) REFERENCES x_service(id) + , CONSTRAINT x_gds_data_share_FK_zone_id FOREIGN KEY(zone_id) REFERENCES x_security_zone(id) +); +CREATE INDEX x_gds_data_share_guid ON x_gds_data_share(guid); +CREATE INDEX x_gds_data_share_service_id ON x_gds_data_share(service_id); +CREATE INDEX x_gds_data_share_zone_id ON x_gds_data_share(zone_id); +commit; + +CREATE SEQUENCE X_GDS_SHARED_RESOURCE_SEQ; +CREATE TABLE x_gds_shared_resource( + id BIGINT NOT NULL DEFAULT nextval('X_GDS_SHARED_RESOURCE_SEQ'::regclass) + , guid VARCHAR(64) NOT NULL + , create_time TIMESTAMP NULL DEFAULT NULL + , update_time TIMESTAMP NULL DEFAULT NULL + , added_by_id BIGINT NULL DEFAULT NULL + , upd_by_id BIGINT NULL DEFAULT NULL + , version BIGINT NOT NULL DEFAULT 1 + , is_enabled BOOLEAN NOT NULL DEFAULT '1' + , name VARCHAR(512) NOT NULL + , description TEXT NULL DEFAULT NULL + , data_share_id BIGINT NOT NULL + , resource TEXT NOT NULL + , resource_signature VARCHAR(128) NOT NULL + , sub_resource_names TEXT NULL DEFAULT NULL + , condition TEXT NULL DEFAULT NULL + , access_types TEXT NULL DEFAULT NULL + , row_filter TEXT NULL DEFAULT NULL + , sub_resource_masks TEXT NULL DEFAULT NULL + , profiles TEXT NULL DEFAULT NULL + , options TEXT NULL DEFAULT NULL + , additional_info TEXT NULL DEFAULT NULL + , PRIMARY KEY(id) + , CONSTRAINT x_gds_shared_resource_UK_name UNIQUE(data_share_id, name) + , CONSTRAINT x_gds_shared_resource_FK_added_by_id FOREIGN KEY(added_by_id) REFERENCES x_portal_user(id) + , CONSTRAINT x_gds_shared_resource_FK_upd_by_id FOREIGN KEY(upd_by_id) REFERENCES x_portal_user(id) + , CONSTRAINT x_gds_shared_resource_FK_data_share_id FOREIGN KEY(data_share_id) REFERENCES x_gds_data_share(id) +); +CREATE INDEX x_gds_shared_resource_guid ON x_gds_shared_resource(guid); +CREATE INDEX x_gds_shared_resource_data_share_id ON x_gds_shared_resource(data_share_id); +commit; + +CREATE SEQUENCE X_GDS_DATA_SHARE_IN_DATASET_SEQ; +CREATE TABLE x_gds_data_share_in_dataset( + id BIGINT NOT NULL DEFAULT nextval('X_GDS_SHARED_RESOURCE_SEQ'::regclass) + , guid VARCHAR(64) NOT NULL + , create_time TIMESTAMP NULL DEFAULT NULL + , update_time TIMESTAMP NULL DEFAULT NULL + , added_by_id BIGINT NULL DEFAULT NULL + , upd_by_id BIGINT NULL DEFAULT NULL + , version BIGINT NOT NULL DEFAULT 1 + , is_enabled BOOLEAN NOT NULL DEFAULT '1' + , description TEXT NULL DEFAULT NULL + , data_share_id BIGINT NOT NULL + , dataset_id BIGINT NOT NULL + , status SMALLINT NOT NULL + , validity_period TEXT NULL DEFAULT NULL + , profiles TEXT NULL DEFAULT NULL + , options TEXT NULL DEFAULT NULL + , additional_info TEXT NULL DEFAULT NULL + , PRIMARY KEY(id) + , CONSTRAINT x_gds_dshid_FK_added_by_id FOREIGN KEY(added_by_id) REFERENCES x_portal_user(id) + , CONSTRAINT x_gds_dshid_FK_upd_by_id FOREIGN KEY(upd_by_id) REFERENCES x_portal_user(id) + , CONSTRAINT x_gds_dshid_FK_data_share_id FOREIGN KEY(data_share_id) REFERENCES x_gds_data_share(id) + , CONSTRAINT x_gds_dshid_FK_dataset_id FOREIGN KEY(dataset_id) REFERENCES x_gds_dataset(id) + , CONSTRAINT x_gds_dshid_UK_data_share_id_dataset_id UNIQUE(data_share_id, dataset_id) +); +CREATE INDEX x_gds_dshid_guid ON x_gds_data_share_in_dataset(guid); +CREATE INDEX x_gds_dshid_data_share_id ON x_gds_data_share_in_dataset(data_share_id); +CREATE INDEX x_gds_dshid_dataset_id ON x_gds_data_share_in_dataset(dataset_id); +CREATE INDEX x_gds_dshid_data_share_id_dataset_id ON x_gds_data_share_in_dataset(data_share_id, dataset_id); +commit; + +CREATE SEQUENCE X_GDS_DATASET_IN_PROJECT_SEQ; +CREATE TABLE x_gds_dataset_in_project( + id BIGINT NOT NULL DEFAULT nextval('X_GDS_DATASET_IN_PROJECT_SEQ'::regclass) + , guid VARCHAR(64) NOT NULL + , create_time TIMESTAMP NULL DEFAULT NULL + , update_time TIMESTAMP NULL DEFAULT NULL + , added_by_id BIGINT NULL DEFAULT NULL + , upd_by_id BIGINT NULL DEFAULT NULL + , version BIGINT NOT NULL DEFAULT 1 + , is_enabled BOOLEAN NOT NULL DEFAULT '1' + , description TEXT NULL DEFAULT NULL + , dataset_id BIGINT NOT NULL + , project_id BIGINT NOT NULL + , status SMALLINT NOT NULL + , validity_period TEXT NULL DEFAULT NULL + , profiles TEXT NULL DEFAULT NULL + , options TEXT NULL DEFAULT NULL + , additional_info TEXT NULL DEFAULT NULL + , PRIMARY KEY(id) + , CONSTRAINT x_gds_dip_FK_added_by_id FOREIGN KEY(added_by_id) REFERENCES x_portal_user(id) + , CONSTRAINT x_gds_dip_FK_upd_by_id FOREIGN KEY(upd_by_id) REFERENCES x_portal_user(id) + , CONSTRAINT x_gds_dip_FK_dataset_id FOREIGN KEY(dataset_id) REFERENCES x_gds_dataset(id) + , CONSTRAINT x_gds_dip_FK_project_id FOREIGN KEY(project_id) REFERENCES x_gds_project(id) + , CONSTRAINT x_gds_dip_UK_data_share_id_dataset_id UNIQUE(dataset_id, project_id) +); +CREATE INDEX x_gds_dip_guid ON x_gds_dataset_in_project(guid); +CREATE INDEX x_gds_dip_dataset_id ON x_gds_dataset_in_project(dataset_id); +CREATE INDEX x_gds_dip_project_id ON x_gds_dataset_in_project(project_id); +commit; + + CREATE INDEX x_tag_change_log_IDX_service_id ON x_tag_change_log(service_id); CREATE INDEX x_tag_change_log_IDX_tag_version ON x_tag_change_log(service_tags_version); commit; diff --git a/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java new file mode 100644 index 0000000000..817bc3d383 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java @@ -0,0 +1,811 @@ +/* + * 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.biz; + +import org.apache.commons.lang3.StringUtils; +import org.apache.ranger.common.GUIDUtil; +import org.apache.ranger.common.db.RangerTransactionSynchronizationAdapter; +import org.apache.ranger.db.RangerDaoManager; +import org.apache.ranger.db.XXGdsDataShareInDatasetDao; +import org.apache.ranger.db.XXGdsDatasetDao; +import org.apache.ranger.db.XXGdsDatasetInProjectDao; +import org.apache.ranger.db.XXGdsProjectDao; +import org.apache.ranger.entity.XXGdsDataShareInDataset; +import org.apache.ranger.entity.XXGdsDataset; +import org.apache.ranger.entity.XXGdsDatasetInProject; +import org.apache.ranger.entity.XXGdsProject; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShareInDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDatasetInProject; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; +import org.apache.ranger.plugin.model.RangerGds.RangerSharedResource; +import org.apache.ranger.plugin.model.RangerPolicyResourceSignature; +import org.apache.ranger.plugin.store.AbstractGdsStore; +import org.apache.ranger.plugin.store.PList; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.service.RangerGdsDataShareService; +import org.apache.ranger.service.RangerGdsDataShareInDatasetService; +import org.apache.ranger.service.RangerGdsDatasetService; +import org.apache.ranger.service.RangerGdsDatasetInProjectService; +import org.apache.ranger.service.RangerGdsProjectService; +import org.apache.ranger.service.RangerGdsSharedResourceService; +import org.apache.ranger.service.RangerServiceService; +import org.apache.ranger.validation.RangerGdsValidator; +import org.apache.ranger.view.RangerGdsVList.RangerDataShareList; +import org.apache.ranger.view.RangerGdsVList.RangerDataShareInDatasetList; +import org.apache.ranger.view.RangerGdsVList.RangerDatasetList; +import org.apache.ranger.view.RangerGdsVList.RangerDatasetInProjectList; +import org.apache.ranger.view.RangerGdsVList.RangerProjectList; +import org.apache.ranger.view.RangerGdsVList.RangerSharedResourceList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.*; + +import static org.apache.ranger.db.XXGlobalStateDao.RANGER_GLOBAL_STATE_NAME_DATASET; +import static org.apache.ranger.db.XXGlobalStateDao.RANGER_GLOBAL_STATE_NAME_DATA_SHARE; +import static org.apache.ranger.db.XXGlobalStateDao.RANGER_GLOBAL_STATE_NAME_PROJECT; + +@Component +public class GdsDBStore extends AbstractGdsStore { + private static final Logger LOG = LoggerFactory.getLogger(GdsDBStore.class); + + @Autowired + RangerGdsValidator validator; + + @Autowired + RangerDaoManager daoMgr; + + @Autowired + RangerGdsDataShareService dataShareService; + + @Autowired + RangerGdsSharedResourceService sharedResourceService; + + @Autowired + RangerGdsDatasetService datasetService; + + @Autowired + RangerGdsDataShareInDatasetService dataShareInDatasetService; + + @Autowired + RangerGdsProjectService projectService; + + @Autowired + RangerGdsDatasetInProjectService datasetInProjectService; + + @Autowired + RangerTransactionSynchronizationAdapter transactionSynchronizationAdapter; + + @Autowired + GUIDUtil guidUtil; + + + @PostConstruct + public void initStore() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> GdsInMemoryStore.initStore()"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== GdsInMemoryStore.initStore()"); + } + } + + @Override + public RangerDataset createDataset(RangerDataset dataset) throws Exception { + LOG.debug("==> createDataset({})", dataset); + + validator.validateCreate(dataset); + + if (StringUtils.isBlank(dataset.getGuid())) { + dataset.setGuid(guidUtil.genGUID()); + } + + RangerDataset ret = datasetService.create(dataset); + + datasetService.createObjectHistory(ret, null, RangerServiceService.OPERATION_CREATE_CONTEXT); + + updateGlobalVersion(RANGER_GLOBAL_STATE_NAME_DATASET); + + LOG.debug("<== createDataset({}): ret={}", dataset, ret); + + return ret; + } + + @Override + public RangerDataset updateDataset(RangerDataset dataset) throws Exception { + LOG.debug("==> updateDataset({})", dataset); + + RangerDataset existing = null; + + try { + existing = datasetService.read(dataset.getId()); + } catch (Exception excp) { + // ignore + } + + validator.validateUpdate(dataset, existing); + + RangerDataset ret = datasetService.update(dataset); + + datasetService.createObjectHistory(ret, existing, RangerServiceService.OPERATION_UPDATE_CONTEXT); + + updateGlobalVersion(RANGER_GLOBAL_STATE_NAME_DATASET); + + LOG.debug("<== updateDataset({}): ret={}", dataset, ret); + + return ret; + } + + @Override + public void deleteDataset(Long datasetId) throws Exception { + LOG.debug("==> deleteDataset({})", datasetId); + + RangerDataset existing = null; + + try { + existing = datasetService.read(datasetId); + } catch (Exception excp) { + // ignore + } + + validator.validateDelete(datasetId, existing); + + datasetService.delete(existing); + + datasetService.createObjectHistory(null, existing, RangerServiceService.OPERATION_DELETE_CONTEXT); + + updateGlobalVersion(RANGER_GLOBAL_STATE_NAME_DATASET); + + LOG.debug("<== deleteDataset({})", datasetId); + } + + @Override + public RangerDataset getDataset(Long datasetId) throws Exception { + LOG.debug("==> getDataset({})", datasetId); + + RangerDataset ret = datasetService.read(datasetId); + + // TODO: enforce RangerDataset.acl + + LOG.debug("<== getDataset({}): ret={}", datasetId, ret); + + return ret; + } + + @Override + public RangerDataset getDatasetByName(String name) throws Exception { + LOG.debug("==> getDatasetByName({})", name); + + XXGdsDatasetDao datasetDao = daoMgr.getXXGdsDataset(); + XXGdsDataset existing = datasetDao.findByName(name); + + if (existing == null) { + throw new Exception("no dataset with name=" + name); + } + + RangerDataset ret = datasetService.getPopulatedViewObject(existing); + + // TODO: enforce RangerDataset.acl + + LOG.debug("<== getDatasetByName({}): ret={}", name, ret); + + return ret; + } + + @Override + public PList getDatasetNames(SearchFilter filter) throws Exception { + LOG.debug("==> getDatasetNames({})", filter); + + RangerDatasetList result = datasetService.searchDatasets(filter); + List names = new ArrayList<>(); + + for (RangerDataset dataset : result.getList()) { + // TODO: enforce RangerDataset.acl + + names.add(dataset.getName()); + } + + PList ret = new PList<>(names, 0, names.size(), names.size(), names.size(), result.getSortType(), result.getSortBy()); + + LOG.debug("<== getDatasetNames({}): ret={}", filter, ret); + + return ret; + } + + @Override + public PList searchDatasets(SearchFilter filter) throws Exception { + LOG.debug("==> searchDatasets({})", filter); + + RangerDatasetList result = datasetService.searchDatasets(filter); + List datasets = new ArrayList<>(); + + for (RangerDataset dataset : result.getList()) { + // TODO: enforce RangerDataset.acl + + datasets.add(dataset); + } + + PList ret = new PList<>(datasets, 0, datasets.size(), datasets.size(), datasets.size(), result.getSortBy(), result.getSortType()); + + LOG.debug("<== searchDatasets({}): ret={}", filter, ret); + + return ret; + } + + + @Override + public RangerProject createProject(RangerProject project) throws Exception { + LOG.debug("==> createProject({})", project); + + validator.validateCreate(project); + + if (StringUtils.isBlank(project.getGuid())) { + project.setGuid(guidUtil.genGUID()); + } + + RangerProject ret = projectService.create(project); + + projectService.createObjectHistory(ret, null, RangerServiceService.OPERATION_CREATE_CONTEXT); + + updateGlobalVersion(RANGER_GLOBAL_STATE_NAME_PROJECT); + + LOG.debug("<== createProject({}): ret={}", project, ret); + + return ret; + } + + @Override + public RangerProject updateProject(RangerProject project) throws Exception { + LOG.debug("==> updateProject({})", project); + + RangerProject existing = null; + + try { + existing = projectService.read(project.getId()); + } catch (Exception excp) { + // ignore + } + + validator.validateUpdate(project, existing); + + RangerProject ret = projectService.update(project); + + projectService.createObjectHistory(ret, existing, RangerServiceService.OPERATION_UPDATE_CONTEXT); + + updateGlobalVersion(RANGER_GLOBAL_STATE_NAME_PROJECT); + + LOG.debug("<== updateProject({}): ret={}", project, ret); + + return ret; + } + + @Override + public void deleteProject(Long projectId) throws Exception { + LOG.debug("==> deleteProject({})", projectId); + + RangerProject existing = null; + + try { + existing = projectService.read(projectId); + } catch(Exception excp) { + // ignore + } + + validator.validateDelete(projectId, existing); + + projectService.delete(existing); + + projectService.createObjectHistory(null, existing, RangerServiceService.OPERATION_DELETE_CONTEXT); + + updateGlobalVersion(RANGER_GLOBAL_STATE_NAME_PROJECT); + + LOG.debug("<== deleteProject({})", projectId); + } + + @Override + public RangerProject getProject(Long projectId) throws Exception { + LOG.debug("==> getProject({})", projectId); + + RangerProject ret = projectService.read(projectId); + + // TODO: enforce RangerProject.acl + + LOG.debug("<== getProject({}): ret={}", projectId, ret); + + return ret; + } + + @Override + public RangerProject getProjectByName(String name) throws Exception { + LOG.debug("==> getProjectByName({})", name); + + XXGdsProjectDao projectDao = daoMgr.getXXGdsProject(); + XXGdsProject existing = projectDao.findByName(name); + + if (existing == null) { + throw new Exception("no project with name=" + name); + } + + RangerProject ret = projectService.getPopulatedViewObject(existing); + + // TODO: enforce RangerProject.acl + + LOG.debug("<== getProjectByName({}): ret={}", name, ret); + + return ret; + } + + @Override + public PList getProjectNames(SearchFilter filter) throws Exception { + LOG.debug("==> getProjectNames({})", filter); + + RangerProjectList result = projectService.searchProjects(filter); + List names = new ArrayList<>(); + + for (RangerProject project : result.getList()) { + // TODO: enforce RangerProject.acl + + names.add(project.getName()); + } + + PList ret = new PList<>(names, 0, names.size(), names.size(), names.size(), result.getSortType(), result.getSortBy()); + + LOG.debug("<== getProjectNames({}): ret={}", filter, ret); + + return ret; + } + + @Override + public PList searchProjects(SearchFilter filter) throws Exception { + LOG.debug("==> searchProjects({})", filter); + + RangerProjectList result = projectService.searchProjects(filter); + List projects = new ArrayList<>(); + + for (RangerProject project : result.getList()) { + // TODO: enforce RangerProject.acl + + projects.add(project); + } + + PList ret = new PList<>(projects, 0, projects.size(), projects.size(), projects.size(), result.getSortBy(), result.getSortType()); + + LOG.debug("<== searchProjects({}): ret={}", filter, ret); + + return ret; + } + + + @Override + public RangerDataShare createDataShare(RangerDataShare dataShare) throws Exception { + LOG.debug("==> createDataShare({})", dataShare); + + validator.validateCreate(dataShare); + + if (StringUtils.isBlank(dataShare.getGuid())) { + dataShare.setGuid(guidUtil.genGUID()); + } + + RangerDataShare ret = dataShareService.create(dataShare); + + dataShareService.createObjectHistory(ret, null, RangerServiceService.OPERATION_CREATE_CONTEXT); + + updateGlobalVersion(RANGER_GLOBAL_STATE_NAME_DATA_SHARE); + + LOG.debug("<== createDataShare({}): ret={}", dataShare, ret); + + return ret; + } + + @Override + public RangerDataShare updateDataShare(RangerDataShare dataShare) throws Exception { + LOG.debug("==> updateDataShare({})", dataShare); + + RangerDataShare existing = null; + + try { + existing = dataShareService.read(dataShare.getId()); + } catch (Exception excp) { + // ignore + } + + validator.validateUpdate(dataShare, existing); + + RangerDataShare ret = dataShareService.update(dataShare); + + dataShareService.createObjectHistory(ret, existing, RangerServiceService.OPERATION_UPDATE_CONTEXT); + + updateGlobalVersion(RANGER_GLOBAL_STATE_NAME_DATA_SHARE); + + LOG.debug("<== updateDataShare({}): ret={}", dataShare, ret); + + return ret; + } + + @Override + public void deleteDataShare(Long dataShareId) throws Exception { + LOG.debug("==> deleteDataShare({})", dataShareId); + + RangerDataShare existing = null; + + try { + existing = dataShareService.read(dataShareId); + } catch (Exception excp) { + // ignore + } + + validator.validateDelete(dataShareId, existing); + + dataShareService.delete(existing); + + dataShareService.createObjectHistory(null, existing, RangerServiceService.OPERATION_DELETE_CONTEXT); + + updateGlobalVersion(RANGER_GLOBAL_STATE_NAME_DATA_SHARE); + + LOG.debug("<== deleteDataShare({})", dataShareId); + } + + @Override + public RangerDataShare getDataShare(Long dataShareId) throws Exception { + LOG.debug("==> getDataShare({})", dataShareId); + + RangerDataShare ret = dataShareService.read(dataShareId); + + // TODO: enforce RangerDataShare.acl + + LOG.debug("<== getDataShare({}): ret={}", dataShareId, ret); + + return ret; + } + + @Override + public PList searchDataShares(SearchFilter filter) throws Exception { + LOG.debug("==> searchDataShares({})", filter); + + RangerDataShareList result = dataShareService.searchDataShares(filter); + List dataShares = new ArrayList<>(); + + for (RangerDataShare dataShare : result.getList()) { + // TODO: enforce RangerDataShare.acl + + dataShares.add(dataShare); + } + + PList ret = new PList<>(dataShares, 0, dataShares.size(), dataShares.size(), dataShares.size(), result.getSortBy(), result.getSortType()); + + LOG.debug("<== searchDataShares({}): ret={}", filter, ret); + + return ret; + } + + + @Override + public RangerSharedResource addSharedResource(RangerSharedResource resource) throws Exception { + LOG.debug("==> addSharedResource({})", resource); + + validator.validateCreate(resource); + + // TODO: enforce RangerSharedResource.acl + resource.setResourceSignature(RangerPolicyResourceSignature.toSignatureString(resource.getResource())); + + if (StringUtils.isBlank(resource.getGuid())) { + resource.setGuid(guidUtil.genGUID()); + } + + RangerSharedResource ret = sharedResourceService.create(resource); + + sharedResourceService.createObjectHistory(ret, null, RangerServiceService.OPERATION_CREATE_CONTEXT); + + LOG.debug("<== addSharedResource({}): ret={}", resource, ret); + + return ret; + } + + @Override + public RangerSharedResource updateSharedResource(RangerSharedResource resource) throws Exception { + LOG.debug("==> updateSharedResource({})", resource); + + RangerSharedResource existing = null; + + try { + existing = sharedResourceService.read(resource.getId()); + } catch (Exception excp) { + // ignore + } + + validator.validateUpdate(resource, existing); + + resource.setResourceSignature(RangerPolicyResourceSignature.toSignatureString(resource.getResource())); + + RangerSharedResource ret = sharedResourceService.update(resource); + + sharedResourceService.createObjectHistory(ret, existing, RangerServiceService.OPERATION_UPDATE_CONTEXT); + + LOG.debug("<== updateSharedResource({}): ret={}", resource, ret); + + return ret; + } + + @Override + public void removeSharedResource(Long sharedResourceId) throws Exception { + LOG.debug("==> removeSharedResource({})", sharedResourceId); + + + RangerSharedResource existing = null; + + try { + existing = sharedResourceService.read(sharedResourceId); + } catch (Exception excp) { + // ignore + } + + validator.validateDelete(sharedResourceId, existing); + + sharedResourceService.delete(existing); + + sharedResourceService.createObjectHistory(null, existing, RangerServiceService.OPERATION_DELETE_CONTEXT); + + LOG.debug("<== removeSharedResource({})", sharedResourceId); + } + + @Override + public RangerSharedResource getSharedResource(Long sharedResourceId) throws Exception { + LOG.debug("==> getSharedResource({})", sharedResourceId); + + RangerSharedResource ret = sharedResourceService.read(sharedResourceId); + + // TODO: enforce RangerSharedResource.acl + + LOG.debug("<== getSharedResource({}): ret={}", sharedResourceId, ret); + + return ret; + } + + @Override + public PList searchSharedResources(SearchFilter filter) throws Exception { + LOG.debug("==> searchSharedResources({})", filter); + + RangerSharedResourceList result = sharedResourceService.searchSharedResources(filter); + List sharedResources = new ArrayList<>(); + + for (RangerSharedResource dataShare : result.getList()) { + // TODO: enforce RangerSharedResource.acl + + sharedResources.add(dataShare); + } + + PList ret = new PList<>(sharedResources, 0, sharedResources.size(), sharedResources.size(), sharedResources.size(), result.getSortBy(), result.getSortType()); + + LOG.debug("<== searchSharedResources({}): ret={}", filter, ret); + + return ret; + } + + + @Override + public RangerDataShareInDataset addDataShareInDataset(RangerDataShareInDataset dataShareInDataset) throws Exception { + LOG.debug("==> addDataShareInDataset({})", dataShareInDataset); + + XXGdsDataShareInDatasetDao datasetDao = daoMgr.getXXGdsDataShareInDataset(); + XXGdsDataShareInDataset existing = datasetDao.findByDataShareIdAndDatasetId(dataShareInDataset.getDataShareId(), dataShareInDataset.getDatasetId()); + + if (existing != null) { + throw new Exception("data share '" + dataShareInDataset.getDataShareId() + "' already shared with dataset " + dataShareInDataset.getDatasetId() + " - id=" + existing.getId()); + } + + // TODO: enforce RangerDataShareInDataset.acl + + if (StringUtils.isBlank(dataShareInDataset.getGuid())) { + dataShareInDataset.setGuid(guidUtil.genGUID()); + } + + RangerDataShareInDataset ret = dataShareInDatasetService.create(dataShareInDataset); + + dataShareInDatasetService.createObjectHistory(ret, null, RangerServiceService.OPERATION_CREATE_CONTEXT); + + LOG.debug("<== addDataShareInDataset({}): ret={}", dataShareInDataset, ret); + + return ret; + } + + @Override + public RangerDataShareInDataset updateDataShareInDataset(RangerDataShareInDataset dataShareInDataset) throws Exception { + LOG.debug("==> updateDataShareInDataset({})", dataShareInDataset); + + RangerDataShareInDataset existing = dataShareInDatasetService.read(dataShareInDataset.getId()); + + // TODO: enforce RangerDataShareInDataset.acl + + RangerDataShareInDataset ret = dataShareInDatasetService.update(dataShareInDataset); + + dataShareInDatasetService.createObjectHistory(ret, existing, RangerServiceService.OPERATION_UPDATE_CONTEXT); + + LOG.debug("<== updateDataShareInDataset({}): ret={}", dataShareInDataset, ret); + + return ret; + } + + @Override + public void removeDataShareInDataset(Long dataShareInDatasetId) throws Exception { + LOG.debug("==> removeDataShareInDataset({})", dataShareInDatasetId); + + RangerDataShareInDataset existing = dataShareInDatasetService.read(dataShareInDatasetId); + + // TODO: enforce RangerDataShareInDataset.acl + + dataShareInDatasetService.delete(existing); + + dataShareInDatasetService.createObjectHistory(null, existing, RangerServiceService.OPERATION_DELETE_CONTEXT); + + LOG.debug("<== removeDataShareInDataset({})", dataShareInDatasetId); + } + + @Override + public RangerDataShareInDataset getDataShareInDataset(Long dataShareInDatasetId) throws Exception { + LOG.debug("==> getDataShareInDataset({})", dataShareInDatasetId); + + RangerDataShareInDataset ret = dataShareInDatasetService.read(dataShareInDatasetId); + + LOG.debug("<== getDataShareInDataset({}): ret={}", dataShareInDatasetId, ret); + + return ret; + } + + @Override + public PList searchDataShareInDatasets(SearchFilter filter) throws Exception { + LOG.debug("==> searchDataShareInDatasets({})", filter); + + List dataShareInDatasets = new ArrayList<>(); + RangerDataShareInDatasetList result = dataShareInDatasetService.searchDataShareInDatasets(filter); + + for (RangerDataShareInDataset dataShareInDataset : result.getList()) { + // TODO: enforce RangerSharedResource.acl + + dataShareInDatasets.add(dataShareInDataset); + } + + PList ret = new PList<>(dataShareInDatasets, 0, dataShareInDatasets.size(), dataShareInDatasets.size(), dataShareInDatasets.size(), result.getSortBy(), result.getSortType()); + + LOG.debug("<== searchDataShareInDatasets({}): ret={}", filter, ret); + + return ret; + } + + + @Override + public RangerDatasetInProject addDatasetInProject(RangerDatasetInProject datasetInProject) throws Exception { + LOG.debug("==> addDatasetInProject({})", datasetInProject); + + XXGdsDatasetInProjectDao datasetDao = daoMgr.getXXGdsDatasetInProject(); + XXGdsDatasetInProject existing = datasetDao.findByDatasetIdAndProjectId(datasetInProject.getDatasetId(), datasetInProject.getProjectId()); + + if (existing != null) { + throw new Exception("dataset '" + datasetInProject.getDatasetId() + "' already shared with project " + datasetInProject.getProjectId() + " - id=" + existing.getId()); + } + + // TODO: enforce RangerDatasetInProject.acl + + if (StringUtils.isBlank(datasetInProject.getGuid())) { + datasetInProject.setGuid(guidUtil.genGUID()); + } + + RangerDatasetInProject ret = datasetInProjectService.create(datasetInProject); + + datasetInProjectService.createObjectHistory(ret, null, RangerServiceService.OPERATION_CREATE_CONTEXT); + + LOG.debug("<== addDatasetInProject({}): ret={}", datasetInProject, ret); + + return ret; + } + + @Override + public RangerDatasetInProject updateDatasetInProject(RangerDatasetInProject datasetInProject) throws Exception { + LOG.debug("==> updateDatasetInProject({})", datasetInProject); + + RangerDatasetInProject existing = datasetInProjectService.read(datasetInProject.getId()); + + // TODO: enforce RangerDatasetInProject.acl + + RangerDatasetInProject ret = datasetInProjectService.update(datasetInProject); + + datasetInProjectService.createObjectHistory(ret, existing, RangerServiceService.OPERATION_UPDATE_CONTEXT); + + LOG.debug("<== updateDatasetInProject({}): ret={}", datasetInProject, ret); + + return ret; + } + + @Override + public void removeDatasetInProject(Long datasetInProjectId) throws Exception { + LOG.debug("==> removeDatasetInProject({})", datasetInProjectId); + + RangerDatasetInProject existing = datasetInProjectService.read(datasetInProjectId); + + // TODO: enforce RangerDatasetInProject.acl + + datasetInProjectService.delete(existing); + + datasetInProjectService.createObjectHistory(null, existing, RangerServiceService.OPERATION_DELETE_CONTEXT); + + LOG.debug("<== removeDatasetInProject({})", datasetInProjectId); + } + + @Override + public RangerDatasetInProject getDatasetInProject(Long datasetInProjectId) throws Exception { + LOG.debug("==> getDatasetInProject({})", datasetInProjectId); + + RangerDatasetInProject ret = datasetInProjectService.read(datasetInProjectId); + + // TODO: enforce RangerDatasetInProject.acl + + LOG.debug("<== getDatasetInProject({}): ret={}", datasetInProjectId, ret); + + return ret; + } + + @Override + public PList searchDatasetInProjects(SearchFilter filter) throws Exception { + LOG.debug("==> searchDatasetInProjects({})", filter); + + List datasetInProjects = new ArrayList<>(); + RangerDatasetInProjectList result = datasetInProjectService.searchDatasetInProjects(filter); + + for (RangerDatasetInProject datasetInProject : result.getList()) { + // TODO: enforce RangerDatasetInProject.acl + + datasetInProjects.add(datasetInProject); + } + + PList ret = new PList<>(datasetInProjects, 0, datasetInProjects.size(), datasetInProjects.size(), datasetInProjects.size(), result.getSortBy(), result.getSortType()); + + LOG.debug("<== searchDatasetInProjects({}): ret={}", filter, ret); + + return ret; + } + + private void updateGlobalVersion(String stateName) { + transactionSynchronizationAdapter.executeOnTransactionCommit(new GlobalVersionUpdater(daoMgr, stateName)); + } + + private static class GlobalVersionUpdater implements Runnable { + final RangerDaoManager daoManager; + final String stateName; + + public GlobalVersionUpdater(RangerDaoManager daoManager, String stateName) { + this.daoManager = daoManager; + this.stateName = stateName; + } + + @Override + public void run() { + try { + this.daoManager.getXXGlobalState().onGlobalAppDataChange(stateName); + } catch (Exception e) { + LOG.error("Failed to update GlobalState version for state:[{}]", stateName , e); + } + } + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java index c19e3e1a1f..84833847dc 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java @@ -56,12 +56,12 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import static org.apache.ranger.db.XXGlobalStateDao.RANGER_GLOBAL_STATE_NAME_ROLE; + @Component public class RoleDBStore implements RoleStore { private static final Logger LOG = LoggerFactory.getLogger(RoleDBStore.class); - private static final String RANGER_ROLE_GLOBAL_STATE_NAME = "RangerRole"; - @Autowired RangerRoleService roleService; @@ -382,7 +382,7 @@ public Long getRoleVersion(String serviceName) { XXServiceVersionInfo xxServiceVersionInfo = daoMgr.getXXServiceVersionInfo().findByServiceName(serviceName); ret = (xxServiceVersionInfo != null) ? xxServiceVersionInfo.getRoleVersion() : null; } else { - ret = daoMgr.getXXGlobalState().getAppDataVersion(RANGER_ROLE_GLOBAL_STATE_NAME); + ret = daoMgr.getXXGlobalState().getAppDataVersion(RANGER_GLOBAL_STATE_NAME_ROLE); } return ret; @@ -475,9 +475,9 @@ public RoleVersionUpdater(RangerDaoManager daoManager) { @Override public void run() { try { - this.daoManager.getXXGlobalState().onGlobalAppDataChange(RANGER_ROLE_GLOBAL_STATE_NAME); + this.daoManager.getXXGlobalState().onGlobalAppDataChange(RANGER_GLOBAL_STATE_NAME_ROLE); } catch (Exception e) { - LOG.error("Cannot update GlobalState version for state:[" + RANGER_ROLE_GLOBAL_STATE_NAME + "]", e); + LOG.error("Cannot update GlobalState version for state:[" + RANGER_GLOBAL_STATE_NAME_ROLE + "]", e); } } } diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java index 77f86a0ad1..bbdd54a77f 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java @@ -47,6 +47,7 @@ import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; import org.apache.ranger.plugin.store.ServiceStore; import org.apache.ranger.service.RangerServiceService; +import org.apache.ranger.services.gds.RangerServiceGds; import org.apache.ranger.services.tag.RangerServiceTag; import org.apache.ranger.view.VXMessage; import org.apache.ranger.view.VXResponse; @@ -81,6 +82,9 @@ public class ServiceMgr { @Autowired TagDBStore tagStore; + @Autowired + GdsDBStore gdsStore; + @Autowired TimedExecutor timedExecutor; @@ -319,6 +323,8 @@ public RangerBaseService getRangerServiceByService(RangerService service, Servic if(ret instanceof RangerServiceTag) { ((RangerServiceTag)ret).setTagStore(tagStore); + } else if (ret instanceof RangerServiceGds) { + ((RangerServiceGds)ret).setGdsStore(gdsStore); } } else { LOG.warn("ServiceMgr.getRangerServiceByService(" + service + "): could not find service class '" diff --git a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java index 455ae0bc41..9f5e5b1cbf 100755 --- a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java @@ -98,10 +98,11 @@ import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; +import static org.apache.ranger.db.XXGlobalStateDao.RANGER_GLOBAL_STATE_NAME_USER_GROUP; + @Component public class XUserMgr extends XUserMgrBase { - private static final String RANGER_USER_GROUP_GLOBAL_STATE_NAME = "RangerUserStore"; private static final String USER = "User"; private static final String GROUP = "Group"; private static final int MAX_DB_TRANSACTION_RETRIES = 5; @@ -2574,7 +2575,7 @@ public synchronized VXUgsyncAuditInfo postUserGroupAuditInfo( } public Long getUserStoreVersion() { - return daoManager.getXXGlobalState().getAppDataVersion(RANGER_USER_GROUP_GLOBAL_STATE_NAME); + return daoManager.getXXGlobalState().getAppDataVersion(RANGER_GLOBAL_STATE_NAME_USER_GROUP); } public Set getUsers() { @@ -2677,7 +2678,7 @@ public Void doInTransaction(TransactionStatus status) { do { noOfRetries++; try { - daoManager.getXXGlobalState().onGlobalAppDataChange(RANGER_USER_GROUP_GLOBAL_STATE_NAME); + daoManager.getXXGlobalState().onGlobalAppDataChange(RANGER_GLOBAL_STATE_NAME_USER_GROUP); if (logger.isDebugEnabled()) { logger.debug("createOrUpdateXGroups(): Successfully updated x_ranger_global_state table"); } @@ -3259,7 +3260,7 @@ private void createExternalUser() { private void updateUserStoreVersion(String label) { try { - daoManager.getXXGlobalState().onGlobalAppDataChange(RANGER_USER_GROUP_GLOBAL_STATE_NAME); + daoManager.getXXGlobalState().onGlobalAppDataChange(RANGER_GLOBAL_STATE_NAME_USER_GROUP); } catch (Exception excp) { logger.error(label + ": userStore version update failed", excp); } diff --git a/security-admin/src/main/java/org/apache/ranger/common/AppConstants.java b/security-admin/src/main/java/org/apache/ranger/common/AppConstants.java index f214385e7a..db0a80aefc 100644 --- a/security-admin/src/main/java/org/apache/ranger/common/AppConstants.java +++ b/security-admin/src/main/java/org/apache/ranger/common/AppConstants.java @@ -636,6 +636,17 @@ public class AppConstants extends RangerCommonEnums { public static final int CLASS_TYPE_RMS_SERVICE_RESOURCE = 1060; public static final int CLASS_TYPE_RMS_RESOURCE_MAPPING = 1061; + /** + * Class type of RangerGds + */ + public static final int CLASS_TYPE_GDS_DATASET = 1062; + public static final int CLASS_TYPE_GDS_PROJECT = 1063; + public static final int CLASS_TYPE_GDS_DATA_SHARE = 1064; + public static final int CLASS_TYPE_GDS_SHARED_RESOURCE = 1065; + public static final int CLASS_TYPE_GDS_DATA_SHARE_IN_DATASET = 1066; + public static final int CLASS_TYPE_GDS_DATA_SHARE_IN_PROJECT = 1067; + public static final int CLASS_TYPE_GDS_DATASET_IN_PROJECT = 1068; + /** * Max value for enum ClassTypes_MAX */ diff --git a/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java b/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java index 8030fe7a4c..b4a3626791 100644 --- a/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java +++ b/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java @@ -99,6 +99,17 @@ public SearchFilter getSearchFilter(@Nonnull HttpServletRequest request, List getNamesByServiceName(String serviceName) { + List ret = null; + + if (serviceName != null) { + try { + ret = getEntityManager().createNamedQuery("XXAccessTypeDef.getNamesByServiceName", String.class) + .setParameter("serviceName", serviceName).getResultList(); + } catch (NoResultException excp) { + // ignore + } + } + + return ret != null ? ret : Collections.emptyList(); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java index 83c2881271..5a0611f893 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java @@ -18,6 +18,7 @@ package org.apache.ranger.db; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.persistence.NoResultException; @@ -60,4 +61,19 @@ public XXDataMaskTypeDef findByNameAndServiceId(String name, Long serviceId) { return null; } } + + public List getNamesByServiceName(String serviceName) { + List ret = null; + + if (serviceName != null) { + try { + ret = getEntityManager().createNamedQuery("XXDataMaskTypeDef.getNamesByServiceName", String.class) + .setParameter("serviceName", serviceName).getResultList(); + } catch (NoResultException excp) { + // ignore + } + } + + return ret != null ? ret : Collections.emptyList(); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java new file mode 100644 index 0000000000..f0e64d7115 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java @@ -0,0 +1,117 @@ +/* + * 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.db; + +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.common.db.BaseDao; +import org.apache.ranger.entity.XXGdsDataShare; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.persistence.NoResultException; +import java.util.Collections; +import java.util.List; + + +@Service +public class XXGdsDataShareDao extends BaseDao { + private static final Logger LOG = LoggerFactory.getLogger(XXGdsDataShareDao.class); + + public XXGdsDataShareDao(RangerDaoManagerBase daoManager) { + super(daoManager); + } + + public XXGdsDataShare findByGuid(String guid) { + XXGdsDataShare ret = null; + + if (StringUtils.isNotBlank(guid)) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataShare.findByGuid", tClass) + .setParameter("guid", guid).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByGuid({}): ", guid, e); + } + } + + return ret; + } + + public XXGdsDataShare findByName(String name) { + XXGdsDataShare ret = null; + + if (StringUtils.isNotBlank(name)) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataShare.findByName", tClass) + .setParameter("name", name).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByName({}): ", name, e); + } + } + + return ret; + } + + public List findByServiceId(Long serviceId) { + List ret = null; + + if (serviceId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataShare.findByServiceId", tClass) + .setParameter("serviceId", serviceId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByServiceId({}): ", serviceId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } + + public List findByServiceIdAndZoneId(Long serviceId, Long zoneId) { + List ret = null; + + if (serviceId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataShare.findByServiceIdAndZoneId", tClass) + .setParameter("serviceId", serviceId) + .setParameter("zoneId", zoneId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByServiceIdAndZoneId({}): ", serviceId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } + + public List findByDatasetId(Long datasetId) { + List ret = null; + + if (datasetId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataShare.findByDatasetId", tClass) + .setParameter("datasetId", datasetId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByDatasetId({}): ", datasetId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareInDatasetDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareInDatasetDao.java new file mode 100644 index 0000000000..52c441104b --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareInDatasetDao.java @@ -0,0 +1,102 @@ +/* + * 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.db; + +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.common.db.BaseDao; +import org.apache.ranger.entity.XXGdsDataShareInDataset; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.persistence.NoResultException; +import java.util.Collections; +import java.util.List; + + +@Service +public class XXGdsDataShareInDatasetDao extends BaseDao { + private static final Logger LOG = LoggerFactory.getLogger(XXGdsDataShareInDatasetDao.class); + + public XXGdsDataShareInDatasetDao(RangerDaoManagerBase daoManager) { + super(daoManager); + } + + public XXGdsDataShareInDataset findByGuid(String guid) { + XXGdsDataShareInDataset ret = null; + + if (StringUtils.isNotBlank(guid)) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataShareInDataset.findByGuid", tClass) + .setParameter("guid", guid).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByGuid({}): ", guid, e); + } + } + + return ret; + } + + public XXGdsDataShareInDataset findByDataShareIdAndDatasetId(Long dataShareId, Long datasetId) { + XXGdsDataShareInDataset ret = null; + + if (dataShareId != null && datasetId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataShareInDataset.findByDataShareIdAndDatasetId", tClass) + .setParameter("dataShareId", dataShareId) + .setParameter("datasetId", datasetId).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByDataShareIdAndDatasetId({}): ", dataShareId, e); + } + } + + return ret; + } + + public List findByDataShareId(Long dataShareId) { + List ret = null; + + if (dataShareId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataShareInDataset.findByDataShareId", tClass) + .setParameter("dataShareId", dataShareId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByDataShareId({}): ", dataShareId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } + + public List findByDatasetId(Long datasetId) { + List ret = null; + + if (datasetId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataShareInDataset.findByDatasetId", tClass) + .setParameter("datasetId", datasetId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByDatasetId({}): ", datasetId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java new file mode 100644 index 0000000000..ee2d4b67b3 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java @@ -0,0 +1,101 @@ +/* + * 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.db; + +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.common.db.BaseDao; +import org.apache.ranger.entity.XXGdsDataset; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.persistence.NoResultException; +import java.util.Collections; +import java.util.List; + + +@Service +public class XXGdsDatasetDao extends BaseDao { + private static final Logger LOG = LoggerFactory.getLogger(XXGdsDatasetDao.class); + + public XXGdsDatasetDao(RangerDaoManagerBase daoManager) { + super(daoManager); + } + + public XXGdsDataset findByGuid(String guid) { + XXGdsDataset ret = null; + + if (StringUtils.isNotBlank(guid)) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataset.findByGuid", tClass) + .setParameter("guid", guid).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByGuid({}): ", guid, e); + } + } + + return ret; + } + + public XXGdsDataset findByName(String name) { + XXGdsDataset ret = null; + + if (StringUtils.isNotBlank(name)) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataset.findByName", tClass) + .setParameter("name", name).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByName({}): ", name, e); + } + } + + return ret; + } + + public List findByDataShareId(Long dataShareId) { + List ret = null; + + if (dataShareId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataset.findByDataShareId", tClass) + .setParameter("dataShareId", dataShareId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByDataShareId({}): ", dataShareId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } + + public List findByProjectId(Long projectId) { + List ret = null; + + if (projectId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataset.findByProjectId", tClass) + .setParameter("projectId", projectId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByProjectId({}): ", projectId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetInProjectDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetInProjectDao.java new file mode 100644 index 0000000000..06bf671056 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetInProjectDao.java @@ -0,0 +1,103 @@ +/* + * 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.db; + +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.common.db.BaseDao; +import org.apache.ranger.entity.XXGdsDatasetInProject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.persistence.NoResultException; +import java.util.Collections; +import java.util.List; + + +@Service +public class XXGdsDatasetInProjectDao extends BaseDao { + private static final Logger LOG = LoggerFactory.getLogger(XXGdsDatasetInProjectDao.class); + + public XXGdsDatasetInProjectDao(RangerDaoManagerBase daoManager) { + super(daoManager); + } + + public XXGdsDatasetInProject findByGuid(String guid) { + XXGdsDatasetInProject ret = null; + + if (StringUtils.isNotBlank(guid)) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDatasetInProject.findByGuid", tClass) + .setParameter("guid", guid).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByGuid({}): ", guid, e); + } + } + + return ret; + } + + public XXGdsDatasetInProject findByDatasetIdAndProjectId(Long datasetId, Long projectId) { + XXGdsDatasetInProject ret = null; + + if (datasetId != null && projectId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDatasetInProject.findByDatasetIdAndProjectId", tClass) + .setParameter("datasetId", datasetId) + .setParameter("projectId", projectId) + .getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByDatasetIdAndProjectId({}): ", datasetId, e); + } + } + + return ret; + } + + public List findByDatasetId(Long datasetId) { + List ret = null; + + if (datasetId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDatasetInProject.findByDatasetId", tClass) + .setParameter("datasetId", datasetId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByDatasetId({}): ", datasetId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } + + public List findByProjectId(Long projectId) { + List ret = null; + + if (projectId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDatasetInProject.findByProjectId", tClass) + .setParameter("projectId", projectId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByProjectId({}): ", projectId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java new file mode 100644 index 0000000000..4f214ff8df --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java @@ -0,0 +1,86 @@ +/* + * 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.db; + +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.common.db.BaseDao; +import org.apache.ranger.entity.XXGdsProject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.persistence.NoResultException; +import java.util.Collections; +import java.util.List; + + +@Service +public class XXGdsProjectDao extends BaseDao { + private static final Logger LOG = LoggerFactory.getLogger(XXGdsProjectDao.class); + + public XXGdsProjectDao(RangerDaoManagerBase daoManager) { + super(daoManager); + } + + public XXGdsProject findByGuid(String guid) { + XXGdsProject ret = null; + + if (StringUtils.isNotBlank(guid)) { + try { + ret = getEntityManager().createNamedQuery("XXGdsProject.findByGuid", tClass) + .setParameter("guid", guid).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByGuid({}): ", guid, e); + } + } + + return ret; + } + + public XXGdsProject findByName(String name) { + XXGdsProject ret = null; + + if (StringUtils.isNotBlank(name)) { + try { + ret = getEntityManager().createNamedQuery("XXGdsProject.findByName", tClass) + .setParameter("name", name).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByName({}): ", name, e); + } + } + + return ret; + } + + public List findByDatasetId(Long datasetId) { + List ret = null; + + if (datasetId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsProject.findByDatasetId", tClass) + .setParameter("datasetId", datasetId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByDatasetId({}): ", datasetId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsSharedResourceDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsSharedResourceDao.java new file mode 100644 index 0000000000..d3bd4d65b6 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsSharedResourceDao.java @@ -0,0 +1,133 @@ +/* + * 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.db; + +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.common.db.BaseDao; +import org.apache.ranger.entity.XXGdsSharedResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.persistence.NoResultException; +import java.util.Collections; +import java.util.List; + + +@Service +public class XXGdsSharedResourceDao extends BaseDao { + private static final Logger LOG = LoggerFactory.getLogger(XXGdsSharedResourceDao.class); + + public XXGdsSharedResourceDao(RangerDaoManagerBase daoManager) { + super(daoManager); + } + + public XXGdsSharedResource findByGuid(String guid) { + XXGdsSharedResource ret = null; + + if (StringUtils.isNotBlank(guid)) { + try { + ret = getEntityManager().createNamedQuery("XXGdsSharedResource.findByGuid", tClass) + .setParameter("guid", guid).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByGuid({}): ", guid, e); + } + } + + return ret; + } + + public XXGdsSharedResource findByName(String name) { + XXGdsSharedResource ret = null; + + if (StringUtils.isNotBlank(name)) { + try { + ret = getEntityManager().createNamedQuery("XXGdsSharedResource.findByName", tClass) + .setParameter("name", name).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("findByName({}): ", name, e); + } + } + + return ret; + } + + public List findByServiceId(Long serviceId) { + List ret = null; + + if (serviceId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsSharedResource.findByServiceId", tClass) + .setParameter("serviceId", serviceId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByServiceId({}): ", serviceId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } + + public List findByServiceIdAndZoneId(Long serviceId, Long zoneId) { + List ret = null; + + if (serviceId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsSharedResource.findByServiceIdAndZoneId", tClass) + .setParameter("serviceId", serviceId) + .setParameter("zoneId", zoneId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByServiceIdAndZoneId({}): ", serviceId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } + + public List findByDatasetId(Long datasetId) { + List ret = null; + + if (datasetId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsSharedResource.findByDatasetId", tClass) + .setParameter("datasetId", datasetId).getResultList(); + } catch (NoResultException e) { + LOG.debug("findByDatasetId({}): ", datasetId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } + + public Long getIdByDataShareIdAndName(Long dataShareId, String name) { + Long ret = null; + + if (dataShareId != null && name != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsSharedResource.getIdByDataShareIdAndName", Long.class) + .setParameter("dataShareId", dataShareId) + .setParameter("name", name).getSingleResult(); + } catch (NoResultException e) { + LOG.debug("getIdByDataShareIdAndName({}, {}): ", dataShareId, name, e); + } + } + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGlobalStateDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGlobalStateDao.java index a614e34b96..e28b607c9a 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXGlobalStateDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGlobalStateDao.java @@ -38,7 +38,13 @@ public class XXGlobalStateDao extends BaseDao { private static final Logger logger = LoggerFactory.getLogger(XXGlobalStateDao.class); - final static String APP_DATA_ENTRY_VERSION = "Version"; + public final static String RANGER_GLOBAL_STATE_NAME_DATASET = "RangerDataset"; + public final static String RANGER_GLOBAL_STATE_NAME_DATA_SHARE = "RangerDataShare"; + public final static String RANGER_GLOBAL_STATE_NAME_PROJECT = "RangerProject"; + public final static String RANGER_GLOBAL_STATE_NAME_ROLE = "RangerRole"; + public final static String RANGER_GLOBAL_STATE_NAME_USER_GROUP = "RangerUserStore"; + public final static String APP_DATA_ENTRY_VERSION = "Version"; + public void onGlobalStateChange(String stateName) throws Exception { diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDataShare.java b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDataShare.java new file mode 100644 index 0000000000..bca7900c5c --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDataShare.java @@ -0,0 +1,212 @@ +/* + * 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.entity; + +import org.apache.ranger.common.AppConstants; + +import javax.persistence.*; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Objects; + +@Entity +@Cacheable +@Table(name="x_gds_data_share") +@XmlRootElement +public class XXGdsDataShare extends XXDBBase implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @SequenceGenerator(name = "X_GDS_DATA_SHARE_SEQ", sequenceName = "X_GDS_DATA_SHARE_SEQ", allocationSize = 1) + @GeneratedValue(strategy = GenerationType.AUTO, generator = "X_GDS_DATA_SHARE_SEQ") + @Column(name = "id") + protected Long id; + + @Column(name = "guid", unique = true, nullable = false, length = 512) + protected String guid; + + @Version + @Column(name = "version") + protected Long version; + + @Column(name = "is_enabled") + protected Boolean isEnabled; + + @Column(name = "service_id") + protected Long serviceId; + + @Column(name = "zone_id") + protected Long zoneId; + + @Column(name = "name") + protected String name; + + @Column(name = "description") + protected String description; + + @Column(name = "owners") + protected String owners; + + @Column(name = "condition") + protected String condition; + + @Column(name = "default_access_types") + protected String defaultAccessTypes; + + @Column(name = "default_masks") + protected String defaultMasks; + + @Column(name = "terms_of_use") + protected String termsOfUse; + + @Column(name = "options") + protected String options; + + @Column(name = "additional_info") + protected String additionalInfo; + + + @Override + public void setId(Long id) { this.id = id; } + + @Override + public Long getId() { return id; } + + public String getGuid() { return guid; } + + public void setGuid(String guid) { this.guid = guid; } + + public Long getVersion() { return version; } + + public void setVersion(Long version) { this.version = version; } + + public Boolean getIsEnabled() { return isEnabled; } + + public void setIsEnabled(Boolean isEnabled) { this.isEnabled = isEnabled; } + + public Long getServiceId() { return serviceId; } + + public void setServiceId(Long serviceId) { this.serviceId = serviceId; } + + public Long getZoneId() { return zoneId; } + + public void setZoneId(Long zoneId) { this.zoneId = zoneId; } + + public String getName() { return name; } + + public void setName(String name) { this.name = name; } + + public String getDescription() { return description; } + + public void setDescription(String description) { this.description = description; } + + public String getOwners() { return owners; } + + public void setOwners(String owners) { this.owners = owners; } + + public String getCondition() { return condition; } + + public void setCondition(String condition) { this.condition = condition; } + + public String getDefaultAccessTypes() { return defaultAccessTypes; } + + public void setDefaultAccessTypes(String defaultAccessTypes) { this.defaultAccessTypes = defaultAccessTypes; } + + public String getDefaultMasks() { return defaultMasks; } + + public void setDefaultMasks(String defaultMasks) { this.defaultMasks = defaultMasks; } + + public String getTermsOfUse() { return termsOfUse; } + + public void setTermsOfUse(String termsOfUse) { this.termsOfUse = termsOfUse; } + + public String getOptions() { return options; } + + public void setOptions(String options) { this.options = options; } + + public String getAdditionalInfo() { return additionalInfo; } + + public void setAdditionalInfo(String additionalInfo) { this.additionalInfo = additionalInfo; } + + @Override + public int getMyClassType() { return AppConstants.CLASS_TYPE_GDS_DATA_SHARE; } + + @Override + public int hashCode() { + return Objects.hash(id, guid, version, isEnabled, serviceId, zoneId, name, description, owners, condition, defaultAccessTypes, defaultMasks, termsOfUse, options, additionalInfo); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (!super.equals(obj)) { + return false; + } else if (getClass() != obj.getClass()) { + return false; + } + + XXGdsDataShare other = (XXGdsDataShare) obj; + + return Objects.equals(id, other.id) && + Objects.equals(guid, other.guid) && + Objects.equals(version, other.version) && + Objects.equals(isEnabled, other.isEnabled) && + Objects.equals(serviceId, other.serviceId) && + Objects.equals(zoneId, other.zoneId) && + Objects.equals(name, other.name) && + Objects.equals(description, other.description) && + Objects.equals(owners, other.owners) && + Objects.equals(condition, other.condition) && + Objects.equals(defaultAccessTypes, other.defaultAccessTypes) && + Objects.equals(defaultMasks, other.defaultMasks) && + Objects.equals(termsOfUse, other.termsOfUse) && + Objects.equals(options, other.options) && + Objects.equals(additionalInfo, other.additionalInfo); + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("XXGdsDataShare={ ") + .append(super.toString()).append(" ") + .append("id={").append(id).append("} ") + .append("guid={").append(guid).append("} ") + .append("version={").append(version).append("} ") + .append("isEnabled={").append(isEnabled).append("} ") + .append("serviceId={").append(serviceId).append("} ") + .append("zoneId={").append(zoneId).append("} ") + .append("name={").append(name).append("} ") + .append("description={").append(description).append("} ") + .append("owners={").append(owners).append("} ") + .append("condition={").append(condition).append("} ") + .append("defaultAccessTypes={").append(defaultAccessTypes).append("} ") + .append("defaultMasks={").append(defaultMasks).append("} ") + .append("termsOfUse={").append(termsOfUse).append("} ") + .append("options={").append(options).append("} ") + .append("additionalInfo={").append(additionalInfo).append("} ") + .append(" }"); + + return sb; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDataShareInDataset.java b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDataShareInDataset.java new file mode 100644 index 0000000000..8c59e0898b --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDataShareInDataset.java @@ -0,0 +1,184 @@ +/* + * 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.entity; + +import org.apache.ranger.common.AppConstants; + +import javax.persistence.*; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Objects; + +@Entity +@Cacheable +@Table(name="x_gds_data_share_in_dataset") +@XmlRootElement +public class XXGdsDataShareInDataset extends XXDBBase implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @SequenceGenerator(name = "X_GDS_DATA_SHARE_IN_DATASET_SEQ", sequenceName = "X_GDS_DATA_SHARE_IN_DATASET_SEQ", allocationSize = 1) + @GeneratedValue(strategy = GenerationType.AUTO, generator = "X_GDS_DATA_SHARE_IN_DATASET_SEQ") + @Column(name = "id") + protected Long id; + + @Column(name = "guid", unique = true, nullable = false, length = 512) + protected String guid; + + @Version + @Column(name = "version") + protected Long version; + + @Column(name = "is_enabled") + protected Boolean isEnabled; + + @Column(name = "description") + protected String description; + + @Column(name = "data_share_id") + protected Long dataShareId; + + @Column(name = "dataset_id") + protected Long datasetId; + + @Column(name = "status") + protected Short status; + + @Column(name = "validity_period") + protected String validityPeriod; + + @Column(name = "profiles") + protected String profiles; + + @Column(name = "options") + protected String options; + + @Column(name = "additional_info") + protected String additionalInfo; + + + @Override + public void setId(Long id) { this.id = id; } + + @Override + public Long getId() { return id; } + + public String getGuid() { return guid; } + + public void setGuid(String guid) { this.guid = guid; } + + public Long getVersion() { return version; } + + public void setVersion(Long version) { this.version = version; } + + public Boolean getIsEnabled() { return isEnabled; } + + public void setIsEnabled(Boolean isEnabled) { this.isEnabled = isEnabled; } + + public String getDescription() { return description; } + + public void setDescription(String description) { this.description = description; } + + public Long getDataShareId() { return dataShareId; } + + public void setDataShareId(Long dataShareId) { this.dataShareId = dataShareId; } + + public Long getDatasetId() { return datasetId; } + + public void setDatasetId(Long datasetId) { this.datasetId = datasetId; } + + public Short getStatus() { return status; } + + public void setStatus(Short status) { this.status = status; } + + public String getValidityPeriod() { return validityPeriod; } + + public void setValidityPeriod(String validityPeriod) { this.validityPeriod = validityPeriod; } + + public String getProfiles() { return profiles; } + + public void setProfiles(String profiles) { this.profiles = profiles; } + + public String getOptions() { return options; } + + public void setOptions(String options) { this.options = options; } + + public String getAdditionalInfo() { return additionalInfo; } + + public void setAdditionalInfo(String additionalInfo) { this.additionalInfo = additionalInfo; } + + @Override + public int getMyClassType() { return AppConstants.CLASS_TYPE_GDS_DATA_SHARE_IN_DATASET; } + + @Override + public int hashCode() { + return Objects.hash(id, guid, dataShareId, datasetId, status, validityPeriod, profiles, options, additionalInfo); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (getClass() != obj.getClass()) { + return false; + } else if (!super.equals(obj)) { + return false; + } + + XXGdsDataShareInDataset other = (XXGdsDataShareInDataset) obj; + + return Objects.equals(id, other.id) && + Objects.equals(guid, other.guid) && + Objects.equals(version, other.version) && + Objects.equals(isEnabled, other.isEnabled) && + Objects.equals(dataShareId, other.dataShareId) && + Objects.equals(datasetId, other.datasetId) && + Objects.equals(status, other.status) && + Objects.equals(validityPeriod, other.validityPeriod) && + Objects.equals(profiles, other.profiles) && + Objects.equals(options, other.options) && + Objects.equals(additionalInfo, other.additionalInfo); + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("XXDataShareInDataset={ ") + .append(super.toString() + "} ") + .append("id={").append(id).append("} ") + .append("guid={").append(guid).append("} ") + .append("version={").append(version).append("} ") + .append("isEnabled={").append(isEnabled).append("} ") + .append("dataShareId={").append(dataShareId).append("} ") + .append("datasetId={").append(datasetId).append("} ") + .append("status={").append(status).append("} ") + .append("validityPeriod={").append(validityPeriod).append("} ") + .append("profiles={").append(profiles).append("} ") + .append("options={").append(options).append("} ") + .append("additionalInfo={").append(additionalInfo).append("} ") + .append(" }"); + + return sb; + } + +} diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDataset.java b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDataset.java new file mode 100644 index 0000000000..6fc163b47b --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDataset.java @@ -0,0 +1,177 @@ +/* + * 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.entity; + +import org.apache.ranger.common.AppConstants; + +import javax.persistence.*; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Objects; + +@Entity +@Cacheable +@Table(name="x_gds_dataset") +@XmlRootElement +public class XXGdsDataset extends XXDBBase implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @SequenceGenerator(name = "X_GDS_DATASET_SEQ", sequenceName = "X_GDS_DATASET_SEQ", allocationSize = 1) + @GeneratedValue(strategy = GenerationType.AUTO, generator = "X_GDS_DATASET_SEQ") + @Column(name = "id") + protected Long id; + + @Column(name = "guid", unique = true, nullable = false, length = 512) + protected String guid; + + @Version + @Column(name = "version") + protected Long version; + + @Column(name = "is_enabled") + protected Boolean isEnabled; + + @Column(name = "name") + protected String name; + + @Column(name = "description") + protected String description; + + @Column(name = "owners") + protected String owners; + + @Column(name = "acl") + protected String acl; + + @Column(name = "terms_of_use") + protected String termsOfUse; + + @Column(name = "options") + protected String options; + + @Column(name = "additional_info") + protected String additionalInfo; + + + @Override + public void setId(Long id) { this.id = id; } + + @Override + public Long getId() { return id; } + + public String getGuid() { return guid; } + + public void setGuid(String guid) { this.guid = guid; } + + public Long getVersion() { return version; } + + public void setVersion(Long version) { this.version = version; } + + public Boolean getIsEnabled() { return isEnabled; } + + public void setIsEnabled(Boolean isEnabled) { this.isEnabled = isEnabled; } + + public String getName() { return name; } + + public void setName(String name) { this.name = name; } + + public String getDescription() { return description; } + + public void setDescription(String description) { this.description = description; } + + public String getOwners() { return owners; } + + public void setOwners(String owners) { this.owners = owners; } + + public String getAcl() { return acl; } + + public void setAcl(String acl) { this.acl = acl; } + + public String getTermsOfUse() { return termsOfUse; } + + public void setTermsOfUse(String termsOfUse) { this.termsOfUse = termsOfUse; } + + public String getOptions() { return options; } + + public void setOptions(String options) { this.options = options; } + + public String getAdditionalInfo() { return additionalInfo; } + + public void setAdditionalInfo(String additionalInfo) { this.additionalInfo = additionalInfo; } + + @Override + public int getMyClassType() { return AppConstants.CLASS_TYPE_GDS_DATASET; } + + @Override + public int hashCode() { + return Objects.hash(id, guid, version, isEnabled, name, description, owners, acl, termsOfUse, options, additionalInfo); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (!super.equals(obj)) { + return false; + } else if (getClass() != obj.getClass()) { + return false; + } + + XXGdsDataset other = (XXGdsDataset) obj; + + return Objects.equals(id, other.id) && + Objects.equals(guid, other.guid) && + Objects.equals(version, other.version) && + Objects.equals(isEnabled, other.isEnabled) && + Objects.equals(name, other.name) && + Objects.equals(description, other.description) && + Objects.equals(owners, other.owners) && + Objects.equals(acl, other.acl) && + Objects.equals(termsOfUse, other.termsOfUse) && + Objects.equals(options, other.options) && + Objects.equals(additionalInfo, other.additionalInfo); + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("XXGdsDataset={ ") + .append(super.toString()).append(" ") + .append("id={").append(id).append("} ") + .append("guid={").append(guid).append("} ") + .append("version={").append(version).append("} ") + .append("isEnabled={").append(isEnabled).append("} ") + .append("name={").append(name).append("} ") + .append("description={").append(description).append("} ") + .append("owners={").append(owners).append("} ") + .append("condition={").append(acl).append("} ") + .append("acl={").append(acl).append("} ") + .append("termsOfUse={").append(termsOfUse).append("} ") + .append("options={").append(options).append("} ") + .append("additionalInfo={").append(additionalInfo).append("} ") + .append(" }"); + + return sb; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDatasetInProject.java b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDatasetInProject.java new file mode 100644 index 0000000000..6babde5272 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsDatasetInProject.java @@ -0,0 +1,185 @@ +/* + * 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.entity; + +import org.apache.ranger.common.AppConstants; + +import javax.persistence.*; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Objects; + +@Entity +@Cacheable +@Table(name="x_gds_dataset_in_project") +@XmlRootElement +public class XXGdsDatasetInProject extends XXDBBase implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @SequenceGenerator(name = "X_GDS_DATASET_IN_PROJECT_SEQ", sequenceName = "X_GDS_DATASET_IN_PROJECT_SEQ", allocationSize = 1) + @GeneratedValue(strategy = GenerationType.AUTO, generator = "X_GDS_DATASET_IN_PROJECT_SEQ") + @Column(name = "id") + protected Long id; + + @Column(name = "guid", unique = true, nullable = false, length = 512) + protected String guid; + + @Version + @Column(name = "version") + protected Long version; + + @Column(name = "is_enabled") + protected Boolean isEnabled; + + @Column(name = "description") + protected String description; + + @Column(name = "dataset_id") + protected Long datasetId; + + @Column(name = "project_id") + protected Long projectId; + + @Column(name = "status") + protected Short status; + + @Column(name = "validity_period") + protected String validityPeriod; + + @Column(name = "profiles") + protected String profiles; + + @Column(name = "options") + protected String options; + + @Column(name = "additional_info") + protected String additionalInfo; + + + @Override + public void setId(Long id) { this.id = id; } + + @Override + public Long getId() { return id; } + + public String getGuid() { return guid; } + + public void setGuid(String guid) { this.guid = guid; } + + public Long getVersion() { return version; } + + public void setVersion(Long version) { this.version = version; } + + public Boolean getIsEnabled() { return isEnabled; } + + public void setIsEnabled(Boolean isEnabled) { this.isEnabled = isEnabled; } + + public String getDescription() { return description; } + + public void setDescription(String description) { this.description = description; } + + public Long getDatasetId() { return datasetId; } + + public void setDatasetId(Long datasetId) { this.datasetId = datasetId; } + + public Long getProjectId() { return projectId; } + + public void setProjectId(Long projectId) { this.projectId = projectId; } + + public Short getStatus() { return status; } + + public void setStatus(Short status) { this.status = status; } + + public String getValidityPeriod() { return validityPeriod; } + + public void setValidityPeriod(String validityPeriod) { this.validityPeriod = validityPeriod; } + + public String getProfiles() { return profiles; } + + public void setProfiles(String profiles) { this.profiles = profiles; } + + public String getOptions() { return options; } + + public void setOptions(String options) { this.options = options; } + + public String getAdditionalInfo() { return additionalInfo; } + + public void setAdditionalInfo(String additionalInfo) { this.additionalInfo = additionalInfo; } + + @Override + public int getMyClassType() { return AppConstants.CLASS_TYPE_GDS_DATASET_IN_PROJECT; } + + @Override + public int hashCode() { + return Objects.hash(id, guid, datasetId, projectId, status, validityPeriod, profiles, options, additionalInfo); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (getClass() != obj.getClass()) { + return false; + } else if (!super.equals(obj)) { + return false; + } + + XXGdsDatasetInProject other = (XXGdsDatasetInProject) obj; + + return Objects.equals(id, other.id) && + Objects.equals(guid, other.guid) && + Objects.equals(version, other.version) && + Objects.equals(isEnabled, other.isEnabled) && + Objects.equals(description, other.description) && + Objects.equals(datasetId, other.datasetId) && + Objects.equals(projectId, other.projectId) && + Objects.equals(status, other.status) && + Objects.equals(validityPeriod, other.validityPeriod) && + Objects.equals(profiles, other.profiles) && + Objects.equals(options, other.options) && + Objects.equals(additionalInfo, other.additionalInfo); + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("XXDataShareInDataset={ ") + .append(super.toString() + "} ") + .append("id={").append(id).append("} ") + .append("guid={").append(guid).append("} ") + .append("version={").append(version).append("} ") + .append("isEnabled={").append(isEnabled).append("} ") + .append("description={").append(description).append("} ") + .append("datasetId={").append(datasetId).append("} ") + .append("dataShareId={").append(projectId).append("} ") + .append("status={").append(status).append("} ") + .append("validityPeriod={").append(validityPeriod).append("} ") + .append("profiles={").append(profiles).append("} ") + .append("options={").append(options).append("} ") + .append("additionalInfo={").append(additionalInfo).append("} ") + .append(" }"); + + return sb; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXGdsProject.java b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsProject.java new file mode 100644 index 0000000000..d5286d52ce --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsProject.java @@ -0,0 +1,175 @@ +/* + * 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.entity; + +import org.apache.ranger.common.AppConstants; + +import javax.persistence.*; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Objects; + +@Entity +@Cacheable +@Table(name="x_gds_project") +@XmlRootElement +public class XXGdsProject extends XXDBBase implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @SequenceGenerator(name = "X_GDS_PROJECT_SEQ", sequenceName = "X_GDS_PROJECT_SEQ", allocationSize = 1) + @GeneratedValue(strategy = GenerationType.AUTO, generator = "X_GDS_PROJECT_SEQ") + @Column(name = "id") + protected Long id; + + @Column(name = "guid", unique = true, nullable = false, length = 512) + protected String guid; + + @Version + @Column(name = "version") + protected Long version; + + @Column(name = "is_enabled") + protected Boolean isEnabled; + + @Column(name = "name") + protected String name; + + @Column(name = "description") + protected String description; + + @Column(name = "owners") + protected String owners; + + @Column(name = "acl") + protected String acl; + + @Column(name = "terms_of_use") + protected String termsOfUse; + + @Column(name = "options") + protected String options; + + @Column(name = "additional_info") + protected String additionalInfo; + + @Override + public void setId(Long id) { this.id = id; } + + @Override + public Long getId() { return id; } + + public String getGuid() { return guid; } + + public void setGuid(String guid) { this.guid = guid; } + + public Long getVersion() { return version; } + + public void setVersion(Long version) { this.version = version; } + + public Boolean getIsEnabled() { return isEnabled; } + + public void setIsEnabled(Boolean isEnabled) { this.isEnabled = isEnabled; } + + public String getName() { return name; } + + public void setName(String name) { this.name = name; } + + public String getDescription() { return description; } + + public void setDescription(String description) { this.description = description; } + + public String getOwners() { return owners; } + + public void setOwners(String owners) { this.owners = owners; } + + public String getAcl() { return acl; } + + public void setAcl(String acl) { this.acl = acl; } + + public String getTermsOfUse() { return termsOfUse; } + + public void setTermsOfUse(String termsOfUse) { this.termsOfUse = termsOfUse; } + + public String getOptions() { return options; } + + public void setOptions(String options) { this.options = options; } + + public String getAdditionalInfo() { return additionalInfo; } + + public void setAdditionalInfo(String additionalInfo) { this.additionalInfo = additionalInfo; } + + @Override + public int getMyClassType() { return AppConstants.CLASS_TYPE_GDS_PROJECT; } + + @Override + public int hashCode() { + return Objects.hash(id, guid, version, isEnabled, name, description, owners, acl, termsOfUse, options, additionalInfo); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (!super.equals(obj)) { + return false; + } else if (getClass() != obj.getClass()) { + return false; + } + + XXGdsProject other = (XXGdsProject) obj; + + return Objects.equals(id, other.id) && + Objects.equals(guid, other.guid) && + Objects.equals(version, other.version) && + Objects.equals(isEnabled, other.isEnabled) && + Objects.equals(name, other.name) && + Objects.equals(description, other.description) && + Objects.equals(owners, other.owners) && + Objects.equals(acl, other.acl) && + Objects.equals(termsOfUse, other.termsOfUse) && + Objects.equals(options, other.options) && + Objects.equals(additionalInfo, other.additionalInfo); + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("XXGdsProject={ ") + .append(super.toString()).append(" ") + .append("id={").append(id).append("} ") + .append("guid={").append(guid).append("} ") + .append("version={").append(version).append("} ") + .append("isEnabled={").append(isEnabled).append("} ") + .append("name={").append(name).append("} ") + .append("description={").append(description).append("} ") + .append("owners={").append(owners).append("} ") + .append("condition={").append(acl).append("} ") + .append("termsOfUse={").append(termsOfUse).append("} ") + .append("options={").append(options).append("} ") + .append("additionalInfo={").append(additionalInfo).append("} ") + .append(" }"); + + return sb; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXGdsSharedResource.java b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsSharedResource.java new file mode 100644 index 0000000000..3050348698 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/entity/XXGdsSharedResource.java @@ -0,0 +1,230 @@ +/* + * 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.entity; + +import org.apache.ranger.common.AppConstants; + +import javax.persistence.*; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Objects; + +@Entity +@Cacheable +@Table(name="x_gds_shared_resource") +@XmlRootElement +public class XXGdsSharedResource extends XXDBBase implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @SequenceGenerator(name = "X_GDS_SHARED_RESOURCE_SEQ", sequenceName = "X_GDS_SHARED_RESOURCE_SEQ", allocationSize = 1) + @GeneratedValue(strategy = GenerationType.AUTO, generator = "X_GDS_SHARED_RESOURCE_SEQ") + @Column(name = "id") + protected Long id; + + @Column(name = "guid", unique = true, nullable = false, length = 512) + protected String guid; + + @Version + @Column(name = "version") + protected Long version; + + @Column(name = "is_enabled") + protected Boolean isEnabled; + + @Column(name = "name") + protected String name; + + @Column(name = "description") + protected String description; + + @Column(name = "data_share_id") + protected Long dataShareId; + + @Column(name = "resource") + protected String resource; + + @Column(name = "sub_resource_names") + protected String subResourceNames; + + @Column(name = "resource_signature") + protected String resourceSignature; + + @Column(name = "condition") + protected String condition; + + @Column(name = "access_types") + protected String accessTypes; + + @Column(name = "row_filter") + protected String rowFilter; + + @Column(name = "sub_resource_masks") + protected String subResourceMasks; + + @Column(name = "profiles") + protected String profiles; + + @Column(name = "options") + protected String options; + + @Column(name = "additional_info") + protected String additionalInfo; + + + @Override + public void setId(Long id) { this.id = id; } + + @Override + public Long getId() { return id; } + + public String getGuid() { return guid; } + + public void setGuid(String guid) { this.guid = guid; } + + public Long getVersion() { return version; } + + public void setVersion(Long version) { this.version = version; } + + public Boolean getIsEnabled() { return isEnabled; } + + public void setIsEnabled(Boolean isEnabled) { this.isEnabled = isEnabled; } + + public String getName() { return name; } + + public void setName(String name) { this.name = name; } + + public String getDescription() { return description; } + + public void setDescription(String description) { this.description = description; } + + public Long getDataShareId() { return dataShareId; } + + public void setDataShareId(Long dataShareId) { this.dataShareId = dataShareId; } + + public String getResource() { return resource; } + + public void setResource(String resource) { this.resource = resource; } + + public String getSubResourceNames() { return subResourceNames; } + + public void setSubResourceNames(String subResourceNames) { this.subResourceNames = subResourceNames; } + + public String getResourceSignature() { return resourceSignature; } + + public void setResourceSignature(String resourceSignature) { this.resourceSignature = resourceSignature; } + + public String getCondition() { return condition; } + + public void setCondition(String condition) { this.condition = condition; } + + public String getAccessTypes() { return accessTypes; } + + public void setAccessTypes(String accessTypes) { this.accessTypes = accessTypes; } + + public String getRowFilter() { return rowFilter; } + + public void setRowFilter(String rowFilter) { this.rowFilter = rowFilter; } + + public String getSubResourceMasks() { return subResourceMasks; } + + public void setSubResourceMasks(String subResourceMasks) { this.subResourceMasks = subResourceMasks; } + + public String getProfiles() { return profiles; } + + public void setProfiles(String profiles) { this.profiles = profiles; } + + public String getOptions() { return options; } + + public void setOptions(String options) { this.options = options; } + + public String getAdditionalInfo() { return additionalInfo; } + + public void setAdditionalInfo(String additionalInfo) { this.additionalInfo = additionalInfo; } + + @Override + public int getMyClassType() { return AppConstants.CLASS_TYPE_GDS_SHARED_RESOURCE; } + + @Override + public int hashCode() { + return Objects.hash(id, guid, version, isEnabled, name, description, dataShareId, resource, subResourceNames, resourceSignature, condition, accessTypes, rowFilter, subResourceMasks, profiles, options, additionalInfo); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (getClass() != obj.getClass()) { + return false; + } else if (!super.equals(obj)) { + return false; + } + + XXGdsSharedResource other = (XXGdsSharedResource) obj; + + return Objects.equals(id, other.id) && + Objects.equals(guid, other.guid) && + Objects.equals(version, other.version) && + Objects.equals(isEnabled, other.isEnabled) && + Objects.equals(name, other.name) && + Objects.equals(description, other.description) && + Objects.equals(dataShareId, other.dataShareId) && + Objects.equals(resource, other.resource) && + Objects.equals(subResourceNames, other.subResourceNames) && + Objects.equals(resourceSignature, other.resourceSignature) && + Objects.equals(condition, other.condition) && + Objects.equals(accessTypes, other.accessTypes) && + Objects.equals(rowFilter, other.rowFilter) && + Objects.equals(subResourceMasks, other.subResourceMasks) && + Objects.equals(profiles, other.profiles) && + Objects.equals(options, other.options) && + Objects.equals(additionalInfo, other.additionalInfo); + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("XXGdsSharedResource={ ") + .append(super.toString()).append(" ") + .append("id={").append(id).append("} ") + .append("guid={").append(guid).append("} ") + .append("version={").append(version).append("} ") + .append("isEnabled={").append(isEnabled).append("} ") + .append("description={").append(description).append("} ") + .append("name={").append(name).append("} ") + .append("description={").append(description).append("} ") + .append("dataShareId={").append(dataShareId).append("} ") + .append("resource={").append(resource).append("} ") + .append("subResourceNames={").append(subResourceNames).append("} ") + .append("condition={").append(condition).append("} ") + .append("accessTypes={").append(accessTypes).append("} ") + .append("rowFilter={").append(rowFilter).append("} ") + .append("subResourceMasks={").append(subResourceMasks).append("} ") + .append("profiles={").append(profiles).append("} ") + .append("options={").append(options).append("} ") + .append("additionalInfo={").append(additionalInfo).append("} ") + .append(" }"); + + return sb; + } +} 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 new file mode 100644 index 0000000000..653e397d4b --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/rest/GdsREST.java @@ -0,0 +1,1104 @@ +/* + * 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.rest; + +import org.apache.ranger.biz.GdsDBStore; +import org.apache.ranger.common.RESTErrorUtil; +import org.apache.ranger.common.RangerSearchUtil; +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDatasetInProject; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShareInDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; +import org.apache.ranger.plugin.model.RangerGds.RangerSharedResource; +import org.apache.ranger.plugin.store.PList; +import org.apache.ranger.plugin.util.RangerPerfTracer; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.security.context.RangerAPIList; +import org.apache.ranger.service.RangerGdsDatasetService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; + +@Path("gds") +@Component +@Scope("request") +@Transactional(propagation = Propagation.REQUIRES_NEW) +public class GdsREST { + private static final Logger LOG = LoggerFactory.getLogger(GdsREST.class); + private static final Logger PERF_LOG = RangerPerfTracer.getPerfLogger("rest.GdsREST"); + + @Autowired + GdsDBStore gdsStore; + + @Autowired + RangerGdsDatasetService datasetService; + + @Autowired + RangerSearchUtil searchUtil; + + @Autowired + RESTErrorUtil restErrorUtil; + + + @POST + @Path("/dataset") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.CREATE_DATASET + "\")") + public RangerDataset createDataset(RangerDataset dataset) { + LOG.debug("==> GdsREST.createDataset({})", dataset); + + RangerDataset ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.createDataset(datasetName=" + dataset.getName() + ")"); + } + + ret = gdsStore.createDataset(dataset); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("createDataset({}) failed", dataset, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.createDataset({}): {}", dataset, ret); + + return ret; + } + + @PUT + @Path("/dataset/{id}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.UPDATE_DATASET + "\")") + public RangerDataset updateDataset(@PathParam("id") Long datasetId, RangerDataset dataset) { + LOG.debug("==> GdsREST.updateDataset({}, {})", datasetId, dataset); + + RangerDataset ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.updateDataset(datasetId=" + datasetId + ", datasetName=" + dataset.getName() + ")"); + } + + dataset.setId(datasetId); + + ret = gdsStore.updateDataset(dataset); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("updateDataset({}, {}) failed", datasetId, dataset, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.updateDataset({}, {}): {}", datasetId, dataset, ret); + + return ret; + } + + @DELETE + @Path("/dataset/{id}") + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.DELETE_DATASET + "\")") + public void deleteDataset(@PathParam("id") Long datasetId) { + LOG.debug("==> deleteDataset({})", datasetId); + + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.deleteDataset(datasetId=" + datasetId + ")"); + } + + gdsStore.deleteDataset(datasetId); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("deleteDataset({}) failed", datasetId, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== deleteDataset({})", datasetId); + } + + @GET + @Path("/dataset/{id}") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_DATASET + "\")") + public RangerDataset getDataset(@PathParam("id") Long datasetId) { + LOG.debug("==> GdsREST.getDataset({})", datasetId); + + RangerDataset ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.getDataset(datasetId=" + datasetId + ")"); + } + + ret = gdsStore.getDataset(datasetId); + + if (ret == null) { + throw new Exception("no dataset with id=" + datasetId); + } + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("getDataset({}) failed", datasetId, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.getDataset({}): {}", datasetId, ret); + + return ret; + } + + @GET + @Path("/dataset") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.SEARCH_DATASETS + "\")") + public PList searchDatasets(@Context HttpServletRequest request) { + LOG.debug("==> GdsREST.searchDatasets()"); + + PList ret; + RangerPerfTracer perf = null; + SearchFilter filter = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.searchDatasets()"); + } + + filter = searchUtil.getSearchFilter(request, datasetService.sortFields); + + ret = gdsStore.searchDatasets(filter); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("searchDatasets({}) failed", filter, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.listDatasets(): {}", ret); + + return ret; + } + + @GET + @Path("/dataset/names") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.LIST_DATASET_NAMES + "\")") + public PList listDatasetNames(@Context HttpServletRequest request) { + LOG.debug("==> GdsREST.listDatasetNames()"); + + PList ret; + RangerPerfTracer perf = null; + SearchFilter filter = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.searchDatasets()"); + } + + filter = searchUtil.getSearchFilter(request, datasetService.sortFields); + + ret = gdsStore.getDatasetNames(filter); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("listDatasetNames({}) failed", filter, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.listDatasetNames(): {}", ret); + + return ret; + } + + @POST + @Path("/project") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.CREATE_PROJECT + "\")") + public RangerProject createProject(RangerProject project) { + LOG.debug("==> GdsREST.createProject({})", project); + + RangerProject ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.createProject(projectName=" + project.getName() + ")"); + } + + ret = gdsStore.createProject(project); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("createProject({}) failed", project, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.createProject({}): {}", project, ret); + + return ret; + } + + @PUT + @Path("/project/{id}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.UPDATE_PROJECT + "\")") + public RangerProject updateProject(@PathParam("id") Long projectId, RangerProject project) { + LOG.debug("==> GdsREST.updateProject({}, {})", projectId, project); + + RangerProject ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.updateProject(projectId=" + projectId + ", projectName=" + project.getName() + ")"); + } + + project.setId(projectId); + + ret = gdsStore.updateProject(project); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("updateProject({}, {}) failed", projectId, project, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.updateProject({}, {}): {}", projectId, project, ret); + + return ret; + } + + @DELETE + @Path("/project/{id}") + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.DELETE_PROJECT + "\")") + public void deleteProject(@PathParam("id") Long projectId) { + LOG.debug("==> deleteProject({})", projectId); + + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.deleteProject(projectId=" + projectId + ")"); + } + + gdsStore.deleteProject(projectId); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("deleteProject({}) failed", projectId, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== deleteProject({})", projectId); + } + + @GET + @Path("/project/{id}") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_PROJECT + "\")") + public RangerProject getProject(@PathParam("id") Long projectId) { + LOG.debug("==> GdsREST.getProject({})", projectId); + + RangerProject ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.getProject(projectId=" + projectId + ")"); + } + + ret = gdsStore.getProject(projectId); + + if (ret == null) { + throw new Exception("no project with id=" + projectId); + } + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("getProject({}) failed", projectId, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.getProject({}): {}", projectId, ret); + + return ret; + } + + @GET + @Path("/project") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.SEARCH_PROJECTS + "\")") + public PList searchProjects(@Context HttpServletRequest request) { + LOG.debug("==> GdsREST.searchProjects()"); + + PList ret; + RangerPerfTracer perf = null; + SearchFilter filter = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.searchProjects()"); + } + + filter = searchUtil.getSearchFilter(request, datasetService.sortFields); + + ret = gdsStore.searchProjects(filter); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("searchProjects({}) failed", filter, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.listProjects(): {}", ret); + + return ret; + } + + @GET + @Path("/project/names") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.LIST_PROJECT_NAMES + "\")") + public PList listProjectNames(@Context HttpServletRequest request) { + LOG.debug("==> GdsREST.listProjectNames()"); + + PList ret; + RangerPerfTracer perf = null; + SearchFilter filter = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.searchProjects()"); + } + + filter = searchUtil.getSearchFilter(request, datasetService.sortFields); + + ret = gdsStore.getProjectNames(filter); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("listProjectNames({}) failed", filter, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.listProjectNames(): {}", ret); + + return ret; + } + + @POST + @Path("/datashare") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.CREATE_DATA_SHARE + "\")") + public RangerDataShare createDataShare(RangerDataShare dataShare) { + LOG.debug("==> GdsREST.createDataShare({})", dataShare); + + RangerDataShare ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.createDataShare(" + dataShare + ")"); + } + + ret = gdsStore.createDataShare(dataShare); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("createDataShare({}) failed", dataShare, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.createDataShare({}): {}", dataShare, ret); + + return ret; + } + + @PUT + @Path("/datashare/{id}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.UPDATE_DATA_SHARE + "\")") + public RangerDataShare updateDataShare(@PathParam("id") Long dataShareId, RangerDataShare dataShare) { + LOG.debug("==> GdsREST.updateDataShare({}, {})", dataShareId, dataShare); + + RangerDataShare ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.updateDataShare(" + dataShare + ")"); + } + + dataShare.setId(dataShareId); + + ret = gdsStore.updateDataShare(dataShare); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("updateDataShare({}, {}) failed", dataShareId, dataShare, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.updateDataShare({}, {}): {}", dataShareId, dataShare, ret); + + return ret; + } + + @DELETE + @Path("/datashare/{id}") + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.DELETE_DATA_SHARE + "\")") + public void deleteDataShare(@PathParam("id") Long dataShareId) { + LOG.debug("==> GdsREST.deleteDataShare({})", dataShareId); + + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.deleteDataShare(" + dataShareId + ")"); + } + + gdsStore.deleteDataShare(dataShareId); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("deleteDataShare({}) failed", dataShareId, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.deleteDataShare({})", dataShareId); + } + + @GET + @Path("/datashare/{id}") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_DATA_SHARE + "\")") + public RangerDataShare getDataShare(@PathParam("id") Long dataShareId) { + LOG.debug("==> GdsREST.getDataShare({})", dataShareId); + + RangerDataShare ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.getDataShare(" + dataShareId + ")"); + } + + ret = gdsStore.getDataShare(dataShareId); + + if (ret == null) { + throw new Exception("no resourceset with id=" + dataShareId); + } + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("getDataShare({}) failed", dataShareId, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.getDataShare({}): {}", dataShareId, ret); + + return ret; + } + + @GET + @Path("/datashare") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.SEARCH_DATA_SHARES + "\")") + public PList searchDataShares(@Context HttpServletRequest request) { + LOG.debug("==> GdsREST.searchDataShares()"); + + PList ret; + RangerPerfTracer perf = null; + SearchFilter filter = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.searchDataShares()"); + } + + filter = searchUtil.getSearchFilter(request, datasetService.sortFields); + + ret = gdsStore.searchDataShares(filter); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("searchDataShares({}) failed", filter, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.searchDataShares({}): {}", filter, ret); + + return ret; + } + + @POST + @Path("/resource") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.ADD_SHARED_RESOURCE + "\")") + public RangerSharedResource addSharedResource(RangerSharedResource resource) { + LOG.debug("==> GdsREST.addSharedResource({})", resource); + + RangerSharedResource ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.addSharedResource(" + resource + ")"); + } + + ret = gdsStore.addSharedResource(resource); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("addSharedResource({}) failed", resource, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.addSharedResource({}): {}", resource, ret); + + return ret; + } + + @PUT + @Path("/resource/{id}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.UPDATE_SHARED_RESOURCE + "\")") + public RangerSharedResource updateSharedResource(@PathParam("id") Long resourceId, RangerSharedResource resource) { + LOG.debug("==> GdsREST.updateSharedResource({}, {})", resourceId, resource); + + RangerSharedResource ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.updateSharedResource(" + resource + ")"); + } + + resource.setId(resourceId); + + ret = gdsStore.updateSharedResource(resource); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("updateSharedResource({}, {}) failed", resourceId, resource, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.updateSharedResource({}, {}): {}", resourceId, resource, ret); + + return ret; + } + + @DELETE + @Path("/resource/{id}") + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.REMOVE_SHARED_RESOURCE + "\")") + public void removeSharedResource(@PathParam("id") Long resourceId) { + LOG.debug("==> GdsREST.removeSharedResource({})", resourceId); + + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.removeSharedResource(" + resourceId + ")"); + } + + gdsStore.removeSharedResource(resourceId); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("removeSharedResource({}) failed", resourceId, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.removeSharedResource({})", resourceId); + } + + @GET + @Path("/resource/{id}") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_SHARED_RESOURCE + "\")") + public RangerSharedResource getSharedResource(@PathParam("id") Long resourceId) { + LOG.debug("==> GdsREST.getSharedResource({})", resourceId); + + RangerSharedResource ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.getSharedResource(" + resourceId + ")"); + } + + ret = gdsStore.getSharedResource(resourceId); + + if (ret == null) { + throw new Exception("no shared-resource with id=" + resourceId); + } + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("getSharedResource({}) failed", resourceId, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.getSharedResource({}): {}", resourceId, ret); + + return ret; + } + + @GET + @Path("/resource") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.SEARCH_SHARED_RESOURCES + "\")") + public PList searchSharedResources(@Context HttpServletRequest request) { + LOG.debug("==> GdsREST.searchSharedResources()"); + + PList ret; + RangerPerfTracer perf = null; + SearchFilter filter = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.searchSharedResources()"); + } + + filter = searchUtil.getSearchFilter(request, datasetService.sortFields); + + ret = gdsStore.searchSharedResources(filter); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("searchSharedResources({}) failed", filter, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.searchSharedResources({}): {}", filter, ret); + + return ret; + } + + @POST + @Path("/datashare/dataset") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.ADD_DATASHARE_IN_DATASET + "\")") + public RangerDataShareInDataset addDataShareInDataset(RangerDataShareInDataset datasetData) { + LOG.debug("==> GdsREST.addDataShareInDataset({})", datasetData); + + RangerDataShareInDataset ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.addDataShareInDataset(" + datasetData + ")"); + } + + ret = gdsStore.addDataShareInDataset(datasetData); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("addDataShareInDataset({}) failed", datasetData, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.addDataShareInDataset({})", datasetData); + + return ret; + } + + @PUT + @Path("/datashare/dataset/{id}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.UPDATE_DATASHARE_IN_DATASET + "\")") + public RangerDataShareInDataset updateDataShareInDataset(@PathParam("id") Long id, RangerDataShareInDataset dataShareInDataset) { + LOG.debug("==> GdsREST.updateDataShareInDataset({}, {})", id, dataShareInDataset); + + RangerDataShareInDataset ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.updateDataShareInDataset(" + dataShareInDataset + ")"); + } + + dataShareInDataset.setId(id); + + ret = gdsStore.updateDataShareInDataset(dataShareInDataset); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("updateDataShareInDataset({}) failed", dataShareInDataset, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.updateDataShareInDataset({}, {})", id, dataShareInDataset); + + return ret; + } + + @DELETE + @Path("/datashare/dataset/{id}") + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.REMOVE_DATASHARE_IN_DATASET + "\")") + public void removeDataShareInDataset(@PathParam("id") Long id) { + LOG.debug("==> GdsREST.removeDatasetData({})", id); + + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.removeDatasetData(" + id + ")"); + } + + gdsStore.removeDataShareInDataset(id); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("removeDatasetData({}) failed", id, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.removeDatasetData({})", id); + } + + @GET + @Path("/datashare/dataset/{id}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_DATASHARE_IN_DATASET + "\")") + public RangerDataShareInDataset getDataShareInDataset(@PathParam("id") Long id) { + LOG.debug("==> GdsREST.updateDataShareInDataset({})", id); + + RangerDataShareInDataset ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.getDataShareInDataset(" + id + ")"); + } + + ret = gdsStore.getDataShareInDataset(id); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("getDataShareInDataset({}) failed", id, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.getDataShareInDataset({}): ret={}", id, ret); + + return ret; + } + + @GET + @Path("/datashare/dataset") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.SEARCH_DATASHARE_IN_DATASET + "\")") + public PList searchDataShareInDatasets(@Context HttpServletRequest request) { + LOG.debug("==> GdsREST.searchDataShareInDatasets()"); + + PList ret; + RangerPerfTracer perf = null; + SearchFilter filter = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.searchDataShareInDatasets()"); + } + + filter = searchUtil.getSearchFilter(request, datasetService.sortFields); + + ret = gdsStore.searchDataShareInDatasets(filter); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("searchDataShareInDatasets({}) failed", filter, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.searchDataShareInDatasets({}): {}", filter, ret); + + return ret; + } + + + @POST + @Path("/dataset/project") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.ADD_DATASET_IN_PROJECT + "\")") + public RangerDatasetInProject addDatasetInProject(RangerDatasetInProject projectData) { + LOG.debug("==> GdsREST.addDatasetInProject({})", projectData); + + RangerDatasetInProject ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.addDatasetInProject(" + projectData + ")"); + } + + ret = gdsStore.addDatasetInProject(projectData); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("addDatasetInProject({}) failed", projectData, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.addDatasetInProject({})", projectData); + + return ret; + } + + @PUT + @Path("/dataset/project/{id}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.UPDATE_DATASET_IN_PROJECT + "\")") + public RangerDatasetInProject updateDatasetInProject(@PathParam("id") Long id, RangerDatasetInProject dataShareInProject) { + LOG.debug("==> GdsREST.updateDatasetInProject({}, {})", id, dataShareInProject); + + RangerDatasetInProject ret; + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.updateDatasetInProject(" + dataShareInProject + ")"); + } + + dataShareInProject.setId(id); + + ret = gdsStore.updateDatasetInProject(dataShareInProject); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("updateDatasetInProject({}) failed", dataShareInProject, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.updateDatasetInProject({}, {})", id, dataShareInProject); + + return ret; + } + + @DELETE + @Path("/dataset/project/{id}") + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.REMOVE_DATASET_IN_PROJECT + "\")") + public void removeDatasetInProject(@PathParam("id") Long id) { + LOG.debug("==> GdsREST.removeProjectData({})", id); + + RangerPerfTracer perf = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.removeProjectData(" + id + ")"); + } + + gdsStore.removeDatasetInProject(id); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("removeProjectData({}) failed", id, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.removeProjectData({})", id); + } + + @GET + @Path("/dataset/project/{id}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_DATASET_IN_PROJECT + "\")") + public RangerDatasetInProject getDatasetInProject(@PathParam("id") Long id) { + LOG.debug("==> GdsREST.getDatasetInProject({})", id); + + RangerDatasetInProject ret; + RangerPerfTracer perf = null; + + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.getDatasetInProject(" + id + ")"); + } + + ret = gdsStore.getDatasetInProject(id); + } catch (WebApplicationException excp) { + throw excp; + } catch (Throwable excp) { + LOG.error("getDatasetInProject({}) failed", id, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.getDatasetInProject({}): ret={}", id, ret); + + return ret; + } + + @GET + @Path("/dataset/project") + @Produces({ "application/json" }) + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.SEARCH_DATASET_IN_PROJECT + "\")") + public PList searchDatasetInProjects(@Context HttpServletRequest request) { + LOG.debug("==> GdsREST.searchDatasetInProjects()"); + + PList ret; + RangerPerfTracer perf = null; + SearchFilter filter = null; + + try { + if(RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "GdsREST.searchDatasetInProjects()"); + } + + filter = searchUtil.getSearchFilter(request, datasetService.sortFields); + + ret = gdsStore.searchDatasetInProjects(filter); + } catch(WebApplicationException excp) { + throw excp; + } catch(Throwable excp) { + LOG.error("searchDatasetInProjects({}) failed", filter, excp); + + throw restErrorUtil.createRESTException(excp.getMessage()); + } finally { + RangerPerfTracer.log(perf); + } + + LOG.debug("<== GdsREST.searchDatasetInProjects({}): {}", filter, ret); + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/security/context/RangerAPIList.java b/security-admin/src/main/java/org/apache/ranger/security/context/RangerAPIList.java index c83c6f69c9..e3469c62d6 100644 --- a/security-admin/src/main/java/org/apache/ranger/security/context/RangerAPIList.java +++ b/security-admin/src/main/java/org/apache/ranger/security/context/RangerAPIList.java @@ -209,4 +209,45 @@ public class RangerAPIList { public static final String SET_USER_ROLES_BY_NAME="XUserREST.setUserRolesByName"; public static final String GET_USER_ROLES_BY_ID="XUserREST.getUserRolesByID"; public static final String GET_USER_ROLES_BY_NAME="XUserREST.getUserRolesByName"; + + /** + * List of APIs for DataShareREST + */ + public static final String CREATE_DATASET = "GdsREST.createDataset"; + public static final String UPDATE_DATASET = "GdsREST.updateDataset"; + public static final String DELETE_DATASET = "GdsREST.deleteDataset"; + public static final String GET_DATASET = "GdsREST.getDataset"; + public static final String SEARCH_DATASETS = "GdsREST.searchDatasets"; + public static final String LIST_DATASET_NAMES = "GdsREST.listDatasetNames"; + + public static final String CREATE_PROJECT = "GdsREST.createProject"; + public static final String UPDATE_PROJECT = "GdsREST.updateProject"; + public static final String DELETE_PROJECT = "GdsREST.deleteProject"; + public static final String GET_PROJECT = "GdsREST.getProject"; + public static final String SEARCH_PROJECTS = "GdsREST.searchProjects"; + public static final String LIST_PROJECT_NAMES = "GdsREST.listProjectNames"; + + public static final String CREATE_DATA_SHARE = "GdsREST.createDataShare"; + public static final String UPDATE_DATA_SHARE = "GdsREST.updateDataShare"; + public static final String DELETE_DATA_SHARE = "GdsREST.deleteDataShare"; + public static final String GET_DATA_SHARE = "GdsREST.getDataShare"; + public static final String SEARCH_DATA_SHARES = "GdsREST.searchDataShares"; + + public static final String ADD_SHARED_RESOURCE = "GdsREST.addSharedResource"; + public static final String UPDATE_SHARED_RESOURCE = "GdsREST.updateSharedResource"; + public static final String REMOVE_SHARED_RESOURCE = "GdsREST.removeSharedResource"; + public static final String GET_SHARED_RESOURCE = "GdsREST.getSharedResource"; + public static final String SEARCH_SHARED_RESOURCES = "GdsREST.searchSharedResources"; + + public static final String ADD_DATASHARE_IN_DATASET = "GdsREST.addDataShareInDataset"; + public static final String UPDATE_DATASHARE_IN_DATASET = "GdsREST.updateDataShareInDataset"; + public static final String REMOVE_DATASHARE_IN_DATASET = "GdsREST.removeDataShareInDataset"; + public static final String GET_DATASHARE_IN_DATASET = "GdsREST.getDataShareInDataset"; + public static final String SEARCH_DATASHARE_IN_DATASET = "GdsREST.searchDataShareInDataset"; + + public static final String ADD_DATASET_IN_PROJECT = "GdsREST.addDatasetInProject"; + public static final String UPDATE_DATASET_IN_PROJECT = "GdsREST.updateDatasetInProject"; + public static final String REMOVE_DATASET_IN_PROJECT = "GdsREST.removeDatasetInProject"; + public static final String GET_DATASET_IN_PROJECT = "GdsREST.getDatasetInProject"; + public static final String SEARCH_DATASET_IN_PROJECT = "GdsREST.searchDatasetInProject"; } diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerDataHistService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerDataHistService.java index ced9ea81fe..38edcea120 100644 --- a/security-admin/src/main/java/org/apache/ranger/service/RangerDataHistService.java +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerDataHistService.java @@ -30,6 +30,12 @@ import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerService; import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDatasetInProject; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShareInDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerSharedResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @@ -94,6 +100,42 @@ public void createObjectDataHistory(RangerBaseModelObject baseModelObj, String a classType = AppConstants.CLASS_TYPE_RANGER_POLICY; policy.setServiceType(policy.getServiceType()); content = jsonUtil.writeObjectAsString(policy); + } else if (baseModelObj instanceof RangerDataset) { + RangerDataset dataset = (RangerDataset) baseModelObj; + + objectName = dataset.getName(); + classType = AppConstants.CLASS_TYPE_GDS_DATASET; + content = jsonUtil.writeObjectAsString(dataset); + } else if (baseModelObj instanceof RangerProject) { + RangerProject project = (RangerProject) baseModelObj; + + objectName = project.getName(); + classType = AppConstants.CLASS_TYPE_GDS_PROJECT; + content = jsonUtil.writeObjectAsString(project); + } else if (baseModelObj instanceof RangerDataShare) { + RangerDataShare dataShare = (RangerDataShare) baseModelObj; + + objectName = dataShare.getName(); + classType = AppConstants.CLASS_TYPE_GDS_DATA_SHARE; + content = jsonUtil.writeObjectAsString(dataShare); + } else if (baseModelObj instanceof RangerSharedResource) { + RangerSharedResource sharedResource = (RangerSharedResource) baseModelObj; + + objectName = sharedResource.getName(); + classType = AppConstants.CLASS_TYPE_GDS_SHARED_RESOURCE; + content = jsonUtil.writeObjectAsString(sharedResource); + } else if (baseModelObj instanceof RangerDataShareInDataset) { + RangerDataShareInDataset dataShareInDataset = (RangerDataShareInDataset) baseModelObj; + + objectName = dataShareInDataset.getGuid(); + classType = AppConstants.CLASS_TYPE_GDS_DATA_SHARE_IN_DATASET; + content = jsonUtil.writeObjectAsString(dataShareInDataset); + } else if (baseModelObj instanceof RangerDatasetInProject) { + RangerDatasetInProject datasetInProject = (RangerDatasetInProject) baseModelObj; + + objectName = datasetInProject.getGuid(); + classType = AppConstants.CLASS_TYPE_GDS_DATASET_IN_PROJECT; + content = jsonUtil.writeObjectAsString(datasetInProject); } xDataHist.setObjectClassType(classType); diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsBaseModelService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsBaseModelService.java new file mode 100644 index 0000000000..bee32c5969 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsBaseModelService.java @@ -0,0 +1,70 @@ +/* + * 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.service; + +import org.apache.ranger.entity.XXDBBase; +import org.apache.ranger.plugin.model.RangerGds.GdsShareStatus; +import org.apache.ranger.plugin.model.RangerGds.RangerGdsBaseModelObject; +import org.apache.ranger.view.VXMessage; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.List; + +public abstract class RangerGdsBaseModelService extends RangerBaseModelService { + @Autowired + RangerDataHistService dataHistService; + + public void createObjectHistory(V current, V former, int action) { + switch (action) { + case RangerServiceService.OPERATION_CREATE_CONTEXT: + dataHistService.createObjectDataHistory(current, RangerDataHistService.ACTION_CREATE); + break; + + case RangerServiceService.OPERATION_UPDATE_CONTEXT: + dataHistService.createObjectDataHistory(current, RangerDataHistService.ACTION_UPDATE); + break; + + case RangerServiceService.OPERATION_DELETE_CONTEXT: + dataHistService.createObjectDataHistory(current == null ? former : current, RangerDataHistService.ACTION_DELETE); + break; + } + } + + public static List getOrCreateMessageList(List msgList) { + if (msgList == null) { + msgList = new ArrayList<>(); + } + + return msgList; + } + + public static GdsShareStatus toShareStatus(short ordinal) { + GdsShareStatus ret = GdsShareStatus.NONE; + + for (GdsShareStatus status : GdsShareStatus.values()) { + if (status.ordinal() == ordinal) { + ret = status; + + break; + } + } + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDataShareInDatasetService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDataShareInDatasetService.java new file mode 100644 index 0000000000..d32282c273 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDataShareInDatasetService.java @@ -0,0 +1,265 @@ +/* + * 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.service; + + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.authorization.utils.JsonUtils; +import org.apache.ranger.common.GUIDUtil; +import org.apache.ranger.common.MessageEnums; +import org.apache.ranger.common.SearchField; +import org.apache.ranger.common.SortField; +import org.apache.ranger.entity.XXGdsDataShare; +import org.apache.ranger.entity.XXGdsDataShareInDataset; +import org.apache.ranger.entity.XXGdsDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShareInDataset; +import org.apache.ranger.plugin.model.RangerValiditySchedule; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.view.RangerGdsVList.RangerDataShareInDatasetList; +import org.apache.ranger.view.VXMessage; +import org.apache.ranger.view.VXResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; + +@Service +@Scope("singleton") +public class RangerGdsDataShareInDatasetService extends RangerGdsBaseModelService { + private static final Logger LOG = LoggerFactory.getLogger(RangerGdsDataShareInDatasetService.class); + + @Autowired + GUIDUtil guidUtil; + + public RangerGdsDataShareInDatasetService() { + super(); + + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_IN_DATASET_ID, "obj.id", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.GUID , "obj.guid", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.IS_ENABLED, "obj.isEnabled", SearchField.DATA_TYPE.BOOLEAN, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_ID, "obj.dataShareId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATASET_ID, "obj.datasetId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_NAME, "dsh.name", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShare dsh", "obj.dataShareId = dsh.id")); + searchFields.add(new SearchField(SearchFilter.DATASET_NAME, "d.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataset d", "obj.datasetId = d.id")); + + sortFields.add(new SortField(SearchFilter.CREATE_TIME, "obj.createTime")); + sortFields.add(new SortField(SearchFilter.UPDATE_TIME, "obj.updateTime")); + sortFields.add(new SortField(SearchFilter.DATA_SHARE_IN_DATASET_ID, "obj.id", true, SortField.SORT_ORDER.ASC)); + } + + @Override + public RangerDataShareInDataset postCreate(XXGdsDataShareInDataset xObj) { + RangerDataShareInDataset ret = super.postCreate(xObj); + + // TODO: + + return ret; + } + + @Override + public RangerDataShareInDataset postUpdate(XXGdsDataShareInDataset xObj) { + RangerDataShareInDataset ret = super.postUpdate(xObj); + + // TODO: + + return ret; + } + + @Override + public XXGdsDataShareInDataset preDelete(Long id) { + // Update ServiceVersionInfo for each service in the zone + XXGdsDataShareInDataset ret = super.preDelete(id); + + // TODO: + + return ret; + } + + @Override + protected void validateForCreate(RangerDataShareInDataset vObj) { + List msgList = null; + + if (vObj.getDataShareId() == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "dataShareId")); + } + + XXGdsDataShare xDataShare = daoMgr.getXXGdsDataShare().getById(vObj.getDataShareId()); + + if (xDataShare == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "dataShareId")); + } + + if (vObj.getDatasetId() == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "datasetId")); + } + + XXGdsDataset xDataset = daoMgr.getXXGdsDataset().getById(vObj.getDatasetId()); + + if (xDataset == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "datasetId")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in createDataShare({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (StringUtils.isBlank(vObj.getGuid())) { + vObj.setGuid(guidUtil.genGUID()); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected void validateForUpdate(RangerDataShareInDataset vObj, XXGdsDataShareInDataset xObj) { + List msgList = null; + + if (vObj.getDataShareId() == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "dataShareId")); + } + + XXGdsDataShare xDataShare = daoMgr.getXXGdsDataShare().getById(vObj.getDataShareId()); + + if (xDataShare == null || !Objects.equals(xDataShare.getId(), xObj.getDataShareId())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "dataShareId")); + } + + if (vObj.getDatasetId() == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "datasetId")); + } + + XXGdsDataset xDataset = daoMgr.getXXGdsDataset().getById(vObj.getDatasetId()); + + if (xDataset == null || !Objects.equals(xDataset.getId(), xObj.getDatasetId())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "datasetId")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in updateDataShare({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected XXGdsDataShareInDataset mapViewToEntityBean(RangerDataShareInDataset vObj, XXGdsDataShareInDataset xObj, int OPERATION_CONTEXT) { + XXGdsDataShare xDataShare = daoMgr.getXXGdsDataShare().getById(vObj.getDataShareId()); + + if (xDataShare == null) { + throw restErrorUtil.createRESTException("No data share found with ID: " + vObj.getDataShareId(), MessageEnums.INVALID_INPUT_DATA); + } + + XXGdsDataset xDataset = daoMgr.getXXGdsDataset().getById(vObj.getDatasetId()); + + if (xDataset == null) { + throw restErrorUtil.createRESTException("No dataset found with ID: " + vObj.getDatasetId(), MessageEnums.INVALID_INPUT_DATA); + } + + xObj.setGuid(vObj.getGuid()); + xObj.setIsEnabled(vObj.getIsEnabled()); + xObj.setDescription(vObj.getDescription()); + xObj.setDataShareId(vObj.getDataShareId()); + xObj.setDatasetId(vObj.getDatasetId()); + xObj.setStatus((short) vObj.getStatus().ordinal()); + xObj.setValidityPeriod(JsonUtils.objectToJson(vObj.getValiditySchedule())); + xObj.setProfiles(JsonUtils.objectToJson(vObj.getProfiles())); + xObj.setOptions(JsonUtils.mapToJson(vObj.getOptions())); + xObj.setAdditionalInfo(JsonUtils.mapToJson(vObj.getAdditionalInfo())); + + return xObj; + } + + @Override + protected RangerDataShareInDataset mapEntityToViewBean(RangerDataShareInDataset vObj, XXGdsDataShareInDataset xObj) { + vObj.setGuid(xObj.getGuid()); + vObj.setIsEnabled(xObj.getIsEnabled()); + vObj.setVersion(xObj.getVersion()); + vObj.setDescription(xObj.getDescription()); + vObj.setDataShareId(xObj.getDataShareId()); + vObj.setDatasetId(xObj.getDatasetId()); + vObj.setStatus(toShareStatus(xObj.getStatus())); + vObj.setValiditySchedule(JsonUtils.jsonToObject(xObj.getValidityPeriod(), RangerValiditySchedule.class)); + vObj.setProfiles(JsonUtils.jsonToSetString(xObj.getProfiles())); + vObj.setOptions(JsonUtils.jsonToMapStringString(xObj.getOptions())); + vObj.setAdditionalInfo(JsonUtils.jsonToMapStringString(xObj.getAdditionalInfo())); + + return vObj; + } + + public RangerDataShareInDataset getPopulatedViewObject(XXGdsDataShareInDataset xObj) { + return this.populateViewBean(xObj); + } + + public RangerDataShareInDatasetList searchDataShareInDatasets(SearchFilter filter) { + LOG.debug("==> searchDataShareInDatasets({})", filter); + + RangerDataShareInDatasetList ret = new RangerDataShareInDatasetList(); + List datasets = super.searchResources(filter, searchFields, sortFields, ret); + + if (datasets != null) { + for (XXGdsDataShareInDataset dataset : datasets) { + ret.getList().add(getPopulatedViewObject(dataset)); + } + } + + LOG.debug("<== searchDataShareInDatasets({}): ret={}", filter, ret); + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDataShareService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDataShareService.java new file mode 100644 index 0000000000..7053e99167 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDataShareService.java @@ -0,0 +1,283 @@ +/* + * 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.service; + + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.authorization.utils.JsonUtils; +import org.apache.ranger.common.GUIDUtil; +import org.apache.ranger.common.MessageEnums; +import org.apache.ranger.common.SearchField; +import org.apache.ranger.common.SortField; +import org.apache.ranger.entity.XXGdsDataShare; +import org.apache.ranger.entity.XXSecurityZone; +import org.apache.ranger.entity.XXService; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerSecurityZone; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.view.RangerGdsVList.RangerDataShareList; +import org.apache.ranger.view.VXMessage; +import org.apache.ranger.view.VXResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; + +@Service +@Scope("singleton") +public class RangerGdsDataShareService extends RangerGdsBaseModelService { + private static final Logger LOG = LoggerFactory.getLogger(RangerGdsDataShareService.class); + + @Autowired + GUIDUtil guidUtil; + + public RangerGdsDataShareService() { + super(); + + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_NAME, "obj.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_ID, "obj.id", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.GUID , "obj.guid", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.IS_ENABLED, "obj.isEnabled", SearchField.DATA_TYPE.BOOLEAN, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATASET_NAME, "d.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShareInDataset dshid, XXGdsDataset d", "obj.id = dshid.dataShareId and dshid.datasetId = d.id")); + searchFields.add(new SearchField(SearchFilter.DATASET_ID, "dshid.datasetId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShareInDataset dshid", "obj.id = dshid.dataShareId")); + searchFields.add(new SearchField(SearchFilter.PROJECT_NAME, "p.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShareInDataset dshid, XXGdsDatasetInProject dip, XXGdsProject p", "obj.id = dshid.dataShareId and dshid.datasetId = dip.datasetId and dip.projectId = p.id")); + searchFields.add(new SearchField(SearchFilter.PROJECT_ID, "dip.projectId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShareInDataset dshid, XXGdsDatasetInProject dip", "obj.id = dshid.dataShareId and dshid.datasetId = dip.datasetId")); + + sortFields.add(new SortField(SearchFilter.CREATE_TIME, "obj.createTime")); + sortFields.add(new SortField(SearchFilter.UPDATE_TIME, "obj.updateTime")); + sortFields.add(new SortField(SearchFilter.DATASET_ID, "obj.id", true, SortField.SORT_ORDER.ASC)); + sortFields.add(new SortField(SearchFilter.DATASET_NAME, "obj.name")); + } + + @Override + public RangerDataShare postCreate(XXGdsDataShare xObj) { + RangerDataShare ret = super.postCreate(xObj); + + // TODO: + + return ret; + } + + @Override + public RangerDataShare postUpdate(XXGdsDataShare xObj) { + RangerDataShare ret = super.postUpdate(xObj); + + // TODO: + + return ret; + } + + @Override + public XXGdsDataShare preDelete(Long id) { + // Update ServiceVersionInfo for each service in the zone + XXGdsDataShare ret = super.preDelete(id); + + // TODO: + + return ret; + } + + @Override + protected void validateForCreate(RangerDataShare vObj) { + List msgList = null; + + if (StringUtils.isBlank(vObj.getName())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "name")); + } + + XXService xService = daoMgr.getXXService().findByName(vObj.getService()); + + if (xService == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.INVALID_INPUT_DATA.getMessage(null, "service")); + } + + if (!StringUtils.isBlank(vObj.getZone())) { + XXSecurityZone xSecurityZone = daoMgr.getXXSecurityZoneDao().findByZoneName(vObj.getZone()); + + if (xSecurityZone == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.INVALID_INPUT_DATA.getMessage(null, "zone")); + } + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in createDataShare({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (StringUtils.isBlank(vObj.getGuid())) { + vObj.setGuid(guidUtil.genGUID()); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected void validateForUpdate(RangerDataShare vObj, XXGdsDataShare xObj) { + List msgList = null; + + if (StringUtils.isBlank(vObj.getName())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "name")); + } + + XXService xService = daoMgr.getXXService().findByName(vObj.getService()); + + if (xService == null || !Objects.equals(xService.getId(), xObj.getServiceId())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.INVALID_INPUT_DATA.getMessage(null, "service")); + } + + if (!StringUtils.isBlank(vObj.getZone())) { + XXSecurityZone xSecurityZone = daoMgr.getXXSecurityZoneDao().findByZoneName(vObj.getZone()); + + if (xSecurityZone == null || !Objects.equals(xSecurityZone.getId(), xObj.getZoneId())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.INVALID_INPUT_DATA.getMessage(null, "zone")); + } + } else if (!Objects.equals(RangerSecurityZone.RANGER_UNZONED_SECURITY_ZONE_ID, xObj.getZoneId())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.INVALID_INPUT_DATA.getMessage(null, "zone")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in updateDataShare({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected XXGdsDataShare mapViewToEntityBean(RangerDataShare vObj, XXGdsDataShare xObj, int OPERATION_CONTEXT) { + XXService xService = daoMgr.getXXService().findByName(vObj.getService()); + + if (xService == null) { + throw restErrorUtil.createRESTException("No service found with name: " + vObj.getService(), MessageEnums.INVALID_INPUT_DATA); + } + + final Long zoneId; + + if (StringUtils.isBlank(vObj.getZone())) { + zoneId = RangerSecurityZone.RANGER_UNZONED_SECURITY_ZONE_ID; + } else { + XXSecurityZone xSecurityZone = daoMgr.getXXSecurityZoneDao().findByZoneName(vObj.getZone()); + + if (xSecurityZone == null) { + throw restErrorUtil.createRESTException("No security zone found with name: " + vObj.getZone(), MessageEnums.INVALID_INPUT_DATA); + } + + zoneId = xSecurityZone.getId(); + } + + xObj.setGuid(vObj.getGuid()); + xObj.setIsEnabled(vObj.getIsEnabled()); + xObj.setName(vObj.getName()); + xObj.setDescription(vObj.getDescription()); + xObj.setOwners(JsonUtils.listToJson(vObj.getOwners())); + xObj.setServiceId(xService.getId()); + xObj.setZoneId(zoneId); + xObj.setCondition(vObj.getCondition()); + xObj.setDefaultAccessTypes(JsonUtils.objectToJson(vObj.getDefaultAccessTypes())); + xObj.setDefaultMasks(JsonUtils.objectToJson(vObj.getDefaultMasks())); + xObj.setTermsOfUse(vObj.getTermsOfUse()); + xObj.setOptions(JsonUtils.mapToJson(vObj.getOptions())); + xObj.setAdditionalInfo(JsonUtils.mapToJson(vObj.getAdditionalInfo())); + + return xObj; + } + + @Override + protected RangerDataShare mapEntityToViewBean(RangerDataShare vObj, XXGdsDataShare xObj) { + XXService xService = daoMgr.getXXService().getById(xObj.getServiceId()); + XXSecurityZone xSecurityZone = daoMgr.getXXSecurityZoneDao().getById(xObj.getZoneId()); + + String serviceName = xService != null ? xService.getName() : null; + String zoneName = xSecurityZone != null ? xSecurityZone.getName() : null; + + vObj.setGuid(xObj.getGuid()); + vObj.setIsEnabled(xObj.getIsEnabled()); + vObj.setVersion(xObj.getVersion()); + vObj.setName(xObj.getName()); + vObj.setDescription(xObj.getDescription()); + vObj.setOwners(JsonUtils.jsonToRangerPrincipalList(xObj.getOwners())); + vObj.setService(serviceName); + vObj.setZone(zoneName); + vObj.setCondition(xObj.getCondition()); + vObj.setDefaultAccessTypes(JsonUtils.jsonToSetString(xObj.getDefaultAccessTypes())); + vObj.setDefaultMasks(JsonUtils.jsonToMapMaskInfo(xObj.getDefaultMasks())); + vObj.setTermsOfUse(xObj.getTermsOfUse()); + vObj.setOptions(JsonUtils.jsonToMapStringString(xObj.getOptions())); + vObj.setAdditionalInfo(JsonUtils.jsonToMapStringString(xObj.getAdditionalInfo())); + + return vObj; + } + + public RangerDataShare getPopulatedViewObject(XXGdsDataShare xObj) { + return this.populateViewBean(xObj); + } + + public RangerDataShareList searchDataShares(SearchFilter filter) { + LOG.debug("==> searchDataShares({})", filter); + + RangerDataShareList ret = new RangerDataShareList(); + List datasets = super.searchResources(filter, searchFields, sortFields, ret); + + if (datasets != null) { + for (XXGdsDataShare dataset : datasets) { + ret.getList().add(getPopulatedViewObject(dataset)); + } + } + + LOG.debug("<== searchDataShares({}): ret={}", filter, ret); + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetInProjectService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetInProjectService.java new file mode 100644 index 0000000000..0ed51c2493 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetInProjectService.java @@ -0,0 +1,265 @@ +/* + * 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.service; + + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.authorization.utils.JsonUtils; +import org.apache.ranger.common.GUIDUtil; +import org.apache.ranger.common.MessageEnums; +import org.apache.ranger.common.SearchField; +import org.apache.ranger.common.SortField; +import org.apache.ranger.entity.XXGdsProject; +import org.apache.ranger.entity.XXGdsDatasetInProject; +import org.apache.ranger.entity.XXGdsDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDatasetInProject; +import org.apache.ranger.plugin.model.RangerValiditySchedule; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.view.RangerGdsVList.RangerDatasetInProjectList; +import org.apache.ranger.view.VXMessage; +import org.apache.ranger.view.VXResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; + +@Service +@Scope("singleton") +public class RangerGdsDatasetInProjectService extends RangerGdsBaseModelService { + private static final Logger LOG = LoggerFactory.getLogger(RangerGdsDatasetInProjectService.class); + + @Autowired + GUIDUtil guidUtil; + + public RangerGdsDatasetInProjectService() { + super(); + + searchFields.add(new SearchField(SearchFilter.DATASET_IN_PROJECT_ID, "obj.id", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.GUID , "obj.guid", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.IS_ENABLED, "obj.isEnabled", SearchField.DATA_TYPE.BOOLEAN, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATASET_ID, "obj.datasetId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.PROJECT_ID, "obj.projectId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATASET_NAME, "d.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataset d", "obj.datasetId = d.id")); + searchFields.add(new SearchField(SearchFilter.PROJECT_NAME, "p.name", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsProject p", "obj.projectId = p.id")); + + sortFields.add(new SortField(SearchFilter.CREATE_TIME, "obj.createTime")); + sortFields.add(new SortField(SearchFilter.UPDATE_TIME, "obj.updateTime")); + sortFields.add(new SortField(SearchFilter.DATASET_IN_PROJECT_ID, "obj.id", true, SortField.SORT_ORDER.ASC)); + } + + @Override + public RangerDatasetInProject postCreate(XXGdsDatasetInProject xObj) { + RangerDatasetInProject ret = super.postCreate(xObj); + + // TODO: + + return ret; + } + + @Override + public RangerDatasetInProject postUpdate(XXGdsDatasetInProject xObj) { + RangerDatasetInProject ret = super.postUpdate(xObj); + + // TODO: + + return ret; + } + + @Override + public XXGdsDatasetInProject preDelete(Long id) { + // Update ServiceVersionInfo for each service in the zone + XXGdsDatasetInProject ret = super.preDelete(id); + + // TODO: + + return ret; + } + + @Override + protected void validateForCreate(RangerDatasetInProject vObj) { + List msgList = null; + + if (vObj.getDatasetId() == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "datasetId")); + } + + XXGdsDataset xDataset = daoMgr.getXXGdsDataset().getById(vObj.getDatasetId()); + + if (xDataset == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "datasetId")); + } + + if (vObj.getProjectId() == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "projectId")); + } + + XXGdsProject xProject = daoMgr.getXXGdsProject().getById(vObj.getProjectId()); + + if (xProject == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "projectId")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in createProject({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (StringUtils.isBlank(vObj.getGuid())) { + vObj.setGuid(guidUtil.genGUID()); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected void validateForUpdate(RangerDatasetInProject vObj, XXGdsDatasetInProject xObj) { + List msgList = null; + + if (vObj.getDatasetId() == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "datasetId")); + } + + XXGdsDataset xDataset = daoMgr.getXXGdsDataset().getById(vObj.getDatasetId()); + + if (xDataset == null || !Objects.equals(xDataset.getId(), xObj.getDatasetId())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "datasetId")); + } + + if (vObj.getProjectId() == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "projectId")); + } + + XXGdsProject xProject = daoMgr.getXXGdsProject().getById(vObj.getProjectId()); + + if (xProject == null || !Objects.equals(xProject.getId(), xObj.getProjectId())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "projectId")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in updateProject({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected XXGdsDatasetInProject mapViewToEntityBean(RangerDatasetInProject vObj, XXGdsDatasetInProject xObj, int OPERATION_CONTEXT) { + XXGdsDataset xDataset = daoMgr.getXXGdsDataset().getById(vObj.getDatasetId()); + + if (xDataset == null) { + throw restErrorUtil.createRESTException("No dataset found with ID: " + vObj.getDatasetId(), MessageEnums.INVALID_INPUT_DATA); + } + + XXGdsProject xProject = daoMgr.getXXGdsProject().getById(vObj.getProjectId()); + + if (xProject == null) { + throw restErrorUtil.createRESTException("No project found with ID: " + vObj.getProjectId(), MessageEnums.INVALID_INPUT_DATA); + } + + xObj.setGuid(vObj.getGuid()); + xObj.setIsEnabled(vObj.getIsEnabled()); + xObj.setDescription(vObj.getDescription()); + xObj.setProjectId(vObj.getProjectId()); + xObj.setDatasetId(vObj.getDatasetId()); + xObj.setStatus((short) vObj.getStatus().ordinal()); + xObj.setValidityPeriod(JsonUtils.objectToJson(vObj.getValiditySchedule())); + xObj.setProfiles(JsonUtils.objectToJson(vObj.getProfiles())); + xObj.setOptions(JsonUtils.mapToJson(vObj.getOptions())); + xObj.setAdditionalInfo(JsonUtils.mapToJson(vObj.getAdditionalInfo())); + + return xObj; + } + + @Override + protected RangerDatasetInProject mapEntityToViewBean(RangerDatasetInProject vObj, XXGdsDatasetInProject xObj) { + vObj.setGuid(xObj.getGuid()); + vObj.setIsEnabled(xObj.getIsEnabled()); + vObj.setVersion(xObj.getVersion()); + vObj.setDescription(xObj.getDescription()); + vObj.setProjectId(xObj.getProjectId()); + vObj.setDatasetId(xObj.getDatasetId()); + vObj.setStatus(toShareStatus(xObj.getStatus())); + vObj.setValiditySchedule(JsonUtils.jsonToObject(xObj.getValidityPeriod(), RangerValiditySchedule.class)); + vObj.setProfiles(JsonUtils.jsonToSetString(xObj.getProfiles())); + vObj.setOptions(JsonUtils.jsonToMapStringString(xObj.getOptions())); + vObj.setAdditionalInfo(JsonUtils.jsonToMapStringString(xObj.getAdditionalInfo())); + + return vObj; + } + + public RangerDatasetInProject getPopulatedViewObject(XXGdsDatasetInProject xObj) { + return this.populateViewBean(xObj); + } + + public RangerDatasetInProjectList searchDatasetInProjects(SearchFilter filter) { + LOG.debug("==> searchDatasetInProjects({})", filter); + + RangerDatasetInProjectList ret = new RangerDatasetInProjectList(); + List datasets = super.searchResources(filter, searchFields, sortFields, ret); + + if (datasets != null) { + for (XXGdsDatasetInProject dataset : datasets) { + ret.getList().add(getPopulatedViewObject(dataset)); + } + } + + LOG.debug("<== searchDatasetInProjects({}): ret={}", filter, ret); + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java new file mode 100644 index 0000000000..a9c030b1ec --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java @@ -0,0 +1,206 @@ +/* + * 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.service; + + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.authorization.utils.JsonUtils; +import org.apache.ranger.common.GUIDUtil; +import org.apache.ranger.common.MessageEnums; +import org.apache.ranger.common.SearchField; +import org.apache.ranger.common.SortField; +import org.apache.ranger.entity.*; +import org.apache.ranger.plugin.model.RangerGds; +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.view.RangerGdsVList.RangerDatasetList; +import org.apache.ranger.view.VXMessage; +import org.apache.ranger.view.VXResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; + +import java.util.*; + +@Service +@Scope("singleton") +public class RangerGdsDatasetService extends RangerGdsBaseModelService { + private static final Logger LOG = LoggerFactory.getLogger(RangerGdsDatasetService.class); + + @Autowired + GUIDUtil guidUtil; + + public RangerGdsDatasetService() { + super(); + + searchFields.add(new SearchField(SearchFilter.DATASET_NAME, "obj.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATASET_ID, "obj.id", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.GUID , "obj.guid", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.IS_ENABLED, "obj.isEnabled", SearchField.DATA_TYPE.BOOLEAN, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.PROJECT_NAME, "proj.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDatasetInProject dip, XXGdsProject proj", "obj.id = dip.datasetId and dip.projectId = proj.id")); + searchFields.add(new SearchField(SearchFilter.PROJECT_ID, "dip.projectId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDatasetInProject dip", "obj.id = dip.datasetId")); + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_NAME, "ds.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShareInDataset dshid, XXGdsDataShare dsh", "obj.id = dshid.datasetId and dshid.dataShareId = dsh.id")); + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_ID, "dshid.dataShareId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShareInDataset dshid", "obj.id = dshid.datasetId")); + + sortFields.add(new SortField(SearchFilter.CREATE_TIME, "obj.createTime")); + sortFields.add(new SortField(SearchFilter.UPDATE_TIME, "obj.updateTime")); + sortFields.add(new SortField(SearchFilter.DATASET_ID, "obj.id", true, SortField.SORT_ORDER.ASC)); + sortFields.add(new SortField(SearchFilter.DATASET_NAME, "obj.name")); + } + + @Override + public RangerDataset postCreate(XXGdsDataset xObj) { + RangerDataset ret = super.postCreate(xObj); + + // TODO: + + return ret; + } + + @Override + public RangerDataset postUpdate(XXGdsDataset xObj) { + RangerDataset ret = super.postUpdate(xObj); + + // TODO: + + return ret; + } + + @Override + public XXGdsDataset preDelete(Long id) { + // Update ServiceVersionInfo for each service in the zone + XXGdsDataset ret = super.preDelete(id); + + // TODO: + + return ret; + } + + @Override + protected void validateForCreate(RangerDataset vObj) { + List msgList = null; + + if (StringUtils.isBlank(vObj.getName())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "name")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in createDataset({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (StringUtils.isBlank(vObj.getGuid())) { + vObj.setGuid(guidUtil.genGUID()); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected void validateForUpdate(RangerDataset vObj, XXGdsDataset xObj) { + List msgList = null; + + if (StringUtils.isBlank(vObj.getName())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "name")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in updateDataset({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected XXGdsDataset mapViewToEntityBean(RangerDataset vObj, XXGdsDataset xObj, int OPERATION_CONTEXT) { + xObj.setGuid(vObj.getGuid()); + xObj.setIsEnabled(vObj.getIsEnabled()); + xObj.setName(vObj.getName()); + xObj.setDescription(vObj.getDescription()); + xObj.setOwners(JsonUtils.listToJson(vObj.getOwners())); + xObj.setAcl(JsonUtils.objectToJson(vObj.getAcl())); + xObj.setTermsOfUse(vObj.getTermsOfUse()); + xObj.setOptions(JsonUtils.mapToJson(vObj.getOptions())); + xObj.setAdditionalInfo(JsonUtils.mapToJson(vObj.getAdditionalInfo())); + + return xObj; + } + + @Override + protected RangerDataset mapEntityToViewBean(RangerDataset vObj, XXGdsDataset xObj) { + vObj.setGuid(xObj.getGuid()); + vObj.setIsEnabled(xObj.getIsEnabled()); + vObj.setVersion(xObj.getVersion()); + vObj.setName(xObj.getName()); + vObj.setDescription(xObj.getDescription()); + vObj.setOwners(JsonUtils.jsonToRangerPrincipalList(xObj.getOwners())); + vObj.setAcl(JsonUtils.jsonToObject(xObj.getAcl(), RangerGds.RangerGdsACL.class)); + vObj.setTermsOfUse(xObj.getTermsOfUse()); + vObj.setOptions(JsonUtils.jsonToMapStringString(xObj.getOptions())); + vObj.setAdditionalInfo(JsonUtils.jsonToMapStringString(xObj.getAdditionalInfo())); + + return vObj; + } + + public RangerDataset getPopulatedViewObject(XXGdsDataset xObj) { + return this.populateViewBean(xObj); + } + + public RangerDatasetList searchDatasets(SearchFilter filter) { + LOG.debug("==> searchDatasets({})", filter); + + RangerDatasetList ret = new RangerDatasetList(); + List datasets = super.searchResources(filter, searchFields, sortFields, ret); + + if (datasets != null) { + for (XXGdsDataset dataset : datasets) { + ret.getList().add(getPopulatedViewObject(dataset)); + } + } + + LOG.debug("<== searchDatasets({}): ret={}", filter, ret); + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsProjectService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsProjectService.java new file mode 100644 index 0000000000..3dc53bd61e --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsProjectService.java @@ -0,0 +1,206 @@ +/* + * 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.service; + + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.authorization.utils.JsonUtils; +import org.apache.ranger.common.GUIDUtil; +import org.apache.ranger.common.MessageEnums; +import org.apache.ranger.common.SearchField; +import org.apache.ranger.common.SortField; +import org.apache.ranger.entity.XXGdsProject; +import org.apache.ranger.plugin.model.RangerGds; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.view.RangerGdsVList.RangerProjectList; +import org.apache.ranger.view.VXMessage; +import org.apache.ranger.view.VXResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@Scope("singleton") +public class RangerGdsProjectService extends RangerGdsBaseModelService { + private static final Logger LOG = LoggerFactory.getLogger(RangerGdsProjectService.class); + + @Autowired + GUIDUtil guidUtil; + + public RangerGdsProjectService() { + super(); + + searchFields.add(new SearchField(SearchFilter.PROJECT_NAME, "obj.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.PROJECT_ID, "obj.id", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.GUID , "obj.guid", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.IS_ENABLED, "obj.isEnabled", SearchField.DATA_TYPE.BOOLEAN, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATASET_NAME, "d.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDatasetInProject dip, XXGdsDataset d", "obj.id = dip.projectId and dip.datasetId = d.id")); + searchFields.add(new SearchField(SearchFilter.DATASET_ID, "dip.datasetId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDatasetInProject dip", "obj.id = dip.projectId")); + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_NAME, "dsh.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDatasetInProject dip, XXGdsDataShareInDataset dshid, XXGdsDataShare dsh", "obj.id = dip.projectId and dip.datasetId = dshid.datasetId and dshid.dataShareId = dsh.id")); + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_ID, "dshid.dataShareId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDatasetInProject dip, XXGdsDataShareInDataset dsid", "obj.id = dip.projectId and dip.datasetId = dshid.datasetId")); + + sortFields.add(new SortField(SearchFilter.CREATE_TIME, "obj.createTime")); + sortFields.add(new SortField(SearchFilter.UPDATE_TIME, "obj.updateTime")); + sortFields.add(new SortField(SearchFilter.DATASET_ID, "obj.id", true, SortField.SORT_ORDER.ASC)); + sortFields.add(new SortField(SearchFilter.DATASET_NAME, "obj.name")); + } + + @Override + public RangerProject postCreate(XXGdsProject xObj) { + RangerProject ret = super.postCreate(xObj); + + // TODO: + + return ret; + } + + @Override + public RangerProject postUpdate(XXGdsProject xObj) { + RangerProject ret = super.postUpdate(xObj); + + // TODO: + + return ret; + } + + @Override + public XXGdsProject preDelete(Long id) { + // Update ServiceVersionInfo for each service in the zone + XXGdsProject ret = super.preDelete(id); + + // TODO: + + return ret; + } + + @Override + protected void validateForCreate(RangerProject vObj) { + List msgList = null; + + if (StringUtils.isBlank(vObj.getName())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "name")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in createProject({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (StringUtils.isBlank(vObj.getGuid())) { + vObj.setGuid(guidUtil.genGUID()); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected void validateForUpdate(RangerProject vObj, XXGdsProject xObj) { + List msgList = null; + + if (StringUtils.isBlank(vObj.getName())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "name")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in updateProject({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected XXGdsProject mapViewToEntityBean(RangerProject vObj, XXGdsProject xObj, int OPERATION_CONTEXT) { + xObj.setGuid(vObj.getGuid()); + xObj.setIsEnabled(vObj.getIsEnabled()); + xObj.setName(vObj.getName()); + xObj.setDescription(vObj.getDescription()); + xObj.setOwners(JsonUtils.listToJson(vObj.getOwners())); + xObj.setAcl(JsonUtils.objectToJson(vObj.getAcl())); + xObj.setTermsOfUse(vObj.getTermsOfUse()); + xObj.setOptions(JsonUtils.mapToJson(vObj.getOptions())); + xObj.setAdditionalInfo(JsonUtils.mapToJson(vObj.getAdditionalInfo())); + + return xObj; + } + + @Override + protected RangerProject mapEntityToViewBean(RangerProject vObj, XXGdsProject xObj) { + vObj.setGuid(xObj.getGuid()); + vObj.setIsEnabled(xObj.getIsEnabled()); + vObj.setVersion(xObj.getVersion()); + vObj.setName(xObj.getName()); + vObj.setDescription(xObj.getDescription()); + vObj.setOwners(JsonUtils.jsonToRangerPrincipalList(xObj.getOwners())); + vObj.setAcl(JsonUtils.jsonToObject(xObj.getAcl(), RangerGds.RangerGdsACL.class)); + vObj.setTermsOfUse(xObj.getTermsOfUse()); + vObj.setOptions(JsonUtils.jsonToMapStringString(xObj.getOptions())); + vObj.setAdditionalInfo(JsonUtils.jsonToMapStringString(xObj.getAdditionalInfo())); + + return vObj; + } + + public RangerProject getPopulatedViewObject(XXGdsProject xObj) { + return this.populateViewBean(xObj); + } + + public RangerProjectList searchProjects(SearchFilter filter) { + LOG.debug("==> searchProjects({})", filter); + + RangerProjectList ret = new RangerProjectList(); + List projects = super.searchResources(filter, searchFields, sortFields, ret); + + if (projects != null) { + for (XXGdsProject project : projects) { + ret.getList().add(getPopulatedViewObject(project)); + } + } + + LOG.debug("<== searchProjects({}): ret={}", filter, ret); + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsSharedResourceService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsSharedResourceService.java new file mode 100644 index 0000000000..857c412862 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsSharedResourceService.java @@ -0,0 +1,250 @@ +/* + * 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.service; + + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.authorization.utils.JsonUtils; +import org.apache.ranger.common.GUIDUtil; +import org.apache.ranger.common.MessageEnums; +import org.apache.ranger.common.SearchField; +import org.apache.ranger.common.SortField; +import org.apache.ranger.entity.XXGdsDataShare; +import org.apache.ranger.entity.XXGdsSharedResource; +import org.apache.ranger.plugin.model.RangerGds.RangerSharedResource; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.view.RangerGdsVList.RangerSharedResourceList; +import org.apache.ranger.view.VXMessage; +import org.apache.ranger.view.VXResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; + +@Service +@Scope("singleton") +public class RangerGdsSharedResourceService extends RangerGdsBaseModelService { + private static final Logger LOG = LoggerFactory.getLogger(RangerGdsSharedResourceService.class); + + @Autowired + GUIDUtil guidUtil; + + public RangerGdsSharedResourceService() { + super(); + + searchFields.add(new SearchField(SearchFilter.SHARED_RESOURCE_NAME, "obj.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.SHARED_RESOURCE_ID, "obj.id", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.GUID , "obj.guid", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.IS_ENABLED, "obj.isEnabled", SearchField.DATA_TYPE.BOOLEAN, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_NAME, "dsh.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShare dsh", "obj.dataShareId = dsh.id")); + searchFields.add(new SearchField(SearchFilter.DATA_SHARE_ID, "obj.dataShareId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.DATASET_NAME, "d.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShare dsh, XXGdsDataShareInDataset dshid, XXGdsDataset d", "obj.dataShareId = dsh.id and dsh.id = dshid.dataShareId and dshid.datasetId = d.id")); + searchFields.add(new SearchField(SearchFilter.DATASET_ID, "dshid.datasetId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShare dsh, XXGdsDataShareInDataset dshid", "obj.dataShareId = dsh.id and dsh.id = dshid.dataShareId")); + searchFields.add(new SearchField(SearchFilter.PROJECT_NAME, "p.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShare dsh, XXGdsDataShareInDataset dshid, XXGdsDatasetInProject dip, XXGdsProject p", "obj.dataShareId = dsh.id and dsh.id = dshid.dataShareId and dshid.datasetId = dip.datasetId and dip.projectId = p.id")); + searchFields.add(new SearchField(SearchFilter.PROJECT_ID, "dip.projectId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShare dsh, XXGdsDataShareInDataset dshid, XXGdsDatasetInProject dip", "obj.dataShareId = dsh.id and dsh.id = dshid.dataShareId and dshid.datasetId = dip.datasetId")); + + sortFields.add(new SortField(SearchFilter.CREATE_TIME, "obj.createTime")); + sortFields.add(new SortField(SearchFilter.UPDATE_TIME, "obj.updateTime")); + sortFields.add(new SortField(SearchFilter.DATASET_ID, "obj.id", true, SortField.SORT_ORDER.ASC)); + sortFields.add(new SortField(SearchFilter.DATASET_NAME, "obj.name")); + } + + @Override + public RangerSharedResource postCreate(XXGdsSharedResource xObj) { + RangerSharedResource ret = super.postCreate(xObj); + + // TODO: + + return ret; + } + + @Override + public RangerSharedResource postUpdate(XXGdsSharedResource xObj) { + RangerSharedResource ret = super.postUpdate(xObj); + + // TODO: + + return ret; + } + + @Override + public XXGdsSharedResource preDelete(Long id) { + // Update ServiceVersionInfo for each service in the zone + XXGdsSharedResource ret = super.preDelete(id); + + // TODO: + + return ret; + } + + @Override + protected void validateForCreate(RangerSharedResource vObj) { + List msgList = null; + + if (vObj.getDataShareId() == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "dataShareId")); + } + + XXGdsDataShare xDataShare = daoMgr.getXXGdsDataShare().getById(vObj.getDataShareId()); + + if (xDataShare == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "dataShareId")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in createSharedResource({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (StringUtils.isBlank(vObj.getGuid())) { + vObj.setGuid(guidUtil.genGUID()); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected void validateForUpdate(RangerSharedResource vObj, XXGdsSharedResource xObj) { + List msgList = null; + + if (vObj.getDataShareId() == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "dataShareId")); + } + + XXGdsDataShare xDataShare = daoMgr.getXXGdsDataShare().getById(vObj.getDataShareId()); + + if (xDataShare == null) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "dataShareId")); + } + + if (!Objects.equals(vObj.getDataShareId(), xDataShare.getId())) { + msgList = getOrCreateMessageList(msgList); + + msgList.add(MessageEnums.NO_INPUT_DATA.getMessage(null, "dataShareId")); + } + + if (CollectionUtils.isNotEmpty(msgList)) { + VXResponse gjResponse = new VXResponse(); + + gjResponse.setStatusCode(VXResponse.STATUS_ERROR); + gjResponse.setMsgDesc("Validation failure"); + gjResponse.setMessageList(msgList); + + LOG.debug("Validation failure in updateSharedResource({}): error={}", vObj, gjResponse); + + throw restErrorUtil.createRESTException(gjResponse); + } + + if (vObj.getIsEnabled() == null) { + vObj.setIsEnabled(Boolean.TRUE); + } + } + + @Override + protected XXGdsSharedResource mapViewToEntityBean(RangerSharedResource vObj, XXGdsSharedResource xObj, int OPERATION_CONTEXT) { + XXGdsDataShare xDataShare = daoMgr.getXXGdsDataShare().getById(vObj.getDataShareId()); + + if (xDataShare == null) { + throw restErrorUtil.createRESTException("No data share found with ID: " + vObj.getDataShareId(), MessageEnums.INVALID_INPUT_DATA); + } + + xObj.setGuid(vObj.getGuid()); + xObj.setIsEnabled(vObj.getIsEnabled()); + xObj.setName(vObj.getName()); + xObj.setDescription(vObj.getDescription()); + xObj.setDataShareId(vObj.getDataShareId()); + xObj.setResource(JsonUtils.mapToJson(vObj.getResource())); + xObj.setSubResourceNames(JsonUtils.listToJson(vObj.getSubResourceNames())); + xObj.setResourceSignature(vObj.getResourceSignature()); + xObj.setCondition(vObj.getCondition()); + xObj.setAccessTypes(JsonUtils.objectToJson(vObj.getAccessTypes())); + xObj.setRowFilter(JsonUtils.objectToJson(vObj.getRowFilter())); + xObj.setSubResourceMasks(JsonUtils.objectToJson(vObj.getSubResourceMasks())); + xObj.setProfiles(JsonUtils.objectToJson(vObj.getProfiles())); + xObj.setOptions(JsonUtils.mapToJson(vObj.getOptions())); + xObj.setAdditionalInfo(JsonUtils.mapToJson(vObj.getAdditionalInfo())); + + return xObj; + } + + @Override + protected RangerSharedResource mapEntityToViewBean(RangerSharedResource vObj, XXGdsSharedResource xObj) { + vObj.setGuid(xObj.getGuid()); + vObj.setIsEnabled(xObj.getIsEnabled()); + vObj.setVersion(xObj.getVersion()); + vObj.setName(xObj.getName()); + vObj.setDescription(xObj.getDescription()); + vObj.setDataShareId(xObj.getDataShareId()); + vObj.setResource(JsonUtils.jsonToMapPolicyResource(xObj.getResource())); + vObj.setSubResourceNames(JsonUtils.jsonToListString(xObj.getSubResourceNames())); + vObj.setResourceSignature(xObj.getResourceSignature()); + vObj.setCondition(xObj.getCondition()); + vObj.setAccessTypes(JsonUtils.jsonToSetString(xObj.getAccessTypes())); + vObj.setRowFilter(JsonUtils.jsonToObject(xObj.getRowFilter(), RangerPolicy.RangerPolicyItemRowFilterInfo.class)); + vObj.setSubResourceMasks(JsonUtils.jsonToMapMaskInfo(xObj.getSubResourceMasks())); + vObj.setProfiles(JsonUtils.jsonToSetString(xObj.getProfiles())); + vObj.setOptions(JsonUtils.jsonToMapStringString(xObj.getOptions())); + vObj.setAdditionalInfo(JsonUtils.jsonToMapStringString(xObj.getAdditionalInfo())); + + return vObj; + } + + public RangerSharedResource getPopulatedViewObject(XXGdsSharedResource xObj) { + return this.populateViewBean(xObj); + } + + public RangerSharedResourceList searchSharedResources(SearchFilter filter) { + LOG.debug("==> searchSharedResources({})", filter); + + RangerSharedResourceList ret = new RangerSharedResourceList(); + List datasets = super.searchResources(filter, searchFields, sortFields, ret); + + if (datasets != null) { + for (XXGdsSharedResource dataset : datasets) { + ret.getList().add(getPopulatedViewObject(dataset)); + } + } + + LOG.debug("<== searchSharedResources({}): ret={}", filter, ret); + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/validation/RangerGdsValidationDBProvider.java b/security-admin/src/main/java/org/apache/ranger/validation/RangerGdsValidationDBProvider.java new file mode 100644 index 0000000000..cd8fcc6960 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/validation/RangerGdsValidationDBProvider.java @@ -0,0 +1,256 @@ +/* + * 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.validation; + +import org.apache.ranger.biz.RangerBizUtil; +import org.apache.ranger.biz.RoleDBStore; +import org.apache.ranger.biz.ServiceMgr; +import org.apache.ranger.biz.XUserMgr; +import org.apache.ranger.common.RangerRoleCache; +import org.apache.ranger.db.RangerDaoManager; +import org.apache.ranger.entity.*; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.util.RangerRoles; +import org.apache.ranger.plugin.util.RangerRolesUtil; +import org.apache.ranger.plugin.util.ServiceDefUtil; +import org.apache.ranger.service.RangerGdsDataShareService; +import org.apache.ranger.service.RangerGdsDatasetService; +import org.apache.ranger.service.RangerGdsProjectService; +import org.apache.ranger.service.RangerServiceService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.apache.ranger.db.XXGlobalStateDao.RANGER_GLOBAL_STATE_NAME_ROLE; + +@Component +public class RangerGdsValidationDBProvider extends RangerGdsValidationDataProvider { + private static final Logger LOG = LoggerFactory.getLogger(RangerGdsValidationDBProvider.class); + + private static final String SERVICE_NAME_FOR_ROLES = ""; + + @Autowired + RangerDaoManager daoMgr; + + @Autowired + XUserMgr userMgr; + + @Autowired + ServiceMgr serviceMgr; + + @Autowired + RangerServiceService svcService; + + @Autowired + RangerGdsDatasetService datasetService; + + @Autowired + RangerGdsProjectService projectService; + + @Autowired + RangerGdsDataShareService dataShareService; + + @Autowired + RoleDBStore rolesStore; + + @Autowired + RangerBizUtil bizUtil; + + RangerRolesUtil rolesUtil; + + + public RangerGdsValidationDBProvider() { + } + + public Long getServiceId(String name) { + XXService obj = daoMgr.getXXService().findByName(name); + + return obj != null ? obj.getId() : null; + } + + public Long getZoneId(String name) { + XXSecurityZone obj = daoMgr.getXXSecurityZoneDao().findByZoneName(name); + + return obj != null ? obj.getId() : null; + } + + public Long getDatasetId(String name) { + XXGdsDataset obj = daoMgr.getXXGdsDataset().findByName(name); + + return obj != null ? obj.getId() : null; + } + + public Long getProjectId(String name) { + XXGdsProject obj = daoMgr.getXXGdsProject().findByName(name); + + return obj != null ? obj.getId() : null; + } + + public Long getDataShareId(String name) { + XXGdsDataShare obj = daoMgr.getXXGdsDataShare().findByName(name); + + return obj != null ? obj.getId() : null; + } + + public Long getUserId(String name) { + XXUser obj = daoMgr.getXXUser().findByUserName(name); + + return obj != null ? obj.getId() : null; + } + + public Long getGroupId(String name) { + XXGroup obj = daoMgr.getXXGroup().findByGroupName(name); + + return obj != null ? obj.getId() : null; + } + + public Long getRoleId(String name) { + XXRole obj = daoMgr.getXXRole().findByRoleName(name); + + return obj != null ? obj.getId() : null; + } + + public String getCurrentUserLoginId() { + return bizUtil.getCurrentUserLoginId(); + } + + public boolean isAdminUser() { + return bizUtil.isAdmin(); + } + + public boolean isServiceAdmin(String name) { + XXService xService = daoMgr.getXXService().findByName(name); + RangerService service = xService != null ? svcService.getPopulatedViewObject(xService) : null; + + return service != null && bizUtil.isUserServiceAdmin(service, bizUtil.getCurrentUserLoginId()); + + } + + public boolean isZoneAdmin(String zoneName) { + return serviceMgr.isZoneAdmin(zoneName); + } + + public Set getGroupsForUser(String userName) { + return userMgr.getGroupsForUser(userName); + } + + public Set getRolesForUser(String userName) { + RangerRolesUtil rolesUtil = initGetRolesUtil(); + + return rolesUtil != null && rolesUtil.getUserRoleMapping() != null ? rolesUtil.getUserRoleMapping().get(userName) : null; + } + + public Set getAccessTypes(String serviceName) { + List accessTypes = daoMgr.getXXAccessTypeDef().getNamesByServiceName(serviceName); + Set ret = new HashSet<>(accessTypes); + + ret.addAll(ServiceDefUtil.ACCESS_TYPE_MARKERS); + + return ret; + } + + public Set getMaskTypes(String serviceName) { + List maskTypes = daoMgr.getXXDataMaskTypeDef().getNamesByServiceName(serviceName); + Set ret = new HashSet<>(maskTypes); + + return ret; + } + + public RangerDataset getDataset(Long id) { + RangerDataset ret = null; + + if (id != null) { + try { + ret = datasetService.read(id); + } catch (Exception excp) { + LOG.debug("failed to get dataset with id={}", id, excp); + + // ignore + } + } + + return ret; + } + + public RangerProject getProject(Long id) { + RangerProject ret = null; + + if (id != null) { + try { + ret = projectService.read(id); + } catch (Exception excp) { + LOG.debug("failed to get project with id={}", id, excp); + + // ignore + } + } + + return ret; + } + + public RangerDataShare getDataShare(Long id) { + RangerDataShare ret = null; + + try { + ret = dataShareService.read(id); + } catch (Exception excp) { + LOG.debug("failed to get DataShare with id={}", id, excp); + + // ignore + } + + return ret; + } + + public Long getSharedResourceId(Long dataShareId, String name) { + Long ret = daoMgr.getXXGdsSharedResource().getIdByDataShareIdAndName(dataShareId, name); + + return ret; + } + + + private RangerRolesUtil initGetRolesUtil() { + RangerRolesUtil ret = this.rolesUtil; + Long lastKnownVersion = ret != null ? ret.getRoleVersion() : null; + Long currentVersion = daoMgr.getXXGlobalState().getAppDataVersion(RANGER_GLOBAL_STATE_NAME_ROLE); + + if (lastKnownVersion == null || !lastKnownVersion.equals(currentVersion)) { + synchronized (this) { + try { + RangerRoles roles = RangerRoleCache.getInstance().getLatestRangerRoleOrCached(SERVICE_NAME_FOR_ROLES, rolesStore, lastKnownVersion, currentVersion); + + if (roles != null) { + this.rolesUtil = ret = new RangerRolesUtil(roles); + } + } catch (Exception excp) { + LOG.warn("failed to get roles from store", excp); + } + } + } + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/validation/RangerGdsValidationDataProvider.java b/security-admin/src/main/java/org/apache/ranger/validation/RangerGdsValidationDataProvider.java new file mode 100644 index 0000000000..ab74e90e4f --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/validation/RangerGdsValidationDataProvider.java @@ -0,0 +1,70 @@ +/* + * 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.validation; + + +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; + +import java.util.Set; + +public abstract class RangerGdsValidationDataProvider { + public RangerGdsValidationDataProvider() { + } + + public abstract Long getServiceId(String name); + + public abstract Long getZoneId(String name); + + public abstract Long getDatasetId(String name); + + public abstract Long getProjectId(String name); + + public abstract Long getDataShareId(String name); + + public abstract Long getUserId(String name); + + public abstract Long getGroupId(String name); + + public abstract Long getRoleId(String name); + + public abstract String getCurrentUserLoginId(); + + public abstract boolean isAdminUser(); + + public abstract boolean isServiceAdmin(String name); + + public abstract boolean isZoneAdmin(String zoneName); + + public abstract Set getGroupsForUser(String userName); + + public abstract Set getRolesForUser(String userName); + + public abstract Set getAccessTypes(String serviceName); + + public abstract Set getMaskTypes(String serviceName); + + public abstract RangerDataset getDataset(Long id); + + public abstract RangerProject getProject(Long id); + + public abstract RangerDataShare getDataShare(Long id); + + public abstract Long getSharedResourceId(Long dataShareId, String name); +} diff --git a/security-admin/src/main/java/org/apache/ranger/validation/RangerGdsValidator.java b/security-admin/src/main/java/org/apache/ranger/validation/RangerGdsValidator.java new file mode 100644 index 0000000000..7ab7dc583e --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/validation/RangerGdsValidator.java @@ -0,0 +1,704 @@ +/* + * 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.validation; + +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.common.MessageEnums; +import org.apache.ranger.common.RESTErrorUtil; +import org.apache.ranger.plugin.errors.ValidationErrorCode; +import org.apache.ranger.plugin.model.RangerGds; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShareInDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerDatasetInProject; +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerGdsACL; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; +import org.apache.ranger.plugin.model.RangerGds.RangerSharedResource; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; +import org.apache.ranger.plugin.model.RangerPrincipal; +import org.apache.ranger.plugin.model.validation.ValidationFailureDetails; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; + + +@Component +public class RangerGdsValidator { + private static final Logger LOG = LoggerFactory.getLogger(RangerGdsValidator.class); + + private final RangerGdsValidationDataProvider dataProvider; + + @Autowired + RESTErrorUtil restErrorUtil; + + + public RangerGdsValidator(RangerGdsValidationDataProvider dataProvider) { + this.dataProvider = dataProvider; + } + + public void validateCreate(RangerDataset dataset) { + LOG.debug("==> validateCreate(dataset={})", dataset); + + ValidationResult result = new ValidationResult(); + Long existing = dataProvider.getDatasetId(dataset.getName()); + + if (existing != null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATASET_NAME_CONFLICT, "name", dataset.getName(), existing)); + } + + validatePrincipals(dataset.getOwners(), "owners", result); + validateAcl(dataset.getAcl(), "acl", result); + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateCreate(dataset={})", dataset); + } + + public void validateUpdate(RangerDataset dataset, RangerDataset existing) { + LOG.debug("==> validateUpdate(dataset={}, existing={})", dataset, existing); + + ValidationResult result = new ValidationResult(); + + if (existing == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATASET_NAME_NOT_FOUND, "name", dataset.getName())); + } else { + if (!dataProvider.isAdminUser()) { + validateOwner(dataProvider.getCurrentUserLoginId(), existing.getOwners(), result); + } + + validatePrincipals(dataset.getOwners(), "owners", result); + validateAcl(dataset.getAcl(), "acl", result); + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateUpdate(dataset={}, existing={})", dataset, existing); + } + + public void validateDelete(long datasetId, RangerDataset existing) { + LOG.debug("==> validateDelete(datasetId={}, existing={})", datasetId, existing); + + ValidationResult result = new ValidationResult(); + + if (existing == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATASET_ID_NOT_FOUND, "id", datasetId)); + } else { + if (!dataProvider.isAdminUser()) { + validateOwner(dataProvider.getCurrentUserLoginId(), existing.getOwners(), result); + } + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateDelete(datasetId={}, existing={})", datasetId, existing); + } + + public void validateCreate(RangerProject project) { + LOG.debug("==> validateCreate(project={})", project); + + ValidationResult result = new ValidationResult(); + Long existing = dataProvider.getProjectId(project.getName()); + + if (existing != null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_PROJECT_NAME_CONFLICT, "name", project.getName(), existing)); + } + + validatePrincipals(project.getOwners(), "owners", result); + validateAcl(project.getAcl(), "acl", result); + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateCreate(project={})", project); + } + + public void validateUpdate(RangerProject project, RangerProject existing) { + LOG.debug("==> validateUpdate(project={}, existing={})", project, existing); + + ValidationResult result = new ValidationResult(); + + if (existing == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_PROJECT_NAME_NOT_FOUND, "name", project.getName())); + } else { + if (!dataProvider.isAdminUser()) { + validateOwner(dataProvider.getCurrentUserLoginId(), existing.getOwners(), result); + } + + validatePrincipals(project.getOwners(), "owners", result); + validateAcl(project.getAcl(), "acl", result); + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateUpdate(project={}, existing={})", project, existing); + } + + public void validateDelete(long projectId, RangerProject existing) { + LOG.debug("==> validateDelete(projectId={}, existing={})", projectId, existing); + + ValidationResult result = new ValidationResult(); + + if (existing == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_PROJECT_ID_NOT_FOUND, "id", projectId)); + } else { + if (!dataProvider.isAdminUser()) { + validateOwner(dataProvider.getCurrentUserLoginId(), existing.getOwners(), result); + } + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateDelete(projectId={}, existing={})", projectId, existing); + } + + public void validateCreate(RangerDataShare dataShare) { + LOG.debug("==> validateCreate(dataShare={})", dataShare); + + ValidationResult result = new ValidationResult(); + Long existing = dataProvider.getDataShareId(dataShare.getName()); + + if (existing != null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_NAME_CONFLICT, "name", dataShare.getName(), existing)); + } + + validateServiceZoneAdmin(dataShare.getService(), dataShare.getZone(), result); + + validatePrincipals(dataShare.getOwners(), "owners", result); + validateAccessTypes(dataShare.getService(), "defaultAccessTypes", dataShare.getDefaultAccessTypes(), result); + validateMaskTypes(dataShare.getService(), "defaultMasks", dataShare.getDefaultMasks(), result); + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateCreate(dataShare={})", dataShare); + } + + public void validateUpdate(RangerDataShare dataShare, RangerDataShare existing) { + LOG.debug("==> validateUpdate(dataShare={}, existing={})", dataShare, existing); + + ValidationResult result = new ValidationResult(); + + if (existing == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_NAME_NOT_FOUND, "name", dataShare.getName())); + } else { + if (!dataProvider.isAdminUser()) { + validateOwner(dataProvider.getCurrentUserLoginId(), existing.getOwners(), result); + } + + validatePrincipals(dataShare.getOwners(), "owners", result); + validateAccessTypes(dataShare.getService(), "defaultAccessTypes", dataShare.getDefaultAccessTypes(), result); + validateMaskTypes(dataShare.getService(), "defaultMasks", dataShare.getDefaultMasks(), result); + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateUpdate(dataShare={}, existing={})", dataShare, existing); + } + + public void validateDelete(long dataShareId, RangerDataShare existing) { + LOG.debug("==> validateDelete(dataShareId={}, existing={})", dataShareId, existing); + + ValidationResult result = new ValidationResult(); + + if (existing == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_ID_NOT_FOUND, "id", dataShareId)); + } else { + if (!dataProvider.isAdminUser()) { + validateOwner(dataProvider.getCurrentUserLoginId(), existing.getOwners(), result); + } + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateDelete(dataShareId={}, existing={})", dataShareId, existing); + } + + public void validateCreate(RangerSharedResource resource) { + LOG.debug("==> validateCreate(resource={})", resource); + + ValidationResult result = new ValidationResult(); + RangerDataShare dataShare = dataProvider.getDataShare(resource.getDataShareId()); + + if (dataShare == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_ID_NOT_FOUND, "dataShareId", resource.getDataShareId())); + } else { + Long existing = dataProvider.getSharedResourceId(resource.getDataShareId(), resource.getName()); + + if (existing != null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_SHARED_RESOURCE_NAME_CONFLICT, "name", resource.getName(), dataShare.getName(), existing)); + } else { + if (!dataProvider.isAdminUser() && !dataProvider.isServiceAdmin(dataShare.getService()) && !dataProvider.isZoneAdmin(dataShare.getZone())) { + validateOwner(dataProvider.getCurrentUserLoginId(), dataShare.getOwners(), result); + } + } + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateCreate(resource={})", resource); + } + + public void validateUpdate(RangerSharedResource resource, RangerSharedResource existing) { + LOG.debug("==> validateUpdate(resource={}, existing={})", resource, existing); + + ValidationResult result = new ValidationResult(); + + if (existing == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_SHARED_RESOURCE_ID_NOT_FOUND, "id", resource.getId())); + } else { + RangerDataShare dataShare = dataProvider.getDataShare(resource.getDataShareId()); + + if (dataShare == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_ID_NOT_FOUND, "dataShareId", resource.getDataShareId())); + } else { + if (!dataProvider.isAdminUser() && !dataProvider.isServiceAdmin(dataShare.getService()) && !dataProvider.isZoneAdmin(dataShare.getZone())) { + validateOwner(dataProvider.getCurrentUserLoginId(), dataShare.getOwners(), result); + } + } + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateUpdate(resource={}, existing={})", resource, existing); + } + + public void validateDelete(Long resourceId, RangerSharedResource existing) { + LOG.debug("==> validateDelete(resourceId={}, existing={})", resourceId, existing); + + ValidationResult result = new ValidationResult(); + + if (existing == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_SHARED_RESOURCE_ID_NOT_FOUND, "id", resourceId)); + } else { + RangerDataShare dataShare = dataProvider.getDataShare(existing.getDataShareId()); + + if (dataShare == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_ID_NOT_FOUND, "dataShareId", existing.getDataShareId())); + } else { + if (!dataProvider.isAdminUser() && !dataProvider.isServiceAdmin(dataShare.getService()) && !dataProvider.isZoneAdmin(dataShare.getZone())) { + validateOwner(dataProvider.getCurrentUserLoginId(), dataShare.getOwners(), result); + } + } + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateDelete(resourceId={}, existing={})", resourceId, existing); + } + + public void validateCreate(RangerDataShareInDataset dshInDataset) { + LOG.debug("==> validateCreate(dshInDataset={})", dshInDataset); + + ValidationResult result = new ValidationResult(); + RangerDataShare dataShare = dataProvider.getDataShare(dshInDataset.getDataShareId()); + RangerDataset dataset = dataProvider.getDataset(dshInDataset.getDatasetId()); + + if (dataShare == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_ID_NOT_FOUND, "dataShareId", dshInDataset.getDataShareId())); + } + + if (dataset == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATASET_ID_NOT_FOUND, "datasetId", dshInDataset.getDatasetId())); + } + + if (dataShare != null) { + if (!dataProvider.isAdminUser() && !dataProvider.isServiceAdmin(dataShare.getService()) && !dataProvider.isZoneAdmin(dataShare.getZone())) { + validateOwner(dataProvider.getCurrentUserLoginId(), dataShare.getOwners(), result); + } + } + + if (dshInDataset.getStatus() != RangerGds.GdsShareStatus.NONE && dshInDataset.getStatus() != RangerGds.GdsShareStatus.REQUESTED) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_ADD_DATA_SHARE_IN_DATASET_INVALID_STATUS, "status", dshInDataset.getStatus())); + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateCreate(dshInDataset={})", dshInDataset); + } + + public void validateUpdate(RangerDataShareInDataset dshInDataset, RangerDataShareInDataset existing) { + LOG.debug("==> validateUpdate(dshInDataset={}, existing={})", dshInDataset, existing); + + ValidationResult result = new ValidationResult(); + + if (existing == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_IN_DATASET_ID_NOT_FOUND, "id", dshInDataset.getId())); + } else { + RangerDataShare dataShare = dataProvider.getDataShare(existing.getDataShareId()); + RangerDataset dataset = dataProvider.getDataset(existing.getDatasetId()); + + if (dataShare == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_ID_NOT_FOUND, "dataShareId", existing.getDataShareId())); + } + + if (dataset == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATASET_ID_NOT_FOUND, "datasetId", existing.getDatasetId())); + } + + if (!Objects.equals(dshInDataset.getDataShareId(), existing.getDataShareId())) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_UPDATE_IMMUTABLE_FIELD, "dataShareId")); + + dataShare = null; + } + + if (!Objects.equals(dshInDataset.getDatasetId(), existing.getDatasetId())) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_UPDATE_IMMUTABLE_FIELD, "datasetId")); + + dataset = null; + } + + if (dataShare != null && dataset != null) { + boolean requireDataShareOwner = false; + boolean requireDatasetOwner = false; + + if (!Objects.equals(existing.getStatus(), dshInDataset.getStatus())) { + switch (existing.getStatus()) { + case NONE: + if (dshInDataset.getStatus() == RangerGds.GdsShareStatus.REQUESTED) { + requireDatasetOwner = true; + } else if (dshInDataset.getStatus() == RangerGds.GdsShareStatus.GRANTED) { + requireDataShareOwner = true; + } else if (dshInDataset.getStatus() == RangerGds.GdsShareStatus.ACCEPTED) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_INVALID_STATUS_CHANGE, "status", existing.getStatus(), dshInDataset.getStatus())); + } + break; + + case REQUESTED: + if (dshInDataset.getStatus() == RangerGds.GdsShareStatus.NONE) { + requireDatasetOwner = true; + } else if (dshInDataset.getStatus() == RangerGds.GdsShareStatus.GRANTED) { + requireDataShareOwner = true; + } else if (dshInDataset.getStatus() == RangerGds.GdsShareStatus.ACCEPTED) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_INVALID_STATUS_CHANGE, "status", existing.getStatus(), dshInDataset.getStatus())); + } + break; + + case GRANTED: + if (dshInDataset.getStatus() == RangerGds.GdsShareStatus.ACCEPTED) { + requireDatasetOwner = true; + } + break; + + case ACCEPTED: + default: + break; + } + + if (requireDataShareOwner) { + if (!dataProvider.isAdminUser() && !dataProvider.isServiceAdmin(dataShare.getService()) && !dataProvider.isZoneAdmin(dataShare.getZone())) { + validateOwner(dataProvider.getCurrentUserLoginId(), dataShare.getOwners(), result); + } + } else if (requireDatasetOwner) { + if (!dataProvider.isAdminUser()) { + validateOwner(dataProvider.getCurrentUserLoginId(), dataset.getOwners(), result); + } + } else { // must be either a dataset owner or a datashare owner + // TODO: + } + } + } + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateUpdate(dshInDataset={}, existing={})", dshInDataset, existing); + } + + public void validateDelete(Long dshInDatasetId, RangerDataShareInDataset existing) { + LOG.debug("==> validateDelete(dshInDatasetId={}, existing={})", dshInDatasetId, existing); + + ValidationResult result = new ValidationResult(); + + if (existing == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_IN_DATASET_ID_NOT_FOUND, "id", dshInDatasetId)); + } else { + RangerDataShare dataShare = dataProvider.getDataShare(existing.getDataShareId()); + RangerDataset dataset = dataProvider.getDataset(existing.getDatasetId()); + + if (dataShare == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_ID_NOT_FOUND, "dataShareId", existing.getDataShareId())); + } + + if (dataset == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATASET_ID_NOT_FOUND, "datasetId", existing.getDatasetId())); + } + + if (dataShare != null && dataset != null) { + // TODO: must be either a dataset owner or datashare owner + } + } + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateDelete(dshInDatasetId={}, existing={})", dshInDatasetId, existing); + } + + public void validateCreate(RangerDatasetInProject dsInProject) { + LOG.debug("==> validateCreate(dsInProject={})", dsInProject); + + ValidationResult result = new ValidationResult(); + + // TODO: + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateCreate(dsInProject={})", dsInProject); + } + + public void validateUpdate(RangerDatasetInProject dsInProject, RangerDatasetInProject existing) { + LOG.debug("==> validateUpdate(dsInProject={}, existing={})", dsInProject, existing); + + ValidationResult result = new ValidationResult(); + + // TODO: + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateUpdate(dsInProject={}, existing={})", dsInProject, existing); + } + + public void validateDelete(Long dsInProjectId, RangerDatasetInProject existing) { + LOG.debug("==> validateDelete(dsInProjectId={}, existing={})", dsInProjectId, existing); + + ValidationResult result = new ValidationResult(); + + // TODO: + + if (!result.isSuccess()) { + result.throwRESTException(); + } + + LOG.debug("<== validateDelete(dsInProjectId={}, existing={})", dsInProjectId, existing); + } + + + private void validatePrincipals(List principals, String fieldName, ValidationResult result) { + if (principals != null) { + for (RangerPrincipal principal : principals) { + switch (principal.getType()) { + case USER: + validateUser(principal.getName(), fieldName, result); + break; + + case GROUP: + validateGroup(principal.getName(), fieldName, result); + break; + + case ROLE: + validateRole(principal.getName(), fieldName, result); + break; + } + } + } + } + + private void validateAcl(RangerGdsACL acl, String fieldName, ValidationResult result) { + if (acl != null) { + if (acl.getUsers() != null) { + for (String userName : acl.getUsers().keySet()) { + validateUser(userName, fieldName, result); + } + } + + if (acl.getGroups() != null) { + for (String groupName : acl.getGroups().keySet()) { + validateGroup(groupName, fieldName, result); + } + } + + if (acl.getRoles() != null) { + for (String roleName : acl.getRoles().keySet()) { + validateRole(roleName, fieldName, result); + } + } + } + } + + private void validateUser(String userName, String fieldName, ValidationResult result) { + Long userId = dataProvider.getUserId(userName); + + if (userId == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_NON_EXISTING_USER, fieldName, userName)); + } + } + + private void validateGroup(String groupName, String fieldName, ValidationResult result) { + Long groupId = dataProvider.getGroupId(groupName); + + if (groupId == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_NON_EXISTING_GROUP, fieldName, groupName)); + } + } + + private void validateRole(String roleName, String fieldName, ValidationResult result) { + Long roleId = dataProvider.getRoleId(roleName); + + if (roleId == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_NON_EXISTING_ROLE, fieldName, roleName)); + } + } + + private void validateOwner(String userName, List owners, ValidationResult result) { + boolean isOwner = false; + + if (owners != null) { + Set userGroups = null; + Set userRoles = null; + + for (RangerPrincipal owner : owners) { + if (owner.getType() == RangerPrincipal.PrincipalType.USER) { + isOwner = StringUtils.equals(userName, owner.getName()); + } else if (owner.getType() == RangerPrincipal.PrincipalType.GROUP) { + if (userGroups == null) { + userGroups = dataProvider.getGroupsForUser(userName); + } + + isOwner = userGroups.contains(owner.getName()); + } else if (owner.getType() == RangerPrincipal.PrincipalType.ROLE) { + if (userRoles == null) { + if (userGroups == null) { + userGroups = dataProvider.getGroupsForUser(userName); + } + + userRoles = dataProvider.getRolesForUser(userName); + } + + isOwner = userRoles != null && userRoles.contains(owner.getName()); + } + + if (isOwner) { + break; + } + } + } + + if (!isOwner) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_NOT_OWNER, null, userName)); + } + } + + private void validateServiceZoneAdmin(String serviceName, String zoneName, ValidationResult result) { + if (StringUtils.isNotBlank(serviceName)) { + Long serviceId = dataProvider.getServiceId(serviceName); + + if (serviceId == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_NON_EXISTING_SERVICE, null, serviceName)); + } else { + boolean isServiceAdmin = dataProvider.isAdminUser() || dataProvider.isServiceAdmin(serviceName); + + if (!isServiceAdmin) { + if (StringUtils.isNotBlank(zoneName)) { + Long zoneId = dataProvider.getZoneId(zoneName); + + if (zoneId == null) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_NON_EXISTING_ZONE, null, zoneName)); + } else { + boolean isZoneAdmin = dataProvider.isZoneAdmin(zoneName); + + if (!isZoneAdmin) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_NOT_SERVICE_OR_ZONE_ADMIN, "serviceName", serviceName, zoneName)); + } + } + } else { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_DATA_SHARE_NOT_SERVICE_ADMIN, "serviceName", serviceName)); + } + } + } + } else { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_SERVICE_NAME_MISSING, null)); + } + } + + private void validateAccessTypes(String serviceName, String fieldName, Set accessTypes, ValidationResult result) { + if (accessTypes != null && !accessTypes.isEmpty()) { + Set validAccessTypes = dataProvider.getAccessTypes(serviceName); + + for (String accessType : accessTypes) { + if (!validAccessTypes.contains(accessType)) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_INVALID_ACCESS_TYPE, fieldName, accessType)); + } + } + } + } + + private void validateMaskTypes(String serviceName, String fieldName, Map maskTypes, ValidationResult result) { + if (maskTypes != null && !maskTypes.isEmpty()) { + Set validMaskTypes = dataProvider.getMaskTypes(serviceName); + + for (RangerPolicyItemDataMaskInfo maskInfo : maskTypes.values()) { + if (!validMaskTypes.contains(maskInfo.getDataMaskType())) { + result.addValidationFailure(new ValidationFailureDetails(ValidationErrorCode.GDS_VALIDATION_ERR_INVALID_MASK_TYPE, fieldName, maskInfo.getDataMaskType())); + } + } + } + } + + public class ValidationResult { + private final List validationFailures = new ArrayList<>(); + + private ValidationResult() { + } + + public boolean isSuccess() { return validationFailures.isEmpty(); } + + public void addValidationFailure(ValidationFailureDetails validationFailure) { + validationFailures.add(validationFailure); + } + + public List getValidationFailures() { return validationFailures; } + + public void throwRESTException() { + throw restErrorUtil.createRESTException(validationFailures.toString(), MessageEnums.INVALID_INPUT_DATA); + } + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/view/RangerGdsVList.java b/security-admin/src/main/java/org/apache/ranger/view/RangerGdsVList.java new file mode 100644 index 0000000000..9c2400155a --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/view/RangerGdsVList.java @@ -0,0 +1,194 @@ +/* + * 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.view; + +import org.apache.ranger.common.view.VList; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShareInDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDatasetInProject; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; +import org.apache.ranger.plugin.model.RangerGds.RangerSharedResource; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.List; + +public class RangerGdsVList { + + @JsonAutoDetect(getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, fieldVisibility = Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDatasetList extends VList { + private static final long serialVersionUID = 1L; + + List list = new ArrayList<>(); + + public RangerDatasetList() { + super(); + } + + public RangerDatasetList(List objList) { + super(objList); + + this.list = objList; + } + + @Override + public int getListSize() { return list != null ? list.size() : 0; } + + @Override + public List getList() { return list; } + } + + @JsonAutoDetect(getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, fieldVisibility = Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerProjectList extends VList { + private static final long serialVersionUID = 1L; + + List list = new ArrayList<>(); + + public RangerProjectList() { + super(); + } + + public RangerProjectList(List objList) { + super(objList); + + this.list = objList; + } + + @Override + public int getListSize() { return list != null ? list.size() : 0; } + + @Override + public List getList() { return list; } + } + + @JsonAutoDetect(getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, fieldVisibility = Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataShareList extends VList { + private static final long serialVersionUID = 1L; + + List list = new ArrayList<>(); + + public RangerDataShareList() { + super(); + } + + public RangerDataShareList(List objList) { + super(objList); + + this.list = objList; + } + + @Override + public int getListSize() { return list != null ? list.size() : 0; } + + @Override + public List getList() { return list; } + } + + @JsonAutoDetect(getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, fieldVisibility = Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerSharedResourceList extends VList { + private static final long serialVersionUID = 1L; + + List list = new ArrayList<>(); + + public RangerSharedResourceList() { + super(); + } + + public RangerSharedResourceList(List objList) { + super(objList); + + this.list = objList; + } + + @Override + public int getListSize() { return list != null ? list.size() : 0; } + + @Override + public List getList() { return list; } + } + + @JsonAutoDetect(getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, fieldVisibility = Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataShareInDatasetList extends VList { + private static final long serialVersionUID = 1L; + + List list = new ArrayList<>(); + + public RangerDataShareInDatasetList() { + super(); + } + + public RangerDataShareInDatasetList(List objList) { + super(objList); + + this.list = objList; + } + + @Override + public int getListSize() { return list != null ? list.size() : 0; } + + @Override + public List getList() { return list; } + } + + @JsonAutoDetect(getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, fieldVisibility = Visibility.ANY) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDatasetInProjectList extends VList { + private static final long serialVersionUID = 1L; + + List list = new ArrayList<>(); + + public RangerDatasetInProjectList() { + super(); + } + + public RangerDatasetInProjectList(List objList) { + super(objList); + + this.list = objList; + } + + @Override + public int getListSize() { return list != null ? list.size() : 0; } + + @Override + public List getList() { return list; } + } +} diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml index 1762d60c6b..6bf5126e48 100755 --- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml +++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml @@ -536,6 +536,13 @@ obj.name = :name and xSvc.id = :serviceId and obj.defId = xSvc.type + + SELECT obj.name FROM XXAccessTypeDef obj, XXService svc + WHERE svc.name = :serviceName + AND svc.type = obj.defId + + + select obj from XXPolicyConditionDef obj where obj.defId = :serviceDefId order by obj.order @@ -570,6 +577,13 @@ obj.name = :name and xSvc.id = :serviceId and obj.defId = xSvc.type + + SELECT obj.name FROM XXDataMaskTypeDef obj, XXService svc + WHERE svc.name = :serviceName + AND svc.type = obj.defId + + + select obj from XXServiceConfigMap obj where obj.serviceId = :serviceId @@ -2016,4 +2030,132 @@ select obj from XXPolicy obj where obj.zoneId = :zoneId + + select obj from XXGdsDataset obj where obj.guid = :guid + + + + select obj from XXGdsDataset obj where obj.name = :name + + + + + select obj from XXGdsDataset obj, XXGdsDataShareInDataset dsid + where dsid.dataShareId = :dataShareId + and dsid.datasetId = obj.id + + + + + select obj from XXGdsDataset obj, XXGdsDatasetInProject dip + where dip.projectId = :projectId + and dip.datasetId = obj.id + + + + + select obj from XXGdsProject obj where obj.guid = :guid + + + + select obj from XXGdsProject obj where obj.name = :name + + + + select obj from XXGdsProject obj, XXGdsDatasetInProject dip + where dip.datasetId = :datasetId + and dip.projectId = obj.id + + + + select obj from XXGdsDataShare obj where obj.guid = :guid + + + + select obj from XXGdsDataShare obj where obj.name = :name + + + + select obj from XXGdsDataShare obj where obj.serviceId = :serviceId + + + + select obj from XXGdsDataShare obj where obj.serviceId = :serviceId and obj.zoneId = :zoneId + + + + select obj from XXGdsDataShare obj, XXGdsDataShareInDataset dsd + where dsd.datasetId = :datasetId + and dsd.dataShareId = obj.id + + + + + select obj from XXGdsSharedResource obj where obj.guid = :guid + + + + select obj from XXGdsSharedResource obj where obj.name = :name + + + + select obj from XXGdsSharedResource obj, XXGdsDataShare ds + where ds.serviceId = :serviceId + and ds.id = obj.dataShareId + + + + + select obj from XXGdsSharedResource obj, XXGdsDataShare ds + where ds.serviceId = :serviceId + and ds.zoneId = :zoneId + and ds.id = obj.dataShareId + + + + + select obj from XXGdsSharedResource obj, XXGdsDataShareInDataset dsd + where dsd.datasetId = :datasetId + and dsd.dataShareId = obj.dataShareId + + + + + select obj.id from XXGdsSharedResource obj + where obj.dataShareId = :dataShareId + and obj.name = :name + + + + + select obj from XXGdsDataShareInDataset obj where obj.guid = :guid + + + + select obj from XXGdsDataShareInDataset obj where obj.dataShareId = :dataShareId and obj.datasetId = :datasetId + + + + select obj from XXGdsDataShareInDataset obj where obj.dataShareId = :dataShareId + + + + select obj from XXGdsDataShareInDataset obj where obj.datasetId = :datasetId + + + + select obj from XXGdsDatasetInProject obj where obj.guid = :guid + + + + select obj from XXGdsDatasetInProject obj where obj.datasetId = :datasetId and obj.projectId = :projectId + + + + select obj from XXGdsDatasetInProject obj where obj.datasetId = :datasetId + + + + select obj from XXGdsDatasetInProject obj where obj.projectId = :projectId +