aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandre.schmid <andre.schmid@est.tech>2021-01-28 17:53:22 +0000
committerVasyl Razinkov <vasyl.razinkov@est.tech>2021-02-21 13:07:13 +0000
commit13b39127c1c91d7c05c67ea2c14220c8f992cba5 (patch)
tree755c7ad631c0673c73e28f415cca9682889e729b
parent8cc03e2c78639be5500ab50f3ebaaf7d64404775 (diff)
ETSI SOL007 3.3.1 package security option 2
Change-Id: I4e021c517449e6ddf11571c02d0b4bdbc93e7c1e Issue-ID: SDC-2614 Signed-off-by: andre.schmid <andre.schmid@est.tech>
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/builder/NsdCsarManifestBuilder.java19
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/factory/EtsiNfvNsdCsarGeneratorFactory.java10
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsCsarEntryGenerator.java19
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGenerator.java4
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGeneratorImpl.java132
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/model/NsdCsar.java110
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/NsdCsarEtsiOption2Signer.java151
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/exception/NsdSignatureException.java31
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/exception/NsdSignatureExceptionSupplier.java39
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/builder/NsdCsarManifestBuilderTest.java18
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsCsarEntryGeneratorTest.java11
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGeneratorImplTest.java41
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/model/NsdCsarTest.java140
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/NsdCsarEtsiOption2SignerTest.java183
-rw-r--r--catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/resources/aFile.txt0
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java1
-rw-r--r--common-be/pom.xml7
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/CertificateManagerImpl.java167
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImpl.java53
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSigner.java98
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/X509CertificateReader.java57
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateManager.java29
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateReader.java34
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CmsContentSigner.java32
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/PrivateKeyReader.java38
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/model/CertificateInfo.java46
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CertificateNotFoundException.java27
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CmsSignatureException.java27
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadCertificateException.java27
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadPrivateKeyException.java27
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/UnsupportedKeyFormatException.java27
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImpl.java70
-rw-r--r--common-be/src/test/java/org/openecomp/sdc/be/csar/security/CertificateManagerImplTest.java141
-rw-r--r--common-be/src/test/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImplTest.java95
-rw-r--r--common-be/src/test/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSignerTest.java119
-rw-r--r--common-be/src/test/java/org/openecomp/sdc/be/csar/security/X509CertificateReaderTest.java81
-rw-r--r--common-be/src/test/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImplTest.java69
-rw-r--r--common-be/src/test/resources/certificateManager/fakeCert1.cert0
-rw-r--r--common-be/src/test/resources/certificateManager/fakeCert1.key0
-rw-r--r--common-be/src/test/resources/certificateManager/fakeCert2.cert0
-rw-r--r--common-be/src/test/resources/certificateManager/fakeCert3.key0
-rw-r--r--common-be/src/test/resources/certificateManager/realCert/realCert1.cert24
-rw-r--r--common-be/src/test/resources/certificateManager/realCert/realCert1.key28
-rw-r--r--common-be/src/test/resources/certificateManager/signerTest/fileToSign.txt1
-rw-r--r--common-be/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker1
-rw-r--r--integration-tests/pom.xml5
-rw-r--r--integration-tests/src/test/resources/cert/catalog-be/nsdCert.cert24
-rw-r--r--integration-tests/src/test/resources/cert/catalog-be/nsdCert.key28
-rw-r--r--integration-tests/src/test/resources/cert/onboarding-be/root.cert (renamed from integration-tests/src/test/resources/cert/root.cert)0
-rw-r--r--openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManagerTest.java53
-rw-r--r--openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/fileToSign.txt1
-rw-r--r--openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/fileToSign.txt.cms18
-rw-r--r--openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/rootCA.cert24
-rw-r--r--openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/rootCA.key28
-rw-r--r--pom.xml1
55 files changed, 2336 insertions, 80 deletions
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/builder/NsdCsarManifestBuilder.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/builder/NsdCsarManifestBuilder.java
index 38f03f12f5..73be4a2100 100644
--- a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/builder/NsdCsarManifestBuilder.java
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/builder/NsdCsarManifestBuilder.java
@@ -1,4 +1,3 @@
-
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
@@ -25,6 +24,7 @@ import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
+import org.apache.commons.lang.StringUtils;
/**
* Builder for the manifest (.mf) file in a NSD CSAR
@@ -45,6 +45,7 @@ public class NsdCsarManifestBuilder {
private final MetadataHeader metadataHeader;
private final Set<String> sources;
private final Set<String> compatibleSpecificationVersions;
+ private String signature;
public NsdCsarManifestBuilder() {
metadataHeader = new MetadataHeader();
@@ -122,6 +123,13 @@ public class NsdCsarManifestBuilder {
return this;
}
+ public NsdCsarManifestBuilder withSignature(final String signature) {
+ if (signature != null) {
+ this.signature = signature.trim();
+ }
+ return this;
+ }
+
/**
* Builds a string representing the manifest content based on provided values.
*
@@ -142,7 +150,14 @@ public class NsdCsarManifestBuilder {
.append(String.join(",", compatibleSpecificationVersions)).append(NEW_LINE);
}
final StringBuilder builder = new StringBuilder();
- builder.append(metadataBuilder).append(compatibleSpecificationVersionsBuilder).append(NEW_LINE).append(sourceBuilder);
+
+ builder.append(metadataBuilder)
+ .append(compatibleSpecificationVersionsBuilder)
+ .append(NEW_LINE)
+ .append(sourceBuilder);
+ if (StringUtils.isNotBlank(signature)) {
+ builder.append(signature);
+ }
return builder.toString();
}
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/factory/EtsiNfvNsdCsarGeneratorFactory.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/factory/EtsiNfvNsdCsarGeneratorFactory.java
index fb08f56ac2..c51dc51854 100644
--- a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/factory/EtsiNfvNsdCsarGeneratorFactory.java
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/factory/EtsiNfvNsdCsarGeneratorFactory.java
@@ -1,4 +1,3 @@
-
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Nordix Foundation
@@ -25,6 +24,7 @@ import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.EtsiNfvNsdCsarGenerat
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.VnfDescriptorGenerator;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.config.EtsiVersion;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.config.NsDescriptorConfig;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.NsdCsarEtsiOption2Signer;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Component;
@@ -35,20 +35,24 @@ public class EtsiNfvNsdCsarGeneratorFactory {
private final NsDescriptorGeneratorFactory nsDescriptorGeneratorFactory;
private final ArtifactCassandraDao artifactCassandraDao;
private final ObjectProvider<EtsiNfvNsdCsarGeneratorImpl> etsiNfvNsdCsarGeneratorObjectProvider;
+ private final NsdCsarEtsiOption2Signer nsdCsarEtsiOption2Signer;
public EtsiNfvNsdCsarGeneratorFactory(final VnfDescriptorGenerator vnfDescriptorGenerator,
final NsDescriptorGeneratorFactory nsDescriptorGeneratorFactory,
final ArtifactCassandraDao artifactCassandraDao,
- final ObjectProvider<EtsiNfvNsdCsarGeneratorImpl> etsiNfvNsdCsarGeneratorObjectProvider) {
+ final ObjectProvider<EtsiNfvNsdCsarGeneratorImpl> etsiNfvNsdCsarGeneratorObjectProvider,
+ final NsdCsarEtsiOption2Signer nsdCsarEtsiOption2Signer) {
this.vnfDescriptorGenerator = vnfDescriptorGenerator;
this.nsDescriptorGeneratorFactory = nsDescriptorGeneratorFactory;
this.artifactCassandraDao = artifactCassandraDao;
this.etsiNfvNsdCsarGeneratorObjectProvider = etsiNfvNsdCsarGeneratorObjectProvider;
+ this.nsdCsarEtsiOption2Signer = nsdCsarEtsiOption2Signer;
}
public EtsiNfvNsdCsarGenerator create(final EtsiVersion version) {
final NsDescriptorConfig nsDescriptorConfig = new NsDescriptorConfig(version);
return etsiNfvNsdCsarGeneratorObjectProvider
- .getObject(nsDescriptorConfig, vnfDescriptorGenerator, nsDescriptorGeneratorFactory, artifactCassandraDao);
+ .getObject(nsDescriptorConfig, vnfDescriptorGenerator, nsDescriptorGeneratorFactory, artifactCassandraDao
+ , nsdCsarEtsiOption2Signer);
}
}
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsCsarEntryGenerator.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsCsarEntryGenerator.java
index 90359a550d..9a7312b0fb 100644
--- a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsCsarEntryGenerator.java
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsCsarEntryGenerator.java
@@ -1,4 +1,3 @@
-
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
@@ -30,6 +29,7 @@ import org.openecomp.sdc.be.plugins.CsarEntryGenerator;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.exception.NsdException;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.factory.EtsiNfvNsdCsarGeneratorFactory;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.config.EtsiVersion;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.NsdCsar;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,7 +40,9 @@ import org.slf4j.LoggerFactory;
public class EtsiNfvNsCsarEntryGenerator implements CsarEntryGenerator {
static final String ETSI_NS_COMPONENT_CATEGORY = "ETSI NFV Network Service";
- static final String NSD_FILE_PATH_FORMAT = "Artifacts/%s/%s.csar";
+ static final String NSD_FILE_PATH_FORMAT = "Artifacts/%s/%s.%s";
+ static final String SIGNED_CSAR_EXTENSION = "zip";
+ static final String UNSIGNED_CSAR_EXTENSION = "csar";
static final String ETSI_VERSION_METADATA = "ETSI Version";
private static final Logger LOGGER = LoggerFactory.getLogger(EtsiNfvNsCsarEntryGenerator.class);
private final EtsiNfvNsdCsarGeneratorFactory etsiNfvNsdCsarGeneratorFactory;
@@ -69,7 +71,8 @@ public class EtsiNfvNsCsarEntryGenerator implements CsarEntryGenerator {
ETSI_NS_COMPONENT_CATEGORY);
return Collections.emptyMap();
}
- final byte[] nsdCsar;
+
+ final NsdCsar nsdCsar;
try {
final EtsiVersion etsiVersion = getComponentEtsiVersion(component);
final EtsiNfvNsdCsarGenerator etsiNfvNsdCsarGenerator = etsiNfvNsdCsarGeneratorFactory.create(etsiVersion);
@@ -81,7 +84,8 @@ public class EtsiNfvNsCsarEntryGenerator implements CsarEntryGenerator {
LOGGER.error("Could not create NSD CSAR entry for component '{}'. An unexpected exception occurred", component.getName(), e);
return Collections.emptyMap();
}
- return createEntry(component.getNormalizedName(), nsdCsar);
+
+ return createEntry(nsdCsar);
}
private EtsiVersion getComponentEtsiVersion(Component component) {
@@ -89,10 +93,11 @@ public class EtsiNfvNsCsarEntryGenerator implements CsarEntryGenerator {
return EtsiVersion.convertOrNull(etsiVersion);
}
- private Map<String, byte[]> createEntry(final String csarName, final byte[] nsdCsar) {
+ private Map<String, byte[]> createEntry(final NsdCsar nsdCsar) {
final Map<String, byte[]> entryMap = new HashMap<>();
- final String entryKey = String.format(NSD_FILE_PATH_FORMAT, ETSI_PACKAGE, csarName);
- entryMap.put(entryKey, nsdCsar);
+ final String extension = nsdCsar.isSigned() ? SIGNED_CSAR_EXTENSION : UNSIGNED_CSAR_EXTENSION;
+ final String entryKey = String.format(NSD_FILE_PATH_FORMAT, ETSI_PACKAGE, nsdCsar.getFileName(), extension);
+ entryMap.put(entryKey, nsdCsar.getCsarPackage());
return entryMap;
}
}
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGenerator.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGenerator.java
index 072c4c5a89..1ad6e82481 100644
--- a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGenerator.java
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGenerator.java
@@ -1,4 +1,3 @@
-
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
@@ -21,6 +20,7 @@ package org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator;
import org.openecomp.sdc.be.model.Component;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.exception.NsdException;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.NsdCsar;
/**
* Generator for a ETSI NFV NSD CSAR
@@ -33,5 +33,5 @@ public interface EtsiNfvNsdCsarGenerator {
* @param component the service component
* @return the CSAR package content
*/
- byte[] generateNsdCsar(Component component) throws NsdException;
+ NsdCsar generateNsdCsar(Component component) throws NsdException;
}
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGeneratorImpl.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGeneratorImpl.java
index e7d30197d7..f9e0970ba9 100644
--- a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGeneratorImpl.java
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGeneratorImpl.java
@@ -1,4 +1,3 @@
-
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
@@ -23,10 +22,13 @@ import static org.openecomp.sdc.common.api.ArtifactTypeEnum.ETSI_PACKAGE;
import static org.openecomp.sdc.common.api.ArtifactTypeEnum.ONBOARDED_PACKAGE;
import fj.data.Either;
+import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -36,9 +38,11 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
+import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang.StringUtils;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
@@ -53,7 +57,9 @@ import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.config.EtsiVersion;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.config.NsDescriptorConfig;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.config.NsDescriptorVersionComparator;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.Nsd;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.NsdCsar;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.VnfDescriptor;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.NsdCsarEtsiOption2Signer;
import org.openecomp.sdc.be.resources.data.DAOArtifactData;
import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
import org.slf4j.Logger;
@@ -74,6 +80,8 @@ public class EtsiNfvNsdCsarGeneratorImpl implements EtsiNfvNsdCsarGenerator {
private static final String MANIFEST_EXT = "mf";
private static final String SLASH = "/";
private static final String DOT = ".";
+ private static final String SIGNATURE_EXTENSION = ".sig.cms";
+ private static final String CSAR_EXTENSION = ".csar";
private static final String DOT_YAML = DOT + "yaml";
private static final String DEFINITION = "Definitions";
private static final String TOSCA_META_PATH = "TOSCA-Metadata/TOSCA.meta";
@@ -81,18 +89,21 @@ public class EtsiNfvNsdCsarGeneratorImpl implements EtsiNfvNsdCsarGenerator {
private final NsDescriptorGeneratorFactory nsDescriptorGeneratorFactory;
private final ArtifactCassandraDao artifactCassandraDao;
private final NsDescriptorConfig nsDescriptorConfig;
+ private final NsdCsarEtsiOption2Signer nsdCsarEtsiOption2Signer;
public EtsiNfvNsdCsarGeneratorImpl(final NsDescriptorConfig nsDescriptorConfig, final VnfDescriptorGenerator vnfDescriptorGenerator,
final NsDescriptorGeneratorFactory nsDescriptorGeneratorFactory,
- final ArtifactCassandraDao artifactCassandraDao) {
+ final ArtifactCassandraDao artifactCassandraDao,
+ final NsdCsarEtsiOption2Signer nsdCsarEtsiOption2Signer) {
this.nsDescriptorConfig = nsDescriptorConfig;
this.vnfDescriptorGenerator = vnfDescriptorGenerator;
this.nsDescriptorGeneratorFactory = nsDescriptorGeneratorFactory;
this.artifactCassandraDao = artifactCassandraDao;
+ this.nsdCsarEtsiOption2Signer = nsdCsarEtsiOption2Signer;
}
@Override
- public byte[] generateNsdCsar(final Component component) throws NsdException {
+ public NsdCsar generateNsdCsar(final Component component) throws NsdException {
if (component == null) {
throw new NsdException("Could not generate the NSD CSAR, invalid component argument");
}
@@ -101,23 +112,43 @@ public class EtsiNfvNsdCsarGeneratorImpl implements EtsiNfvNsdCsarGenerator {
final String componentName = component.getName();
try {
LOGGER.debug("Starting NSD CSAR generation for component '{}'", componentName);
- final Map<String, byte[]> nsdCsarFiles = new HashMap<>();
- final List<VnfDescriptor> vnfDescriptorList = generateVnfPackages(component);
- vnfDescriptorList.forEach(vnfPackage -> nsdCsarFiles.putAll(vnfPackage.getDefinitionFiles()));
final String nsdFileName = getNsdFileName(component);
+ final NsdCsar nsdCsar = new NsdCsar(nsdFileName);
+
+ final List<VnfDescriptor> vnfDescriptorList = generateVnfPackages(component);
+ vnfDescriptorList.forEach(vnfPackage -> nsdCsar.addAllFiles(vnfPackage.getDefinitionFiles()));
+
final EtsiVersion etsiVersion = nsDescriptorConfig.getNsVersion();
final Nsd nsd = generateNsd(component, vnfDescriptorList);
- nsdCsarFiles.put(getNsdPath(nsdFileName), nsd.getContents());
- nsdCsarFiles.put(TOSCA_META_PATH, buildToscaMetaContent(nsdFileName).getBytes());
- addEtsiSolNsdTypes(etsiVersion, nsdCsarFiles);
+
+ nsdCsar.addFile(getNsdPath(nsdFileName), nsd.getContents());
+ nsdCsar.addFile(TOSCA_META_PATH, buildToscaMetaContent(nsdFileName).getBytes());
+
+ nsdCsar.addAllFiles(createEtsiSolNsdTypeEntries(etsiVersion));
for (final String referencedFile : nsd.getArtifactReferences()) {
getReferencedArtifact(component, referencedFile)
- .ifPresent(artifactDefinition -> nsdCsarFiles.put(referencedFile, artifactDefinition.getPayloadData()));
+ .ifPresent(artifactDefinition -> nsdCsar.addFile(referencedFile, artifactDefinition.getPayloadData())
+ );
+ }
+ final boolean isCertificateConfigured = nsdCsarEtsiOption2Signer.isCertificateConfigured();
+ final String manifestPath = getManifestPath(nsdFileName);
+ final NsdCsarManifestBuilder manifestBuilder =
+ createManifestBuilder(nsd, etsiVersion, manifestPath, nsdCsar.getFileMap().keySet(), isCertificateConfigured);
+
+ nsdCsar.addManifest(manifestBuilder);
+
+ if (isCertificateConfigured) {
+ nsdCsarEtsiOption2Signer.signArtifacts(nsdCsar);
+ }
+
+ byte[] package1 = buildCsarPackage(nsdCsar.getFileMap());
+ if (isCertificateConfigured) {
+ package1 = buildZipWithCsarAndSignature(nsdCsar.getFileName(), package1);
+ nsdCsar.setSigned(true);
}
- nsdCsarFiles.put(getManifestPath(nsdFileName), getManifestFileContent(nsd, etsiVersion, nsdCsarFiles.keySet()).getBytes());
- final byte[] csar = buildCsarPackage(nsdCsarFiles);
+ nsdCsar.setCsarPackage(package1);
LOGGER.debug("Successfully generated NSD CSAR package");
- return csar;
+ return nsdCsar;
} catch (final Exception exception) {
throw new NsdException("Could not generate the NSD CSAR file", exception);
}
@@ -205,29 +236,41 @@ public class EtsiNfvNsdCsarGeneratorImpl implements EtsiNfvNsdCsarGenerator {
}).findFirst();
}
- private void addEtsiSolNsdTypes(final EtsiVersion etsiVersion, final Map<String, byte[]> nsdCsarFileMap) {
+ private Map<String, byte[]> createEtsiSolNsdTypeEntries(final EtsiVersion etsiVersion) {
final EtsiVersion currentVersion = etsiVersion == null ? EtsiVersion.getDefaultVersion() : etsiVersion;
+
final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
final Resource[] resources =
resolver.getResources(String.format("classpath:etsi-nfv-types/%s/*.*", currentVersion.getVersion()));
if (resources.length > 0) {
+ final Map<String, byte[]> entryMap = new HashMap<>();
for (final Resource resource : resources) {
- addToCsarFileMap(resource, nsdCsarFileMap);
+ readResource(resource).ifPresent(resourceBytes -> {
+ final String entryName = createDefinitionEntryName(resource.getFilename());
+ entryMap.put(entryName, resourceBytes);
+ });
}
+ return entryMap;
}
} catch (final IOException e) {
LOGGER.error("Could not find types files for the version '{}'", currentVersion.getVersion(), e);
}
+
+ return Collections.emptyMap();
+ }
+
+ private String createDefinitionEntryName(final String fileName) {
+ return DEFINITION + "/" + fileName;
}
- private void addToCsarFileMap(final Resource resource, final Map<String, byte[]> nsdCsarFileMap) {
+ private Optional<byte[]> readResource(final Resource resource) {
try {
- nsdCsarFileMap.put(DEFINITION + "/" + resource.getFilename(),
- IOUtils.toByteArray(resource.getInputStream()));
+ return Optional.ofNullable(IOUtils.toByteArray(resource.getInputStream()));
} catch (final IOException exception) {
LOGGER.error("Error adding '{}' to NSD CSAR", resource.getFilename(), exception);
}
+ return Optional.empty();
}
private Nsd generateNsd(final Component component,
@@ -294,18 +337,24 @@ public class EtsiNfvNsdCsarGeneratorImpl implements EtsiNfvNsdCsarGenerator {
return toscaMetadata;
}
- private String getManifestFileContent(final Nsd nsd,
- final EtsiVersion nsdVersion,
- final Set<String> files) {
+ private NsdCsarManifestBuilder createManifestBuilder(final Nsd nsd, final EtsiVersion nsdVersion,
+ final String manifestFilePath, final Set<String> filePath,
+ final boolean addSignatureFiles) {
LOGGER.debug("Creating NS manifest file content");
+ final Set<String> filesToAdd = new HashSet<>(filePath);
+ if (addSignatureFiles) {
+ filePath.forEach(file -> filesToAdd.add(file + SIGNATURE_EXTENSION));
+ }
+ filesToAdd.add(manifestFilePath);
+
final NsdCsarManifestBuilder nsdCsarManifestBuilder = new NsdCsarManifestBuilder();
nsdCsarManifestBuilder.withDesigner(nsd.getDesigner())
.withInvariantId(nsd.getInvariantId())
.withName(nsd.getName())
.withNowReleaseDateTime()
.withFileStructureVersion(nsd.getVersion())
- .withSources(files);
+ .withSources(filesToAdd);
final NsDescriptorVersionComparator nsdVersionComparator = new NsDescriptorVersionComparator();
@@ -313,10 +362,10 @@ public class EtsiNfvNsdCsarGeneratorImpl implements EtsiNfvNsdCsarGenerator {
nsdCsarManifestBuilder.withCompatibleSpecificationVersion(nsdVersion.getVersion());
}
- final String manifest = nsdCsarManifestBuilder.build();
- LOGGER.debug("Successfully created NS CSAR manifest file content:\n {}", manifest);
- return manifest;
-
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Successfully created NS CSAR manifest file content:\n {}", nsdCsarManifestBuilder.build());
+ }
+ return nsdCsarManifestBuilder;
}
private String getManifestPath(final String nsdFileName) {
@@ -358,6 +407,37 @@ public class EtsiNfvNsdCsarGeneratorImpl implements EtsiNfvNsdCsarGenerator {
}
}
+ private byte[] buildZipWithCsarAndSignature(final String csarFileName, final byte[] csarPackageBytes) throws NsdException {
+ final byte[] signature;
+ try {
+ signature = nsdCsarEtsiOption2Signer.sign(csarPackageBytes);
+ } catch (final Exception e) {
+ throw new NsdException(String.format("Could not sign the CSAR '%s'", csarFileName), e);
+ }
+ final Optional<CertificateInfo> certificateInfoOpt = nsdCsarEtsiOption2Signer.getSigningCertificate();
+ if (certificateInfoOpt.isEmpty()) {
+ throw new NsdException(String.format("Could not sign the CSAR '%s'. No certificate configured.", csarFileName));
+ }
+ final CertificateInfo certificateInfo = certificateInfoOpt.get();
+ try (final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final ZipOutputStream zip = new ZipOutputStream(out)) {
+ zip.putNextEntry(new ZipEntry(csarFileName + CSAR_EXTENSION));
+ zip.write(csarPackageBytes);
+ zip.putNextEntry(new ZipEntry(csarFileName + SIGNATURE_EXTENSION));
+ zip.write(signature);
+ final File certificateFile = certificateInfo.getCertificateFile();
+ zip.putNextEntry(new ZipEntry(csarFileName + "." + FilenameUtils.getExtension(certificateFile.getName())));
+ zip.write(Files.readAllBytes(certificateFile.toPath()));
+ zip.flush();
+ zip.finish();
+ LOGGER.debug("NSD signed CSAR zip file was successfully built");
+
+ return out.toByteArray();
+ } catch (final IOException e) {
+ throw new NsdException("Could not build the NSD signed CSAR zip file", e);
+ }
+ }
+
}
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/model/NsdCsar.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/model/NsdCsar.java
new file mode 100644
index 0000000000..733604529a
--- /dev/null
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/model/NsdCsar.java
@@ -0,0 +1,110 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.plugins.etsi.nfv.nsd.model;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import lombok.Getter;
+import lombok.Setter;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.builder.NsdCsarManifestBuilder;
+
+/**
+ * Represents a NSD CSAR package
+ */
+public class NsdCsar {
+
+ private static final String MANIFEST_EXTENSION = "mf";
+ private static final String YAML_EXTENSION = "yaml";
+ private static final String DOT = ".";
+ private static final String SLASH = "/";
+ private static final String DEFINITIONS = "Definitions";
+
+ private final Map<String, byte[]> fileMap = new HashMap<>();
+ @Getter
+ private final String fileName;
+ @Getter
+ @Setter
+ private byte[] csarPackage;
+ @Getter
+ @Setter
+ private boolean isSigned;
+ @Getter
+ private NsdCsarManifestBuilder manifestBuilder;
+
+ public NsdCsar(final String fileName) {
+ this.fileName = fileName;
+ manifestBuilder = new NsdCsarManifestBuilder();
+ }
+
+ public void addFile(final String filePath, final byte[] fileBytes) {
+ fileMap.put(filePath, fileBytes);
+ }
+
+ public byte[] getFile(final String filePath) {
+ return fileMap.get(filePath);
+ }
+
+ public byte[] getManifest() {
+ return fileMap.get(getManifestPath());
+ }
+
+ public byte[] getMainDefinition() {
+ return fileMap.get(getMainDefinitionPath());
+ }
+
+ public Map<String, byte[]> getFileMap() {
+ return new HashMap<>(fileMap);
+ }
+
+ public String getManifestPath() {
+ return fileName + DOT + MANIFEST_EXTENSION;
+ }
+
+ public boolean isManifest(final String filePath) {
+ return getManifestPath().equals(filePath);
+ }
+
+ public String getMainDefinitionPath() {
+ return DEFINITIONS + SLASH + fileName + YAML_EXTENSION;
+ }
+
+ public void addAllFiles(final Map<String, byte[]> definitionFiles) {
+ fileMap.putAll(definitionFiles);
+ }
+
+ /**
+ * Sets a manifest builder and build it, adding its content to the to the CSAR files. Ignores {@code null} manifest builders.
+ *
+ * @param manifestBuilder the manifest builder
+ */
+ public void addManifest(final NsdCsarManifestBuilder manifestBuilder) {
+ if (manifestBuilder == null) {
+ return;
+ }
+ this.manifestBuilder = manifestBuilder;
+ final String manifestContent = manifestBuilder.build();
+ addFile(getManifestPath(), manifestContent.getBytes(StandardCharsets.UTF_8));
+ }
+
+ public boolean isEmpty() {
+ return fileMap.isEmpty();
+ }
+}
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/NsdCsarEtsiOption2Signer.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/NsdCsarEtsiOption2Signer.java
new file mode 100644
index 0000000000..abba32ad8d
--- /dev/null
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/NsdCsarEtsiOption2Signer.java
@@ -0,0 +1,151 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.plugins.etsi.nfv.nsd.security;
+
+import java.nio.charset.StandardCharsets;
+import java.security.Key;
+import java.security.cert.Certificate;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.openecomp.sdc.be.csar.security.api.CertificateManager;
+import org.openecomp.sdc.be.csar.security.api.CmsContentSigner;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
+import org.openecomp.sdc.be.csar.security.exception.CmsSignatureException;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.builder.NsdCsarManifestBuilder;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.NsdCsar;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.exception.NsdSignatureException;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.exception.NsdSignatureExceptionSupplier;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+/**
+ * Handles NSD CSAR file and package signature, following the ETSI SOL007 v3.3.1, section 5.1, signing option 2.
+ *
+ * @see <a href="https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/007/03.03.01_60/gs_NFV-SOL007v030301p.pdf">ETSI SOL007 v3.3.1 documentation</a>
+ */
+@Component
+public class NsdCsarEtsiOption2Signer {
+
+ public static final String SDC_NSD_CERT_NAME = "SDC_NSD_CERT_NAME";
+ public static final String SIGNATURE_EXTENSION = ".sig.cms";
+
+ private final CertificateManager certificateManager;
+ private final CmsContentSigner cmsContentSigner;
+ private final Environment environment;
+
+ public NsdCsarEtsiOption2Signer(final CertificateManager certificateManager,
+ final CmsContentSigner cmsContentSigner,
+ final Environment environment) {
+ this.certificateManager = certificateManager;
+ this.cmsContentSigner = cmsContentSigner;
+ this.environment = environment;
+ }
+
+ /**
+ * Sign each NSD CSAR artifact (files), generating a cms file for each. The manifest, though, have its signature added in its body instead of a separate
+ * CMS file. Modifies the given NSD CSAR by adding the file signatures and the modified manifest.
+ *
+ * @param nsdCsar the NSD CSAR
+ * @throws NsdSignatureException when there was a problem while creating a file signature
+ */
+ public void signArtifacts(final NsdCsar nsdCsar) throws NsdSignatureException {
+ if (nsdCsar == null) {
+ return;
+ }
+ //ignore the manifest, the signature of the manifest goes inside the manifest itself ETSI 3.3.1 section 5.3
+ final Map<String, byte[]> fileMap = nsdCsar.getFileMap().entrySet().stream()
+ .filter(entry -> !nsdCsar.isManifest(entry.getKey()))
+ .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
+
+ for (final Entry<String, byte[]> fileEntry : fileMap.entrySet()) {
+ final byte[] signatureBytes = sign(fileEntry.getValue());
+ final String filePath = fileEntry.getKey();
+ nsdCsar.addFile(filePath + SIGNATURE_EXTENSION, signatureBytes);
+ }
+
+ signManifest(nsdCsar);
+ }
+
+ private void signManifest(final NsdCsar nsdCsar) throws NsdSignatureException {
+ final Optional<Entry<String, byte[]>> manifestEntryOpt = nsdCsar.getFileMap().entrySet().stream()
+ .filter(entry -> nsdCsar.isManifest(entry.getKey())).findFirst();
+ if (manifestEntryOpt.isEmpty()) {
+ return;
+ }
+ final CertificateInfo certificateInfo = getValidCertificate();
+
+ final Entry<String, byte[]> manifestEntry = manifestEntryOpt.get();
+ final String pemSignature = createFileSignature(certificateInfo.getCertificate(),
+ certificateInfo.getPrivateKey(), manifestEntry.getValue());
+ final NsdCsarManifestBuilder manifestBuilder = nsdCsar.getManifestBuilder();
+ manifestBuilder.withSignature(pemSignature);
+ nsdCsar.addManifest(manifestBuilder);
+ }
+
+ /**
+ * Sign a file, creating the PEM format signature and returning its bytes.
+ *
+ * @param fileBytes the file to sign
+ * @return the bytes of the PEM format signature created from the given file and the NSD certificate
+ * @throws NsdSignatureException when it was not possible to retrieve the NSD certificate
+ * @throws NsdSignatureException when the NSD certificate is invalid
+ * @throws NsdSignatureException it was not possible to sign the file
+ */
+ public byte[] sign(final byte[] fileBytes) throws NsdSignatureException {
+ final CertificateInfo certificateInfo = getValidCertificate();
+ final String pemSignature =
+ createFileSignature(certificateInfo.getCertificate(), certificateInfo.getPrivateKey(), fileBytes);
+ return pemSignature.getBytes(StandardCharsets.UTF_8);
+ }
+
+ public Optional<CertificateInfo> getSigningCertificate() {
+ final String sdcNsdCertName = environment.getProperty(SDC_NSD_CERT_NAME);
+ return certificateManager.getCertificate(sdcNsdCertName);
+ }
+
+ public boolean isCertificateConfigured() {
+ return getSigningCertificate().isPresent();
+ }
+
+ private CertificateInfo getValidCertificate() throws NsdSignatureException {
+ final Optional<CertificateInfo> certificateInfoOpt = getSigningCertificate();
+ if (certificateInfoOpt.isEmpty()) {
+ throw NsdSignatureExceptionSupplier.certificateNotConfigured();
+ }
+ final CertificateInfo certificateInfo = certificateInfoOpt.get();
+ if (!certificateInfo.isValid()) {
+ throw NsdSignatureExceptionSupplier.invalidCertificate(certificateInfo.getName());
+ }
+
+ return certificateInfo;
+ }
+
+ private String createFileSignature(final Certificate certificate, final Key privateKey,
+ final byte[] fileBytes) throws NsdSignatureException {
+ try {
+ final byte[] dataSignature = cmsContentSigner.signData(fileBytes, certificate, privateKey);
+ return cmsContentSigner.formatToPemSignature(dataSignature);
+ } catch (final CmsSignatureException e) {
+ throw NsdSignatureExceptionSupplier.unableToCreateSignature(e);
+ }
+ }
+}
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/exception/NsdSignatureException.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/exception/NsdSignatureException.java
new file mode 100644
index 0000000000..1591a5e294
--- /dev/null
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/exception/NsdSignatureException.java
@@ -0,0 +1,31 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.plugins.etsi.nfv.nsd.security.exception;
+
+public class NsdSignatureException extends Exception {
+
+ public NsdSignatureException(final String message) {
+ super(message);
+ }
+
+ public NsdSignatureException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/exception/NsdSignatureExceptionSupplier.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/exception/NsdSignatureExceptionSupplier.java
new file mode 100644
index 0000000000..696a8d8626
--- /dev/null
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/exception/NsdSignatureExceptionSupplier.java
@@ -0,0 +1,39 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.plugins.etsi.nfv.nsd.security.exception;
+
+public final class NsdSignatureExceptionSupplier {
+
+ private NsdSignatureExceptionSupplier() {
+ }
+
+ public static NsdSignatureException invalidCertificate(final String certificateName) {
+ return new NsdSignatureException(String.format("The certificate '%s' is invalid", certificateName));
+ }
+
+ public static NsdSignatureException certificateNotConfigured() {
+ return new NsdSignatureException("No certificate configured");
+ }
+
+ public static NsdSignatureException unableToCreateSignature(final Exception e) {
+ return new NsdSignatureException("Could create file signature", e);
+ }
+
+} \ No newline at end of file
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/builder/NsdCsarManifestBuilderTest.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/builder/NsdCsarManifestBuilderTest.java
index 1ff3a6d52b..caca932929 100644
--- a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/builder/NsdCsarManifestBuilderTest.java
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/builder/NsdCsarManifestBuilderTest.java
@@ -1,4 +1,3 @@
-
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Nordix Foundation
@@ -43,6 +42,10 @@ class NsdCsarManifestBuilderTest {
nsdCsarManifestBuilder.withFileStructureVersion("fileStructureVersion");
nsdCsarManifestBuilder.withCompatibleSpecificationVersion("1.0.0");
nsdCsarManifestBuilder.withCompatibleSpecificationVersion("1.0.1");
+ final String signature = "-----BEGIN CMS-----\n"
+ + "12d08j19d981928129dj129j1\n"
+ + "-----END CMS-----";
+ nsdCsarManifestBuilder.withSignature(signature);
final List<String> sourceList = new ArrayList<>();
final String source1 = "Definitions/aSource1.yaml";
sourceList.add(source1);
@@ -53,9 +56,16 @@ class NsdCsarManifestBuilderTest {
assertSource(manifest, source1);
assertSource(manifest, source2);
assertCompatibleSpecificationVersions(manifest, "1.0.0,1.0.1");
- final String expectedManifest = "metadata: \n" + "nsd_designer: designer\n" + "nsd_invariant_id: invariantId\n" + "nsd_name: name\n"
- + "nsd_file_structure_version: fileStructureVersion\n" + "compatible_specification_versions: 1.0.0,1.0.1\n" + "\n"
- + "Source: Definitions/aSource1.yaml\n" + "Source: Definitions/aSource2.yaml\n" + "";
+ final String expectedManifest = "metadata: \n"
+ + "nsd_designer: designer\n"
+ + "nsd_invariant_id: invariantId\n"
+ + "nsd_name: name\n"
+ + "nsd_file_structure_version: fileStructureVersion\n"
+ + "compatible_specification_versions: 1.0.0,1.0.1\n"
+ + "\n"
+ + "Source: Definitions/aSource1.yaml\n"
+ + "Source: Definitions/aSource2.yaml\n"
+ + signature;
assertEquals(expectedManifest, manifest);
}
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsCsarEntryGeneratorTest.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsCsarEntryGeneratorTest.java
index 8ebd1df190..837179d50d 100644
--- a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsCsarEntryGeneratorTest.java
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsCsarEntryGeneratorTest.java
@@ -1,4 +1,3 @@
-
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
@@ -27,6 +26,7 @@ import static org.mockito.Mockito.when;
import static org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.EtsiNfvNsCsarEntryGenerator.ETSI_NS_COMPONENT_CATEGORY;
import static org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.EtsiNfvNsCsarEntryGenerator.ETSI_VERSION_METADATA;
import static org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.EtsiNfvNsCsarEntryGenerator.NSD_FILE_PATH_FORMAT;
+import static org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.EtsiNfvNsCsarEntryGenerator.UNSIGNED_CSAR_EXTENSION;
import static org.openecomp.sdc.common.api.ArtifactTypeEnum.ETSI_PACKAGE;
import java.util.ArrayList;
@@ -44,6 +44,7 @@ import org.openecomp.sdc.be.model.category.CategoryDefinition;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.exception.NsdException;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.factory.EtsiNfvNsdCsarGeneratorFactory;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.config.EtsiVersion;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.NsdCsar;
class EtsiNfvNsCsarEntryGeneratorTest {
@@ -68,12 +69,14 @@ class EtsiNfvNsCsarEntryGeneratorTest {
@Test
void successfullyEntryGenerationTest() throws NsdException {
mockServiceComponent();
- final byte[] expectedNsdCsar = new byte[5];
- when(etsiNfvNsdCsarGenerator.generateNsdCsar(service)).thenReturn(expectedNsdCsar);
+ final NsdCsar nsdCsar = new NsdCsar(SERVICE_NORMALIZED_NAME);
+ nsdCsar.setCsarPackage(new byte[5]);
+ when(etsiNfvNsdCsarGenerator.generateNsdCsar(service)).thenReturn(nsdCsar);
final Map<String, byte[]> entryMap = etsiNfvNsCsarEntryGenerator.generateCsarEntries(service);
assertThat("Csar Entries should contain only one entry", entryMap.size(), is(1));
assertThat("Csar Entries should contain the expected entry", entryMap,
- hasEntry(String.format(NSD_FILE_PATH_FORMAT, ETSI_PACKAGE, SERVICE_NORMALIZED_NAME), expectedNsdCsar));
+ hasEntry(String.format(NSD_FILE_PATH_FORMAT, ETSI_PACKAGE, SERVICE_NORMALIZED_NAME, UNSIGNED_CSAR_EXTENSION),
+ nsdCsar.getCsarPackage()));
}
@Test
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGeneratorImplTest.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGeneratorImplTest.java
index b498c45d1f..b1b8157534 100644
--- a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGeneratorImplTest.java
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/generator/EtsiNfvNsdCsarGeneratorImplTest.java
@@ -1,4 +1,3 @@
-
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation
@@ -23,12 +22,16 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.EtsiNfvNsCsarEntryGenerator.ETSI_NS_COMPONENT_CATEGORY;
import static org.openecomp.sdc.common.api.ArtifactTypeEnum.ONBOARDED_PACKAGE;
import fj.data.Either;
+import java.io.File;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -39,6 +42,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.csar.security.model.CertificateInfoImpl;
import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
@@ -52,7 +56,10 @@ import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.factory.NsDescriptorGeneratorFa
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.config.EtsiVersion;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator.config.NsDescriptorConfig;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.Nsd;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.NsdCsar;
import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.VnfDescriptor;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.NsdCsarEtsiOption2Signer;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.exception.NsdSignatureException;
import org.openecomp.sdc.be.resources.data.DAOArtifactData;
class EtsiNfvNsdCsarGeneratorImplTest {
@@ -67,6 +74,8 @@ class EtsiNfvNsdCsarGeneratorImplTest {
@Mock
private ArtifactCassandraDao artifactCassandraDao;
@Mock
+ private NsdCsarEtsiOption2Signer nsdCsarEtsiOption2Signer;
+ @Mock
private Service service;
private EtsiNfvNsdCsarGeneratorImpl etsiNfvNsdCsarGenerator;
@@ -74,8 +83,8 @@ class EtsiNfvNsdCsarGeneratorImplTest {
void setUp() {
MockitoAnnotations.initMocks(this);
final EtsiVersion version2_5_1 = EtsiVersion.VERSION_2_5_1;
- etsiNfvNsdCsarGenerator = new EtsiNfvNsdCsarGeneratorImpl(new NsDescriptorConfig(version2_5_1), vnfDescriptorGenerator,
- nsDescriptorGeneratorFactory, artifactCassandraDao);
+ etsiNfvNsdCsarGenerator = new EtsiNfvNsdCsarGeneratorImpl(new NsDescriptorConfig(version2_5_1),
+ vnfDescriptorGenerator, nsDescriptorGeneratorFactory, artifactCassandraDao, nsdCsarEtsiOption2Signer);
when(nsDescriptorGeneratorFactory.create()).thenReturn(nsDescriptorGeneratorImpl);
}
@@ -83,8 +92,29 @@ class EtsiNfvNsdCsarGeneratorImplTest {
void generateNsdCsarSuccessfulTest() throws VnfDescriptorException, NsdException {
mockServiceComponent();
mockServiceComponentArtifacts();
- final byte[] nsdCsar = etsiNfvNsdCsarGenerator.generateNsdCsar(service);
- assertThat("", nsdCsar, is(notNullValue()));
+ final NsdCsar nsdCsar = etsiNfvNsdCsarGenerator.generateNsdCsar(service);
+ assertThat("The NSD CSAR should not be null", nsdCsar, is(notNullValue()));
+ assertThat("The NSD CSAR should not be signed", nsdCsar.isSigned(), is(false));
+ assertThat("The NSD CSAR content should not be null", nsdCsar.getCsarPackage(), is(notNullValue()));
+ }
+
+ @Test
+ void generateSignedNsdCsarSuccessfulTest() throws VnfDescriptorException, NsdException, NsdSignatureException {
+ mockServiceComponent();
+ mockServiceComponentArtifacts();
+ when(nsdCsarEtsiOption2Signer.isCertificateConfigured()).thenReturn(true);
+ final String path = getClass().getClassLoader().getResource("aFile.txt").getPath();
+ System.out.println(path);
+ final CertificateInfoImpl certificateInfo = new CertificateInfoImpl(new File(path), null);
+ when(nsdCsarEtsiOption2Signer.getSigningCertificate()).thenReturn(Optional.of(certificateInfo));
+ when(nsdCsarEtsiOption2Signer.sign(any(byte[].class))).thenReturn("signedCsar".getBytes(StandardCharsets.UTF_8));
+ final NsdCsar nsdCsar = etsiNfvNsdCsarGenerator.generateNsdCsar(service);
+ verify(nsdCsarEtsiOption2Signer).signArtifacts(any(NsdCsar.class));
+ assertThat("The NSD CSAR should not be null", nsdCsar, is(notNullValue()));
+ assertThat("The NSD CSAR should be signed", nsdCsar.isSigned(), is(true));
+ assertThat("The NSD CSAR content should not be null", nsdCsar.getCsarPackage(), is(notNullValue()));
+ assertThat("The NSD CSAR name should be as expected", nsdCsar.getFileName(), is(SERVICE_NORMALIZED_NAME));
+ assertThat("The NSD CSAR name should be as expected", nsdCsar.isEmpty(), is(false));
}
@Test()
@@ -103,6 +133,7 @@ class EtsiNfvNsdCsarGeneratorImplTest {
final Nsd nsd = new Nsd();
when(vnfDescriptorGenerator.generate(componentInstance1Name, instanceArtifact1)).thenReturn(Optional.of(vnfDescriptor1));
when(nsDescriptorGeneratorImpl.generate(service, vnfDescriptorList)).thenReturn(Optional.of(nsd));
+
final List<CategoryDefinition> categoryDefinitionList = new ArrayList<>();
final CategoryDefinition nsComponentCategoryDefinition = new CategoryDefinition();
nsComponentCategoryDefinition.setName(ETSI_NS_COMPONENT_CATEGORY);
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/model/NsdCsarTest.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/model/NsdCsarTest.java
new file mode 100644
index 0000000000..061a52a2dc
--- /dev/null
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/model/NsdCsarTest.java
@@ -0,0 +1,140 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.plugins.etsi.nfv.nsd.model;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.builder.NsdCsarManifestBuilder;
+
+class NsdCsarTest {
+
+ @Test
+ void testAddFile() {
+ final NsdCsar nsdCsar = new NsdCsar("");
+ assertTrue(nsdCsar.getFileMap().isEmpty());
+ final String aFilePath = "aFile";
+ final byte[] fileContent = aFilePath.getBytes(StandardCharsets.UTF_8);
+ nsdCsar.addFile(aFilePath, fileContent);
+ assertEquals(1, nsdCsar.getFileMap().size());
+ assertEquals(fileContent, nsdCsar.getFile(aFilePath));
+ }
+
+ @Test
+ void testGetFile() {
+ final NsdCsar nsdCsar = new NsdCsar("");
+ final String aFilePath = "aFile";
+ assertNull(nsdCsar.getFile(aFilePath));
+ final byte[] fileContent = aFilePath.getBytes(StandardCharsets.UTF_8);
+ nsdCsar.addFile(aFilePath, fileContent);
+ assertEquals(1, nsdCsar.getFileMap().size());
+ assertEquals(fileContent, nsdCsar.getFile(aFilePath));
+ }
+
+ @Test
+ void testIsManifest() {
+ final NsdCsar nsdCsar = new NsdCsar("");
+ assertTrue(nsdCsar.isManifest(nsdCsar.getManifestPath()));
+ assertFalse(nsdCsar.isManifest(""));
+ }
+
+ @Test
+ void testGetManifest() {
+ final NsdCsar nsdCsar = new NsdCsar("");
+ assertNull(nsdCsar.getManifest());
+ final byte[] expectedManifest = "".getBytes(StandardCharsets.UTF_8);
+ nsdCsar.addFile(nsdCsar.getManifestPath(), expectedManifest);
+ final byte[] actualManifest = nsdCsar.getManifest();
+ assertNotNull(actualManifest);
+ assertEquals(actualManifest, expectedManifest);
+ }
+
+ @Test
+ void testGetMainDefinition() {
+ final String csarFileName = "csarFileName";
+ final NsdCsar nsdCsar = new NsdCsar(csarFileName);
+ assertNull(nsdCsar.getMainDefinition());
+ assertTrue(nsdCsar.getMainDefinitionPath().contains(csarFileName));
+ final byte[] expectedMainDefinition = "".getBytes(StandardCharsets.UTF_8);
+ nsdCsar.addFile(nsdCsar.getMainDefinitionPath(), expectedMainDefinition);
+ final byte[] actualMainDefinition = nsdCsar.getMainDefinition();
+ assertNotNull(actualMainDefinition);
+ assertEquals(actualMainDefinition, expectedMainDefinition);
+ }
+
+ @Test
+ void testFileMapEncapsulation() {
+ final NsdCsar nsdCsar = new NsdCsar("");
+ final Map<String, byte[]> fileMap = nsdCsar.getFileMap();
+ fileMap.put("", new byte[]{});
+ assertTrue(nsdCsar.getFileMap().isEmpty());
+ }
+
+ @Test
+ void addAllFiles() {
+ final NsdCsar nsdCsar = new NsdCsar("");
+ assertTrue(nsdCsar.isEmpty());
+ Map<String, byte[]> fileMap = new HashMap();
+ fileMap.put("1", new byte[]{});
+ fileMap.put("2", new byte[]{});
+ fileMap.put("3", new byte[]{});
+ fileMap.put("4", new byte[]{});
+ nsdCsar.addAllFiles(fileMap);
+ assertFalse(nsdCsar.isEmpty());
+ assertEquals(nsdCsar.getFileMap().size(), fileMap.size());
+ }
+
+ @Test
+ void testIfStartsEmpty() {
+ final NsdCsar nsdCsar = new NsdCsar("test");
+ assertTrue(nsdCsar.getFileMap().isEmpty(), "Csar should starts empty");
+ assertTrue(nsdCsar.isEmpty(), "Csar should starts empty");
+ }
+
+ @Test
+ void testIsEmpty() {
+ final NsdCsar nsdCsar = new NsdCsar("test");
+ assertTrue(nsdCsar.isEmpty());
+ nsdCsar.addFile("", new byte[]{});
+ assertFalse(nsdCsar.isEmpty());
+ }
+
+ @Test
+ void testAddManifest() {
+ final NsdCsar nsdCsar = new NsdCsar("test");
+ nsdCsar.addManifest(null);
+ assertTrue(nsdCsar.isEmpty());
+ final NsdCsarManifestBuilder manifestBuilder = new NsdCsarManifestBuilder();
+ nsdCsar.addManifest(manifestBuilder);
+ assertFalse(nsdCsar.isEmpty());
+ assertEquals(1, nsdCsar.getFileMap().size());
+ final byte[] expectedManifestContent = manifestBuilder.build().getBytes(StandardCharsets.UTF_8);
+ assertThat("Manifest content should be the same", nsdCsar.getManifest(), is(expectedManifestContent));
+ }
+} \ No newline at end of file
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/NsdCsarEtsiOption2SignerTest.java b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/NsdCsarEtsiOption2SignerTest.java
new file mode 100644
index 0000000000..e6e89574f9
--- /dev/null
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/NsdCsarEtsiOption2SignerTest.java
@@ -0,0 +1,183 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.plugins.etsi.nfv.nsd.security;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+import static org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.NsdCsarEtsiOption2Signer.SDC_NSD_CERT_NAME;
+import static org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.NsdCsarEtsiOption2Signer.SIGNATURE_EXTENSION;
+import static org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.exception.NsdSignatureExceptionSupplier.certificateNotConfigured;
+import static org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.exception.NsdSignatureExceptionSupplier.invalidCertificate;
+import static org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.exception.NsdSignatureExceptionSupplier.unableToCreateSignature;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Optional;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.csar.security.api.CertificateManager;
+import org.openecomp.sdc.be.csar.security.api.CmsContentSigner;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
+import org.openecomp.sdc.be.csar.security.exception.CmsSignatureException;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.NsdCsar;
+import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.security.exception.NsdSignatureException;
+import org.springframework.core.env.Environment;
+
+class NsdCsarEtsiOption2SignerTest {
+
+ private static final String CERT_NAME = "nsdCert";
+
+ @Mock
+ private CertificateManager certificateManager;
+ @Mock
+ private CmsContentSigner cmsContentSigner;
+ @Mock
+ private Environment environment;
+ @Mock
+ private CertificateInfo certificateInfo;
+ @InjectMocks
+ private NsdCsarEtsiOption2Signer nsdCsarEtsiOption2Signer;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(environment.getProperty(SDC_NSD_CERT_NAME)).thenReturn(CERT_NAME);
+ when(certificateManager.getCertificate(CERT_NAME)).thenReturn(Optional.of(certificateInfo));
+ when(certificateInfo.isValid()).thenReturn(true);
+ }
+
+ @Test
+ void signNsdTest() throws NsdSignatureException, CmsSignatureException {
+ final NsdCsar nsdCsar = new NsdCsar("");
+ nsdCsar.addFile("aFile", "aFile".getBytes(StandardCharsets.UTF_8));
+ final byte[] aFileSigned = "aFileSigned".getBytes(StandardCharsets.UTF_8);
+ when(cmsContentSigner.signData(eq("aFile".getBytes(StandardCharsets.UTF_8)), any(), any())).thenReturn(
+ aFileSigned);
+ final String aFileSignedPemString = "aFileSignedPemString";
+ when(cmsContentSigner.formatToPemSignature(aFileSigned)).thenReturn(aFileSignedPemString);
+ nsdCsarEtsiOption2Signer.signArtifacts(nsdCsar);
+ assertThat("The NSD CSAR should contain the original file and its signature",
+ nsdCsar.getFileMap().keySet(), hasSize(2));
+ assertThat("The signed file should be as expected",
+ nsdCsar.getFile("aFile" + SIGNATURE_EXTENSION), is(aFileSignedPemString.getBytes(StandardCharsets.UTF_8)));
+ }
+
+ @Test
+ void dontCreateNsdManifestSignatureFileTest() throws NsdSignatureException {
+ final NsdCsar nsdCsar = new NsdCsar("nsdCsar");
+ nsdCsar.addFile(nsdCsar.getManifestPath(), "manifest".getBytes(StandardCharsets.UTF_8));
+ nsdCsarEtsiOption2Signer.signArtifacts(nsdCsar);
+ assertThat("The NSD CSAR should contain only the original file",
+ nsdCsar.getFileMap().keySet(), hasSize(1));
+ assertThat("The NSD CSAR should not contain the manifest signature file",
+ nsdCsar.getFile(nsdCsar.getManifestPath() + SIGNATURE_EXTENSION), is(nullValue()));
+ }
+
+ @Test
+ void signEmptyNsdTest() throws NsdSignatureException {
+ final NsdCsar nsdCsar = new NsdCsar("");
+ nsdCsarEtsiOption2Signer.signArtifacts(nsdCsar);
+ assertThat("The NSD CSAR should continue empty", nsdCsar.isEmpty(), is(true));
+ }
+
+ @Test
+ void signNsdNoCertificateTest() {
+ when(certificateManager.getCertificate(CERT_NAME)).thenReturn(Optional.empty());
+ final NsdCsar nsdCsar = new NsdCsar("");
+ nsdCsar.addFile("anyFile", "anyFile".getBytes());
+ final NsdSignatureException actualException = assertThrows(NsdSignatureException.class,
+ () -> nsdCsarEtsiOption2Signer.signArtifacts(nsdCsar));
+ assertThat(actualException.getMessage(), is(certificateNotConfigured().getMessage()));
+ }
+
+ @Test
+ void signWholeNoCertificateTest() {
+ when(certificateManager.getCertificate(CERT_NAME)).thenReturn(Optional.empty());
+ final NsdSignatureException actualException =
+ Assertions.assertThrows(NsdSignatureException.class,
+ () -> nsdCsarEtsiOption2Signer.sign(new byte[]{}));
+ assertThat(actualException.getMessage(), is(certificateNotConfigured().getMessage()));
+ }
+
+ @Test
+ void signWithInvalidCertificateTest() {
+ when(certificateInfo.isValid()).thenReturn(false);
+ final NsdSignatureException actualException =
+ Assertions.assertThrows(NsdSignatureException.class,
+ () -> nsdCsarEtsiOption2Signer.sign(new byte[]{}));
+ assertThat(actualException.getMessage(), is(invalidCertificate(null).getMessage()));
+ }
+
+ @Test
+ void signWholeFileTest() throws NsdSignatureException, CmsSignatureException {
+ final byte[] nsdCsarBytes = "nsdCsarBytes".getBytes(StandardCharsets.UTF_8);
+ final NsdCsar nsdCsar = new NsdCsar("");
+ nsdCsar.addFile("aFile", "aFile".getBytes(StandardCharsets.UTF_8));
+ final byte[] nsdCsarBytesSigned = "nsdCsarBytesSigned".getBytes(StandardCharsets.UTF_8);
+ when(cmsContentSigner.signData(eq(nsdCsarBytes), any(), any())).thenReturn(nsdCsarBytesSigned);
+ final String nsdCsarBytesSignedPemString = "nsdCsarBytesSignedPemString";
+ when(cmsContentSigner.formatToPemSignature(nsdCsarBytesSigned)).thenReturn(nsdCsarBytesSignedPemString);
+ final byte[] actualNsdSignedCsar = nsdCsarEtsiOption2Signer.sign(nsdCsarBytes);
+ assertThat("Signature should be as expected",
+ actualNsdSignedCsar, is(nsdCsarBytesSignedPemString.getBytes(StandardCharsets.UTF_8)));
+ }
+
+ @Test
+ void signatureCreationErrorTest() throws CmsSignatureException {
+ final byte[] nsdCsarBytes = "nsdCsarBytes".getBytes(StandardCharsets.UTF_8);
+ final NsdCsar nsdCsar = new NsdCsar("");
+ nsdCsar.addFile("aFile", "aFile".getBytes(StandardCharsets.UTF_8));
+ when(cmsContentSigner.signData(eq(nsdCsarBytes), any(), any()))
+ .thenThrow(new CmsSignatureException(null, null));
+ final NsdSignatureException actualException = assertThrows(NsdSignatureException.class,
+ () -> nsdCsarEtsiOption2Signer.sign(nsdCsarBytes));
+ assertThat(actualException.getMessage(), is(unableToCreateSignature(null).getMessage()));
+ }
+
+ @Test
+ void getSigningCertificateTest() {
+ when(certificateManager.getCertificate(CERT_NAME)).thenReturn(Optional.empty());
+ Optional<CertificateInfo> signingCertificate = nsdCsarEtsiOption2Signer.getSigningCertificate();
+ assertThat("Certificate should not be present", signingCertificate.isEmpty(), is(true));
+ when(certificateManager.getCertificate(CERT_NAME)).thenReturn(Optional.of(certificateInfo));
+ signingCertificate = nsdCsarEtsiOption2Signer.getSigningCertificate();
+ assertThat("Certificate should be present", signingCertificate.isPresent(), is(true));
+ assertThat("Certificate should be as expected", signingCertificate.get(), is(certificateInfo));
+ }
+
+ @Test
+ void isCertificateConfiguredTest() {
+ when(certificateManager.getCertificate(CERT_NAME)).thenReturn(Optional.empty());
+ boolean isCertificateConfigured = nsdCsarEtsiOption2Signer.isCertificateConfigured();
+ assertThat("Certificate should not be configured", isCertificateConfigured, is(false));
+ when(certificateManager.getCertificate(CERT_NAME)).thenReturn(Optional.of(certificateInfo));
+ isCertificateConfigured = nsdCsarEtsiOption2Signer.isCertificateConfigured();
+ assertThat("Certificate should be configured", isCertificateConfigured, is(true));
+ }
+} \ No newline at end of file
diff --git a/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/resources/aFile.txt b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/resources/aFile.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/test/resources/aFile.txt
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java b/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java
index 2f72b771e1..0c8d0fc012 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java
@@ -55,6 +55,7 @@ import org.springframework.core.annotation.Order;
"org.openecomp.sdc.be.components.merge",
"org.openecomp.sdc.be.components.csar",
"org.openecomp.sdc.be.components.property",
+ "org.openecomp.sdc.be.csar.security",
"org.openecomp.sdc.be.datamodel.utils",
"org.openecomp.sdc.be.components.upgrade",
"org.openecomp.sdc.be.externalapi.servlet",
diff --git a/common-be/pom.xml b/common-be/pom.xml
index 94da6cf7c2..c4489b0e17 100644
--- a/common-be/pom.xml
+++ b/common-be/pom.xml
@@ -74,6 +74,13 @@
</dependency>
<dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <version>${bouncycastle.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>${hamcrest.version}</version>
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/CertificateManagerImpl.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/CertificateManagerImpl.java
new file mode 100644
index 0000000000..9ec8ea864e
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/CertificateManagerImpl.java
@@ -0,0 +1,167 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.Key;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.apache.commons.io.FilenameUtils;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.openecomp.sdc.be.csar.security.api.CertificateManager;
+import org.openecomp.sdc.be.csar.security.api.CertificateReader;
+import org.openecomp.sdc.be.csar.security.api.PrivateKeyReader;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
+import org.openecomp.sdc.be.csar.security.exception.CertificateNotFoundException;
+import org.openecomp.sdc.be.csar.security.model.CertificateInfoImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CertificateManagerImpl implements CertificateManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CertificateManagerImpl.class);
+
+ private final PrivateKeyReader privateKeyReader;
+ private final CertificateReader certificateReader;
+ private final Environment environment;
+
+ private Path certificateDirectoryPath;
+ private File certificateDirectory;
+ private final Map<String, CertificateInfo> certificateMap = new HashMap<>();
+
+ public static final String CERT_DIR_ENV_VARIABLE = "SDC_CERT_DIR";
+
+ public CertificateManagerImpl(final PrivateKeyReader privateKeyReader,
+ final CertificateReader certificateReader,
+ final Environment environment) {
+ this.certificateReader = certificateReader;
+ this.privateKeyReader = privateKeyReader;
+ this.environment = environment;
+ init();
+ }
+
+ private void init() {
+ if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
+ final String certificateDir = environment.getProperty(CERT_DIR_ENV_VARIABLE);
+ if (certificateDir == null) {
+ LOGGER.warn("Environment variable '{}' was not provided. Could not load certificates.", CERT_DIR_ENV_VARIABLE);
+ return;
+ }
+ try {
+ this.certificateDirectoryPath = Paths.get(certificateDir);
+ } catch (final Exception e) {
+ LOGGER.error("Invalid path '{}' provided in the environment variable '{}'. Could not load certificates.",
+ certificateDir, CERT_DIR_ENV_VARIABLE, e);
+ return;
+ }
+ try {
+ loadCertificateDirectory();
+ } catch (final Exception e) {
+ LOGGER.error("Could not load certificate directory", e);
+ return;
+ }
+ try {
+ loadCertificates();
+ } catch (final Exception e) {
+ LOGGER.error("Could not load certificates", e);
+ }
+ }
+
+ private void loadCertificates() {
+ final File[] files = certificateDirectory.listFiles();
+ if (files == null || files.length == 0) {
+ LOGGER.warn("Certificate directory is empty. No trusted certificate found.");
+ return;
+ }
+
+ final List<File> certFileList = Arrays.stream(files)
+ .filter(file -> "cert".equals(FilenameUtils.getExtension(file.getName())))
+ .collect(Collectors.toList());
+ final List<File> keyFileList = Arrays.stream(files)
+ .filter(file -> "key".equals(FilenameUtils.getExtension(file.getName())))
+ .collect(Collectors.toList());
+
+ if (certFileList.isEmpty()) {
+ LOGGER.error("Certificate directory is empty. No trusted certificate found.");
+ return;
+ }
+
+ certFileList.forEach(certFile -> {
+ final String baseFileName = FilenameUtils.getBaseName(certFile.getName());
+ final Certificate certificate = loadCertificate(certFile);
+ final Optional<File> keyFileOptional = keyFileList.stream().filter(
+ keyFile1 -> FilenameUtils.getBaseName(keyFile1.getName())
+ .equals(baseFileName)).findFirst();
+ keyFileOptional.ifPresentOrElse(
+ keyFile -> {
+ final CertificateInfoImpl certificateInfo =
+ new CertificateInfoImpl(certFile, certificate, keyFile, loadPrivateKey(keyFile));
+ if (certificateInfo.isValid()) {
+ certificateMap.put(baseFileName, certificateInfo);
+ }
+ },
+ () -> {
+ final CertificateInfoImpl certificateInfo = new CertificateInfoImpl(certFile, certificate);
+ if (certificateInfo.isValid()) {
+ certificateMap.put(baseFileName, new CertificateInfoImpl(certFile, certificate));
+ }
+ }
+ );
+ });
+ }
+
+ private void loadCertificateDirectory() {
+ final File file = certificateDirectoryPath.toFile();
+ if (!file.exists() || !file.isDirectory()) {
+ final String errorMsg =
+ String.format("Provided certificate path '%s' is not a directory or does not exist",
+ certificateDirectoryPath);
+ throw new CertificateNotFoundException(errorMsg);
+ }
+ this.certificateDirectory = file;
+ }
+
+ private Certificate loadCertificate(final File certFile) {
+ return certificateReader.loadCertificate(certFile);
+ }
+
+ private Key loadPrivateKey(final File privateKeyFile) {
+ return privateKeyReader.loadPrivateKey(privateKeyFile);
+ }
+
+ @Override
+ public Optional<CertificateInfo> getCertificate(final String certName) {
+ return Optional.ofNullable(certificateMap.get(certName));
+ }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImpl.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImpl.java
new file mode 100644
index 0000000000..a6ee61d680
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImpl.java
@@ -0,0 +1,53 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security;
+
+import java.io.File;
+import java.io.FileReader;
+import java.security.Key;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
+import org.openecomp.sdc.be.csar.security.api.PrivateKeyReader;
+import org.openecomp.sdc.be.csar.security.exception.LoadPrivateKeyException;
+import org.openecomp.sdc.be.csar.security.exception.UnsupportedKeyFormatException;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PrivateKeyReaderImpl implements PrivateKeyReader {
+
+ @Override
+ public Key loadPrivateKey(final File privateKeyFile) {
+ try (final PEMParser pemParser = new PEMParser(new FileReader(privateKeyFile))) {
+ final Object pemObject = pemParser.readObject();
+ final JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);
+ if (pemObject instanceof PrivateKeyInfo) {
+ return converter.getPrivateKey((PrivateKeyInfo) pemObject);
+ }
+ } catch (final Exception e) {
+ final String errorMsg = "Could not load the private key from given file '%s'";
+ throw new LoadPrivateKeyException(String.format(errorMsg, privateKeyFile), e);
+ }
+ final String errorMsg = "Could not load the private key from given file '%s'. Unsupported format.";
+ throw new UnsupportedKeyFormatException(String.format(errorMsg, privateKeyFile));
+ }
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSigner.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSigner.java
new file mode 100644
index 0000000000..7b7273e810
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSigner.java
@@ -0,0 +1,98 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.cms.ContentInfo;
+import org.bouncycastle.cert.jcajce.JcaCertStore;
+import org.bouncycastle.cms.CMSProcessableByteArray;
+import org.bouncycastle.cms.CMSSignedData;
+import org.bouncycastle.cms.CMSSignedDataGenerator;
+import org.bouncycastle.cms.CMSTypedData;
+import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
+import org.openecomp.sdc.be.csar.security.api.CmsContentSigner;
+import org.openecomp.sdc.be.csar.security.exception.CmsSignatureException;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Sha256WithRsaCmsContentSigner implements CmsContentSigner {
+
+ @Override
+ public byte[] signData(final byte[] data, final Certificate signingCertificate, final Key signingKey)
+ throws CmsSignatureException {
+
+ final CMSTypedData cmsData = new CMSProcessableByteArray(data);
+ final JcaCertStore certStore = createCertificateStore(signingCertificate);
+ try {
+ final ContentSigner contentSigner
+ = new JcaContentSignerBuilder("SHA256withRSA")
+ .setProvider(BouncyCastleProvider.PROVIDER_NAME).build((PrivateKey) signingKey);
+
+ final CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator();
+ cmsGenerator.addSignerInfoGenerator(
+ new JcaSignerInfoGeneratorBuilder(
+ new JcaDigestCalculatorProviderBuilder().setProvider(BouncyCastleProvider.PROVIDER_NAME).build()
+ ).build(contentSigner, (X509Certificate) signingCertificate)
+ );
+ cmsGenerator.addCertificates(certStore);
+
+ final CMSSignedData cms = cmsGenerator.generate(cmsData, false);
+ return cms.getEncoded();
+ } catch (final Exception e) {
+ throw new CmsSignatureException("Could not sign the given data", e);
+ }
+ }
+
+ @Override
+ public String formatToPemSignature(final byte[] signedData) throws CmsSignatureException {
+ final StringWriter sw = new StringWriter();
+ try (final JcaPEMWriter jcaPEMWriter = new JcaPEMWriter(sw)) {
+ final ContentInfo ci = ContentInfo.getInstance(ASN1Primitive.fromByteArray(signedData));
+ jcaPEMWriter.writeObject(ci);
+ } catch (final IOException e) {
+ throw new CmsSignatureException("Could not convert signed data to PEM format", e);
+ }
+ return sw.toString();
+ }
+
+ private JcaCertStore createCertificateStore(final Certificate signingCertificate) throws CmsSignatureException {
+ try {
+ return new JcaCertStore(Collections.singletonList(signingCertificate));
+ } catch (final CertificateEncodingException e) {
+ final String errorMsg = String
+ .format("Could not create certificate store from certificate '%s'", signingCertificate);
+ throw new CmsSignatureException(errorMsg, e);
+ }
+ }
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/X509CertificateReader.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/X509CertificateReader.java
new file mode 100644
index 0000000000..b8e95e7b18
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/X509CertificateReader.java
@@ -0,0 +1,57 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import org.openecomp.sdc.be.csar.security.api.CertificateReader;
+import org.openecomp.sdc.be.csar.security.exception.LoadCertificateException;
+import org.springframework.stereotype.Component;
+
+@Component
+public class X509CertificateReader implements CertificateReader {
+
+ /**
+ * Reads X.509 certificate file.
+ *
+ * @param certFile the certificate file
+ * @return the read certificate
+ * @throws LoadCertificateException when an error has occurred while reading the certificate
+ */
+ @Override
+ public Certificate loadCertificate(final File certFile) {
+ try (final FileInputStream fi = new FileInputStream(certFile)) {
+ return buildCertificate(fi);
+ } catch (final Exception e) {
+ final String errorMsg = "Could not load the certificate from given file '%s'";
+ throw new LoadCertificateException(String.format(errorMsg, certFile), e);
+ }
+ }
+
+ private Certificate buildCertificate(final InputStream certificateInputStream) throws CertificateException {
+ final CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ return factory.generateCertificate(certificateInputStream);
+ }
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateManager.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateManager.java
new file mode 100644
index 0000000000..53437f399f
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateManager.java
@@ -0,0 +1,29 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.api;
+
+import java.util.Optional;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
+
+public interface CertificateManager {
+
+ Optional<CertificateInfo> getCertificate(String certName);
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateReader.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateReader.java
new file mode 100644
index 0000000000..4c32fa1cee
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CertificateReader.java
@@ -0,0 +1,34 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.api;
+
+import java.io.File;
+import java.security.cert.Certificate;
+
+public interface CertificateReader {
+
+ /**
+ * Reads a certificate file.
+ *
+ * @param certFile the certificate file
+ * @return the read certificate
+ */
+ Certificate loadCertificate(File certFile);
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CmsContentSigner.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CmsContentSigner.java
new file mode 100644
index 0000000000..37bd988e50
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/CmsContentSigner.java
@@ -0,0 +1,32 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.api;
+
+import java.security.Key;
+import java.security.cert.Certificate;
+import org.openecomp.sdc.be.csar.security.exception.CmsSignatureException;
+
+public interface CmsContentSigner {
+
+ byte[] signData(byte[] data, Certificate signingCertificate, Key signingKey)
+ throws CmsSignatureException;
+
+ String formatToPemSignature(byte[] signedData) throws CmsSignatureException;
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/PrivateKeyReader.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/PrivateKeyReader.java
new file mode 100644
index 0000000000..3e8c406b74
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/PrivateKeyReader.java
@@ -0,0 +1,38 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.api;
+
+import java.io.File;
+import java.security.Key;
+import org.openecomp.sdc.be.csar.security.exception.LoadPrivateKeyException;
+import org.openecomp.sdc.be.csar.security.exception.UnsupportedKeyFormatException;
+
+public interface PrivateKeyReader {
+
+ /**
+ * Reads a given private file.
+ *
+ * @param privateKeyFile the private key file
+ * @return the read private key
+ * @throws LoadPrivateKeyException when an error has occurred while reading the private key
+ * @throws UnsupportedKeyFormatException when the private key is not supported
+ */
+ Key loadPrivateKey(final File privateKeyFile);
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/model/CertificateInfo.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/model/CertificateInfo.java
new file mode 100644
index 0000000000..5b234cc661
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/api/model/CertificateInfo.java
@@ -0,0 +1,46 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.api.model;
+
+import java.io.File;
+import java.security.Key;
+import java.security.cert.Certificate;
+
+public interface CertificateInfo {
+
+ String getName();
+
+ File getCertificateFile();
+
+ Certificate getCertificate();
+
+ File getPrivateKeyFile();
+
+ Key getPrivateKey();
+
+ /**
+ * Check if the certificate is valid.
+ *
+ * @return {@code true} if the certificate is valid. {@code false} otherwise.
+ * @throws UnsupportedOperationException when the certificate is not supported
+ */
+ boolean isValid();
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CertificateNotFoundException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CertificateNotFoundException.java
new file mode 100644
index 0000000000..a2175f379c
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CertificateNotFoundException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.exception;
+
+public class CertificateNotFoundException extends RuntimeException {
+
+ public CertificateNotFoundException(final String message) {
+ super(message);
+ }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CmsSignatureException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CmsSignatureException.java
new file mode 100644
index 0000000000..6bc49d6e4d
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/CmsSignatureException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.exception;
+
+public class CmsSignatureException extends Exception {
+
+ public CmsSignatureException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadCertificateException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadCertificateException.java
new file mode 100644
index 0000000000..3cd10628f5
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadCertificateException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.exception;
+
+public class LoadCertificateException extends RuntimeException {
+
+ public LoadCertificateException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadPrivateKeyException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadPrivateKeyException.java
new file mode 100644
index 0000000000..00681bc842
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/LoadPrivateKeyException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.exception;
+
+public class LoadPrivateKeyException extends RuntimeException {
+
+ public LoadPrivateKeyException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/UnsupportedKeyFormatException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/UnsupportedKeyFormatException.java
new file mode 100644
index 0000000000..d30f6f274a
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/exception/UnsupportedKeyFormatException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.exception;
+
+public class UnsupportedKeyFormatException extends RuntimeException {
+
+ public UnsupportedKeyFormatException(final String message) {
+ super(message);
+ }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImpl.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImpl.java
new file mode 100644
index 0000000000..f7b2fafb3c
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImpl.java
@@ -0,0 +1,70 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.model;
+
+import java.io.File;
+import java.security.Key;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import lombok.Getter;
+import org.apache.commons.io.FilenameUtils;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Getter
+public class CertificateInfoImpl implements CertificateInfo {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CertificateInfoImpl.class);
+
+ private final String name;
+ private final File certificateFile;
+ private final Certificate certificate;
+ private File privateKeyFile;
+ private Key privateKey;
+
+ public CertificateInfoImpl(final File certificateFile, final Certificate certificate) {
+ this.certificateFile = certificateFile;
+ this.certificate = certificate;
+ this.name = FilenameUtils.getBaseName(certificateFile.getName());
+ }
+
+ public CertificateInfoImpl(final File certificateFile, final Certificate certificate,
+ final File privateKeyFile, final Key privateKey) {
+ this(certificateFile, certificate);
+ this.privateKeyFile = privateKeyFile;
+ this.privateKey = privateKey;
+ }
+
+ @Override
+ public boolean isValid() {
+ if("X.509".equals(certificate.getType())) {
+ try {
+ ((X509Certificate) certificate).checkValidity();
+ return true;
+ } catch (final Exception e) {
+ LOGGER.warn("Invalid certificate '{}'", certificateFile.getAbsolutePath(), e);
+ return false;
+ }
+ }
+ throw new UnsupportedOperationException(String.format("Certificate type '%s' not supported", certificate.getType()));
+ }
+
+}
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/security/CertificateManagerImplTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/CertificateManagerImplTest.java
new file mode 100644
index 0000000000..6287c0e85b
--- /dev/null
+++ b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/CertificateManagerImplTest.java
@@ -0,0 +1,141 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.when;
+import static org.openecomp.sdc.be.csar.security.CertificateManagerImpl.CERT_DIR_ENV_VARIABLE;
+
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Optional;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.csar.security.api.CertificateReader;
+import org.openecomp.sdc.be.csar.security.api.PrivateKeyReader;
+import org.openecomp.sdc.be.csar.security.api.model.CertificateInfo;
+import org.springframework.core.env.Environment;
+
+class CertificateManagerImplTest {
+
+ @Mock
+ private Environment environment;
+ @Mock
+ private PrivateKeyReader privateKeyReader;
+ @Mock
+ private CertificateReader certificateReader;
+ @Mock
+ private X509Certificate certificateMock;
+ private CertificateManagerImpl certificateManager;
+
+ static Path certificateFolderPath;
+
+ @BeforeAll
+ static void beforeAll() {
+ final String resourceFolder = "certificateManager";
+ final URL certificateManager = CertificateManagerImplTest.class.getClassLoader().getResource(resourceFolder);
+ if (certificateManager == null) {
+ fail("Could not find resource folder " + resourceFolder);
+ }
+ certificateFolderPath = Paths.get(certificateManager.getPath());
+ }
+
+ @BeforeEach
+ void setUp() throws CertificateNotYetValidException, CertificateExpiredException {
+ MockitoAnnotations.initMocks(this);
+ when(environment.getProperty(CERT_DIR_ENV_VARIABLE)).thenReturn(certificateFolderPath.toString());
+ when(certificateMock.getType()).thenReturn("X.509");
+ doNothing().when(certificateMock).checkValidity();
+ when(certificateReader.loadCertificate(ArgumentMatchers.any())).thenReturn(certificateMock);
+ certificateManager = new CertificateManagerImpl(privateKeyReader, certificateReader, environment);
+ }
+
+ @Test
+ void getCertificateSuccessTest() {
+ final String certificateName = "fakeCert1";
+ final Optional<CertificateInfo> certificateOpt = certificateManager.getCertificate(certificateName);
+ assertThat(certificateOpt.isPresent(), is(true));
+ final CertificateInfo certificateInfo = certificateOpt.get();
+ assertThat(certificateInfo.getName(), is(certificateName));
+ assertThat(certificateInfo.getPrivateKeyFile(), is(notNullValue()));
+ assertThat(certificateInfo.getPrivateKeyFile().getAbsolutePath(),
+ is(certificateFolderPath.resolve(certificateName + ".key").toString()));
+ assertThat(certificateInfo.getCertificateFile(), is(notNullValue()));
+ assertThat(certificateInfo.getCertificateFile().getAbsolutePath(),
+ is(certificateFolderPath.resolve(certificateName + ".cert").toString()));
+ }
+
+ @Test
+ void initCertificateSuccessTest() {
+ final String certificateName1 = "fakeCert1";
+ final String certificateName2 = "fakeCert2";
+ final String certificateName3 = "fakeCert3";
+ assertThat("Certificate " + certificateName1 + " should be present",
+ certificateManager.getCertificate(certificateName1).isPresent(), is(true));
+ assertThat("Certificate " + certificateName2 + " should be present",
+ certificateManager.getCertificate(certificateName2).isPresent(), is(true));
+ assertThat("Certificate " + certificateName3 + " should not be present",
+ certificateManager.getCertificate(certificateName3).isEmpty(), is(true));
+ }
+
+ @Test
+ void invalidCertificateFolderTest() {
+ final String certificateName1 = "fakeCert1";
+ when(environment.getProperty(CERT_DIR_ENV_VARIABLE)).thenReturn("/an/invalid/folder");
+ final CertificateManagerImpl certificateManager =
+ new CertificateManagerImpl(privateKeyReader, certificateReader, environment);
+ assertThat("Certificate " + certificateName1 + " should be present",
+ certificateManager.getCertificate(certificateName1).isPresent(), is(false));
+ }
+
+ @Test
+ void noEnvironmentVariableConfiguredTest() {
+ final String certificateName1 = "fakeCert1";
+ when(environment.getProperty(CERT_DIR_ENV_VARIABLE)).thenReturn(null);
+ final CertificateManagerImpl certificateManager =
+ new CertificateManagerImpl(privateKeyReader, certificateReader, environment);
+ assertThat("Certificate " + certificateName1 + " should be present",
+ certificateManager.getCertificate(certificateName1).isPresent(), is(false));
+ }
+
+ @Test
+ void loadCertificateExceptionTest() {
+ final String certificateName1 = "fakeCert1";
+ when(certificateReader.loadCertificate(any())).thenThrow(new RuntimeException());
+ final CertificateManagerImpl certificateManager =
+ new CertificateManagerImpl(privateKeyReader, certificateReader, environment);
+ assertThat("Certificate " + certificateName1 + " should be present",
+ certificateManager.getCertificate(certificateName1).isPresent(), is(false));
+ }
+
+} \ No newline at end of file
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImplTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImplTest.java
new file mode 100644
index 0000000000..7bd44cf9c1
--- /dev/null
+++ b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/PrivateKeyReaderImplTest.java
@@ -0,0 +1,95 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.Key;
+import java.security.Security;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.csar.security.exception.LoadPrivateKeyException;
+import org.openecomp.sdc.be.csar.security.exception.UnsupportedKeyFormatException;
+
+class PrivateKeyReaderImplTest {
+
+ private PrivateKeyReaderImpl privateKeyReader;
+
+ @BeforeEach
+ void setUp() {
+ privateKeyReader = new PrivateKeyReaderImpl();
+ if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+ }
+
+ @AfterEach
+ void tearDown() {
+ if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) != null) {
+ Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
+ }
+ }
+
+ @Test
+ void loadPrivateKeySuccessTest() {
+ final Path certPath = Paths.get("certificateManager", "realCert", "realCert1.key");
+ final URL resource = getClass().getClassLoader().getResource(certPath.toString());
+ if (resource == null) {
+ fail("Could not find resource " + certPath.toString());
+ }
+ final Key privateKey = privateKeyReader.loadPrivateKey(new File(resource.getPath()));
+ assertNotNull(privateKey);
+ }
+
+ @Test
+ void loadInvalidKeyFilePathTest() {
+ final String invalidFilePath = "aaaa";
+ final File keyFile = new File(invalidFilePath);
+ final LoadPrivateKeyException actualException = assertThrows(LoadPrivateKeyException.class,
+ () -> privateKeyReader.loadPrivateKey(keyFile));
+ assertThat(actualException.getMessage(),
+ is(String.format("Could not load the private key from given file '%s'", invalidFilePath)));
+ }
+
+ @Test
+ void loadInvalidKeyFileTest() {
+ final Path certPath = Paths.get("certificateManager", "fakeCert1.key");
+ final URL resource = getClass().getClassLoader().getResource(certPath.toString());
+ if (resource == null) {
+ fail("Could not find resource " + certPath.toString());
+ }
+ final File keyFile = new File(resource.getPath());
+ final UnsupportedKeyFormatException actualException = assertThrows(UnsupportedKeyFormatException.class,
+ () -> privateKeyReader.loadPrivateKey(keyFile));
+ assertThat(actualException.getMessage(),
+ is(String.format("Could not load the private key from given file '%s'. Unsupported format.",
+ resource.getPath())));
+ }
+} \ No newline at end of file
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSignerTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSignerTest.java
new file mode 100644
index 0000000000..2f0031d6e1
--- /dev/null
+++ b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/Sha256WithRsaCmsContentSignerTest.java
@@ -0,0 +1,119 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.Key;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.cms.CMSProcessableByteArray;
+import org.bouncycastle.cms.CMSSignedData;
+import org.bouncycastle.cms.SignerInformation;
+import org.bouncycastle.cms.SignerInformationStore;
+import org.bouncycastle.cms.SignerInformationVerifier;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.csar.security.api.CertificateReader;
+import org.openecomp.sdc.be.csar.security.api.PrivateKeyReader;
+import org.openecomp.sdc.be.csar.security.exception.CmsSignatureException;
+
+class Sha256WithRsaCmsContentSignerTest {
+
+ private Sha256WithRsaCmsContentSigner cmsContentSigner;
+ private PrivateKeyReader privateKeyReader;
+ private CertificateReader certificateReader;
+
+ private static final Path testFilesPath = Path.of("certificateManager", "signerTest");
+ private static final Path certFilesPath = Path.of("certificateManager", "realCert");
+
+ @BeforeEach
+ void setUp() {
+ Security.addProvider(new BouncyCastleProvider());
+ cmsContentSigner = new Sha256WithRsaCmsContentSigner();
+ privateKeyReader = new PrivateKeyReaderImpl();
+ certificateReader = new X509CertificateReader();
+ }
+
+ @AfterEach
+ void tearDown() {
+ Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
+ }
+
+ @Test
+ void signDataSuccessTest() throws OperatorCreationException, CMSException, IOException, CmsSignatureException {
+ final File certFile = getResourceFile(certFilesPath.resolve("realCert1.cert"));
+ final File keyFile = getResourceFile(certFilesPath.resolve("realCert1.key"));
+ final File fileToSign = getResourceFile(testFilesPath.resolve("fileToSign.txt"));
+ final Key privateKey = privateKeyReader.loadPrivateKey(keyFile);
+ final Certificate certificate = certificateReader.loadCertificate(certFile);
+ final byte[] actualSignatureBytes = cmsContentSigner
+ .signData(Files.readAllBytes(fileToSign.toPath()), certificate, privateKey);
+
+ assertTrue(verifySignature(Files.readAllBytes(fileToSign.toPath()), actualSignatureBytes,
+ (X509Certificate) certificate));
+ }
+
+ @Test
+ void signDataInvalidCertAndKeyTest() {
+ assertThrows(CmsSignatureException.class,
+ () -> cmsContentSigner.signData(null, null, null));
+ }
+
+ private boolean verifySignature(byte[] contentBytes, byte[] signatureBytes, X509Certificate certificate)
+ throws CMSException, OperatorCreationException {
+
+ final CMSSignedData cms = new CMSSignedData(new CMSProcessableByteArray(contentBytes), signatureBytes);
+ final SignerInformationStore signers = cms.getSignerInfos();
+ final SignerInformationVerifier signerInformationVerifier =
+ new JcaSimpleSignerInfoVerifierBuilder()
+ .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(certificate);
+ for (final SignerInformation signer : signers.getSigners()) {
+ if (!signer.verify(signerInformationVerifier)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private File getResourceFile(final Path testResourcePath) {
+ final URL resource = getClass().getClassLoader().getResource(testResourcePath.toString());
+ if (resource == null) {
+ fail("Could not load the file " + testResourcePath.toString());
+ }
+
+ return new File(resource.getPath());
+ }
+
+} \ No newline at end of file
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/security/X509CertificateReaderTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/X509CertificateReaderTest.java
new file mode 100644
index 0000000000..3235739780
--- /dev/null
+++ b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/X509CertificateReaderTest.java
@@ -0,0 +1,81 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.cert.Certificate;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.csar.security.exception.LoadCertificateException;
+
+class X509CertificateReaderTest {
+
+ private X509CertificateReader certificateReader;
+
+ @BeforeEach
+ void setUp() {
+ certificateReader = new X509CertificateReader();
+ }
+
+ @Test
+ void loadCertificateSuccessTest() {
+ final Path certPath = Paths.get("certificateManager", "realCert", "realCert1.cert");
+ final URL resource = getClass().getClassLoader().getResource(certPath.toString());
+ if (resource == null) {
+ fail("Could not find resource " + certPath.toString());
+ }
+ final Certificate certificate = certificateReader.loadCertificate(new File(resource.getPath()));
+ assertNotNull(certificate);
+ }
+
+ @Test
+ void loadInvalidCertificateFilePathTest() {
+ final String invalidFilePath = "aaaa";
+ final File certFile = new File(invalidFilePath);
+ final LoadCertificateException actualException = assertThrows(LoadCertificateException.class,
+ () -> certificateReader.loadCertificate(certFile));
+ assertThat(actualException.getMessage(),
+ is(String.format("Could not load the certificate from given file '%s'", invalidFilePath)));
+ }
+
+ @Test
+ void loadInvalidCertificateFileTest() {
+ final Path certPath = Paths.get("certificateManager", "fakeCert1.cert");
+ System.out.println(certPath.toString());
+ final URL resource = getClass().getClassLoader().getResource(certPath.toString());
+ if (resource == null) {
+ fail("Could not find resource " + certPath.toString());
+ }
+ final File certFile = new File(resource.getPath());
+ final LoadCertificateException actualException = assertThrows(LoadCertificateException.class,
+ () -> certificateReader.loadCertificate(certFile));
+ assertThat(actualException.getMessage(),
+ is(String.format("Could not load the certificate from given file '%s'", resource.getPath())));
+ }
+} \ No newline at end of file
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImplTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImplTest.java
new file mode 100644
index 0000000000..6b094130b0
--- /dev/null
+++ b/common-be/src/test/java/org/openecomp/sdc/be/csar/security/model/CertificateInfoImplTest.java
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.be.csar.security.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+class CertificateInfoImplTest {
+
+ @Mock
+ private X509Certificate certificate;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ void isValidTest() throws CertificateNotYetValidException, CertificateExpiredException {
+ when(certificate.getType()).thenReturn("X.509");
+ doNothing().when(certificate).checkValidity();
+ final CertificateInfoImpl certificateInfo = new CertificateInfoImpl(new File(""), certificate);
+ assertTrue(certificateInfo.isValid());
+ doThrow(CertificateExpiredException.class).when(certificate).checkValidity();
+ assertFalse(certificateInfo.isValid());
+ }
+
+ @Test
+ void unsupportedCertificateTypeTest() {
+ final String certificateType = "unknown";
+ when(certificate.getType()).thenReturn(certificateType);
+ final CertificateInfoImpl certificateInfo = new CertificateInfoImpl(new File(""), certificate);
+ final UnsupportedOperationException actualException =
+ assertThrows(UnsupportedOperationException.class, certificateInfo::isValid);
+ assertEquals(actualException.getMessage(),
+ String.format("Certificate type '%s' not supported", certificateType));
+ }
+}
diff --git a/common-be/src/test/resources/certificateManager/fakeCert1.cert b/common-be/src/test/resources/certificateManager/fakeCert1.cert
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/fakeCert1.cert
diff --git a/common-be/src/test/resources/certificateManager/fakeCert1.key b/common-be/src/test/resources/certificateManager/fakeCert1.key
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/fakeCert1.key
diff --git a/common-be/src/test/resources/certificateManager/fakeCert2.cert b/common-be/src/test/resources/certificateManager/fakeCert2.cert
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/fakeCert2.cert
diff --git a/common-be/src/test/resources/certificateManager/fakeCert3.key b/common-be/src/test/resources/certificateManager/fakeCert3.key
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/fakeCert3.key
diff --git a/common-be/src/test/resources/certificateManager/realCert/realCert1.cert b/common-be/src/test/resources/certificateManager/realCert/realCert1.cert
new file mode 100644
index 0000000000..ae7d518ab0
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/realCert/realCert1.cert
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEAzCCAuugAwIBAgIUZqdsy8mtirp4AGnTopg9rb3NXcEwDQYJKoZIhvcNAQEL
+BQAwgY8xCzAJBgNVBAYTAkVVMRAwDgYDVQQIDAdOb3doZXJlMRIwEAYDVQQHDAlT
+b21ld2hlcmUxDTALBgNVBAoMBEFDTUUxDDAKBgNVBAsMA1NEQzEVMBMGA1UEAwwM
+c2RjLm9uYXAub3JnMSYwJAYJKoZIhvcNAQkBFhdvbmFwLXNkY0BsaXN0cy5vbmFw
+Lm9yZzAgFw0yMTAyMTYxNDQ2NThaGA8yMDcxMDIwNDE0NDY1OFowgY8xCzAJBgNV
+BAYTAkVVMRAwDgYDVQQIDAdOb3doZXJlMRIwEAYDVQQHDAlTb21ld2hlcmUxDTAL
+BgNVBAoMBEFDTUUxDDAKBgNVBAsMA1NEQzEVMBMGA1UEAwwMc2RjLm9uYXAub3Jn
+MSYwJAYJKoZIhvcNAQkBFhdvbmFwLXNkY0BsaXN0cy5vbmFwLm9yZzCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBANAWK6fjuOq6Wgxwh6QqK0YB9ahjPRj0
+ik/l86AokwyawpgY/iC2xXw+9Etq91C6plYy8BlbYIcv/+KoiteL4YgME9Hk1lwK
+GEceNGwvLKzU5/fTX1BP4qpVi3aB5zCAWa9MhCk+UI/aIeERKFP9XHAx/wuAUq/x
+OP4HLxgLuX/A7Trld3RjjaMYOLjbfJjPFN3lrvfQ02fy5DlJfWG3ASTOOEfdHt1g
+wfOLuzl2l5R34p+zwQKid+2cyKXYs0owZu7Dz9OTWLVxZcLiYEGz8Y3gmmHVhXy+
+TPpvl5wPEajOQBUMksdOric0dIfKjJCMJqFzILv1dfZCr3843MYN3oMCAwEAAaNT
+MFEwHQYDVR0OBBYEFJ6mFarA/5ISm7nZimLshzCH/0F8MB8GA1UdIwQYMBaAFJ6m
+FarA/5ISm7nZimLshzCH/0F8MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBAGUzF4W1vHfksW9qSYqtc8xuM+lV1WrdOW7pX7JkIihUv3Z4jMqysrU4
+nj2iVBG5dPNm9v5GtaeK1ESnVilcdMSYTj/F34/MXJ0iZy1UR0j0IBSrR7JjbTAD
+aYH1sx00hH13U8GMZInnmenmwziOQgBwhhCjLMblUY2vQ4O5MGwZG0VW2e3mUcq1
+HBC69yRMx9jQ+Iof6+rHnCLZXTjcl+65IxXSbKhofvpPJMVXFlmV3TdDdONuvKpS
+051z/ISD6/SEWEvF9ZwAnZvJ/5yPqGzKgyC7rp8zJL+N3VLfr+la1D1w7qgoyFTi
+drptEMCzLOk4OuM8PX8l2kY0G+gQD1o=
+-----END CERTIFICATE-----
diff --git a/common-be/src/test/resources/certificateManager/realCert/realCert1.key b/common-be/src/test/resources/certificateManager/realCert/realCert1.key
new file mode 100644
index 0000000000..a31579a407
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/realCert/realCert1.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQFiun47jquloM
+cIekKitGAfWoYz0Y9IpP5fOgKJMMmsKYGP4gtsV8PvRLavdQuqZWMvAZW2CHL//i
+qIrXi+GIDBPR5NZcChhHHjRsLyys1Of3019QT+KqVYt2gecwgFmvTIQpPlCP2iHh
+EShT/VxwMf8LgFKv8Tj+By8YC7l/wO065Xd0Y42jGDi423yYzxTd5a730NNn8uQ5
+SX1htwEkzjhH3R7dYMHzi7s5dpeUd+Kfs8EConftnMil2LNKMGbuw8/Tk1i1cWXC
+4mBBs/GN4Jph1YV8vkz6b5ecDxGozkAVDJLHTq4nNHSHyoyQjCahcyC79XX2Qq9/
+ONzGDd6DAgMBAAECggEANLj5VK+JIcgXmsFETN72WeWTNZf3WgRTqwzLXpAJOg9Y
+MKtccDN+9A0LXrR6dzTjgkGjvfj+CyKpReeITja97PeKagr+GRHhtts7UxHc0uma
+4JrosnObLadBD8S4K/zJPHY5oi2MwfX10Y3EVwuByVeRlHtt9/A5jXuKfiAyXuCw
+42AT6GUFxntwcKhJSQEcy2B9FwvnF5BDDQKyRVD1McrIj/g7+fiyOpqBXGxk+VYX
+6GjYb0kWR+lVexPBP4fgSs6Yx9EroDqzXAolH94NQfb93sOJuawtNVhkEgjE9hec
+NumdpHMXhXGP0WI/jhicz4gaBDGyEwuSqUxMnfqNyQKBgQDyFx715F3iz2yfnsUQ
+xU7KheUjN0g/vhrcir31L9NuhRpWoBJyRUDeXekuCaDF2ElUXJAdUTMGWDwXxlLx
+aa5b8LPBL4pGvNRakfT1TJrViUm3A9wC4EO8l0IIpoYAEt8nstaw4pMEWLOSSKH/
+O2wG+v1h1/Xfd+ruTbmcBn6yLwKBgQDcCuSQoheMZrb6Hq+i+99LF3ZHVqJKUUCI
+XRnH3fhwhnMrsR9EshOVRtex0aAdl1GUWCAoVt4ZNom5m7b2qRji0gx8npwA0jxD
+CSDUw68Jy3MzQxDMPWNRI38P2r46CslNqCkEGlebbgHEJ0qzp2tIfN25pO6EXfjx
+wk9afY5n7QKBgQCG0Wtzgn7qfZs/dTrHsSnEzTYjG3lHzkXFRhqtfbngVY2qajB7
+pKeQbnoaIlB/fYiwy2+SdBLXWLH2h4LPYIwyNWTVk/UMmcIkwh3JsaSUgIUlv6d5
+jo0KbK3ghWQgjGHsCMNY9ITtKbyvHXXh3qS1andLUuphTbXuiihwhIlwDwKBgD9P
+QwP6HxxeUTcVrSMPpOdOENHlszv+tLqHTuuaieiWRnzDsWNqeQfyIg0faxoYd3hf
+AqGYnL5UWrv0eWfuryJTnRQd7nSuCHihH7kXtDz1NGgDW8nnv7OQqvY80Y6Rm+mk
+AGkVyy8FL6zoQS3/dXadto27ToT3JLEqXvqCNX7hAoGAPfNcJtXJXrXh9P3JZqkM
+pa8nRqUW0MeRt3v8rLqi4D7J6kW1Rkz5AhjiKkp1EwtE0IbGRI1EPhxT5DCMKlIy
+UX7VfP8nf+wb6dLHQ0s4oB20y5J6T7FAkD+50dE6Q/6fAl/2MkE+/R0npKRVhOlc
+eXIeBGzSc7p92K1p/vRMOZg=
+-----END PRIVATE KEY-----
diff --git a/common-be/src/test/resources/certificateManager/signerTest/fileToSign.txt b/common-be/src/test/resources/certificateManager/signerTest/fileToSign.txt
new file mode 100644
index 0000000000..cf3472103d
--- /dev/null
+++ b/common-be/src/test/resources/certificateManager/signerTest/fileToSign.txt
@@ -0,0 +1 @@
+This is a file to be signed.
diff --git a/common-be/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/common-be/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..ca6ee9cea8
--- /dev/null
+++ b/common-be/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline \ No newline at end of file
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 98d827d04c..5506ecfb7a 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -531,7 +531,7 @@ limitations under the License.
<volumes>
<bind>
<volume>${it.chef.config}:/var/lib/jetty/chef-solo/environments</volume>
- <volume>${project.basedir}/src/test/resources/cert:/var/lib/jetty/onap/cert
+ <volume>${project.basedir}/src/test/resources/cert/onboarding-be:/var/lib/jetty/onap/cert
</volume>
<volume>${it.shared.volume}:/var/lib/jetty/logs</volume>
</bind>
@@ -572,12 +572,15 @@ limitations under the License.
<ENVNAME>${it.env.name}</ENVNAME>
<JAVA_OPTIONS>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:4000
-Xmx1536m -Xms1536m</JAVA_OPTIONS>
+ <SDC_CERT_DIR>onap/cert</SDC_CERT_DIR>
+ <SDC_NSD_CERT_NAME>nsdCert</SDC_NSD_CERT_NAME>
</env>
<hostname>sdc-BE</hostname>
<volumes>
<bind>
<volume>${it.chef.config}:/var/lib/jetty/chef-solo/environments</volume>
<volume>${it.shared.volume}:/var/lib/jetty/logs</volume>
+ <volume>${project.basedir}/src/test/resources/cert/catalog-be:/var/lib/jetty/onap/cert</volume>
</bind>
</volumes>
<wait>
diff --git a/integration-tests/src/test/resources/cert/catalog-be/nsdCert.cert b/integration-tests/src/test/resources/cert/catalog-be/nsdCert.cert
new file mode 100644
index 0000000000..ae7d518ab0
--- /dev/null
+++ b/integration-tests/src/test/resources/cert/catalog-be/nsdCert.cert
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEAzCCAuugAwIBAgIUZqdsy8mtirp4AGnTopg9rb3NXcEwDQYJKoZIhvcNAQEL
+BQAwgY8xCzAJBgNVBAYTAkVVMRAwDgYDVQQIDAdOb3doZXJlMRIwEAYDVQQHDAlT
+b21ld2hlcmUxDTALBgNVBAoMBEFDTUUxDDAKBgNVBAsMA1NEQzEVMBMGA1UEAwwM
+c2RjLm9uYXAub3JnMSYwJAYJKoZIhvcNAQkBFhdvbmFwLXNkY0BsaXN0cy5vbmFw
+Lm9yZzAgFw0yMTAyMTYxNDQ2NThaGA8yMDcxMDIwNDE0NDY1OFowgY8xCzAJBgNV
+BAYTAkVVMRAwDgYDVQQIDAdOb3doZXJlMRIwEAYDVQQHDAlTb21ld2hlcmUxDTAL
+BgNVBAoMBEFDTUUxDDAKBgNVBAsMA1NEQzEVMBMGA1UEAwwMc2RjLm9uYXAub3Jn
+MSYwJAYJKoZIhvcNAQkBFhdvbmFwLXNkY0BsaXN0cy5vbmFwLm9yZzCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBANAWK6fjuOq6Wgxwh6QqK0YB9ahjPRj0
+ik/l86AokwyawpgY/iC2xXw+9Etq91C6plYy8BlbYIcv/+KoiteL4YgME9Hk1lwK
+GEceNGwvLKzU5/fTX1BP4qpVi3aB5zCAWa9MhCk+UI/aIeERKFP9XHAx/wuAUq/x
+OP4HLxgLuX/A7Trld3RjjaMYOLjbfJjPFN3lrvfQ02fy5DlJfWG3ASTOOEfdHt1g
+wfOLuzl2l5R34p+zwQKid+2cyKXYs0owZu7Dz9OTWLVxZcLiYEGz8Y3gmmHVhXy+
+TPpvl5wPEajOQBUMksdOric0dIfKjJCMJqFzILv1dfZCr3843MYN3oMCAwEAAaNT
+MFEwHQYDVR0OBBYEFJ6mFarA/5ISm7nZimLshzCH/0F8MB8GA1UdIwQYMBaAFJ6m
+FarA/5ISm7nZimLshzCH/0F8MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBAGUzF4W1vHfksW9qSYqtc8xuM+lV1WrdOW7pX7JkIihUv3Z4jMqysrU4
+nj2iVBG5dPNm9v5GtaeK1ESnVilcdMSYTj/F34/MXJ0iZy1UR0j0IBSrR7JjbTAD
+aYH1sx00hH13U8GMZInnmenmwziOQgBwhhCjLMblUY2vQ4O5MGwZG0VW2e3mUcq1
+HBC69yRMx9jQ+Iof6+rHnCLZXTjcl+65IxXSbKhofvpPJMVXFlmV3TdDdONuvKpS
+051z/ISD6/SEWEvF9ZwAnZvJ/5yPqGzKgyC7rp8zJL+N3VLfr+la1D1w7qgoyFTi
+drptEMCzLOk4OuM8PX8l2kY0G+gQD1o=
+-----END CERTIFICATE-----
diff --git a/integration-tests/src/test/resources/cert/catalog-be/nsdCert.key b/integration-tests/src/test/resources/cert/catalog-be/nsdCert.key
new file mode 100644
index 0000000000..a31579a407
--- /dev/null
+++ b/integration-tests/src/test/resources/cert/catalog-be/nsdCert.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQFiun47jquloM
+cIekKitGAfWoYz0Y9IpP5fOgKJMMmsKYGP4gtsV8PvRLavdQuqZWMvAZW2CHL//i
+qIrXi+GIDBPR5NZcChhHHjRsLyys1Of3019QT+KqVYt2gecwgFmvTIQpPlCP2iHh
+EShT/VxwMf8LgFKv8Tj+By8YC7l/wO065Xd0Y42jGDi423yYzxTd5a730NNn8uQ5
+SX1htwEkzjhH3R7dYMHzi7s5dpeUd+Kfs8EConftnMil2LNKMGbuw8/Tk1i1cWXC
+4mBBs/GN4Jph1YV8vkz6b5ecDxGozkAVDJLHTq4nNHSHyoyQjCahcyC79XX2Qq9/
+ONzGDd6DAgMBAAECggEANLj5VK+JIcgXmsFETN72WeWTNZf3WgRTqwzLXpAJOg9Y
+MKtccDN+9A0LXrR6dzTjgkGjvfj+CyKpReeITja97PeKagr+GRHhtts7UxHc0uma
+4JrosnObLadBD8S4K/zJPHY5oi2MwfX10Y3EVwuByVeRlHtt9/A5jXuKfiAyXuCw
+42AT6GUFxntwcKhJSQEcy2B9FwvnF5BDDQKyRVD1McrIj/g7+fiyOpqBXGxk+VYX
+6GjYb0kWR+lVexPBP4fgSs6Yx9EroDqzXAolH94NQfb93sOJuawtNVhkEgjE9hec
+NumdpHMXhXGP0WI/jhicz4gaBDGyEwuSqUxMnfqNyQKBgQDyFx715F3iz2yfnsUQ
+xU7KheUjN0g/vhrcir31L9NuhRpWoBJyRUDeXekuCaDF2ElUXJAdUTMGWDwXxlLx
+aa5b8LPBL4pGvNRakfT1TJrViUm3A9wC4EO8l0IIpoYAEt8nstaw4pMEWLOSSKH/
+O2wG+v1h1/Xfd+ruTbmcBn6yLwKBgQDcCuSQoheMZrb6Hq+i+99LF3ZHVqJKUUCI
+XRnH3fhwhnMrsR9EshOVRtex0aAdl1GUWCAoVt4ZNom5m7b2qRji0gx8npwA0jxD
+CSDUw68Jy3MzQxDMPWNRI38P2r46CslNqCkEGlebbgHEJ0qzp2tIfN25pO6EXfjx
+wk9afY5n7QKBgQCG0Wtzgn7qfZs/dTrHsSnEzTYjG3lHzkXFRhqtfbngVY2qajB7
+pKeQbnoaIlB/fYiwy2+SdBLXWLH2h4LPYIwyNWTVk/UMmcIkwh3JsaSUgIUlv6d5
+jo0KbK3ghWQgjGHsCMNY9ITtKbyvHXXh3qS1andLUuphTbXuiihwhIlwDwKBgD9P
+QwP6HxxeUTcVrSMPpOdOENHlszv+tLqHTuuaieiWRnzDsWNqeQfyIg0faxoYd3hf
+AqGYnL5UWrv0eWfuryJTnRQd7nSuCHihH7kXtDz1NGgDW8nnv7OQqvY80Y6Rm+mk
+AGkVyy8FL6zoQS3/dXadto27ToT3JLEqXvqCNX7hAoGAPfNcJtXJXrXh9P3JZqkM
+pa8nRqUW0MeRt3v8rLqi4D7J6kW1Rkz5AhjiKkp1EwtE0IbGRI1EPhxT5DCMKlIy
+UX7VfP8nf+wb6dLHQ0s4oB20y5J6T7FAkD+50dE6Q/6fAl/2MkE+/R0npKRVhOlc
+eXIeBGzSc7p92K1p/vRMOZg=
+-----END PRIVATE KEY-----
diff --git a/integration-tests/src/test/resources/cert/root.cert b/integration-tests/src/test/resources/cert/onboarding-be/root.cert
index 11c827ac6f..11c827ac6f 100644
--- a/integration-tests/src/test/resources/cert/root.cert
+++ b/integration-tests/src/test/resources/cert/onboarding-be/root.cert
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManagerTest.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManagerTest.java
index 3b24c4feb6..b5479e0868 100644
--- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManagerTest.java
+++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManagerTest.java
@@ -20,27 +20,27 @@
package org.openecomp.sdc.vendorsoftwareproduct.security;
-import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
-
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertTrue;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
public class SecurityManagerTest {
+
private File certDir;
private String cerDirPath = "/tmp/cert/";
private SecurityManager securityManager;
- private File PrepareCertFiles(String origFilePath, String newFilePath) throws IOException, URISyntaxException {
+ private File prepareCertFiles(String origFilePath, String newFilePath) throws IOException, URISyntaxException {
File origFile = new File(getClass().getResource(origFilePath).toURI());
File newFile = new File(newFilePath);
newFile.createNewFile();
@@ -72,7 +72,7 @@ public class SecurityManagerTest {
@Test
public void testGetCertificates() throws IOException, SecurityManagerException, URISyntaxException {
- File newFile = PrepareCertFiles("/cert/root-certificate.pem", cerDirPath + "/root-certificate.pem");
+ File newFile = prepareCertFiles("/cert/root-certificate.pem", cerDirPath + "/root-certificate.pem");
assertEquals(1, securityManager.getTrustedCertificates().size());
newFile.delete();
assertEquals(0, securityManager.getTrustedCertificates().size());
@@ -98,9 +98,9 @@ public class SecurityManagerTest {
@Test
public void testGetCertificatesUpdated() throws IOException, SecurityManagerException, URISyntaxException {
- File newFile = PrepareCertFiles("/cert/root-certificate.pem", cerDirPath + "root-certificate.pem");
+ File newFile = prepareCertFiles("/cert/root-certificate.pem", cerDirPath + "root-certificate.pem");
assertTrue(securityManager.getTrustedCertificates().size() == 1);
- File otherNewFile = PrepareCertFiles("/cert/package-certificate.pem", cerDirPath + "package-certificate.pem");
+ File otherNewFile = prepareCertFiles("/cert/package-certificate.pem", cerDirPath + "package-certificate.pem");
assertEquals(2, securityManager.getTrustedCertificates().size());
otherNewFile.delete();
assertEquals(1, securityManager.getTrustedCertificates().size());
@@ -110,7 +110,7 @@ public class SecurityManagerTest {
@Test
public void verifySignedDataTestCertIncludedIntoSignature() throws IOException, URISyntaxException, SecurityManagerException {
- PrepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
+ prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
byte[] signature = readAllBytes("/cert/2-file-signed-package/dummyPnfv4.cms");
byte[] archive = readAllBytes("/cert/2-file-signed-package/dummyPnfv4.csar");
assertTrue(securityManager.verifySignedData(signature, null, archive));
@@ -119,7 +119,7 @@ public class SecurityManagerTest {
@Test
public void verifySignedDataTestCertNotIncludedIntoSignatureButExpected() throws IOException, URISyntaxException, SecurityManagerException {
Assertions.assertThrows(SecurityManagerException.class, () -> {
- PrepareCertFiles("/cert/root.cert", cerDirPath + "root.cert");
+ prepareCertFiles("/cert/root.cert", cerDirPath + "root.cert");
byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
securityManager.verifySignedData(signature, null, archive);
@@ -129,7 +129,7 @@ public class SecurityManagerTest {
@Test
public void verifySignedDataTestCertNotIncludedIntoSignature() throws IOException, URISyntaxException, SecurityManagerException {
- PrepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
+ prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
byte[] cert = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cert");
@@ -138,8 +138,8 @@ public class SecurityManagerTest {
@Test
public void verifySignedDataTestCertIntermediateNotIncludedIntoSignature() throws IOException, URISyntaxException, SecurityManagerException {
- PrepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
- PrepareCertFiles("/cert/package2.cert", cerDirPath + "signing-ca2.crt");
+ prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
+ prepareCertFiles("/cert/package2.cert", cerDirPath + "signing-ca2.crt");
byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
byte[] cert = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cert");
@@ -149,8 +149,8 @@ public class SecurityManagerTest {
@Test
public void verifySignedDataTestCertWrongIntermediate() throws IOException, URISyntaxException, SecurityManagerException {
Assertions.assertThrows(SecurityManagerException.class, () -> {
- PrepareCertFiles("/cert/root.cert", cerDirPath + "root.cert");
- PrepareCertFiles("/cert/signing-ca1.crt", cerDirPath + "signing-ca1.crt");
+ prepareCertFiles("/cert/root.cert", cerDirPath + "root.cert");
+ prepareCertFiles("/cert/signing-ca1.crt", cerDirPath + "signing-ca1.crt");
byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
byte[] cert = readAllBytes("/cert/3-file-signed-package/dummyPnfv4-no-intermediate.cert");
@@ -160,9 +160,10 @@ public class SecurityManagerTest {
}
@Test
- public void verifySignedDataTestCertIncludedIntoSignatureWithWrongIntermediateInDirectory() throws IOException, URISyntaxException, SecurityManagerException {
- PrepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
- PrepareCertFiles("/cert/signing-ca1.crt", cerDirPath + "signing-ca1.crt");
+ public void verifySignedDataTestCertIncludedIntoSignatureWithWrongIntermediateInDirectory()
+ throws IOException, URISyntaxException, SecurityManagerException {
+ prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
+ prepareCertFiles("/cert/signing-ca1.crt", cerDirPath + "signing-ca1.crt");
byte[] signature = readAllBytes("/cert/2-file-signed-package/dummyPnfv4.cms");
byte[] archive = readAllBytes("/cert/2-file-signed-package/dummyPnfv4.csar");
assertTrue(securityManager.verifySignedData(signature, null, archive));
@@ -170,8 +171,8 @@ public class SecurityManagerTest {
@Test
public void verifySignedDataTestCertWrongIntermediateInDirectory() throws IOException, URISyntaxException, SecurityManagerException {
- PrepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
- PrepareCertFiles("/cert/signing-ca1.crt", cerDirPath + "signing-ca1.crt");
+ prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
+ prepareCertFiles("/cert/signing-ca1.crt", cerDirPath + "signing-ca1.crt");
byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
byte[] cert = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cert");
@@ -181,7 +182,7 @@ public class SecurityManagerTest {
@Test
public void verifySignedDataTestWrongCertificate() throws IOException, URISyntaxException, SecurityManagerException {
Assertions.assertThrows(SecurityManagerException.class, () -> {
- PrepareCertFiles("/cert/root-certificate.pem", cerDirPath + "root-certificate.cert");
+ prepareCertFiles("/cert/root-certificate.pem", cerDirPath + "root-certificate.cert");
byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
byte[] cert = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cert");
@@ -193,7 +194,7 @@ public class SecurityManagerTest {
@Test
public void verifySignedDataTestChangedArchive() throws IOException, URISyntaxException, SecurityManagerException {
Assertions.assertThrows(SecurityManagerException.class, () -> {
- PrepareCertFiles("/cert/root.cert", cerDirPath + "root.cert");
+ prepareCertFiles("/cert/root.cert", cerDirPath + "root.cert");
byte[] signature = readAllBytes("/cert/tampered-signed-package/dummyPnfv4.cms");
byte[] archive = readAllBytes("/cert/tampered-signed-package/dummyPnfv4.csar");
securityManager.verifySignedData(signature, null, archive);
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/fileToSign.txt b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/fileToSign.txt
new file mode 100644
index 0000000000..cf3472103d
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/fileToSign.txt
@@ -0,0 +1 @@
+This is a file to be signed.
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/fileToSign.txt.cms b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/fileToSign.txt.cms
new file mode 100644
index 0000000000..c0ac6467da
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/fileToSign.txt.cms
@@ -0,0 +1,18 @@
+-----BEGIN CMS-----
+MIIC8gYJKoZIhvcNAQcCoIIC4zCCAt8CAQExDTALBglghkgBZQMEAgEwCwYJKoZI
+hvcNAQcBMYICvDCCArgCAQEwgaswgZIxCzAJBgNVBAYTAklSMRIwEAYDVQQIDAlX
+ZXN0bWVhdGgxEDAOBgNVBAcMB0F0aGxvbmUxETAPBgNVBAoMCGVzdC50ZWNoMREw
+DwYDVQQLDAhlc3QudGVjaDERMA8GA1UEAwwIZXN0LnRlY2gxJDAiBgkqhkiG9w0B
+CQEWFWFuZHJlLnNjaG1pZEBlc3QudGVjaAIUPr/6LGtQEr6HkS9OPY3VkUJocycw
+CwYJYIZIAWUDBAIBoIHkMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZI
+hvcNAQkFMQ8XDTIxMDEyODE2NTY0MlowLwYJKoZIhvcNAQkEMSIEIKJ0GRZdnzHz
+edaHW6QPdArXCWESAmfwrhzusQh4iDofMHkGCSqGSIb3DQEJDzFsMGowCwYJYIZI
+AWUDBAEqMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYIKoZIhvcNAwcwDgYI
+KoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIHMA0GCCqGSIb3DQMC
+AgEoMA0GCSqGSIb3DQEBAQUABIIBAFDH2MqTh2j7hhctKghJ0QJFyE2u8zkrWlzD
+WSVhVBJGiVHIuDe5bBGbT5h0Vvwde2bFNvb448p7Ymps68g8Wh+oFHS4wEEfmGtX
+rCjO+fw8JSol4/y0R49xBhACMgVzuUo7v6uaHMy13sHNsyFbA6k/QmV2nPYaD0VY
+6/qQN50soiNA/XGt6iDEwKsPMVv45Fl/tt/ldQ9MEpWaet3nvPS5/o2DMNQbB8c9
+moHi+05QLltoAQBn9dcipOuMXSyDUKFf0VsOBeHekTJ9BZdn4m938Vznr4zcE02P
+AvOTghecINTJEVCxwZlHf4sv96RjDLohMBX2VGY+6tjdgMCDDEg=
+-----END CMS-----
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/rootCA.cert b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/rootCA.cert
new file mode 100644
index 0000000000..24511f8456
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/rootCA.cert
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEBzCCAu+gAwIBAgIUPr/6LGtQEr6HkS9OPY3VkUJocycwDQYJKoZIhvcNAQEL
+BQAwgZIxCzAJBgNVBAYTAklSMRIwEAYDVQQIDAlXZXN0bWVhdGgxEDAOBgNVBAcM
+B0F0aGxvbmUxETAPBgNVBAoMCGVzdC50ZWNoMREwDwYDVQQLDAhlc3QudGVjaDER
+MA8GA1UEAwwIZXN0LnRlY2gxJDAiBgkqhkiG9w0BCQEWFWFuZHJlLnNjaG1pZEBl
+c3QudGVjaDAeFw0yMTAxMjgxNDIwMDBaFw0yMTAyMjcxNDIwMDBaMIGSMQswCQYD
+VQQGEwJJUjESMBAGA1UECAwJV2VzdG1lYXRoMRAwDgYDVQQHDAdBdGhsb25lMREw
+DwYDVQQKDAhlc3QudGVjaDERMA8GA1UECwwIZXN0LnRlY2gxETAPBgNVBAMMCGVz
+dC50ZWNoMSQwIgYJKoZIhvcNAQkBFhVhbmRyZS5zY2htaWRAZXN0LnRlY2gwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDc2nm2hCmwkN0CHn4xtdERaUY5
+NnypzPbond32qhRQAfJodLqRJVHx6p7moHmYCZJyYQxxSaAHXGsg64NvkM3OUoIv
+S/9wVh3S7PX7ZdxBxntK8iLxVxMoqJ0rzboU0PAvMgBWKl5pI0YQRvnwZkOCCEbp
+5CaBmT+j8x526mbyozr8fyaxpVDEnbYNp464DPOuVtdlXAz8+xNP935bOYDhvt0N
+EL8Eb+8peGvxowHXwYwFRiySzu13Lx6yR5UP+KP5PidGzm8jAKlkxPLZg3yGH23q
+/6Lw/4inS/gsl0j+REzZLl1hWcMsXwYWn9K457Xryyv9vYdImi47w9cikIbHAgMB
+AAGjUzBRMB0GA1UdDgQWBBQTRLbprizfJqO3nTYCgAuIbEpEfzAfBgNVHSMEGDAW
+gBQTRLbprizfJqO3nTYCgAuIbEpEfzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQB3MDFS6LMogHjYxhfgFJsvbpvSu9QNLNezHIdwOpJlz+iNMMr6
+OqqVLMVBjAjdtXOUcY0QSmpL5Jo25/5LY4vXpRoJRBDcZDyWUjuDGksBuPr+vxeD
+lA/JQ+xT8XOkNi75KcgARw8FUEAuOtbZtPGycOQj+ckeHcywod+ZOB3lyKgUk1Jl
+9S0QGF+6PI7WgCh9NMRXmSyFz9pskUeZxT73QNmknUz88XG3HDOTT4wEwOABeOV4
+xjMnyTiIWO+MsO0Jf51TcdRIhoxDylGLyHV1ihkFd5XBLVaSxkbHr65N0pR97nee
+nnoSqS+jd965dR1Ixwnoap2tLegACXsNDgC+
+-----END CERTIFICATE-----
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/rootCA.key b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/rootCA.key
new file mode 100644
index 0000000000..779e7e1655
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/cert/certificateManager/rootCA.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDc2nm2hCmwkN0C
+Hn4xtdERaUY5NnypzPbond32qhRQAfJodLqRJVHx6p7moHmYCZJyYQxxSaAHXGsg
+64NvkM3OUoIvS/9wVh3S7PX7ZdxBxntK8iLxVxMoqJ0rzboU0PAvMgBWKl5pI0YQ
+RvnwZkOCCEbp5CaBmT+j8x526mbyozr8fyaxpVDEnbYNp464DPOuVtdlXAz8+xNP
+935bOYDhvt0NEL8Eb+8peGvxowHXwYwFRiySzu13Lx6yR5UP+KP5PidGzm8jAKlk
+xPLZg3yGH23q/6Lw/4inS/gsl0j+REzZLl1hWcMsXwYWn9K457Xryyv9vYdImi47
+w9cikIbHAgMBAAECggEBAKasDpzKYvgIa3I09wGm+C/Opht5Xl16/H+S3DdSJeA3
+h+yC42W0p4INkXv1ca5m0umVCiHY8Xd8rLB8bIXe3yKtK+hrz0vFAd7zy7O9LJtL
+IjLuR6ahEyllDrBHIv6grBLCBnUApp1r7G1OU0O0uY/BlVrgPpshv2CIkt4liinj
+1Ix7Hy7bu2dp8JETon3sH4sqQ+/AJOalvR97FK1Dr6m2O3zF6b+kfb/9ZiVaork7
+kh03KblopQ8SG3N4YHGBcAGHRtRvfxCUYZ/CD1Ym8oeH/xRiYPJETeil6ogf2o5h
+3zbXVe1I1cOR5W2XVoSCvwbnH0lywx2jnvK+DtdYjLECgYEA/JV8a1DxOG+PEDmZ
+760bI5FTHwaq3aLVT9xnSfnRZzLpR1/dTLdS0R2plAggAcmp9OU2bSB17vmgUjg0
+2AmKNm2lyhCbP7H3IS5pBa4qmOn9i/HZpLkWMnS1h7wYyr0Q/6hfrJvCpkseFN9s
+2KWPGd/ehdVl1VJi/1uxh25q/bkCgYEA39chOw89IjJsPDY9sBhFBR03poiGMJB8
+sMPQ8fxxDiDHh+Hqn2GgAD7RFXtksxFd9iRrFCjMxL+Y+39zs29BpHklfGtZw8Ef
+jLxGORRam/NoTJDeyPgxjSlupSl436p2a72st2d948/2YHIH4tS3EaBjEJAcYA9O
+FXmI6/B16H8CgYEA+BcQDQyE0izpNUOOipbZyDaukRPocifFI1rV7Rg+cQHVlfB4
+GikaZCGhdbABWCAvGkalDczLaX2w1fE1HllIcyuBoxZqlsaDeQjvyM+IMYfrLTDQ
+2HWfctGll/vN0hygfKxxxMV9C/9OPawyah07kGuOUqAHFN+GM1Fp7x8qYakCgYEA
+g6Vy1dlQixw8q+z6uuaLMUbNxBPnWAiiTRPdf3SIyVZeA3zLEJHKGFrZfVjlEKvW
+Jz2j/GdChzRoNQHwekekw6a8dUBtusOKWqsgYdGmuLGfVeieHnRaMDt954VMob8P
+hq43NmaXk7Rroq1uFeolASjjGoqnJZfaxKaF8L2rmuECgYEAqjNkDrhmokEJ9Tj/
+Kj/bvFi9Hc67LPYNi24HqEHWFBu9Ss9SFMR5wyx+5sGmEffqoK6pQLhiivVCSJ+J
+4m6WCWRoXJWZsonUvVb68AajLw/FHjzMpxOehPVTRvwYFn77/0KmCnK40fe6y/dl
+yiV5bMP+AuBKc4+WITet1tYHM/c=
+-----END PRIVATE KEY-----
diff --git a/pom.xml b/pom.xml
index 3aadb7f735..90150f1ea6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -171,6 +171,7 @@ Modifications copyright (c) 2018-2019 Nokia
<surefire.skip.tests>false</surefire.skip.tests>
<docker.api.version>1.35</docker.api.version>
+ <bouncycastle.version>1.68</bouncycastle.version>
</properties>
<dependencyManagement>