From 433947b5ab5e28fc29aee447de934de89a707419 Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Thu, 19 Sep 2019 16:14:01 +0100 Subject: Centralize onboarding package validation Change-Id: I3cc58cf15f62008e83cfc7ddb095d07ab216b82a Issue-ID: SDC-2583 Signed-off-by: andre.schmid --- .../sdcrests/vsp/rest/data/PackageArchive.java | 163 --------------------- .../OrchestrationTemplateCandidateImpl.java | 112 ++++---------- 2 files changed, 28 insertions(+), 247 deletions(-) delete mode 100644 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 (limited to 'openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java') 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 deleted file mode 100644 index 4f4258ad53..0000000000 --- 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 +++ /dev/null @@ -1,163 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * Copyright (C) 2019, Nordix Foundation. 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.sdcrests.vsp.rest.data; - -import java.security.cert.CertificateException; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import org.apache.commons.io.FilenameUtils; -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; -import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManagerException; - -/** - * Class responsible for processing zip archive and verify if this package corresponds SOL004 option 2 signed package - * format, verifies the cms signature if package is signed - */ -public class PackageArchive { - - private static final Logger LOG = LoggerFactory.getLogger(PackageArchive.class); - private static final String[] ALLOWED_ARCHIVE_EXTENSIONS = {"csar", "zip"}; - private static final String[] ALLOWED_SIGNATURE_EXTENSIONS = {"cms"}; - private static final String[] ALLOWED_CERTIFICATE_EXTENSIONS = {"cert"}; - private static final int NUMBER_OF_FILES_FOR_SIGNATURE_WITH_CERT_INSIDE = 2; - private static final int NUMBER_OF_FILES_FOR_SIGNATURE_WITHOUT_CERT_INSIDE = 3; - private final SecurityManager securityManager; - private final byte[] outerPackageFileBytes; - private Pair> handlerPair; - private Boolean signatureValid; - - public PackageArchive(Attachment uploadedFile) { - this(uploadedFile.getObject(byte[].class)); - } - - public PackageArchive(byte[] outerPackageFileBytes) { - this.outerPackageFileBytes = outerPackageFileBytes; - this.securityManager = SecurityManager.getInstance(); - try { - handlerPair = CommonUtil.getFileContentMapFromOrchestrationCandidateZip( - outerPackageFileBytes); - } catch (final ZipException exception) { - LOG.error("Error reading files inside archive", exception); - } - } - - /** - * Checks if package matches required format {package.csar/zip, package.cms, package.cert(optional)} - * - * @return true if structure matches sol004 option 2 structure - */ - public boolean isSigned() { - return isPackageSizeMatches() && getSignatureFileName().isPresent(); - } - - /** - * Gets csar/zip package name with extension only if package is signed - * - * @return csar package name - */ - public Optional getArchiveFileName() { - if (isSigned()) { - return getFileByExtension(ALLOWED_ARCHIVE_EXTENSIONS); - } - return Optional.empty(); - } - - /** - * Gets csar/zip package content from zip archive - * - * @return csar package content - * @throws SecurityManagerException - */ - public byte[] getPackageFileContents() throws SecurityManagerException { - try { - if (isSignatureValid()) { - return handlerPair.getKey().getFiles().get(getArchiveFileName().orElseThrow(CertificateException::new)); - } - } catch (CertificateException exception) { - LOG.info("Error verifying signature ", exception); - } - return outerPackageFileBytes; - } - - /** - * Validates package signature against trusted certificates - * - * @return true if signature verified - * @throws SecurityManagerException - */ - public boolean isSignatureValid() throws SecurityManagerException { - if (signatureValid == null) { - final Map files = handlerPair.getLeft().getFiles(); - final Optional signatureFileName = getSignatureFileName(); - final Optional archiveFileName = getArchiveFileName(); - if (files.isEmpty() || !signatureFileName.isPresent() || !archiveFileName.isPresent()) { - signatureValid = false; - } else { - final Optional certificateFile = getCertificateFileName(); - signatureValid = securityManager.verifySignedData(files.get(signatureFileName.get()), - certificateFile.map(files::get).orElse(null), files.get(archiveFileName.get())); - } - - } - return signatureValid; - } - - private boolean isPackageSizeMatches() { - return handlerPair.getRight().isEmpty() - && (handlerPair.getLeft().getFiles().size() == NUMBER_OF_FILES_FOR_SIGNATURE_WITH_CERT_INSIDE - || handlerPair.getLeft().getFiles().size() == NUMBER_OF_FILES_FOR_SIGNATURE_WITHOUT_CERT_INSIDE); - } - - private Optional getSignatureFileName() { - return getFileByExtension(ALLOWED_SIGNATURE_EXTENSIONS); - } - - private Optional getFileByExtension(String[] extensions) { - for (String fileName : handlerPair.getLeft().getFileList()) { - for (String extension : extensions) { - if (extension.equalsIgnoreCase(FilenameUtils.getExtension(fileName))) { - return Optional.of(fileName); - } - } - } - return Optional.empty(); - } - - private Optional getCertificateFileName() { - Optional certFileName = getFileByExtension(ALLOWED_CERTIFICATE_EXTENSIONS); - if (!certFileName.isPresent()) { - return Optional.empty(); - } - String certNameWithoutExtension = FilenameUtils.removeExtension(certFileName.get()); - if (certNameWithoutExtension.equals(FilenameUtils.removeExtension(getArchiveFileName().orElse("")))) { - return certFileName; - } - //cert file name should be the same as package name, e.g. vnfpackage.scar-->vnfpackage.cert - return Optional.empty(); - } -} 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/services/OrchestrationTemplateCandidateImpl.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/services/OrchestrationTemplateCandidateImpl.java index 10f96e9d3b..e4262df105 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/services/OrchestrationTemplateCandidateImpl.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/services/OrchestrationTemplateCandidateImpl.java @@ -19,13 +19,11 @@ package org.openecomp.sdcrests.vsp.rest.services; -import static org.openecomp.core.utilities.file.FileUtils.getFileExtension; -import static org.openecomp.core.utilities.file.FileUtils.getNetworkPackageName; import static org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder.getErrorWithParameters; import java.io.IOException; -import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,10 +31,8 @@ import java.util.Optional; import javax.activation.DataHandler; import javax.inject.Named; import javax.ws.rs.core.Response; -import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.cxf.jaxrs.ext.multipart.Attachment; -import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum; import org.openecomp.sdc.activitylog.ActivityLogManager; import org.openecomp.sdc.activitylog.ActivityLogManagerFactory; import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity; @@ -52,8 +48,7 @@ import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateMan import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory; import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails; -import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManagerException; -import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackage; +import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.OnboardingPackageProcessor; import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo; import org.openecomp.sdc.vendorsoftwareproduct.types.OrchestrationTemplateActionResponse; import org.openecomp.sdc.vendorsoftwareproduct.types.UploadFileResponse; @@ -65,7 +60,6 @@ import org.openecomp.sdcrests.vendorsoftwareproducts.types.OrchestrationTemplate import org.openecomp.sdcrests.vendorsoftwareproducts.types.UploadFileResponseDto; import org.openecomp.sdcrests.vendorsoftwareproducts.types.ValidationResponseDto; import org.openecomp.sdcrests.vsp.rest.OrchestrationTemplateCandidate; -import org.openecomp.sdcrests.vsp.rest.data.PackageArchive; import org.openecomp.sdcrests.vsp.rest.mapping.MapFilesDataStructureToDto; import org.openecomp.sdcrests.vsp.rest.mapping.MapUploadFileResponseToUploadFileResponseDto; import org.openecomp.sdcrests.vsp.rest.mapping.MapValidationResponseToDto; @@ -89,91 +83,41 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate public Response upload(final String vspId, final String versionId, final Attachment fileToUpload, final String user) { final byte[] fileToUploadBytes = fileToUpload.getObject(byte[].class); - String fileToUploadName = ""; - String fileToUploadExtension = ""; final DataHandler dataHandler = fileToUpload.getDataHandler(); - if(dataHandler != null) { - final String filename = dataHandler.getName(); - fileToUploadName = FilenameUtils.removeExtension(filename); - fileToUploadExtension = FilenameUtils.getExtension(filename); - } - final PackageArchive archive = new PackageArchive(fileToUploadBytes); - final Optional validatePackageArchiveResponse = - validatePackageArchive(archive); - if (!validatePackageArchiveResponse.isPresent()) { - final VspDetails vspDetails = new VspDetails(vspId, new Version(versionId)); - return processOnboardPackage(fileToUpload, fileToUploadBytes, fileToUploadName, - fileToUploadExtension, archive, vspDetails); - } else { - return Response.ok(validatePackageArchiveResponse.get()).build(); - } - } + final String filename = dataHandler.getName(); - private Optional validatePackageArchive(final PackageArchive archive) { - UploadFileResponseDto uploadFileResponseDto; - try { - if (archive.isSigned() && !archive.isSignatureValid()) { - final ErrorMessage errorMessage = new ErrorMessage(ErrorLevel.ERROR, - getErrorWithParameters(Messages.FAILED_TO_VERIFY_SIGNATURE.getErrorMessage(), "")); - LOGGER.error(errorMessage.getMessage()); - uploadFileResponseDto = buildUploadResponseWithError(errorMessage); - //returning OK as SDC UI won't show error message if NOT OK error code. - return Optional.of(uploadFileResponseDto); - } - } catch (final SecurityManagerException e) { - final ErrorMessage errorMessage = new ErrorMessage(ErrorLevel.ERROR, - getErrorWithParameters(e.getMessage(), "")); - LOGGER.error(errorMessage.getMessage(), e); - uploadFileResponseDto = buildUploadResponseWithError(errorMessage); - //returning OK as SDC UI won't show error message if NOT OK error code. - return Optional.of(uploadFileResponseDto); + final OnboardingPackageProcessor onboardingPackageProcessor = new OnboardingPackageProcessor(filename, fileToUploadBytes); + if (onboardingPackageProcessor.hasErrors()) { + final UploadFileResponseDto uploadFileResponseDto = + buildUploadResponseWithError(onboardingPackageProcessor.getErrorMessageSet().toArray(new ErrorMessage[0])); + return Response.ok(uploadFileResponseDto).build(); } - return Optional.empty(); - } - private Response processOnboardPackage(final Attachment fileToUpload, - final byte[] fileToUploadBytes, - final String fileToUploadName, - final String fileToUploadExtension, - final PackageArchive archive, - final VspDetails vspDetails) { - final String filename = archive.getArchiveFileName() - .orElse(fileToUpload.getContentDisposition().getFilename()); - UploadFileResponseDto uploadFileResponseDto; - try { - final String archiveFileExtension = getFileExtension(filename); - final OnboardPackageInfo onboardPackageInfo; - if (OnboardingTypesEnum.CSAR.toString().equalsIgnoreCase(archiveFileExtension)) { - final OnboardPackage onboardPackage = new OnboardPackage(getNetworkPackageName(filename), - archiveFileExtension, ByteBuffer.wrap(archive.getPackageFileContents())); - onboardPackageInfo = new OnboardPackageInfo(fileToUploadName, - fileToUploadExtension, ByteBuffer.wrap(fileToUploadBytes), onboardPackage); - } else { - onboardPackageInfo = new OnboardPackageInfo(fileToUploadName, - fileToUploadExtension, ByteBuffer.wrap(fileToUploadBytes)); - } - final UploadFileResponse uploadFileResponse = candidateManager - .upload(vspDetails, onboardPackageInfo); - uploadFileResponseDto = new MapUploadFileResponseToUploadFileResponseDto() - .applyMapping(uploadFileResponse, UploadFileResponseDto.class); + final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null); - return Response.ok(uploadFileResponseDto).build(); - } catch (final SecurityManagerException e) { - final ErrorMessage errorMessage = new ErrorMessage(ErrorLevel.ERROR, - getErrorWithParameters(e.getMessage(), "")); - LOGGER.error(errorMessage.getMessage(), e); - uploadFileResponseDto = buildUploadResponseWithError(errorMessage); - //returning OK as SDC UI won't show error message if NOT OK error code. + if (onboardPackageInfo == null) { + final UploadFileResponseDto uploadFileResponseDto = buildUploadResponseWithError( + new ErrorMessage(ErrorLevel.ERROR, Messages.PACKAGE_PROCESS_ERROR.formatMessage(filename))); return Response.ok(uploadFileResponseDto).build(); } + + final VspDetails vspDetails = new VspDetails(vspId, new Version(versionId)); + return processOnboardPackage(onboardPackageInfo, vspDetails); } - private UploadFileResponseDto buildUploadResponseWithError(ErrorMessage errorMessage) { - UploadFileResponseDto uploadFileResponseDto = new UploadFileResponseDto(); - Map> errorMap = new HashMap<>(); - List errorMessages = new ArrayList<>(); - errorMessages.add(errorMessage); - errorMap.put(SdcCommon.UPLOAD_FILE, errorMessages); + private Response processOnboardPackage(final OnboardPackageInfo onboardPackageInfo, final VspDetails vspDetails) { + final UploadFileResponse uploadFileResponse = candidateManager.upload(vspDetails, onboardPackageInfo); + final UploadFileResponseDto uploadFileResponseDto = new MapUploadFileResponseToUploadFileResponseDto() + .applyMapping(uploadFileResponse, UploadFileResponseDto.class); + return Response.ok(uploadFileResponseDto).build(); + } + + private UploadFileResponseDto buildUploadResponseWithError(final ErrorMessage... errorMessages) { + final UploadFileResponseDto uploadFileResponseDto = new UploadFileResponseDto(); + final Map> errorMap = new HashMap<>(); + final List errorMessageList = new ArrayList<>(); + Collections.addAll(errorMessageList, errorMessages); + errorMap.put(SdcCommon.UPLOAD_FILE, errorMessageList); uploadFileResponseDto.setErrors(errorMap); return uploadFileResponseDto; } -- cgit 1.2.3-korg