diff options
author | andre.schmid <andre.schmid@est.tech> | 2019-09-27 13:27:11 +0100 |
---|---|---|
committer | Ofir Sonsino <ofir.sonsino@intl.att.com> | 2019-10-30 09:47:54 +0000 |
commit | bf5eeb23a769a2e2b75f432b74f10fdbcfd2f161 (patch) | |
tree | fa27998ee6efef6f7651315cbf71271130fca025 | |
parent | 19773b769c6762a12876064c70a34cc31d2b12da (diff) |
Fix zip slip security flaw
Apply zip slip checking in zip operations throughout the system.
Centralizes most of the zip logic in one class. Create tests to zip
functionalities and zip slip problem.
Change-Id: I721f3d44b34fe6d242c9537f5a515ce1bb534c9a
Issue-ID: SDC-1401
Signed-off-by: andre.schmid <andre.schmid@est.tech>
44 files changed, 1918 insertions, 2173 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java index e00889646a..514576fcd8 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java @@ -42,12 +42,12 @@ import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Response; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.collections4.MapUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; import org.openecomp.sdc.be.components.impl.CsarValidationUtils; -import org.openecomp.sdc.be.components.impl.GroupBusinessLogic; import org.openecomp.sdc.be.components.impl.ImportUtils; import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum; @@ -75,7 +75,8 @@ import org.openecomp.sdc.common.datastructure.Wrapper; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.common.util.GeneralUtility; import org.openecomp.sdc.common.util.YamlToObjectConverter; -import org.openecomp.sdc.common.util.ZipUtil; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.exception.ResponseFormat; import org.yaml.snakeyaml.Yaml; @@ -168,37 +169,76 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { } - protected void validateZip(Wrapper<Response> responseWrapper, File file, String payloadName) { - Map<String, byte[]> unzippedFolder = ZipUtil.readZip(file); - if (payloadName == null || payloadName.isEmpty() || !unzippedFolder.containsKey(payloadName)) { - log.info("Invalid json was received. payloadName should be yml file name"); - Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); + protected void validateZip(final Wrapper<Response> responseWrapper, final File zipFile, final String payloadName) { + if (StringUtils.isEmpty(payloadName)) { + log.info("Invalid JSON was received. Payload name is empty"); + final Response errorResponse = + buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); responseWrapper.setInnerElement(errorResponse); + return; } + final Map<String, byte[]> unzippedFolder; + try { + unzippedFolder = ZipUtils.readZip(zipFile, false); + } catch (final ZipException e) { + log.error("Could not read ZIP file '{}' for validation", zipFile.getName(), e); + final Response errorResponse = + buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); + responseWrapper.setInnerElement(errorResponse); + return; + } + if (!unzippedFolder.containsKey(payloadName)) { + log.info("Could no find payload '{}' in ZIP file '{}'", payloadName, zipFile.getName()); + final Response errorResponse = + buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); + responseWrapper.setInnerElement(errorResponse); + } + } - protected void validateCsar(Wrapper<Response> responseWrapper, File file, String payloadName) { - Map<String, byte[]> unzippedFolder = ZipUtil.readZip(file); - if (payloadName == null || payloadName.isEmpty() || unzippedFolder.isEmpty()) { - log.info("Invalid json was received. payloadName should be yml file name"); + + protected void validateCsar(final Wrapper<Response> responseWrapper, final File csarFile, final String payloadName) { + if (StringUtils.isEmpty(payloadName)) { + log.info("Invalid JSON was received. Payload name is empty"); + Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); + responseWrapper.setInnerElement(errorResponse); + return; + } + final Map<String, byte[]> unzippedFolder; + try { + unzippedFolder = ZipUtils.readZip(csarFile, false); + } catch (final ZipException e) { + log.error("Could not read CSAR file '{}' for validation", csarFile.getName(), e); + final Response errorResponse = + buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); + responseWrapper.setInnerElement(errorResponse); + return; + } + if (unzippedFolder.isEmpty()) { + log.info("The CSAR file is empty"); Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); responseWrapper.setInnerElement(errorResponse); } } - protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) { + protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException { extractZipContents(yamlStringWrapper, file); } - public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) { - Map<String, byte[]> unzippedFolder = ZipUtil.readZip(file); + public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException { + final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false); String ymlName = unzippedFolder.keySet().iterator().next(); fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file); } private static void fillToscaTemplateFromZip(Wrapper<String> yamlStringWrapper, String payloadName, File file) { - Map<String, byte[]> unzippedFolder = ZipUtil.readZip(file); + Map<String, byte[]> unzippedFolder = null; + try { + unzippedFolder = ZipUtils.readZip(file, false); + } catch (final ZipException e) { + log.info("Failed to unzip file", e); + } byte[] yamlFileInBytes = unzippedFolder.get(payloadName); String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8); log.debug("received yaml: {}", yamlAsString); @@ -738,19 +778,23 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { String csarUUID = innerElement.getPayloadName(); String payloadData = innerElement.getPayloadData(); if (payloadData == null) { - log.info("Failed to decode received csar", csarUUID); + log.info("Failed to decode received csar {}", csarUUID); return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_NOT_FOUND, csarUUID)); } byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8)); if (decodedPayload == null) { - log.info("Failed to decode received csar", csarUUID); + log.info("Failed to decode received csar {}", csarUUID); return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_NOT_FOUND, csarUUID)); } - Map<String, byte[]> csar = ZipUtil.readZip(decodedPayload); - if (csar == null) { - log.info("Failed to unzip received csar", csarUUID); + Map<String, byte[]> csar = null; + try { + csar = ZipUtils.readZip(decodedPayload, false); + } catch (final ZipException e) { + log.info("Failed to unzip received csar {}", csarUUID, e); + } + if (MapUtils.isEmpty(csar)) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID, csarUUID)); } return Either.left(csar); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java index 3d7471ebc3..bfd7ce720a 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java @@ -1,187 +1,186 @@ -/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed 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.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.be.servlets;
-
-import java.io.File;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
-import org.glassfish.jersey.media.multipart.FormDataParam;
-import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
-import org.openecomp.sdc.be.components.impl.ResourceImportManager;
-import org.openecomp.sdc.be.config.BeEcompErrorManager;
-import org.openecomp.sdc.be.dao.api.ActionStatus;
-import org.openecomp.sdc.be.impl.ComponentsUtils;
-import org.openecomp.sdc.be.impl.ServletUtils;
-import org.openecomp.sdc.be.model.UploadResourceInfo;
-import org.openecomp.sdc.be.model.User;
-import org.openecomp.sdc.be.user.UserBusinessLogic;
-import org.openecomp.sdc.common.api.Constants;
-import org.openecomp.sdc.common.datastructure.Wrapper;
-import org.openecomp.sdc.common.log.wrappers.Logger;
-import com.jcabi.aspects.Loggable;
-import io.swagger.v3.oas.annotations.OpenAPIDefinition;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.info.Info;
-import io.swagger.v3.oas.annotations.media.ArraySchema;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.responses.ApiResponses;
-/**
- * Root resource (exposed at "/" path)
- */
-@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
-@Path("/v1/catalog/upload")
-@OpenAPIDefinition(info = @Info(title = "Resources Catalog Upload", description = "Upload resource yaml"))
-@Singleton
-public class ResourceUploadServlet extends AbstractValidationsServlet {
-
- private static final Logger log = Logger.getLogger(ResourceUploadServlet.class);
- public static final String NORMATIVE_TYPE_RESOURCE = "multipart";
- public static final String CSAR_TYPE_RESOURCE = "csar";
- public static final String USER_TYPE_RESOURCE = "user-resource";
- public static final String USER_TYPE_RESOURCE_UI_IMPORT = "user-resource-ui-import";
-
- @Inject
- public ResourceUploadServlet(UserBusinessLogic userBusinessLogic,
- ComponentInstanceBusinessLogic componentInstanceBL,
- ComponentsUtils componentsUtils, ServletUtils servletUtils,
- ResourceImportManager resourceImportManager) {
- super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
- }
-
- public enum ResourceAuthorityTypeEnum {
- NORMATIVE_TYPE_BE(NORMATIVE_TYPE_RESOURCE, true, false), USER_TYPE_BE(USER_TYPE_RESOURCE, true,
- true), USER_TYPE_UI(USER_TYPE_RESOURCE_UI_IMPORT, false,
- true), CSAR_TYPE_BE(CSAR_TYPE_RESOURCE, true, true);
-
- private String urlPath;
- private boolean isBackEndImport, isUserTypeResource;
-
- public static ResourceAuthorityTypeEnum findByUrlPath(String urlPath) {
- ResourceAuthorityTypeEnum found = null;
- for (ResourceAuthorityTypeEnum curr : ResourceAuthorityTypeEnum.values()) {
- if (curr.getUrlPath().equals(urlPath)) {
- found = curr;
- break;
- }
- }
- return found;
- }
-
- private ResourceAuthorityTypeEnum(String urlPath, boolean isBackEndImport, boolean isUserTypeResource) {
- this.urlPath = urlPath;
- this.isBackEndImport = isBackEndImport;
- this.isUserTypeResource = isUserTypeResource;
- }
-
- public String getUrlPath() {
- return urlPath;
- }
-
- public boolean isBackEndImport() {
- return isBackEndImport;
- }
-
- public boolean isUserTypeResource() {
- return isUserTypeResource;
- }
- }
-
- @POST
- @Path("/{resourceAuthority}")
- @Consumes(MediaType.MULTIPART_FORM_DATA)
- @Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "Create Resource from yaml", method = "POST", summary = "Returns created resource",
- responses = @ApiResponse(
- content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
- @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Resource already exist")})
- public Response uploadMultipart(
- @Parameter(description = "validValues: normative-resource / user-resource",
- schema = @Schema(allowableValues = {NORMATIVE_TYPE_RESOURCE ,
- USER_TYPE_RESOURCE,USER_TYPE_RESOURCE_UI_IMPORT})) @PathParam(
- value = "resourceAuthority") final String resourceAuthority,
- @Parameter(description = "FileInputStream") @FormDataParam("resourceZip") File file,
- @Parameter(description = "ContentDisposition") @FormDataParam("resourceZip") FormDataContentDisposition contentDispositionHeader,
- @Parameter(description = "resourceMetadata") @FormDataParam("resourceMetadata") String resourceInfoJsonString,
- @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
- // updateResourse Query Parameter if false checks if already exist
- @DefaultValue("true") @QueryParam("createNewVersion") boolean createNewVersion) {
-
- try {
-
- Wrapper<Response> responseWrapper = new Wrapper<>();
- Wrapper<User> userWrapper = new Wrapper<>();
- Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();
- Wrapper<String> yamlStringWrapper = new Wrapper<>();
-
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("Start handle request of {}", url);
-
- // When we get an errorResponse it will be filled into the
- // responseWrapper
- validateAuthorityType(responseWrapper, resourceAuthority);
-
- ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.findByUrlPath(resourceAuthority);
-
- commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, resourceInfoJsonString);
-
- fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), resourceInfoJsonString, resourceAuthorityEnum, file);
-
- // PayLoad Validations
- if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){
- commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement());
-
- specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, resourceInfoJsonString, resourceAuthorityEnum);
- }
-
- if (responseWrapper.isEmpty()) {
- handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, createNewVersion, null);
- }
-
- return responseWrapper.getInnerElement();
-
- } catch (Exception e) {
- BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Upload Resource");
- log.debug("upload resource failed with exception", e);
- return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
- }
- }
-
- /********************************************************************************************************************/
-}
+/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.servlets; + +import java.io.File; +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.FormDataParam; +import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ResourceImportManager; +import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.model.UploadResourceInfo; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.user.UserBusinessLogic; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.datastructure.Wrapper; +import org.openecomp.sdc.common.log.wrappers.Logger; +import com.jcabi.aspects.Loggable; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +/** + * Root resource (exposed at "/" path) + */ +@Loggable(prepend = true, value = Loggable.DEBUG, trim = false) +@Path("/v1/catalog/upload") +@OpenAPIDefinition(info = @Info(title = "Resources Catalog Upload", description = "Upload resource yaml")) +@Singleton +public class ResourceUploadServlet extends AbstractValidationsServlet { + + private static final Logger log = Logger.getLogger(ResourceUploadServlet.class); + public static final String NORMATIVE_TYPE_RESOURCE = "multipart"; + public static final String CSAR_TYPE_RESOURCE = "csar"; + public static final String USER_TYPE_RESOURCE = "user-resource"; + public static final String USER_TYPE_RESOURCE_UI_IMPORT = "user-resource-ui-import"; + + @Inject + public ResourceUploadServlet(UserBusinessLogic userBusinessLogic, + ComponentInstanceBusinessLogic componentInstanceBL, + ComponentsUtils componentsUtils, ServletUtils servletUtils, + ResourceImportManager resourceImportManager) { + super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager); + } + + public enum ResourceAuthorityTypeEnum { + NORMATIVE_TYPE_BE(NORMATIVE_TYPE_RESOURCE, true, false), USER_TYPE_BE(USER_TYPE_RESOURCE, true, + true), USER_TYPE_UI(USER_TYPE_RESOURCE_UI_IMPORT, false, + true), CSAR_TYPE_BE(CSAR_TYPE_RESOURCE, true, true); + + private String urlPath; + private boolean isBackEndImport, isUserTypeResource; + + public static ResourceAuthorityTypeEnum findByUrlPath(String urlPath) { + ResourceAuthorityTypeEnum found = null; + for (ResourceAuthorityTypeEnum curr : ResourceAuthorityTypeEnum.values()) { + if (curr.getUrlPath().equals(urlPath)) { + found = curr; + break; + } + } + return found; + } + + private ResourceAuthorityTypeEnum(String urlPath, boolean isBackEndImport, boolean isUserTypeResource) { + this.urlPath = urlPath; + this.isBackEndImport = isBackEndImport; + this.isUserTypeResource = isUserTypeResource; + } + + public String getUrlPath() { + return urlPath; + } + + public boolean isBackEndImport() { + return isBackEndImport; + } + + public boolean isUserTypeResource() { + return isUserTypeResource; + } + } + + @POST + @Path("/{resourceAuthority}") + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Create Resource from yaml", method = "POST", summary = "Returns created resource", + responses = @ApiResponse( + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class))))) + @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource created"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "409", description = "Resource already exist")}) + public Response uploadMultipart( + @Parameter(description = "validValues: normative-resource / user-resource", + schema = @Schema(allowableValues = {NORMATIVE_TYPE_RESOURCE , + USER_TYPE_RESOURCE,USER_TYPE_RESOURCE_UI_IMPORT})) @PathParam( + value = "resourceAuthority") final String resourceAuthority, + @Parameter(description = "FileInputStream") @FormDataParam("resourceZip") File file, + @Parameter(description = "ContentDisposition") @FormDataParam("resourceZip") FormDataContentDisposition contentDispositionHeader, + @Parameter(description = "resourceMetadata") @FormDataParam("resourceMetadata") String resourceInfoJsonString, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId, + // updateResourse Query Parameter if false checks if already exist + @DefaultValue("true") @QueryParam("createNewVersion") boolean createNewVersion) { + + try { + + Wrapper<Response> responseWrapper = new Wrapper<>(); + Wrapper<User> userWrapper = new Wrapper<>(); + Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>(); + Wrapper<String> yamlStringWrapper = new Wrapper<>(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}", url); + + // When we get an errorResponse it will be filled into the + // responseWrapper + validateAuthorityType(responseWrapper, resourceAuthority); + + ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.findByUrlPath(resourceAuthority); + + commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, resourceInfoJsonString); + + fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), resourceInfoJsonString, resourceAuthorityEnum, file); + + // PayLoad Validations + if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){ + commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement()); + + specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, resourceInfoJsonString, resourceAuthorityEnum); + } + + if (responseWrapper.isEmpty()) { + handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, createNewVersion, null); + } + + return responseWrapper.getInnerElement(); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Upload Resource"); + log.debug("upload resource failed with exception", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java index 415fdcf562..03bed4762f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java @@ -1,574 +1,572 @@ -/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed 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.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.be.servlets;
-
-import com.jcabi.aspects.Loggable;
-import fj.data.Either;
-import javax.inject.Inject;
-import org.apache.http.HttpStatus;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
-import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
-import org.openecomp.sdc.be.components.impl.GroupBusinessLogic;
-import org.openecomp.sdc.be.components.impl.ImportUtils;
-import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
-import org.openecomp.sdc.be.components.impl.ResourceImportManager;
-import org.openecomp.sdc.be.config.BeEcompErrorManager;
-import org.openecomp.sdc.be.dao.api.ActionStatus;
-import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum;
-import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
-import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
-import org.openecomp.sdc.be.impl.ComponentsUtils;
-import org.openecomp.sdc.be.impl.ServletUtils;
-import org.openecomp.sdc.be.model.Product;
-import org.openecomp.sdc.be.model.Resource;
-import org.openecomp.sdc.be.model.UploadResourceInfo;
-import org.openecomp.sdc.be.model.User;
-import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
-import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
-import org.openecomp.sdc.be.user.UserBusinessLogic;
-import org.openecomp.sdc.common.api.Constants;
-import org.openecomp.sdc.common.datastructure.Wrapper;
-import org.openecomp.sdc.common.log.wrappers.Logger;
-import org.openecomp.sdc.exception.ResponseFormat;
-import io.swagger.v3.oas.annotations.OpenAPIDefinition;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.info.Info;
-import io.swagger.v3.oas.annotations.media.ArraySchema;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.responses.ApiResponses;
-import javax.inject.Singleton;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.*;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
-@Path("/v1/catalog")
-@OpenAPIDefinition(info = @Info(title = "Resources Catalog", description = "Resources Servlet"))
-@Singleton
-public class ResourcesServlet extends AbstractValidationsServlet {
-
- private static final Logger log = Logger.getLogger(ResourcesServlet.class);
- private final ResourceBusinessLogic resourceBusinessLogic;
-
- @Inject
- public ResourcesServlet(UserBusinessLogic userBusinessLogic,
- ComponentInstanceBusinessLogic componentInstanceBL,
- ResourceBusinessLogic resourceBusinessLogic,
- ComponentsUtils componentsUtils, ServletUtils servletUtils,
- ResourceImportManager resourceImportManager) {
- super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
- this.resourceBusinessLogic = resourceBusinessLogic;
- }
-
- @POST
- @Path("/resources")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "Create Resource", method = "POST", summary = "Returns created resource",
- responses = @ApiResponse(
- content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
- @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Resource already exist")})
- public Response createResource(@Parameter(description = "Resource object to be created", required = true) String data,
- @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
-
- userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
- init();
-
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("Start handle request of {}" , url);
-
- // get modifier id
- User modifier = new User();
- modifier.setUserId(userId);
- log.debug("modifier id is {}", userId);
-
- Response response;
- try {
-
- Wrapper<Response> responseWrapper = new Wrapper<>();
- // UI Import
- if (isUIImport(data)) {
- performUIImport(responseWrapper, data, request, userId, null);
- }
- // UI Create
- else {
-
- Either<Resource, ResponseFormat> convertResponse = parseToResource(data, modifier);
- if (convertResponse.isRight()) {
- log.debug("failed to parse resource");
- response = buildErrorResponse(convertResponse.right().value());
- return response;
- }
-
- Resource resource = convertResponse.left().value();
- Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);
- Object representation = RepresentationUtils.toRepresentation(createdResource);
- response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
- responseWrapper.setInnerElement(response);
- }
- return responseWrapper.getInnerElement();
- } catch (IOException e) {
- BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Resource");
- log.debug("create resource failed with exception", e);
- response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
- return response;
- }
- }
-
- private boolean isUIImport(String data) {
- boolean isUIImport;
- try {
- JSONObject json = new JSONObject(data);
- String payloadName = json.getString(ImportUtils.Constants.UI_JSON_PAYLOAD_NAME);
- isUIImport = payloadName != null && !payloadName.isEmpty();
- } catch (JSONException e) {
- log.debug("failed to parse json sent from client, json:{}", data, e);
- isUIImport = false;
- }
- return isUIImport;
- }
-
- private void performUIImport(Wrapper<Response> responseWrapper, String data, final HttpServletRequest request, String userId, String resourceUniqueId) throws FileNotFoundException {
-
- Wrapper<User> userWrapper = new Wrapper<>();
- Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();
- Wrapper<String> yamlStringWrapper = new Wrapper<>();
-
- ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.USER_TYPE_UI;
-
- commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, data);
-
- if (!CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
- fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), data, resourceAuthorityEnum, null);
-
- // PayLoad Validations
- commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement());
- }
- specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, data, resourceAuthorityEnum);
-
- if (responseWrapper.isEmpty()) {
- handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, true, resourceUniqueId);
- }
- }
-
- private Either<Resource, ResponseFormat> parseToResource(String resourceJson, User user) {
- return getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.RESOURCE);
- }
-
- private Either<Resource, ResponseFormat> parseToLightResource(String resourceJson, User user) {
- Either<Resource, ResponseFormat> ret = getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE);
- if (ret.isLeft()) {// drop unwanted data (sent from UI in update flow)
- ret.left().value().setRequirements(null);
- ret.left().value().setCapabilities(null);
- }
- return ret;
- }
-
- @DELETE
- @Path("/resources/{resourceId}")
- public Response deleteResource(@PathParam("resourceId") final String resourceId, @Context final HttpServletRequest request) {
-
- ServletContext context = request.getSession().getServletContext();
-
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("Start handle request of {}" , url);
-
- // get modifier id
- String userId = request.getHeader(Constants.USER_ID_HEADER);
- User modifier = new User();
- modifier.setUserId(userId);
- log.debug("modifier id is {}" , userId);
-
- Response response;
-
- try {
- String resourceIdLower = resourceId.toLowerCase();
- ResponseFormat actionResponse = resourceBusinessLogic.deleteResource(resourceIdLower, modifier);
-
- if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
- log.debug("failed to delete resource");
- response = buildErrorResponse(actionResponse);
- return response;
- }
- response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
- return response;
-
- } catch (JSONException e) {
- BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Resource");
- log.debug("delete resource failed with exception", e);
- response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
- return response;
-
- }
- }
-
- @DELETE
- @Path("/resources/{resourceName}/{version}")
- public Response deleteResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, @PathParam("version") final String version, @Context final HttpServletRequest request) {
-
- ServletContext context = request.getSession().getServletContext();
-
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("Start handle request of {}" , url);
-
- // get modifier id
- String userId = request.getHeader(Constants.USER_ID_HEADER);
- User modifier = new User();
- modifier.setUserId(userId);
- log.debug("modifier id is {}" , userId);
-
- Response response;
- ResponseFormat actionResponse = resourceBusinessLogic.deleteResourceByNameAndVersion(resourceName, version, modifier);
-
- if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
- log.debug("failed to delete resource");
- response = buildErrorResponse(actionResponse);
- return response;
- }
- response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
- return response;
- }
-
- @GET
- @Path("/resources/{resourceId}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "Retrieve Resource", method = "GET", summary = "Returns resource according to resourceId",
- responses = @ApiResponse(
- content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
- @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "404", description = "Resource not found")})
- public Response getResourceById(@PathParam("resourceId") final String resourceId,
- @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
-
- ServletContext context = request.getSession().getServletContext();
-
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("Start handle request of {}" , url);
-
- // get modifier id
- User modifier = new User();
- modifier.setUserId(userId);
- log.debug("modifier id is {}" , userId);
-
- Response response;
-
- try {
- String resourceIdLower = resourceId.toLowerCase();
- log.trace("get resource with id {}", resourceId);
- Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResource(resourceIdLower, modifier);
-
- if (actionResponse.isRight()) {
- log.debug("failed to get resource");
- response = buildErrorResponse(actionResponse.right().value());
- return response;
- }
- Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
- return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
-
- } catch (IOException e) {
- BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource");
- log.debug("get resource failed with exception", e);
- return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
-
- }
- }
-
- @GET
- @Path("/resources/resourceName/{resourceName}/resourceVersion/{resourceVersion}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "Retrieve Resource by name and version", method = "GET",
- summary = "Returns resource according to resourceId", responses = @ApiResponse(
- content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
- @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "404", description = "Resource not found")})
- public Response getResourceByNameAndVersion(@PathParam("resourceName") final String resourceName,
- @PathParam("resourceVersion") final String resourceVersion, @Context final HttpServletRequest request,
- @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
-
- ServletContext context = request.getSession().getServletContext();
- // get modifier id
- User modifier = new User();
- modifier.setUserId(userId);
- log.debug("modifier id is {}" , userId);
- Response response;
- try {
- Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResourceByNameAndVersion(resourceName, resourceVersion, userId);
- if (actionResponse.isRight()) {
- response = buildErrorResponse(actionResponse.right().value());
- return response;
- }
- Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
- return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
-
- } catch (IOException e) {
- BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource by name and version");
- log.debug("get resource failed with exception", e);
- return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
-
- }
- }
-
- @GET
- @Path("/resources/validate-name/{resourceName}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "validate resource name", method = "GET",
- summary = "checks if the chosen resource name is available ", responses = @ApiResponse(
- content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
- @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"),
- @ApiResponse(responseCode = "403", description = "Restricted operation")})
- public Response validateResourceName(@PathParam("resourceName") final String resourceName,
- @QueryParam("subtype") String resourceType, @Context final HttpServletRequest request,
- @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
- ServletContext context = request.getSession().getServletContext();
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("Start handle request of {}" , url);
-
- // get modifier id
- User modifier = new User();
- modifier.setUserId(userId);
- log.debug("modifier id is {}" , userId);
- Response response;
-
- if (resourceType != null && !ResourceTypeEnum.containsName(resourceType)) {
- log.debug("invalid resource type received");
- response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
- return response;
-
- }
- ResourceTypeEnum typeEnum = null;
- if (resourceType != null) {
- typeEnum = ResourceTypeEnum.valueOf(resourceType);
- }
- Either<Map<String, Boolean>, ResponseFormat> actionResponse = resourceBusinessLogic.validateResourceNameExists(resourceName, typeEnum, userId);
-
- if (actionResponse.isRight()) {
- log.debug("failed to validate resource name");
- response = buildErrorResponse(actionResponse.right().value());
- return response;
- }
- return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
- }
-
- @GET
- @Path("/resources/certified/abstract")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- public Response getCertifiedAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("(get) Start handle request of {}" , url);
- try {
- List<Resource> resources = resourceBusinessLogic
- .getAllCertifiedResources(true, HighestFilterEnum.HIGHEST_ONLY, userId);
- return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resources));
-
- } catch (IOException e) {
- BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Abstract Resources");
- log.debug("getCertifiedAbstractResources failed with exception", e);
- return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
- }
- }
-
- @GET
- @Path("/resources/certified/notabstract")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- public Response getCertifiedNotAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("(get) Start handle request of {}" , url);
- try {
- List<Resource> resouces = resourceBusinessLogic.getAllCertifiedResources(false, HighestFilterEnum.ALL, userId);
- return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resouces));
-
- } catch (IOException e) {
- BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Non Abstract Resources");
- log.debug("getCertifiedNotAbstractResources failed with exception", e);
- return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
- }
-
- }
-
- @PUT
- @Path("/resources/{resourceId}/metadata")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "Update Resource Metadata", method = "PUT", summary = "Returns updated resource metadata",
- responses = @ApiResponse(
- content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
- @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource metadata updated"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content")})
- public Response updateResourceMetadata(@PathParam("resourceId") final String resourceId,
- @Parameter(description = "Resource metadata to be updated", required = true) String data,
- @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
-
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("Start handle request of {}" , url);
-
- // get modifier id
- User modifier = new User();
- modifier.setUserId(userId);
- log.debug("modifier id is {}", userId);
- Response response;
- try {
- String resourceIdLower = resourceId.toLowerCase();
- Either<Resource, ResponseFormat> updateInfoResource = getComponentsUtils().convertJsonToObjectUsingObjectMapper(data, modifier, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE);
- if (updateInfoResource.isRight()) {
- log.debug("failed to parse resource metadata");
- response = buildErrorResponse(updateInfoResource.right().value());
- return response;
- }
- Resource updatedResource = resourceBusinessLogic.updateResourceMetadata(resourceIdLower, updateInfoResource.left().value(), null, modifier, false);
- Object resource = RepresentationUtils.toRepresentation(updatedResource);
- return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
- } catch (IOException e) {
- BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource Metadata");
- log.debug("Update Resource Metadata failed with exception", e);
- response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
- return response;
-
- }
- }
-
- @PUT
- @Path("/resources/{resourceId}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "Update Resource", method = "PUT", summary = "Returns updated resource",
- responses = @ApiResponse(
- content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
- @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource updated"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Resource already exist")})
- public Response updateResource(
- @Parameter(description = "Resource object to be updated", required = true) String data,
- @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
- @PathParam(value = "resourceId") String resourceId) {
-
- userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
- init();
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("Start handle request of {}", url);
- // get modifier id
- User modifier = new User();
- modifier.setUserId(userId);
- log.debug("modifier id is {}", userId);
- Response response;
- try {
- Wrapper<Response> responseWrapper = new Wrapper<>();
- // UI Import
- if (isUIImport(data)) {
- performUIImport(responseWrapper, data, request, userId, resourceId);
- } else {
- Either<Resource, ResponseFormat> convertResponse = parseToLightResource(data, modifier);
- if (convertResponse.isRight()) {
- log.debug("failed to parse resource");
- response = buildErrorResponse(convertResponse.right().value());
- return response;
- }
- Resource updatedResource = resourceBusinessLogic.validateAndUpdateResourceFromCsar(
- convertResponse.left().value(), modifier, null, null, resourceId);
- Object representation = RepresentationUtils.toRepresentation(updatedResource);
- response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
- responseWrapper.setInnerElement(response);
- }
- return responseWrapper.getInnerElement();
- } catch (IOException e) {
- BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource");
- log.debug("update resource failed with exception", e);
- response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
- return response;
-
- }
- }
-
- @GET
- @Path("/resources/csar/{csaruuid}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "Create Resource", method = "POST", summary = "Returns resource created from csar uuid",
- responses = @ApiResponse(
- content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
- @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource retrieced"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
- public Response getResourceFromCsar(@Context final HttpServletRequest request,
- @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
- @PathParam(value = "csaruuid") String csarUUID) {
-
- init();
-
- String url = request.getMethod() + " " + request.getRequestURI();
- log.debug("Start handle request of {}", url);
-
- // retrieve user details
- userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
- User user = new User();
- user.setUserId(userId);
-
- log.debug("user id is {}", userId);
-
- Response response;
-
- try {
-
- Either<Resource, ResponseFormat> eitherResource =
- resourceBusinessLogic.getLatestResourceFromCsarUuid(csarUUID, user);
-
- // validate response
- if (eitherResource.isRight()) {
- log.debug("failed to get resource from csarUuid : {}", csarUUID);
- response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
- eitherResource.right().value());
- } else {
- Object representation = RepresentationUtils.toRepresentation(eitherResource.left().value());
- response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
- }
-
- return response;
-
- } catch (IOException e) {
- log.debug("get resource by csar failed with exception", e);
- response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
- return response;
- }
- }
-}
+/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.servlets; + +import com.jcabi.aspects.Loggable; +import fj.data.Either; +import javax.inject.Inject; +import org.apache.http.HttpStatus; +import org.json.JSONException; +import org.json.JSONObject; +import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.impl.CsarValidationUtils; +import org.openecomp.sdc.be.components.impl.ImportUtils; +import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ResourceImportManager; +import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.UploadResourceInfo; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum; +import org.openecomp.sdc.be.user.UserBusinessLogic; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.datastructure.Wrapper; +import org.openecomp.sdc.common.log.wrappers.Logger; +import org.openecomp.sdc.exception.ResponseFormat; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import javax.inject.Singleton; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +@Loggable(prepend = true, value = Loggable.DEBUG, trim = false) +@Path("/v1/catalog") +@OpenAPIDefinition(info = @Info(title = "Resources Catalog", description = "Resources Servlet")) +@Singleton +public class ResourcesServlet extends AbstractValidationsServlet { + + private static final Logger log = Logger.getLogger(ResourcesServlet.class); + private final ResourceBusinessLogic resourceBusinessLogic; + + @Inject + public ResourcesServlet(UserBusinessLogic userBusinessLogic, + ComponentInstanceBusinessLogic componentInstanceBL, + ResourceBusinessLogic resourceBusinessLogic, + ComponentsUtils componentsUtils, ServletUtils servletUtils, + ResourceImportManager resourceImportManager) { + super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager); + this.resourceBusinessLogic = resourceBusinessLogic; + } + + @POST + @Path("/resources") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Create Resource", method = "POST", summary = "Returns created resource", + responses = @ApiResponse( + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class))))) + @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource created"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "409", description = "Resource already exist")}) + public Response createResource(@Parameter(description = "Resource object to be created", required = true) String data, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER); + init(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}" , url); + + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}", userId); + + Response response; + try { + + Wrapper<Response> responseWrapper = new Wrapper<>(); + // UI Import + if (isUIImport(data)) { + performUIImport(responseWrapper, data, request, userId, null); + } + // UI Create + else { + + Either<Resource, ResponseFormat> convertResponse = parseToResource(data, modifier); + if (convertResponse.isRight()) { + log.debug("failed to parse resource"); + response = buildErrorResponse(convertResponse.right().value()); + return response; + } + + Resource resource = convertResponse.left().value(); + Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null); + Object representation = RepresentationUtils.toRepresentation(createdResource); + response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation); + responseWrapper.setInnerElement(response); + } + return responseWrapper.getInnerElement(); + } catch (IOException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Resource"); + log.debug("create resource failed with exception", e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + } + } + + private boolean isUIImport(String data) { + boolean isUIImport; + try { + JSONObject json = new JSONObject(data); + String payloadName = json.getString(ImportUtils.Constants.UI_JSON_PAYLOAD_NAME); + isUIImport = payloadName != null && !payloadName.isEmpty(); + } catch (JSONException e) { + log.debug("failed to parse json sent from client, json:{}", data, e); + isUIImport = false; + } + return isUIImport; + } + + private void performUIImport(Wrapper<Response> responseWrapper, String data, final HttpServletRequest request, String userId, String resourceUniqueId) throws FileNotFoundException { + + Wrapper<User> userWrapper = new Wrapper<>(); + Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>(); + Wrapper<String> yamlStringWrapper = new Wrapper<>(); + + ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.USER_TYPE_UI; + + commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, data); + + if (!CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) { + fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), data, resourceAuthorityEnum, null); + + // PayLoad Validations + commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement()); + } + specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, data, resourceAuthorityEnum); + + if (responseWrapper.isEmpty()) { + handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, true, resourceUniqueId); + } + } + + private Either<Resource, ResponseFormat> parseToResource(String resourceJson, User user) { + return getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.RESOURCE); + } + + private Either<Resource, ResponseFormat> parseToLightResource(String resourceJson, User user) { + Either<Resource, ResponseFormat> ret = getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE); + if (ret.isLeft()) {// drop unwanted data (sent from UI in update flow) + ret.left().value().setRequirements(null); + ret.left().value().setCapabilities(null); + } + return ret; + } + + @DELETE + @Path("/resources/{resourceId}") + public Response deleteResource(@PathParam("resourceId") final String resourceId, @Context final HttpServletRequest request) { + + ServletContext context = request.getSession().getServletContext(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}" , url); + + // get modifier id + String userId = request.getHeader(Constants.USER_ID_HEADER); + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}" , userId); + + Response response; + + try { + String resourceIdLower = resourceId.toLowerCase(); + ResponseFormat actionResponse = resourceBusinessLogic.deleteResource(resourceIdLower, modifier); + + if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) { + log.debug("failed to delete resource"); + response = buildErrorResponse(actionResponse); + return response; + } + response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null); + return response; + + } catch (JSONException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Resource"); + log.debug("delete resource failed with exception", e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + + } + } + + @DELETE + @Path("/resources/{resourceName}/{version}") + public Response deleteResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, @PathParam("version") final String version, @Context final HttpServletRequest request) { + + ServletContext context = request.getSession().getServletContext(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}" , url); + + // get modifier id + String userId = request.getHeader(Constants.USER_ID_HEADER); + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}" , userId); + + Response response; + ResponseFormat actionResponse = resourceBusinessLogic.deleteResourceByNameAndVersion(resourceName, version, modifier); + + if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) { + log.debug("failed to delete resource"); + response = buildErrorResponse(actionResponse); + return response; + } + response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null); + return response; + } + + @GET + @Path("/resources/{resourceId}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Retrieve Resource", method = "GET", summary = "Returns resource according to resourceId", + responses = @ApiResponse( + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class))))) + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "404", description = "Resource not found")}) + public Response getResourceById(@PathParam("resourceId") final String resourceId, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + ServletContext context = request.getSession().getServletContext(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}" , url); + + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}" , userId); + + Response response; + + try { + String resourceIdLower = resourceId.toLowerCase(); + log.trace("get resource with id {}", resourceId); + Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResource(resourceIdLower, modifier); + + if (actionResponse.isRight()) { + log.debug("failed to get resource"); + response = buildErrorResponse(actionResponse.right().value()); + return response; + } + Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value()); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource); + + } catch (IOException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource"); + log.debug("get resource failed with exception", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + + } + } + + @GET + @Path("/resources/resourceName/{resourceName}/resourceVersion/{resourceVersion}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Retrieve Resource by name and version", method = "GET", + summary = "Returns resource according to resourceId", responses = @ApiResponse( + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class))))) + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "404", description = "Resource not found")}) + public Response getResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, + @PathParam("resourceVersion") final String resourceVersion, @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + ServletContext context = request.getSession().getServletContext(); + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}" , userId); + Response response; + try { + Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResourceByNameAndVersion(resourceName, resourceVersion, userId); + if (actionResponse.isRight()) { + response = buildErrorResponse(actionResponse.right().value()); + return response; + } + Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value()); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource); + + } catch (IOException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource by name and version"); + log.debug("get resource failed with exception", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + + } + } + + @GET + @Path("/resources/validate-name/{resourceName}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "validate resource name", method = "GET", + summary = "checks if the chosen resource name is available ", responses = @ApiResponse( + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class))))) + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"), + @ApiResponse(responseCode = "403", description = "Restricted operation")}) + public Response validateResourceName(@PathParam("resourceName") final String resourceName, + @QueryParam("subtype") String resourceType, @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + ServletContext context = request.getSession().getServletContext(); + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}" , url); + + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}" , userId); + Response response; + + if (resourceType != null && !ResourceTypeEnum.containsName(resourceType)) { + log.debug("invalid resource type received"); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); + return response; + + } + ResourceTypeEnum typeEnum = null; + if (resourceType != null) { + typeEnum = ResourceTypeEnum.valueOf(resourceType); + } + Either<Map<String, Boolean>, ResponseFormat> actionResponse = resourceBusinessLogic.validateResourceNameExists(resourceName, typeEnum, userId); + + if (actionResponse.isRight()) { + log.debug("failed to validate resource name"); + response = buildErrorResponse(actionResponse.right().value()); + return response; + } + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value()); + } + + @GET + @Path("/resources/certified/abstract") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response getCertifiedAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("(get) Start handle request of {}" , url); + try { + List<Resource> resources = resourceBusinessLogic + .getAllCertifiedResources(true, HighestFilterEnum.HIGHEST_ONLY, userId); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resources)); + + } catch (IOException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Abstract Resources"); + log.debug("getCertifiedAbstractResources failed with exception", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + @GET + @Path("/resources/certified/notabstract") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response getCertifiedNotAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("(get) Start handle request of {}" , url); + try { + List<Resource> resouces = resourceBusinessLogic.getAllCertifiedResources(false, HighestFilterEnum.ALL, userId); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resouces)); + + } catch (IOException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Non Abstract Resources"); + log.debug("getCertifiedNotAbstractResources failed with exception", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + + } + + @PUT + @Path("/resources/{resourceId}/metadata") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Update Resource Metadata", method = "PUT", summary = "Returns updated resource metadata", + responses = @ApiResponse( + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class))))) + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource metadata updated"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content")}) + public Response updateResourceMetadata(@PathParam("resourceId") final String resourceId, + @Parameter(description = "Resource metadata to be updated", required = true) String data, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}" , url); + + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}", userId); + Response response; + try { + String resourceIdLower = resourceId.toLowerCase(); + Either<Resource, ResponseFormat> updateInfoResource = getComponentsUtils().convertJsonToObjectUsingObjectMapper(data, modifier, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE); + if (updateInfoResource.isRight()) { + log.debug("failed to parse resource metadata"); + response = buildErrorResponse(updateInfoResource.right().value()); + return response; + } + Resource updatedResource = resourceBusinessLogic.updateResourceMetadata(resourceIdLower, updateInfoResource.left().value(), null, modifier, false); + Object resource = RepresentationUtils.toRepresentation(updatedResource); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource); + } catch (IOException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource Metadata"); + log.debug("Update Resource Metadata failed with exception", e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + + } + } + + @PUT + @Path("/resources/{resourceId}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Update Resource", method = "PUT", summary = "Returns updated resource", + responses = @ApiResponse( + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class))))) + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource updated"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "409", description = "Resource already exist")}) + public Response updateResource( + @Parameter(description = "Resource object to be updated", required = true) String data, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId, + @PathParam(value = "resourceId") String resourceId) { + + userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER); + init(); + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}", url); + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}", userId); + Response response; + try { + Wrapper<Response> responseWrapper = new Wrapper<>(); + // UI Import + if (isUIImport(data)) { + performUIImport(responseWrapper, data, request, userId, resourceId); + } else { + Either<Resource, ResponseFormat> convertResponse = parseToLightResource(data, modifier); + if (convertResponse.isRight()) { + log.debug("failed to parse resource"); + response = buildErrorResponse(convertResponse.right().value()); + return response; + } + Resource updatedResource = resourceBusinessLogic.validateAndUpdateResourceFromCsar( + convertResponse.left().value(), modifier, null, null, resourceId); + Object representation = RepresentationUtils.toRepresentation(updatedResource); + response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation); + responseWrapper.setInnerElement(response); + } + return responseWrapper.getInnerElement(); + } catch (IOException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource"); + log.debug("update resource failed with exception", e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + + } + } + + @GET + @Path("/resources/csar/{csaruuid}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Create Resource", method = "POST", summary = "Returns resource created from csar uuid", + responses = @ApiResponse( + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class))))) + @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource retrieced"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")}) + public Response getResourceFromCsar(@Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId, + @PathParam(value = "csaruuid") String csarUUID) { + + init(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}", url); + + // retrieve user details + userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER); + User user = new User(); + user.setUserId(userId); + + log.debug("user id is {}", userId); + + Response response; + + try { + + Either<Resource, ResponseFormat> eitherResource = + resourceBusinessLogic.getLatestResourceFromCsarUuid(csarUUID, user); + + // validate response + if (eitherResource.isRight()) { + log.debug("failed to get resource from csarUuid : {}", csarUUID); + response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), + eitherResource.right().value()); + } else { + Object representation = RepresentationUtils.toRepresentation(eitherResource.left().value()); + response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation); + } + + return response; + + } catch (IOException e) { + log.debug("get resource by csar failed with exception", e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + } + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadEndpoint.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadEndpoint.java index 5847a06e2b..5a148ef39e 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadEndpoint.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadEndpoint.java @@ -1,136 +1,143 @@ -/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed 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.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.be.servlets;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.glassfish.jersey.media.multipart.FormDataParam;
-import org.openecomp.sdc.be.components.impl.CommonImportManager;
-import org.openecomp.sdc.be.components.validation.AccessValidations;
-import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
-import org.openecomp.sdc.be.model.AnnotationTypeDefinition;
-import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations;
-import org.openecomp.sdc.be.utils.TypeUtils;
-import org.openecomp.sdc.common.datastructure.Wrapper;
-import org.springframework.http.HttpStatus;
-import org.springframework.stereotype.Controller;
-import com.google.common.annotations.VisibleForTesting;
-import com.jcabi.aspects.Loggable;
-import io.swagger.v3.oas.annotations.OpenAPIDefinition;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.info.Info;
-import io.swagger.v3.oas.annotations.media.ArraySchema;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.responses.ApiResponses;
-/**
- * Here new APIs for types upload written in an attempt to gradually servlet responseCode
- */
-@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
-@Path("/v1/catalog/uploadType")
-@Consumes(MediaType.MULTIPART_FORM_DATA)
-@Produces(MediaType.APPLICATION_JSON)
-@OpenAPIDefinition(info = @Info(title = "Catalog Types Upload"))
-@Controller
-public class TypesUploadEndpoint {
-
- private final CommonImportManager commonImportManager;
- private final AnnotationTypeOperations annotationTypeOperations;
- private final AccessValidations accessValidations;
-
- public TypesUploadEndpoint(CommonImportManager commonImportManager, AnnotationTypeOperations annotationTypeOperations, AccessValidations accessValidations) {
- this.commonImportManager = commonImportManager;
- this.annotationTypeOperations = annotationTypeOperations;
- this.accessValidations = accessValidations;
- }
-
- @POST
- @Path("/annotationtypes")
- @Operation(description = "Create AnnotationTypes from yaml", method = "POST",
- summary = "Returns created annotation types",responses = @ApiResponse(
- content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
- @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "annotation types created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "annotation types already exist")})
-
- public Response uploadAnnotationTypes(@Parameter(description = "FileInputStream") @FormDataParam("annotationTypesZip") File file,
- @HeaderParam("USER_ID") String userId) throws IOException {
- accessValidations.validateUserExists(userId, "Annotation Types Creation");
- Wrapper<String> yamlStringWrapper = new Wrapper<>();
- AbstractValidationsServlet.extractZipContents(yamlStringWrapper, file);
- List<ImmutablePair<AnnotationTypeDefinition, Boolean>> typesResults =
- commonImportManager.createElementTypes(yamlStringWrapper.getInnerElement(),
- TypesUploadEndpoint::buildAnnotationFromFieldMap, annotationTypeOperations);
- HttpStatus status = getHttpStatus(typesResults);
- return Response.status(status.value()).entity(typesResults).build();
- }
-
- @VisibleForTesting
- static <T extends ToscaDataDefinition> HttpStatus getHttpStatus(List<ImmutablePair<T, Boolean>> typesResults) {
- boolean typeActionFailed = false;
- boolean typeExists = false;
- boolean typeActionSucceeded = false;
- for (ImmutablePair<T, Boolean> typeResult : typesResults) {
- Boolean result = typeResult.getRight();
- if (result==null) {
- typeExists = true;
- } else if (result) {
- typeActionSucceeded = true;
- } else {
- typeActionFailed = true;
- }
- }
- HttpStatus status = HttpStatus.OK;
- if (typeActionFailed) {
- status = HttpStatus.BAD_REQUEST;
- } else if (typeActionSucceeded) {
- status = HttpStatus.CREATED;
- } else if (typeExists) {
- status = HttpStatus.CONFLICT;
- }
- return status;
- }
-
- private static <T extends ToscaDataDefinition> T buildAnnotationFromFieldMap(String typeName, Map<String, Object> toscaJson) {
- AnnotationTypeDefinition annotationType = new AnnotationTypeDefinition();
- annotationType.setVersion(TypeUtils.getFirstCertifiedVersionVersion());
- annotationType.setHighestVersion(true);
- annotationType.setType(typeName);
- TypeUtils.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, annotationType::setDescription);
- CommonImportManager.setProperties(toscaJson, annotationType::setProperties);
- return (T) annotationType;
- }
-
-
-}
+/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.servlets; + +import java.io.File; +import java.util.List; +import java.util.Map; +import javax.ws.rs.Consumes; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.glassfish.jersey.media.multipart.FormDataParam; +import org.openecomp.sdc.be.components.impl.CommonImportManager; +import org.openecomp.sdc.be.components.validation.AccessValidations; +import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; +import org.openecomp.sdc.be.model.AnnotationTypeDefinition; +import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations; +import org.openecomp.sdc.be.utils.TypeUtils; +import org.openecomp.sdc.common.datastructure.Wrapper; +import org.openecomp.sdc.common.zip.exception.ZipException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import com.google.common.annotations.VisibleForTesting; +import com.jcabi.aspects.Loggable; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +/** + * Here new APIs for types upload written in an attempt to gradually servlet responseCode + */ +@Loggable(prepend = true, value = Loggable.DEBUG, trim = false) +@Path("/v1/catalog/uploadType") +@Consumes(MediaType.MULTIPART_FORM_DATA) +@Produces(MediaType.APPLICATION_JSON) +@OpenAPIDefinition(info = @Info(title = "Catalog Types Upload")) +@Controller +public class TypesUploadEndpoint { + private static final Logger LOGGER = LoggerFactory.getLogger(TypesUploadEndpoint.class); + + private final CommonImportManager commonImportManager; + private final AnnotationTypeOperations annotationTypeOperations; + private final AccessValidations accessValidations; + + public TypesUploadEndpoint(CommonImportManager commonImportManager, AnnotationTypeOperations annotationTypeOperations, AccessValidations accessValidations) { + this.commonImportManager = commonImportManager; + this.annotationTypeOperations = annotationTypeOperations; + this.accessValidations = accessValidations; + } + + @POST + @Path("/annotationtypes") + @Operation(description = "Create AnnotationTypes from yaml", method = "POST", + summary = "Returns created annotation types",responses = @ApiResponse( + content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class))))) + @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "annotation types created"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "409", description = "annotation types already exist")}) + + public Response uploadAnnotationTypes(@Parameter(description = "FileInputStream") @FormDataParam("annotationTypesZip") File file, + @HeaderParam("USER_ID") String userId) { + accessValidations.validateUserExists(userId, "Annotation Types Creation"); + final Wrapper<String> yamlStringWrapper = new Wrapper<>(); + try { + AbstractValidationsServlet.extractZipContents(yamlStringWrapper, file); + } catch (final ZipException e) { + LOGGER.error("Could not extract zip contents", e); + } + List<ImmutablePair<AnnotationTypeDefinition, Boolean>> typesResults = + commonImportManager.createElementTypes(yamlStringWrapper.getInnerElement(), + TypesUploadEndpoint::buildAnnotationFromFieldMap, annotationTypeOperations); + HttpStatus status = getHttpStatus(typesResults); + return Response.status(status.value()).entity(typesResults).build(); + } + + @VisibleForTesting + static <T extends ToscaDataDefinition> HttpStatus getHttpStatus(List<ImmutablePair<T, Boolean>> typesResults) { + boolean typeActionFailed = false; + boolean typeExists = false; + boolean typeActionSucceeded = false; + for (ImmutablePair<T, Boolean> typeResult : typesResults) { + Boolean result = typeResult.getRight(); + if (result==null) { + typeExists = true; + } else if (result) { + typeActionSucceeded = true; + } else { + typeActionFailed = true; + } + } + HttpStatus status = HttpStatus.OK; + if (typeActionFailed) { + status = HttpStatus.BAD_REQUEST; + } else if (typeActionSucceeded) { + status = HttpStatus.CREATED; + } else if (typeExists) { + status = HttpStatus.CONFLICT; + } + return status; + } + + private static <T extends ToscaDataDefinition> T buildAnnotationFromFieldMap(String typeName, Map<String, Object> toscaJson) { + AnnotationTypeDefinition annotationType = new AnnotationTypeDefinition(); + annotationType.setVersion(TypeUtils.getFirstCertifiedVersionVersion()); + annotationType.setHighestVersion(true); + annotationType.setType(typeName); + TypeUtils.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, annotationType::setDescription); + CommonImportManager.setProperties(toscaJson, annotationType::setProperties); + return (T) annotationType; + } + + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java index 2f1357ea13..836565c1fe 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java @@ -55,6 +55,7 @@ import org.openecomp.sdc.common.impl.ExternalConfiguration; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.common.util.GeneralUtility; import org.openecomp.sdc.common.util.ValidationUtils; +import org.openecomp.sdc.common.zip.ZipUtils; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.beans.factory.annotation.Autowired; @@ -339,23 +340,20 @@ public class CsarUtils { isInCertificationRequest); } - private Either<ZipOutputStream, ResponseFormat> addSchemaFilesFromCassandra(ZipOutputStream zip, - byte[] schemaFileZip) { - + private Either<ZipOutputStream, ResponseFormat> addSchemaFilesFromCassandra(final ZipOutputStream zip, + final byte[] schemaFileZip) { final int initSize = 2048; - log.debug("Starting copy from Schema file zip to CSAR zip"); - - try (ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(schemaFileZip)); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - BufferedOutputStream bos = new BufferedOutputStream(out, initSize)) { + try (final ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(schemaFileZip)); + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final BufferedOutputStream bos = new BufferedOutputStream(out, initSize)) { ZipEntry entry; while ((entry = zipStream.getNextEntry()) != null) { - - String entryName = entry.getName(); + ZipUtils.checkForZipSlipInRead(entry); + final String entryName = entry.getName(); int readSize = initSize; - byte[] entryData = new byte[initSize]; + final byte[] entryData = new byte[initSize]; while ((readSize = zipStream.read(entryData, 0, readSize)) != -1) { bos.write(entryData, 0, readSize); @@ -368,13 +366,12 @@ public class CsarUtils { zip.flush(); out.reset(); } - } catch (IOException | NullPointerException e) { - log.error("Error while writing the SDC schema file to the CSAR {}", e); + } catch (final Exception e) { + log.error("Error while writing the SDC schema file to the CSAR", e); return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); } log.debug("Finished coppy from Schema file zip to CSAR zip"); - return Either.left(zip); } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/ZipUtil.java b/catalog-be/src/test/java/org/openecomp/sdc/ZipUtil.java deleted file mode 100644 index 87e351be8a..0000000000 --- a/catalog-be/src/test/java/org/openecomp/sdc/ZipUtil.java +++ /dev/null @@ -1,143 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Modifications Copyright (c) 2019 Samsung - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.sdc; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.output.ByteArrayOutputStream; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -public class ZipUtil { - - public static void main(String[] args) { - - String zipFileName = "/src/test/resources/config/config.zip"; - - zipFileName = "C:\\Git_work\\D2-SDnC\\catalog-be\\src\\test\\resources\\config\\config.zip"; - zipFileName = "src/test/resources/config/config.zip"; - - Path path = Paths.get(zipFileName); - - try { - byte[] zipAsBytes = Files.readAllBytes(path); - // encode to base - - byte[] decodedMd5 = Base64.encodeBase64(zipAsBytes); - String decodedStr = new String(decodedMd5); - - zipAsBytes = Base64.decodeBase64(decodedStr.getBytes()); - - // String str = new String(zipAsBytes); - - // readZip(str.getBytes()); - readZip(zipAsBytes); - - } catch (IOException e) { - e.printStackTrace(); - } - - } - - private static Map<String, byte[]> readZip(byte[] zipAsBytes) { - - Map<String, byte[]> fileNameToByteArray = new HashMap<>(); - - byte[] buffer = new byte[1024]; - ZipInputStream zis = null; - try { - - zis = new ZipInputStream(new ByteArrayInputStream(zipAsBytes)); - // get the zipped file list entry - ZipEntry ze = zis.getNextEntry(); - - while (ze != null) { - - String fileName = ze.getName(); - - if (!ze.isDirectory()) { - - ByteArrayOutputStream os = new ByteArrayOutputStream(); - try { - int len; - while ((len = zis.read(buffer)) > 0) { - os.write(buffer, 0, len); - } - - // aClass.outputStreamMethod(os); - String aString = new String(os.toByteArray(), "UTF-8"); - - fileNameToByteArray.put(fileName, os.toByteArray()); - - } finally { - if (os != null) { - os.close(); - } - } - } - ze = zis.getNextEntry(); - - } - - zis.closeEntry(); - zis.close(); - - } catch (IOException ex) { - ex.printStackTrace(); - return null; - } finally { - if (zis != null) { - try { - zis.closeEntry(); - zis.close(); - } catch (IOException e) { - // TODO: add log - } - - } - } - - return fileNameToByteArray; - - } - - private static byte[] loadResource(String resourceDir) throws IOException, URISyntaxException { - - Path path = Paths.get(ZipUtil.class.getResource(resourceDir).toURI()); - return Files.readAllBytes(path); - } - - public static Map<String, byte[]> readData(String resourceDir) throws IOException, URISyntaxException { - - byte[] data = loadResource(resourceDir); - return readZip(data); - } -} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogicTest.java index 2f7f5aab17..9bad9f4fa8 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogicTest.java @@ -50,11 +50,7 @@ import java.util.Map; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; import org.openecomp.sdc.be.components.impl.BaseBusinessLogicMock; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; @@ -66,7 +62,8 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.CsarOperation; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; -import org.openecomp.sdc.common.util.ZipUtil; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.exception.ResponseFormat; public class CsarBusinessLogicTest extends BaseBusinessLogicMock { @@ -125,7 +122,7 @@ public class CsarBusinessLogicTest extends BaseBusinessLogicMock { } @Test() - public void testGetCsarInfoWithPayload() throws IOException, URISyntaxException { + public void testGetCsarInfoWithPayload() throws IOException, URISyntaxException, ZipException { // given Resource resource = new Resource(); resource.setName(RESOURCE_NAME); @@ -185,11 +182,11 @@ public class CsarBusinessLogicTest extends BaseBusinessLogicMock { test.validateCsarBeforeCreate(resource, AuditingActionEnum.ARTIFACT_DOWNLOAD, user, "csarUUID"); } - public Map<String, byte[]> loadPayload(String payloadName) throws IOException, URISyntaxException { + public Map<String, byte[]> loadPayload(String payloadName) throws IOException, URISyntaxException, ZipException { Path path = Paths.get(getClass().getResource("/" + payloadName).toURI()); byte[] data = Files.readAllBytes(path); - return ZipUtil.readZip(data); + return ZipUtils.readZip(data, false); } } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java index 3ae65c818a..69f9f5704d 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java @@ -25,7 +25,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.io.IOException; +import java.io.File; import java.net.URISyntaxException; import java.util.Arrays; import java.util.List; @@ -41,7 +41,8 @@ import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentEx import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.model.NodeTypeInfo; import org.openecomp.sdc.be.model.User; -import org.openecomp.sdc.ZipUtil; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; @RunWith(MockitoJUnitRunner.class) public class CsarInfoTest { @@ -52,19 +53,18 @@ public class CsarInfoTest { private User user; private static final String CSAR_UUID = "csarUUID"; - private static final String PAYLOAD_NAME = "/mock_service.csar"; + private static final String PAYLOAD_NAME = "mock_service.csar"; private static final String RESOURCE_NAME = "resourceName"; private static final String MAIN_TEMPLATE_NAME = "Definitions/tosca_mock_vf.yaml"; - private static final String NEW_NODE_NAME = "new_db"; private static final String NODE_TYPE = "tosca.nodes.Compute"; private static final String DELIVER_FOR = "tosca.nodes.Root"; @Before - public void setup() throws IOException, URISyntaxException { - + public void setup() throws ZipException, URISyntaxException { // given - Map<String, byte[]> payload = ZipUtil.readData(PAYLOAD_NAME); + final File csarFile = new File(CsarInfoTest.class.getClassLoader().getResource(PAYLOAD_NAME).toURI()); + final Map<String, byte[]> payload = ZipUtils.readZip(csarFile, false); String mainTemplateContent = new String(payload.get(MAIN_TEMPLATE_NAME)); csarInfo = new CsarInfo(user, CSAR_UUID, payload, RESOURCE_NAME, diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java index 19d1a17e84..8ae02c4f1b 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java @@ -27,11 +27,14 @@ import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; -import java.io.IOException; +import java.io.File; import java.net.URISyntaxException; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; - import org.assertj.core.util.Lists; import org.junit.Assert; import org.junit.Before; @@ -41,8 +44,6 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; - -import org.openecomp.sdc.ZipUtil; import org.openecomp.sdc.be.components.csar.CsarInfo; import org.openecomp.sdc.be.components.csar.YamlTemplateParsingHandler; import org.openecomp.sdc.be.components.impl.AnnotationBusinessLogic; @@ -50,8 +51,15 @@ import org.openecomp.sdc.be.components.impl.GroupTypeBusinessLogic; import org.openecomp.sdc.be.components.validation.AnnotationValidator; import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; -import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.GroupProperty; +import org.openecomp.sdc.be.model.GroupTypeDefinition; +import org.openecomp.sdc.be.model.ParsedToscaYamlInfo; +import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import java.io.File; import java.io.IOException; @@ -88,10 +96,8 @@ public class YamlTemplateParsingHandlerTest { private final static GroupTypeDefinition rootGroupType = buildRootGroupType(); private final static String CAPABILITY_TYPE = "org.openecomp.capabilities.VLANAssignment"; private final static String CAPABILITY_NAME = "vlan_assignment"; - private static final String CSAR_FILE_PATH = "/csars/with_groups.csar"; - + private static final String CSAR_FILE_PATH = "csars/with_groups.csar"; private static final String FILE_NAME = "MainServiceTemplate.yaml"; - private static final String CSAR_UUID = "csarUUID"; private static final String RESOURCE_NAME = "resourceName"; private static final String MAIN_TEMPLATE_NAME = "Definitions/MainServiceTemplate.yaml"; @@ -103,8 +109,10 @@ public class YamlTemplateParsingHandlerTest { YamlTemplateParsingHandler testSubject; @BeforeClass() - public static void prepareData() throws IOException, URISyntaxException { - csar = ZipUtil.readData(CSAR_FILE_PATH); + public static void prepareData() throws URISyntaxException, ZipException { + final File csarFile = new File( + YamlTemplateParsingHandlerTest.class.getClassLoader().getResource(CSAR_FILE_PATH).toURI()); + csar = ZipUtils.readZip(csarFile, false); Optional<String> keyOp = csar.keySet().stream().filter(k -> k.endsWith(FILE_NAME)).findAny(); byte[] mainTemplateService = keyOp.map(csar::get).orElse(null); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CsarOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CsarOperation.java index 9ae2f252c9..af8a68f410 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CsarOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CsarOperation.java @@ -25,17 +25,11 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import fj.data.Either; -import org.apache.commons.io.filefilter.WildcardFileFilter; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.common.log.wrappers.Logger; -import org.openecomp.sdc.common.util.ZipUtil; import javax.annotation.PostConstruct; -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.nio.file.Files; import java.util.Map; @org.springframework.stereotype.Component("csar-operation") @@ -62,29 +56,6 @@ public class CsarOperation { } - public Either<Map<String, byte[]>, StorageOperationStatus> getMockCsar(String csarUuid) { - File dir = new File("/var/tmp/mockCsar"); - FileFilter fileFilter = new WildcardFileFilter("*.csar"); - File[] files = dir.listFiles(fileFilter); - for (int i = 0; i < files.length; i++) { - File csar = files[i]; - if (csar.getName().startsWith(csarUuid)) { - log.debug("Found CSAR file {} matching the passed csarUuid {}", csar.getAbsolutePath(), csarUuid); - byte[] data; - try { - data = Files.readAllBytes(csar.toPath()); - } catch (IOException e) { - log.debug("Error reading mock file for CSAR, error: {}", e); - return Either.right(StorageOperationStatus.NOT_FOUND); - } - Map<String, byte[]> readZip = ZipUtil.readZip(data); - return Either.left(readZip); - } - } - log.debug("Couldn't find mock file for CSAR starting with {}", csarUuid); - return Either.right(StorageOperationStatus.CSAR_NOT_FOUND); - } - /** * get csar from remote repository * diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OnboardingClient.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OnboardingClient.java index 8e1ee19358..ed0b43e38e 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OnboardingClient.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OnboardingClient.java @@ -21,7 +21,8 @@ package org.openecomp.sdc.be.model.operations.impl; import fj.data.Either; -import org.apache.commons.io.filefilter.WildcardFileFilter; +import java.util.Map; +import java.util.Properties; import org.apache.http.HttpStatus; import org.openecomp.sdc.be.config.Configuration.OnboardingConfig; import org.openecomp.sdc.be.config.ConfigurationManager; @@ -30,14 +31,7 @@ import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.http.client.api.HttpRequest; import org.openecomp.sdc.common.http.client.api.HttpResponse; import org.openecomp.sdc.common.log.wrappers.Logger; -import org.openecomp.sdc.common.util.ZipUtil; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.nio.file.Files; -import java.util.Map; -import java.util.Properties; +import org.openecomp.sdc.common.zip.ZipUtils; @org.springframework.stereotype.Component("onboarding-client") public class OnboardingClient { @@ -64,29 +58,6 @@ public class OnboardingClient { } - public Either<Map<String, byte[]>, StorageOperationStatus> getMockCsar(String csarUuid) { - File dir = new File("/var/tmp/mockCsar"); - FileFilter fileFilter = new WildcardFileFilter("*.csar"); - File[] files = dir.listFiles(fileFilter); - for (int i = 0; i < files.length; i++) { - File csar = files[i]; - if (csar.getName().startsWith(csarUuid)) { - log.debug("Found CSAR file {} matching the passed csarUuid {}", csar.getAbsolutePath(), csarUuid); - byte[] data; - try { - data = Files.readAllBytes(csar.toPath()); - } catch (IOException e) { - log.debug("Error reading mock file for CSAR, error: {}", e); - return Either.right(StorageOperationStatus.NOT_FOUND); - } - Map<String, byte[]> readZip = ZipUtil.readZip(data); - return Either.left(readZip); - } - } - log.debug("Couldn't find mock file for CSAR starting with {}", csarUuid); - return Either.right(StorageOperationStatus.NOT_FOUND); - } - public Either<Map<String, byte[]>, StorageOperationStatus> getCsar(String csarUuid, String userId) { String url = buildDownloadCsarUrl() + "/" + csarUuid; @@ -109,7 +80,7 @@ public class OnboardingClient { case HttpStatus.SC_OK: byte[] data = httpResponse.getResponse(); if (data != null && data.length > 0) { - Map<String, byte[]> readZip = ZipUtil.readZip(data); + Map<String, byte[]> readZip = ZipUtils.readZip(data, false); return Either.left(readZip); } else { log.debug("Data received from rest is null or empty"); @@ -124,7 +95,7 @@ public class OnboardingClient { } } catch(Exception e) { - log.debug("Request failed with exception {}", e); + log.debug("Request failed with exception", e); return Either.right(StorageOperationStatus.GENERAL_ERROR); } } @@ -158,7 +129,7 @@ public class OnboardingClient { } } catch(Exception e) { - log.debug("Request failed with exception {}", e); + log.debug("Request failed with exception", e); return Either.right(StorageOperationStatus.GENERAL_ERROR); } } diff --git a/common-app-api/pom.xml b/common-app-api/pom.xml index 38d3bbec87..62bfb24b28 100644 --- a/common-app-api/pom.xml +++ b/common-app-api/pom.xml @@ -159,6 +159,20 @@ </dependency> <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest</artifactId> + <version>${hamcrest.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-library</artifactId> + <version>${hamcrest.version}</version> + <scope>test</scope> + </dependency> + + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/util/ZipUtil.java b/common-app-api/src/main/java/org/openecomp/sdc/common/util/ZipUtil.java deleted file mode 100644 index ec3c31cffe..0000000000 --- a/common-app-api/src/main/java/org/openecomp/sdc/common/util/ZipUtil.java +++ /dev/null @@ -1,135 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.sdc.common.util; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.output.ByteArrayOutputStream; -import org.openecomp.sdc.common.log.wrappers.Logger; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -public class ZipUtil { - - private static final int KB = 1024; - private static Logger log = Logger.getLogger(ZipUtil.class.getName()); - - private ZipUtil() { - } - - public static Map<String, byte[]> readZip(File file) { - try (InputStream fileInputStream = new FileInputStream(file)) { - return readZip(IOUtils.toByteArray(fileInputStream)); - } catch (IOException e) { - log.info("close File stream failed - {}", e); - return null; - } - } - - public static Map<String, byte[]> readZip(byte[] zipAsBytes) { - Map<String, byte[]> fileNameToByteArray = new HashMap<>(); - byte[] buffer = new byte[KB]; - try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipAsBytes); - ZipInputStream zis = new ZipInputStream(byteArrayInputStream)) { - // get the zipped file list entry - ZipEntry ze = zis.getNextEntry(); - - while (ze != null) { - - String fileName = ze.getName(); - - if (!ze.isDirectory()) { - - try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { - int len; - while ((len = zis.read(buffer)) > 0) { - os.write(buffer, 0, len); - } - - fileNameToByteArray.put(fileName, os.toByteArray()); - - } - } - ze = zis.getNextEntry(); - } - } catch (IOException ex) { - log.info("close Byte stream failed", ex); - return null; - } - - return fileNameToByteArray; - - } - - public static void main(String[] args) { - String zipFileName = "/src/test/resources/config/config.zip"; - zipFileName = "C:\\Git_work\\D2-SDnC\\catalog-be\\src\\test\\resources\\config\\config.zip"; - Path path = Paths.get(zipFileName); - - try { - byte[] zipAsBytes = Files.readAllBytes(path); - // encode to base - - ZipUtil.readZip(zipAsBytes); - - } catch (IOException e) { - log.info("close Byte stream failed", e); - } - } - - public static byte[] zipBytes(byte[] input) throws IOException { - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ZipOutputStream zos = new ZipOutputStream(baos)) { - ZipEntry entry = new ZipEntry("zip"); - entry.setSize(input.length); - zos.putNextEntry(entry); - zos.write(input); - zos.closeEntry(); - return baos.toByteArray(); - } - } - - public static byte[] unzip(byte[] zipped) { - try (ZipInputStream zipinputstream = new ZipInputStream(new ByteArrayInputStream(zipped)); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - byte[] buf = new byte[KB]; - ZipEntry zipentry = zipinputstream.getNextEntry(); - int n; - while ((n = zipinputstream.read(buf, 0, KB)) > -1) { - outputStream.write(buf, 0, n); - } - return outputStream.toByteArray(); - } catch (Exception e) { - throw new IllegalStateException("Can't unzip input stream", e); - } - } -} diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/zip/ZipUtils.java b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/ZipUtils.java new file mode 100644 index 0000000000..d90377fc88 --- /dev/null +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/ZipUtils.java @@ -0,0 +1,354 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation + * ================================================================================ + * Licensed 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.common.zip; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; +import org.apache.commons.io.IOUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; +import org.openecomp.sdc.common.zip.exception.ZipSlipException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handles zip operations. + */ +public class ZipUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(ZipUtils.class); + + private ZipUtils() { + } + + /** + * Checks if the path is a zip slip attempt calling the {@link #checkForZipSlipInRead(Path)} method. + * @param zipEntry the zip entry + * @throws ZipSlipException when a zip slip attempt is detected + */ + public static void checkForZipSlipInRead(final ZipEntry zipEntry) throws ZipSlipException { + final Path filePath = Paths.get(zipEntry.getName()); + checkForZipSlipInRead(filePath); + } + + /** + * Checks if the path is a zip slip attempt when you don't have a destination folder eg in memory reading or zip + * creation. + * + * @param filePath the file path + * @throws ZipSlipException when a zip slip attempt is detected + */ + public static void checkForZipSlipInRead(final Path filePath) throws ZipSlipException { + final File file = filePath.toFile(); + String canonicalPath = null; + try { + canonicalPath = file.getCanonicalPath(); + } catch (final IOException ignored) { + //ignored + } + if (canonicalPath != null && !canonicalPath.equals(file.getAbsolutePath())) { + throw new ZipSlipException(filePath.toString()); + } + + if (filePath.toString().contains("../") || filePath.toString().contains("..\\")) { + throw new ZipSlipException(filePath.toString()); + } + } + + /** + * Checks if the zip entry is a zip slip attempt based on the destination directory. + * + * @param zipEntry the zip entry + * @param targetDirectoryPath the target extraction folder + * @throws ZipException when the zip slip was detected as a {@link ZipSlipException}. Also when there was a problem + * getting the canonical paths from the zip entry or target directory. + */ + public static void checkForZipSlipInExtraction(final ZipEntry zipEntry, + final Path targetDirectoryPath) throws ZipException { + final File targetDirectoryAsFile = targetDirectoryPath.toFile(); + final File targetFile = new File(targetDirectoryAsFile, zipEntry.getName()); + final String targetDirectoryCanonicalPath; + try { + targetDirectoryCanonicalPath = targetDirectoryAsFile.getCanonicalPath(); + } catch (final IOException e) { + throw new ZipException( + String.format("Could not obtain canonical path of: '%s'", targetDirectoryAsFile.getAbsolutePath()), e); + } + final String targetFileCanonicalPath; + try { + targetFileCanonicalPath = targetFile.getCanonicalPath(); + } catch (final IOException e) { + throw new ZipException( + String.format("Could not obtain canonical path of: '%s'", targetFile.getAbsolutePath()), e); + } + + if (!targetFileCanonicalPath.startsWith(targetDirectoryCanonicalPath + File.separator)) { + throw new ZipSlipException(zipEntry.getName()); + } + } + + /** + * Creates a ZipInputStream from a byte array. + * + * @param zipFileBytes the zip byte array + * @return the created ZipInputStream. + */ + private static ZipInputStream getInputStreamFromBytes(final byte[] zipFileBytes) { + return new ZipInputStream(new ByteArrayInputStream(zipFileBytes)); + } + + /** + * Reads a zip file into memory. Parses the zipFile in byte array and calls {@link #readZip(byte[], boolean)}. + * + * @param zipFile the zip file to read + * @param hasToIncludeDirectories includes or not the directories found during the zip reading + * @return a Map representing a pair of file path and file byte array + * @throws ZipException when there was a problem during the reading process + */ + public static Map<String, byte[]> readZip(final File zipFile, + final boolean hasToIncludeDirectories) throws ZipException { + try { + return readZip(Files.readAllBytes(zipFile.toPath()), hasToIncludeDirectories); + } catch (final IOException e) { + throw new ZipException(String.format("Could not read the zip file '%s'", zipFile.getName()), e); + } + } + + /** + * Reads a zip file to a in memory structure formed by the file path and its bytes. The structure can contains only + * files or files and directories. If configured to include directories, only empty directories and directories that + * contains files will be included. The full directory tree will not be generated, eg: + * <pre> + * \ + * \..\Directory + * \..\..\ChildDirectory + * \..\..\..\aFile.txt + * \..\..\EmptyChildDirectory + * </pre> + * The return will include "Directory\ChildDirectory\aFile.txt" and "Directory\EmptyChildDirectory" but not + * "Directory" or the root. + * + * @param zipFileBytes the zip file byte array to read + * @param hasToIncludeDirectories includes or not the directories found during the zip reading. + * @return a Map representing a pair of file path and file byte array + * @throws ZipException when there was a problem during the reading process + */ + public static Map<String, byte[]> readZip(final byte[] zipFileBytes, + final boolean hasToIncludeDirectories) throws ZipException { + final Map<String, byte[]> filePathAndByteMap = new HashMap<>(); + + try (final ZipInputStream inputZipStream = ZipUtils.getInputStreamFromBytes(zipFileBytes)) { + byte[] fileByteContent; + String currentEntryName; + ZipEntry zipEntry; + while ((zipEntry = inputZipStream.getNextEntry()) != null) { + checkForZipSlipInRead(zipEntry); + currentEntryName = zipEntry.getName(); + fileByteContent = getBytes(inputZipStream); + if (zipEntry.isDirectory()) { + if (hasToIncludeDirectories) { + filePathAndByteMap.put(normalizeFolder(currentEntryName), null); + } + } else { + if (hasToIncludeDirectories) { + final Path parentFolderPath = Paths.get(zipEntry.getName()).getParent(); + if (parentFolderPath != null) { + filePathAndByteMap.putIfAbsent(normalizeFolder(parentFolderPath.toString()), null); + } + } + filePathAndByteMap.put(currentEntryName, fileByteContent); + } + } + } catch (final IOException e) { + LOGGER.warn("Could not close the zip input stream", e); + } + + return filePathAndByteMap; + } + + /** + * Adds a {@link File#separator} at the end of the folder path if not present. + * + * @param folderPath the folder to normalize + * @return the normalized folder + */ + private static String normalizeFolder(final String folderPath) { + final StringBuilder normalizedFolderBuilder = new StringBuilder(folderPath); + if(!folderPath.endsWith(File.separator)) { + normalizedFolderBuilder.append(File.separator); + } + return normalizedFolderBuilder.toString(); + } + + /** + * Converts a ZipInputStream in byte array. + * + * @param inputZipStream the zip input stream + * @return the byte array representing the input stream + * @throws ZipException when there was a problem parsing the input zip stream + */ + private static byte[] getBytes(final ZipInputStream inputZipStream) throws ZipException { + final byte[] fileByteContent; + try { + fileByteContent = IOUtils.toByteArray(inputZipStream); + } catch (final IOException e) { + throw new ZipException("Could not read bytes from file", e); + } + return fileByteContent; + } + + /** + * Unzips a zip file into an output folder. + * + * @param zipFilePath the zip file path + * @param outputFolder the output folder path + * @throws ZipException when there was a problem during the unzip process + */ + public static void unzip(final Path zipFilePath, final Path outputFolder) throws ZipException { + if (zipFilePath == null || outputFolder == null) { + return; + } + createDirectoryIfNotExists(outputFolder); + + final File zipFile = zipFilePath.toFile(); + try (final FileInputStream fileInputStream = new FileInputStream(zipFile); + final ZipInputStream stream = new ZipInputStream(fileInputStream)) { + + ZipEntry zipEntry; + while ((zipEntry = stream.getNextEntry()) != null) { + checkForZipSlipInExtraction(zipEntry, outputFolder); + final String fileName = zipEntry.getName(); + final Path fileToWritePath = Paths.get(outputFolder.toString(), fileName); + if (zipEntry.isDirectory()) { + createDirectoryIfNotExists(fileToWritePath); + } else { + writeFile(stream, fileToWritePath); + } + } + } catch (final FileNotFoundException e) { + throw new ZipException(String.format("Could not find file: '%s'", zipFile.getAbsolutePath()), e); + } catch (final IOException e) { + throw new ZipException( + String.format("An unexpected error occurred trying to unzip '%s'", zipFile.getAbsolutePath()), e); + } + } + + /** + * Writes a file from a zipInputStream to a path. Creates the file parent directories if they don't exist. + * @param zipInputStream the zip input stream + * @param fileToWritePath the file path to write + * @throws ZipException when there was a problem during the file creation + */ + private static void writeFile(final ZipInputStream zipInputStream, final Path fileToWritePath) throws ZipException { + final Path parentFolderPath = fileToWritePath.getParent(); + if (parentFolderPath != null) { + try { + Files.createDirectories(parentFolderPath); + } catch (final IOException e) { + throw new ZipException( + String.format("Could not create parent directories of '%s'", fileToWritePath.toString()), e); + } + } + try (final FileOutputStream outputStream = new FileOutputStream(fileToWritePath.toFile())) { + IOUtils.copy(zipInputStream, outputStream); + } catch (final FileNotFoundException e) { + throw new ZipException(String.format("Could not find file '%s'", fileToWritePath.toString()), e); + } catch (final IOException e) { + throw new ZipException( + String.format("An unexpected error has occurred while writing file '%s'", fileToWritePath.toString()) + , e); + } + } + + /** + * Creates the path directories if the provided path does not exists. + * + * @param path the path to create directories + * @throws ZipException when there was a problem to create the directories + */ + private static void createDirectoryIfNotExists(final Path path) throws ZipException { + if(path.toFile().exists()) { + return; + } + try { + Files.createDirectories(path); + } catch (final IOException e) { + throw new ZipException(String.format("Could not create directories for path '%s'", path.toString()), e); + } + } + + /** + * Zips a directory and its children content. + * + * @param fromPath the directory path to zip + * @param toZipFilePath the path to the zip file that will be created + * @throws ZipException when there was a problem during the zip process + */ + public static void createZipFromPath(final Path fromPath, final Path toZipFilePath) throws ZipException { + final Path createdZipFilePath; + try { + createdZipFilePath = Files.createFile(toZipFilePath); + } catch (final IOException e) { + throw new ZipException(String.format("Could not create file '%s'", toZipFilePath.toString()), e); + } + + try(final FileOutputStream fileOutputStream = new FileOutputStream(createdZipFilePath.toFile()); + final BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream); + final ZipOutputStream zipOut = new ZipOutputStream(bos); + final Stream<Path> walkStream = Files.walk(fromPath)) { + final Set<Path> allFilesSet = walkStream.collect(Collectors.toSet()); + for (final Path path : allFilesSet) { + checkForZipSlipInRead(path); + if (path.equals(fromPath)) { + continue; + } + final Path relativePath = fromPath.relativize(path); + final File file = path.toFile(); + if (file.isDirectory()) { + zipOut.putNextEntry(new ZipEntry(relativePath.toString() + File.separator)); + } else { + zipOut.putNextEntry(new ZipEntry(relativePath.toString())); + zipOut.write(Files.readAllBytes(path)); + } + zipOut.closeEntry(); + } + } catch (final FileNotFoundException e) { + throw new ZipException(String.format("Could not create file '%s'", toZipFilePath.toString()), e); + } catch (final IOException e) { + throw new ZipException("An error has occurred while creating the zip package", e); + } + } + +} diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipException.java b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipException.java new file mode 100644 index 0000000000..414b4823ad --- /dev/null +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipException.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation + * ================================================================================ + * Licensed 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.common.zip.exception; + +public class ZipException extends Exception { + + public ZipException(String s) { + super(s); + } + + public ZipException(String s, Throwable throwable) { + super(s, throwable); + } +} diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipSlipException.java b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipSlipException.java new file mode 100644 index 0000000000..203e357f8f --- /dev/null +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipSlipException.java @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation + * ================================================================================ + * Licensed 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.common.zip.exception; + +public class ZipSlipException extends ZipException { + + public ZipSlipException(final String filePath) { + super(String.format("Zip slip attempt detected in file: %s", filePath)); + } +} diff --git a/common-app-api/src/test/java/org/openecomp/sdc/common/util/ZipUtilTest.java b/common-app-api/src/test/java/org/openecomp/sdc/common/util/ZipUtilTest.java deleted file mode 100644 index 71e8d1509a..0000000000 --- a/common-app-api/src/test/java/org/openecomp/sdc/common/util/ZipUtilTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.sdc.common.util; - -import org.junit.Test; - -import java.util.Map; - -public class ZipUtilTest { - - // private ZipUtil createTestSubject() { - // return new ZipUtil(); - // } - - @Test - public void testReadZip() throws Exception { - byte[] zipAsBytes = new byte[] { ' ' }; - Map<String, byte[]> result; - - // default test - result = ZipUtil.readZip(zipAsBytes); - } - - @Test - public void testMain() throws Exception { - String[] args = new String[] { "" }; - - // default test - ZipUtil.main(args); - } - - @Test - public void testZipBytes() throws Exception { - byte[] input = new byte[] { ' ' }; - byte[] result; - - // default test - result = ZipUtil.zipBytes(input); - } - - @Test - public void testUnzip() throws Exception { - byte[] zipped = new byte[] { ' ' }; - byte[] result; - - // default test - result = ZipUtil.unzip(zipped); - } -} diff --git a/common-app-api/src/test/java/org/openecomp/sdc/common/zip/ZipUtilsTest.java b/common-app-api/src/test/java/org/openecomp/sdc/common/zip/ZipUtilsTest.java new file mode 100644 index 0000000000..d5fb3dcc8b --- /dev/null +++ b/common-app-api/src/test/java/org/openecomp/sdc/common/zip/ZipUtilsTest.java @@ -0,0 +1,172 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation + * ================================================================================ + * Licensed 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.common.zip; + +import static org.hamcrest.Matchers.aMapWithSize; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isIn; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.openecomp.sdc.common.zip.exception.ZipException; +import org.openecomp.sdc.common.zip.exception.ZipSlipException; + +public class ZipUtilsTest { + + @Test + public void testZipSlipInRead() { + final byte[] windowsZipBytes; + final byte[] linuxZipBytes; + try { + final InputStream linuxZipAsStream = ZipUtilsTest.class.getClassLoader().getResourceAsStream("zip-slip/zip-slip-linux.zip"); + final InputStream windowsZipAsStream = ZipUtilsTest.class.getClassLoader().getResourceAsStream("zip-slip/zip-slip-windows.zip"); + if(linuxZipAsStream == null || windowsZipAsStream == null) { + fail("Could not load the zip slip files"); + } + linuxZipBytes = IOUtils.toByteArray(linuxZipAsStream); + windowsZipBytes = IOUtils.toByteArray(windowsZipAsStream); + } catch (final IOException e) { + e.printStackTrace(); + fail("Could not load the required zip slip files"); + return; + } + + try { + ZipUtils.readZip(linuxZipBytes, true); + fail("Zip slip should be detected"); + } catch (final ZipException ex) { + assertThat("Expected ZipSlipException", ex, is(instanceOf(ZipSlipException.class))); + } + + try { + ZipUtils.readZip(windowsZipBytes, true); + fail("Zip slip should be detected"); + } catch (final ZipException ex) { + assertThat("Expected ZipSlipException", ex, is(instanceOf(ZipSlipException.class))); + } + } + + @Test + public void testZipSlipInUnzip() throws IOException { + final Path tempDirectoryWindows = Files.createTempDirectory("zipSlipWindows" + System.currentTimeMillis()); + final Path tempDirectoryLinux = Files.createTempDirectory("zipSlipLinux" + System.currentTimeMillis()); + try { + final Path linuxZipPath; + final Path windowsZipPath; + try { + linuxZipPath = Paths + .get(ZipUtilsTest.class.getClassLoader().getResource("zip-slip/zip-slip-linux.zip").toURI()); + windowsZipPath = Paths + .get(ZipUtilsTest.class.getClassLoader().getResource("zip-slip/zip-slip-windows.zip").toURI()); + } catch (final URISyntaxException e) { + fail("Could not load the required zip slip files"); + return; + } + + try { + ZipUtils.unzip(windowsZipPath, tempDirectoryWindows); + ZipUtils.unzip(linuxZipPath, tempDirectoryLinux); + fail("Zip slip should be detected"); + } catch (final ZipException ex) { + assertThat("At least one of the zip files should throw ZipSlipException", + ex, is(instanceOf(ZipSlipException.class))); + } + } finally { + org.apache.commons.io.FileUtils.deleteDirectory(tempDirectoryLinux.toFile()); + org.apache.commons.io.FileUtils.deleteDirectory(tempDirectoryWindows.toFile()); + } + } + + @Test + public void testUnzipAndZip() throws IOException, ZipException { + final Path unzipTempPath = Files.createTempDirectory("testUnzip"); + final Path zipTempPath = Files.createTempDirectory("testZip"); + final Path testZipPath; + try { + try { + testZipPath = Paths + .get(ZipUtilsTest.class.getClassLoader().getResource("zip/extract-test.zip").toURI()); + ZipUtils.unzip(testZipPath, unzipTempPath); + } catch (final URISyntaxException e) { + fail("Could not load the required zip file"); + return; + } + + final Set<Path> expectedPaths = new HashSet<>(); + expectedPaths.add(Paths.get(unzipTempPath.toString(),"rootFile1.txt")); + expectedPaths.add(Paths.get(unzipTempPath.toString(),"rootFileNoExtension")); + expectedPaths.add(Paths.get(unzipTempPath.toString(),"EmptyFolder")); + expectedPaths.add(Paths.get(unzipTempPath.toString(), "SingleLvlFolder")); + expectedPaths.add(Paths.get(unzipTempPath.toString(), "SingleLvlFolder", "singleLvlFolderFile.txt")); + expectedPaths.add(Paths.get(unzipTempPath.toString(), "SingleLvlFolder", "singleLvlFolderFileNoExtension")); + expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder")); + expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder", "twoLvlFolderFile.txt")); + expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder", "twoLvlFolderFileNoExtension")); + expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder", "SingleLvlFolder")); + expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder", "SingleLvlFolder", "singleLvlFolderFile.txt")); + expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder", "SingleLvlFolder", "singleLvlFolderFileNoExtension")); + + final AtomicLong actualPathCount = new AtomicLong(0); + try (Stream<Path> stream = Files.walk(unzipTempPath)) { + stream.filter(path -> !unzipTempPath.equals(path)).forEach(actualPath -> { + actualPathCount.getAndIncrement(); + assertThat("Unzipped file should be in the expected list", actualPath, isIn(expectedPaths)); + }); + } + assertThat("The number of unzipped files should be as expected", actualPathCount.get(), is((long) expectedPaths.size())); + final Path zipFilePath = zipTempPath.resolve("testzip.zip"); + ZipUtils.createZipFromPath(unzipTempPath, zipFilePath); + final Map<String, byte[]> fileMap = ZipUtils.readZip(zipFilePath.toFile(), true); + //matching the folder pattern of the readZip + final Set<String> expectedPathStringSet = expectedPaths.stream() + .map(path -> { + final Path relativePath = unzipTempPath.relativize(path); + return path.toFile().isDirectory() ? relativePath.toString() + File.separator : relativePath.toString(); + }).collect(Collectors.toSet()); + assertThat("The number of zipped files should be as expected", fileMap, aMapWithSize(expectedPathStringSet.size())); + fileMap.keySet().forEach(s -> { + assertThat("File in zip package should be in the expected list", s, isIn(expectedPathStringSet)); + }); + } finally { + FileUtils.deleteDirectory(unzipTempPath.toFile()); + FileUtils.deleteDirectory(zipTempPath.toFile()); + } + } + + + +}
\ No newline at end of file diff --git a/common-app-api/src/test/resources/zip-slip/zip-slip-linux.zip b/common-app-api/src/test/resources/zip-slip/zip-slip-linux.zip Binary files differnew file mode 100644 index 0000000000..38b3f499de --- /dev/null +++ b/common-app-api/src/test/resources/zip-slip/zip-slip-linux.zip diff --git a/common-app-api/src/test/resources/zip-slip/zip-slip-windows.zip b/common-app-api/src/test/resources/zip-slip/zip-slip-windows.zip Binary files differnew file mode 100644 index 0000000000..3474c88bec --- /dev/null +++ b/common-app-api/src/test/resources/zip-slip/zip-slip-windows.zip diff --git a/common-app-api/src/test/resources/zip/extract-test.zip b/common-app-api/src/test/resources/zip/extract-test.zip Binary files differnew file mode 100644 index 0000000000..880452fdc7 --- /dev/null +++ b/common-app-api/src/test/resources/zip/extract-test.zip diff --git a/common-be/pom.xml b/common-be/pom.xml index f4b9ebf176..025e3a9ec0 100644 --- a/common-be/pom.xml +++ b/common-be/pom.xml @@ -17,7 +17,7 @@ <groupId>org.openecomp.sdc</groupId> <artifactId>common-app-api</artifactId> <version>${project.version}</version> - <scope>provided</scope> + <scope>compile</scope> </dependency> <dependency> diff --git a/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/CommonUtil.java b/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/CommonUtil.java index bb26e6a2b9..eb60d95889 100644 --- a/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/CommonUtil.java +++ b/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/CommonUtil.java @@ -34,8 +34,8 @@ import org.apache.commons.beanutils.BeanUtils; public class CommonUtil { - private static final String DEFAULT = "default"; - private static final String UNDERSCORE_DEFAULT = "_default"; + public static final String DEFAULT = "default"; + public static final String UNDERSCORE_DEFAULT = "_default"; private static ImmutableSet<Class<?>> complexClassType = ImmutableSet.of(Map.class, String.class, Integer.class, Float.class, Double.class, Set.class, Object.class, List.class); diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/data/PackageArchive.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/data/PackageArchive.java index 97bc375eb8..4f4258ad53 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/data/PackageArchive.java +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/data/PackageArchive.java @@ -19,7 +19,6 @@ */ package org.openecomp.sdcrests.vsp.rest.data; -import java.io.IOException; import java.security.cert.CertificateException; import java.util.List; import java.util.Map; @@ -29,6 +28,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.openecomp.core.utilities.file.FileContentHandler; import org.openecomp.sdc.common.utils.CommonUtil; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.logging.api.Logger; import org.openecomp.sdc.logging.api.LoggerFactory; import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager; @@ -61,7 +61,7 @@ public class PackageArchive { try { handlerPair = CommonUtil.getFileContentMapFromOrchestrationCandidateZip( outerPackageFileBytes); - } catch (IOException exception) { + } catch (final ZipException exception) { LOG.error("Error reading files inside archive", exception); } } diff --git a/openecomp-be/backend/openecomp-sdc-validation-manager/src/main/java/org/openecomp/sdc/validation/impl/UploadValidationManagerImpl.java b/openecomp-be/backend/openecomp-sdc-validation-manager/src/main/java/org/openecomp/sdc/validation/impl/UploadValidationManagerImpl.java index 42c77b96d8..90f8ad369b 100644 --- a/openecomp-be/backend/openecomp-sdc-validation-manager/src/main/java/org/openecomp/sdc/validation/impl/UploadValidationManagerImpl.java +++ b/openecomp-be/backend/openecomp-sdc-validation-manager/src/main/java/org/openecomp/sdc/validation/impl/UploadValidationManagerImpl.java @@ -20,7 +20,11 @@ package org.openecomp.sdc.validation.impl; -import org.apache.commons.collections4.CollectionUtils; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import java.util.Objects; import org.apache.commons.collections4.MapUtils; import org.openecomp.core.utilities.file.FileContentHandler; import org.openecomp.core.utilities.file.FileUtils; @@ -30,6 +34,8 @@ import org.openecomp.sdc.common.errors.ErrorCategory; import org.openecomp.sdc.common.errors.ErrorCode; import org.openecomp.sdc.common.errors.Messages; import org.openecomp.sdc.common.utils.SdcCommon; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.datatypes.error.ErrorMessage; import org.openecomp.sdc.heat.datatypes.structure.ValidationStructureList; import org.openecomp.sdc.heat.services.tree.HeatTreeManager; @@ -38,79 +44,35 @@ import org.openecomp.sdc.validation.UploadValidationManager; import org.openecomp.sdc.validation.types.ValidationFileResponse; import org.openecomp.sdc.validation.util.ValidationManagerUtil; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - /** * Created by TALIO on 4/20/2016. */ public class UploadValidationManagerImpl implements UploadValidationManager { - private static FileContentHandler getFileContentMapFromZip(byte[] uploadFileData) - throws IOException, CoreException { - - ZipEntry zipEntry; - List<String> folderList = new ArrayList<>(); - FileContentHandler mapFileContent = new FileContentHandler(); - try (ZipInputStream inputZipStream = new ZipInputStream(new ByteArrayInputStream(uploadFileData))) { - - byte[] fileByteContent; - String currentEntryName; - - while ((zipEntry = inputZipStream.getNextEntry()) != null) { - currentEntryName = zipEntry.getName(); - // else, get the file content (as byte array) and save it in a map. - fileByteContent = FileUtils.toByteArray(inputZipStream); - - int index = lastIndexFileSeparatorIndex(currentEntryName); - String currSubstringWithoutSeparator = - currentEntryName.substring(index + 1, currentEntryName.length()); - if (index != -1) { - if (currSubstringWithoutSeparator.length() > 0) { - mapFileContent.addFile(currentEntryName.substring(index + 1, currentEntryName.length()), - fileByteContent); - } else { - folderList.add(currentEntryName); - } - } else { - mapFileContent.addFile(currentEntryName, fileByteContent); - } - } - } catch (RuntimeException exception) { - throw new IOException(exception); + + private static FileContentHandler getFileContentMapFromZip(byte[] uploadFileData) throws IOException { + final Map<String, byte[]> zipFileAndByteMap; + try { + zipFileAndByteMap = ZipUtils.readZip(uploadFileData, true); + } catch (final ZipException e) { + throw new IOException(e); } - if (CollectionUtils.isNotEmpty(folderList)) { + final boolean zipHasFolders = zipFileAndByteMap.values().stream().anyMatch(Objects::isNull); + if (zipHasFolders) { throw new CoreException((new ErrorCode.ErrorCodeBuilder()) .withMessage(Messages.ZIP_SHOULD_NOT_CONTAIN_FOLDERS.getErrorMessage()) .withId(Messages.ZIP_SHOULD_NOT_CONTAIN_FOLDERS.getErrorMessage()) .withCategory(ErrorCategory.APPLICATION).build()); - } + final FileContentHandler mapFileContent = new FileContentHandler(); + zipFileAndByteMap.entrySet().stream() + .filter(entry -> entry.getValue() != null) + .forEach(zipEntry -> mapFileContent.addFile(zipEntry.getKey(), zipEntry.getValue())); return mapFileContent; } - private static int lastIndexFileSeparatorIndex(String filePath) { - int length = filePath.length() - 1; - - for (int i = length; i >= 0; i--) { - char currChar = filePath.charAt(i); - if (currChar == '/' || currChar == File.separatorChar || currChar == File.pathSeparatorChar) { - return i; - } - } - // if we've reached to the start of the string and didn't find file separator - return -1 - return -1; - } - @Override public ValidationFileResponse validateFile(String type, InputStream fileToValidate) throws IOException { diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/OrchestrationTemplateCSARHandler.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/OrchestrationTemplateCSARHandler.java index 61d1799aa0..8f0029aa83 100644 --- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/OrchestrationTemplateCSARHandler.java +++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/OrchestrationTemplateCSARHandler.java @@ -32,6 +32,7 @@ import org.openecomp.sdc.common.errors.CoreException; import org.openecomp.sdc.common.errors.Messages; import org.openecomp.sdc.common.utils.CommonUtil; import org.openecomp.sdc.common.utils.SdcCommon; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.datatypes.error.ErrorLevel; import org.openecomp.sdc.datatypes.error.ErrorMessage; import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData; @@ -58,7 +59,7 @@ public class OrchestrationTemplateCSARHandler extends BaseOrchestrationTemplateH folderList = fileContentMapFromOrchestrationCandidateZip.getRight(); Validator validator = ValidatorFactory.getValidator(contentMap); uploadFileResponse.addStructureErrors(validator.validateContent(contentMap, folderList)); - } catch (IOException exception) { + } catch (final ZipException | IOException exception) { logger.error(exception.getMessage(), exception); uploadFileResponse.addStructureError( SdcCommon.UPLOAD_FILE, diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java index 122809896e..7a183c0dbb 100644 --- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java +++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java @@ -18,7 +18,9 @@ package org.openecomp.sdc.vendorsoftwareproduct.upload.csar; import static junit.framework.TestCase.assertTrue; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; @@ -161,7 +163,7 @@ public class UploadCSARFileTest { onboardPackageInfo = new OnboardPackageInfo(csarFileName, OnboardingTypesEnum.CSAR.toString(), convertFileInputStream(inputStream)); uploadFileResponse = candidateManager.upload(vspDetails, onboardPackageInfo); - assertEquals(expectedErrorsNumber, uploadFileResponse.getErrors().size()); + assertThat(String.format("Expecting %s error(s) in file '%s'", expectedErrorsNumber, csarFileName), uploadFileResponse.getErrors().size(), is(expectedErrorsNumber)); } return uploadFileResponse; } diff --git a/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/utils/CommonUtil.java b/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/utils/CommonUtil.java index ae7d44efd8..8610ecb74b 100644 --- a/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/utils/CommonUtil.java +++ b/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/utils/CommonUtil.java @@ -20,62 +20,50 @@ package org.openecomp.sdc.common.utils; import com.google.common.collect.Multimap; - +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.openecomp.core.utilities.file.FileContentHandler; -import org.openecomp.core.utilities.file.FileUtils; import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum; import org.openecomp.sdc.common.errors.CoreException; import org.openecomp.sdc.common.errors.ErrorCategory; import org.openecomp.sdc.common.errors.ErrorCode; import org.openecomp.sdc.common.errors.Messages; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipInputStream; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; public class CommonUtil { - static final String DEFAULT = "default"; - static final String _DEFAULT = "_default"; private CommonUtil() { // prevent instantiation } - public static FileContentHandler validateAndUploadFileContent(OnboardingTypesEnum type, - byte[] uploadedFileData) - throws IOException { - return getFileContentMapFromOrchestrationCandidateZipAndValidateNoFolders(type, - uploadedFileData); - } - /** - * Gets files out of the zip AND validates zip is flat (no folders) + * Reads the files from the zip AND validates zip is flat (no folders). * - * @param uploadFileData zip file + * @param type the onboarding type + * @param uploadedFileData zip file bytes * @return FileContentHandler if input is valid and has no folders + * @throws IOException when the zip could not be read */ - private static FileContentHandler getFileContentMapFromOrchestrationCandidateZipAndValidateNoFolders( - OnboardingTypesEnum type, byte[] uploadFileData) - throws IOException { - Pair<FileContentHandler, List<String>> pair = - getFileContentMapFromOrchestrationCandidateZip(uploadFileData); - + public static FileContentHandler validateAndUploadFileContent(final OnboardingTypesEnum type, + final byte[] uploadedFileData) throws IOException { + final Pair<FileContentHandler, List<String>> pair; + try { + pair = getFileContentMapFromOrchestrationCandidateZip(uploadedFileData); + } catch (final ZipException e) { + throw new IOException(e); + } if (isFileOriginFromZip(type.toString())) { validateNoFolders(pair.getRight()); } @@ -84,47 +72,22 @@ public class CommonUtil { } public static Pair<FileContentHandler, List<String>> getFileContentMapFromOrchestrationCandidateZip( - byte[] uploadFileData) - throws IOException { - ZipEntry zipEntry; - List<String> folderList = new ArrayList<>(); - FileContentHandler mapFileContent = new FileContentHandler(); - try (ByteArrayInputStream in = new ByteArrayInputStream(uploadFileData); - ZipInputStream inputZipStream = new ZipInputStream(in)) { - byte[] fileByteContent; - String currentEntryName; - - while ((zipEntry = inputZipStream.getNextEntry()) != null) { - assertEntryNotVulnerable(zipEntry); - currentEntryName = zipEntry.getName(); - fileByteContent = FileUtils.toByteArray(inputZipStream); - - int index = lastIndexFileSeparatorIndex(currentEntryName); - if (index != -1) { - folderList.add(currentEntryName); - } - if (isFile(currentEntryName)) { - mapFileContent.addFile(currentEntryName, fileByteContent); - } + byte[] uploadFileData) throws ZipException { + final Map<String, byte[]> zipFileMap = ZipUtils.readZip(uploadFileData, true); + final List<String> folderList = new ArrayList<>(); + final FileContentHandler mapFileContent = new FileContentHandler(); + + zipFileMap.forEach((key, value) -> { + if (value == null) { + folderList.add(key); + } else { + mapFileContent.addFile(key, value); } - - } catch (RuntimeException exception) { - throw new IOException(exception); - } + }); return new ImmutablePair<>(mapFileContent, folderList); } - private static void assertEntryNotVulnerable(ZipEntry entry) throws ZipException { - if (entry.getName().contains("../")) { - throw new ZipException("Path traversal attempt discovered."); - } - } - - private static boolean isFile(String currentEntryName) { - return !(currentEntryName.endsWith("\\") || currentEntryName.endsWith("/")); - } - private static void validateNoFolders(List<String> folderList) { if (CollectionUtils.isNotEmpty(folderList)) { throw new CoreException((new ErrorCode.ErrorCodeBuilder()) @@ -134,19 +97,6 @@ public class CommonUtil { } } - private static int lastIndexFileSeparatorIndex(String filePath) { - int length = filePath.length() - 1; - - for (int i = length; i >= 0; i--) { - char currChar = filePath.charAt(i); - if (currChar == '/' || currChar == File.separatorChar || currChar == File.pathSeparatorChar) { - return i; - } - } - // if we've reached to the start of the string and didn't find file separator - return -1 - return -1; - } - private static boolean validateFilesExtensions(Set<String> allowedExtensions, FileContentHandler files) { for (String fileName : files.getFileList()) { diff --git a/openecomp-be/lib/openecomp-common-lib/src/test/java/org/openecomp/sdc/common/utils/CommonUtilTest.java b/openecomp-be/lib/openecomp-common-lib/src/test/java/org/openecomp/sdc/common/utils/CommonUtilTest.java index bc0bd137a0..119616a9be 100644 --- a/openecomp-be/lib/openecomp-common-lib/src/test/java/org/openecomp/sdc/common/utils/CommonUtilTest.java +++ b/openecomp-be/lib/openecomp-common-lib/src/test/java/org/openecomp/sdc/common/utils/CommonUtilTest.java @@ -16,23 +16,21 @@ package org.openecomp.sdc.common.utils; -import org.testng.annotations.Test; +import static org.onap.sdc.tosca.services.CommonUtil.DEFAULT; +import static org.onap.sdc.tosca.services.CommonUtil.UNDERSCORE_DEFAULT; +import static org.testng.Assert.assertTrue; import java.util.HashMap; import java.util.Map; - -import static org.testng.Assert.assertTrue; +import org.testng.annotations.Test; public class CommonUtilTest { @Test public void testGetObjectAsMap() { - Map<String, String> obj = new HashMap<>(1); - obj.put(CommonUtil.DEFAULT, ""); - Map<String, Object> newMap = CommonUtil.getObjectAsMap(obj); - - boolean exists = newMap.containsKey(CommonUtil._DEFAULT); - - assertTrue(exists); + final Map<String, String> obj = new HashMap<>(1); + obj.put(DEFAULT, ""); + assertTrue(CommonUtil.getObjectAsMap(obj).containsKey(UNDERSCORE_DEFAULT)); } + } diff --git a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/pom.xml b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/pom.xml index ce88037706..b86964f61f 100644 --- a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/pom.xml +++ b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/pom.xml @@ -66,6 +66,18 @@ <version>${commons.codec.version}</version> </dependency> <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest</artifactId> + <version>${hamcrest.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-library</artifactId> + <version>${hamcrest.version}</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> @@ -85,6 +97,12 @@ <artifactId>openecomp-sdc-logging-api</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.openecomp.sdc</groupId> + <artifactId>common-app-api</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> </dependencies> </project> diff --git a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/main/java/org/openecomp/core/utilities/file/FileUtils.java b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/main/java/org/openecomp/core/utilities/file/FileUtils.java index c807d1b979..31338dcda4 100644 --- a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/main/java/org/openecomp/core/utilities/file/FileUtils.java +++ b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/main/java/org/openecomp/core/utilities/file/FileUtils.java @@ -16,11 +16,6 @@ package org.openecomp.core.utilities.file; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.onap.sdc.tosca.services.YamlUtil; -import org.openecomp.core.utilities.json.JsonUtil; - import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; @@ -28,11 +23,20 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.file.Path; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.function.Function; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipInputStream; -import java.util.*; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.onap.sdc.tosca.services.YamlUtil; +import org.openecomp.core.utilities.json.JsonUtil; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; /** * The type File utils. @@ -220,26 +224,14 @@ public class FileUtils { * * @param zipData the zip data * @return the file content map from zip - * @throws IOException the io exception + * @throws ZipException when an error occurs while extracting zip files */ - public static FileContentHandler getFileContentMapFromZip(byte[] zipData) throws IOException { - - try (ZipInputStream inputZipStream = new ZipInputStream(new ByteArrayInputStream(zipData))) { - - FileContentHandler mapFileContent = new FileContentHandler(); - - ZipEntry zipEntry; - - while ((zipEntry = inputZipStream.getNextEntry()) != null) { - assertEntryNotVulnerable(zipEntry); - mapFileContent.addFile(zipEntry.getName(), FileUtils.toByteArray(inputZipStream)); - } - - return mapFileContent; - - } catch (RuntimeException exception) { - throw new IOException(exception); - } + public static FileContentHandler getFileContentMapFromZip(byte[] zipData) + throws ZipException { + final Map<String, byte[]> zipFileAndByteMap = ZipUtils.readZip(zipData, true); + final FileContentHandler mapFileContent = new FileContentHandler(); + mapFileContent.setFiles(zipFileAndByteMap); + return mapFileContent; } @@ -286,20 +278,28 @@ public class FileUtils { * @return a map containing file names and their absolute paths * @throws IOException the io exception */ - public static Map<String, String> writeFilesFromFileContentHandler(FileContentHandler - fileContentHandler, - Path dir) - throws IOException { - + public static Map<String, String> writeFilesFromFileContentHandler(final FileContentHandler fileContentHandler, + final Path dir) throws IOException { File file; - File dirFile = dir.toFile(); - Map<String, String> filePaths = new HashMap<>(); - for (Map.Entry<String, byte[]> fileEntry : fileContentHandler.getFiles().entrySet()) { + final File dirFile = dir.toFile(); + final Map<String, String> filePaths = new HashMap<>(); + for (final Map.Entry<String, byte[]> fileEntry : fileContentHandler.getFiles().entrySet()) { file = new File(dirFile, fileEntry.getKey()); - file.getParentFile().mkdirs(); filePaths.put(fileEntry.getKey(), file.getAbsolutePath()); - try (FileOutputStream fop = new FileOutputStream(file.getAbsolutePath());) { - fop.write(fileEntry.getValue()); + final byte[] fileBytes = fileEntry.getValue(); + if (fileBytes == null) { + if (!file.exists() && !file.mkdirs()) { + throw new IOException("Could not create directory " + file.getAbsolutePath()); + } + continue; + } else { + if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) { + throw new IOException("Could not create parent directory for " + file.getAbsolutePath()); + } + } + + try (final FileOutputStream fop = new FileOutputStream(file.getAbsolutePath());) { + fop.write(fileBytes); fop.flush(); } } @@ -318,10 +318,4 @@ public class FileUtils { fileExtension.equalsIgnoreCase(FileExtension.YAML.getDisplayName()); } - private static void assertEntryNotVulnerable(ZipEntry entry) throws ZipException { - if (entry.getName().contains("../")) { - throw new ZipException("Path traversal attempt discovered."); - } - } - } diff --git a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/test/java/org/openecomp/core/utilities/file/FileUtilsTest.java b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/test/java/org/openecomp/core/utilities/file/FileUtilsTest.java index a4928ac739..facfe57622 100644 --- a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/test/java/org/openecomp/core/utilities/file/FileUtilsTest.java +++ b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/test/java/org/openecomp/core/utilities/file/FileUtilsTest.java @@ -17,8 +17,12 @@ package org.openecomp.core.utilities.file; import static junit.framework.TestCase.assertTrue; -import static org.junit.Assert.assertEquals; +import static org.hamcrest.Matchers.aMapWithSize; +import static org.hamcrest.Matchers.anEmptyMap; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; import java.io.File; import java.io.IOException; @@ -34,6 +38,7 @@ import java.util.stream.Stream; import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; +import org.openecomp.sdc.common.zip.exception.ZipException; /** * @author EVITALIY @@ -74,25 +79,22 @@ public class FileUtilsTest { } @Test - public void testWriteFilesFromFileContentHandler() throws IOException { - Path dir = Files.createTempDirectory("CSAR_" + System.currentTimeMillis()); + public void testWriteFilesFromFileContentHandler() throws IOException, ZipException { + final Path tempDirectory = Files.createTempDirectory("CSAR_" + System.currentTimeMillis()); try { - byte[] uploadedFileData = IOUtils.toByteArray( - FileUtilsTest.class.getResource("resource-Spgw-csar-ZTE" + - ".csar")); - FileContentHandler contentMap = FileUtils.getFileContentMapFromZip(uploadedFileData); - Map<String, String> filePaths = FileUtils.writeFilesFromFileContentHandler(contentMap, - dir); - - assertFalse(filePaths.isEmpty()); - assertEquals(filePaths.size(), 18); - for (Map.Entry<String, String> fileEntry : filePaths.entrySet()) { - File f = new File(fileEntry.getValue()); - assertTrue(f.exists()); + byte[] uploadedFileData = + IOUtils.toByteArray(FileUtilsTest.class.getResource("resource-Spgw-csar-ZTE.csar")); + final FileContentHandler contentMap = FileUtils.getFileContentMapFromZip(uploadedFileData); + final Map<String, String> filePaths = FileUtils.writeFilesFromFileContentHandler(contentMap, tempDirectory); + + assertThat("The file map should not be empty", filePaths, is(not(anEmptyMap()))); + assertThat("The file map should have size 20", filePaths, is(aMapWithSize(20))); + for (final Map.Entry<String, String> fileEntry : filePaths.entrySet()) { + final File f = new File(fileEntry.getValue()); + assertThat(String.format("The file '%s' is expected to", f.getAbsolutePath()), f.exists(), is(true)); } - } - finally { - org.apache.commons.io.FileUtils.deleteDirectory(dir.toFile()); + } finally { + org.apache.commons.io.FileUtils.deleteDirectory(tempDirectory.toFile()); } } @@ -106,22 +108,22 @@ public class FileUtilsTest { @Test public void testGetFileWithoutExtention() { - Assert.assertEquals(FileUtils.getFileWithoutExtention("test.txt"), "test"); + Assert.assertEquals("test", FileUtils.getFileWithoutExtention("test.txt")); } @Test public void testGetFileWithoutExtentionContainsNoExtension() { - Assert.assertEquals(FileUtils.getFileWithoutExtention("test"), "test"); + Assert.assertEquals("test", FileUtils.getFileWithoutExtention("test")); } @Test public void testGetFileExtention() { - Assert.assertEquals(FileUtils.getFileExtension("test.txt"), "txt"); + Assert.assertEquals("txt", FileUtils.getFileExtension("test.txt")); } @Test public void testGetNetworkPackageName() { - Assert.assertEquals(FileUtils.getNetworkPackageName("heat.zip"), "heat"); + Assert.assertEquals("heat", FileUtils.getNetworkPackageName("heat.zip")); } @Test @@ -191,6 +193,6 @@ public class FileUtilsTest { } Assert.assertNotNull(inputStream); - Assert.assertEquals(builder.toString(), "hello-test"); + Assert.assertEquals("hello-test", builder.toString()); } } diff --git a/openecomp-be/lib/openecomp-sdc-enrichment-lib/openecomp-sdc-enrichment-impl/src/main/java/org/openecomp/sdc/enrichment/impl/external/artifact/MonitoringMibEnricher.java b/openecomp-be/lib/openecomp-sdc-enrichment-lib/openecomp-sdc-enrichment-impl/src/main/java/org/openecomp/sdc/enrichment/impl/external/artifact/MonitoringMibEnricher.java index dac9eae9ad..ca1fbe11b7 100644 --- a/openecomp-be/lib/openecomp-sdc-enrichment-lib/openecomp-sdc-enrichment-impl/src/main/java/org/openecomp/sdc/enrichment/impl/external/artifact/MonitoringMibEnricher.java +++ b/openecomp-be/lib/openecomp-sdc-enrichment-lib/openecomp-sdc-enrichment-impl/src/main/java/org/openecomp/sdc/enrichment/impl/external/artifact/MonitoringMibEnricher.java @@ -16,6 +16,19 @@ package org.openecomp.sdc.enrichment.impl.external.artifact; +import static org.openecomp.sdc.tosca.services.ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME; +import static org.openecomp.sdc.tosca.services.ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; import org.onap.sdc.tosca.datatypes.model.Directive; import org.onap.sdc.tosca.datatypes.model.NodeTemplate; import org.onap.sdc.tosca.datatypes.model.ServiceTemplate; @@ -29,6 +42,7 @@ import org.openecomp.core.model.types.ServiceArtifact; import org.openecomp.core.utilities.file.FileContentHandler; import org.openecomp.core.utilities.file.FileUtils; import org.openecomp.sdc.common.errors.Messages; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.datatypes.error.ErrorLevel; import org.openecomp.sdc.datatypes.error.ErrorMessage; import org.openecomp.sdc.enrichment.EnrichmentInfo; @@ -45,13 +59,6 @@ import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentEntity; import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentMonitoringUploadEntity; import org.openecomp.sdc.versioning.dao.types.Version; -import java.io.File; -import java.io.IOException; -import java.util.*; - -import static org.openecomp.sdc.tosca.services.ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME; -import static org.openecomp.sdc.tosca.services.ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME; - public class MonitoringMibEnricher implements ExternalArtifactEnricherInterface { private EnrichedServiceModelDao enrichedServiceModelDao; @@ -265,8 +272,8 @@ public class MonitoringMibEnricher implements ExternalArtifactEnricherInterface try { mibs = FileUtils .getFileContentMapFromZip(FileUtils.toByteArray(monitoringArtifactInfo.getContent())); - } catch (IOException ioException) { - log.error("Failed to get file content map from zip ", ioException); + } catch (ZipException ex) { + log.error("Failed to get file content map from zip ", ex); ErrorMessage.ErrorMessageUtil .addMessage(mibServiceArtifact.getName() + "." + type.name(), errors) .add(new ErrorMessage(ErrorLevel.ERROR, Messages.INVALID_ZIP_FILE.getErrorMessage())); diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java index e112ef432c..22ac1e8ed8 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java @@ -18,17 +18,21 @@ package org.openecomp.core.externaltesting.impl; import com.amdocs.zusammen.utils.fileutils.json.JsonUtil; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableSet; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; +import java.util.Map.Entry; import lombok.EqualsAndHashCode; -import org.apache.commons.io.IOUtils; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.onap.sdc.tosca.services.YamlUtil; import org.openecomp.core.externaltesting.api.*; import org.openecomp.core.externaltesting.errors.ExternalTestingException; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.heat.datatypes.manifest.FileData; import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent; import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager; @@ -58,7 +62,6 @@ import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; public class ExternalTestingManagerImpl implements ExternalTestingManager { @@ -97,6 +100,8 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { private static final String SDC_CSAR = "sdc-csar"; private static final String SDC_HEAT = "sdc-heat"; + private final ImmutableSet<String> relevantArchiveFileExtensionSet = + ImmutableSet.of("yaml", "meta", "yml", "json", "env"); private VersioningManager versioningManager; @@ -721,10 +726,8 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { private void processArchive(final VtpTestExecutionRequest test, final MultiValueMap<String, Object> body, final byte[] zip) { // We need to make one pass through the zip input stream. Pull out files that match our expectations into a temporary - // map that we can process over. These are not huge files so we shouldn't need to worry about memory. - - List<String> extensions = Arrays.asList(".yaml", ".meta", ".yml", ".json", ".env"); - final Map<String, byte[]> contentWeCareAbout = extractRelevantContent(zip, extensions); + // map that we can process over. These are not huge files so we shouldn't need to worry about memory. + final Map<String, byte[]> contentWeCareAbout = extractRelevantContent(zip); // VTP does not support concurrent executions of the same test with the same associated file name. // It writes files to /tmp and if we were to send two requests with the same file, the results are unpredictable. @@ -891,34 +894,30 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { * @param zip csar/heat zip to iterate over * @return relevant content from the archive file as a map. */ - private Map<String, byte[]> extractRelevantContent(final byte[] zip, final List<String> extensions) { - final Map<String, byte[]> rv = new HashMap<>(); // FYI, rv = return value. - try (ByteArrayInputStream is = new ByteArrayInputStream(zip)) { - try (ZipInputStream zipStream = new ZipInputStream(is)) { - ZipEntry entry; - while ((entry = zipStream.getNextEntry()) != null) { - final String entryName = entry.getName(); - - // NOTE: leaving this debugging in for dublin... - logger.debug("archive contains entry {}", entryName); - - extractIfMatching(extensions, rv, zipStream, entryName); - } - } - } - catch (IOException ex) { - logger.error("error encountered processing archive", ex); - throw new ExternalTestingException(SDC_RESOLVER_ERR, 500, ex.getMessage()); + private Map<String, byte[]> extractRelevantContent(final byte[] zip) { + final Map<String, byte[]> zipFileAndByteMap; + try { + zipFileAndByteMap = ZipUtils.readZip(zip, false); + } catch (final ZipException ex) { + logger.error("An error occurred while processing archive", ex); + throw new ExternalTestingException(SDC_RESOLVER_ERR, 500, ex.getMessage(), ex); } - return rv; + + return zipFileAndByteMap.entrySet().stream() + .filter(stringEntry -> hasRelevantExtension(stringEntry.getKey())) + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - private void extractIfMatching(List<String> extensions, Map<String, byte[]> rv, ZipInputStream zipStream, String entryName) throws IOException { - int idx = entryName.lastIndexOf('.'); - if ((idx >= 0) && (extensions.contains(entryName.substring(idx)))) { - byte[] content = IOUtils.toByteArray(zipStream); - rv.put(entryName, content); - } + /** + * Checks if the file matches with a expected extension. + * + * @param filePath the file path + * @return {@code true} if the file extension matches with {@link #relevantArchiveFileExtensionSet}, {@code false} + * otherwise + */ + private boolean hasRelevantExtension(final String filePath) { + final String entryExtension = FilenameUtils.getExtension(filePath); + return StringUtils.isNotEmpty(entryExtension) && (relevantArchiveFileExtensionSet.contains(entryExtension)); } /** diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTest.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTest.java index 04ddf6e2d4..c429709182 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTest.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTest.java @@ -18,6 +18,16 @@ package org.openecomp.core.externaltesting.impl; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.UUID; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.tuple.Pair; @@ -25,28 +35,37 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.*; +import org.mockito.ArgumentMatchers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; -import org.openecomp.core.externaltesting.api.*; +import org.openecomp.core.externaltesting.api.ClientConfiguration; +import org.openecomp.core.externaltesting.api.ExternalTestingManager; +import org.openecomp.core.externaltesting.api.RemoteTestingEndpointDefinition; +import org.openecomp.core.externaltesting.api.TestTreeNode; +import org.openecomp.core.externaltesting.api.VtpNameDescriptionPair; +import org.openecomp.core.externaltesting.api.VtpTestCase; +import org.openecomp.core.externaltesting.api.VtpTestExecutionRequest; +import org.openecomp.core.externaltesting.api.VtpTestExecutionResponse; import org.openecomp.core.externaltesting.errors.ExternalTestingException; import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager; import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; import org.openecomp.sdc.versioning.VersioningManager; import org.openecomp.sdc.versioning.dao.types.Version; import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.util.LinkedMultiValueMap; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.*; - @RunWith(MockitoJUnitRunner.class) public class ExternalTestingManagerImplTest { diff --git a/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/CandidateServiceImpl.java b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/CandidateServiceImpl.java index 3255e186e4..07dc53dfae 100644 --- a/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/CandidateServiceImpl.java +++ b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/CandidateServiceImpl.java @@ -44,6 +44,8 @@ import org.openecomp.sdc.common.errors.ErrorCategory; import org.openecomp.sdc.common.errors.ErrorCode; import org.openecomp.sdc.common.errors.Messages; import org.openecomp.sdc.common.utils.SdcCommon; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipSlipException; import org.openecomp.sdc.datatypes.error.ErrorLevel; import org.openecomp.sdc.datatypes.error.ErrorMessage; import org.openecomp.sdc.heat.datatypes.manifest.FileData; @@ -426,6 +428,11 @@ public class CandidateServiceImpl implements CandidateService { new ByteArrayInputStream(contentData.array()))) { ZipEntry zipEntry; while ((zipEntry = zipStream.getNextEntry()) != null) { + try { + ZipUtils.checkForZipSlipInRead(zipEntry); + } catch (ZipSlipException e) { + throw new IOException(e); + } ZipEntry locZipEntry = new ZipEntry(zipEntry.getName()); zos.putNextEntry(locZipEntry); byte[] buf = new byte[1024]; diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java index 14cf90a272..1bc547aed7 100644 --- a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java +++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java @@ -58,6 +58,8 @@ import org.openecomp.core.utilities.file.FileContentHandler; import org.openecomp.core.utilities.file.FileUtils; import org.openecomp.sdc.common.errors.CoreException; import org.openecomp.sdc.common.errors.SdcRuntimeException; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipSlipException; import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes; import org.openecomp.sdc.tosca.datatypes.ToscaFlatData; import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel; @@ -123,6 +125,7 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService { try (ZipInputStream inputZipStream = new ZipInputStream(new ByteArrayInputStream(toscaCsarPackage))) { ZipEntry zipEntry; while ((zipEntry = inputZipStream.getNextEntry()) != null) { + ZipUtils.checkForZipSlipInRead(zipEntry); byte[] fileContent = FileUtils.toByteArray(inputZipStream); String currentEntryName = zipEntry.getName(); if (!isFile(currentEntryName)) { @@ -141,7 +144,7 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService { handleToscaCsarWithoutToscaMetadata(toscaServiceModel); } - } catch (IOException exc) { + } catch (IOException | ZipSlipException exc) { throw new SdcRuntimeException(exc.getMessage(), exc); } return toscaServiceModel; diff --git a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/exportinfo/ExportDataCommand.java b/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/exportinfo/ExportDataCommand.java index 5060f4bce2..2907d1e0cc 100644 --- a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/exportinfo/ExportDataCommand.java +++ b/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/exportinfo/ExportDataCommand.java @@ -28,7 +28,6 @@ import com.datastax.driver.core.Session; import com.google.common.collect.Sets; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; @@ -52,8 +51,9 @@ import org.openecomp.core.tools.commands.Command; import org.openecomp.core.tools.commands.CommandName; import org.openecomp.core.tools.importinfo.ImportProperties; import org.openecomp.core.tools.util.Utils; -import org.openecomp.core.tools.util.ZipUtils; import org.openecomp.core.zusammen.impl.CassandraConnectionInitializer; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.logging.api.Logger; import org.openecomp.sdc.logging.api.LoggerFactory; import org.yaml.snakeyaml.Yaml; @@ -157,14 +157,14 @@ public final class ExportDataCommand extends Command { }, executor); } - private static void zipPath(Path rootDir) throws IOException { - LocalDateTime date = LocalDateTime.now(); - DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; - String dateStr = date.format(formatter); - dateStr = dateStr.replaceAll(":", "_"); - String zipFile = System.getProperty("user.home") + File.separatorChar + "onboarding_import" + dateStr + ".zip"; - ZipUtils.createZip(zipFile, rootDir); - Utils.printMessage(LOGGER, "Exported file :" + zipFile); + private static void zipPath(final Path rootDir) throws ZipException { + final LocalDateTime date = LocalDateTime.now(); + final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; + final String dateStr = date.format(formatter).replace(":", "_"); + final Path zipFile = Paths.get(System.getProperty("user.home"),String.format("onboarding_import%s.zip", dateStr)); + ZipUtils.createZipFromPath(rootDir, zipFile); + Utils.printMessage(LOGGER, "Zip file was created " + zipFile.toString()); + Utils.printMessage(LOGGER, "Exported file :" + zipFile.toString()); } diff --git a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/importinfo/ImportDataCommand.java b/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/importinfo/ImportDataCommand.java index 1f5281a66e..cff8eb98cf 100644 --- a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/importinfo/ImportDataCommand.java +++ b/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/importinfo/ImportDataCommand.java @@ -35,8 +35,9 @@ import org.openecomp.core.tools.commands.Command; import org.openecomp.core.tools.commands.CommandName; import org.openecomp.core.tools.exportinfo.ExportDataCommand; import org.openecomp.core.tools.util.Utils; -import org.openecomp.core.tools.util.ZipUtils; import org.openecomp.core.zusammen.impl.CassandraConnectionInitializer; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.logging.api.Logger; import org.openecomp.sdc.logging.api.LoggerFactory; @@ -66,7 +67,7 @@ public class ImportDataCommand extends Command { files.forEach(new ImportSingleTable()::importFile); } FileUtils.forceDelete(outputFolder.toFile()); // leaves directory clean - } catch (IOException e) { + } catch (final IOException | ZipException e) { Utils.logError(LOGGER, e); } return true; diff --git a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/util/ZipUtils.java b/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/util/ZipUtils.java deleted file mode 100644 index f58f18d93c..0000000000 --- a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/util/ZipUtils.java +++ /dev/null @@ -1,104 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.core.tools.util; - -import com.google.common.io.ByteStreams; -import org.openecomp.sdc.logging.api.Logger; -import org.openecomp.sdc.logging.api.LoggerFactory; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -public class ZipUtils { - - private static final Logger logger = LoggerFactory.getLogger(ZipUtils.class); - - private ZipUtils() { - // prevent instantiation - } - - public static void createZip(String zipFileName, Path dir) throws IOException { - File dirObj = dir.toFile(); - Path zippedFile = Files.createFile(Paths.get(zipFileName)); - try ( - FileOutputStream fileOutputStream = new FileOutputStream(File.separator + zippedFile.toFile()); - BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream); - ZipOutputStream out = new ZipOutputStream(bos)) { - File[] files = dirObj.listFiles(); - for (File file : files) { - out.putNextEntry(new ZipEntry(file.getName())); - Files.copy(Paths.get(file.getPath()), out); - out.closeEntry(); - } - Utils.printMessage(logger, "Zip file was created " + zipFileName); - } - } - - public static void unzip(Path zipFile, Path outputFolder) throws IOException { - if (zipFile == null || outputFolder == null) { - return; - } - createDirectoryIfNotExists(outputFolder); - - try (FileInputStream fileInputStream = new FileInputStream(zipFile.toFile()); - ZipInputStream stream = new ZipInputStream(fileInputStream)) { - - ZipEntry entry; - while ((entry = stream.getNextEntry()) != null) { - assertEntryNotVulnerable(entry); - String fileName = entry.getName(); - File newFile = new File(outputFolder.toString() + File.separator + fileName); - if (entry.isDirectory()) { - createDirectoryIfNotExists(newFile.toPath()); - } else { - persistFile(stream, newFile); - } - } - } - - } - - private static void persistFile(ZipInputStream stream, File newFile) throws IOException { - new File(newFile.getParent()).mkdirs(); - try (FileOutputStream outputStream = new FileOutputStream(newFile)) { - ByteStreams.copy(stream, outputStream); - } - } - - private static void createDirectoryIfNotExists(Path path) throws IOException { - if (!path.toFile().exists()) { - Files.createDirectories(path); - } - } - - private static void assertEntryNotVulnerable(ZipEntry entry) throws ZipException { - if (entry.getName().contains("../")) { - throw new ZipException("Path traversal attempt discovered."); - } - } -} - diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java index be235d03ae..b7eaf99724 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java @@ -20,29 +20,40 @@ package org.openecomp.sdc.ci.tests.utils; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertTrue; +import static org.testng.AssertJUnit.fail; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import org.apache.commons.collections4.MapUtils; import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; -import org.openecomp.sdc.ci.tests.tosca.datatypes.*; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaDefinition; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaGroupsTopologyTemplateDefinition; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaImportsDefinition; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaInputsTopologyTemplateDefinition; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaMetadataDefinition; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaNodeTemplatesTopologyTemplateDefinition; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaParameterConstants; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaSubstitutionMappingsDefinition; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaTopologyTemplateDefinition; import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils; import org.openecomp.sdc.ci.tests.utils.rest.ImportRestUtils; import org.openecomp.sdc.common.http.client.api.HttpResponse; -import org.openecomp.sdc.common.util.ZipUtil; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.introspector.PropertyUtils; -import java.io.File; -import java.io.FileInputStream; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Map; - -import static org.testng.AssertJUnit.assertNotNull; -import static org.testng.AssertJUnit.assertTrue; - public class ToscaParserUtils { private static Logger log = LoggerFactory.getLogger(ToscaParserUtils.class.getName()); @@ -135,10 +146,8 @@ public class ToscaParserUtils { try { toscaDefinition = (ToscaDefinition) yaml.load(payload); } catch (Exception e) { - log.debug("Failed to parse tosca yaml file"); - log.debug("Exception: " + e); - System.out.println("Exception: " + e); - assertTrue("Exception: " + e, false); + log.debug("Failed to parse tosca yaml file", e); + fail("Exception: " + e); } return toscaDefinition; @@ -155,7 +164,6 @@ public class ToscaParserUtils { toscaStructure.addTypeDescription(ToscaImportsDefinition.getTypeDescription()); toscaStructure.addTypeDescription(ToscaMetadataDefinition.getTypeDescription()); toscaStructure.addTypeDescription(ToscaInputsTopologyTemplateDefinition.getTypeDescription()); -// toscaStructure.addTypeDescription(ToscaInputsDefinition.getTypeDescription()); // Skip properties which are found in YAML, but not found in POJO PropertyUtils propertyUtils = new PropertyUtils(); propertyUtils.setSkipMissingProperties(true); @@ -193,12 +201,10 @@ public class ToscaParserUtils { } - public static String getYamlPayloadFromCsar(File csarName, String fileLocation) throws Exception { - + public static String getYamlPayloadFromCsar(File csarName, String fileLocation) throws IOException, ZipException { Path path = csarName.toPath(); byte[] data = Files.readAllBytes(path); return getDataFromZipFileByBytes(fileLocation, data); - } /** method get file data from zip data by file location in the zip structure @@ -206,243 +212,16 @@ public class ToscaParserUtils { * @param data * @return */ - public static String getDataFromZipFileByBytes(String fileLocation, byte[] data) { - Map<String, byte[]> readZip = null; - if (data != null && data.length > 0) { - readZip = ZipUtil.readZip(data); - + public static String getDataFromZipFileByBytes(String fileLocation, byte[] data) throws ZipException { + if (data == null || data.length == 0) { + return null; } - byte[] artifactsBs = readZip.get(fileLocation); - String str = new String(artifactsBs, StandardCharsets.UTF_8); - return str; - } -/* public static Map<?, ?> getToscaYamlMap(String csarUUID, String fileLocation) throws Exception { - String csarPayload = CsarValidationUtils.getCsarPayload(csarUUID, fileLocation); - if (csarPayload != null) { - Yaml yaml = new Yaml(); - Map<?, ?> map = (Map<?, ?>) yaml.load(csarPayload); - return map; + final Map<String, byte[]> readZip = ZipUtils.readZip(data, false); + if (MapUtils.isEmpty(readZip)) { + return null; } - return null; + byte[] artifactsBytes = readZip.get(fileLocation); + return new String(artifactsBytes, StandardCharsets.UTF_8); } - - public static ToscaDefinition getToscaDefinitionObjectByCsarUuid(String csarUUID) throws Exception { - - String TOSCAMetaLocation = "TOSCA-Metadata/TOSCA.meta"; - Map<?, ?> map = getToscaYamlMap(csarUUID, TOSCAMetaLocation); - assertNotNull("Tosca Entry-Definitions is null", map); - if (map != null) { - String definitionYamlLocation = (String) map.get("Entry-Definitions"); - Map<?, ?> toscaMap = getToscaYamlMap(csarUUID, definitionYamlLocation); - assertNotNull("Tosca definition is null", toscaMap); - if (toscaMap != null) { - ToscaDefinition toscaDefinition = new ToscaDefinition(); - Set<?> keySet = toscaMap.keySet(); - for (Object key : keySet) { - ToscaKeysEnum toscaKey = ToscaKeysEnum.findToscaKey((String) key); - switch (toscaKey) { - case TOSCA_DEFINITION_VERSION: - getToscaDefinitionVersion(toscaMap, toscaDefinition); - break; - case NODE_TYPES: - getToscaNodeTypes(toscaMap, toscaDefinition); - break; - case TOPOLOGY_TEMPLATE: - getToscaTopologyTemplate(toscaMap, toscaDefinition); - break; - case IMPORTS: - // toscaMap.get("imports"); - break; - default: - break; - } - } - return toscaDefinition; - } - } - return null; - - } - - public static void getToscaDefinitionVersion(Map<?, ?> toscaMap, ToscaDefinition toscaDefinition) { - if (toscaMap.get("tosca_definitions_version") != null) { - toscaDefinition.setTosca_definitions_version((String) toscaMap.get("tosca_definitions_version")); - } - } - - // spec 90 page - public static void getToscaNodeTypes(Map<?, ?> toscaMap, ToscaDefinition toscaDefinition) { - @SuppressWarnings("unchecked") - Map<String, Map<String, String>> nodeTypes = (Map<String, Map<String, String>>) toscaMap.get("node_types"); - Map<String, ToscaNodeTypesDefinition> listToscaNodeTypes = new HashMap<String, ToscaNodeTypesDefinition>(); - if (nodeTypes != null) { - for (Map.Entry<String, Map<String, String>> entry : nodeTypes.entrySet()) { - ToscaNodeTypesDefinition toscaNodeTypes = new ToscaNodeTypesDefinition(); - String toscaNodeName = entry.getKey(); - toscaNodeTypes.setName(toscaNodeName); - - Map<String, String> toscaNodeType = entry.getValue(); - if (toscaNodeType != null) { - Set<Entry<String, String>> entrySet = toscaNodeType.entrySet(); - if (entrySet != null) { - // boolean found = false; - for (Entry<String, String> toscaNodeTypeMap : entrySet) { - String key = toscaNodeTypeMap.getKey(); - if (key.equals("derived_from")) { - String derivedFrom = toscaNodeTypeMap.getValue(); - toscaNodeTypes.setDerived_from(derivedFrom); - // found = true; - break; - } else { - continue; - } - - } - // if (found == false) { - // System.out.println("Tosca file not valid, - // derived_from not found"); - // } - } - - } -// listToscaNodeTypes.add(toscaNodeTypes); - listToscaNodeTypes.put(toscaNodeName, toscaNodeTypes); - } - toscaDefinition.setNode_types(listToscaNodeTypes); - } - } - - public static void getToscaTopologyTemplate(Map<?, ?> toscaMap, ToscaDefinition toscaDefinition) { - ToscaTopologyTemplateDefinition toscaTopologyTemplate = new ToscaTopologyTemplateDefinition(); - @SuppressWarnings("unchecked") - Map<String, Map<String, Object>> topologyTemplateMap = (Map<String, Map<String, Object>>) toscaMap.get("topology_template"); -// List<ToscaNodeTemplatesTopologyTemplateDefinition> listToscaNodeTemplates = new ArrayList<>(); - Map<String,ToscaNodeTemplatesTopologyTemplateDefinition> mapToscaNodeTemplates = new HashMap<String, ToscaNodeTemplatesTopologyTemplateDefinition>(); - - if (topologyTemplateMap != null) { - getToscaNodeTemplates(topologyTemplateMap, mapToscaNodeTemplates); - } -// toscaTopologyTemplate.setToscaNodeTemplatesTopologyTemplateDefinition(listToscaNodeTemplates); - toscaTopologyTemplate.setNode_templates(mapToscaNodeTemplates); - toscaDefinition.setTopology_template(toscaTopologyTemplate); - } - - public static void getToscaNodeTemplates(Map<String, Map<String, Object>> topologyTemplateMap, Map<String,ToscaNodeTemplatesTopologyTemplateDefinition> mapToscaNodeTemplates) { - Map<String, Object> nodeTemplatesMap = topologyTemplateMap.get("node_templates"); - if (nodeTemplatesMap != null) { - - for (Entry<String, Object> nodeTemplates : nodeTemplatesMap.entrySet()) { - ToscaNodeTemplatesTopologyTemplateDefinition toscaNodeTemplates = new ToscaNodeTemplatesTopologyTemplateDefinition(); - getToscaNodeTemplatesName(nodeTemplates, toscaNodeTemplates); - - @SuppressWarnings("unchecked") - Map<String, Object> node = (Map<String, Object>) nodeTemplates.getValue(); - getNodeTemplatesType(toscaNodeTemplates, node); - getToscaNodeTemplateProperties(toscaNodeTemplates, node); - getToscaNodeTemplateRequirements(toscaNodeTemplates, node); - mapToscaNodeTemplates.putAll(mapToscaNodeTemplates); - } - } - } - - public static void getToscaNodeTemplateRequirements(ToscaNodeTemplatesTopologyTemplateDefinition toscaNodeTemplates, Map<String, Object> node) { -//// List<ToscaRequirementsNodeTemplatesDefinition> toscaRequirements = new ArrayList<>(); -// List<Map<String, ToscaRequirementsNodeTemplatesDefinition>> toscaRequirements = new ArrayList<>(); -// if (node.get("requirements") != null) { -// @SuppressWarnings("unchecked") -// List<Map<String, Object>> requirementList = (List<Map<String, Object>>) node.get("requirements"); -// for (int i = 0; i < requirementList.size(); i++) { -// for (Map.Entry<String, Object> requirement : requirementList.get(i).entrySet()) { -// ToscaRequirementsNodeTemplatesDefinition toscaRequirement = new ToscaRequirementsNodeTemplatesDefinition(); -// if (requirement.getKey() != null) { -// String requirementName = requirement.getKey(); -// toscaRequirement.setName(requirementName); -// } else { -// log.debug("Tosca file not valid, requirements should contain name"); -// } -// -// @SuppressWarnings("unchecked") -// Map<String, String> requirementMap = (Map<String, String>) requirement.getValue(); -// Set<Entry<String, String>> entrySet = requirementMap.entrySet(); -// if (entrySet != null) { -// for (Entry<String, String> requirementField : entrySet) { -// String key = requirementField.getKey(); -// switch (key) { -// case "capability": -// if (requirementMap.get(key) != null) { -// String capability = (String) requirementMap.get(key); -// toscaRequirement.setCapability(capability); -// break; -// } else { -// continue; -// } -// case "node": -// if (requirementMap.get(key) != null) { -// String requirementNode = (String) requirementMap.get(key); -// toscaRequirement.setNode(requirementNode); -// break; -// } else { -// continue; -// } -// case "relationship": -// if (requirementMap.get(key) != null) { -// String relationship = (String) requirementMap.get(key); -// toscaRequirement.setRelationship(relationship); -// break; -// } else { -// continue; -// } -// default: -// break; -// } -// } -// } -//// toscaRequirements.add(toscaRequirement); -// toscaRequirements.add(requirementMap); -// } -// } -// } -//// toscaNodeTemplates.setRequirements(toscaRequirements); -// toscaNodeTemplates.setRequirements(requirements); - - } - - public static void getToscaNodeTemplateProperties(ToscaNodeTemplatesTopologyTemplateDefinition toscaNodeTemplates, - Map<String, Object> node) { -// List<ToscaPropertiesNodeTemplatesDefinition> listToscaProperties = new ArrayList<>(); - Map<String, Object> mapToscaProperties = new HashMap<>(); - if (node.get("properties") != null) { - @SuppressWarnings("unchecked") - Map<String, Object> properties = (Map<String, Object>) node.get("properties"); - for (Map.Entry<String, Object> property : properties.entrySet()) { - ToscaPropertiesNodeTemplatesDefinition toscaProperty = new ToscaPropertiesNodeTemplatesDefinition(); - String propertyName = property.getKey(); - Object propertyValue = property.getValue(); - toscaProperty.setName(propertyName); - toscaProperty.setValue(propertyValue); -// mapToscaProperties.add(toscaProperty); - mapToscaProperties.put(propertyName, propertyValue); - } - } - toscaNodeTemplates.setProperties(mapToscaProperties); - } - - protected static void getNodeTemplatesType(ToscaNodeTemplatesTopologyTemplateDefinition toscaNodeTemplates, - Map<String, Object> node) { - if (node.get("type") != null) { - String type = (String) node.get("type"); - toscaNodeTemplates.setType(type); - } else { - log.debug("Tosca file not valid, nodeTemplate should contain type"); - } - } - - protected static void getToscaNodeTemplatesName(Entry<String, Object> nodeTemplates, - ToscaNodeTemplatesTopologyTemplateDefinition toscaNodeTemplates) { - String name = nodeTemplates.getKey(); - toscaNodeTemplates.setName(name); - }*/ - - } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/FileHandling.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/FileHandling.java index 4dbc8b2dee..dae13a2c82 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/FileHandling.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/FileHandling.java @@ -20,25 +20,33 @@ package org.openecomp.sdc.ci.tests.utils.general; +import static org.testng.AssertJUnit.assertTrue; + import com.aventstack.extentreports.Status; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; import org.apache.commons.io.FileUtils; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.ci.tests.api.ComponentBaseTest; -import org.openecomp.sdc.ci.tests.config.Config; import org.openecomp.sdc.ci.tests.datatypes.enums.XnfTypeEnum; import org.openecomp.sdc.common.util.GeneralUtility; import org.yaml.snakeyaml.Yaml; -import java.io.*; -import java.nio.file.Paths; -import java.util.*; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; - -import static org.testng.AssertJUnit.assertTrue; - public class FileHandling { // ------------------yaml parser methods---------------------------- @@ -264,10 +272,6 @@ public class FileHandling { return null; } -// public static Object[] getZipFileNamesFromFolder(String filepath) { -// return filterFileNamesFromFolder(filepath, ".zip"); -// } - public static List<String> getZipFileNamesFromFolder(String filepath) { List<String> fileNamesListFromFolder = filterFileNamesListFromFolder(filepath, ".zip"); fileNamesListFromFolder.addAll(filterFileNamesListFromFolder(filepath, ".csar")); @@ -285,16 +289,6 @@ public class FileHandling { return fileCounter; } - - /** - * @return last modified file name from default directory - * @throws Exception - */ -// TODO add download directory capability -// public static synchronized File getLastModifiedFileNameFromDir() throws Exception{ -// return getLastModifiedFileNameFromDir(ComponentBaseTest.getWindowTest().getDownloadDirectory()); -// } - /** * @param dirPath * @return last modified file name from dirPath directory @@ -369,52 +363,6 @@ public class FileHandling { ComponentBaseTest.getExtendTest().log(Status.INFO, "Unable to write to flie " + pathToFile); } } - -// public static synchronized void writeToFile(File pathToFile, Map<String, Pair<String, Object>> dataMap, Integer leftSpaceCount) throws IOException{ -// -// BufferedWriter bw = null; -// FileWriter fw = null; -// try { -// if(!pathToFile.exists()){ -// createEmptyFile(pathToFile); -// } -// fw = new FileWriter(pathToFile, true); -// bw = new BufferedWriter(fw); -// StringBuilder sb = new StringBuilder(); -// if(leftSpaceCount > 0 ){ -// for(int i = 0; i < leftSpaceCount; i++){ -// sb.append(" "); -// } -// } -// for(Map.Entry<String, Pair<String, Object>> entry : dataMap.entrySet()){ -// Object record = ArtifactUIUtils.getFormatedData(entry.getKey(), entry.getValue().right); -// bw.write(sb.toString() + record); -// bw.newLine(); -// } -// bw.close(); -// fw.close(); -// } catch (Exception e) { -// ComponentBaseTest.getExtendTest().log(Status.INFO, "Unable to write to flie " + pathToFile); -// } -// } - - public static void deleteLastDowloadedFiles(List<File> files) throws IOException { - for (File file : files) { - File fileToDelete =new File(Config.instance().getWindowsDownloadDirectory()+file.getName()); - fileToDelete.delete(); - } - } -// TODO add work with directory capaability -// public static void cleanCurrentDownloadDir() throws IOException { -// try{ -// ExtentTestActions.log(Status.INFO, "Cleaning directory " + ComponentBaseTest.getWindowTest().getDownloadDirectory()); -// System.gc(); -// FileUtils.cleanDirectory(new File(ComponentBaseTest.getWindowTest().getDownloadDirectory())); -// } -// catch(Exception e){ -// -// } -// } public static String getCreateDirByName(String dirName) { File dir = new File(dirName); @@ -507,63 +455,7 @@ public class FileHandling { } return fileList; } - - private static final int BUFFER_SIZE = 4096; -// public static void unzip(String zipFilePath, String destDirectory) throws IOException { -// File destDir = new File(destDirectory); -// if (!destDir.exists()) { -// destDir.mkdir(); -// } -// ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath)); -// ZipEntry entry = zipIn.getNextEntry(); -//// iterates over entries in the zip file -// while (entry != null) { -// String entryName; -// if(System.getProperty("os.name").contains("Windows")){ -// entryName = entry.getName().replaceAll("/", "\\"+File.separator); -// }else{ -// entryName = entry.getName(); -// } -// String filePath = destDirectory + entryName; -// String currPath = destDirectory; -// String[] dirs = entryName.split("\\"+File.separator); -// String currToken; -// for(int i = 0; i<dirs.length;++i){ -// currToken = dirs[i]; -// if(!entry.isDirectory() && i==dirs.length-1){ -// extractFile(zipIn, filePath); -// } else { -// if(currPath.endsWith(File.separator)){ -// currPath = currPath + currToken; -// }else{ -// currPath = currPath + File.separator + currToken; -// } -//// if the entry is a directory, make the directory -// File dir = new File(currPath); -// dir.mkdir(); -// } -// } -// zipIn.closeEntry(); -// entry = zipIn.getNextEntry(); -// } -// zipIn.close(); -// } - - private static void extractFile(ZipInputStream zipIn, String filePath) throws IOException { - BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); - byte[] bytesIn = new byte[BUFFER_SIZE]; - int read = 0; - while ((read = zipIn.read(bytesIn)) != -1) { - bos.write(bytesIn, 0, read); - } - bos.close(); - } - -// public static int getFileCountFromDefaulDownloadDirectory(){ -// return new File(ComponentBaseTest.getWindowTest().getDownloadDirectory()).listFiles().length; -// } - - + public static String getKeyByValueFromPropertyFormatFile(String fullPath, String key) { Properties prop = new Properties(); InputStream input = null; diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/DeploymentValiditaion.java b/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/DeploymentValiditaion.java index fb60f44b64..de2b40868d 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/DeploymentValiditaion.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/DeploymentValiditaion.java @@ -39,7 +39,6 @@ import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; import org.openecomp.sdc.ci.tests.utils.rest.CatalogRestUtils; import org.openecomp.sdc.ci.tests.utils.rest.CategoryRestUtils; import org.openecomp.sdc.ci.tests.utils.rest.ResponseParser; -import org.openecomp.sdc.common.util.ZipUtil; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import org.yaml.snakeyaml.Yaml; @@ -48,7 +47,6 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.stream.Collectors; @@ -177,34 +175,6 @@ public class DeploymentValiditaion extends ComponentBaseTest{ return yamlList; } - @Test (enabled=false) - public void testYaml() throws IOException{ - - System.out.println(""); - - File file = new File("\\\\Comp-1\\FileIO\\Stop.txt"); - - Map<String, byte[]> readZip = null; - Path path = Paths.get("C:\\Users\\ys9693\\Documents\\csar\\attributesWithProporties\\attributesWithProporties.csar"); - byte[] data = Files.readAllBytes(path); - if (data != null && data.length > 0) { - readZip = ZipUtil.readZip(data); - - } - - byte[] artifactsBs = readZip.get("Definitions/VF_RI2_G6.yaml"); - String str = new String(artifactsBs, StandardCharsets.UTF_8); - - Yaml yaml = new Yaml(); - Map<String, Object> load = (Map<String, Object>) yaml.load(str); - Map<String, Object> topology_template = (Map<String, Object>) load.get("topology_template"); - Map<String, Object> node_templates = (Map<String, Object>) topology_template.get("node_templates"); - - Set<String> keySet = node_templates.keySet(); - } - - - @Test public void pasrseDataTypes() throws Exception{ diff --git a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/FileHandling.java b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/FileHandling.java index 1ac4a72059..f8cc628d58 100644 --- a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/FileHandling.java +++ b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/FileHandling.java @@ -501,7 +501,7 @@ public class FileHandling { while (entry != null) { String entryName; if (System.getProperty("os.name").contains("Windows")) { - entryName = entry.getName().replaceAll("/", "\\" + File.separator); + entryName = entry.getName().replace("/", "\\" + File.separator); } else { entryName = entry.getName(); } |