aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-be-plugins
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 /catalog-be-plugins
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>
Diffstat (limited to 'catalog-be-plugins')
-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
15 files changed, 855 insertions, 53 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