summaryrefslogtreecommitdiffstats
path: root/openecomp-be/api/openecomp-sdc-rest-webapp
diff options
context:
space:
mode:
authorkooper <sergey.sachkov@est.tech>2019-04-02 09:22:01 +0000
committerkooper <sergey.sachkov@est.tech>2019-04-02 09:22:01 +0000
commitb2f9dc5d3bc02564b4d952caa0bf2ccd20dfc6af (patch)
tree9d26cfd0a4771c38bc1f662d697bce77190d5e4c /openecomp-be/api/openecomp-sdc-rest-webapp
parentddaa4ab7cbefb3c765b6d5732bef568a447f134a (diff)
Verify signature
Change-Id: I8fc5d50d74d3dd8031c96ee16708489dc7c789b8 Issue-ID: SDC-2163 Signed-off-by: kooper <sergey.sachkov@est.tech>
Diffstat (limited to 'openecomp-be/api/openecomp-sdc-rest-webapp')
-rw-r--r--openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/pom.xml18
-rw-r--r--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.java160
-rw-r--r--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.java27
-rw-r--r--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.java55
-rw-r--r--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.java99
-rw-r--r--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.java121
-rw-r--r--openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/notCsar.txt0
-rw-r--r--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.zipbin0 -> 290 bytes
-rw-r--r--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.zipbin0 -> 558 bytes
-rw-r--r--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.zipbin0 -> 420 bytes
-rw-r--r--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.zipbin0 -> 286 bytes
-rw-r--r--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.zipbin0 -> 304 bytes
-rw-r--r--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.zipbin0 -> 4242 bytes
-rw-r--r--openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/signing/signed-package.zipbin0 -> 4242 bytes
14 files changed, 470 insertions, 10 deletions
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 @@
<artifactId>unique-type-rest-types</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
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<FileContentHandler, List<String>> 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<String> 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<String, byte[]> files = handlerPair.getLeft().getFiles();
+ Optional<String> signatureFileName = getSignatureFileName();
+ Optional<String> archiveFileName = getArchiveFileName();
+ if (files.isEmpty() || !signatureFileName.isPresent() || !archiveFileName.isPresent()) {
+ return false;
+ }
+ Optional<String> 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<String> getSignatureFileName() {
+ return getFileByExtension(ALLOWED_SIGNATURE_EXTENSIONS);
+ }
+
+ private Optional<String> 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<String> getCertificateFileName() {
+ Optional<String> 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<String, List<ErrorMessage>> errorMap = new HashMap<>();
+ List<ErrorMessage> 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<Pair<String, byte[]>> 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
--- /dev/null
+++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/resources/vspmanager.csar/notCsar.txt
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
--- /dev/null
+++ 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
Binary files 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
--- /dev/null
+++ 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
Binary files 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
--- /dev/null
+++ 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
Binary files 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
--- /dev/null
+++ 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
Binary files 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
--- /dev/null
+++ 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
Binary files 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
--- /dev/null
+++ 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
Binary files 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
--- /dev/null
+++ 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
Binary files differ