From 9887eb7e274511699874422202b5ef9720017b22 Mon Sep 17 00:00:00 2001 From: Anand Nadar Date: Fri, 22 Mar 2024 14:01:48 -0700 Subject: [PATCH] RANGER-4749: added TagREST APIs to retrieve by resource and get paginated resources along with associated tags Signed-off-by: Madhan Neethiraj --- .../ranger/authorization/utils/JsonUtils.java | 11 ++ .../model/RangerServiceResourceWithTags.java | 68 ++++++++++ .../ranger/plugin/util/SearchFilter.java | 2 + .../org/apache/ranger/biz/TagDBStore.java | 63 ++++++++++ .../ranger/common/RangerSearchUtil.java | 98 ++++++++++++++- .../java/org/apache/ranger/rest/TagREST.java | 38 +++++- .../RangerServiceResourceWithTagsService.java | 119 ++++++++++++++++++ ...gerServiceResourceWithTagsServiceBase.java | 67 ++++++++++ .../RangerServiceResourceWithTagsList.java | 62 +++++++++ .../org/apache/ranger/biz/TestTagDBStore.java | 56 ++++++++- .../org/apache/ranger/rest/TestTagREST.java | 51 +++++--- 11 files changed, 609 insertions(+), 26 deletions(-) mode change 100644 => 100755 agents-common/src/main/java/org/apache/ranger/authorization/utils/JsonUtils.java create mode 100755 agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceResourceWithTags.java mode change 100644 => 100755 security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java create mode 100755 security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceWithTagsService.java create mode 100755 security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceWithTagsServiceBase.java create mode 100644 security-admin/src/main/java/org/apache/ranger/view/RangerServiceResourceWithTagsList.java mode change 100644 => 100755 security-admin/src/test/java/org/apache/ranger/biz/TestTagDBStore.java mode change 100644 => 100755 security-admin/src/test/java/org/apache/ranger/rest/TestTagREST.java 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 old mode 100644 new mode 100755 index 716a1a9ea7..8113e4280f --- 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 @@ -26,6 +26,7 @@ import org.apache.ranger.plugin.model.AuditFilter; import org.apache.ranger.plugin.model.RangerGds.RangerTagDataMaskInfo; import org.apache.ranger.plugin.model.RangerPrincipal; +import org.apache.ranger.plugin.model.RangerTag; import org.apache.ranger.plugin.model.RangerValidityRecurrence; import org.apache.ranger.plugin.model.RangerValiditySchedule; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; @@ -51,6 +52,7 @@ public class JsonUtils { private static final Type TYPE_LIST_RANGER_TAG_MASK_INFO = 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 Type TYPE_LIST_RANGER_TAG = new TypeToken>() {}.getType(); private static final ThreadLocal gson = new ThreadLocal() { @Override @@ -189,6 +191,15 @@ public static List jsonToRangerPrincipalList(String jsonStr) { } } + public static List jsonToRangerTagList(String jsonStr) { + try { + return gson.get().fromJson(jsonStr, TYPE_LIST_RANGER_TAG); + } 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); diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceResourceWithTags.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceResourceWithTags.java new file mode 100755 index 0000000000..f3c24d6233 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceResourceWithTags.java @@ -0,0 +1,68 @@ +/* + * 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 java.util.List; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY) +@JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown=true) +public class RangerServiceResourceWithTags extends RangerServiceResource implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private List associatedTags; + + public List getAssociatedTags() { + return associatedTags; + } + + public void setAssociatedTags(List associatedTags) { + this.associatedTags = associatedTags; + } + + @Override + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerServiceResourceWithTags={ "); + + super.toString(sb); + + sb.append("associatedTags=["); + if (associatedTags != null) { + String prefix = ""; + + for (RangerTag associatedTag : associatedTags) { + sb.append(prefix); + + associatedTag.toString(sb); + + prefix = ", "; + } + } + sb.append("] "); + + sb.append(" }"); + + return sb; + } +} 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 b0fad0aea1..0da5f2aafd 100755 --- 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 @@ -76,6 +76,7 @@ public class SearchFilter { public static final String TAG_DEF_ID = "tagDefId"; // search public static final String TAG_DEF_GUID = "tagDefGuid"; // search + public static final String TAG_NAMES = "tagNames"; // search public static final String TAG_TYPE = "tagType"; // search public static final String TAG_TYPE_PARTIAL = "tagTypePartial"; // search public static final String TAG_SOURCE = "tagSource"; // search @@ -88,6 +89,7 @@ public class SearchFilter { public static final String TAG_RESOURCE_GUID = "resourceGuid"; // search public static final String TAG_RESOURCE_SERVICE_NAME = "resourceServiceName"; // search public static final String TAG_RESOURCE_SIGNATURE = "resourceSignature"; // search + public static final String TAG_RESOURCE_ELEMENTS = "resourceElements"; // search public static final String TAG_MAP_ID = "tagResourceMapId"; // search public static final String TAG_MAP_GUID = "tagResourceMapGuid"; // search diff --git a/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java old mode 100644 new mode 100755 index a472fe131c..ce59505848 --- a/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -45,6 +46,7 @@ import org.apache.ranger.entity.XXTagDef; import org.apache.ranger.entity.XXTagResourceMap; import org.apache.ranger.plugin.model.*; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; import org.apache.ranger.plugin.model.validation.RangerValidityScheduleValidator; import org.apache.ranger.plugin.model.validation.ValidationFailureDetails; import org.apache.ranger.plugin.store.AbstractTagStore; @@ -59,7 +61,9 @@ import org.apache.ranger.service.RangerTagDefService; import org.apache.ranger.service.RangerTagResourceMapService; import org.apache.ranger.service.RangerTagService; +import org.apache.ranger.view.RangerServiceResourceWithTagsList; import org.apache.ranger.service.RangerServiceResourceService; +import org.apache.ranger.service.RangerServiceResourceWithTagsService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -89,6 +93,9 @@ public class TagDBStore extends AbstractTagStore { @Autowired RangerServiceResourceService rangerServiceResourceService; + @Autowired + RangerServiceResourceWithTagsService rangerServiceResourceWithTagsService; + @Autowired RangerTagResourceMapService rangerTagResourceMapService; @@ -714,6 +721,10 @@ public PList getPaginatedServiceResources(SearchFilter fi return ret; } + public RangerServiceResourceWithTagsList getPaginatedServiceResourcesWithTags(SearchFilter filter) throws Exception { + return rangerServiceResourceWithTagsService.searchServiceResourcesWithTags(filter); + } + @Override public RangerTagResourceMap createTagResourceMap(RangerTagResourceMap tagResourceMap) throws Exception { @@ -1386,4 +1397,56 @@ private void deleteTagDef(RangerTagDef tagDef) throws Exception { } } } + + public RangerServiceResource getRangerServiceResource(String serviceName, Map resourceMap) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> TagDBStore.getRangerServiceResource(): serviceName={" + serviceName + "}"); + } + + Map resourceElements = new HashMap<>(); + + for (Map.Entry entry : resourceMap.entrySet()) { + String[] parts = entry.getKey().split("\\."); + String[] valueArray = entry.getValue(); + + if (parts.length < 1 || valueArray == null) { + continue; + } + + String key = parts[0]; + + RangerPolicyResource policyResource = resourceElements.get(key); + + if (policyResource == null) { + policyResource = new RangerPolicyResource(); + + resourceElements.put(key, policyResource); + } + + if (parts.length == 1) { + List valueList = new ArrayList<>(); + + for (String str : valueArray) { + valueList.add(str.trim()); + } + } else if (parts.length == 2 && valueArray[0] != null) { + String subKey = parts[1]; + String value = valueArray[0]; + + if (subKey.equalsIgnoreCase("isExcludes")) { + policyResource.setIsExcludes(Boolean.parseBoolean(value.trim())); + } else if (subKey.equalsIgnoreCase("isRecursive")) { + policyResource.setIsRecursive(Boolean.parseBoolean(value.trim())); + } + } + } + + RangerServiceResource ret = new RangerServiceResource(serviceName, resourceElements); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== TagDBStore.getRangerServiceResource(): (serviceName={" + serviceName + "} RangerServiceResource={" + ret + "})"); + } + + return ret; + } } 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 c816ad2290..fcef33269b 100755 --- a/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java +++ b/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java @@ -19,11 +19,7 @@ package org.apache.ranger.common; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import javax.annotation.Nonnull; import javax.persistence.EntityManager; @@ -106,6 +102,7 @@ public SearchFilter getSearchFilter(@Nonnull HttpServletRequest request, List strValueList = new ArrayList<>(); + + for (Object value : multiValue) { + strValueList.add(String.valueOf(value)); + } + + if (!strValueList.isEmpty()) { + if (searchField.getCustomCondition() == null) { + if (strValueList.size() <= minInListLength) { + whereClause.append(" and "); + + if (strValueList.size() > 1) { + whereClause.append(" ( "); + } + + for (int count = 0; count < strValueList.size(); count++) { + if (count > 0) { + whereClause.append(" or "); + } + + whereClause.append(searchField.getFieldName()).append("= :") + .append(searchField.getClientFieldName()).append("_").append(count); + } + + if (strValueList.size() > 1) { + whereClause.append(" ) "); + } + } else { whereClause.append(" and ") .append(searchField.getFieldName()) @@ -477,6 +513,22 @@ protected void resolveQueryParams(Query query, SearchFilter searchCriteria, List query.setParameter(searchField.getClientFieldName(), intValueList); } } + } else if (isMultiValue && searchField.getDataType() == SearchField.DATA_TYPE.STR_LIST) { + List strValueList = new ArrayList<>(); + + for (Object value : multiValue) { + strValueList.add(String.valueOf(value)); + } + + if (!strValueList.isEmpty()) { + if (strValueList.size() <= minInListLength) { + for (int idx = 0; idx < strValueList.size(); idx++) { + query.setParameter(searchField.getClientFieldName() + "_" + idx, strValueList.get(idx)); + } + } else { + query.setParameter(searchField.getClientFieldName(), strValueList); + } + } } else if (searchField.getDataType() == SearchField.DATA_TYPE.INTEGER) { Integer paramVal = restErrorUtil.parseInt(searchCriteria.getParam(searchField.getClientFieldName()), "Invalid value for " + searchField.getClientFieldName(), @@ -599,6 +651,42 @@ public void extractIntList(HttpServletRequest request, SearchFilter searchFilter } } + public void extractStringList(HttpServletRequest request, SearchFilter searchFilter, String paramName, + String userFriendlyParamName, String listName, String[] validValues, String regEx) { + String[] values = getParamMultiValues(request, paramName); + + if (values != null) { + List stringList = new ArrayList<>(values.length); + + for (String value : values) { + if (!stringUtil.isEmpty(regEx)) { + restErrorUtil.validateString(value, regEx, "Invalid value for " + userFriendlyParamName, MessageEnums.INVALID_INPUT_DATA, null, paramName); + } + + stringList.add(value); + } + + searchFilter.setMultiValueParam(paramName, stringList.toArray()); + } + } + + public Map getMultiValueParamsWithPrefix(HttpServletRequest request, String prefix, boolean stripPrefix) { + Map ret = new HashMap(); + for (Map.Entry e : request.getParameterMap().entrySet()) { + String name = e.getKey(); + String[] values = e.getValue(); + + if (!StringUtils.isEmpty(name) && !ArrayUtils.isEmpty(values) + && name.startsWith(prefix)) { + if(stripPrefix) { + name = name.substring(prefix.length()); + } + ret.put(name, values); + } + } + return ret; + } + /** * @param request * @param paramName diff --git a/security-admin/src/main/java/org/apache/ranger/rest/TagREST.java b/security-admin/src/main/java/org/apache/ranger/rest/TagREST.java index 09d7715655..882bf4d861 100755 --- a/security-admin/src/main/java/org/apache/ranger/rest/TagREST.java +++ b/security-admin/src/main/java/org/apache/ranger/rest/TagREST.java @@ -40,6 +40,7 @@ import org.apache.ranger.plugin.model.RangerTagDef; import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; import org.apache.ranger.plugin.store.PList; +import org.apache.ranger.plugin.store.RangerServiceResourceSignature; import org.apache.ranger.plugin.store.TagStore; import org.apache.ranger.plugin.store.TagValidator; import org.apache.ranger.plugin.util.RangerPerfTracer; @@ -47,9 +48,11 @@ import org.apache.ranger.plugin.util.SearchFilter; import org.apache.ranger.plugin.util.ServiceTags; import org.apache.ranger.service.RangerServiceResourceService; +import org.apache.ranger.service.RangerServiceResourceWithTagsService; import org.apache.ranger.service.RangerTagDefService; import org.apache.ranger.service.RangerTagResourceMapService; import org.apache.ranger.service.RangerTagService; +import org.apache.ranger.view.RangerServiceResourceWithTagsList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -75,6 +78,7 @@ import javax.ws.rs.core.Context; import java.util.List; +import java.util.Map; @Path(TagRESTConstants.TAGDEF_NAME_AND_VERSION) @Component @@ -118,6 +122,9 @@ public class TagREST { @Autowired RangerServiceResourceService rangerServiceResourceService; + @Autowired + RangerServiceResourceWithTagsService rangerServiceResourceWithTagsService; + @Autowired RangerTagResourceMapService rangerTagResourceMapService; @@ -1011,6 +1018,27 @@ public RangerServiceResource getServiceResourceByServiceAndResourceSignature(@Pa return ret; } + @GET + @Path(TagRESTConstants.RESOURCE_RESOURCE + "service/{serviceName}/resource") + @Produces({ "application/json" }) + @PreAuthorize("hasRole('ROLE_SYS_ADMIN')") + public RangerServiceResource getServiceResourceByResource(@PathParam("serviceName") String serviceName, @Context HttpServletRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> TagREST.getServiceResourceByResource(" + serviceName + ")"); + } + + Map resourceMap = searchUtil.getMultiValueParamsWithPrefix(request, SearchFilter.RESOURCE_PREFIX, true); + RangerServiceResource serviceResource = tagStore.getRangerServiceResource(serviceName, resourceMap); + + serviceResource = getServiceResourceByServiceAndResourceSignature(serviceName, new RangerServiceResourceSignature(serviceResource).getSignature()); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== TagREST.getServiceResourceByResource(serviceName={" + serviceName + "} RangerServiceResource={" + serviceResource + "})"); + } + + return serviceResource; + } + @GET @Path(TagRESTConstants.RESOURCES_RESOURCE) @Produces({ "application/json" }) @@ -1041,18 +1069,18 @@ public List getAllServiceResources() { @Path(TagRESTConstants.RESOURCES_RESOURCE_PAGINATED) @Produces({ "application/json" }) @PreAuthorize("hasRole('ROLE_SYS_ADMIN')") - public PList getServiceResources(@Context HttpServletRequest request) { + public RangerServiceResourceWithTagsList getServiceResourcesWithTags(@Context HttpServletRequest request) { if (LOG.isDebugEnabled()) { LOG.debug("==> TagREST.getServiceResources()"); } - final PList ret; + RangerServiceResourceWithTagsList ret; try { - SearchFilter filter = searchUtil.getSearchFilter(request, rangerServiceResourceService.sortFields); + SearchFilter filter = searchUtil.getSearchFilter(request, rangerServiceResourceWithTagsService.sortFields); searchUtil.extractIntList(request, filter, SearchFilter.TAG_RESOURCE_IDS, "Tag resource list"); - - ret = tagStore.getPaginatedServiceResources(filter); + searchUtil.extractStringList(request, filter, SearchFilter.TAG_NAMES, "Tag type List", "tagTypes", null, null); + ret = tagStore.getPaginatedServiceResourcesWithTags(filter); } catch (Exception excp) { LOG.error("getServiceResources() failed", excp); diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceWithTagsService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceWithTagsService.java new file mode 100755 index 0000000000..2b3acd17a7 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceWithTagsService.java @@ -0,0 +1,119 @@ +/* + * 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 java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.ranger.biz.RangerTagDBRetriever; +import org.apache.ranger.common.SearchField; +import org.apache.ranger.common.SortField; +import org.apache.ranger.common.SearchField.DATA_TYPE; +import org.apache.ranger.common.SearchField.SEARCH_TYPE; +import org.apache.ranger.entity.XXServiceResource; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.ranger.plugin.model.RangerServiceResourceWithTags; +import org.apache.ranger.plugin.util.SearchFilter; +import org.apache.ranger.view.RangerServiceResourceWithTagsList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class RangerServiceResourceWithTagsService extends RangerServiceResourceWithTagsServiceBase { + + private static final Logger LOG = LoggerFactory.getLogger(RangerServiceResourceWithTagsService.class); + + public RangerServiceResourceWithTagsService() { + searchFields.add(new SearchField(SearchFilter.TAG_RESOURCE_ID, "obj.id", DATA_TYPE.INTEGER, SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.TAG_SERVICE_ID, "obj.serviceId", DATA_TYPE.INTEGER, SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.TAG_SERVICE_NAME, "service.name", DATA_TYPE.STRING, SEARCH_TYPE.FULL, "XXService service", "obj.serviceId = service.id")); + searchFields.add(new SearchField(SearchFilter.TAG_SERVICE_NAME_PARTIAL, "service.name", DATA_TYPE.STRING, SEARCH_TYPE.PARTIAL, "XXService service", "obj.serviceId = service.id")); + searchFields.add(new SearchField(SearchFilter.TAG_RESOURCE_GUID, "obj.guid", DATA_TYPE.STRING, SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.TAG_RESOURCE_SIGNATURE, "obj.resourceSignature", DATA_TYPE.STRING, SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.TAG_RESOURCE_IDS, "obj.id", DATA_TYPE.INT_LIST, SEARCH_TYPE.FULL)); + searchFields.add(new SearchField(SearchFilter.TAG_RESOURCE_ELEMENTS, "obj.serviceResourceElements", DATA_TYPE.STRING, SEARCH_TYPE.PARTIAL)); + searchFields.add(new SearchField(SearchFilter.TAG_NAMES, "tagDef.name", DATA_TYPE.STR_LIST, SEARCH_TYPE.FULL, "XXTagResourceMap map, XXTag tag, XXTagDef tagDef", "obj.id = map.resourceId and map.tagId = tag.id and tag.type = tagDef.id")); + + sortFields.add(new SortField(SearchFilter.TAG_RESOURCE_ID, "obj.id", true, SortField.SORT_ORDER.ASC)); + sortFields.add(new SortField(SearchFilter.TAG_SERVICE_ID, "obj.serviceId")); + sortFields.add(new SortField(SearchFilter.CREATE_TIME, "obj.createTime")); + sortFields.add(new SortField(SearchFilter.UPDATE_TIME, "obj.updateTime")); + } + + @Override + protected XXServiceResource mapViewToEntityBean(RangerServiceResourceWithTags viewBean, XXServiceResource t, int OPERATION_CONTEXT) { + return null; + } + + @Override + protected void validateForCreate(RangerServiceResourceWithTags vObj) { + } + + @Override + protected void validateForUpdate(RangerServiceResourceWithTags vObj, XXServiceResource entityObj) { + } + + public RangerServiceResourceWithTags getPopulatedViewObject(XXServiceResource xObj) { + return this.populateViewBean(xObj); + } + + public RangerServiceResourceWithTagsList searchServiceResourcesWithTags(SearchFilter filter) { + LOG.debug("==> searchServiceResourcesWithTags({})", filter); + + RangerServiceResourceWithTagsList ret = new RangerServiceResourceWithTagsList(); + List xObjList = super.searchResources(filter, searchFields, sortFields, ret); + List resourceList = new ArrayList<>(); + + if (xObjList != null) { + for (XXServiceResource resource:xObjList) { + resourceList.add(getPopulatedViewObject(resource)); + } + } + + ret.setResourceList(resourceList); + + LOG.debug("<== searchServiceResourcesWithTags({}): ret={}", filter, ret); + + return ret; + } + + @Override + protected RangerServiceResourceWithTags mapEntityToViewBean(RangerServiceResourceWithTags serviceResourceWithTags, XXServiceResource xxServiceResource) { + RangerServiceResourceWithTags ret = super.mapEntityToViewBean(serviceResourceWithTags, xxServiceResource); + + if (StringUtils.isNotEmpty(xxServiceResource.getServiceResourceElements())) { + Map serviceResourceElements = RangerTagDBRetriever.gsonBuilder.fromJson(xxServiceResource.getServiceResourceElements(), RangerServiceResourceService.subsumedDataType); + + if (MapUtils.isNotEmpty(serviceResourceElements)) { + ret.setResourceElements(serviceResourceElements); + } else { + LOG.info("Empty serviceResourceElement in [" + ret + "]!!"); + } + } else { + LOG.info("Empty string representing serviceResourceElements in [" + xxServiceResource + "]!!"); + } + + return ret; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceWithTagsServiceBase.java b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceWithTagsServiceBase.java new file mode 100755 index 0000000000..57cd20ab36 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceWithTagsServiceBase.java @@ -0,0 +1,67 @@ +/* + * 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 java.util.ArrayList; +import java.util.List; + +import org.apache.ranger.authorization.utils.JsonUtils; +import org.apache.ranger.entity.XXService; +import org.apache.ranger.entity.XXServiceResource; +import org.apache.ranger.plugin.model.RangerServiceResourceWithTags; +import org.apache.ranger.plugin.store.PList; +import org.apache.ranger.plugin.util.SearchFilter; + +public abstract class RangerServiceResourceWithTagsServiceBase extends RangerBaseModelService { + + @Override + protected V mapEntityToViewBean(V vObj, T xObj) { + XXService xService = daoMgr.getXXService().getById(xObj.getServiceId()); + + vObj.setGuid(xObj.getGuid()); + vObj.setVersion(xObj.getVersion()); + vObj.setIsEnabled(xObj.getIsEnabled()); + vObj.setServiceName(xService.getName()); + vObj.setAssociatedTags(JsonUtils.jsonToRangerTagList(xObj.getTags())); + + return vObj; + } + + public PList searchServiceResources(SearchFilter searchFilter) { + PList retList = new PList(); + List resourceList = new ArrayList(); + List xResourceList = searchRangerObjects(searchFilter, searchFields, sortFields, retList); + + for (T xResource : xResourceList) { + V taggedRes = populateViewBean(xResource); + + resourceList.add(taggedRes); + } + + retList.setList(resourceList); + retList.setResultSize(resourceList.size()); + retList.setPageSize(searchFilter.getMaxRows()); + retList.setStartIndex(searchFilter.getStartIndex()); + retList.setSortType(searchFilter.getSortType()); + retList.setSortBy(searchFilter.getSortBy()); + + return retList; + } +} diff --git a/security-admin/src/main/java/org/apache/ranger/view/RangerServiceResourceWithTagsList.java b/security-admin/src/main/java/org/apache/ranger/view/RangerServiceResourceWithTagsList.java new file mode 100644 index 0000000000..a40953eefd --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/view/RangerServiceResourceWithTagsList.java @@ -0,0 +1,62 @@ +/* + * 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 java.util.List; + +import org.apache.ranger.common.view.VList; +import org.apache.ranger.plugin.model.RangerServiceResourceWithTags; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +@JsonAutoDetect(getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, fieldVisibility = Visibility.ANY) +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +public class RangerServiceResourceWithTagsList extends VList { + private static final long serialVersionUID = 1L; + + List resourceList; + + public RangerServiceResourceWithTagsList() { + super(); + } + + public RangerServiceResourceWithTagsList(List objList) { + super(objList); + + this.resourceList = objList; + } + + public List getResourceList() { + return resourceList; + } + + public void setResourceList(List resourceList) { + this.resourceList = resourceList; + } + + @Override + public int getListSize() { + return (resourceList != null) ? resourceList.size() : 0; + } + + @Override + public List getList() { + return resourceList; + } +} diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestTagDBStore.java b/security-admin/src/test/java/org/apache/ranger/biz/TestTagDBStore.java old mode 100644 new mode 100755 index d6ebbc54d4..acc9cab3ce --- a/security-admin/src/test/java/org/apache/ranger/biz/TestTagDBStore.java +++ b/security-admin/src/test/java/org/apache/ranger/biz/TestTagDBStore.java @@ -46,6 +46,7 @@ import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef; import org.apache.ranger.plugin.model.RangerServiceResource; +import org.apache.ranger.plugin.model.RangerServiceResourceWithTags; import org.apache.ranger.plugin.model.RangerTag; import org.apache.ranger.plugin.model.RangerTagDef; import org.apache.ranger.plugin.model.RangerTagResourceMap; @@ -53,9 +54,11 @@ import org.apache.ranger.plugin.util.SearchFilter; import org.apache.ranger.plugin.util.ServiceTags; import org.apache.ranger.service.RangerServiceResourceService; +import org.apache.ranger.service.RangerServiceResourceWithTagsService; import org.apache.ranger.service.RangerTagDefService; import org.apache.ranger.service.RangerTagResourceMapService; import org.apache.ranger.service.RangerTagService; +import org.apache.ranger.view.RangerServiceResourceWithTagsList; import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Rule; @@ -87,6 +90,9 @@ public class TestTagDBStore { @Mock RangerServiceResourceService rangerServiceResourceService; + @Mock + RangerServiceResourceWithTagsService rangerServiceResourceWithTagsService; + @Mock RangerTagResourceMapService rangerTagResourceMapService; @@ -1185,4 +1191,52 @@ private XXTagResourceMap createXXTagResourceMap() { return xxTagResourceMap; } -} + + @Test + public void tesGetPaginatedServiceResourcesWithTags() throws Exception { + RangerServiceResourceWithTagsList rangerServiceResourceViewList = createRangerServiceResourceWithTagsViewList(); + SearchFilter searchFilter = new SearchFilter(); + + Mockito.when(rangerServiceResourceWithTagsService.searchServiceResourcesWithTags(searchFilter)).thenReturn(rangerServiceResourceViewList); + + RangerServiceResourceWithTagsList returnedRangerServiceResourcePList = tagDBStore.getPaginatedServiceResourcesWithTags(searchFilter); + + Assert.assertNotNull(returnedRangerServiceResourcePList); + Assert.assertEquals(returnedRangerServiceResourcePList.getList().size(), 1); + + RangerServiceResourceWithTags returnedRangerServiceResource = returnedRangerServiceResourcePList.getResourceList().get(0); + + Assert.assertEquals(returnedRangerServiceResource.getId(), id); + Assert.assertEquals(returnedRangerServiceResource.getGuid(), gId); + Assert.assertNotNull(returnedRangerServiceResource.getAssociatedTags()); + Assert.assertEquals(rangerServiceResourceViewList.getResourceList().get(0).getAssociatedTags().size(), returnedRangerServiceResource.getAssociatedTags().size()); + } + + private RangerServiceResourceWithTagsList createRangerServiceResourceWithTagsViewList() { + RangerServiceResourceWithTagsList rangerServiceResourceViewList = new RangerServiceResourceWithTagsList(); + List rangerServiceResourceList = new ArrayList<>(); + RangerServiceResourceWithTags rangerServiceResource = new RangerServiceResourceWithTags(); + List associatedTags = new ArrayList<>(); + + associatedTags.add(createRangerTag()); + + rangerServiceResource.setId(id); + rangerServiceResource.setCreateTime(new Date()); + rangerServiceResource.setGuid(gId); + rangerServiceResource.setVersion(lastKnownVersion); + rangerServiceResource.setServiceName(serviceName); + rangerServiceResource.setAssociatedTags(associatedTags); + + rangerServiceResourceList.add(rangerServiceResource); + + rangerServiceResourceViewList.setResourceList(rangerServiceResourceList); + rangerServiceResourceViewList.setPageSize(0); + rangerServiceResourceViewList.setResultSize(1); + rangerServiceResourceViewList.setSortBy("asc"); + rangerServiceResourceViewList.setSortType("1"); + rangerServiceResourceViewList.setStartIndex(0); + rangerServiceResourceViewList.setTotalCount(1); + + return rangerServiceResourceViewList; + } +} \ No newline at end of file diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestTagREST.java b/security-admin/src/test/java/org/apache/ranger/rest/TestTagREST.java old mode 100644 new mode 100755 index 98d87bc0a4..7165a304da --- a/security-admin/src/test/java/org/apache/ranger/rest/TestTagREST.java +++ b/security-admin/src/test/java/org/apache/ranger/rest/TestTagREST.java @@ -37,6 +37,7 @@ import org.apache.ranger.entity.XXServiceDef; import org.apache.ranger.plugin.model.RangerService; import org.apache.ranger.plugin.model.RangerServiceResource; +import org.apache.ranger.plugin.model.RangerServiceResourceWithTags; import org.apache.ranger.plugin.model.RangerTag; import org.apache.ranger.plugin.model.RangerTagDef; import org.apache.ranger.plugin.model.RangerTagResourceMap; @@ -46,8 +47,10 @@ import org.apache.ranger.plugin.util.SearchFilter; import org.apache.ranger.plugin.util.ServiceTags; import org.apache.ranger.service.RangerServiceResourceService; +import org.apache.ranger.service.RangerServiceResourceWithTagsService; import org.apache.ranger.service.RangerTagDefService; import org.apache.ranger.service.RangerTagService; +import org.apache.ranger.view.RangerServiceResourceWithTagsList; import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Rule; @@ -110,6 +113,9 @@ public class TestTagREST { @Mock RangerServiceResourceService resourceService; + @Mock + RangerServiceResourceWithTagsService serviceResourceWithTagsService; + @Rule public ExpectedException thrown = ExpectedException.none(); @@ -1134,34 +1140,43 @@ public void test37getAllServiceResources() { } @Test - public void test64getServiceResources() { - HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - SearchFilter searchFilter = new SearchFilter(); - PList ret = new PList(); - List serviceResourceList = new ArrayList(); - RangerServiceResource rangerServiceResource = new RangerServiceResource(); + public void test64getServiceResourcesWithTags() { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + SearchFilter searchFilter = new SearchFilter(); + RangerServiceResourceWithTagsList ret = new RangerServiceResourceWithTagsList(); + List serviceResourceList = new ArrayList(); + RangerServiceResourceWithTags rangerServiceResource = new RangerServiceResourceWithTags(); + List associatedTags = new ArrayList(); + RangerTag rangerTag = new RangerTag(); + + rangerTag.setId(id); + rangerTag.setGuid(gId); + rangerTag.setType(name); + associatedTags.add(rangerTag); rangerServiceResource.setId(id); rangerServiceResource.setServiceName(serviceName); + rangerServiceResource.setAssociatedTags(associatedTags); serviceResourceList.add(rangerServiceResource); - ret.setList(serviceResourceList); + ret.setResourceList(serviceResourceList); - Mockito.when(searchUtil.getSearchFilter(Mockito.any(HttpServletRequest.class), eq(resourceService.sortFields))) - .thenReturn(searchFilter); + Mockito.when(searchUtil.getSearchFilter(Mockito.any(HttpServletRequest.class), eq(resourceService.sortFields))).thenReturn(searchFilter); try { - Mockito.when(tagStore.getPaginatedServiceResources((SearchFilter) Mockito.any())).thenReturn(ret); + Mockito.when(tagStore.getPaginatedServiceResourcesWithTags(Mockito.any())).thenReturn(ret); } catch (Exception e) { } - PList result = tagREST.getServiceResources(request); + RangerServiceResourceWithTagsList result = tagREST.getServiceResourcesWithTags(request); - Assert.assertNotNull(result.getList().get(0).getId()); - Assert.assertEquals(result.getList().get(0).getId(), serviceResourceList.get(0).getId()); - Assert.assertEquals(result.getList().get(0).getServiceName(), serviceResourceList.get(0).getServiceName()); + Assert.assertNotNull(result.getResourceList().get(0).getId()); + Assert.assertEquals(result.getResourceList().get(0).getId(), serviceResourceList.get(0).getId()); + Assert.assertEquals(result.getResourceList().get(0).getServiceName(), serviceResourceList.get(0).getServiceName()); + Assert.assertEquals(result.getResourceList().get(0).getAssociatedTags().size(), 1); + Assert.assertEquals(result.getResourceList().get(0).getAssociatedTags().get(0).getType(), name); try { - Mockito.verify(tagStore).getPaginatedServiceResources((SearchFilter) Mockito.any()); + Mockito.verify(tagStore).getPaginatedServiceResourcesWithTags((SearchFilter) Mockito.any()); } catch (Exception e) { } } @@ -1170,6 +1185,7 @@ public void test64getServiceResources() { public void test38createTagResourceMap() { RangerTagResourceMap oldTagResourceMap = null; RangerTagResourceMap newTagResourceMap = new RangerTagResourceMap(); + newTagResourceMap.setTagId(id); newTagResourceMap.setResourceId(id); @@ -1187,6 +1203,7 @@ public void test38createTagResourceMap() { } RangerTagResourceMap rangerTagResourceMap = tagREST.createTagResourceMap(tagGuid, resourceGuid, false); + Assert.assertEquals(rangerTagResourceMap.getTagId(), newTagResourceMap.getTagId()); Assert.assertEquals(rangerTagResourceMap.getResourceId(), newTagResourceMap.getResourceId()); @@ -1194,10 +1211,12 @@ public void test38createTagResourceMap() { Mockito.verify(tagStore).getTagResourceMapForTagAndResourceGuid(tagGuid, resourceGuid); } catch (Exception e) { } + try { Mockito.verify(validator).preCreateTagResourceMap(tagGuid, resourceGuid); } catch (Exception e) { } + try { Mockito.verify(tagStore).createTagResourceMap(newTagResourceMap); } catch (Exception e) { @@ -1212,7 +1231,9 @@ public void test39createTagResourceMap() { Mockito.when(tagStore.getTagResourceMapForTagAndResourceGuid(tagGuid, resourceGuid)).thenReturn(oldTagResourceMap); } catch (Exception e) { } + Mockito.when(restErrorUtil.createRESTException(Mockito.anyInt(),Mockito.anyString(), Mockito.anyBoolean())).thenThrow(new WebApplicationException()); + thrown.expect(WebApplicationException.class); tagREST.createTagResourceMap(tagGuid, resourceGuid, false);