diff options
35 files changed, 1056 insertions, 406 deletions
@@ -2,6 +2,8 @@ all: build start-backend run-client stop-backend start-with-client: start-backend run-client .PHONY: build +CA_NAME=RA + build: @echo "##### Build Cert Service images locally #####" mvn clean install -P docker @@ -40,9 +42,9 @@ send-initialization-request: openssl req -new -newkey rsa:2048 -nodes -keyout `pwd`/compose-resources/certs-from-curl/ir.key \ -out `pwd`/compose-resources/certs-from-curl/ir.csr \ -subj "/C=US/ST=California/L=San-Francisco/OU=ONAP/O=Linux-Foundation/CN=onap.org" \ - -addext "subjectAltName = DNS:test.onap.org" + -addext "subjectAltName = DNS.1:test.onap.org,DNS.2:onap.org,IP.1:127.0.0.1,URI.1:ftp://test.org,email.1:test@onap.org" @echo "##### Send Initialization Request #####" - curl -sN https://localhost:8443/v1/certificate/RA -H "PK: $$(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \ + curl -sN https://localhost:8443/v1/certificate/${CA_NAME} -H "PK: $$(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \ -H "CSR: $$(cat ./compose-resources/certs-from-curl/ir.csr | base64 | tr -d \\n)" \ --cert `pwd`/certs/cmpv2Issuer-cert.pem \ --key `pwd`/certs/cmpv2Issuer-key.pem \ @@ -53,9 +55,9 @@ send-key-update-request: verify-initialization-request-files-exist openssl req -new -newkey rsa:2048 -nodes -keyout `pwd`/compose-resources/certs-from-curl/kur.key \ -out `pwd`/compose-resources/certs-from-curl/kur.csr \ -subj "/C=US/ST=California/L=San-Francisco/OU=ONAP/O=Linux-Foundation/CN=onap.org" \ - -addext "subjectAltName = DNS:test.onap.org" + -addext "subjectAltName = DNS.1:test.onap.org,DNS.2:onap.org,IP.1:127.0.0.1,URI.1:ftp://test.org,email.1:test@onap.org" @echo "##### Send Key Update Request #####" - curl -sN https://localhost:8443/v1/certificate-update/RA -H "PK: $$(cat ./compose-resources/certs-from-curl/kur.key | base64 | tr -d \\n)" \ + curl -sN https://localhost:8443/v1/certificate-update/${CA_NAME} -H "PK: $$(cat ./compose-resources/certs-from-curl/kur.key | base64 | tr -d \\n)" \ -H "CSR: $$(cat ./compose-resources/certs-from-curl/kur.csr | base64 | tr -d \\n)" \ -H "OLD_PK: $$(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \ -H "OLD_CERT: $$(cat ./compose-resources/certs-from-curl/ir-cert.pem | base64 | tr -d \\n)" \ @@ -68,9 +70,9 @@ send-certification-request: verify-initialization-request-files-exist openssl req -new -newkey rsa:2048 -nodes -keyout `pwd`/compose-resources/certs-from-curl/cr.key \ -out `pwd`/compose-resources/certs-from-curl/cr.csr \ -subj "/C=US/ST=California/L=San-Francisco/OU=ONAP/O=Linux-Foundation/CN=new-onap.org" \ - -addext "subjectAltName = DNS:test.onap.org" + -addext "subjectAltName = DNS.1:test.onap.org,DNS.2:onap.org,IP.1:127.0.0.1,URI.1:ftp://test.org,email.1:test@onap.org" @echo "##### Send Certification Request #####" - curl -sN https://localhost:8443/v1/certificate-update/RA -H "PK: $$(cat ./compose-resources/certs-from-curl/cr.key | base64 | tr -d \\n)" \ + curl -sN https://localhost:8443/v1/certificate-update/${CA_NAME} -H "PK: $$(cat ./compose-resources/certs-from-curl/cr.key | base64 | tr -d \\n)" \ -H "CSR: $$(cat ./compose-resources/certs-from-curl/cr.csr | base64 | tr -d \\n)" \ -H "OLD_PK: $$(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \ -H "OLD_CERT: $$(cat ./compose-resources/certs-from-curl/ir-cert.pem | base64 | tr -d \\n)" \ @@ -138,6 +138,11 @@ or: make send-certification-request ``` +To send request to custom CA use ```make <request> -e CA_NAME=<custom CA>``` e.g: +``` +make send-initialization-request -e CA_NAME=CUSTOM_CA +``` + ### OOM CertService CSITs #### CSIT repository ``` diff --git a/certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java b/certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java index d21b1eb5..8e2a378e 100644 --- a/certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java +++ b/certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java @@ -27,12 +27,12 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; -import org.onap.oom.certservice.certification.CertificationModelFactory; +import org.onap.oom.certservice.certification.CertificationResponseModelFactory; import org.onap.oom.certservice.certification.exception.CertificateDecryptionException; import org.onap.oom.certservice.certification.exception.DecryptionException; import org.onap.oom.certservice.certification.exception.ErrorResponseModel; import org.onap.oom.certservice.certification.model.CertificateUpdateModel; -import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.certification.model.CertificationResponseModel; import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,11 +51,11 @@ public class CertificationController { private static final Logger LOGGER = LoggerFactory.getLogger(CertificationController.class); - private final CertificationModelFactory certificationModelFactory; + private final CertificationResponseModelFactory certificationResponseModelFactory; @Autowired - CertificationController(CertificationModelFactory certificationModelFactory) { - this.certificationModelFactory = certificationModelFactory; + CertificationController(CertificationResponseModelFactory certificationResponseModelFactory) { + this.certificationResponseModelFactory = certificationResponseModelFactory; } /** @@ -80,7 +80,7 @@ public class CertificationController { summary = "sign certificate", description = "Web endpoint for requesting certificate signing. Used by system components to gain certificate signed by CA.", tags = {"CertificationService"}) - public ResponseEntity<CertificationModel> signCertificate( + public ResponseEntity<CertificationResponseModel> signCertificate( @Parameter(description = "Name of certification authority that will sign CSR.") @PathVariable String caName, @Parameter(description = "Certificate signing request in form of PEM object encoded in Base64 (with header and footer).") @@ -90,9 +90,9 @@ public class CertificationController { ) throws DecryptionException, CmpClientException { caName = replaceWhiteSpaceChars(caName); LOGGER.info("Received certificate signing request for CA named: {}", caName); - CertificationModel certificationModel = certificationModelFactory - .createCertificationModel(encodedCsr, encodedPrivateKey, caName); - return new ResponseEntity<>(certificationModel, HttpStatus.OK); + CertificationResponseModel certificationResponseModel = certificationResponseModelFactory + .provideCertificationModelFromInitialRequest(encodedCsr, encodedPrivateKey, caName); + return new ResponseEntity<>(certificationResponseModel, HttpStatus.OK); } /** @@ -106,13 +106,13 @@ public class CertificationController { * @return JSON containing trusted certificates and certificate chain */ @GetMapping(value = "v1/certificate-update/{caName}", produces = "application/json") - public ResponseEntity<CertificationModel> updateCertificate( + public ResponseEntity<CertificationResponseModel> updateCertificate( @PathVariable String caName, @RequestHeader("CSR") String encodedCsr, @RequestHeader("PK") String encodedPrivateKey, @RequestHeader("OLD_CERT") String encodedOldCert, @RequestHeader("OLD_PK") String encodedOldPrivateKey - ) throws DecryptionException, CertificateDecryptionException { + ) throws DecryptionException, CmpClientException, CertificateDecryptionException { caName = replaceWhiteSpaceChars(caName); LOGGER.info("Received certificate update request for CA named: {}", caName); CertificateUpdateModel certificateUpdateModel = new CertificateUpdateModel.CertificateUpdateModelBuilder() @@ -122,9 +122,9 @@ public class CertificationController { .setEncodedOldPrivateKey(encodedOldPrivateKey) .setCaName(caName) .build(); - CertificationModel certificationModel = certificationModelFactory - .createCertificationModel(certificateUpdateModel); - return new ResponseEntity<>(certificationModel, HttpStatus.OK); + CertificationResponseModel certificationResponseModel = certificationResponseModelFactory + .provideCertificationModelFromUpdateRequest(certificateUpdateModel); + return new ResponseEntity<>(certificationResponseModel, HttpStatus.OK); } private String replaceWhiteSpaceChars(String text) { diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/CertificateFactoryProvider.java b/certService/src/main/java/org/onap/oom/certservice/certification/CertificateFactoryProvider.java deleted file mode 100644 index 93fa4c21..00000000 --- a/certService/src/main/java/org/onap/oom/certservice/certification/CertificateFactoryProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Cert Service - * ================================================================================ - * Copyright (C) 2020 Nokia. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.oom.certservice.certification; - -import java.io.InputStream; -import java.security.NoSuchProviderException; -import java.security.Security; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.springframework.stereotype.Component; - -@Component -public class CertificateFactoryProvider { - - static { - Security.addProvider(new BouncyCastleProvider()); - } - - X509Certificate generateCertificate(InputStream inStream) throws CertificateException, NoSuchProviderException { - return (X509Certificate) CertificateFactory.getInstance("X.509", "BC").generateCertificate(inStream); - } -} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java index 91148a22..94e778e3 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * Cert Service * ================================================================================ - * Copyright (C) 2020 Nokia. All rights reserved. + * Copyright (C) 2020-2021 Nokia. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,8 +24,9 @@ import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator; import org.bouncycastle.util.io.pem.PemObjectGenerator; import org.bouncycastle.util.io.pem.PemWriter; import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; -import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.certification.model.CertificationResponseModel; import org.onap.oom.certservice.certification.model.CsrModel; +import org.onap.oom.certservice.certification.model.OldCertificateModel; import org.onap.oom.certservice.cmpv2client.api.CmpClient; import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel; @@ -52,11 +53,21 @@ public class CertificationProvider { this.cmpClient = cmpClient; } - public CertificationModel signCsr(CsrModel csrModel, Cmpv2Server server) + public CertificationResponseModel executeInitializationRequest(CsrModel csrModel, Cmpv2Server server) throws CmpClientException { - Cmpv2CertificationModel certificates = cmpClient.createCertificate(csrModel, server); - return new CertificationModel(convertFromX509CertificateListToPemList(certificates.getCertificateChain()), - convertFromX509CertificateListToPemList(certificates.getTrustedCertificates())); + Cmpv2CertificationModel certificates = cmpClient.executeInitializationRequest(csrModel, server); + return getCertificationResponseModel(certificates); + } + + public CertificationResponseModel executeKeyUpdateRequest(CsrModel csrModel, Cmpv2Server cmpv2Server, + OldCertificateModel oldCertificateModel) throws CmpClientException { + Cmpv2CertificationModel certificates = cmpClient.executeKeyUpdateRequest(csrModel, cmpv2Server, oldCertificateModel); + return getCertificationResponseModel(certificates); + } + + public CertificationResponseModel executeCertificationRequest(CsrModel csrModel, Cmpv2Server cmpv2Server) throws CmpClientException { + Cmpv2CertificationModel certificates = cmpClient.executeCertificationRequest(csrModel, cmpv2Server); + return getCertificationResponseModel(certificates); } private static List<String> convertFromX509CertificateListToPemList(List<X509Certificate> certificates) { @@ -64,6 +75,12 @@ public class CertificationProvider { .collect(Collectors.toList()); } + private CertificationResponseModel getCertificationResponseModel(Cmpv2CertificationModel certificates) { + return new CertificationResponseModel( + convertFromX509CertificateListToPemList(certificates.getCertificateChain()), + convertFromX509CertificateListToPemList(certificates.getTrustedCertificates())); + } + private static String convertFromX509CertificateToPem(X509Certificate certificate) { StringWriter sw = new StringWriter(); try (PemWriter pw = new PemWriter(sw)) { @@ -74,5 +91,4 @@ public class CertificationProvider { } return sw.toString(); } - } diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationResponseModelFactory.java index d5d9d9b8..0e793bb0 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationResponseModelFactory.java @@ -22,12 +22,15 @@ package org.onap.oom.certservice.certification; import org.onap.oom.certservice.certification.configuration.Cmpv2ServerProvider; import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.conversion.CsrModelFactory; +import org.onap.oom.certservice.certification.conversion.OldCertificateModelFactory; +import org.onap.oom.certservice.certification.conversion.StringBase64; import org.onap.oom.certservice.certification.exception.CertificateDecryptionException; import org.onap.oom.certservice.certification.exception.DecryptionException; import org.onap.oom.certservice.certification.model.CertificateUpdateModel; -import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.certification.model.CertificationResponseModel; import org.onap.oom.certservice.certification.model.CsrModel; -import org.onap.oom.certservice.certification.model.X509CertificateModel; +import org.onap.oom.certservice.certification.model.OldCertificateModel; import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,31 +38,31 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service -public class CertificationModelFactory { +public class CertificationResponseModelFactory { - private static final Logger LOGGER = LoggerFactory.getLogger(CertificationModelFactory.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CertificationResponseModelFactory.class); private final CsrModelFactory csrModelFactory; private final Cmpv2ServerProvider cmpv2ServerProvider; private final CertificationProvider certificationProvider; - private final X509CertificateModelFactory x509CertificateModelFactory; + private final OldCertificateModelFactory oldCertificateModelFactory; private final UpdateRequestTypeDetector updateRequestTypeDetector; @Autowired - CertificationModelFactory( + CertificationResponseModelFactory( CsrModelFactory csrModelFactory, Cmpv2ServerProvider cmpv2ServerProvider, CertificationProvider certificationProvider, - X509CertificateModelFactory x509CertificateModelFactory, + OldCertificateModelFactory oldCertificateModelFactory, UpdateRequestTypeDetector updateRequestTypeDetector) { this.cmpv2ServerProvider = cmpv2ServerProvider; this.csrModelFactory = csrModelFactory; this.certificationProvider = certificationProvider; - this.x509CertificateModelFactory = x509CertificateModelFactory; + this.oldCertificateModelFactory = oldCertificateModelFactory; this.updateRequestTypeDetector = updateRequestTypeDetector; } - public CertificationModel createCertificationModel(String encodedCsr, String encodedPrivateKey, String caName) + public CertificationResponseModel provideCertificationModelFromInitialRequest(String encodedCsr, String encodedPrivateKey, String caName) throws DecryptionException, CmpClientException { CsrModel csrModel = csrModelFactory.createCsrModel( new StringBase64(encodedCsr), @@ -72,11 +75,11 @@ public class CertificationModelFactory { LOGGER.info("Sending sign request for certification model for CA named: {}, and certificate signing request:\n{}", caName, csrModel); - return certificationProvider.signCsr(csrModel, cmpv2Server); + return certificationProvider.executeInitializationRequest(csrModel, cmpv2Server); } - public CertificationModel createCertificationModel(CertificateUpdateModel certificateUpdateModel) - throws DecryptionException, CertificateDecryptionException { + public CertificationResponseModel provideCertificationModelFromUpdateRequest(CertificateUpdateModel certificateUpdateModel) + throws DecryptionException, CmpClientException, CertificateDecryptionException { LOGGER.info("CSR: " + certificateUpdateModel.getEncodedCsr() + ", old cert: " + certificateUpdateModel.getEncodedOldCert() + ", CA: " + certificateUpdateModel.getCaName()); @@ -84,17 +87,22 @@ public class CertificationModelFactory { new StringBase64(certificateUpdateModel.getEncodedCsr()), new StringBase64(certificateUpdateModel.getEncodedPrivateKey()) ); - final X509CertificateModel certificateModel = x509CertificateModelFactory.createCertificateModel( - new StringBase64(certificateUpdateModel.getEncodedOldCert())); + final OldCertificateModel certificateModel = oldCertificateModelFactory.createCertificateModel( + new StringBase64(certificateUpdateModel.getEncodedOldCert()), certificateUpdateModel.getEncodedOldPrivateKey()); + + Cmpv2Server cmpv2Server = cmpv2ServerProvider.getCmpv2Server(certificateUpdateModel.getCaName()); + LOGGER.debug("Found server for given CA name: \n{}", cmpv2Server); + LOGGER.info("Sending update request for certification model for CA named: {}, and certificate update request:\n{}", + certificateUpdateModel.getCaName(), csrModel); if (updateRequestTypeDetector.isKur(csrModel.getCertificateData(), certificateModel.getCertificateData())) { LOGGER.info( "Certificate Signing Request and Old Certificate have the same parameters. Preparing Key Update Request"); - throw new UnsupportedOperationException("TODO: implement KUR in separate MR"); + return certificationProvider.executeKeyUpdateRequest(csrModel, cmpv2Server, certificateModel); } else { LOGGER.info( "Certificate Signing Request and Old Certificate have different parameters. Preparing Certification Request"); - throw new UnsupportedOperationException("TODO: implement CR in separate MR"); + return certificationProvider.executeCertificationRequest(csrModel, cmpv2Server); } } } diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/CsrModelFactory.java b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/CsrModelFactory.java index 789773d6..e4ee4c10 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/CsrModelFactory.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/CsrModelFactory.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.bouncycastle.util.io.pem.PemObject; diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/X509CertificateModelFactory.java b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/OldCertificateModelFactory.java index 17367ce7..f5c199f6 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/X509CertificateModelFactory.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/OldCertificateModelFactory.java @@ -18,49 +18,65 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; +import org.bouncycastle.util.io.pem.PemObject; +import org.onap.oom.certservice.certification.X509CertificateParser; import org.onap.oom.certservice.certification.exception.CertificateDecryptionException; +import org.onap.oom.certservice.certification.exception.KeyDecryptionException; import org.onap.oom.certservice.certification.exception.StringToCertificateConversionException; -import org.onap.oom.certservice.certification.model.X509CertificateModel; +import org.onap.oom.certservice.certification.model.OldCertificateModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service -public class X509CertificateModelFactory { +public class OldCertificateModelFactory { private static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"; private static final String END_CERTIFICATE = "-----END CERTIFICATE-----\n"; + private static final PemObjectFactory PEM_OBJECT_FACTORY = new PemObjectFactory(); private final PemStringToCertificateConverter pemStringToCertificateConverter; private final X509CertificateParser x509CertificateParser; @Autowired - public X509CertificateModelFactory(PemStringToCertificateConverter pemStringToCertificateConverter, + public OldCertificateModelFactory(PemStringToCertificateConverter pemStringToCertificateConverter, X509CertificateParser x509CertificateParser) { this.pemStringToCertificateConverter = pemStringToCertificateConverter; this.x509CertificateParser = x509CertificateParser; } - public X509CertificateModel createCertificateModel(StringBase64 base64EncodedCertificate) + public OldCertificateModel createCertificateModel(StringBase64 base64EncodedCertificate, String encodedOldPrivateKey) throws CertificateDecryptionException { final String certificateString = base64EncodedCertificate.asString() .map(this::getFirstCertificateFromCertificateChain) .orElseThrow(() -> new CertificateDecryptionException("Incorrect certificate, decryption failed")); try { - final X509Certificate certificate = pemStringToCertificateConverter.convert(certificateString); - final X500Name subjectData = x509CertificateParser.getSubject(certificate); - final GeneralName[] sans = x509CertificateParser.getSans(certificate); - return new X509CertificateModel(certificate, subjectData, sans); + final X509Certificate x509Certificate = pemStringToCertificateConverter.convert(certificateString); + final X500Name subjectData = x509CertificateParser.getSubject(x509Certificate); + final GeneralName[] sans = x509CertificateParser.getSans(x509Certificate); + final Certificate certificate = new JcaX509CertificateHolder(x509Certificate).toASN1Structure(); + final PrivateKey oldPrivateKey = getOldPrivateKeyObject(encodedOldPrivateKey); + return new OldCertificateModel(certificate, subjectData, sans, oldPrivateKey); } catch (StringToCertificateConversionException e) { throw new CertificateDecryptionException("Cannot convert certificate", e); } catch (CertificateParsingException e) { throw new CertificateDecryptionException("Cannot read Subject Alternative Names from certificate"); + } catch (NoSuchAlgorithmException | KeyDecryptionException | CertificateEncodingException | InvalidKeySpecException e) { + throw new CertificateDecryptionException("Cannot convert certificate or key", e); } } @@ -74,4 +90,18 @@ public class X509CertificateModelFactory { private boolean doesNotContainCertificates(String certificateChain) { return !(certificateChain.contains(BEGIN_CERTIFICATE) && certificateChain.contains(END_CERTIFICATE)); } + + private PrivateKey getOldPrivateKeyObject(String encodedOldPrivateKey) + throws KeyDecryptionException, InvalidKeySpecException, NoSuchAlgorithmException { + + StringBase64 stringBase64 = new StringBase64(encodedOldPrivateKey); + PemObject pemObject = stringBase64.asString() + .flatMap(PEM_OBJECT_FACTORY::createPemObject) + .orElseThrow( + () -> new KeyDecryptionException("Incorrect Key, decryption failed") + ); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pemObject.getContent()); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return keyFactory.generatePrivate(keySpec); + } } diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/PemObjectFactory.java b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/PemObjectFactory.java index 24d32bdd..0bded4d3 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/PemObjectFactory.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/PemObjectFactory.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; import java.io.IOException; import java.io.StringReader; diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/PemStringToCertificateConverter.java b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/PemStringToCertificateConverter.java index 7126cd4a..99499939 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/PemStringToCertificateConverter.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/PemStringToCertificateConverter.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; import java.io.IOException; import java.io.StringReader; diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/Pkcs10CertificationRequestFactory.java b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/Pkcs10CertificationRequestFactory.java index c38eb0a1..2b9399d0 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/Pkcs10CertificationRequestFactory.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/Pkcs10CertificationRequestFactory.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.bouncycastle.util.encoders.DecoderException; diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/RsaContentSignerBuilder.java b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/RsaContentSignerBuilder.java index 741b20ab..d869cef9 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/RsaContentSignerBuilder.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/RsaContentSignerBuilder.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; import java.io.IOException; import java.security.PrivateKey; diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/StringBase64.java b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/StringBase64.java index 9929e52c..4b4813ba 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/StringBase64.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/StringBase64.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; import java.util.Base64; import java.util.Objects; diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/X509CertificateBuilder.java b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/X509CertificateBuilder.java index 67aecb7c..88e77766 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/X509CertificateBuilder.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/conversion/X509CertificateBuilder.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; import java.io.IOException; import java.math.BigInteger; @@ -38,7 +38,7 @@ public class X509CertificateBuilder { private static final int SECURE_NEXT_BYTES = 16; private static final int VALID_PERIOD_IN_DAYS = 365; - X509v3CertificateBuilder build(PKCS10CertificationRequest csr) throws IOException { + public X509v3CertificateBuilder build(PKCS10CertificationRequest csr) throws IOException { return new X509v3CertificateBuilder(csr.getSubject(), createSerial(), Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)), Date.from(LocalDateTime.now().plusDays(VALID_PERIOD_IN_DAYS).toInstant(ZoneOffset.UTC)), diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/model/CertificationModel.java b/certService/src/main/java/org/onap/oom/certservice/certification/model/CertificationResponseModel.java index 08a09a75..27b9c917 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/model/CertificationModel.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/model/CertificationResponseModel.java @@ -23,12 +23,12 @@ package org.onap.oom.certservice.certification.model; import java.util.Collections; import java.util.List; -public class CertificationModel { +public class CertificationResponseModel { private final List<String> certificateChain; private final List<String> trustedCertificates; - public CertificationModel(List<String> certificateChain, List<String> trustedCertificates) { + public CertificationResponseModel(List<String> certificateChain, List<String> trustedCertificates) { this.certificateChain = certificateChain; this.trustedCertificates = trustedCertificates; } diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/model/X509CertificateModel.java b/certService/src/main/java/org/onap/oom/certservice/certification/model/OldCertificateModel.java index f45fb7d3..bd2d33a5 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/model/X509CertificateModel.java +++ b/certService/src/main/java/org/onap/oom/certservice/certification/model/OldCertificateModel.java @@ -20,22 +20,28 @@ package org.onap.oom.certservice.certification.model; -import java.security.cert.X509Certificate; +import java.security.PrivateKey; import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.asn1.x509.GeneralName; -public class X509CertificateModel { +public class OldCertificateModel { - private final X509Certificate certificate; private final CertificateData certificateData; - public X509CertificateModel(X509Certificate certificate, X500Name subjectData, - GeneralName[] sans) { - this.certificate = certificate; + private final Certificate certificate; + + private final PrivateKey oldPrivateKey; + + + public OldCertificateModel(Certificate certificate, X500Name subjectData, + GeneralName[] sans, PrivateKey oldPrivateKey) { this.certificateData = new CertificateData(subjectData, sans); + this.certificate = certificate; + this.oldPrivateKey = oldPrivateKey; } - public X509Certificate getCertificate() { + public Certificate getOldCertificate() { return certificate; } @@ -50,4 +56,8 @@ public class X509CertificateModel { public CertificateData getCertificateData() { return certificateData; } + + public PrivateKey getOldPrivateKey() { + return oldPrivateKey; + } } diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java index d525c6e3..0d9fdeea 100644 --- a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix Foundation. + * Copyright (C) 2021 Nokia. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +25,7 @@ import java.util.Date; import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; import org.onap.oom.certservice.certification.model.CsrModel; +import org.onap.oom.certservice.certification.model.OldCertificateModel; import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel; @@ -49,7 +51,7 @@ public interface CmpClient { * @return model for certification containing certificate chain and trusted certificates * @throws CmpClientException if client error occurs. */ - Cmpv2CertificationModel createCertificate( + Cmpv2CertificationModel executeInitializationRequest( CsrModel csrModel, Cmpv2Server server, Date notBefore, @@ -67,8 +69,36 @@ public interface CmpClient { * @return model for certification containing certificate chain and trusted certificates * @throws CmpClientException if client error occurs. */ - Cmpv2CertificationModel createCertificate( + Cmpv2CertificationModel executeInitializationRequest( CsrModel csrModel, Cmpv2Server server) throws CmpClientException; + + /** + * Requests for a External Root CA Certificate to be updated for the passed keyPair wrapped + * in a CSRMeta with common details. Authentication using End Entity Certificate. Old certificate and old privateKey + * are wrapped in CertificateUpdateModel.class + * Exception thrown if verification fails or issue encountered in fetching certificate from CA. + * + * @param csrModel Certificate Signing Request Model. Must not be {@code null}. + * @param cmpv2Server CMPv2 server. Must not be {@code null}. + * @param oldCertificateModel Model with key update parameters {@code null}. + * @return model for certification containing certificate chain and trusted certificates + * @throws CmpClientException if client error occurs. + */ + Cmpv2CertificationModel executeKeyUpdateRequest(CsrModel csrModel, Cmpv2Server cmpv2Server, + OldCertificateModel oldCertificateModel) throws CmpClientException; + + /** + * Requests for an additional External Root CA Certificate to be created for the passed keyPair wrapped + * in a CSRMeta with common details. Basic Authentication using IAK/RV, Verification of the signature + * (proof-of-possession) on the request is performed and an Exception thrown if verification fails + * or issue encountered in fetching certificate from CA. + * + * @param csrModel Certificate Signing Request Model. Must not be {@code null}. + * @param cmpv2Server CMPv2 server. Must not be {@code null}. + * @return model for certification containing certificate chain and trusted certificates + * @throws CmpClientException if client error occurs. + */ + Cmpv2CertificationModel executeCertificationRequest(CsrModel csrModel, Cmpv2Server cmpv2Server) throws CmpClientException; } diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java index 06e785ac..bbca91b6 100644 --- a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java @@ -25,13 +25,10 @@ package org.onap.oom.certservice.cmpv2client.impl; import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseHelper.checkIfCmpResponseContainsError; import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseHelper.getCertFromByteArray; import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore; -import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.checkImplicitConfirm; -import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.verifyPasswordBasedProtection; -import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.verifySignature; import java.io.IOException; import java.security.KeyPair; -import java.security.PublicKey; +import java.security.Security; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.Collections; @@ -39,21 +36,20 @@ import java.util.Date; import java.util.Objects; import java.util.Optional; import org.apache.http.impl.client.CloseableHttpClient; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.cmp.CMPCertificate; import org.bouncycastle.asn1.cmp.CertRepMessage; import org.bouncycastle.asn1.cmp.CertResponse; import org.bouncycastle.asn1.cmp.PKIBody; -import org.bouncycastle.asn1.cmp.PKIHeader; import org.bouncycastle.asn1.cmp.PKIMessage; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.onap.oom.certservice.certification.configuration.model.CaMode; +import org.bouncycastle.asn1.x509.Certificate; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; import org.onap.oom.certservice.certification.model.CsrModel; +import org.onap.oom.certservice.certification.model.OldCertificateModel; import org.onap.oom.certservice.cmpv2client.api.CmpClient; import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; -import org.onap.oom.certservice.cmpv2client.exceptions.CmpServerException; import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel; +import org.onap.oom.certservice.cmpv2client.validation.CmpCertificationValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -65,105 +61,137 @@ public class CmpClientImpl implements CmpClient { private static final Logger LOG = LoggerFactory.getLogger(CmpClientImpl.class); private final CloseableHttpClient httpClient; - - private static final String DEFAULT_CA_NAME = "Certification Authority"; - private static final String DEFAULT_PROFILE = CaMode.RA.getProfile(); - private static final ASN1ObjectIdentifier PASSWORD_BASED_MAC = new ASN1ObjectIdentifier("1.2.840.113533.7.66.13"); + private final CmpCertificationValidator validator; public CmpClientImpl(CloseableHttpClient httpClient) { this.httpClient = httpClient; + this.validator = new CmpCertificationValidator(); + } + + static { + Security.addProvider(new BouncyCastleProvider()); } @Override - public Cmpv2CertificationModel createCertificate( + public Cmpv2CertificationModel executeInitializationRequest( CsrModel csrModel, Cmpv2Server server, Date notBefore, Date notAfter) throws CmpClientException { - validate(csrModel, server, httpClient, notBefore, notAfter); - KeyPair keyPair = new KeyPair(csrModel.getPublicKey(), csrModel.getPrivateKey()); + validator.validate(csrModel, server, httpClient, notBefore, notAfter); + final CreateCertRequest certRequest = getIakRvRequest(csrModel, server, notBefore, notAfter, PKIBody.TYPE_INIT_REQ); + return executeCmpRequest(csrModel, server, certRequest); + } + + @Override + public Cmpv2CertificationModel executeInitializationRequest(CsrModel csrModel, Cmpv2Server server) + throws CmpClientException { + return executeInitializationRequest(csrModel, server, null, null); + } + + @Override + public Cmpv2CertificationModel executeKeyUpdateRequest(CsrModel csrModel, Cmpv2Server cmpv2Server, + OldCertificateModel oldCertificateModel) throws CmpClientException { + validator.validate(csrModel, cmpv2Server, httpClient, null, null); + + final PkiMessageProtection pkiMessageProtection = getSignatureProtection(oldCertificateModel); + final CreateCertRequest certRequest = + getCmpMessageBuilderWithCommonRequestValues(csrModel, cmpv2Server) + .with(CreateCertRequest::setCmpRequestType, PKIBody.TYPE_KEY_UPDATE_REQ) + .with(CreateCertRequest::setExtraCerts, getCMPCertificate(oldCertificateModel.getOldCertificate())) + .with(CreateCertRequest::setProtection, pkiMessageProtection) + .build(); + + return executeCmpRequest(csrModel, cmpv2Server, certRequest); + } + + @Override + public Cmpv2CertificationModel executeCertificationRequest(CsrModel csrModel, Cmpv2Server cmpv2Server) throws CmpClientException { + + validator.validate(csrModel, cmpv2Server, httpClient, null, null); + final CreateCertRequest certRequest = getIakRvRequest(csrModel, cmpv2Server, null, null, PKIBody.TYPE_CERT_REQ); + return executeCmpRequest(csrModel, cmpv2Server, certRequest); + } + + private CreateCertRequest getIakRvRequest( + CsrModel csrModel, + Cmpv2Server server, + Date notBefore, + Date notAfter, + int requestType) { final String iak = server.getAuthentication().getIak(); final PkiMessageProtection pkiMessageProtection = new PasswordBasedProtection(iak); - final CreateCertRequest certRequest = - CmpMessageBuilder.of(CreateCertRequest::new) - .with(CreateCertRequest::setIssuerDn, server.getIssuerDN()) - .with(CreateCertRequest::setSubjectDn, csrModel.getSubjectData()) - .with(CreateCertRequest::setSansArray, csrModel.getSans()) - .with(CreateCertRequest::setSubjectKeyPair, keyPair) - .with(CreateCertRequest::setNotBefore, notBefore) - .with(CreateCertRequest::setNotAfter, notAfter) - .with(CreateCertRequest::setSenderKid, server.getAuthentication().getRv()) - .with(CreateCertRequest::setProtection, pkiMessageProtection) - .build(); + return getCmpMessageBuilderWithCommonRequestValues(csrModel, server) + .with(CreateCertRequest::setNotBefore, notBefore) + .with(CreateCertRequest::setNotAfter, notAfter) + .with(CreateCertRequest::setSenderKid, server.getAuthentication().getRv()) + .with(CreateCertRequest::setCmpRequestType, requestType) + .with(CreateCertRequest::setProtection, pkiMessageProtection) + .build(); + } + private Cmpv2CertificationModel executeCmpRequest(CsrModel csrModel, Cmpv2Server cmpv2Server, + CreateCertRequest certRequest) throws CmpClientException { final PKIMessage pkiMessage = certRequest.generateCertReq(); Cmpv2HttpClient cmpv2HttpClient = new Cmpv2HttpClient(httpClient); - return retrieveCertificates(csrModel, server, pkiMessage, cmpv2HttpClient); + return retrieveCertificates(csrModel, cmpv2Server, pkiMessage, cmpv2HttpClient); } - @Override - public Cmpv2CertificationModel createCertificate(CsrModel csrModel, Cmpv2Server server) - throws CmpClientException { - return createCertificate(csrModel, server, null, null); + private CmpMessageBuilder<CreateCertRequest> getCmpMessageBuilderWithCommonRequestValues(CsrModel csrModel, + Cmpv2Server cmpv2Server) { + KeyPair keyPair = new KeyPair(csrModel.getPublicKey(), csrModel.getPrivateKey()); + return CmpMessageBuilder.of(CreateCertRequest::new) + .with(CreateCertRequest::setIssuerDn, cmpv2Server.getIssuerDN()) + .with(CreateCertRequest::setSubjectDn, csrModel.getSubjectData()) + .with(CreateCertRequest::setSansArray, csrModel.getSans()) + .with(CreateCertRequest::setSubjectKeyPair, keyPair); } - private void checkCmpResponse( - final PKIMessage respPkiMessage, final PublicKey publicKey, final String initAuthPassword) - throws CmpClientException { - final PKIHeader header = respPkiMessage.getHeader(); - final AlgorithmIdentifier protectionAlgo = header.getProtectionAlg(); - verifySignatureWithPublicKey(respPkiMessage, publicKey); - if (isPasswordBasedMacAlgorithm(protectionAlgo)) { - LOG.info("CMP response is protected by Password Base Mac Algorithm. Attempt to verify protection"); - verifyPasswordBasedMacProtection(respPkiMessage, initAuthPassword, header, protectionAlgo); - } + private SignatureProtection getSignatureProtection(OldCertificateModel oldCertificateModel) { + return new SignatureProtection(oldCertificateModel.getOldPrivateKey()); } - private boolean isPasswordBasedMacAlgorithm(AlgorithmIdentifier protectionAlgo) throws CmpClientException { - if (Objects.isNull(protectionAlgo)) { - LOG.error("CMP response does not contain Protection Algorithm field"); - throw new CmpClientException("CMP response does not contain Protection Algorithm field"); - } - return PASSWORD_BASED_MAC.equals(protectionAlgo.getAlgorithm()); + private CMPCertificate[] getCMPCertificate(Certificate oldCertificate) { + CMPCertificate cert = new CMPCertificate(oldCertificate); + return new CMPCertificate[]{cert}; } - private void verifySignatureWithPublicKey(PKIMessage respPkiMessage, PublicKey publicKey) + private Cmpv2CertificationModel retrieveCertificates( + CsrModel csrModel, Cmpv2Server server, PKIMessage pkiMessage, Cmpv2HttpClient cmpv2HttpClient) throws CmpClientException { - if (Objects.nonNull(publicKey)) { - LOG.debug("Verifying signature of the response."); - verifySignature(respPkiMessage, publicKey); - } else { - LOG.error("Public Key is not available, therefore cannot verify signature"); - throw new CmpClientException( - "Public Key is not available, therefore cannot verify signature"); + final byte[] respBytes = cmpv2HttpClient.postRequest(pkiMessage, server.getUrl(), server.getCaName()); + try { + final PKIMessage respPkiMessage = PKIMessage.getInstance(respBytes); + LOG.info("Received response from Server"); + checkIfCmpResponseContainsError(respPkiMessage); + validator.checkCmpResponse(respPkiMessage, csrModel.getPublicKey(), server.getAuthentication().getIak()); + return checkCmpCertRepMessage(respPkiMessage); + } catch (IllegalArgumentException iae) { + CmpClientException cmpClientException = + new CmpClientException( + "Error encountered while processing response from CA server ", iae); + LOG.error("Error encountered while processing response from CA server ", iae); + throw cmpClientException; } } - private void verifyPasswordBasedMacProtection(PKIMessage respPkiMessage, String initAuthPassword, - PKIHeader header, AlgorithmIdentifier protectionAlgo) - throws CmpClientException { - LOG.debug("Verifying PasswordBased Protection of the Response."); - verifyPasswordBasedProtection(respPkiMessage, initAuthPassword, protectionAlgo); - checkImplicitConfirm(header); - } - private Cmpv2CertificationModel checkCmpCertRepMessage(final PKIMessage respPkiMessage) - throws CmpClientException { + throws CmpClientException { final PKIBody pkiBody = respPkiMessage.getBody(); if (Objects.nonNull(pkiBody) && pkiBody.getContent() instanceof CertRepMessage) { final CertRepMessage certRepMessage = (CertRepMessage) pkiBody.getContent(); if (Objects.nonNull(certRepMessage)) { try { CertResponse certResponse = getCertificateResponseContainingNewCertificate(certRepMessage); - checkServerResponse(certResponse); + validator.checkServerResponse(certResponse); return verifyReturnCertChainAndTrustStore(respPkiMessage, certRepMessage, certResponse); } catch (IOException | CertificateParsingException ex) { CmpClientException cmpClientException = - new CmpClientException( - "Exception occurred while retrieving Certificates from response", ex); + new CmpClientException( + "Exception occurred while retrieving Certificates from response", ex); LOG.error("Exception occurred while retrieving Certificates from response", ex); throw cmpClientException; } @@ -174,98 +202,23 @@ public class CmpClientImpl implements CmpClient { return new Cmpv2CertificationModel(Collections.emptyList(), Collections.emptyList()); } - private void checkServerResponse(CertResponse certResponse) { - if (certResponse.getStatus() != null && certResponse.getStatus().getStatus() != null) { - logServerResponse(certResponse); - if (certResponse.getStatus().getStatus().intValue() == PkiStatus.REJECTED.getCode()) { - String serverMessage = certResponse.getStatus().getStatusString().getStringAt(0).getString(); - throw new CmpServerException(Optional.ofNullable(serverMessage).orElse("N/A")); - } - } - } - - private void logServerResponse(CertResponse certResponse) { - if (LOG.isInfoEnabled()) { - LOG.info("Response status code: {}", certResponse.getStatus().getStatus()); - } - if (certResponse.getStatus().getStatusString() != null) { - String serverMessage = certResponse.getStatus().getStatusString().getStringAt(0).getString(); - LOG.warn("Response status text: {}", serverMessage); - } - if (LOG.isWarnEnabled() && certResponse.getStatus().getFailInfo() != null) { - LOG.warn("Response fail info: {}", certResponse.getStatus().getFailInfo()); - } - } - private Cmpv2CertificationModel verifyReturnCertChainAndTrustStore( - PKIMessage respPkiMessage, CertRepMessage certRepMessage, CertResponse certResponse) - throws CertificateParsingException, CmpClientException, IOException { + PKIMessage respPkiMessage, CertRepMessage certRepMessage, CertResponse certResponse) + throws CertificateParsingException, CmpClientException, IOException { LOG.info("Verifying certificates returned as part of CertResponse."); final CMPCertificate cmpCertificate = - certResponse.getCertifiedKeyPair().getCertOrEncCert().getCertificate(); + certResponse.getCertifiedKeyPair().getCertOrEncCert().getCertificate(); final Optional<X509Certificate> leafCertificate = - getCertFromByteArray(cmpCertificate.getEncoded(), X509Certificate.class); + getCertFromByteArray(cmpCertificate.getEncoded(), X509Certificate.class); if (leafCertificate.isPresent()) { return verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate.get()); + respPkiMessage, certRepMessage, leafCertificate.get()); } return new Cmpv2CertificationModel(Collections.emptyList(), Collections.emptyList()); } private CertResponse getCertificateResponseContainingNewCertificate( - CertRepMessage certRepMessage) { + CertRepMessage certRepMessage) { return certRepMessage.getResponse()[0]; } - - /** - * Validate inputs for Certificate Creation. - * - * @param csrModel Certificate Signing Request model. Must not be {@code null}. - * @param server CMPv2 Server. Must not be {@code null}. - * @throws IllegalArgumentException if Before Date is set after the After Date. - */ - private static void validate( - final CsrModel csrModel, - final Cmpv2Server server, - final CloseableHttpClient httpClient, - final Date notBefore, - final Date notAfter) { - - String caName = CmpUtil.isNullOrEmpty(server.getCaName()) ? server.getCaName() : DEFAULT_CA_NAME; - String profile = server.getCaMode() != null ? server.getCaMode().getProfile() : DEFAULT_PROFILE; - LOG.info( - "Validate before creating Certificate Request for CA :{} in Mode {} ", caName, profile); - - CmpUtil.notNull(csrModel, "CsrModel Instance"); - CmpUtil.notNull(csrModel.getSubjectData(), "Subject DN"); - CmpUtil.notNull(csrModel.getPrivateKey(), "Subject private key"); - CmpUtil.notNull(csrModel.getPublicKey(), "Subject public key"); - CmpUtil.notNull(server.getIssuerDN(), "Issuer DN"); - CmpUtil.notNull(server.getUrl(), "External CA URL"); - CmpUtil.notNull(server.getAuthentication().getIak(), "IAK/RV Password"); - CmpUtil.notNull(httpClient, "Closeable Http Client"); - - if (notBefore != null && notAfter != null && notBefore.compareTo(notAfter) > 0) { - throw new IllegalArgumentException("Before Date is set after the After Date"); - } - } - - private Cmpv2CertificationModel retrieveCertificates( - CsrModel csrModel, Cmpv2Server server, PKIMessage pkiMessage, Cmpv2HttpClient cmpv2HttpClient) - throws CmpClientException { - final byte[] respBytes = cmpv2HttpClient.postRequest(pkiMessage, server.getUrl(), server.getCaName()); - try { - final PKIMessage respPkiMessage = PKIMessage.getInstance(respBytes); - LOG.info("Received response from Server"); - checkIfCmpResponseContainsError(respPkiMessage); - checkCmpResponse(respPkiMessage, csrModel.getPublicKey(), server.getAuthentication().getIak()); - return checkCmpCertRepMessage(respPkiMessage); - } catch (IllegalArgumentException iae) { - CmpClientException cmpClientException = - new CmpClientException( - "Error encountered while processing response from CA server ", iae); - LOG.error("Error encountered while processing response from CA server ", iae); - throw cmpClientException; - } - } } diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java index 0ed493b7..c3283044 100644 --- a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java @@ -29,6 +29,7 @@ import java.util.Date; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.cmp.CMPCertificate; import org.bouncycastle.asn1.cmp.PKIBody; import org.bouncycastle.asn1.cmp.PKIHeader; import org.bouncycastle.asn1.cmp.PKIMessage; @@ -58,6 +59,8 @@ class CreateCertRequest { private Date notBefore; private Date notAfter; private String senderKid; + private int cmpRequestType; + private CMPCertificate[] extraCerts; private final int certReqId = createRandomInt(Integer.MAX_VALUE); private final AlgorithmIdentifier signingAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder() @@ -95,6 +98,14 @@ class CreateCertRequest { this.senderKid = senderKid; } + public void setCmpRequestType(int requestType) { + this.cmpRequestType = requestType; + } + + public void setExtraCerts(CMPCertificate[] extraCert) { + this.extraCerts = extraCert; + } + /** * Method to create {@link PKIMessage} from {@link CertRequest},{@link ProofOfPossession}, {@link * CertReqMsg}, {@link CertReqMessages}, {@link PKIHeader} and {@link PKIBody}. @@ -127,9 +138,9 @@ class CreateCertRequest { issuerDn, pkiMessageProtection.getAlgorithmIdentifier(), senderKid); - final PKIBody pkiBody = new PKIBody(PKIBody.TYPE_INIT_REQ, certReqMessages); + final PKIBody pkiBody = new PKIBody(cmpRequestType, certReqMessages); final DERBitString messageProtection = this.pkiMessageProtection.generatePkiMessageProtection(pkiHeader, pkiBody); - return new PKIMessage(pkiHeader, pkiBody, messageProtection); + return new PKIMessage(pkiHeader, pkiBody, messageProtection, extraCerts); } } diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/validation/CmpCertificationValidator.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/validation/CmpCertificationValidator.java new file mode 100644 index 00000000..40a2a1d9 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/validation/CmpCertificationValidator.java @@ -0,0 +1,142 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Modification copyright 2021 Nokia + * ================================================================================ + * 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.onap.oom.certservice.cmpv2client.validation; + +import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.checkImplicitConfirm; +import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.verifyPasswordBasedProtection; +import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.verifySignature; + +import java.security.PublicKey; +import java.util.Date; +import java.util.Objects; +import java.util.Optional; +import org.apache.http.impl.client.CloseableHttpClient; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.cmp.CertResponse; +import org.bouncycastle.asn1.cmp.PKIHeader; +import org.bouncycastle.asn1.cmp.PKIMessage; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.onap.oom.certservice.certification.configuration.model.CaMode; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.model.CsrModel; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpServerException; +import org.onap.oom.certservice.cmpv2client.impl.CmpUtil; +import org.onap.oom.certservice.cmpv2client.impl.PkiStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CmpCertificationValidator { + private static final String DEFAULT_CA_NAME = "Certification Authority"; + private static final String DEFAULT_PROFILE = CaMode.RA.getProfile(); + private static final ASN1ObjectIdentifier PASSWORD_BASED_MAC = new ASN1ObjectIdentifier("1.2.840.113533.7.66.13"); + private static final Logger LOG = LoggerFactory.getLogger(CmpCertificationValidator.class); + + public static void validate( + final CsrModel csrModel, + final Cmpv2Server server, + final CloseableHttpClient httpClient, + final Date notBefore, + final Date notAfter) { + + String caName = CmpUtil.isNullOrEmpty(server.getCaName()) ? server.getCaName() : DEFAULT_CA_NAME; + String profile = server.getCaMode() != null ? server.getCaMode().getProfile() : DEFAULT_PROFILE; + LOG.info( + "Validate before creating Certificate Request for CA :{} in Mode {} ", caName, profile); + + CmpUtil.notNull(csrModel, "CsrModel Instance"); + CmpUtil.notNull(csrModel.getSubjectData(), "Subject DN"); + CmpUtil.notNull(csrModel.getPrivateKey(), "Subject private key"); + CmpUtil.notNull(csrModel.getPublicKey(), "Subject public key"); + CmpUtil.notNull(server.getIssuerDN(), "Issuer DN"); + CmpUtil.notNull(server.getUrl(), "External CA URL"); + CmpUtil.notNull(server.getAuthentication().getIak(), "IAK/RV Password"); + CmpUtil.notNull(httpClient, "Closeable Http Client"); + + if (notBefore != null && notAfter != null && notBefore.compareTo(notAfter) > 0) { + throw new IllegalArgumentException("Before Date is set after the After Date"); + } + } + + public void checkCmpResponse(final PKIMessage respPkiMessage, final PublicKey publicKey, final String initAuthPassword) + throws CmpClientException { + final PKIHeader header = respPkiMessage.getHeader(); + final AlgorithmIdentifier protectionAlgo = header.getProtectionAlg(); + verifySignatureWithPublicKey(respPkiMessage, publicKey); + if (isPasswordBasedMacAlgorithm(protectionAlgo)) { + LOG.info("CMP response is protected by Password Base Mac Algorithm. Attempt to verify protection"); + verifyPasswordBasedMacProtection(respPkiMessage, initAuthPassword, header, protectionAlgo); + } + } + + public void checkServerResponse(CertResponse certResponse) { + if (certResponse.getStatus() != null && certResponse.getStatus().getStatus() != null) { + logServerResponse(certResponse); + if (certResponse.getStatus().getStatus().intValue() == PkiStatus.REJECTED.getCode()) { + String serverMessage = certResponse.getStatus().getStatusString().getStringAt(0).getString(); + throw new CmpServerException(Optional.ofNullable(serverMessage).orElse("N/A")); + } + } + } + + private boolean isPasswordBasedMacAlgorithm(AlgorithmIdentifier protectionAlgo) throws CmpClientException { + if (Objects.isNull(protectionAlgo)) { + LOG.error("CMP response does not contain Protection Algorithm field"); + throw new CmpClientException("CMP response does not contain Protection Algorithm field"); + } + return PASSWORD_BASED_MAC.equals(protectionAlgo.getAlgorithm()); + } + + private void verifySignatureWithPublicKey(PKIMessage respPkiMessage, PublicKey publicKey) + throws CmpClientException { + if (Objects.nonNull(publicKey)) { + LOG.debug("Verifying signature of the response."); + verifySignature(respPkiMessage, publicKey); + } else { + LOG.error("Public Key is not available, therefore cannot verify signature"); + throw new CmpClientException( + "Public Key is not available, therefore cannot verify signature"); + } + } + + private void verifyPasswordBasedMacProtection(PKIMessage respPkiMessage, String initAuthPassword, + PKIHeader header, AlgorithmIdentifier protectionAlgo) + throws CmpClientException { + LOG.debug("Verifying PasswordBased Protection of the Response."); + verifyPasswordBasedProtection(respPkiMessage, initAuthPassword, protectionAlgo); + checkImplicitConfirm(header); + } + + private void logServerResponse(CertResponse certResponse) { + if (LOG.isInfoEnabled()) { + LOG.info("Response status code: {}", certResponse.getStatus().getStatus()); + } + if (certResponse.getStatus().getStatusString() != null) { + String serverMessage = certResponse.getStatus().getStatusString().getStringAt(0).getString(); + LOG.warn("Response status text: {}", serverMessage); + } + if (LOG.isWarnEnabled() && certResponse.getStatus().getFailInfo() != null) { + LOG.warn("Response fail info: {}", certResponse.getStatus().getFailInfo()); + } + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/api/CertificationControllerTest.java b/certService/src/test/java/org/onap/oom/certservice/api/CertificationControllerTest.java index f1d5baaf..81c2d39a 100644 --- a/certService/src/test/java/org/onap/oom/certservice/api/CertificationControllerTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/api/CertificationControllerTest.java @@ -33,15 +33,14 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.onap.oom.certservice.certification.exception.CertificateDecryptionException; -import org.onap.oom.certservice.certification.exception.StringToCertificateConversionException; import org.onap.oom.certservice.certification.model.CertificateUpdateModel; -import org.onap.oom.certservice.certification.CertificationModelFactory; +import org.onap.oom.certservice.certification.CertificationResponseModelFactory; import org.onap.oom.certservice.certification.exception.Cmpv2ServerNotFoundException; import org.onap.oom.certservice.certification.exception.CsrDecryptionException; import org.onap.oom.certservice.certification.exception.DecryptionException; import org.onap.oom.certservice.certification.exception.KeyDecryptionException; import org.onap.oom.certservice.certification.model.CertificateUpdateModel.CertificateUpdateModelBuilder; -import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.certification.model.CertificationResponseModel; import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -68,32 +67,33 @@ class CertificationControllerTest { private CertificationController certificationController; @Mock - private CertificationModelFactory certificationModelFactory; + private CertificationResponseModelFactory certificationResponseModelFactory; @BeforeEach void serUp() { - certificationController = new CertificationController(certificationModelFactory); + certificationController = new CertificationController(certificationResponseModelFactory); } @Test void shouldReturnDataAboutCsrBaseOnEncodedParameters() throws DecryptionException, CmpClientException { // Given - CertificationModel testCertificationModel = new CertificationModel( + CertificationResponseModel testCertificationResponseModel = new CertificationResponseModel( Arrays.asList("ENTITY_CERT", "INTERMEDIATE_CERT"), Arrays.asList("CA_CERT", "EXTRA_CA_CERT") ); - when(certificationModelFactory.createCertificationModel(TEST_ENCODED_CSR, TEST_ENCODED_PK, TEST_CA_NAME)) - .thenReturn(testCertificationModel); + when(certificationResponseModelFactory + .provideCertificationModelFromInitialRequest(TEST_ENCODED_CSR, TEST_ENCODED_PK, TEST_CA_NAME)) + .thenReturn(testCertificationResponseModel); // When - ResponseEntity<CertificationModel> responseCertificationModel = + ResponseEntity<CertificationResponseModel> responseCertificationModel = certificationController.signCertificate(TEST_CA_NAME, TEST_ENCODED_CSR, TEST_ENCODED_PK); // Then assertEquals(HttpStatus.OK, responseCertificationModel.getStatusCode()); assertThat(responseCertificationModel.getBody() - ).isEqualToComparingFieldByField(testCertificationModel); + ).isEqualToComparingFieldByField(testCertificationResponseModel); } @@ -102,7 +102,8 @@ class CertificationControllerTest { throws DecryptionException, CmpClientException { // Given String expectedMessage = "Incorrect CSR, decryption failed"; - when(certificationModelFactory.createCertificationModel(TEST_WRONG_ENCODED_CSR, TEST_ENCODED_PK, TEST_CA_NAME)) + when(certificationResponseModelFactory + .provideCertificationModelFromInitialRequest(TEST_WRONG_ENCODED_CSR, TEST_ENCODED_PK, TEST_CA_NAME)) .thenThrow(new CsrDecryptionException(expectedMessage)); // When @@ -122,7 +123,8 @@ class CertificationControllerTest { throws DecryptionException, CmpClientException { // Given String expectedMessage = "Incorrect PEM, decryption failed"; - when(certificationModelFactory.createCertificationModel(TEST_ENCODED_CSR, TEST_WRONG_ENCODED_PK, TEST_CA_NAME)) + when(certificationResponseModelFactory + .provideCertificationModelFromInitialRequest(TEST_ENCODED_CSR, TEST_WRONG_ENCODED_PK, TEST_CA_NAME)) .thenThrow(new KeyDecryptionException(expectedMessage)); // When @@ -142,7 +144,8 @@ class CertificationControllerTest { throws DecryptionException, CmpClientException { // Given String expectedMessage = "No server found for given CA name"; - when(certificationModelFactory.createCertificationModel(TEST_ENCODED_CSR, TEST_ENCODED_PK, TEST_WRONG_CA_NAME)) + when(certificationResponseModelFactory + .provideCertificationModelFromInitialRequest(TEST_ENCODED_CSR, TEST_ENCODED_PK, TEST_WRONG_CA_NAME)) .thenThrow(new Cmpv2ServerNotFoundException(expectedMessage)); // When @@ -159,30 +162,31 @@ class CertificationControllerTest { @Test void shouldUpdateEndpointReturnDataAboutCsrBaseOnEncodedParameters() - throws DecryptionException, CertificateDecryptionException { + throws DecryptionException, CmpClientException, CertificateDecryptionException { // Given - CertificationModel testCertificationModel = new CertificationModel( + CertificationResponseModel testCertificationResponseModel = new CertificationResponseModel( Arrays.asList("ENTITY_CERT", "INTERMEDIATE_CERT"), Arrays.asList("CA_CERT", "EXTRA_CA_CERT") ); - when(certificationModelFactory.createCertificationModel(TEST_CERTIFICATE_UPDATE_MODEL)).thenReturn(testCertificationModel); + when(certificationResponseModelFactory.provideCertificationModelFromUpdateRequest(TEST_CERTIFICATE_UPDATE_MODEL)).thenReturn( + testCertificationResponseModel); // When - ResponseEntity<CertificationModel> responseCertificationModel = + ResponseEntity<CertificationResponseModel> responseCertificationModel = certificationController.updateCertificate(TEST_CA_NAME, TEST_ENCODED_CSR, TEST_ENCODED_PK, TEST_ENCODED_OLD_CERT, TEST_ENCODED_OLD_PK); // Then assertEquals(HttpStatus.OK, responseCertificationModel.getStatusCode()); - assertThat(responseCertificationModel.getBody()).isEqualToComparingFieldByField(testCertificationModel); + assertThat(responseCertificationModel.getBody()).isEqualToComparingFieldByField(testCertificationResponseModel); } @Test void shouldThrowCertificateDecryptionExceptionWhenCreatingPemModelFails() - throws DecryptionException, CertificateDecryptionException { + throws DecryptionException, CertificateDecryptionException, CmpClientException { // Given String expectedMessage = "Incorrect certificate, decryption failed"; - when(certificationModelFactory.createCertificationModel(TEST_CERTIFICATE_UPDATE_MODEL)) + when(certificationResponseModelFactory.provideCertificationModelFromUpdateRequest(TEST_CERTIFICATE_UPDATE_MODEL)) .thenThrow(new CertificateDecryptionException(expectedMessage)); // When diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationData.java b/certService/src/test/java/org/onap/oom/certservice/certification/CertificationData.java index 11e81807..11e81807 100644 --- a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationData.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/CertificationData.java diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/CertificationProviderTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/CertificationProviderTest.java index 54744ba0..192050dc 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/CertificationProviderTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/CertificationProviderTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * OOM Certification Service * ================================================================================ - * Copyright (C) 2020 Nokia. All rights reserved. + * Copyright (C) 2020-2021 Nokia. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,36 +20,47 @@ package org.onap.oom.certservice.certification; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.onap.oom.certservice.certification.TestData.TEST_CMPv2_KEYSTORE; +import static org.onap.oom.certservice.certification.TestData.TEST_CMPv2_TRUSTSTORE; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.List; +import java.util.Objects; import org.apache.commons.io.IOUtils; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMParser; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; -import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.certification.model.CertificationResponseModel; import org.onap.oom.certservice.certification.model.CsrModel; +import org.onap.oom.certservice.certification.model.OldCertificateModel; import org.onap.oom.certservice.cmpv2client.api.CmpClient; import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchProviderException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Collections; -import java.util.Objects; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) class CertificationProviderTest { + private static final int EXPECTED_SIZE_ONE = 1; @Mock private CsrModel csrModel; @Mock @@ -60,23 +71,32 @@ class CertificationProviderTest { private Cmpv2Server testServer; @Mock private CmpClient cmpClient; + @Mock + private OldCertificateModel oldCertificateModel; private CertificationProvider certificationProvider; + private static final String EXPECTED_BEGIN_OF_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"; + private static final String EXPECTED_END_OF_CERTIFICATE = "-----END CERTIFICATE-----\n"; + + static { + Security.addProvider(new BouncyCastleProvider()); + } + @BeforeEach public void init() { certificationProvider = new CertificationProvider(cmpClient); } @Test - void shouldConvertToCertificationModel() + void shouldConvertToCertificationModelForSignCsr() throws CertificateException, NoSuchProviderException, IOException, CmpClientException { // When when( - cmpClient.createCertificate(any(CsrModel.class), any(Cmpv2Server.class)) + cmpClient.executeInitializationRequest(any(CsrModel.class), any(Cmpv2Server.class)) ).thenReturn(createCorrectClientResponse()); - CertificationModel certificationModel = certificationProvider.signCsr(csrModel, server); + CertificationResponseModel certificationModel = certificationProvider.executeInitializationRequest(csrModel, server); // Then InputStream certificate = getClass().getClassLoader().getResourceAsStream("certificateModelChain.first"); @@ -93,34 +113,98 @@ class CertificationProviderTest { assertThat(trustedCertificateModel).isEqualTo(expectedTrustedCertificate); } - @Test - void certificationProviderThrowCmpClientWhenCallingClientFails() + void certificationProviderThrowCmpClientWhenCallingClientFailsForSignCsr() throws CmpClientException { // Given String expectedErrorMessage = "connecting to CMP client failed"; when( - cmpClient.createCertificate(any(CsrModel.class), any(Cmpv2Server.class)) + cmpClient.executeInitializationRequest(any(CsrModel.class), any(Cmpv2Server.class)) ).thenThrow(new CmpClientException(expectedErrorMessage)); // When Exception exception = assertThrows( CmpClientException.class, () -> - certificationProvider.signCsr(testCsrModel, testServer) + certificationProvider.executeInitializationRequest(testCsrModel, testServer) ); // Then assertThat(exception.getMessage()).isEqualTo(expectedErrorMessage); } + @Test + void shouldCorrectConvertToCertificationModelForUpdateRequest() + throws IOException, CertificateException, CmpClientException { + + // When + when( + cmpClient.executeKeyUpdateRequest(any(CsrModel.class), any(Cmpv2Server.class), any(OldCertificateModel.class)) + ).thenReturn(getCMPv2CertificationModel()); + + CertificationResponseModel certificationModel = certificationProvider + .executeKeyUpdateRequest(csrModel, server, oldCertificateModel); + List<String> certificateChain = certificationModel.getCertificateChain(); + List<String> trustedCertificates = certificationModel.getTrustedCertificates(); + + assertThat(certificateChain.size()).isEqualTo(EXPECTED_SIZE_ONE); + assertThat(certificateChain.get(0)).startsWith(EXPECTED_BEGIN_OF_CERTIFICATE); + assertThat(certificateChain.get(0)).endsWith(EXPECTED_END_OF_CERTIFICATE); + + assertThat(trustedCertificates.size()).isEqualTo(EXPECTED_SIZE_ONE); + assertThat(trustedCertificates.get(0)).startsWith(EXPECTED_BEGIN_OF_CERTIFICATE); + assertThat(trustedCertificates.get(0)).endsWith(EXPECTED_END_OF_CERTIFICATE); + } + + @Test + void shouldCorrectConvertToCertificationModelForCertificationRequest() + throws IOException, CertificateException, CmpClientException { + + when( + cmpClient.executeInitializationRequest(any(CsrModel.class), any(Cmpv2Server.class)) + ).thenReturn(getCMPv2CertificationModel()); + + CertificationResponseModel certificationModel = certificationProvider + .executeInitializationRequest(csrModel, server); + List<String> certificateChain = certificationModel.getCertificateChain(); + List<String> trustedCertificates = certificationModel.getTrustedCertificates(); + + assertThat(certificateChain.size()).isEqualTo(EXPECTED_SIZE_ONE); + assertThat(certificateChain.get(0)).startsWith(EXPECTED_BEGIN_OF_CERTIFICATE); + assertThat(certificateChain.get(0)).endsWith(EXPECTED_END_OF_CERTIFICATE); + + assertThat(trustedCertificates.size()).isEqualTo(EXPECTED_SIZE_ONE); + assertThat(trustedCertificates.get(0)).startsWith(EXPECTED_BEGIN_OF_CERTIFICATE); + assertThat(trustedCertificates.get(0)).endsWith(EXPECTED_END_OF_CERTIFICATE); + } + + @Test + void certificationProviderThrowCmpClientWhenCallingClientFailsForUpdateCertificate() + throws CmpClientException { + // Given + String expectedErrorMessage = "Exception occurred while send request to CMPv2 Server"; + + when( + cmpClient.executeKeyUpdateRequest(any(CsrModel.class), any(Cmpv2Server.class), any(OldCertificateModel.class)) + ).thenThrow(new CmpClientException(expectedErrorMessage)); + + // When + Exception exception = assertThrows( + CmpClientException.class, () -> + certificationProvider.executeKeyUpdateRequest(testCsrModel, testServer, oldCertificateModel) + ); + + // Then + assertThat(exception.getMessage()).isEqualTo(expectedErrorMessage); + } + + private Cmpv2CertificationModel createCorrectClientResponse() throws CertificateException, NoSuchProviderException { InputStream certificateChain = getClass().getClassLoader().getResourceAsStream("certificateChain.first"); InputStream trustedCertificate = getClass().getClassLoader().getResourceAsStream("trustedCertificates.first"); - X509Certificate x509Certificate = new CertificateFactoryProvider().generateCertificate(certificateChain); - X509Certificate x509TrustedCertificate = - new CertificateFactoryProvider().generateCertificate(trustedCertificate); + X509Certificate x509Certificate = generateCertificate(certificateChain); + X509Certificate x509TrustedCertificate = generateCertificate(trustedCertificate); return new Cmpv2CertificationModel( Collections.singletonList(x509Certificate), Collections.singletonList(x509TrustedCertificate)); @@ -129,4 +213,24 @@ class CertificationProviderTest { private String removeLineEndings(String string) { return string.replace("\n", "").replace("\r", ""); } + + private Cmpv2CertificationModel getCMPv2CertificationModel() throws IOException, CertificateException { + List<X509Certificate> certificateChain = getX509CertificateFromPem(TEST_CMPv2_KEYSTORE); + List<X509Certificate> trustedCertificates = getX509CertificateFromPem(TEST_CMPv2_TRUSTSTORE); + return new Cmpv2CertificationModel(certificateChain, trustedCertificates); + } + + + private List<X509Certificate> getX509CertificateFromPem(String pemString) throws IOException, CertificateException { + PEMParser pemParser = new PEMParser(new StringReader(pemString)); + X509CertificateHolder certHolder = (X509CertificateHolder) pemParser.readObject(); + X509Certificate x509Certificate = new JcaX509CertificateConverter() + .setProvider(new BouncyCastleProvider()) + .getCertificate(certHolder); + return List.of(x509Certificate); + } + + private X509Certificate generateCertificate(InputStream inStream) throws CertificateException, NoSuchProviderException { + return (X509Certificate) CertificateFactory.getInstance("X.509", "BC").generateCertificate(inStream); + } } diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/CertificationModelFactoryTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/CertificationResponseModelFactoryTest.java index c898b687..205513f5 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/CertificationModelFactoryTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/CertificationResponseModelFactoryTest.java @@ -26,6 +26,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.onap.oom.certservice.certification.CertificationData.CA_CERT; import static org.onap.oom.certservice.certification.CertificationData.ENTITY_CERT; @@ -46,27 +48,29 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.onap.oom.certservice.certification.configuration.Cmpv2ServerProvider; import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.conversion.CsrModelFactory; +import org.onap.oom.certservice.certification.conversion.OldCertificateModelFactory; +import org.onap.oom.certservice.certification.conversion.StringBase64; import org.onap.oom.certservice.certification.exception.CertificateDecryptionException; -import org.onap.oom.certservice.certification.exception.Cmpv2ClientAdapterException; import org.onap.oom.certservice.certification.exception.Cmpv2ServerNotFoundException; import org.onap.oom.certservice.certification.exception.CsrDecryptionException; import org.onap.oom.certservice.certification.exception.DecryptionException; import org.onap.oom.certservice.certification.model.CertificateUpdateModel; import org.onap.oom.certservice.certification.model.CertificateUpdateModel.CertificateUpdateModelBuilder; -import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.certification.model.CertificationResponseModel; import org.onap.oom.certservice.certification.model.CsrModel; -import org.onap.oom.certservice.certification.model.X509CertificateModel; +import org.onap.oom.certservice.certification.model.OldCertificateModel; import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; @ExtendWith(MockitoExtension.class) -class CertificationModelFactoryTest { +class CertificationResponseModelFactoryTest { - private static final String TEST_CA = "testCA"; + private static final String TEST_CA_NAME = "TestCA"; private static final String ENCODED_CSR = getEncodedString(TEST_CSR); private static final String ENCODED_PK = getEncodedString(TEST_PK); private static final String ENCODED_WRONG_CSR = getEncodedString(TEST_WRONG_CSR); private static final String ENCODED_WRONG_PK = getEncodedString(TEST_WRONG_PEM); - private static final String TEST_CA_NAME = "TestCa"; + private static final String TEST_ENCODED_CSR = "encodedCSR"; private static final String TEST_ENCODED_PK = "encodedPK"; private static final String TEST_ENCODED_OLD_PK = "encodedOldPK"; @@ -79,7 +83,7 @@ class CertificationModelFactoryTest { .setCaName(TEST_CA_NAME) .build(); - private CertificationModelFactory certificationModelFactory; + private CertificationResponseModelFactory certificationResponseModelFactory; @Mock private Cmpv2ServerProvider cmpv2ServerProvider; @@ -88,9 +92,11 @@ class CertificationModelFactoryTest { @Mock private CertificationProvider certificationProvider; @Mock - private X509CertificateModelFactory x509CertificateModelFactory; + private OldCertificateModelFactory oldCertificateModelFactory; @Mock private UpdateRequestTypeDetector updateRequestTypeDetector; + @Mock + private OldCertificateModel testOldCertificateModel; private static String getEncodedString(String testCsr) { return Base64.getEncoder().encodeToString(testCsr.getBytes()); @@ -98,14 +104,14 @@ class CertificationModelFactoryTest { @BeforeEach void setUp() { - certificationModelFactory = - new CertificationModelFactory(csrModelFactory, cmpv2ServerProvider, certificationProvider, - x509CertificateModelFactory, updateRequestTypeDetector); + certificationResponseModelFactory = + new CertificationResponseModelFactory(csrModelFactory, cmpv2ServerProvider, certificationProvider, + oldCertificateModelFactory, updateRequestTypeDetector); } @Test void shouldCreateProperCertificationModelWhenGivenProperCsrModelAndCaName() - throws CmpClientException, DecryptionException, Cmpv2ClientAdapterException { + throws CmpClientException, DecryptionException { // Given CsrModel csrModel = mockCsrFactoryModelCreation(); @@ -113,8 +119,9 @@ class CertificationModelFactoryTest { mockCertificateProviderCertificateSigning(csrModel, testServer); // When - CertificationModel certificationModel = - certificationModelFactory.createCertificationModel(ENCODED_CSR, ENCODED_PK, TEST_CA); + CertificationResponseModel certificationModel = + certificationResponseModelFactory + .provideCertificationModelFromInitialRequest(ENCODED_CSR, ENCODED_PK, TEST_CA_NAME); // Then assertEquals(2, certificationModel.getCertificateChain().size()); @@ -140,7 +147,8 @@ class CertificationModelFactoryTest { // When Exception exception = assertThrows( DecryptionException.class, () -> - certificationModelFactory.createCertificationModel(ENCODED_WRONG_CSR, ENCODED_WRONG_PK, TEST_CA) + certificationResponseModelFactory + .provideCertificationModelFromInitialRequest(ENCODED_WRONG_CSR, ENCODED_WRONG_PK, TEST_CA_NAME) ); // Then @@ -154,7 +162,7 @@ class CertificationModelFactoryTest { String expectedMessage = "CA not found"; mockCsrFactoryModelCreation(); when( - cmpv2ServerProvider.getCmpv2Server(TEST_CA) + cmpv2ServerProvider.getCmpv2Server(TEST_CA_NAME) ).thenThrow( new Cmpv2ServerNotFoundException(expectedMessage) ); @@ -162,7 +170,8 @@ class CertificationModelFactoryTest { // When Exception exception = assertThrows( Cmpv2ServerNotFoundException.class, () -> - certificationModelFactory.createCertificationModel(ENCODED_CSR, ENCODED_PK, TEST_CA) + certificationResponseModelFactory + .provideCertificationModelFromInitialRequest(ENCODED_CSR, ENCODED_PK, TEST_CA_NAME) ); // Then @@ -171,13 +180,13 @@ class CertificationModelFactoryTest { @Test void shouldThrowCmpClientExceptionWhenSigningCsrFailed() - throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { + throws DecryptionException, CmpClientException { // Given String expectedMessage = "failed to sign certificate"; CsrModel csrModel = mockCsrFactoryModelCreation(); Cmpv2Server testServer = mockCmpv2ProviderServerSelection(); when( - certificationProvider.signCsr(csrModel, testServer) + certificationProvider.executeInitializationRequest(csrModel, testServer) ).thenThrow( new CmpClientException(expectedMessage) ); @@ -185,7 +194,8 @@ class CertificationModelFactoryTest { // When Exception exception = assertThrows( CmpClientException.class, () -> - certificationModelFactory.createCertificationModel(ENCODED_CSR, ENCODED_PK, TEST_CA) + certificationResponseModelFactory + .provideCertificationModelFromInitialRequest(ENCODED_CSR, ENCODED_PK, TEST_CA_NAME) ); // Then @@ -193,58 +203,118 @@ class CertificationModelFactoryTest { } @Test - void shouldPerformKurWhenCsrAndOldCertDataMatch() throws CertificateDecryptionException, DecryptionException { - //given - mockCsrFactoryModelCreation(); + void shouldPerformKurWhenCsrAndOldCertDataMatch() + throws CertificateDecryptionException, DecryptionException, CmpClientException { + // Given + CsrModel csrModel = mockCsrFactoryModelCreation(); + Cmpv2Server testServer = mockCmpv2ProviderServerSelection(); + mockCertificateProviderCertificateUpdate(csrModel, testServer); mockCertificateFactoryModelCreation(); when(updateRequestTypeDetector.isKur(any(), any())).thenReturn(true); - //when, then + when(oldCertificateModelFactory.createCertificateModel(any(), any())).thenReturn(testOldCertificateModel); + + // When + CertificationResponseModel certificationModel = certificationResponseModelFactory + .provideCertificationModelFromUpdateRequest(TEST_CERTIFICATE_UPDATE_MODEL); + + // Then + assertEquals(2, certificationModel.getCertificateChain().size()); + assertThat(certificationModel.getCertificateChain()).contains(INTERMEDIATE_CERT, ENTITY_CERT); + assertEquals(2, certificationModel.getTrustedCertificates().size()); + assertThat(certificationModel.getTrustedCertificates()).contains(CA_CERT, EXTRA_CA_CERT); + + verify(certificationProvider, times(1)) + .executeKeyUpdateRequest(csrModel, testServer, testOldCertificateModel); + } + + @Test + void shouldThrowCmpClientExceptionWhenUpdateRequestFailed() + throws DecryptionException, CmpClientException, CertificateDecryptionException { + + // Given + String expectedMessage = "Exception occurred while send request to CMPv2 Server"; + CsrModel csrModel = mockCsrFactoryModelCreation(); + Cmpv2Server testServer = mockCmpv2ProviderServerSelection(); + mockCertificateFactoryModelCreation(); + + when(oldCertificateModelFactory.createCertificateModel(any(), any())).thenReturn(testOldCertificateModel); + when(certificationProvider.executeKeyUpdateRequest(csrModel, testServer, testOldCertificateModel)) + .thenThrow(new CmpClientException(expectedMessage)); + when(updateRequestTypeDetector.isKur(any(), any())).thenReturn(true); + + // When Exception exception = assertThrows( - UnsupportedOperationException.class, () -> - certificationModelFactory.createCertificationModel(TEST_CERTIFICATE_UPDATE_MODEL) + CmpClientException.class, () -> + certificationResponseModelFactory.provideCertificationModelFromUpdateRequest(TEST_CERTIFICATE_UPDATE_MODEL) ); - assertEquals(exception.getMessage(), "TODO: implement KUR in separate MR"); + + // Then + assertTrue(exception.getMessage().contains(expectedMessage)); } @Test - void shouldPerformCrWhenCsrAndOldCertDataMatch() throws CertificateDecryptionException, DecryptionException { - //given - mockCsrFactoryModelCreation(); + void shouldPerformCrWhenCsrAndOldCertDataDontMatch() + throws CertificateDecryptionException, DecryptionException, CmpClientException { + // Given + CsrModel csrModel = mockCsrFactoryModelCreation(); + Cmpv2Server testServer = mockCmpv2ProviderServerSelection(); + mockCertificateProviderCertificationRequest(csrModel, testServer); mockCertificateFactoryModelCreation(); + // When when(updateRequestTypeDetector.isKur(any(), any())).thenReturn(false); - //when, then - Exception exception = assertThrows( - UnsupportedOperationException.class, () -> - certificationModelFactory.createCertificationModel(TEST_CERTIFICATE_UPDATE_MODEL) - ); - assertEquals(exception.getMessage(), "TODO: implement CR in separate MR"); + CertificationResponseModel certificationModel = certificationResponseModelFactory + .provideCertificationModelFromUpdateRequest(TEST_CERTIFICATE_UPDATE_MODEL); + // Then + assertEquals(2, certificationModel.getCertificateChain().size()); + assertThat(certificationModel.getCertificateChain()).contains(INTERMEDIATE_CERT, ENTITY_CERT); + assertEquals(2, certificationModel.getTrustedCertificates().size()); + assertThat(certificationModel.getTrustedCertificates()).contains(CA_CERT, EXTRA_CA_CERT); + + verify(certificationProvider, times(1)) + .executeCertificationRequest(csrModel, testServer); } @Test void shouldThrowCertificateDecryptionExceptionWhenOldCertificateInvalid() throws CertificateDecryptionException { //given - when(x509CertificateModelFactory.createCertificateModel(any())) + when(oldCertificateModelFactory.createCertificateModel(any(), any())) .thenThrow(new CertificateDecryptionException("Incorrect certificate, decryption failed")); //when, then assertThrows( CertificateDecryptionException.class, () -> - certificationModelFactory.createCertificationModel(TEST_CERTIFICATE_UPDATE_MODEL) + certificationResponseModelFactory.provideCertificationModelFromUpdateRequest(TEST_CERTIFICATE_UPDATE_MODEL) ); } + private void mockCertificateProviderCertificateUpdate(CsrModel csrModel, Cmpv2Server testServer) + throws CmpClientException { + CertificationResponseModel expectedCertificationModel = getCertificationModel(); + when( + certificationProvider.executeKeyUpdateRequest(csrModel, testServer, testOldCertificateModel) + ).thenReturn(expectedCertificationModel); + } + + private void mockCertificateProviderCertificationRequest(CsrModel csrModel, Cmpv2Server testServer) + throws CmpClientException { + CertificationResponseModel expectedCertificationModel = getCertificationModel(); + when( + certificationProvider.executeCertificationRequest(csrModel, testServer) + ).thenReturn(expectedCertificationModel); + } + private void mockCertificateProviderCertificateSigning(CsrModel csrModel, Cmpv2Server testServer) - throws CmpClientException, Cmpv2ClientAdapterException { - CertificationModel expectedCertificationModel = getCertificationModel(); + throws CmpClientException { + CertificationResponseModel expectedCertificationModel = getCertificationModel(); when( - certificationProvider.signCsr(csrModel, testServer) + certificationProvider.executeInitializationRequest(csrModel, testServer) ).thenReturn(expectedCertificationModel); } private Cmpv2Server mockCmpv2ProviderServerSelection() { Cmpv2Server testServer = getCmpv2Server(); when( - cmpv2ServerProvider.getCmpv2Server(TEST_CA) + cmpv2ServerProvider.getCmpv2Server(TEST_CA_NAME) ).thenReturn(testServer); return testServer; } @@ -256,10 +326,10 @@ class CertificationModelFactoryTest { return csrModel; } - private X509CertificateModel mockCertificateFactoryModelCreation() + private OldCertificateModel mockCertificateFactoryModelCreation() throws CertificateDecryptionException { - final X509CertificateModel certificateModel = mock(X509CertificateModel.class); - when(x509CertificateModelFactory.createCertificateModel(any())).thenReturn(certificateModel); + final OldCertificateModel certificateModel = mock(OldCertificateModel.class); + when(oldCertificateModelFactory.createCertificateModel(any(), any())).thenReturn(certificateModel); return certificateModel; } @@ -271,11 +341,10 @@ class CertificationModelFactoryTest { return mock(CsrModel.class); } - private CertificationModel getCertificationModel() { + private CertificationResponseModel getCertificationModel() { List<String> testTrustedCertificates = Arrays.asList(CA_CERT, EXTRA_CA_CERT); List<String> testCertificationChain = Arrays.asList(INTERMEDIATE_CERT, ENTITY_CERT); - return new CertificationModel(testCertificationChain, testTrustedCertificates); + return new CertificationResponseModel(testCertificationChain, testTrustedCertificates); } - } diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/TestData.java b/certService/src/test/java/org/onap/oom/certservice/certification/TestData.java index 92b239f1..3c47d866 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/TestData.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/TestData.java @@ -99,4 +99,61 @@ public final class TestData { + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh" + "-----END WRONG REQUEST-----"; + + public static final String TEST_CMPv2_KEYSTORE = "-----BEGIN CERTIFICATE-----\n" + + "MIIEfTCCAuWgAwIBAgIUdF/Efkrll/wuwfT2w+RO9cJrLvQwDQYJKoZIhvcNAQEL\n" + + "BQAwUzEVMBMGCgmSJomT8ixkAQEMBTEyMzQ1MRUwEwYDVQQDDAxNYW5hZ2VtZW50\n" + + "Q0ExIzAhBgNVBAoMGkVKQkNBIENvbnRhaW5lciBRdWlja3N0YXJ0MB4XDTIxMDcw\n" + + "MTE0MjUxMloXDTIzMDcwMTE0MjUxMVowdzERMA8GA1UEAwwIb25hcC5vcmcxGTAX\n" + + "BgNVBAsMEExpbnV4LUZvdW5kYXRpb24xDTALBgNVBAoMBE9OQVAxFjAUBgNVBAcM\n" + + "DVNhbi1GcmFuY2lzY28xEzARBgNVBAgMCkNhbGlmb3JuaWExCzAJBgNVBAYTAlVT\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzEAteHOLPXl93XwT9yDa\n" + + "3SS1nOV1KN+wZApOqvzbA7NBf8Pw/72i6LXvAHABfzUWkUQnbWw9WygPiEbWfaGO\n" + + "AArlcVTtXnY5RkfOpt5UXBokZwn1PaT3a1hXrFHA2W2jwD7q2Ft3gRNNFsxenJYi\n" + + "BcsnJOBkS3hc+zAG7mYw5gYdnPX69D+/+4G0N1k1bBA5rsaK7F3h54NJfPxILpJB\n" + + "0yuVBE0QBEaHVoqDyq6AwmiHpk2Nt5h4TMDiINwwkoxvNG+ZCaM2CSFbmUyq3j1c\n" + + "xZ/ZrhLIZ1rRlMTPz+lA1wo1yBB2AoDtoPsAlQG5nIWfr1d5ToUtLOxZ+dVTQkJi\n" + + "VQIDAQABo4GkMIGhMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU0pApkFDmdpd/\n" + + "O4a/byDxTEP2UvAwGAYDVR0RBBEwD4INdGVzdC5vbmFwLm9yZzAnBgNVHSUEIDAe\n" + + "BggrBgEFBQcDAgYIKwYBBQUHAwQGCCsGAQUFBwMBMB0GA1UdDgQWBBS3Wd6mIs8L\n" + + "ZxAfYyvM/U2g/XM2wjAOBgNVHQ8BAf8EBAMCBeAwDQYJKoZIhvcNAQELBQADggGB\n" + + "AF9ecmK2jpi4u8NERcx/HGXGxZDgj8EpRMxzHAPMa8gJRwm87O4tn4QZHFSnDYdl\n" + + "ZmDWhA1iEvOOrTNDimRslAOoOE3bRAiA5c3cYVhancZq0OqS8dUOyOxSwLoXtnFC\n" + + "RGnHMmABq3OpdWpeRTv3iLzPDeybP+hJn3WrlX9v4kjwgO5mbwQTG+MCzTWgNsyy\n" + + "xeEF0pH6JYDyIoRNWwrrRG7zWzjIaFuMtOfbN1lVaaycMsRw+IxvojsDmXK2PWOA\n" + + "HRu5k2xpQfHF/waN4F0vzKxmHyCVnwbwx6by6G2FJo8CYQeDwgyRARm3xywu1Wwt\n" + + "CIbRhIekMFY7RLPs5vkTPxs65numYZlbI+z+EdYofQBbJFeyqpzkoIQqWyfkwtki\n" + + "x7sJ9B6sUPIibxQnMI+tdX+wz5p5Ift+nnSUbx8N+FVvc9kEbvvPpzJRpAyQBVIq\n" + + "CIvPjAmyZNIztpxLi0bh7voZqH5ZwHdWWEaDrwg5cMjFZMRUGRPUQ8NN04KGiAww\n" + + "hQ==\n" + + "-----END CERTIFICATE-----"; + + public static final String TEST_CMPv2_TRUSTSTORE = "-----BEGIN CERTIFICATE-----\n" + + "MIIElzCCAv+gAwIBAgIUcwn218DR9QI1ORrGSb2exaf2tp0wDQYJKoZIhvcNAQEL\n" + + "BQAwUzEVMBMGCgmSJomT8ixkAQEMBTEyMzQ1MRUwEwYDVQQDDAxNYW5hZ2VtZW50\n" + + "Q0ExIzAhBgNVBAoMGkVKQkNBIENvbnRhaW5lciBRdWlja3N0YXJ0MB4XDTIxMDcw\n" + + "MTEzNTIwMloXDTMxMDcwMTEzNTIwMVowUzEVMBMGCgmSJomT8ixkAQEMBTEyMzQ1\n" + + "MRUwEwYDVQQDDAxNYW5hZ2VtZW50Q0ExIzAhBgNVBAoMGkVKQkNBIENvbnRhaW5l\n" + + "ciBRdWlja3N0YXJ0MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEApU2B\n" + + "yG6Y5D72dC7jL7kW7HxMDL93sKGo/9GriPL/re+ogipg9SezZoX0UbYH6ZCuPlPn\n" + + "GKXaLDdrwX/oAaYnq1h4hA75Fy2P7Im3rcuw01F7kBk3bSbFSU0RLbr0POuP+rNr\n" + + "IXNpFS1tonTpLgS0l7vfMkAfbBBlFLuSZQUD6oq0OHB60uBe8vOF7olq6bewduUz\n" + + "jNgqjoUz5cR9cuWCXMZUA71+ZEzSNDJtDeFpkd00wklB9Q86JQ3/5poe4ALKuyRj\n" + + "+6ltNdRtybHY+gT9iltDqJ7d9JWwG5EIBjYWlqLAHV1YP3XnonLiyCfArvnp1fLZ\n" + + "vOdyxk0cA21EFF6b6MUGI3bMJPdwYjWEKkVFETqsbpxRyFNjqJ1EUibLttRnOKeS\n" + + "COw8KdP+1QTvygA7lb75lCnVpn8JKDy2FbpuoEnSkA6o/25tlM5BjzFrKeCCdO8t\n" + + "lcUFlQsxniSXaZF4i46U1BI1x5onY82hpLB3kErPCCA7Y4wu6fpmuOLxvvR3AgMB\n" + + "AAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU0pApkFDmdpd/O4a/\n" + + "byDxTEP2UvAwHQYDVR0OBBYEFNKQKZBQ5naXfzuGv28g8UxD9lLwMA4GA1UdDwEB\n" + + "/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAYEAf6cQKAUp1oz/wNu+wGr0ihCtYoTv\n" + + "0E8Sj6NaVg25iZWwE+eH9iJ5tP84ofVVBSKbnbcWcKOiBWdwMHK926yWhDq1Okj3\n" + + "cKn4PEo/Tp7DWgSxaBFWvafIMYgD08AeCSBykdwodNxhPWIMIe0Wv+timjacYUFV\n" + + "Aq8IjFfEwpznlbJWNoctne5YFcbGbo+Z3cMaFG0eWtjpVg5pF3p+D35FBCeNzIx7\n" + + "PjI4blyKAAIVBppYY7mTC9iEvu1Djt9653LOj2ZalC8mj6ZnvSxEhcQ3PJle8VvT\n" + + "jq1pCYNegPATlT3eRKXlQOUQQtkw2NK9jQCCbwHnQHreL76iGhoIyFfR8P/EA2KU\n" + + "CCMFg1yrToWJxDhkuBHu7vqbceC4YNGU1wl7nGJA18PDpglm0WI1mWzh7s+oeNNr\n" + + "vvPaTimegOkO/u2vbl9McNdSu5Chj+gUpz6w6a3DiBeROYAVQaw44LncJtaGKojU\n" + + "Q81F/bSyUp6jkdo5Dx2pFQDLDdhmMF4txiqG\n" + + "-----END CERTIFICATE-----"; + } diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/TestUtils.java b/certService/src/test/java/org/onap/oom/certservice/certification/TestUtils.java index 0dceda19..0284b0af 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/TestUtils.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/TestUtils.java @@ -23,6 +23,8 @@ package org.onap.oom.certservice.certification; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemWriter; +import org.onap.oom.certservice.certification.conversion.CsrModelFactory; +import org.onap.oom.certservice.certification.conversion.StringBase64; import org.onap.oom.certservice.certification.exception.DecryptionException; import org.onap.oom.certservice.certification.exception.KeyDecryptionException; import org.onap.oom.certservice.certification.model.CsrModel; diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/CsrModelFactoryTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/CsrModelFactoryTest.java index eb6a0550..26624867 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/CsrModelFactoryTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/CsrModelFactoryTest.java @@ -18,23 +18,24 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.onap.oom.certservice.certification.TestData.TEST_CSR; +import static org.onap.oom.certservice.certification.TestData.TEST_PK; +import static org.onap.oom.certservice.certification.TestData.TEST_WRONG_CSR; +import static org.onap.oom.certservice.certification.TestData.TEST_WRONG_PEM; import org.bouncycastle.util.encoders.Base64; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.onap.oom.certservice.certification.TestData; import org.onap.oom.certservice.certification.exception.CsrDecryptionException; import org.onap.oom.certservice.certification.exception.DecryptionException; import org.onap.oom.certservice.certification.exception.KeyDecryptionException; import org.onap.oom.certservice.certification.model.CsrModel; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.onap.oom.certservice.certification.TestData.TEST_CSR; -import static org.onap.oom.certservice.certification.TestData.TEST_PK; -import static org.onap.oom.certservice.certification.TestData.TEST_WRONG_CSR; -import static org.onap.oom.certservice.certification.TestData.TEST_WRONG_PEM; - class CsrModelFactoryTest { diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/X509CertificateModelFactoryTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/OldCertificateModelFactoryTest.java index bad4887b..4adf0355 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/X509CertificateModelFactoryTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/OldCertificateModelFactoryTest.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -26,10 +26,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.GeneralName; import org.junit.jupiter.api.Test; +import org.onap.oom.certservice.certification.X509CertificateParser; import org.onap.oom.certservice.certification.exception.CertificateDecryptionException; -import org.onap.oom.certservice.certification.model.X509CertificateModel; +import org.onap.oom.certservice.certification.model.OldCertificateModel; -class X509CertificateModelFactoryTest { +class OldCertificateModelFactoryTest { private static final String ENCODED_CERTIFICATE_STRING = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVpekNDQXZPZ0F3SUJBZ0lVR0VwMkdaNlk4" @@ -123,11 +124,44 @@ class X509CertificateModelFactoryTest { + "bE8wdHErc2lJK1Y0T3lORkhadnJHQUNaUTNxYUFUZlozYlN3RVcKYkg1QjRlbHRodz09Ci0tLS0t" + "RU5EIENFUlRJRklDQVRFLS0tLS0K"; + private static final String ENCODED_PRIVATE_KEY = + "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQk" + + "tnd2dnU2tBZ0VBQW9JQkFRRFNOS0pCUU5XRmF0ajUKUmRhTmQyMGdnTnBOVUVaYzgxU1Y1d0hLeH" + + "EwUy9rT0llTG8rekI5c3lkUUJLWm9JRXJPL3JIekwzb0VCNW5YNQp4NVBkeTViYUdYTzRQZDVCUS" + + "trSXRHckFnNzVrRldmT3VHNU9GWUxpWldMUEcra3FBRXJKNTdzQlB5TzNKNjVxCkEzN0gxNnBiZV" + + "hRL2VzR2RNaVZsenM4dE9UOEtaT1lDQUpGQXg1ZEk4OEowaEt4ZThONFdrZEJLSStXVndKMUsKR0" + + "5pZmgwc2Jjam9rOG1Gbll4Nzcwd3BuZU5nbkZUbU9MWXFIUTRuSklUODdza1BYSUt1RHNMRUJDL0" + + "1kVGQ0QwpPTTZJekZYZmQxNzNDc1p5UnR3V0F2ZXNDcWJGYkVhcDBiWHlCRFN1R0w3NlhGdzRTdj" + + "ZiZkoyano2SjIyRU9SCmVPOGpVdWhKQWdNQkFBRUNnZ0VBUWJyZHBjUHRRSnZwbndEY2x6M3A3TW" + + "o5K2tFSXo1WHpORENaR2R4SVVIRWIKa3ZnVlhQK2RML3BvaGJpSmhzNjZVRXhTZGJsczQ3ZzUyZE" + + "l6aFo1YzNIUXJBRWl3VC80NVIxU0xNUW5CSmpDZgpWai9MbGpVWnlVdGt1MWlCNzNWSjdacTltaV" + + "V4T050NnFZSFFTaE5CSFB0OGcwRVNlK0lyV1l0eXN6UjhadllXCjlqWm9xb0pOTW5ySVkyNmdtdF" + + "RCRURpTmVmaEhBMGVoVHkwYzNBQ1lDTUY3aWlNenplMWhkUjZvTDhuTEZscmQKVGJZRGdCUzBueE" + + "pvRVpxQnZBZWViZFVBaXc1UCtqZ1NXcXhnUkhpWGk2Rk0xWXVnMGF5Mm9GNEl1alV0ek5kNwplbn" + + "NqeTVTTGFGcVp5dy81bkdlWDJMTXYvbFovQUtWYlZ6NnNBa3RVdFFLQmdRRHBBT3BBUVorNWRheG" + + "xyQk5oClFoYy9ndnRPekJpRTA0YU5EdDVLMllEVU80dHdFRmYxTVdXSkNrV3Z1czNOSUphdkJ1K2" + + "5GYzdEREphUEFxbk4KZnQrUGw3NTJ4UUlJRk1GdUt5QTdKL1hSZzFjVUIzNEFrZWtZeTZvRlYwa2" + + "FlWmZvYXBRbGdDWnFWVkd5L2FCdAprSHBndDJnckpZZG82OE11bFQ0ZWplbGE4d0tCZ1FEbTg3UW" + + "E4YzFYRTNuTGFQcGJIeTU5N0N5S0ZKTzBRdC9tCm1RT1FNaEJCOTJGU0JpRE05ZHFkbUU2d3JVU2" + + "NFYVo3aDlaZ1kwQUdxVVFobzE3d3oyL1BxaGhaUFRiOU0rVTgKWUVaWTdnWnNoYkJ1MDgvTkJLTD" + + "NGTitGd216VG8xN1d1SlNyQWFWV3dra1RMOWVSbkI2cUFTeHBMaDFKQ0J4cQpQSE9Kd1FmRzB3S0" + + "JnUUNSTHlUSGpSeDliemxRMFB2eWFrQWFMdjl3aGZQeEwreHpFSVNxbHdTVE9kY1VxTnBsCnliVy" + + "t3a3ZSeDlCY3RLV3Z3ZDZxZWdndnVUUkhRQjJXRWl3elNSWkE0MWowdUJvZkQzZ3g1Q0Jqd0RjT0" + + "grei8KWmV1Y3E2cnhVUVlZSFJQdW1ocGRrNUJjU1hWeTFsNlVacVlhaGEyKzFNK2ZMT2lkcWhqZT" + + "ZRWXl5UUtCZ1FDbwpTclhYWEpRUSs3UW9zVnFkdzk4UkMyUjVTZjFId2VOK0djb3E3UkJEd1l3OV" + + "JSSHB5TTJCUVZjMkQweUxuYUQvCkswRGdBL0xINTlncDJ1NTM4L0M2Rm15ZnVxZXpZbm1Nd1dzQn" + + "FwRXJ5MCtCc3Y4ZG1sOVdSUE9NZU56c2E0UFUKVzdTWjJCMHZWMndBZTBCT2JzRTVpSmxnRzZaam" + + "JYR25TRjI0NTl4TzJRS0JnRER1cXJBcThQMXpXU28wcWZ0QgpkTS9Xc3p6U3VZRHdjemhvajNKek" + + "5VK3lvQ3g4ejNzY0NML240eXFUT1RiWVhLTXFHbUVrSW01eXJ1SWlJeHBRCmNJM1pDUlVZbHZDY0" + + "FaeCtiVU1QSXNkek1TeGJMaHNqSU5Oc3F4dDJlMlQvd2dJWXpWenVERExpZ1drN1lDZkEKNDJ4YX" + + "VldHQ0M21qM25wYUFvcURIVG92Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"; + + private static final String SUBJECT = "CN=onap.org,OU=Linux-Foundation,O=ONAP,L=San-Francisco,ST=California,C=US"; private static final GeneralName GENERAL_NAME = new GeneralName(GeneralName.dNSName, "test.onap.org"); - private final X509CertificateModelFactory factory = - new X509CertificateModelFactory(new PemStringToCertificateConverter(), new X509CertificateParser()); + private final OldCertificateModelFactory factory = + new OldCertificateModelFactory(new PemStringToCertificateConverter(), new X509CertificateParser()); @Test void shouldCorrectlyParseX509CertificateFromCertificate() @@ -135,11 +169,12 @@ class X509CertificateModelFactoryTest { //given StringBase64 base64EncodedCertificate = new StringBase64(ENCODED_CERTIFICATE_STRING); //when - final X509CertificateModel certificateModel = factory.createCertificateModel(base64EncodedCertificate); + final OldCertificateModel certificateModel = factory.createCertificateModel(base64EncodedCertificate, ENCODED_PRIVATE_KEY); //then - assertThat(certificateModel.getCertificate()).isNotNull(); + assertThat(certificateModel.getOldCertificate()).isNotNull(); assertThat(certificateModel.getSubjectData()).isEqualTo(new X500Name(SUBJECT)); assertThat(certificateModel.getSans()).containsExactly(GENERAL_NAME); + assertThat(certificateModel.getOldPrivateKey()).isNotNull(); } @Test @@ -148,11 +183,12 @@ class X509CertificateModelFactoryTest { //given StringBase64 base64EncodedCertificate = new StringBase64(ENCODED_CERTIFICATE_CHAIN_STRING); //when - final X509CertificateModel certificateModel = factory.createCertificateModel(base64EncodedCertificate); + final OldCertificateModel certificateModel = factory.createCertificateModel(base64EncodedCertificate, ENCODED_PRIVATE_KEY); //then - assertThat(certificateModel.getCertificate()).isNotNull(); + assertThat(certificateModel.getOldCertificate()).isNotNull(); assertThat(certificateModel.getSubjectData()).isEqualTo(new X500Name(SUBJECT)); assertThat(certificateModel.getSans()).containsExactly(GENERAL_NAME); + assertThat(certificateModel.getOldPrivateKey()).isNotNull(); } @Test @@ -160,7 +196,7 @@ class X509CertificateModelFactoryTest { //given StringBase64 base64EncodedCertificate = new StringBase64(""); //when, then - assertThatThrownBy(() -> factory.createCertificateModel(base64EncodedCertificate)) + assertThatThrownBy(() -> factory.createCertificateModel(base64EncodedCertificate, ENCODED_PRIVATE_KEY)) .isInstanceOf(CertificateDecryptionException.class); } } diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/PemObjectFactoryTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/PemObjectFactoryTest.java index 68cfa1a1..2df9490e 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/PemObjectFactoryTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/PemObjectFactoryTest.java @@ -18,12 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; - -import org.bouncycastle.util.io.pem.PemObject; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.onap.oom.certservice.certification.exception.DecryptionException; +package org.onap.oom.certservice.certification.conversion; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -32,6 +27,11 @@ import static org.onap.oom.certservice.certification.TestData.TEST_PEM; import static org.onap.oom.certservice.certification.TestData.TEST_WRONG_PEM; import static org.onap.oom.certservice.certification.TestUtils.pemObjectToString; +import org.bouncycastle.util.io.pem.PemObject; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.oom.certservice.certification.exception.DecryptionException; + class PemObjectFactoryTest { diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/PemStringToCertificateConverterTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/PemStringToCertificateConverterTest.java index ecdb1a2e..708d59ab 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/PemStringToCertificateConverterTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/PemStringToCertificateConverterTest.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/RsaContentSignerBuilderTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/RsaContentSignerBuilderTest.java index eebe1815..2694d514 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/RsaContentSignerBuilderTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/RsaContentSignerBuilderTest.java @@ -18,23 +18,21 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; +import static org.assertj.core.api.Assertions.assertThat; +import static org.onap.oom.certservice.certification.TestUtils.createCsrModel; + +import java.io.IOException; +import java.security.PrivateKey; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.onap.oom.certservice.certification.RsaContentSignerBuilder; import org.onap.oom.certservice.certification.exception.DecryptionException; import org.onap.oom.certservice.certification.model.CsrModel; -import java.io.IOException; -import java.security.PrivateKey; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.onap.oom.certservice.certification.TestUtils.createCsrModel; - class RsaContentSignerBuilderTest { private RsaContentSignerBuilder rsaContentSignerBuilder; diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/X509CertificateBuilderTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/X509CertificateBuilderTest.java index 52ed99e7..bf9d1cfb 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/X509CertificateBuilderTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/conversion/X509CertificateBuilderTest.java @@ -18,8 +18,13 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.certservice.certification; +package org.onap.oom.certservice.certification.conversion; +import static org.assertj.core.api.Assertions.assertThat; +import static org.onap.oom.certservice.certification.TestUtils.createCsrModel; + +import java.io.IOException; +import java.security.PrivateKey; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.operator.ContentSigner; @@ -30,12 +35,6 @@ import org.junit.jupiter.api.Test; import org.onap.oom.certservice.certification.exception.DecryptionException; import org.onap.oom.certservice.certification.model.CsrModel; -import java.io.IOException; -import java.security.PrivateKey; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.onap.oom.certservice.certification.TestUtils.createCsrModel; - class X509CertificateBuilderTest { private X509CertificateBuilder certificateBuilder; diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/model/CsrModelTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/model/CsrModelTest.java index 84c1cca0..72837e56 100644 --- a/certService/src/test/java/org/onap/oom/certservice/certification/model/CsrModelTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/certification/model/CsrModelTest.java @@ -27,8 +27,8 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.bouncycastle.util.io.pem.PemObject; import org.junit.jupiter.api.Test; -import org.onap.oom.certservice.certification.Pkcs10CertificationRequestFactory; -import org.onap.oom.certservice.certification.PemObjectFactory; +import org.onap.oom.certservice.certification.conversion.Pkcs10CertificationRequestFactory; +import org.onap.oom.certservice.certification.conversion.PemObjectFactory; import org.onap.oom.certservice.certification.TestData; import org.onap.oom.certservice.certification.exception.CsrDecryptionException; import org.onap.oom.certservice.certification.exception.DecryptionException; diff --git a/certService/src/test/java/org/onap/oom/certservice/cmpv2client/ClientTestData.java b/certService/src/test/java/org/onap/oom/certservice/cmpv2client/ClientTestData.java new file mode 100644 index 00000000..845361ef --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/cmpv2client/ClientTestData.java @@ -0,0 +1,74 @@ +/* + * ============LICENSE_START======================================================= + * Cert Service + * ================================================================================ + * Copyright (C) 2021 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client; + +import org.onap.oom.certservice.certification.conversion.PemStringToCertificateConverter; +import org.onap.oom.certservice.certification.conversion.StringBase64; +import org.onap.oom.certservice.certification.conversion.OldCertificateModelFactory; +import org.onap.oom.certservice.certification.X509CertificateParser; +import org.onap.oom.certservice.certification.exception.CertificateDecryptionException; +import org.onap.oom.certservice.certification.model.OldCertificateModel; + +public final class ClientTestData { + + static final String KUR_CORRECT_SERVER_RESPONSE_ENCODED = "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"; + static final String CR_CORRECT_SERVER_RESPONSE_ENCODED = "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"; + + private static final String WRONG_OLD_CERT = "wrong old cert"; + private static final String WRONG_OLD_PRIVATE_KEY = "wrong old private key"; + + private static final String TEST_ENCODED_PRIVATE_KEY_IN_PKCS8 = "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRRFNOS0pCUU5XRmF0ajUKUmRhTmQyMGdnTnBOVUVaYzgxU1Y1d0hLeHEwUy9rT0llTG8rekI5c3lkUUJLWm9JRXJPL3JIekwzb0VCNW5YNQp4NVBkeTViYUdYTzRQZDVCUStrSXRHckFnNzVrRldmT3VHNU9GWUxpWldMUEcra3FBRXJKNTdzQlB5TzNKNjVxCkEzN0gxNnBiZVhRL2VzR2RNaVZsenM4dE9UOEtaT1lDQUpGQXg1ZEk4OEowaEt4ZThONFdrZEJLSStXVndKMUsKR05pZmgwc2Jjam9rOG1Gbll4Nzcwd3BuZU5nbkZUbU9MWXFIUTRuSklUODdza1BYSUt1RHNMRUJDL01kVGQ0QwpPTTZJekZYZmQxNzNDc1p5UnR3V0F2ZXNDcWJGYkVhcDBiWHlCRFN1R0w3NlhGdzRTdjZiZkoyano2SjIyRU9SCmVPOGpVdWhKQWdNQkFBRUNnZ0VBUWJyZHBjUHRRSnZwbndEY2x6M3A3TWo5K2tFSXo1WHpORENaR2R4SVVIRWIKa3ZnVlhQK2RML3BvaGJpSmhzNjZVRXhTZGJsczQ3ZzUyZEl6aFo1YzNIUXJBRWl3VC80NVIxU0xNUW5CSmpDZgpWai9MbGpVWnlVdGt1MWlCNzNWSjdacTltaVV4T050NnFZSFFTaE5CSFB0OGcwRVNlK0lyV1l0eXN6UjhadllXCjlqWm9xb0pOTW5ySVkyNmdtdFRCRURpTmVmaEhBMGVoVHkwYzNBQ1lDTUY3aWlNenplMWhkUjZvTDhuTEZscmQKVGJZRGdCUzBueEpvRVpxQnZBZWViZFVBaXc1UCtqZ1NXcXhnUkhpWGk2Rk0xWXVnMGF5Mm9GNEl1alV0ek5kNwplbnNqeTVTTGFGcVp5dy81bkdlWDJMTXYvbFovQUtWYlZ6NnNBa3RVdFFLQmdRRHBBT3BBUVorNWRheGxyQk5oClFoYy9ndnRPekJpRTA0YU5EdDVLMllEVU80dHdFRmYxTVdXSkNrV3Z1czNOSUphdkJ1K25GYzdEREphUEFxbk4KZnQrUGw3NTJ4UUlJRk1GdUt5QTdKL1hSZzFjVUIzNEFrZWtZeTZvRlYwa2FlWmZvYXBRbGdDWnFWVkd5L2FCdAprSHBndDJnckpZZG82OE11bFQ0ZWplbGE4d0tCZ1FEbTg3UWE4YzFYRTNuTGFQcGJIeTU5N0N5S0ZKTzBRdC9tCm1RT1FNaEJCOTJGU0JpRE05ZHFkbUU2d3JVU2NFYVo3aDlaZ1kwQUdxVVFobzE3d3oyL1BxaGhaUFRiOU0rVTgKWUVaWTdnWnNoYkJ1MDgvTkJLTDNGTitGd216VG8xN1d1SlNyQWFWV3dra1RMOWVSbkI2cUFTeHBMaDFKQ0J4cQpQSE9Kd1FmRzB3S0JnUUNSTHlUSGpSeDliemxRMFB2eWFrQWFMdjl3aGZQeEwreHpFSVNxbHdTVE9kY1VxTnBsCnliVyt3a3ZSeDlCY3RLV3Z3ZDZxZWdndnVUUkhRQjJXRWl3elNSWkE0MWowdUJvZkQzZ3g1Q0Jqd0RjT0grei8KWmV1Y3E2cnhVUVlZSFJQdW1ocGRrNUJjU1hWeTFsNlVacVlhaGEyKzFNK2ZMT2lkcWhqZTZRWXl5UUtCZ1FDbwpTclhYWEpRUSs3UW9zVnFkdzk4UkMyUjVTZjFId2VOK0djb3E3UkJEd1l3OVJSSHB5TTJCUVZjMkQweUxuYUQvCkswRGdBL0xINTlncDJ1NTM4L0M2Rm15ZnVxZXpZbm1Nd1dzQnFwRXJ5MCtCc3Y4ZG1sOVdSUE9NZU56c2E0UFUKVzdTWjJCMHZWMndBZTBCT2JzRTVpSmxnRzZaamJYR25TRjI0NTl4TzJRS0JnRER1cXJBcThQMXpXU28wcWZ0QgpkTS9Xc3p6U3VZRHdjemhvajNKek5VK3lvQ3g4ejNzY0NML240eXFUT1RiWVhLTXFHbUVrSW01eXJ1SWlJeHBRCmNJM1pDUlVZbHZDY0FaeCtiVU1QSXNkek1TeGJMaHNqSU5Oc3F4dDJlMlQvd2dJWXpWenVERExpZ1drN1lDZkEKNDJ4YXVldHQ0M21qM25wYUFvcURIVG92Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"; + private static final String TEST_ENCODED_PRIVATE_KEY_IN_PKCS1 = "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBOHNMTXZWdlRmaTRtRWZpcithbS9jbzY2Z04rcVhveWVDbHFxNXVBZWdsYkgvSmJsCm11dlBMV3pnREZQZnVQSEQ1N2FqL1cxWnhjUFBPSXJNTkhsdkJuRU1HRjZnOVJPd0twRVA1OGx1cTVDbmxFc0IKckowdlRVbUZFSXlwdkU5UGk2eURwTVJsV1hkZm1nVXBIRmJMcmZ1V21ldXZ0MEFPaW90RHZiWkx6amV5NjZkMApHUmtySXVlUVhoWlNVTVk4akltRjdqUEg5WVNZaHNQTnR6N0VVcXU0UCtXb0pkc0EwcnFxRVVkaXM4SC9udXlQCmFEOS9OUW1HdUtzRW1ZVVNCcExiMHFXWklhN0lXWHdmQ21KbEVVZEUvYjM4aEw2T3c0NzlZZ2dtYlBKUzVZam4KdGhkaEhkZFlqTW5hV3BNeGowUWVzMVFvR01NaHYvdExyeTBzcVFJREFRQUJBb0lCQUZYcklnRm03WXg4RXRkTApkcnB2SEtZVDQraFd3UHFqdEErZ0ZWcVBPZDBSajhoVE04Skg4VlIzY3ppSnV1Vy9FNEgvL3p4anBtRTdNeTBrCjJxODd4MUsxVWYyU0NFK1UvMFdoZjhxZVhULzFlNG9kbmVNVTRyZnM3RjUyR21EZWhSMi9HZnlIMGdML0grUG8KTGF1dEFIdDhUc245UTN5TS9GaUdmNXcyVjlBTThCSUcreVJ3d0hhMjU1UEJrNzhBTnQrc2psend6M053QVB2NgpKNldXWTBEWnBJZzlEenBlRnRqNWJMaks4OGlFTDAwb1l2empQU2tuOTJhNnNhZXRDUG16bGkrRzB3SzUwK25yCjZCS2w1MFFsZTQ2bkIya2Zhd1JqY3h4RlJHTUdXbE4yYkZzNkkrU00zTGVFQWhiZXhiUWEyRGtxZHhzRU8zc24KVmtJdVN6RUNnWUVBL3NUMTBzZG94eVV2Y0NGTGw2dlpwUldEZTlIcm13NjM1aUo3Ui9Idi9Vd3pBWEE2VlZtcwpKN1c1WFNFSjRtZFNXRllqY09TekFLc2ZmWlF1cVZsRTlxOFNkaExjQVlvdTNpMW9UWUJ4S1J2MnZxZHJrMS9ECjAyVDJyTXY0MEJBOWFEUXgxRHN6V1BKNW9EYWJGZUdWY09vck5hTW04eTFVQlE4MitsOS9aQzBDZ1lFQTgrNzkKZ2JkR0FlRVl1bldUS2ZwTGRISTZsZWl1eFEyUks1N3VmNzlZOGJQREw4YktBREZvMnYvNW9oNVlSUzRTOThpTgpRTzlQYW0rdG5TRE1aRHNjVkVNRm4rbUVpaVNRUm55OG5jZm5UVTdDa21qM3ZnRlZEbGpGL2FpRk9kRk5rRkJjCnJIem5yd3pYUVVuMDlmUEVUS0IwcmFQL0tHNkJDcDV2eUNEZGkrMENnWUVBL0FKaVU1UlM3YUszMFFmdVdXSngKVU4zK0NLMzJpNU84anhXT3N2VDcrcWUwVUhqdUN0MC84S3ZPWnZPMmJsRGI0R3VjZFNDVWZGWEpPWlFwci9TUQp4aDhaZU5oZzdkajlVV0xES042amtSR0xPcjRyS0VWelZKa3JkSFB6ZEFTTWFaWXZzQXE3V1FISkU1VFFSWTIyCklGSlNXYVZBY3cxa2JmakYzbFkya2lVQ2dZQnZ5QVREZklqSU02NXhRNCs4bk1ZWEJvRnlVTDVGN29Hbnk1emYKVFlBa3dvdWZTU2tvRFh4UFh4MjEvTkhXWWRhdlZXZmxhY1Nxc2FLTmJvbzdKQnRIUWE5Q0tIQmtIWDAvejhsZgpSRXZxVVQwNGVvR013RytKczRTSFNNSkVUSFdPdkVTN2hrRmxKaTA5N2ZZaS95SGxPMkk4Yi9wdFBMWkZkM1VoCjhHMlZ3UUtCZ1FDWGE2eXNhb09uREFXNFEzNTlYeGJ0TEJ3NTltR0NwVDRsbzJFR0tWaWVkQWh5Sk5wY01nbTEKN0NxSzN2Uml4enRTZGNpa2hHQ3IweGVWWDdEbFphb1ZPTURGeHZZWDhmSkJ6N1N6ejNDc29WZS8vSXRKR2kzdQppUThpQWhaN3J3Szk1TjZHeUI0RHhBMWhVV09LYVczbXVHWEpOc1JySmpqdk9tY3VBbXgzSWc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo="; + private static final String TEST_ENCODED_OLD_PRIVATE_KEY = "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2d0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktrd2dnU2xBZ0VBQW9JQkFRRHVTZ0FtVWovWEo5NlQKOGkzREZxWE1QOUpaa3RkeEtYZUV2NDZhcGFVTmJyNGNoSi9EM2pLdTFBRFdWVEx4YlNyOEpuT0dDSUFzenZjaQozQmxLb1VUaHVvaUl0NXBnKy9kaFc2SDRnazdtdTRVdzAxdEFVQjZqM2ZubVhJTDZaMTlmS2F0bXlRTmVMSzRQCnlNNTFMTG03ZjgyNjZsR0NrektmdWx0NVAvc21Ya0lxL0FGN1d6Q3gzclNXOW0yZkdKaEFGcjAyL09pV1JvOWIKd0VHSjFkUnJhaTc5ZGtpMEN4eFlDMXYvb3FXVTJLTmpSZDF5RXNXb0ZxTC9pd1NoWCtwazl5cmtSMzQ0aEZLZwpRVFl1bGg3Z0NKQmwyOFhGM2kraDNiVHZJL3VMRk5PLzdvZ29PTjlDM04wdTRiTzhlNUNnUERHZWI5eG9VQklrClVnM0hOSkczQWdNQkFBRUNnZ0VCQU1qOTFEaCtvZWlxY1h5YkJ1eUtPdGtZY0NZcnpOdGZuYmQwR0NYcldGZ0gKTkFZNys4S3J0bFp1N2pIYmRYZmNuQ2hKaXFIZ283U244aDhPUmFzRWNtUndBV0JJZGNnZVgrQlgrVHZ6TmZnNgo3YkpzWklqUHk3aHVzSzRWRkVtQVRocW52REtibE9Lbmp6NHpJNm9FU3JtVHFJVmp4ZEw4cy9PMHJobU0xUnZiClB0QXRCeDNMTEtBUFZWTlN6a05JeHFIY1cwaFJ1bFlqOU81S3hmZDJJdDlrKzVzY0RpQU5qcU9YTVRIMmxrdzcKcE41ZFRtNU1EQXcrMGpaUVNpUFRia0hFQWdPZElxNmxuYStSN1lBRkFNc0ZVKzlmbnNEZVR2M2VHT2h6ZVhCSApJRlRkTStIOVU3Tm8xOW91d0NHU05JTEJESnE1V2JVd3VLQWRTUDBVaGZFQ2dZRUEvNElFa1g2djJVSUpqbldwCjBnbzBTSFJFamQ1Vmk0T2dnQW00L0hDbWx6Q3ljZzljRUhXeXFsd3RNN24xVkw5WDdJaytxMFc2UjBYRXlJbHMKTWlPSEF0cFhxbDB0RnRNQVd5SnBLY05vaktyRjlMR3g2VDVKQk5HTFo1b2JCaXRLNTZtTVZta0RTTzljc3hRYgpURXhQY1JGZmpQdkpJTlBRNDRZYWNRR0padThDZ1lFQTdyOStJN2svdzg2YVNWWkJObTh4NURrZVd4anRBSmRnCndFeXpEWklxYXEwU3IvQ0dxZnRSTFFrNnF4RDQxVWh2d1QrVHVMd2xuWWJMWmRzQmJVVW11cHNBZWpMbnY0RGIKR1RiTHpiNEM1c2FONW13dEJPeU5vaGNoUUVHVUF0RzdzN3BCYStsOE9MSmVzS1FsMWJBc0JXRC9leG01bzZyYwo0T0NYQkNpaHdia0NnWUFjU2ZEbml2YzlQcXFBTTFiU0FuODNabWdRclFVYnBUOG43ZXVsUjNPcVdhSG9MdnNxCmQxMklyeHZ5Rml5cmJXUDJ0RnRUNnl4c3A3VFozeDB6ait0cXpYSFhVdW1qRlVsOHpacUhIVE4rSDRvN1JWRkYKV2JnTDZJZGV1UmswM2FZMWIvZ3h1UDY4SElSTzczTDJSNXlrRUNCY0k2UnBGZ3FTcGs1WEpLeHAwUUtCZ1FEWAp5VmhYTFg1R21odTFJVEs3NG5Dem1EU3BuYlBJandteGhTRm9xSzJSMFhCTWVSY2QxN3FjKy9SODNWQXFaZGdzClVDeFNFaXZsWHduRHU5aGtUTlllWHk1bFJGRldNejdVWVVSL1pyZjBvWTFyc0daWVJ2NFVmTmRlM21iS3pZbmIKZmdMWGFDY1FqNWNxREpMdHV0ZHUzU2JNdW9taE5qT0JSVHo1VTBnd2NRS0JnUURyRy9wZDN6aUw1dFZFSk1KOApUQmdodko1NTZNMjFXaXFRNG1WUGcwbGNub1RXVmdCV0hqS2k2MzNhZVVRRlYrQTN2d3ljS1h4YVdsUzBYWmZVCmRobTJaUnVwYzhaeVA2ZGNaR3VLTWxHR21kSGtGaExIcUNhZXViS25ZUEkyVTFrZklNVGlWR0Jubmk2Y3dkRGIKUzczSG12YVpwU0xsbDlhbXkvZEx1N0QxdGc9PQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg=="; + private static final String TEST_ENCODED_OLD_CERT = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVmVENDQXVXZ0F3SUJBZ0lVRncwd1VZc2wxUkF2bHB1bXpqcFRrNjZzNGlzd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1V6RVZNQk1HQ2dtU0pvbVQ4aXhrQVFFTUJURXlNelExTVJVd0V3WURWUVFEREF4TllXNWhaMlZ0Wlc1MApRMEV4SXpBaEJnTlZCQW9NR2tWS1FrTkJJRU52Ym5SaGFXNWxjaUJSZFdsamEzTjBZWEowTUI0WERUSXhNRGN3Ck1qQTNNVE0xTlZvWERUSXpNRGN3TWpBM01EWTFNMW93ZHpFUk1BOEdBMVVFQXd3SWIyNWhjQzV2Y21jeEdUQVgKQmdOVkJBc01FRXhwYm5WNExVWnZkVzVrWVhScGIyNHhEVEFMQmdOVkJBb01CRTlPUVZBeEZqQVVCZ05WQkFjTQpEVk5oYmkxR2NtRnVZMmx6WTI4eEV6QVJCZ05WQkFnTUNrTmhiR2xtYjNKdWFXRXhDekFKQmdOVkJBWVRBbFZUCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBN2tvQUpsSS8xeWZlay9JdHd4YWwKekQvU1daTFhjU2wzaEwrT21xV2xEVzYrSElTZnc5NHlydFFBMWxVeThXMHEvQ1p6aGdpQUxNNzNJdHdaU3FGRQo0YnFJaUxlYVlQdjNZVnVoK0lKTzVydUZNTk5iUUZBZW85MzU1bHlDK21kZlh5bXJac2tEWGl5dUQ4ak9kU3k1CnUzL051dXBSZ3BNeW43cGJlVC83Smw1Q0t2d0JlMXN3c2Q2MGx2WnRueGlZUUJhOU52em9sa2FQVzhCQmlkWFUKYTJvdS9YWkl0QXNjV0F0Yi82S2xsTmlqWTBYZGNoTEZxQmFpLzRzRW9WL3FaUGNxNUVkK09JUlNvRUUyTHBZZQo0QWlRWmR2RnhkNHZvZDIwN3lQN2l4VFR2KzZJS0RqZlF0emRMdUd6dkh1UW9Ed3hubS9jYUZBU0pGSU54elNSCnR3SURBUUFCbzRHa01JR2hNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVzWW1NQytnWTE4WWMKdDVMejJheDlTRjhzaHlNd0dBWURWUjBSQkJFd0Q0SU5kR1Z6ZEM1dmJtRndMbTl5WnpBbkJnTlZIU1VFSURBZQpCZ2dyQmdFRkJRY0RBZ1lJS3dZQkJRVUhBd1FHQ0NzR0FRVUZCd01CTUIwR0ExVWREZ1FXQkJTdDVzYTFCc1VNCjJrTHFpdXNGWkxCWGlFMStJREFPQmdOVkhROEJBZjhFQkFNQ0JlQXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnR0IKQUkrYW94LzJPUFdQZC9IanB0b1VhVlRhNkFnZldMMHoyR3NkOS9oVDBPVTdGSWloTEwrUGx4Y3Z2VWVQWGZlRQpHaEtJb3FJb3pERndMeWs1OUVWNVMxSEdsYVI3QnlUZkVJcVl5T0I5YkNPMmlPWjdIcW9vNmxoN2hoUTZXUENRCmtpY3VRMXJRWDJFSHlOVW05aFovU2dWamFYQlpZY0l0cFNsN1lWSVFGUElXY2VYYmtFaG8rSG5HczExTDI0V0QKUWhCNkpWWWJzME9JQzVaNDNablBKaHdHYlVyOCs5Q2IwR0J1dzNITUVMN05mNmFQSWVjOG8ydXphVHU3WXlOegpjYlN4WmMyUzRpeVpSbjdkTldQSmtFUVFGd1dPNlBOYzRwd0xSeC9zR3pHdlY0cFZGdlRuOGE3c0FiVXpwcnZBCmRDNFdjYnJhNE1wTFFKczZqNWJoUFJ1QlRsSXBnZEVhdkVSM1J5bUVGUTBSRHdER2thSndNbkdVVTlqSWdFN3AKR282RG5aV2RJZEFoRlN2Q3RybERLL1NGYmVKM3RTNlMrSUxXUDgydWU3Q0UwSnYrUEVoUnc5aWVreE5hRElNbwpzeXcvM2tnSUNnckV3RjJzUHY5UnVLQ212V3NrMkdKaHRRcXZSK3FFRE5FQW15aXJodFh6L214QUZ0dy9ualpVCjBBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQoK"; + + private static final OldCertificateModelFactory factory = + new OldCertificateModelFactory(new PemStringToCertificateConverter(), new X509CertificateParser()); + + static final OldCertificateModel createCorrectOldCertificateModel() throws CertificateDecryptionException { + return createOldCertificateModel(TEST_ENCODED_OLD_CERT, TEST_ENCODED_OLD_PRIVATE_KEY); + } + + static final OldCertificateModel createOldCertificateModelWithWrongCert() throws CertificateDecryptionException { + return createOldCertificateModel(WRONG_OLD_CERT, TEST_ENCODED_OLD_PRIVATE_KEY); + } + + static final OldCertificateModel createOldCertificateModelWithWrongPrivateKey() throws CertificateDecryptionException { + return createOldCertificateModel(TEST_ENCODED_OLD_CERT, WRONG_OLD_PRIVATE_KEY); + } + + static final OldCertificateModel createOldCertificateModelWithPrivateKeyInPKCS1() throws CertificateDecryptionException { + return createOldCertificateModel(TEST_ENCODED_OLD_CERT, TEST_ENCODED_PRIVATE_KEY_IN_PKCS1); + } + + static final OldCertificateModel createOldCertificateModelWithPrivateKeyInPKCS8() throws CertificateDecryptionException { + return createOldCertificateModel(TEST_ENCODED_OLD_CERT, TEST_ENCODED_PRIVATE_KEY_IN_PKCS8); + } + + private static final OldCertificateModel createOldCertificateModel(String certificate, String privateKey) throws CertificateDecryptionException { + StringBase64 base64EncodedCertificate = new StringBase64(certificate); + return factory.createCertificateModel(base64EncodedCertificate, privateKey); + } + + private ClientTestData() { + } + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java b/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java index 337ed8c1..93dcbb77 100644 --- a/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java +++ b/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java @@ -17,13 +17,17 @@ package org.onap.oom.certservice.cmpv2client; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; +import static org.onap.oom.certservice.cmpv2client.ClientTestData.createOldCertificateModelWithPrivateKeyInPKCS1; +import static org.onap.oom.certservice.cmpv2client.ClientTestData.createOldCertificateModelWithPrivateKeyInPKCS8; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; @@ -44,8 +48,11 @@ import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.Base64.Decoder; import java.util.Date; +import java.util.stream.Stream; import org.apache.commons.io.IOUtils; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; @@ -70,10 +77,15 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mock; import org.onap.oom.certservice.certification.configuration.model.Authentication; import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.exception.CertificateDecryptionException; import org.onap.oom.certservice.certification.model.CsrModel; +import org.onap.oom.certservice.certification.model.OldCertificateModel; import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; import org.onap.oom.certservice.cmpv2client.exceptions.CmpServerException; import org.onap.oom.certservice.cmpv2client.impl.CmpClientImpl; @@ -103,6 +115,8 @@ class Cmpv2ClientTest { private static KeyPair keyPair; + private final static Decoder BASE64_DECODER = Base64.getDecoder(); + @BeforeEach void setUp() throws NoSuchProviderException, NoSuchAlgorithmException, IOException, @@ -136,6 +150,102 @@ class Cmpv2ClientTest { } @Test + void shouldReturnCorrectCmpCertificateForCorrectKeyUpdateResponse() throws CmpClientException, IOException, CertificateDecryptionException { + + // given + setCsrModelAndServerTestDefaultValues(); + when(httpClient.execute(any())).thenReturn(httpResponse); + when(httpResponse.getEntity()).thenReturn(httpEntity); + + mockCorrectKeyUpdateResponse(); + CmpClientImpl cmpClient = new CmpClientImpl(httpClient); + + // when + Cmpv2CertificationModel cmpClientResult = + cmpClient.executeKeyUpdateRequest(csrModel, server, ClientTestData.createCorrectOldCertificateModel()); + + // then + assertNotNull(cmpClientResult); + assertThat(cmpClientResult.getCertificateChain()).isNotEmpty(); + assertThat(cmpClientResult.getCertificateChain()).isNotEmpty(); + + } + + @Test + void shouldReturnCorrectCmpCertificateForCorrectCertificationRequest() throws CmpClientException, IOException { + + // given + setCsrModelAndServerTestDefaultValues(); + when(httpClient.execute(any())).thenReturn(httpResponse); + when(httpResponse.getEntity()).thenReturn(httpEntity); + + doAnswer( + invocation -> { + OutputStream os = invocation.getArgument(0); + os.write(BASE64_DECODER.decode(ClientTestData.CR_CORRECT_SERVER_RESPONSE_ENCODED.getBytes())); + return null; + }) + .when(httpEntity) + .writeTo(any(OutputStream.class)); + CmpClientImpl cmpClient = new CmpClientImpl(httpClient); + + // when + Cmpv2CertificationModel cmpClientResult = + cmpClient.executeCertificationRequest(csrModel, server); + + // then + assertNotNull(cmpClientResult); + assertThat(cmpClientResult.getCertificateChain()).isNotEmpty(); + assertThat(cmpClientResult.getCertificateChain()).isNotEmpty(); + + } + + @ParameterizedTest + @MethodSource("getTestUpdateModelWithSupportedPrivateKeys") + void shouldNotThrowExceptionForPrivateKeyInExpectedFormat(OldCertificateModel oldCertificateModel) + throws IOException { + + // given + setCsrModelAndServerTestDefaultValues(); + when(httpClient.execute(any())).thenReturn(httpResponse); + when(httpResponse.getEntity()).thenReturn(httpEntity); + + mockCorrectKeyUpdateResponse(); + CmpClientImpl cmpClient = new CmpClientImpl(httpClient); + + // when // then + assertDoesNotThrow(() -> cmpClient + .executeKeyUpdateRequest(csrModel, server, oldCertificateModel) + ); + + } + + @Test + void shouldThrowCmpClientExceptionWhenCannotParseOldPrivateKey() { + setCsrModelAndServerTestDefaultValues(); + + CmpClientImpl cmpClient = new CmpClientImpl(httpClient); + assertThatExceptionOfType(CertificateDecryptionException.class) + .isThrownBy(() -> cmpClient.executeKeyUpdateRequest(csrModel, server, ClientTestData.createOldCertificateModelWithWrongPrivateKey())) + .withMessageContaining("Cannot convert certificate or key"); + + } + + + @Test + void shouldThrowCMPClientExceptionWhenCannotParseOldCertificate() { + setCsrModelAndServerTestDefaultValues(); + + CmpClientImpl cmpClient = new CmpClientImpl(httpClient); + + // When // Then + assertThatExceptionOfType(CertificateDecryptionException.class) + .isThrownBy(() -> cmpClient.executeKeyUpdateRequest(csrModel, server, ClientTestData.createOldCertificateModelWithWrongCert())) + .withMessageContaining("Incorrect certificate, decryption failed"); + } + + + @Test void shouldReturnValidPkiMessageWhenCreateCertificateRequestMessageMethodCalledWithValidCsr() throws Exception { // given @@ -167,7 +277,7 @@ class Cmpv2ClientTest { CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient)); // when Cmpv2CertificationModel cmpClientResult = - cmpClient.createCertificate(csrModel, server, notBefore, notAfter); + cmpClient.executeInitializationRequest(csrModel, server, notBefore, notAfter); // then assertNotNull(cmpClientResult); } @@ -206,7 +316,7 @@ class Cmpv2ClientTest { // then Assertions.assertThrows( CmpClientException.class, - () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); + () -> cmpClient.executeInitializationRequest(csrModel, server, notBefore, notAfter)); } @Test @@ -243,7 +353,7 @@ class Cmpv2ClientTest { // then Assertions.assertThrows( CmpServerException.class, - () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); + () -> cmpClient.executeInitializationRequest(csrModel, server, notBefore, notAfter)); } @@ -282,7 +392,7 @@ class Cmpv2ClientTest { CmpClientImpl cmpClient = new CmpClientImpl(httpClient); assertThatExceptionOfType(CmpClientException.class) - .isThrownBy(() -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)) + .isThrownBy(() -> cmpClient.executeInitializationRequest(csrModel, server, notBefore, notAfter)) .withMessageContaining("CMP response does not contain Protection Algorithm field"); } @@ -303,7 +413,7 @@ class Cmpv2ClientTest { // then Assertions.assertThrows( IllegalArgumentException.class, - () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); + () -> cmpClient.executeInitializationRequest(csrModel, server, notBefore, notAfter)); } @Test @@ -323,7 +433,18 @@ class Cmpv2ClientTest { // then Assertions.assertThrows( CmpClientException.class, - () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); + () -> cmpClient.executeInitializationRequest(csrModel, server, notBefore, notAfter)); + } + + private void mockCorrectKeyUpdateResponse() throws IOException { + doAnswer( + invocation -> { + OutputStream os = invocation.getArgument(0); + os.write(BASE64_DECODER.decode(ClientTestData.KUR_CORRECT_SERVER_RESPONSE_ENCODED.getBytes())); + return null; + }) + .when(httpEntity) + .writeTo(any(OutputStream.class)); } private void setCsrModelAndServerValues(String iak, String rv, String externalCaUrl, Date notBefore, Date notAfter) { @@ -340,6 +461,18 @@ class Cmpv2ClientTest { this.notAfter = notAfter; } + private void setCsrModelAndServerTestDefaultValues() { + csrModel = new CsrModel(null, dn, keyPair.getPrivate(), keyPair.getPublic(), new GeneralName[0]); + + Authentication authentication = new Authentication(); + authentication.setIak("mypassword"); + authentication.setRv("senderKID"); + server = new Cmpv2Server(); + server.setAuthentication(authentication); + server.setUrl("http://127.0.0.1/ejbca/publicweb/cmp/cmp"); + server.setIssuerDN(dn); + } + private PKIMessage preparePKIMessageWithoutProtectionAlgorithm() { CertTemplateBuilder certTemplateBuilder = new CertTemplateBuilder(); @@ -368,4 +501,12 @@ class Cmpv2ClientTest { .build(); } + private static Stream<Arguments> getTestUpdateModelWithSupportedPrivateKeys() + throws CertificateDecryptionException { + return Stream.of( + Arguments.of(createOldCertificateModelWithPrivateKeyInPKCS1()), + Arguments.of(createOldCertificateModelWithPrivateKeyInPKCS8()) + ); + } + } |