summaryrefslogtreecommitdiffstats
path: root/catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/NsdCsarEtsiOption2Signer.java
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-be-plugins/etsi-nfv-nsd-csar-plugin/src/main/java/org/openecomp/sdc/be/plugins/etsi/nfv/nsd/security/NsdCsarEtsiOption2Signer.java')
-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
1 files changed, 151 insertions, 0 deletions
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);
+ }
+ }
+}