From b2f9dc5d3bc02564b4d952caa0bf2ccd20dfc6af Mon Sep 17 00:00:00 2001 From: kooper Date: Tue, 2 Apr 2019 09:22:01 +0000 Subject: Verify signature Change-Id: I8fc5d50d74d3dd8031c96ee16708489dc7c789b8 Issue-ID: SDC-2163 Signed-off-by: kooper --- .../vendor-software-products-rest-services/pom.xml | 18 +++ .../sdcrests/vsp/rest/data/PackageArchive.java | 160 +++++++++++++++++++++ .../OrchestrationTemplateCandidateException.java | 27 ++++ .../OrchestrationTemplateCandidateImpl.java | 55 +++++-- .../sdcrests/vsp/rest/data/PackageArchiveTest.java | 99 +++++++++++++ .../OrchestrationTemplateCandidateImplTest.java | 121 ++++++++++++++++ .../src/test/resources/vspmanager.csar/notCsar.txt | 0 .../signing/2-empty-directories-in-root.zip | Bin 0 -> 290 bytes ...pty-files-1-directory-with-contents-in-root.zip | Bin 0 -> 558 bytes .../2-empty-files-1-empty-directory-in-root.zip | Bin 0 -> 420 bytes .../vspmanager.csar/signing/2-files-in-root.zip | Bin 0 -> 286 bytes .../signing/csar-and-cms-in-root.zip | Bin 0 -> 304 bytes .../signing/signed-package-tampered-data.zip | Bin 0 -> 4242 bytes .../vspmanager.csar/signing/signed-package.zip | Bin 0 -> 4242 bytes 14 files changed, 470 insertions(+), 10 deletions(-) create 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 create 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/services/OrchestrationTemplateCandidateException.java create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/data/PackageArchiveTest.java create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/services/OrchestrationTemplateCandidateImplTest.java create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/notCsar.txt create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-directories-in-root.zip create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-files-1-directory-with-contents-in-root.zip create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-files-1-empty-directory-in-root.zip create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-files-in-root.zip create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/csar-and-cms-in-root.zip create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/signed-package-tampered-data.zip create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/signed-package.zip (limited to 'openecomp-be/api/openecomp-sdc-rest-webapp') diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/pom.xml b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/pom.xml index 26a7c15ff2..b1cee443a8 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/pom.xml +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/pom.xml @@ -130,6 +130,24 @@ unique-type-rest-types ${project.version} + + org.powermock + powermock-module-junit4-common + ${powermock.version} + test + + + org.powermock + powermock-api-mockito2 + ${powermock.version} + test + + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + 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 new file mode 100644 index 0000000000..bf029fb29e --- /dev/null +++ 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 @@ -0,0 +1,160 @@ +/*- + * ============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 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.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; +import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager; +import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManagerException; + +import java.io.IOException; +import java.security.cert.CertificateException; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * 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; + + 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 (IOException 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 { + Map files = handlerPair.getLeft().getFiles(); + Optional signatureFileName = getSignatureFileName(); + Optional archiveFileName = getArchiveFileName(); + if (files.isEmpty() || !signatureFileName.isPresent() || !archiveFileName.isPresent()) { + return false; + } + Optional certificateFile = getCertificateFileName(); + if(certificateFile.isPresent()){ + return securityManager.verifySignedData(files.get(signatureFileName.get()), + files.get(certificateFile.get()), files.get(archiveFileName.get())); + }else { + return securityManager.verifySignedData(files.get(signatureFileName.get()), + null, files.get(archiveFileName.get())); + } + } + + 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/OrchestrationTemplateCandidateException.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/OrchestrationTemplateCandidateException.java new file mode 100644 index 0000000000..a7e65a7e6f --- /dev/null +++ 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/OrchestrationTemplateCandidateException.java @@ -0,0 +1,27 @@ +/*- + * ============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.services; + +public class OrchestrationTemplateCandidateException extends Exception{ + + public OrchestrationTemplateCandidateException(String message, Throwable t){ + super(message, t); + } +} 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 bdc422d580..4978b3fb34 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 @@ -25,6 +25,7 @@ import org.openecomp.sdc.activitylog.ActivityLogManagerFactory; import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity; import org.openecomp.sdc.activitylog.dao.type.ActivityType; import org.openecomp.sdc.common.errors.Messages; +import org.openecomp.sdc.common.utils.SdcCommon; import org.openecomp.sdc.datatypes.error.ErrorLevel; import org.openecomp.sdc.datatypes.error.ErrorMessage; import org.openecomp.sdc.logging.api.Logger; @@ -33,6 +34,7 @@ import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateMan import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManagerFactory; import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory; +import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManagerException; import org.openecomp.sdc.vendorsoftwareproduct.types.OrchestrationTemplateActionResponse; import org.openecomp.sdc.vendorsoftwareproduct.types.UploadFileResponse; import org.openecomp.sdc.vendorsoftwareproduct.types.ValidationResponse; @@ -43,6 +45,7 @@ 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; @@ -51,9 +54,13 @@ import org.springframework.stereotype.Service; import javax.inject.Named; import javax.ws.rs.core.Response; +import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Optional; import static org.openecomp.core.utilities.file.FileUtils.getFileExtension; @@ -75,18 +82,46 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate @Override public Response upload(String vspId, String versionId, Attachment fileToUpload, String user) { + PackageArchive archive = new PackageArchive(fileToUpload.getObject(byte[].class)); + UploadFileResponseDto uploadFileResponseDto; + try { + if (archive.isSigned() && !archive.isSignatureValid()) { + 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 Response.ok(uploadFileResponseDto).build(); + } - String filename = fileToUpload.getContentDisposition().getParameter("filename"); - UploadFileResponse uploadFileResponse = candidateManager - .upload(vspId, new Version(versionId), fileToUpload.getObject(InputStream.class), - getFileExtension(filename), getNetworkPackageName(filename)); - - UploadFileResponseDto uploadFileResponseDto = new MapUploadFileResponseToUploadFileResponseDto() - .applyMapping(uploadFileResponse, UploadFileResponseDto.class); - + String filename = archive.getArchiveFileName().orElse(fileToUpload.getContentDisposition().getFilename()); + UploadFileResponse uploadFileResponse = candidateManager + .upload(vspId, new Version(versionId), new ByteArrayInputStream(archive.getPackageFileContents()), + getFileExtension(filename), getNetworkPackageName(filename)); + + uploadFileResponseDto = new MapUploadFileResponseToUploadFileResponseDto() + .applyMapping(uploadFileResponse, UploadFileResponseDto.class); + } catch (SecurityManagerException e) { + 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 Response.ok(uploadFileResponseDto).build(); + } return Response.ok(uploadFileResponseDto).build(); } + 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); + uploadFileResponseDto.setErrors(errorMap); + return uploadFileResponseDto; + } + @Override public Response get(String vspId, String versionId, String user) throws IOException { Optional> zipFile = candidateManager.get(vspId, new Version(versionId)); @@ -146,7 +181,7 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate String errorWithParameters = ErrorMessagesFormatBuilder .getErrorWithParameters(Messages.MAPPING_OBJECTS_FAILURE.getErrorMessage(), fileDataStructureDto.toString(), fileDataStructure.toString()); - throw new Exception(errorWithParameters, exception); + throw new OrchestrationTemplateCandidateException(errorWithParameters, exception); } ValidationResponse response = candidateManager .updateFilesDataStructure(vspId, new Version(versionId), fileDataStructure); diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/data/PackageArchiveTest.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/data/PackageArchiveTest.java new file mode 100644 index 0000000000..6458a65d17 --- /dev/null +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/data/PackageArchiveTest.java @@ -0,0 +1,99 @@ +package org.openecomp.sdcrests.vsp.rest.data; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager; +import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManagerException; +import org.powermock.reflect.Whitebox; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.MockitoAnnotations.initMocks; +import static org.powermock.api.mockito.PowerMockito.when; + +public class PackageArchiveTest { + private static final String BASE_DIR = "/vspmanager.csar/"; + + @Mock + SecurityManager manager; + + @Before + public void setUp(){ + initMocks(this); + } + + + @Test + public void isSignedTestCheckingWrongFile() throws IOException, + URISyntaxException { + PackageArchive packageArchive = getArchive("notCsar.txt"); + assertFalse("2 or 3 files expected for signed package present or signature valid for " + + "empty file", packageArchive.isSigned()); + } + + @Test + public void isSignedTestWrongPackageStructure2EmptyDirInRoot() throws IOException, + URISyntaxException { + PackageArchive packageArchive = getArchive("signing/2-empty-directories-in-root.zip"); + assertFalse(packageArchive.isSigned()); + } + + @Test + public void isSignedTestWrongPackageStructure2EmptyFilesAndEmptyDirInRoot() throws IOException, + URISyntaxException { + PackageArchive packageArchive = getArchive("signing/2-empty-files-1-empty-directory-in-root.zip"); + assertFalse(packageArchive.isSigned()); + } + + @Test + public void isSignedTestWrongPackageStructure2EmptyFilesAndDirWithContentInRoot() throws IOException, + URISyntaxException { + PackageArchive packageArchive = getArchive("signing/2-empty-files-1-directory-with-contents-in-root.zip"); + assertFalse(packageArchive.isSigned()); + } + + @Test + public void isSignedTestCorrectStructureNoSignature() throws IOException, + URISyntaxException { + PackageArchive packageArchive = getArchive("signing/2-files-in-root.zip"); + assertFalse(packageArchive.isSigned()); + } + + @Test + public void isSignedTestCorrectStructureAndSignatureExists() throws IOException, + URISyntaxException { + PackageArchive packageArchive = getArchive("signing/csar-and-cms-in-root.zip"); + assertTrue(packageArchive.isSigned()); + } + + @Test + public void isSignatureValidTestCorrectStructureAndValidSignatureExists() throws IOException, + URISyntaxException, SecurityManagerException { + PackageArchive packageArchive = getArchive("signing/signed-package.zip"); + Whitebox.setInternalState(packageArchive, "securityManager", manager); + when(manager.verifySignedData(any(), any(), any())).thenReturn(true); + assertTrue("Signature invalid for signed package", + packageArchive.isSignatureValid()); + } + + @Test(expected = SecurityManagerException.class) + public void isSignatureValidTestCorrectStructureAndNotValidSignatureExists() throws IOException, + URISyntaxException, SecurityManagerException { + PackageArchive packageArchive = getArchive("signing/signed-package-tampered-data.zip"); + Whitebox.setInternalState(packageArchive, "securityManager", manager); + when(manager.verifySignedData(any(), any(), any())).thenThrow(new SecurityManagerException("error!")); + packageArchive.isSignatureValid(); + } + + private PackageArchive getArchive(String path) throws URISyntaxException, IOException { + return new PackageArchive(Files.readAllBytes(Paths.get( + PackageArchiveTest.class.getResource(BASE_DIR + path).toURI()))); + } +} diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/services/OrchestrationTemplateCandidateImplTest.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/services/OrchestrationTemplateCandidateImplTest.java new file mode 100644 index 0000000000..2dc6cd737c --- /dev/null +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/services/OrchestrationTemplateCandidateImplTest.java @@ -0,0 +1,121 @@ +package org.openecomp.sdcrests.vsp.rest.services; + +import org.apache.cxf.jaxrs.ext.multipart.Attachment; +import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum; +import org.openecomp.sdc.activitylog.ActivityLogManager; +import org.openecomp.sdc.activitylog.ActivityLogManagerFactory; +import org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; +import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager; +import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManagerFactory; +import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; +import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory; +import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManagerException; +import org.openecomp.sdc.vendorsoftwareproduct.types.UploadFileResponse; +import org.openecomp.sdcrests.vendorsoftwareproducts.types.UploadFileResponseDto; +import org.openecomp.sdcrests.vsp.rest.data.PackageArchive; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import javax.ws.rs.core.Response; + +import java.util.Optional; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.MockitoAnnotations.initMocks; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.when; +import static org.powermock.api.mockito.PowerMockito.whenNew; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({VspManagerFactory.class, ActivityLogManagerFactory.class, + OrchestrationTemplateCandidateManagerFactory.class, OrchestrationTemplateCandidateImpl.class}) +public class OrchestrationTemplateCandidateImplTest { + + Logger logger = LoggerFactory.getLogger(OrchestrationTemplateCandidateImplTest.class); + @Mock + private OrchestrationTemplateCandidateManager candidateManager; + @Mock + private VendorSoftwareProductManager vendorSoftwareProductManager; + @Mock + private PackageArchive packageArchive; + @Mock + private VspManagerFactory vspManagerFactory; + @Mock + private ActivityLogManager activityLogManager; + @Mock + private ActivityLogManagerFactory activityLogManagerFactory; + @Mock + OrchestrationTemplateCandidateManagerFactory orchestrationTemplateCandidateManagerFactory; + + private OrchestrationTemplateCandidateImpl orchestrationTemplateCandidate; + + @Before + public void setUp(){ + try { + initMocks(this); + packageArchive = mock(PackageArchive.class); + mockStatic(VspManagerFactory.class); + when(VspManagerFactory.getInstance()).thenReturn(vspManagerFactory); + when(vspManagerFactory.createInterface()).thenReturn(vendorSoftwareProductManager); + mockStatic(ActivityLogManagerFactory.class); + when(ActivityLogManagerFactory.getInstance()).thenReturn(activityLogManagerFactory); + when(activityLogManagerFactory.createInterface()).thenReturn(activityLogManager); + whenNew(PackageArchive.class).withAnyArguments().thenReturn(packageArchive); + mockStatic(OrchestrationTemplateCandidateManagerFactory.class); + when(OrchestrationTemplateCandidateManagerFactory.getInstance()).thenReturn(orchestrationTemplateCandidateManagerFactory); + when(orchestrationTemplateCandidateManagerFactory.createInterface()).thenReturn(candidateManager); + when(packageArchive.getArchiveFileName()).thenReturn(Optional.of("test")); + when(packageArchive.getPackageFileContents()).thenReturn(new byte[0]); + UploadFileResponse uploadFileResponse = new UploadFileResponse(); + uploadFileResponse.setOnboardingType(OnboardingTypesEnum.ZIP); + uploadFileResponse.setNetworkPackageName("test"); + when(candidateManager.upload(any(), any(), any(), any(), any())).thenReturn(uploadFileResponse); + }catch (Exception e){ + logger.error(e.getMessage(), e); + } + } + + @Test + public void uploadSignedTest() throws SecurityManagerException { + when(packageArchive.isSigned()).thenReturn(true); + when(packageArchive.isSignatureValid()).thenReturn(true); + orchestrationTemplateCandidate = new OrchestrationTemplateCandidateImpl(); + Attachment attachment = mock(Attachment.class); + when(attachment.getContentDisposition()).thenReturn(new ContentDisposition("test")); + Response response = orchestrationTemplateCandidate.upload("1", "1", attachment, "1"); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + } + + @Test + public void uploadNotSignedTest(){ + when(packageArchive.isSigned()).thenReturn(false); + orchestrationTemplateCandidate = new OrchestrationTemplateCandidateImpl(); + Attachment attachment = mock(Attachment.class); + when(attachment.getContentDisposition()).thenReturn(new ContentDisposition("test")); + Response response = orchestrationTemplateCandidate.upload("1", "1", attachment, "1"); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + } + + @Test + public void uploadSignNotValidTest() throws SecurityManagerException { + when(packageArchive.isSigned()).thenReturn(true); + when(packageArchive.isSignatureValid()).thenReturn(false); + orchestrationTemplateCandidate = new OrchestrationTemplateCandidateImpl(); + Attachment attachment = mock(Attachment.class); + when(attachment.getContentDisposition()).thenReturn(new ContentDisposition("test")); + Response response = orchestrationTemplateCandidate.upload("1", "1", attachment, "1"); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + assertFalse(((UploadFileResponseDto)response.getEntity()).getErrors().isEmpty()); + + } +} diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/notCsar.txt b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/notCsar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-directories-in-root.zip b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-directories-in-root.zip new file mode 100644 index 0000000000..d0f1fd09dc Binary files /dev/null and b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-directories-in-root.zip differ diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-files-1-directory-with-contents-in-root.zip b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-files-1-directory-with-contents-in-root.zip new file mode 100644 index 0000000000..0f10af262f Binary files /dev/null and b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-files-1-directory-with-contents-in-root.zip differ diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-files-1-empty-directory-in-root.zip b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-files-1-empty-directory-in-root.zip new file mode 100644 index 0000000000..6ded8b1d57 Binary files /dev/null and b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-empty-files-1-empty-directory-in-root.zip differ diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-files-in-root.zip b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-files-in-root.zip new file mode 100644 index 0000000000..d1e80ae132 Binary files /dev/null and b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/2-files-in-root.zip differ diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/csar-and-cms-in-root.zip b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/csar-and-cms-in-root.zip new file mode 100644 index 0000000000..07331466df Binary files /dev/null and b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/csar-and-cms-in-root.zip differ diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/signed-package-tampered-data.zip b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/signed-package-tampered-data.zip new file mode 100644 index 0000000000..0cfb9e0265 Binary files /dev/null and b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/signed-package-tampered-data.zip differ diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/signed-package.zip b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/signed-package.zip new file mode 100644 index 0000000000..a64ddd9be2 Binary files /dev/null and b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/signed-package.zip differ -- cgit 1.2.3-korg