From b8c4e6867d6b26652f4382e93665c220769cdc9f Mon Sep 17 00:00:00 2001 From: baniewsk Date: Wed, 29 Jul 2020 16:01:27 +0200 Subject: Removing AAF references from Cert-Service in OOM repo. Certificates regenerated External files (from legacy AAF) removed Still left: * Sonar link, * Link to documentation, * Names of K8s resources in RTD documentation, * Link to CSITs Issue-ID: OOM-2526 Signed-off-by: Pawel Baniewski Change-Id: I675f7485160b9b8e46e9ea573550e62ed28ca607 --- .../aaf/certservice/CertServiceApplication.java | 37 --- .../certservice/api/CertificationController.java | 96 ------ .../aaf/certservice/api/ReadinessController.java | 61 ---- .../certservice/api/ReloadConfigController.java | 64 ---- .../api/advice/CertificationExceptionAdvice.java | 100 ------ .../api/advice/ReloadConfigExceptionAdvice.java | 43 --- .../api/configuration/OpenApiConfig.java | 44 --- .../certification/CertificateFactoryProvider.java | 42 --- .../certification/CertificationData.java | 128 -------- .../certification/CertificationModelFactory.java | 70 ----- .../certification/CertificationProvider.java | 78 ----- .../certservice/certification/CsrModelFactory.java | 113 ------- .../certification/PemObjectFactory.java | 49 --- .../Pkcs10CertificationRequestFactory.java | 45 --- .../certification/RsaContentSignerBuilder.java | 46 --- .../certification/X509CertificateBuilder.java | 56 ---- .../configuration/CmpClientConfig.java | 50 --- .../configuration/CmpServersConfig.java | 87 ------ .../configuration/CmpServersConfigLoader.java | 64 ---- .../CmpServersConfigLoadingException.java | 32 -- .../configuration/Cmpv2ServerProvider.java | 43 --- .../configuration/model/Authentication.java | 60 ---- .../certification/configuration/model/CaMode.java | 35 --- .../configuration/model/CmpServers.java | 37 --- .../configuration/model/Cmpv2Server.java | 98 ------ .../Cmpv2ServersConfigurationValidator.java | 68 ----- .../validation/constraints/Cmpv2Url.java | 41 --- .../validation/constraints/Cmpv2UrlValidator.java | 55 ---- .../violations/PortNumberViolation.java | 43 --- .../violations/RequestTypeViolation.java | 49 --- .../constraints/violations/UrlServerViolation.java | 25 -- .../exception/Cmpv2ClientAdapterException.java | 28 -- .../exception/Cmpv2ServerNotFoundException.java | 27 -- .../exception/CsrDecryptionException.java | 31 -- .../exception/DecryptionException.java | 33 -- .../exception/ErrorResponseModel.java | 36 --- .../exception/KeyDecryptionException.java | 31 -- .../certification/model/CertificationModel.java | 44 --- .../certservice/certification/model/CsrModel.java | 170 ----------- .../aaf/certservice/cmpv2client/api/CmpClient.java | 74 ----- .../cmpv2client/exceptions/CmpClientException.java | 50 --- .../cmpv2client/exceptions/PkiErrorException.java | 47 --- .../certservice/cmpv2client/external/Factory.java | 61 ---- .../aaf/certservice/cmpv2client/external/Rdn.java | 157 ---------- .../cmpv2client/impl/CmpClientImpl.java | 242 --------------- .../cmpv2client/impl/CmpMessageBuilder.java | 57 ---- .../cmpv2client/impl/CmpMessageHelper.java | 246 --------------- .../cmpv2client/impl/CmpResponseHelper.java | 335 --------------------- .../impl/CmpResponseValidationHelper.java | 241 --------------- .../aaf/certservice/cmpv2client/impl/CmpUtil.java | 153 ---------- .../cmpv2client/impl/Cmpv2HttpClient.java | 83 ----- .../cmpv2client/impl/CreateCertRequest.java | 128 -------- .../cmpv2client/model/Cmpv2CertificationModel.java | 44 --- .../oom/certservice/CertServiceApplication.java | 37 +++ .../certservice/api/CertificationController.java | 96 ++++++ .../oom/certservice/api/ReadinessController.java | 61 ++++ .../certservice/api/ReloadConfigController.java | 64 ++++ .../api/advice/CertificationExceptionAdvice.java | 100 ++++++ .../api/advice/ReloadConfigExceptionAdvice.java | 43 +++ .../api/configuration/OpenApiConfig.java | 44 +++ .../certification/CertificateFactoryProvider.java | 42 +++ .../certification/CertificationData.java | 128 ++++++++ .../certification/CertificationModelFactory.java | 70 +++++ .../certification/CertificationProvider.java | 78 +++++ .../certservice/certification/CsrModelFactory.java | 113 +++++++ .../certification/PemObjectFactory.java | 49 +++ .../Pkcs10CertificationRequestFactory.java | 45 +++ .../certification/RsaContentSignerBuilder.java | 46 +++ .../certification/X509CertificateBuilder.java | 56 ++++ .../configuration/CmpClientConfig.java | 50 +++ .../configuration/CmpServersConfig.java | 87 ++++++ .../configuration/CmpServersConfigLoader.java | 64 ++++ .../CmpServersConfigLoadingException.java | 32 ++ .../configuration/Cmpv2ServerProvider.java | 43 +++ .../configuration/model/Authentication.java | 60 ++++ .../certification/configuration/model/CaMode.java | 35 +++ .../configuration/model/CmpServers.java | 37 +++ .../configuration/model/Cmpv2Server.java | 98 ++++++ .../Cmpv2ServersConfigurationValidator.java | 68 +++++ .../validation/constraints/Cmpv2Url.java | 41 +++ .../validation/constraints/Cmpv2UrlValidator.java | 55 ++++ .../violations/PortNumberViolation.java | 43 +++ .../violations/RequestTypeViolation.java | 49 +++ .../constraints/violations/UrlServerViolation.java | 25 ++ .../exception/Cmpv2ClientAdapterException.java | 28 ++ .../exception/Cmpv2ServerNotFoundException.java | 27 ++ .../exception/CsrDecryptionException.java | 31 ++ .../exception/DecryptionException.java | 33 ++ .../exception/ErrorResponseModel.java | 36 +++ .../exception/KeyDecryptionException.java | 31 ++ .../certification/model/CertificationModel.java | 44 +++ .../certservice/certification/model/CsrModel.java | 170 +++++++++++ .../oom/certservice/cmpv2client/api/CmpClient.java | 74 +++++ .../cmpv2client/exceptions/CmpClientException.java | 50 +++ .../cmpv2client/exceptions/PkiErrorException.java | 47 +++ .../cmpv2client/impl/CmpClientImpl.java | 242 +++++++++++++++ .../cmpv2client/impl/CmpMessageBuilder.java | 57 ++++ .../cmpv2client/impl/CmpMessageHelper.java | 246 +++++++++++++++ .../cmpv2client/impl/CmpResponseHelper.java | 335 +++++++++++++++++++++ .../impl/CmpResponseValidationHelper.java | 241 +++++++++++++++ .../oom/certservice/cmpv2client/impl/CmpUtil.java | 153 ++++++++++ .../cmpv2client/impl/Cmpv2HttpClient.java | 83 +++++ .../cmpv2client/impl/CreateCertRequest.java | 128 ++++++++ .../cmpv2client/model/Cmpv2CertificationModel.java | 44 +++ 104 files changed, 3959 insertions(+), 4177 deletions(-) delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/CertServiceApplication.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/api/CertificationController.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/api/ReadinessController.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/api/ReloadConfigController.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/api/advice/CertificationExceptionAdvice.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/api/advice/ReloadConfigExceptionAdvice.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/api/configuration/OpenApiConfig.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/CertificateFactoryProvider.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/CertificationData.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/CertificationModelFactory.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/CertificationProvider.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/PemObjectFactory.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/Pkcs10CertificationRequestFactory.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/RsaContentSignerBuilder.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/X509CertificateBuilder.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpClientConfig.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfig.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoader.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoadingException.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/Cmpv2ServerProvider.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/Authentication.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/CaMode.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/CmpServers.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/Cmpv2Server.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidator.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2Url.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidator.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/PortNumberViolation.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolation.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/UrlServerViolation.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/exception/Cmpv2ClientAdapterException.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/exception/Cmpv2ServerNotFoundException.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/exception/CsrDecryptionException.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/exception/DecryptionException.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/exception/ErrorResponseModel.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/exception/KeyDecryptionException.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/model/CertificationModel.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/certification/model/CsrModel.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/api/CmpClient.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/exceptions/CmpClientException.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/exceptions/PkiErrorException.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/external/Factory.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/external/Rdn.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpClientImpl.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpMessageBuilder.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpMessageHelper.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseHelper.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseValidationHelper.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpUtil.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/Cmpv2HttpClient.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CreateCertRequest.java delete mode 100644 certService/src/main/java/org/onap/aaf/certservice/cmpv2client/model/Cmpv2CertificationModel.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/CertServiceApplication.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/api/ReadinessController.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/api/ReloadConfigController.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/api/advice/CertificationExceptionAdvice.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/api/advice/ReloadConfigExceptionAdvice.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/api/configuration/OpenApiConfig.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/CertificateFactoryProvider.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/CertificationData.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/CsrModelFactory.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/PemObjectFactory.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/Pkcs10CertificationRequestFactory.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/RsaContentSignerBuilder.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/X509CertificateBuilder.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpClientConfig.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfig.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoader.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoadingException.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/Cmpv2ServerProvider.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/Authentication.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/CaMode.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/CmpServers.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/Cmpv2Server.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidator.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2Url.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidator.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/PortNumberViolation.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolation.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/UrlServerViolation.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/exception/Cmpv2ClientAdapterException.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/exception/Cmpv2ServerNotFoundException.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/exception/CsrDecryptionException.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/exception/DecryptionException.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/exception/ErrorResponseModel.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/exception/KeyDecryptionException.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/model/CertificationModel.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/certification/model/CsrModel.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/exceptions/CmpClientException.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/exceptions/PkiErrorException.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpMessageBuilder.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpMessageHelper.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseHelper.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseValidationHelper.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpUtil.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/Cmpv2HttpClient.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java create mode 100644 certService/src/main/java/org/onap/oom/certservice/cmpv2client/model/Cmpv2CertificationModel.java (limited to 'certService/src/main/java/org') diff --git a/certService/src/main/java/org/onap/aaf/certservice/CertServiceApplication.java b/certService/src/main/java/org/onap/aaf/certservice/CertServiceApplication.java deleted file mode 100644 index 11478965..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/CertServiceApplication.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.PropertySource; - -@SpringBootApplication -@PropertySource(value = {"classpath:application.properties"}) -public class CertServiceApplication { - - // We are excluding this line in Sonar due to fact that - // Spring is handling arguments - public static void main(String[] args) { // NOSONAR - SpringApplication.run(CertServiceApplication.class, args); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/api/CertificationController.java b/certService/src/main/java/org/onap/aaf/certservice/api/CertificationController.java deleted file mode 100644 index c440ec34..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/api/CertificationController.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.api; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -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.aaf.certservice.certification.CertificationModelFactory; -import org.onap.aaf.certservice.certification.exception.DecryptionException; -import org.onap.aaf.certservice.certification.exception.ErrorResponseModel; -import org.onap.aaf.certservice.certification.model.CertificationModel; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - - -@RestController -@Tag(name = "CertificationService") -public class CertificationController { - - private static final Logger LOGGER = LoggerFactory.getLogger(CertificationController.class); - - private final CertificationModelFactory certificationModelFactory; - - @Autowired - CertificationController(CertificationModelFactory certificationModelFactory) { - this.certificationModelFactory = certificationModelFactory; - } - - /** - * Request for signing certificate by given CA. - * - * @param caName the name of Certification Authority that will sign root certificate - * @param encodedCsr Certificate Sign Request encoded in Base64 form - * @param encodedPrivateKey Private key for CSR, needed for PoP, encoded in Base64 form - * @return JSON containing trusted certificates and certificate chain - */ - @GetMapping(value = "v1/certificate/{caName}", produces = "application/json") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Certificate successfully signed"), - @ApiResponse(responseCode = "400", description = "Given CSR or/and PK is incorrect", - content = @Content(schema = @Schema(implementation = ErrorResponseModel.class))), - @ApiResponse(responseCode = "404", description = "CA not found for given name", - content = @Content(schema = @Schema(implementation = ErrorResponseModel.class))), - @ApiResponse(responseCode = "500", description = "Something went wrong during connectiion to CMPv2 server", - content = @Content(schema = @Schema(implementation = ErrorResponseModel.class))) - }) - @Operation( - summary = "sign certificate", - description = "Web endpoint for requesting certificate signing. Used by system components to gain certificate signed by CA.", - tags = {"CertificationService"}) - public ResponseEntity 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).") - @RequestHeader("CSR") String encodedCsr, - @Parameter(description = "Private key in form of PEM object encoded in Base64 (with header and footer).") - @RequestHeader("PK") String encodedPrivateKey - ) throws DecryptionException, CmpClientException { - caName = caName.replaceAll("[\n|\r|\t]", "_"); - LOGGER.info("Received certificate signing request for CA named: {}", caName); - CertificationModel certificationModel = certificationModelFactory - .createCertificationModel(encodedCsr, encodedPrivateKey, caName); - return new ResponseEntity<>(certificationModel, HttpStatus.OK); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/api/ReadinessController.java b/certService/src/main/java/org/onap/aaf/certservice/api/ReadinessController.java deleted file mode 100644 index 9c8e1bf0..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/api/ReadinessController.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.api; - -import io.swagger.v3.oas.annotations.Operation; -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.aaf.certservice.certification.configuration.CmpServersConfig; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@Tag(name = "CertificationService") -public final class ReadinessController { - - private final CmpServersConfig cmpServersConfig; - - @Autowired - public ReadinessController(CmpServersConfig cmpServersConfig) { - this.cmpServersConfig = cmpServersConfig; - } - - @GetMapping(value = "/ready", produces = "application/json") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Configuration is loaded and service is ready to use"), - @ApiResponse(responseCode = "503", description = "Configuration loading failed and service is unavailable") - }) - @Operation( - summary = "Check if CertService application is ready", - description = "Web endpoint for checking if service is ready to be used.", - tags = {"CertificationService"}) - public ResponseEntity checkReady() { - if (cmpServersConfig.isReady()) { - return new ResponseEntity<>(HttpStatus.OK); - } else { - return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); - } - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/api/ReloadConfigController.java b/certService/src/main/java/org/onap/aaf/certservice/api/ReloadConfigController.java deleted file mode 100644 index 14bff8dd..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/api/ReloadConfigController.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.api; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -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.aaf.certservice.certification.configuration.CmpServersConfig; -import org.onap.aaf.certservice.certification.configuration.CmpServersConfigLoadingException; -import org.onap.aaf.certservice.certification.exception.ErrorResponseModel; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@Tag(name = "CertificationService") -public final class ReloadConfigController { - - private final CmpServersConfig cmpServersConfig; - - @Autowired - public ReloadConfigController(CmpServersConfig cmpServersConfig) { - this.cmpServersConfig = cmpServersConfig; - } - - @GetMapping(value = "/reload", produces = "application/json") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Configuration has been successfully reloaded"), - @ApiResponse(responseCode = "500", description = "Something went wrong during configuration loading", - content = @Content(schema = @Schema(implementation = ErrorResponseModel.class))) - }) - @Operation( - summary = "Reload CMPv2 servers configuration from configuration file", - description = "Web endpoint for performing configuration reload. Used to reload configuration from file.", - tags = {"CertificationService"}) - public ResponseEntity reloadConfiguration() throws CmpServersConfigLoadingException { - cmpServersConfig.reloadConfiguration(); - return new ResponseEntity<>(HttpStatus.OK); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/api/advice/CertificationExceptionAdvice.java b/certService/src/main/java/org/onap/aaf/certservice/api/advice/CertificationExceptionAdvice.java deleted file mode 100644 index a40fea8f..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/api/advice/CertificationExceptionAdvice.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.api.advice; - -import org.onap.aaf.certservice.api.CertificationController; -import org.onap.aaf.certservice.certification.exception.Cmpv2ClientAdapterException; -import org.onap.aaf.certservice.certification.exception.Cmpv2ServerNotFoundException; -import org.onap.aaf.certservice.certification.exception.CsrDecryptionException; -import org.onap.aaf.certservice.certification.exception.ErrorResponseModel; -import org.onap.aaf.certservice.certification.exception.KeyDecryptionException; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -@RestControllerAdvice(assignableTypes = CertificationController.class) -public final class CertificationExceptionAdvice { - - private static final Logger LOGGER = LoggerFactory.getLogger(CertificationExceptionAdvice.class); - - @ExceptionHandler(value = CsrDecryptionException.class) - public ResponseEntity handle(CsrDecryptionException exception) { - LOGGER.error("Exception occurred during decoding certificate sign request:", exception); - return getErrorResponseEntity( - "Wrong certificate signing request (CSR) format", - HttpStatus.BAD_REQUEST - ); - } - - @ExceptionHandler(value = KeyDecryptionException.class) - public ResponseEntity handle(KeyDecryptionException exception) { - LOGGER.error("Exception occurred during decoding key:", exception); - return getErrorResponseEntity( - "Wrong key (PK) format", - HttpStatus.BAD_REQUEST - ); - } - - @ExceptionHandler(value = Cmpv2ServerNotFoundException.class) - public ResponseEntity handle(Cmpv2ServerNotFoundException exception) { - LOGGER.error("Exception occurred selecting CMPv2 server:", exception); - return getErrorResponseEntity( - "Certification authority not found for given CAName", - HttpStatus.NOT_FOUND - ); - } - - @ExceptionHandler(value = RuntimeException.class) - public ResponseEntity handle(RuntimeException exception) throws CmpClientException { - throw new CmpClientException("Runtime exception occurred calling cmp client business logic", exception); - } - - @ExceptionHandler(value = CmpClientException.class) - public ResponseEntity handle(CmpClientException exception) { - LOGGER.error("Exception occurred calling cmp client:", exception); - return getErrorResponseEntity( - "Exception occurred during call to cmp client", - HttpStatus.INTERNAL_SERVER_ERROR - ); - } - - @ExceptionHandler(value = Cmpv2ClientAdapterException.class) - public ResponseEntity handle(Cmpv2ClientAdapterException exception) { - LOGGER.error("Exception occurred parsing cmp client response:", exception); - return getErrorResponseEntity( - "Exception occurred parsing cmp client response", - HttpStatus.INTERNAL_SERVER_ERROR - ); - } - - private ResponseEntity getErrorResponseEntity(String errorMessage, HttpStatus status) { - ErrorResponseModel errorResponse = new ErrorResponseModel(errorMessage); - return new ResponseEntity<>( - errorResponse, - status - ); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/api/advice/ReloadConfigExceptionAdvice.java b/certService/src/main/java/org/onap/aaf/certservice/api/advice/ReloadConfigExceptionAdvice.java deleted file mode 100644 index 4a4073ff..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/api/advice/ReloadConfigExceptionAdvice.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.api.advice; - -import org.onap.aaf.certservice.api.ReloadConfigController; -import org.onap.aaf.certservice.certification.configuration.CmpServersConfigLoadingException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -@RestControllerAdvice(assignableTypes = ReloadConfigController.class) -public final class ReloadConfigExceptionAdvice { - - private static final Logger LOGGER = LoggerFactory.getLogger(ReloadConfigExceptionAdvice.class); - - @ExceptionHandler(value = CmpServersConfigLoadingException.class) - public ResponseEntity handle(CmpServersConfigLoadingException exception) { - LOGGER.error(exception.getMessage(), exception.getCause()); - return new ResponseEntity<>(exception.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/api/configuration/OpenApiConfig.java b/certService/src/main/java/org/onap/aaf/certservice/api/configuration/OpenApiConfig.java deleted file mode 100644 index f946598a..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/api/configuration/OpenApiConfig.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.api.configuration; - -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.info.Info; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class OpenApiConfig { - - @Bean - public OpenAPI customOpenApi() { - return new OpenAPI() - .components(new Components()) - .info( - new Info() - .title("CertService Documentation") - .description("Certification service API documentation") - .version("1.0.1") - ); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/CertificateFactoryProvider.java b/certService/src/main/java/org/onap/aaf/certservice/certification/CertificateFactoryProvider.java deleted file mode 100644 index b633f905..00000000 --- a/certService/src/main/java/org/onap/aaf/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.aaf.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/aaf/certservice/certification/CertificationData.java b/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationData.java deleted file mode 100644 index bce72977..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationData.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification; - - -final class CertificationData { - - private CertificationData() { - } - - private static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"; - private static final String END_CERTIFICATE = "-----END CERTIFICATE-----"; - - static final String EXTRA_CA_CERT = "" - + BEGIN_CERTIFICATE - + "MIIDvzCCAqcCFF5DejiyfoNfPiiMmBXulniBewBGMA0GCSqGSIb3DQEBCwUAMIGb\n" - + "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\n" - + "LUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwE\n" - + "T05BUDEVMBMGA1UEAwwMbmV3Lm9uYXAub3JnMR4wHAYJKoZIhvcNAQkBFg90ZXN0\n" - + "ZXJAb25hcC5vcmcwHhcNMjAwMjEyMDk1OTM3WhcNMjEwMjExMDk1OTM3WjCBmzEL\n" - + "MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbi1G\n" - + "cmFuY2lzY28xGTAXBgNVBAoMEExpbnV4LUZvdW5kYXRpb24xDTALBgNVBAsMBE9O\n" - + "QVAxFTATBgNVBAMMDG5ldy5vbmFwLm9yZzEeMBwGCSqGSIb3DQEJARYPdGVzdGVy\n" - + "QG9uYXAub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtF4FXeDV\n" - + "ng/inC/bTACmZnLC9IiC7PyG/vVbMxxN1bvQLRAwC/Hbl3i9zD68Vs/jPPr/SDr9\n" - + "2rgItdDdUY1V30Y3PT06F11XdEaRb+t++1NX0rDf1AqPaBZgnBmB86s1wbqHdJTr\n" - + "wEImDZ5xMPfP3fiWy/9Yw/U7iRMIi1/oI0lWuHJV0bn908shuJ6dvInpRCoDnoTX\n" - + "YP/FiDSZCFVewQcq4TigB7kRqZrDcPZWbSlqHklDMXRwbCxAiFSziuX6TBwru9Rn\n" - + "HhIeXVSgMU1ZSSopVbJGtQ4zSsU1nvTK5Bhc2UHGcAOZy1xTN5D9EEbTqh7l+Wtx\n" - + "y8ojkEXvFG8lVwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAE+bUphwHit78LK8sb\n" - + "OMjt4DiEu32KeSJOpYgPLeBeAIynaNsa7sQrpuxerGNTmQWIcw6olXI0J+OOwkik\n" - + "II7elrYtd5G1uALxXWdamNsaY0Du34moVL1YjexJ7qQ4oBUxg2tuY8NAQGDK+23I\n" - + "nCA+ZwzdTJo73TYS6sx64d/YLWkX4nHGUoMlF+xUH34csDyhpuTSzQhC2quB5N8z\n" - + "tSFdpe4z2jqx07qo2EBFxi03EQ8Q0ex6l421QM2gbs7cZQ66K0DkpPcF2+iHZnyx\n" - + "xq1lnlsWHklElF2bhyXTn3fPp5wtan00P8IolKx7CAWb92QjkW6M0RvTW/xuwIzh\n" - + "0rTO\n" - + END_CERTIFICATE; - - static final String CA_CERT = "" - + BEGIN_CERTIFICATE - + "MIIDtzCCAp8CFAwqQddh4/iyGfP8UZ3dpXlxfAN8MA0GCSqGSIb3DQEBCwUAMIGX\n" - + "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\n" - + "LUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwE\n" - + "T05BUDERMA8GA1UEAwwIb25hcC5vcmcxHjAcBgkqhkiG9w0BCQEWD3Rlc3RlckBv\n" - + "bmFwLm9yZzAeFw0yMDAyMTIwOTM0MjdaFw0yMTAyMTEwOTM0MjdaMIGXMQswCQYD\n" - + "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuLUZyYW5j\n" - + "aXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwET05BUDER\n" - + "MA8GA1UEAwwIb25hcC5vcmcxHjAcBgkqhkiG9w0BCQEWD3Rlc3RlckBvbmFwLm9y\n" - + "ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCFrnO7/eT6V+7XkPPd\n" - + "eiL/6xXreuegvit/1/jTVjG+3AOVcmTn2WXwXXRcQLvkWQfJVPoltsY8E3FqFRti\n" - + "797XjY6cdQJFVDyzNU0+Fb4vJL9FK5wSvnS6EFjBEn3JvXRlENorDCs/mfjkjJoa\n" - + "Dl74gXQEJYcg4nsTeNIj7cm3Q7VK3mZt1t7LSJJ+czxv69UJDuNJpmQ/2WOKyLZA\n" - + "gTtBJ+Hyol45/OLsrqwq1dAn9ZRWIFPvRt/XQYH9bI/6MtqSreRVUrdYCiTe/XpP\n" - + "B/OM6NEi2+p5QLi3Yi70CEbqP3HqUVbkzF+r7bwIb6M5/HxfqzLmGwLvD+6rYnUn\n" - + "Bm8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAhXoO65DXth2X/zFRNsCNpLwmDy7r\n" - + "PxT9ZAIZAzSxx3/aCYiuTrKP1JnqjkO+F2IbikrI4n6sKO49SKnRf9SWTFhd+5dX\n" - + "vxq5y7MaqxHAY9J7+Qzq33+COVFQnaF7ddel2NbyUVb2b9ZINNsaZkkPXui6DtQ7\n" - + "/Fb/1tmAGWd3hMp75G2thBSzs816JMKKa9WD+4VGATEs6OSll4sv2fOZEn+0mAD3\n" - + "9q9c+WtLGIudOwcHwzPb2njtNntQSCK/tVOqbY+vzhMY3JW+p9oSrLDSdGC+pAKK\n" - + "m/wB+2VPIYcsPMtIhHC4tgoSaiCqjXYptaOh4b8ye8CPBUCpX/AYYkN0Ow==\n" - + END_CERTIFICATE; - - static final String INTERMEDIATE_CERT = "" - + BEGIN_CERTIFICATE - + "MIIDqTCCApGgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNVBAYTAlVT\n" - + "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw\n" - + "FwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQD\n" - + "DAhvbmFwLm9yZzEeMBwGCSqGSIb3DQEJARYPdGVzdGVyQG9uYXAub3JnMB4XDTIw\n" - + "MDIxMjA5NDAxMloXDTIyMTEwODA5NDAxMlowgYQxCzAJBgNVBAYTAlVTMRMwEQYD\n" - + "VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQK\n" - + "DBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQDDBVpbnRl\n" - + "cm1lZGlhdGUub25hcC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n" - + "AQC1oOYMZ6G+2DGDAizYnzdCNiogivlht1s4oqgem7fM1XFPxD2p31ATIibOdqr/\n" - + "gv1qemO9Q4r1xn6w1Ufq7T1K7PjnMzdSeTqZefurE2JM/HHx2QvW4TjMlz2ILgaD\n" - + "L1LN60kmMQSOi5VxKJpsrCQxbOsxhvefd212gny5AZMcjJe23kUd9OxUrtvpdLEv\n" - + "wI3vFEvT7oRUnEUg/XNz7qeg33vf1C39yMR+6O4s6oevgsEebVKjb+yOoS6zzGtz\n" - + "72wZjm07C54ZlO+4Uy+QAlMjRiU3mgWkKbkOy+4CvwehjhpTikdBs2DX39ZLGHhn\n" - + "L/0a2NYtGulp9XEqmTvRoI+PAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" - + "hvcNAQELBQADggEBADcitdJ6YswiV8jAD9GK0gf3+zqcGegt4kt+79JXlXYbb1sY\n" - + "q3o6prcB7nSUoClgF2xUPCslFGpM0Er9FCSFElQM/ru0l/KVmJS6kSpwEHvsYIH3\n" - + "q5anta+Pyk8JSQWAAw+qrind0uBQMnhR8Tn13tgV+Kjvg/xlH/nZIEdN5YtLB1cA\n" - + "beVsZRyRfVL9DeZU8s/MZ5wC3kgcEp5A4m5lg7HyBxBdqhzFcDr6xiy6OGqW8Yep\n" - + "xrwfc8Fw8a/lOv4U+tBeGNKPQDYaL9hh+oM+qMkNXsHXDqdJsuEGJtU4i3Wcwzoc\n" - + "XGN5NWV//4bP+NFmwgcn7AYCdRvz04A8GU/0Cwg=\n" - + END_CERTIFICATE; - - static final String ENTITY_CERT = "" - + BEGIN_CERTIFICATE - + "MIIDjDCCAnSgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwgYQxCzAJBgNVBAYTAlVT\n" - + "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw\n" - + "FwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQD\n" - + "DBVpbnRlcm1lZGlhdGUub25hcC5vcmcwHhcNMjAwMjEyMDk1MTI2WhcNMjIxMTA4\n" - + "MDk1MTI2WjB7MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG\n" - + "A1UEBwwNU2FuLUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjEN\n" - + "MAsGA1UECwwET05BUDEVMBMGA1UEAwwMdmlkLm9uYXAub3JnMIIBIjANBgkqhkiG\n" - + "9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+GIRzJzUOh0gtc+wzFJEdTnn+q5F10L0Yhr\n" - + "G1xKdjPieHIFGsoiXwcuCU8arNSqlz7ocx62KQRkcA8y6edlOAsYtdOEJvqEI9vc\n" - + "eyTB/HYsbzw3URPGch4AmibrQkKU9QvGwouHtHn4R2Ft2Y0tfEqv9hxj9v4njq4A\n" - + "EiDLAFLl5FmVyCZu/MtKngSgu1smcaFKTYySPMxytgJZexoa/ALZyyE0gRhsvwHm\n" - + "NLGCPt1bmE/PEGZybsCqliyTO0S56ncD55The7+D/UDS4kE1Wg0svlWon/YsE6QW\n" - + "B3oeJDX7Kr8ebDTIAErevIAD7Sm4ee5se2zxYrsYlj0MzHZtvwIDAQABoxAwDjAM\n" - + "BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCvQ1pTvjON6vSlcJRKSY4r\n" - + "8q7L4/9ZaVXWJAjzEYJtPIqsgGiPWz0vGfgklowU6tZxp9zRZFXfMil+mPQSe+yo\n" - + "ULrZSQ/z48YHPueE/BNO/nT4aaVBEhPLR5aVwC7uQVX8H+m1V1UGT8lk9vdI9rej\n" - + "CI9l524sLCpdE4dFXiWK2XHEZ0Vfylk221u3IYEogVVA+UMX7BFPSsOnI2vtYK/i\n" - + "lwZtlri8LtTusNe4oiTkYyq+RSyDhtAswg8ANgvfHolhCHoLFj6w1IkG88UCmbwN\n" - + "d7BoGMy06y5MJxyXEZG0vR7eNeLey0TIh+rAszAFPsIQvrOHW+HuA+WLQAj1mhnm\n" - + END_CERTIFICATE; - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationModelFactory.java b/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationModelFactory.java deleted file mode 100644 index 631d56ef..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationModelFactory.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification; - -import org.onap.aaf.certservice.certification.configuration.Cmpv2ServerProvider; -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.onap.aaf.certservice.certification.exception.DecryptionException; -import org.onap.aaf.certservice.certification.model.CertificationModel; -import org.onap.aaf.certservice.certification.model.CsrModel; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class CertificationModelFactory { - - private static final Logger LOGGER = LoggerFactory.getLogger(CertificationModelFactory.class); - - private final CsrModelFactory csrModelFactory; - private final Cmpv2ServerProvider cmpv2ServerProvider; - private final CertificationProvider certificationProvider; - - @Autowired - CertificationModelFactory( - CsrModelFactory csrModelFactory, - Cmpv2ServerProvider cmpv2ServerProvider, - CertificationProvider certificationProvider - ) { - this.cmpv2ServerProvider = cmpv2ServerProvider; - this.csrModelFactory = csrModelFactory; - this.certificationProvider = certificationProvider; - } - - public CertificationModel createCertificationModel(String encodedCsr, String encodedPrivateKey, String caName) - throws DecryptionException, CmpClientException { - CsrModel csrModel = csrModelFactory.createCsrModel( - new CsrModelFactory.StringBase64(encodedCsr), - new CsrModelFactory.StringBase64(encodedPrivateKey) - ); - LOGGER.debug("Received CSR meta data: \n{}", csrModel); - - Cmpv2Server cmpv2Server = cmpv2ServerProvider.getCmpv2Server(caName); - LOGGER.debug("Found server for given CA name: \n{}", cmpv2Server); - - LOGGER.info("Sending sign request for certification model for CA named: {}, and certificate signing request:\n{}", - caName, csrModel); - return certificationProvider.signCsr(csrModel, cmpv2Server); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationProvider.java b/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationProvider.java deleted file mode 100644 index 2478cc58..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationProvider.java +++ /dev/null @@ -1,78 +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.aaf.certservice.certification; - -import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator; -import org.bouncycastle.util.io.pem.PemObjectGenerator; -import org.bouncycastle.util.io.pem.PemWriter; -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.onap.aaf.certservice.certification.model.CertificationModel; -import org.onap.aaf.certservice.certification.model.CsrModel; -import org.onap.aaf.certservice.cmpv2client.api.CmpClient; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.onap.aaf.certservice.cmpv2client.model.Cmpv2CertificationModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.io.IOException; -import java.io.StringWriter; -import java.security.cert.X509Certificate; -import java.util.List; -import java.util.stream.Collectors; - -@Service -public class CertificationProvider { - - private static final Logger LOGGER = LoggerFactory.getLogger(CertificationProvider.class); - - private final CmpClient cmpClient; - - @Autowired - public CertificationProvider(CmpClient cmpClient) { - this.cmpClient = cmpClient; - } - - public CertificationModel signCsr(CsrModel csrModel, Cmpv2Server server) - throws CmpClientException { - Cmpv2CertificationModel certificates = cmpClient.createCertificate(csrModel, server); - return new CertificationModel(convertFromX509CertificateListToPemList(certificates.getCertificateChain()), - convertFromX509CertificateListToPemList(certificates.getTrustedCertificates())); - } - - private static List convertFromX509CertificateListToPemList(List certificates) { - return certificates.stream().map(CertificationProvider::convertFromX509CertificateToPem).filter(cert -> !cert.isEmpty()) - .collect(Collectors.toList()); - } - - private static String convertFromX509CertificateToPem(X509Certificate certificate) { - StringWriter sw = new StringWriter(); - try (PemWriter pw = new PemWriter(sw)) { - PemObjectGenerator gen = new JcaMiscPEMGenerator(certificate); - pw.writeObject(gen); - } catch (IOException e) { - LOGGER.error("Exception occurred during convert of X509 certificate", e); - } - return sw.toString(); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java b/certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java deleted file mode 100644 index b4f94b93..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification; - -import java.util.Base64; -import java.util.Objects; -import java.util.Optional; - -import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.bouncycastle.util.io.pem.PemObject; -import org.onap.aaf.certservice.certification.exception.CsrDecryptionException; -import org.onap.aaf.certservice.certification.exception.DecryptionException; -import org.onap.aaf.certservice.certification.exception.KeyDecryptionException; -import org.onap.aaf.certservice.certification.model.CsrModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - - -@Service -public class CsrModelFactory { - - private final PemObjectFactory pemObjectFactory - = new PemObjectFactory(); - private final Pkcs10CertificationRequestFactory certificationRequestFactory - = new Pkcs10CertificationRequestFactory(); - - - public CsrModel createCsrModel(StringBase64 csr, StringBase64 privateKey) - throws DecryptionException { - PKCS10CertificationRequest decodedCsr = decodeCsr(csr); - PemObject decodedPrivateKey = decodePrivateKey(privateKey); - return new CsrModel.CsrModelBuilder(decodedCsr, decodedPrivateKey).build(); - } - - private PemObject decodePrivateKey(StringBase64 privateKey) - throws KeyDecryptionException { - - return privateKey.asString() - .flatMap(pemObjectFactory::createPemObject) - .orElseThrow( - () -> new KeyDecryptionException("Incorrect Key, decryption failed") - ); - } - - private PKCS10CertificationRequest decodeCsr(StringBase64 csr) - throws CsrDecryptionException { - return csr.asString() - .flatMap(pemObjectFactory::createPemObject) - .flatMap(certificationRequestFactory::createPkcs10CertificationRequest) - .orElseThrow( - () -> new CsrDecryptionException("Incorrect CSR, decryption failed") - ); - } - - public static class StringBase64 { - private final String value; - private final Base64.Decoder decoder = Base64.getDecoder(); - private static final Logger LOGGER = LoggerFactory.getLogger(StringBase64.class); - - public StringBase64(String value) { - this.value = value; - } - - public Optional asString() { - try { - String decodedString = new String(decoder.decode(value)); - return Optional.of(decodedString); - } catch (RuntimeException e) { - LOGGER.error("Exception occurred during decoding:", e); - return Optional.empty(); - } - } - - @Override - public boolean equals(Object otherObject) { - if (this == otherObject) { - return true; - } - if (otherObject == null || getClass() != otherObject.getClass()) { - return false; - } - StringBase64 that = (StringBase64) otherObject; - return Objects.equals(value, that.value); - } - - @Override - public int hashCode() { - return value.hashCode(); - } - } - -} - - diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/PemObjectFactory.java b/certService/src/main/java/org/onap/aaf/certservice/certification/PemObjectFactory.java deleted file mode 100644 index 1eb5270f..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/PemObjectFactory.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification; - -import java.io.IOException; -import java.io.StringReader; -import java.util.Optional; - -import org.bouncycastle.util.encoders.DecoderException; -import org.bouncycastle.util.io.pem.PemObject; -import org.bouncycastle.util.io.pem.PemReader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class PemObjectFactory { - - private static final Logger LOGGER = LoggerFactory.getLogger(PemObjectFactory.class); - - public Optional createPemObject(String pem) { - - try (StringReader stringReader = new StringReader(pem); - PemReader pemReader = new PemReader(stringReader)) { - return Optional.ofNullable(pemReader.readPemObject()); - } catch (DecoderException | IOException e) { - LOGGER.error("Exception occurred during creation of PEM:", e); - return Optional.empty(); - } - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/Pkcs10CertificationRequestFactory.java b/certService/src/main/java/org/onap/aaf/certservice/certification/Pkcs10CertificationRequestFactory.java deleted file mode 100644 index 1b00a815..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/Pkcs10CertificationRequestFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification; - -import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.bouncycastle.util.encoders.DecoderException; -import org.bouncycastle.util.io.pem.PemObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.Optional; - -public class Pkcs10CertificationRequestFactory { - - private static final Logger LOGGER = LoggerFactory.getLogger(Pkcs10CertificationRequestFactory.class); - - public Optional createPkcs10CertificationRequest(PemObject pemObject) { - try { - LOGGER.debug("Creating certification request from pem object"); - return Optional.of(new PKCS10CertificationRequest(pemObject.getContent())); - } catch (DecoderException | IOException e) { - LOGGER.error("Exception occurred during creation of certification request:", e); - return Optional.empty(); - } - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/RsaContentSignerBuilder.java b/certService/src/main/java/org/onap/aaf/certservice/certification/RsaContentSignerBuilder.java deleted file mode 100644 index 12f00f9c..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/RsaContentSignerBuilder.java +++ /dev/null @@ -1,46 +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.aaf.certservice.certification; - -import java.io.IOException; -import java.security.PrivateKey; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.crypto.util.PrivateKeyFactory; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder; -import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.springframework.stereotype.Component; - -@Component -public class RsaContentSignerBuilder { - - ContentSigner build(PKCS10CertificationRequest csr, PrivateKey privateKey) - throws IOException, OperatorCreationException { - AlgorithmIdentifier sigAlgId = csr.getSignatureAlgorithm(); - AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId); - - return new BcRSAContentSignerBuilder(sigAlgId, digAlgId) - .build(PrivateKeyFactory.createKey(privateKey.getEncoded())); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/X509CertificateBuilder.java b/certService/src/main/java/org/onap/aaf/certservice/certification/X509CertificateBuilder.java deleted file mode 100644 index 5b24c653..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/X509CertificateBuilder.java +++ /dev/null @@ -1,56 +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.aaf.certservice.certification; - -import java.io.IOException; -import java.math.BigInteger; -import java.security.SecureRandom; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.Date; -import org.bouncycastle.asn1.ASN1Sequence; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.cert.X509v3CertificateBuilder; -import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.springframework.stereotype.Component; - -@Component -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 { - 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)), - new PKCS10CertificationRequest(csr.getEncoded()).getSubject(), - SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(csr.getSubjectPublicKeyInfo().getEncoded()))); - - } - - private BigInteger createSerial() { - byte[] serial = new byte[SECURE_NEXT_BYTES]; - new SecureRandom().nextBytes(serial); - return new BigInteger(serial).abs(); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpClientConfig.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpClientConfig.java deleted file mode 100644 index 329098ac..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpClientConfig.java +++ /dev/null @@ -1,50 +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.aaf.certservice.certification.configuration; - -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.onap.aaf.certservice.cmpv2client.api.CmpClient; -import org.onap.aaf.certservice.cmpv2client.impl.CmpClientImpl; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.context.annotation.RequestScope; - -@Configuration -public class CmpClientConfig { - - @Bean - CmpClient cmpClient(CloseableHttpClient closeableHttpClient) { - return new CmpClientImpl(closeableHttpClient); - } - - @Bean - @RequestScope - CloseableHttpClient closeableHttpClient(HttpClientBuilder httpClientBuilder) { - return httpClientBuilder.build(); - } - - @Bean - HttpClientBuilder httpClientBuilder() { - return HttpClientBuilder.create(); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfig.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfig.java deleted file mode 100644 index cea228c1..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfig.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration; - -import java.io.File; -import java.util.Collections; -import java.util.List; -import javax.annotation.PostConstruct; -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class CmpServersConfig { - - private static final Logger LOGGER = LoggerFactory.getLogger(CmpServersConfig.class); - private static final String INIT_CONFIGURATION = "Loading initial configuration"; - private static final String RELOADING_CONFIGURATION = "Reloading configuration"; - private static final String LOADING_SUCCESS_MESSAGE = "CMP Servers configuration successfully loaded from file {}"; - private static final String CMP_SERVERS_CONFIG_FILENAME = "cmpServers.json"; - - private final String configPath; - private final CmpServersConfigLoader cmpServersConfigLoader; - - private List cmpServers; - private volatile boolean isReady; - - @Autowired - public CmpServersConfig(@Value("${app.config.path}") String configPath, - CmpServersConfigLoader cmpServersConfigLoader) { - this.cmpServersConfigLoader = cmpServersConfigLoader; - this.configPath = configPath; - } - - @PostConstruct - void init() { - try { - LOGGER.info(INIT_CONFIGURATION); - loadConfiguration(); - } catch (CmpServersConfigLoadingException e) { - LOGGER.error(e.getMessage(), e.getCause()); - } - } - - public void reloadConfiguration() throws CmpServersConfigLoadingException { - LOGGER.info(RELOADING_CONFIGURATION); - loadConfiguration(); - } - - - synchronized void loadConfiguration() throws CmpServersConfigLoadingException { - isReady = false; - String configFilePath = configPath + File.separator + CMP_SERVERS_CONFIG_FILENAME; - this.cmpServers = Collections.unmodifiableList(cmpServersConfigLoader.load(configFilePath)); - LOGGER.info(LOADING_SUCCESS_MESSAGE, configFilePath); - isReady = true; - } - - public List getCmpServers() { - return cmpServers; - } - - public boolean isReady() { - return isReady; - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoader.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoader.java deleted file mode 100644 index 101712e2..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoader.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.File; -import java.io.IOException; -import java.security.InvalidParameterException; -import java.util.List; - -import org.onap.aaf.certservice.certification.configuration.model.CmpServers; -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.onap.aaf.certservice.certification.configuration.validation.Cmpv2ServersConfigurationValidator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -class CmpServersConfigLoader { - - private static final String LOADING_EXCEPTION_MESSAGE = "Exception occurred during CMP Servers configuration loading"; - private static final String VALIDATION_EXCEPTION_MESSAGE = "Validation of CMPv2 servers configuration failed"; - - private final Cmpv2ServersConfigurationValidator validator; - - @Autowired - CmpServersConfigLoader(Cmpv2ServersConfigurationValidator validator) { - this.validator = validator; - } - - List load(String path) throws CmpServersConfigLoadingException { - try { - List servers = loadConfigFromFile(path).getCmpv2Servers(); - validator.validate(servers); - return servers; - } catch (IOException e) { - throw new CmpServersConfigLoadingException(LOADING_EXCEPTION_MESSAGE, e); - } catch (InvalidParameterException e) { - throw new CmpServersConfigLoadingException(VALIDATION_EXCEPTION_MESSAGE, e); - } - } - - private CmpServers loadConfigFromFile(String path) throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(new File(path), CmpServers.class); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoadingException.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoadingException.java deleted file mode 100644 index b7c3638d..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoadingException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration; - -public class CmpServersConfigLoadingException extends Exception { - - public CmpServersConfigLoadingException(String message) { - super(message); - } - - public CmpServersConfigLoadingException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/Cmpv2ServerProvider.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/Cmpv2ServerProvider.java deleted file mode 100644 index 190bb28a..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/Cmpv2ServerProvider.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration; - -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.onap.aaf.certservice.certification.exception.Cmpv2ServerNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class Cmpv2ServerProvider { - - private final CmpServersConfig cmpServersConfig; - - @Autowired - Cmpv2ServerProvider(CmpServersConfig cmpServersConfig) { - this.cmpServersConfig = cmpServersConfig; - } - - public Cmpv2Server getCmpv2Server(String caName) { - return cmpServersConfig.getCmpServers().stream().filter(server -> server.getCaName().equals(caName)).findFirst() - .orElseThrow(() -> new Cmpv2ServerNotFoundException("No server found for given CA name")); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/Authentication.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/Authentication.java deleted file mode 100644 index e4c15518..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/Authentication.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration.model; - -import javax.validation.constraints.NotNull; -import org.hibernate.validator.constraints.Length; - -public class Authentication { - - private static final int MAX_IAK_RV_LENGTH = 256; - - @NotNull - @Length(min = 1, max = MAX_IAK_RV_LENGTH) - private String iak; - @NotNull - @Length(min = 1, max = MAX_IAK_RV_LENGTH) - private String rv; - - public String getIak() { - return iak; - } - - public void setIak(String iak) { - this.iak = iak; - } - - public String getRv() { - return rv; - } - - public void setRv(String rv) { - this.rv = rv; - } - - @Override - public String toString() { - return "Authentication{" - + " iak=*****" - + ", rv=*****" - + '}'; - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/CaMode.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/CaMode.java deleted file mode 100644 index 374feb3b..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/CaMode.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration.model; - -public enum CaMode { - RA("RA"), CLIENT("Client"); - - private String profile; - - CaMode(String profile) { - this.profile = profile; - } - - public String getProfile() { - return profile; - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/CmpServers.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/CmpServers.java deleted file mode 100644 index 7fac1887..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/CmpServers.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration.model; - -import java.util.List; - -public class CmpServers { - - private List cmpv2Servers; - - public List getCmpv2Servers() { - return cmpv2Servers; - } - - public void setCmpv2Servers(List cmpv2Servers) { - this.cmpv2Servers = cmpv2Servers; - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/Cmpv2Server.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/Cmpv2Server.java deleted file mode 100644 index 51d91966..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/Cmpv2Server.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration.model; - -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - -import org.bouncycastle.asn1.x500.X500Name; -import org.hibernate.validator.constraints.Length; -import org.onap.aaf.certservice.certification.configuration.validation.constraints.Cmpv2Url; - -public class Cmpv2Server { - - private static final int MAX_CA_NAME_LENGTH = 128; - - @NotNull - @Valid - private Authentication authentication; - @NotNull - private CaMode caMode; - @NotNull - @Length(min = 1, max = MAX_CA_NAME_LENGTH) - private String caName; - @NotNull - private X500Name issuerDN; - @Cmpv2Url - private String url; - - public Authentication getAuthentication() { - return authentication; - } - - public void setAuthentication(Authentication authentication) { - this.authentication = authentication; - } - - public CaMode getCaMode() { - return caMode; - } - - public void setCaMode(CaMode caMode) { - this.caMode = caMode; - } - - public String getCaName() { - return caName; - } - - public void setCaName(String caName) { - this.caName = caName; - } - - public X500Name getIssuerDN() { - return issuerDN; - } - - public void setIssuerDN(X500Name issuerDN) { - this.issuerDN = issuerDN; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - @Override - public String toString() { - return "Cmpv2Server{" - + "authentication=" + authentication - + ", caMode=" + caMode - + ", caName='" + caName + '\'' - + ", issuerDN='" + issuerDN + '\'' - + ", url='" + url + '\'' - + '}'; - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidator.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidator.java deleted file mode 100644 index 3cf7fdf7..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidator.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration.validation; - -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.validation.ConstraintViolation; -import javax.validation.Validator; -import java.security.InvalidParameterException; -import java.util.List; -import java.util.Set; - -@Service -public class Cmpv2ServersConfigurationValidator { - - private final Validator validator; - - @Autowired - public Cmpv2ServersConfigurationValidator(Validator validator) { - this.validator = validator; - } - - public void validate(List servers) { - servers.forEach(this::validateServer); - validateUniqueCaNames(servers); - } - - private void validateServer(Cmpv2Server serverDetails) { - Set> violations = validator.validate(serverDetails); - if (!violations.isEmpty()) { - throw new InvalidParameterException(violations.toString()); - } - } - - private void validateUniqueCaNames(List servers) { - long distinctCAs = getNumberOfUniqueCaNames(servers); - if (servers.size() != distinctCAs) { - throw new InvalidParameterException("CA names are not unique within given CMPv2 servers"); - } - } - - private long getNumberOfUniqueCaNames(List servers) { - return servers.stream().map(Cmpv2Server::getCaName) - .distinct() - .count(); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2Url.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2Url.java deleted file mode 100644 index a5450a25..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2Url.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration.validation.constraints; - -import javax.validation.Constraint; -import javax.validation.Payload; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -@Target({FIELD, ANNOTATION_TYPE}) -@Retention(RUNTIME) -@Constraint(validatedBy = Cmpv2UrlValidator.class) -public @interface Cmpv2Url { - String message() default "Server URL is invalid."; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidator.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidator.java deleted file mode 100644 index 7ce3bb6c..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidator.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration.validation.constraints; - -import org.onap.aaf.certservice.certification.configuration.validation.constraints.violations.PortNumberViolation; -import org.onap.aaf.certservice.certification.configuration.validation.constraints.violations.RequestTypeViolation; -import org.onap.aaf.certservice.certification.configuration.validation.constraints.violations.UrlServerViolation; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -class Cmpv2UrlValidator implements ConstraintValidator { - - private final List violations; - - Cmpv2UrlValidator() { - this.violations = Arrays.asList( - new PortNumberViolation(), - new RequestTypeViolation() - ); - } - - @Override - public boolean isValid(String url, ConstraintValidatorContext context) { - AtomicBoolean isValid = new AtomicBoolean(true); - violations.forEach(violation -> { - if (!violation.validate(url)) { - isValid.set(false); - } - }); - return isValid.get(); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/PortNumberViolation.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/PortNumberViolation.java deleted file mode 100644 index 96f30149..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/PortNumberViolation.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration.validation.constraints.violations; - -import java.net.MalformedURLException; -import java.net.URL; - -public class PortNumberViolation implements UrlServerViolation { - - private static final int MIN_PORT = 1; - private static final int MAX_PORT = 65535; - private static final int PORT_UNDEFINED = -1; - - @Override - public boolean validate(String serverUrl) { - try { - URL url = new URL(serverUrl); - int port = url.getPort(); - return port >= MIN_PORT && port <= MAX_PORT || port == PORT_UNDEFINED; - } catch (MalformedURLException e) { - return false; - } - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolation.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolation.java deleted file mode 100644 index 67a5c3c4..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolation.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration.validation.constraints.violations; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -public class RequestTypeViolation implements UrlServerViolation { - - private static final List VALID_REQUESTS = Collections.singletonList("http"); - - @Override - public boolean validate(String serverUrl) { - try { - AtomicBoolean isValid = new AtomicBoolean(false); - String protocol = new URL(serverUrl).getProtocol(); - VALID_REQUESTS.forEach(requestType -> { - if (protocol.equals(requestType)) { - isValid.set(true); - } - }); - return isValid.get(); - } catch (MalformedURLException e) { - return false; - } - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/UrlServerViolation.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/UrlServerViolation.java deleted file mode 100644 index 5452beb4..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/UrlServerViolation.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.configuration.validation.constraints.violations; - -public interface UrlServerViolation { - boolean validate(String url); -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/Cmpv2ClientAdapterException.java b/certService/src/main/java/org/onap/aaf/certservice/certification/exception/Cmpv2ClientAdapterException.java deleted file mode 100644 index 1b26da7b..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/Cmpv2ClientAdapterException.java +++ /dev/null @@ -1,28 +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.aaf.certservice.certification.exception; - -public class Cmpv2ClientAdapterException extends Exception { - - public Cmpv2ClientAdapterException(Throwable cause) { - super(cause); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/Cmpv2ServerNotFoundException.java b/certService/src/main/java/org/onap/aaf/certservice/certification/exception/Cmpv2ServerNotFoundException.java deleted file mode 100644 index 35acb0cd..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/Cmpv2ServerNotFoundException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.exception; - -public class Cmpv2ServerNotFoundException extends RuntimeException { - public Cmpv2ServerNotFoundException(String message) { - super(message); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/CsrDecryptionException.java b/certService/src/main/java/org/onap/aaf/certservice/certification/exception/CsrDecryptionException.java deleted file mode 100644 index ed434e07..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/CsrDecryptionException.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.exception; - -public class CsrDecryptionException extends DecryptionException { - public CsrDecryptionException(String message, Throwable cause) { - super(message, cause); - } - - public CsrDecryptionException(String message) { - super(message); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/DecryptionException.java b/certService/src/main/java/org/onap/aaf/certservice/certification/exception/DecryptionException.java deleted file mode 100644 index 6d8f7073..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/DecryptionException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.exception; - -public class DecryptionException extends Exception { - - public DecryptionException(String message, Throwable cause) { - super(message, cause); - } - - public DecryptionException(String message) { - super(message); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/ErrorResponseModel.java b/certService/src/main/java/org/onap/aaf/certservice/certification/exception/ErrorResponseModel.java deleted file mode 100644 index 8899f77c..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/ErrorResponseModel.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.exception; - -public class ErrorResponseModel { - - private final String errorMessage; - - public ErrorResponseModel(String errorMessage) { - this.errorMessage = errorMessage; - } - - public String getErrorMessage() { - return errorMessage; - } - -} - diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/KeyDecryptionException.java b/certService/src/main/java/org/onap/aaf/certservice/certification/exception/KeyDecryptionException.java deleted file mode 100644 index d4814d6a..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/exception/KeyDecryptionException.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.exception; - -public class KeyDecryptionException extends DecryptionException { - public KeyDecryptionException(String message, Throwable cause) { - super(message, cause); - } - - public KeyDecryptionException(String message) { - super(message); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/model/CertificationModel.java b/certService/src/main/java/org/onap/aaf/certservice/certification/model/CertificationModel.java deleted file mode 100644 index b851d0d9..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/model/CertificationModel.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.model; - -import java.util.Collections; -import java.util.List; - -public class CertificationModel { - - private final List certificateChain; - private final List trustedCertificates; - - public CertificationModel(List certificateChain, List trustedCertificates) { - this.certificateChain = certificateChain; - this.trustedCertificates = trustedCertificates; - } - - public List getCertificateChain() { - return Collections.unmodifiableList(certificateChain); - } - - public List getTrustedCertificates() { - return Collections.unmodifiableList(trustedCertificates); - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/model/CsrModel.java b/certService/src/main/java/org/onap/aaf/certservice/certification/model/CsrModel.java deleted file mode 100644 index d81da10a..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/model/CsrModel.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * 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.aaf.certservice.certification.model; - -import java.io.IOException; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.Extension; -import org.bouncycastle.asn1.x509.Extensions; -import org.bouncycastle.asn1.x509.GeneralName; -import org.bouncycastle.asn1.x509.GeneralNames; -import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.bouncycastle.util.io.pem.PemObject; - -import org.onap.aaf.certservice.certification.exception.CsrDecryptionException; -import org.onap.aaf.certservice.certification.exception.DecryptionException; -import org.onap.aaf.certservice.certification.exception.KeyDecryptionException; - - -public class CsrModel { - - private final PKCS10CertificationRequest csr; - private final X500Name subjectData; - private final PrivateKey privateKey; - private final PublicKey publicKey; - private final List sans; - - public CsrModel(PKCS10CertificationRequest csr, X500Name subjectData, PrivateKey privateKey, PublicKey publicKey, - List sans) { - this.csr = csr; - this.subjectData = subjectData; - this.privateKey = privateKey; - this.publicKey = publicKey; - this.sans = sans; - } - - public PKCS10CertificationRequest getCsr() { - return csr; - } - - public X500Name getSubjectData() { - return subjectData; - } - - public PrivateKey getPrivateKey() { - return privateKey; - } - - public PublicKey getPublicKey() { - return publicKey; - } - - public List getSans() { - return sans; - } - - @Override - public String toString() { - return "Subject: { " + subjectData + " ,SANs: " + sans + " }"; - } - - public static class CsrModelBuilder { - - private final PKCS10CertificationRequest csr; - private final PemObject privateKey; - - public CsrModel build() throws DecryptionException { - - X500Name subjectData = getSubjectData(); - PrivateKey javaPrivateKey = convertingPemPrivateKeyToJavaSecurityPrivateKey(getPrivateKey()); - PublicKey javaPublicKey = convertingPemPublicKeyToJavaSecurityPublicKey(getPublicKey()); - List sans = getSansData(); - - return new CsrModel(csr, subjectData, javaPrivateKey, javaPublicKey, sans); - } - - public CsrModelBuilder(PKCS10CertificationRequest csr, PemObject privateKey) { - this.csr = csr; - this.privateKey = privateKey; - } - - private PemObject getPublicKey() throws CsrDecryptionException { - try { - return new PemObject("PUBLIC KEY", csr.getSubjectPublicKeyInfo().getEncoded()); - } catch (IOException e) { - throw new CsrDecryptionException("Reading Public Key from CSR failed", e.getCause()); - } - } - - private PemObject getPrivateKey() { - return privateKey; - } - - private X500Name getSubjectData() { - return csr.getSubject(); - } - - private List getSansData() { - if (!isAttrsEmpty() && !isAttrsValuesEmpty()) { - Extensions extensions = Extensions.getInstance(csr.getAttributes()[0].getAttrValues().getObjectAt(0)); - GeneralName[] arrayOfAlternativeNames = - GeneralNames.fromExtensions(extensions, Extension.subjectAlternativeName).getNames(); - return Arrays.stream(arrayOfAlternativeNames).map(GeneralName::getName).map(Objects::toString) - .collect(Collectors.toList()); - } - return Collections.emptyList(); - } - - private boolean isAttrsValuesEmpty() { - return csr.getAttributes()[0].getAttrValues().size() == 0; - } - - private boolean isAttrsEmpty() { - return csr.getAttributes().length == 0; - } - - private PrivateKey convertingPemPrivateKeyToJavaSecurityPrivateKey(PemObject privateKey) - throws KeyDecryptionException { - try { - KeyFactory factory = KeyFactory.getInstance("RSA"); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey.getContent()); - return factory.generatePrivate(keySpec); - } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { - throw new KeyDecryptionException("Converting Private Key failed", e.getCause()); - } - } - - private PublicKey convertingPemPublicKeyToJavaSecurityPublicKey(PemObject publicKey) - throws KeyDecryptionException { - try { - KeyFactory factory = KeyFactory.getInstance("RSA"); - X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey.getContent()); - return factory.generatePublic(keySpec); - } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { - throw new KeyDecryptionException("Converting Public Key from CSR failed", e.getCause()); - } - } - } - -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/api/CmpClient.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/api/CmpClient.java deleted file mode 100644 index cccb744d..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/api/CmpClient.java +++ /dev/null @@ -1,74 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.api; - -import java.util.Date; - -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.onap.aaf.certservice.certification.model.CsrModel; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.onap.aaf.certservice.cmpv2client.model.Cmpv2CertificationModel; - -/** - * This class represent CmpV2Client Interface for obtaining X.509 Digital Certificates in a Public - * Key Infrastructure (PKI), making use of Certificate Management Protocol (CMPv2) operating on - * newest version: cmp2000(2). - */ -public interface CmpClient { - - /** - * Requests for a External Root CA Certificate to be created for the passed public keyPair wrapped - * in a CSRMeta with common details, accepts self-signed certificate. 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 server CMPv2 Server. Must not be {@code null}. - * @param notBefore An optional validity to set in the created certificate, Certificate not valid - * before this date. - * @param notAfter An optional validity to set in the created certificate, Certificate not valid - * after this date. - * @return model for certification containing certificate chain and trusted certificates - * @throws CmpClientException if client error occurs. - */ - Cmpv2CertificationModel createCertificate( - CsrModel csrModel, - Cmpv2Server server, - Date notBefore, - Date notAfter) - throws CmpClientException; - - /** - * Requests for a External Root CA Certificate to be created for the passed public keyPair wrapped - * in a CSRMeta with common details, accepts self-signed certificate. 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 server CMPv2 server. Must not be {@code null}. - * @return model for certification containing certificate chain and trusted certificates - * @throws CmpClientException if client error occurs. - */ - Cmpv2CertificationModel createCertificate( - CsrModel csrModel, - Cmpv2Server server) - throws CmpClientException; -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/exceptions/CmpClientException.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/exceptions/CmpClientException.java deleted file mode 100644 index 2a04306a..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/exceptions/CmpClientException.java +++ /dev/null @@ -1,50 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.exceptions; - -/** - * The CmpClientException wraps all exceptions occur internally to Cmpv2Client Api code. - */ -public class CmpClientException extends Exception { - - private static final long serialVersionUID = 1L; - - /** - * Creates a new instance with detail message. - */ - public CmpClientException(String message) { - super(message); - } - - /** - * Creates a new instance with detail Throwable cause. - */ - public CmpClientException(Throwable cause) { - super(cause); - } - - /** - * Creates a new instance with detail message and Throwable cause. - */ - public CmpClientException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/exceptions/PkiErrorException.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/exceptions/PkiErrorException.java deleted file mode 100644 index 62411fbd..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/exceptions/PkiErrorException.java +++ /dev/null @@ -1,47 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.exceptions; - -public class PkiErrorException extends Exception { - - private static final long serialVersionUID = 1L; - - /** - * Creates a new instance with detail message. - */ - public PkiErrorException(String message) { - super(message); - } - - /** - * Creates a new instance with detail Throwable cause. - */ - public PkiErrorException(Throwable cause) { - super(cause); - } - - /** - * Creates a new instance with detail message and Throwable cause. - */ - public PkiErrorException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/external/Factory.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/external/Factory.java deleted file mode 100644 index 9e95ab2f..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/external/Factory.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ============LICENSE_START==================================================== - * org.onap.aaf - * =========================================================================== - * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. - * - * Modifications Copyright (C) 2019 IBM. - * =========================================================================== - * 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.aaf.certservice.cmpv2client.external; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - -public final class Factory { - - private static final Logger LOGGER = LoggerFactory.getLogger(Factory.class); - private static final KeyPairGenerator KEY_PAIR_GENERATOR; - private static final SecureRandom SECURE_RANDOM; - private static final String KEY_ALGORITHM = "RSA"; - private static final int KEY_LENGTH = 2048; - - static { - SECURE_RANDOM = new SecureRandom(); - KeyPairGenerator tempKeygen; - try { - tempKeygen = KeyPairGenerator.getInstance(KEY_ALGORITHM); - tempKeygen.initialize(KEY_LENGTH, SECURE_RANDOM); - } catch (NoSuchAlgorithmException e) { - tempKeygen = null; - LOGGER.error("Given KEY_ALGORITHM is invalid.", e); - } - KEY_PAIR_GENERATOR = tempKeygen; - } - - private Factory() { - } - - public static KeyPair generateKeyPair() { - return KEY_PAIR_GENERATOR.generateKeyPair(); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/external/Rdn.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/external/Rdn.java deleted file mode 100644 index 25017b8a..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/external/Rdn.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * ============LICENSE_START==================================================== - * org.onap.aaf - * =========================================================================== - * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. - * - * Modifications Copyright (C) 2019 IBM. - * =========================================================================== - * 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.aaf.certservice.cmpv2client.external; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.x500.style.BCStyle; -import org.bouncycastle.cert.CertException; - -public class Rdn { - - private String tag; - private String value; - private ASN1ObjectIdentifier aoi; - - public String getValue() { - return value; - } - - public Rdn(final String tag, final String value) throws CertException { - this.tag = tag; - this.value = value; - this.aoi = getAoi(tag); - } - - public Rdn(final String tagValue) throws CertException { - List tv = parseRdn("=", tagValue); - this.tag = tv.get(0); - this.value = tv.get(1); - this.aoi = getAoi(this.tag); - } - - /** - * Splits RDN as string by given delimiter, then trims every part. - * - * @param splitBy Delimiter which splits value - * @param value Value to be splitted - * @return List of splitted and trimmed strings - */ - static List parseRdn(String splitBy, String value) { - String[] splitted = value.split(splitBy); - return Arrays.stream(splitted) - .map(String::trim) - .collect(Collectors.toList()); - } - /** - * Parse various forms of DNs into appropriate RDNs, which have the ASN1ObjectIdentifier - * - * @param delim - * @param dnString - * @return - * @throws CertException - */ - - public static List parse(final char delim, final String dnString) throws CertException { - List lrnd = new ArrayList<>(); - StringBuilder sb = new StringBuilder(); - boolean inQuotes = false; - for (int i = 0; i < dnString.length(); ++i) { - char currentCharacter = dnString.charAt(i); - if (inQuotes) { - if ('"' == currentCharacter) { - inQuotes = false; - } else { - sb.append(dnString.charAt(i)); - } - } else { - if ('"' == currentCharacter) { - inQuotes = true; - } else if (delim == currentCharacter) { - if (sb.length() > 0) { - lrnd.add(new Rdn(sb.toString())); - sb.setLength(0); - } - } else { - sb.append(dnString.charAt(i)); - } - } - } - if (sb.indexOf("=") > 0) { - lrnd.add(new Rdn(sb.toString())); - } - return lrnd; - } - - @Override - public String toString() { - return tag + '=' + value; - } - - ASN1ObjectIdentifier getAoi() { - return aoi; - } - - ASN1ObjectIdentifier getAoi(String tag) throws CertException { - switch (tag.toLowerCase()) { - case "cn": - return BCStyle.CN; - case "c": - return BCStyle.C; - case "st": - return BCStyle.ST; - case "l": - return BCStyle.L; - case "o": - return BCStyle.O; - case "ou": - return BCStyle.OU; - case "dc": - return BCStyle.DC; - case "gn": - return BCStyle.GIVENNAME; - case "sn": - return BCStyle.SN; - case "email": - case "e": - case "emailaddress": - return BCStyle.EmailAddress; - case "initials": - return BCStyle.INITIALS; - case "pseudonym": - return BCStyle.PSEUDONYM; - case "generationqualifier": - return BCStyle.GENERATION; - case "serialnumber": - return BCStyle.SERIALNUMBER; - default: - throw new CertException( - "Unknown ASN1ObjectIdentifier for tag " + tag); - } - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpClientImpl.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpClientImpl.java deleted file mode 100644 index 87991132..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpClientImpl.java +++ /dev/null @@ -1,242 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.impl; - -import java.security.KeyPair; -import java.security.PublicKey; - -import static org.onap.aaf.certservice.cmpv2client.impl.CmpResponseHelper.checkIfCmpResponseContainsError; -import static org.onap.aaf.certservice.cmpv2client.impl.CmpResponseHelper.getCertFromByteArray; -import static org.onap.aaf.certservice.cmpv2client.impl.CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore; -import static org.onap.aaf.certservice.cmpv2client.impl.CmpResponseValidationHelper.checkImplicitConfirm; -import static org.onap.aaf.certservice.cmpv2client.impl.CmpResponseValidationHelper.verifyPasswordBasedProtection; -import static org.onap.aaf.certservice.cmpv2client.impl.CmpResponseValidationHelper.verifySignature; - -import java.io.IOException; -import java.security.cert.CertificateParsingException; -import java.security.cert.X509Certificate; -import java.util.Collections; -import java.util.Date; -import java.util.Objects; -import java.util.Optional; - -import org.apache.http.impl.client.CloseableHttpClient; -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.aaf.certservice.certification.configuration.model.CaMode; -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.onap.aaf.certservice.certification.model.CsrModel; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.onap.aaf.certservice.cmpv2client.api.CmpClient; -import org.onap.aaf.certservice.cmpv2client.model.Cmpv2CertificationModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Implementation of the CmpClient Interface conforming to RFC4210 (Certificate Management Protocol - * (CMP)) and RFC4211 (Certificate Request Message Format (CRMF)) standards. - */ -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(); - - public CmpClientImpl(CloseableHttpClient httpClient) { - this.httpClient = httpClient; - } - - @Override - public Cmpv2CertificationModel createCertificate( - CsrModel csrModel, - Cmpv2Server server, - Date notBefore, - Date notAfter) - throws CmpClientException { - - validate(csrModel, server, httpClient, notBefore, notAfter); - KeyPair keyPair = new KeyPair(csrModel.getPublicKey(), csrModel.getPrivateKey()); - - final CreateCertRequest certRequest = - CmpMessageBuilder.of(CreateCertRequest::new) - .with(CreateCertRequest::setIssuerDn, server.getIssuerDN()) - .with(CreateCertRequest::setSubjectDn, csrModel.getSubjectData()) - .with(CreateCertRequest::setSansList, csrModel.getSans()) - .with(CreateCertRequest::setSubjectKeyPair, keyPair) - .with(CreateCertRequest::setNotBefore, notBefore) - .with(CreateCertRequest::setNotAfter, notAfter) - .with(CreateCertRequest::setInitAuthPassword, server.getAuthentication().getIak()) - .with(CreateCertRequest::setSenderKid, server.getAuthentication().getRv()) - .build(); - - final PKIMessage pkiMessage = certRequest.generateCertReq(); - Cmpv2HttpClient cmpv2HttpClient = new Cmpv2HttpClient(httpClient); - return retrieveCertificates(csrModel, server, pkiMessage, cmpv2HttpClient); - } - - @Override - public Cmpv2CertificationModel createCertificate(CsrModel csrModel, Cmpv2Server server) - throws CmpClientException { - return createCertificate(csrModel, server, null, null); - } - - 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); - verifyProtectionWithProtectionAlgo(respPkiMessage, initAuthPassword, header, protectionAlgo); - } - - 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 verifyProtectionWithProtectionAlgo( - PKIMessage respPkiMessage, - String initAuthPassword, - PKIHeader header, - AlgorithmIdentifier protectionAlgo) - throws CmpClientException { - if (Objects.nonNull(protectionAlgo)) { - LOG.debug("Verifying PasswordBased Protection of the Response."); - verifyPasswordBasedProtection(respPkiMessage, initAuthPassword, protectionAlgo); - checkImplicitConfirm(header); - } else { - LOG.error( - "Protection Algorithm is not available when expecting PBE protected response containing protection algorithm"); - throw new CmpClientException( - "Protection Algorithm is not available when expecting PBE protected response containing protection algorithm"); - } - } - - private Cmpv2CertificationModel checkCmpCertRepMessage(final PKIMessage respPkiMessage) - 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)) { - final CertResponse certResponse = - getCertificateResponseContainingNewCertificate(certRepMessage); - try { - return verifyReturnCertChainAndTrustStore(respPkiMessage, certRepMessage, certResponse); - } catch (IOException | CertificateParsingException ex) { - CmpClientException cmpClientException = - new CmpClientException( - "Exception occurred while retrieving Certificates from response", ex); - LOG.error("Exception occurred while retrieving Certificates from response", ex); - throw cmpClientException; - } - } else { - return new Cmpv2CertificationModel(Collections.emptyList(), Collections.emptyList()); - } - } - return new Cmpv2CertificationModel(Collections.emptyList(), Collections.emptyList()); - } - - private Cmpv2CertificationModel verifyReturnCertChainAndTrustStore( - 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(); - final Optional leafCertificate = - getCertFromByteArray(cmpCertificate.getEncoded(), X509Certificate.class); - if (leafCertificate.isPresent()) { - return verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate.get()); - } - return new Cmpv2CertificationModel(Collections.emptyList(), Collections.emptyList()); - } - - private CertResponse getCertificateResponseContainingNewCertificate( - 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/aaf/certservice/cmpv2client/impl/CmpMessageBuilder.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpMessageBuilder.java deleted file mode 100644 index 1f370f93..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpMessageBuilder.java +++ /dev/null @@ -1,57 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.impl; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Supplier; - -/** - * Generic Builder Class for creating CMP Message. - */ -public final class CmpMessageBuilder { - - private final Supplier instantiator; - private final List> instanceModifiers = new ArrayList<>(); - - public CmpMessageBuilder(Supplier instantiator) { - this.instantiator = instantiator; - } - - public static CmpMessageBuilder of(Supplier instantiator) { - return new CmpMessageBuilder<>(instantiator); - } - - public CmpMessageBuilder with(BiConsumer consumer, U value) { - Consumer valueConsumer = instance -> consumer.accept(instance, value); - instanceModifiers.add(valueConsumer); - return this; - } - - public T build() { - T value = instantiator.get(); - instanceModifiers.forEach(modifier -> modifier.accept(value)); - instanceModifiers.clear(); - return value; - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpMessageHelper.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpMessageHelper.java deleted file mode 100644 index 6fcc5f14..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpMessageHelper.java +++ /dev/null @@ -1,246 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.impl; - -import static org.onap.aaf.certservice.cmpv2client.impl.CmpUtil.generateProtectedBytes; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.security.InvalidKeyException; -import java.security.KeyPair; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.Signature; -import java.security.SignatureException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import javax.crypto.Mac; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import org.bouncycastle.asn1.ASN1EncodableVector; -import org.bouncycastle.asn1.ASN1Integer; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.DERBitString; -import org.bouncycastle.asn1.DEROctetString; -import org.bouncycastle.asn1.DEROutputStream; -import org.bouncycastle.asn1.DERSequence; -import org.bouncycastle.asn1.DERTaggedObject; -import org.bouncycastle.asn1.cmp.PBMParameter; -import org.bouncycastle.asn1.cmp.PKIBody; -import org.bouncycastle.asn1.cmp.PKIHeader; -import org.bouncycastle.asn1.cmp.PKIMessage; -import org.bouncycastle.asn1.crmf.CertRequest; -import org.bouncycastle.asn1.crmf.OptionalValidity; -import org.bouncycastle.asn1.crmf.POPOSigningKey; -import org.bouncycastle.asn1.crmf.ProofOfPossession; -import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.asn1.x509.Extension; -import org.bouncycastle.asn1.x509.Extensions; -import org.bouncycastle.asn1.x509.ExtensionsGenerator; -import org.bouncycastle.asn1.x509.GeneralName; -import org.bouncycastle.asn1.x509.GeneralNames; -import org.bouncycastle.asn1.x509.KeyUsage; -import org.bouncycastle.asn1.x509.Time; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class CmpMessageHelper { - - private static final Logger LOG = LoggerFactory.getLogger(CmpMessageHelper.class); - private static final AlgorithmIdentifier OWF_ALGORITHM = - new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.3.14.3.2.26")); - private static final AlgorithmIdentifier MAC_ALGORITHM = - new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.840.113549.2.9")); - private static final ASN1ObjectIdentifier PASSWORD_BASED_MAC = - new ASN1ObjectIdentifier("1.2.840.113533.7.66.13"); - - private CmpMessageHelper() { - } - - /** - * Creates an Optional Validity, which is used to specify how long the returned cert should be - * valid for. - * - * @param notBefore Date specifying certificate is not valid before this date. - * @param notAfter Date specifying certificate is not valid after this date. - * @return {@link OptionalValidity} that can be set for certificate on external CA. - */ - public static OptionalValidity generateOptionalValidity( - final Date notBefore, final Date notAfter) { - LOG.info("Generating Optional Validity from Date objects"); - ASN1EncodableVector optionalValidityV = new ASN1EncodableVector(); - if (notBefore != null) { - Time nb = new Time(notBefore); - optionalValidityV.add(new DERTaggedObject(true, 0, nb)); - } - if (notAfter != null) { - Time na = new Time(notAfter); - optionalValidityV.add(new DERTaggedObject(true, 1, na)); - } - return OptionalValidity.getInstance(new DERSequence(optionalValidityV)); - } - - /** - * Create Extensions from Subject Alternative Names. - * - * @return {@link Extensions}. - */ - public static Extensions generateExtension(final List sansList) - throws CmpClientException { - LOG.info("Generating Extensions from Subject Alternative Names"); - final ExtensionsGenerator extGenerator = new ExtensionsGenerator(); - final GeneralName[] sansGeneralNames = getGeneralNames(sansList); - // KeyUsage - try { - final KeyUsage keyUsage = - new KeyUsage( - KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.nonRepudiation); - extGenerator.addExtension(Extension.keyUsage, false, new DERBitString(keyUsage)); - extGenerator.addExtension( - Extension.subjectAlternativeName, false, new GeneralNames(sansGeneralNames)); - } catch (IOException ioe) { - CmpClientException cmpClientException = - new CmpClientException( - "Exception occurred while creating extensions for PKIMessage", ioe); - LOG.error("Exception occurred while creating extensions for PKIMessage"); - throw cmpClientException; - } - return extGenerator.generate(); - } - - public static GeneralName[] getGeneralNames(List sansList) { - final List nameList = new ArrayList<>(); - for (String san : sansList) { - nameList.add(new GeneralName(GeneralName.dNSName, san)); - } - final GeneralName[] sansGeneralNames = new GeneralName[nameList.size()]; - nameList.toArray(sansGeneralNames); - return sansGeneralNames; - } - - /** - * Method generates Proof-of-Possession (POP) of Private Key. To allow a CA/RA to properly - * validity binding between an End Entity and a Key Pair, the PKI Operations specified here make - * it possible for an End Entity to prove that it has possession of the Private Key corresponding - * to the Public Key for which a Certificate is requested. - * - * @param certRequest Certificate request that requires proof of possession - * @param keypair keypair associated with the subject sending the certificate request - * @return {@link ProofOfPossession}. - * @throws CmpClientException A general-purpose Cmp client exception. - */ - public static ProofOfPossession generateProofOfPossession( - final CertRequest certRequest, final KeyPair keypair) throws CmpClientException { - ProofOfPossession proofOfPossession; - try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { - final DEROutputStream derOutputStream = new DEROutputStream(byteArrayOutputStream); - derOutputStream.writeObject(certRequest); - - byte[] popoProtectionBytes = byteArrayOutputStream.toByteArray(); - final String sigalg = PKCSObjectIdentifiers.sha256WithRSAEncryption.getId(); - final Signature signature = Signature.getInstance(sigalg, BouncyCastleProvider.PROVIDER_NAME); - signature.initSign(keypair.getPrivate()); - signature.update(popoProtectionBytes); - DERBitString bs = new DERBitString(signature.sign()); - - proofOfPossession = - new ProofOfPossession( - new POPOSigningKey( - null, new AlgorithmIdentifier(new ASN1ObjectIdentifier(sigalg)), bs)); - } catch (IOException - | NoSuchProviderException - | NoSuchAlgorithmException - | InvalidKeyException - | SignatureException ex) { - CmpClientException cmpClientException = - new CmpClientException( - "Exception occurred while creating proof of possession for PKIMessage", ex); - LOG.error("Exception occurred while creating proof of possession for PKIMessage"); - throw cmpClientException; - } - return proofOfPossession; - } - - /** - * Generic code to create Algorithm Identifier for protection of PKIMessage. - * - * @return Algorithm Identifier - */ - public static AlgorithmIdentifier protectionAlgoIdentifier(int iterations, byte[] salt) { - ASN1Integer iteration = new ASN1Integer(iterations); - DEROctetString derSalt = new DEROctetString(salt); - - PBMParameter pp = new PBMParameter(derSalt, OWF_ALGORITHM, iteration, MAC_ALGORITHM); - return new AlgorithmIdentifier(PASSWORD_BASED_MAC, pp); - } - - /** - * Adds protection to the PKIMessage via a specified protection algorithm. - * - * @param password password used to authenticate PkiMessage with external CA - * @param pkiHeader Header of PKIMessage containing generic details for any PKIMessage - * @param pkiBody Body of PKIMessage containing specific details for certificate request - * @return Protected Pki Message - * @throws CmpClientException Wraps several exceptions into one general-purpose exception. - */ - public static PKIMessage protectPkiMessage( - PKIHeader pkiHeader, PKIBody pkiBody, String password, int iterations, byte[] salt) - throws CmpClientException { - - byte[] raSecret = password.getBytes(); - byte[] basekey = new byte[raSecret.length + salt.length]; - System.arraycopy(raSecret, 0, basekey, 0, raSecret.length); - System.arraycopy(salt, 0, basekey, raSecret.length, salt.length); - byte[] out; - try { - MessageDigest dig = - MessageDigest.getInstance( - OWF_ALGORITHM.getAlgorithm().getId(), BouncyCastleProvider.PROVIDER_NAME); - for (int i = 0; i < iterations; i++) { - basekey = dig.digest(basekey); - dig.reset(); - } - byte[] protectedBytes = generateProtectedBytes(pkiHeader, pkiBody); - Mac mac = - Mac.getInstance(MAC_ALGORITHM.getAlgorithm().getId(), BouncyCastleProvider.PROVIDER_NAME); - SecretKey key = new SecretKeySpec(basekey, MAC_ALGORITHM.getAlgorithm().getId()); - mac.init(key); - mac.reset(); - mac.update(protectedBytes, 0, protectedBytes.length); - out = mac.doFinal(); - } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException ex) { - CmpClientException cmpClientException = - new CmpClientException( - "Exception occurred while generating proof of possession for PKIMessage", ex); - LOG.error("Exception occured while generating the proof of possession for PKIMessage"); - throw cmpClientException; - } - DERBitString bs = new DERBitString(out); - - return new PKIMessage(pkiHeader, pkiBody, bs); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseHelper.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseHelper.java deleted file mode 100644 index 3cb0b0c5..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseHelper.java +++ /dev/null @@ -1,335 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.impl; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.cert.CertPath; -import java.security.cert.CertPathValidator; -import java.security.cert.CertPathValidatorException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.CertificateParsingException; -import java.security.cert.PKIXCertPathChecker; -import java.security.cert.PKIXCertPathValidatorResult; -import java.security.cert.PKIXParameters; -import java.security.cert.TrustAnchor; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -import org.bouncycastle.asn1.cmp.CMPCertificate; -import org.bouncycastle.asn1.cmp.CertRepMessage; -import org.bouncycastle.asn1.cmp.ErrorMsgContent; -import org.bouncycastle.asn1.cmp.PKIBody; -import org.bouncycastle.asn1.cmp.PKIMessage; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.onap.aaf.certservice.cmpv2client.exceptions.PkiErrorException; -import org.onap.aaf.certservice.cmpv2client.model.Cmpv2CertificationModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class CmpResponseHelper { - - private static final Logger LOG = LoggerFactory.getLogger(CmpResponseHelper.class); - - private CmpResponseHelper() { - } - - static void checkIfCmpResponseContainsError(PKIMessage respPkiMessage) - throws CmpClientException { - if (respPkiMessage.getBody().getType() == PKIBody.TYPE_ERROR) { - final ErrorMsgContent errorMsgContent = - (ErrorMsgContent) respPkiMessage.getBody().getContent(); - PkiErrorException pkiErrorException = - new PkiErrorException( - errorMsgContent.getPKIStatusInfo().getStatusString().getStringAt(0).getString()); - CmpClientException cmpClientException = - new CmpClientException("Error in the PkiMessage response", pkiErrorException); - LOG.error("Error in the PkiMessage response: {} ", pkiErrorException.getMessage()); - throw cmpClientException; - } - } - - - /** - * Puts together certChain and Trust store and verifies the certChain - * - * @param respPkiMessage PKIMessage that may contain extra certs used for certchain - * @param certRepMessage CertRepMessage that should contain rootCA for certchain - * @param leafCertificate certificate returned from our original Cert Request - * @return model for certification containing certificate chain and trusted certificates - * @throws CertificateParsingException thrown if error occurs while parsing certificate - * @throws IOException thrown if IOException occurs while parsing certificate - * @throws CmpClientException thrown if error occurs during the verification of the certChain - */ - static Cmpv2CertificationModel verifyAndReturnCertChainAndTrustSTore( - PKIMessage respPkiMessage, CertRepMessage certRepMessage, X509Certificate leafCertificate) - throws CertificateParsingException, IOException, CmpClientException { - Map certificates = mapAllCertificates(respPkiMessage, certRepMessage); - return extractCertificationModel(certificates, leafCertificate); - } - - private static Map mapAllCertificates( - PKIMessage respPkiMessage, CertRepMessage certRepMessage - ) - throws IOException, CertificateParsingException, CmpClientException { - - Map certificates = new HashMap<>(); - - CMPCertificate[] extraCerts = respPkiMessage.getExtraCerts(); - certificates.putAll(mapCertificates(extraCerts)); - - CMPCertificate[] caPubsCerts = certRepMessage.getCaPubs(); - certificates.putAll(mapCertificates(caPubsCerts)); - - return certificates; - } - - private static Map mapCertificates( - CMPCertificate[] cmpCertificates) - throws CertificateParsingException, CmpClientException, IOException { - - Map certificates = new HashMap<>(); - if (cmpCertificates != null) { - for (CMPCertificate certificate : cmpCertificates) { - getCertFromByteArray(certificate.getEncoded(), X509Certificate.class) - .ifPresent(x509Certificate -> - certificates.put(extractSubjectDn(x509Certificate), x509Certificate) - ); - } - } - - return certificates; - } - - private static Cmpv2CertificationModel extractCertificationModel( - Map certificates, X509Certificate leafCertificate - ) - throws CmpClientException { - List certificateChain = new ArrayList<>(); - X509Certificate previousCertificateInChain; - X509Certificate nextCertificateInChain = leafCertificate; - do { - certificateChain.add(nextCertificateInChain); - certificates.remove(extractSubjectDn(nextCertificateInChain)); - previousCertificateInChain = nextCertificateInChain; - nextCertificateInChain = certificates.get(extractIssuerDn(nextCertificateInChain)); - verify(previousCertificateInChain, nextCertificateInChain, null); - } - while (!isSelfSign(nextCertificateInChain)); - List trustedCertificates = new ArrayList<>(certificates.values()); - - return new Cmpv2CertificationModel(certificateChain, trustedCertificates); - } - - private static boolean isSelfSign(X509Certificate certificate) { - return extractIssuerDn(certificate).equals(extractSubjectDn(certificate)); - } - - private static X500Name extractIssuerDn(X509Certificate x509Certificate) { - return X500Name.getInstance(x509Certificate.getIssuerDN()); - } - - private static X500Name extractSubjectDn(X509Certificate x509Certificate) { - return X500Name.getInstance(x509Certificate.getSubjectDN()); - } - - - /** - * Check the certificate with CA certificate. - * - * @param certificate X.509 certificate to verify. May not be null. - * @param caCertChain Collection of X509Certificates. May not be null, an empty list or a - * Collection with null entries. - * @param date Date to verify at, or null to use current time. - * @param pkixCertPathCheckers optional PKIXCertPathChecker implementations to use during cert - * path validation - * @throws CmpClientException if certificate could not be validated - */ - private static void verify( - X509Certificate certificate, - X509Certificate caCertChain, - Date date, - PKIXCertPathChecker... pkixCertPathCheckers) - throws CmpClientException { - try { - verifyCertificates(certificate, caCertChain, date, pkixCertPathCheckers); - } catch (CertPathValidatorException cpve) { - CmpClientException cmpClientException = - new CmpClientException( - "Invalid certificate or certificate not issued by specified CA: ", cpve); - LOG.error("Invalid certificate or certificate not issued by specified CA: ", cpve); - throw cmpClientException; - } catch (CertificateException ce) { - CmpClientException cmpClientException = - new CmpClientException("Something was wrong with the supplied certificate", ce); - LOG.error("Something was wrong with the supplied certificate", ce); - throw cmpClientException; - } catch (NoSuchProviderException nspe) { - CmpClientException cmpClientException = - new CmpClientException("BouncyCastle provider not found.", nspe); - LOG.error("BouncyCastle provider not found.", nspe); - throw cmpClientException; - } catch (NoSuchAlgorithmException nsae) { - CmpClientException cmpClientException = - new CmpClientException("Algorithm PKIX was not found.", nsae); - LOG.error("Algorithm PKIX was not found.", nsae); - throw cmpClientException; - } catch (InvalidAlgorithmParameterException iape) { - CmpClientException cmpClientException = - new CmpClientException( - "Either ca certificate chain was empty," - + " or the certificate was on an inappropriate type for a PKIX path checker.", - iape); - LOG.error( - "Either ca certificate chain was empty, " - + "or the certificate was on an inappropriate type for a PKIX path checker.", - iape); - throw cmpClientException; - } - } - - private static void verifyCertificates( - X509Certificate certificate, - X509Certificate caCertChain, - Date date, - PKIXCertPathChecker[] pkixCertPathCheckers) - throws CertificateException, NoSuchProviderException, InvalidAlgorithmParameterException, - NoSuchAlgorithmException, CertPathValidatorException { - if (caCertChain == null) { - final String noRootCaCertificateMessage = "Server response does not contain proper root CA certificate"; - throw new CertificateException(noRootCaCertificateMessage); - } - LOG.debug( - "Verifying certificate {} as part of cert chain with certificate {}", - certificate.getSubjectDN().getName(), - caCertChain.getSubjectDN().getName()); - CertPath cp = getCertPath(certificate); - PKIXParameters params = getPkixParameters(caCertChain, date, pkixCertPathCheckers); - CertPathValidator cpv = - CertPathValidator.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME); - PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult) cpv.validate(cp, params); - if (LOG.isDebugEnabled()) { - LOG.debug("Certificate verify result:{} ", result); - } - } - - private static PKIXParameters getPkixParameters( - X509Certificate caCertChain, Date date, PKIXCertPathChecker[] pkixCertPathCheckers) - throws InvalidAlgorithmParameterException { - TrustAnchor anchor = new TrustAnchor(caCertChain, null); - PKIXParameters params = new PKIXParameters(Collections.singleton(anchor)); - for (final PKIXCertPathChecker pkixCertPathChecker : pkixCertPathCheckers) { - params.addCertPathChecker(pkixCertPathChecker); - } - params.setRevocationEnabled(false); - params.setDate(date); - return params; - } - - private static CertPath getCertPath(X509Certificate certificate) - throws CertificateException, NoSuchProviderException { - ArrayList certlist = new ArrayList<>(); - certlist.add(certificate); - return CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME) - .generateCertPath(certlist); - } - - /** - * Returns a CertificateFactory that can be used to create certificates from byte arrays and such. - * - * @param provider Security provider that should be used to create certificates, default BC is - * null is passed. - * @return CertificateFactory for creating certificate - */ - private static CertificateFactory getCertificateFactory(final String provider) - throws CmpClientException { - LOG.debug("Creating certificate Factory to generate certificate using provider {}", provider); - final String prov; - prov = Objects.requireNonNullElse(provider, BouncyCastleProvider.PROVIDER_NAME); - try { - return CertificateFactory.getInstance("X.509", prov); - } catch (NoSuchProviderException nspe) { - CmpClientException cmpClientException = new CmpClientException("NoSuchProvider: ", nspe); - LOG.error("NoSuchProvider: ", nspe); - throw cmpClientException; - } catch (CertificateException ce) { - CmpClientException cmpClientException = new CmpClientException("CertificateException: ", ce); - LOG.error("CertificateException: ", ce); - throw cmpClientException; - } - } - - /** - * @param cert byte array that contains certificate - * @param returnType the type of Certificate to be returned, for example X509Certificate.class. - * Certificate.class can be used if certificate type is unknown. - * @throws CertificateParsingException if the byte array does not contain a proper certificate. - */ - static Optional getCertFromByteArray( - byte[] cert, Class returnType) throws CertificateParsingException, CmpClientException { - LOG.debug("Retrieving certificate of type {} from byte array.", returnType); - String prov = BouncyCastleProvider.PROVIDER_NAME; - - if (returnType.equals(X509Certificate.class)) { - return parseX509Certificate(prov, cert); - } else { - LOG.debug("Certificate of type {} was skipped, because type of certificate is not 'X509Certificate'.", returnType); - return Optional.empty(); - } - } - - - /** - * Parse a X509Certificate from an array of bytes - * - * @param provider a provider name - * @param cert a byte array containing an encoded certificate - * @return a decoded X509Certificate - * @throws CertificateParsingException if the byte array wasn't valid, or contained a certificate - * other than an X509 Certificate. - */ - private static Optional parseX509Certificate(String provider, byte[] cert) - throws CertificateParsingException, CmpClientException { - LOG.debug("Parsing X509Certificate from bytes with provider {}", provider); - final CertificateFactory cf = getCertificateFactory(provider); - X509Certificate result; - try { - result = (X509Certificate) Objects.requireNonNull(cf).generateCertificate(new ByteArrayInputStream(cert)); - return Optional.ofNullable(result); - } catch (CertificateException ce) { - throw new CertificateParsingException("Could not parse byte array as X509Certificate ", ce); - } - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseValidationHelper.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseValidationHelper.java deleted file mode 100644 index 4b9f2cd1..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseValidationHelper.java +++ /dev/null @@ -1,241 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.impl; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.security.InvalidKeyException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PublicKey; -import java.security.Signature; -import java.security.SignatureException; -import java.util.Arrays; -import java.util.Objects; -import javax.crypto.Mac; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import org.bouncycastle.asn1.ASN1Encodable; -import org.bouncycastle.asn1.ASN1EncodableVector; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.DERBitString; -import org.bouncycastle.asn1.DEROutputStream; -import org.bouncycastle.asn1.DERSequence; -import org.bouncycastle.asn1.cmp.CMPObjectIdentifiers; -import org.bouncycastle.asn1.cmp.InfoTypeAndValue; -import org.bouncycastle.asn1.cmp.PBMParameter; -import org.bouncycastle.asn1.cmp.PKIBody; -import org.bouncycastle.asn1.cmp.PKIHeader; -import org.bouncycastle.asn1.cmp.PKIMessage; -import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class CmpResponseValidationHelper { - - private static final Logger LOG = LoggerFactory.getLogger(CmpResponseValidationHelper.class); - - private CmpResponseValidationHelper() { - } - - /** - * Create a base key to use for verifying the PasswordBasedMac on a PKIMessage - * - * @param pbmParamSeq parameters recieved in PKIMessage used with password - * @param initAuthPassword password used to decrypt the basekey - * @return bytes representing the basekey - * @throws CmpClientException thrown if algorithem exceptions occur for the message digest - */ - public static byte[] getBaseKeyFromPbmParameters( - PBMParameter pbmParamSeq, String initAuthPassword) throws CmpClientException { - final int iterationCount = pbmParamSeq.getIterationCount().getPositiveValue().intValue(); - LOG.info("Iteration count is: {}", iterationCount); - final AlgorithmIdentifier owfAlg = pbmParamSeq.getOwf(); - LOG.info("One Way Function type is: {}", owfAlg.getAlgorithm().getId()); - final byte[] salt = pbmParamSeq.getSalt().getOctets(); - final byte[] raSecret = initAuthPassword != null ? initAuthPassword.getBytes() : new byte[0]; - byte[] basekey = new byte[raSecret.length + salt.length]; - System.arraycopy(raSecret, 0, basekey, 0, raSecret.length); - System.arraycopy(salt, 0, basekey, raSecret.length, salt.length); - try { - final MessageDigest messageDigest = - MessageDigest.getInstance( - owfAlg.getAlgorithm().getId(), BouncyCastleProvider.PROVIDER_NAME); - for (int i = 0; i < iterationCount; i++) { - basekey = messageDigest.digest(basekey); - messageDigest.reset(); - } - } catch (NoSuchAlgorithmException | NoSuchProviderException ex) { - LOG.error("ProtectionBytes don't match passwordBasedProtection, authentication failed"); - throw new CmpClientException( - "ProtectionBytes don't match passwordBasedProtection, authentication failed", ex); - } - return basekey; - } - - /** - * Verifies the signature of the response message using our public key - * - * @param respPkiMessage PKIMessage we wish to verify signature for - * @param pk public key used to verify signature. - * @throws CmpClientException - */ - public static void verifySignature(PKIMessage respPkiMessage, PublicKey pk) - throws CmpClientException { - final byte[] protBytes = getProtectedBytes(respPkiMessage); - final DERBitString derBitString = respPkiMessage.getProtection(); - try { - final Signature signature = - Signature.getInstance( - PKCSObjectIdentifiers.sha256WithRSAEncryption.getId(), - BouncyCastleProvider.PROVIDER_NAME); - signature.initVerify(pk); - signature.update(protBytes); - signature.verify(derBitString.getBytes()); - } catch (NoSuchAlgorithmException - | NoSuchProviderException - | InvalidKeyException - | SignatureException e) { - CmpClientException clientException = - new CmpClientException("Signature Verification failed", e); - LOG.error("Signature Verification failed", e); - throw clientException; - } - } - - /** - * Converts the header and the body of a PKIMessage to an ASN1Encodable and returns the as a byte - * array - * - * @param msg PKIMessage to get protected bytes from - * @return the PKIMessage's header and body in byte array - */ - public static byte[] getProtectedBytes(PKIMessage msg) throws CmpClientException { - return getProtectedBytes(msg.getHeader(), msg.getBody()); - } - - /** - * Converts the header and the body of a PKIMessage to an ASN1Encodable and returns the as a byte - * array - * - * @param header PKIHeader to be converted - * @param body PKIMessage to be converted - * @return the PKIMessage's header and body in byte array - */ - public static byte[] getProtectedBytes(PKIHeader header, PKIBody body) throws CmpClientException { - byte[] res; - ASN1EncodableVector encodableVector = new ASN1EncodableVector(); - encodableVector.add(header); - encodableVector.add(body); - ASN1Encodable protectedPart = new DERSequence(encodableVector); - try { - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - DEROutputStream out = new DEROutputStream(bao); - out.writeObject(protectedPart); - res = bao.toByteArray(); - } catch (IOException ioe) { - CmpClientException cmpClientException = - new CmpClientException("Error occured while getting protected bytes", ioe); - LOG.error("Error occured while getting protected bytes", ioe); - throw cmpClientException; - } - return res; - } - - /** - * verify the password based protection within the response message - * - * @param respPkiMessage PKIMessage we want to verify password based protection for - * @param initAuthPassword password used to decrypt protection - * @param protectionAlgo protection algorithm we can use to decrypt protection - * @throws CmpClientException - */ - public static void verifyPasswordBasedProtection( - PKIMessage respPkiMessage, String initAuthPassword, AlgorithmIdentifier protectionAlgo) - throws CmpClientException { - final byte[] protectedBytes = getProtectedBytes(respPkiMessage); - final PBMParameter pbmParamSeq = PBMParameter.getInstance(protectionAlgo.getParameters()); - if (Objects.nonNull(pbmParamSeq)) { - try { - byte[] basekey = getBaseKeyFromPbmParameters(pbmParamSeq, initAuthPassword); - final Mac mac = getMac(protectedBytes, pbmParamSeq, basekey); - final byte[] outBytes = mac.doFinal(); - final byte[] protectionBytes = respPkiMessage.getProtection().getBytes(); - if (!Arrays.equals(outBytes, protectionBytes)) { - LOG.error("protectionBytes don't match passwordBasedProtection, authentication failed"); - throw new CmpClientException( - "protectionBytes don't match passwordBasedProtection, authentication failed"); - } - } catch (NoSuchProviderException | NoSuchAlgorithmException | InvalidKeyException ex) { - CmpClientException cmpClientException = - new CmpClientException("Error while validating CMP response ", ex); - LOG.error("Error while validating CMP response ", ex); - throw cmpClientException; - } - } - } - - public static void checkImplicitConfirm(PKIHeader header) { - InfoTypeAndValue[] infos = header.getGeneralInfo(); - if (Objects.nonNull(infos)) { - if (CMPObjectIdentifiers.it_implicitConfirm.equals(getImplicitConfirm(infos))) { - LOG.info("Implicit Confirm on certificate from server."); - } else { - LOG.debug("No Implicit confirm in Response"); - } - } else { - LOG.debug("No general Info in header of response, cannot verify implicit confirm"); - } - } - - public static ASN1ObjectIdentifier getImplicitConfirm(InfoTypeAndValue[] info) { - return info[0].getInfoType(); - } - - /** - * Get cryptographical Mac we can use to decrypt our PKIMessage - * - * @param protectedBytes Protected bytes representing the PKIMessage - * @param pbmParamSeq Parameters used to decrypt PKIMessage, including mac algorithm used - * @param basekey Key used alongside mac Oid to create secret key for decrypting PKIMessage - * @return Mac that's ready to return decrypted bytes - * @throws NoSuchAlgorithmException Possibly thrown trying to get mac instance - * @throws NoSuchProviderException Possibly thrown trying to get mac instance - * @throws InvalidKeyException Possibly thrown trying to initialize mac using secretkey - */ - public static Mac getMac(byte[] protectedBytes, PBMParameter pbmParamSeq, byte[] basekey) - throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException { - final AlgorithmIdentifier macAlg = pbmParamSeq.getMac(); - LOG.info("Mac type is: {}", macAlg.getAlgorithm().getId()); - final String macOid = macAlg.getAlgorithm().getId(); - final Mac mac = Mac.getInstance(macOid, BouncyCastleProvider.PROVIDER_NAME); - final SecretKey key = new SecretKeySpec(basekey, macOid); - mac.init(key); - mac.reset(); - mac.update(protectedBytes, 0, protectedBytes.length); - return mac; - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpUtil.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpUtil.java deleted file mode 100644 index ced0fed0..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CmpUtil.java +++ /dev/null @@ -1,153 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.impl; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.security.SecureRandom; -import java.util.Date; -import java.util.Objects; - -import org.bouncycastle.asn1.ASN1Encodable; -import org.bouncycastle.asn1.ASN1EncodableVector; -import org.bouncycastle.asn1.ASN1GeneralizedTime; -import org.bouncycastle.asn1.DEROctetString; -import org.bouncycastle.asn1.DEROutputStream; -import org.bouncycastle.asn1.DERSequence; -import org.bouncycastle.asn1.cmp.CMPObjectIdentifiers; -import org.bouncycastle.asn1.cmp.InfoTypeAndValue; -import org.bouncycastle.asn1.cmp.PKIBody; -import org.bouncycastle.asn1.cmp.PKIHeader; -import org.bouncycastle.asn1.cmp.PKIHeaderBuilder; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.asn1.x509.GeneralName; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class CmpUtil { - - private static final Logger LOGGER = LoggerFactory.getLogger(CmpUtil.class); - private static final SecureRandom SECURE_RANDOM = new SecureRandom(); - public static final int RANDOM_BYTE_LENGTH = 16; - public static final int RANDOM_SEED = 1000; - - private CmpUtil() { - } - - /** - * Validates specified object reference is not null. - * - * @param argument T - the type of the reference. - * @param message message - detail message to be used in the event that a NullPointerException is - * thrown. - * @return The Object if not null - */ - public static T notNull(T argument, String message) { - return Objects.requireNonNull(argument, message + " must not be null"); - } - - /** - * Validates String object reference is not null and not empty. - * - * @param stringArg String Object that need to be validated. - * @return boolean - */ - public static boolean isNullOrEmpty(String stringArg) { - return (stringArg != null && !stringArg.trim().isEmpty()); - } - - /** - * Creates a random number than can be used for sendernonce, transactionId and salts. - * - * @return bytes containing a random number string representing a nonce - */ - static byte[] createRandomBytes() { - LOGGER.info("Generating random array of bytes"); - byte[] randomBytes = new byte[RANDOM_BYTE_LENGTH]; - SECURE_RANDOM.nextBytes(randomBytes); - return randomBytes; - } - - /** - * Creates a random integer than can be used to represent a transactionId or determine the number - * iterations in a protection algorithm. - * - * @return bytes containing a random number string representing a nonce - */ - static int createRandomInt(int range) { - LOGGER.info("Generating random integer"); - return SECURE_RANDOM.nextInt(range) + RANDOM_SEED; - } - - /** - * Generates protected bytes of a combined PKIHeader and PKIBody. - * - * @param header Header of PKIMessage containing common parameters - * @param body Body of PKIMessage containing specific information for message - * @return bytes representing the PKIHeader and PKIBody thats to be protected - */ - static byte[] generateProtectedBytes(PKIHeader header, PKIBody body) throws CmpClientException { - LOGGER.info("Generating array of bytes representing PkiHeader and PkiBody"); - byte[] res; - ASN1EncodableVector vector = new ASN1EncodableVector(); - vector.add(header); - vector.add(body); - ASN1Encodable protectedPart = new DERSequence(vector); - try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { - DEROutputStream out = new DEROutputStream(baos); - out.writeObject(protectedPart); - res = baos.toByteArray(); - } catch (IOException ioe) { - CmpClientException cmpClientException = - new CmpClientException("IOException occurred while creating protectedBytes", ioe); - LOGGER.error("IOException occurred while creating protectedBytes"); - throw cmpClientException; - } - return res; - } - - /** - * Generates a PKIHeader Builder object. - * - * @param subjectDn distinguished name of Subject - * @param issuerDn distinguished name of external CA - * @param protectionAlg protection Algorithm used to protect PKIMessage - * @return PKIHeaderBuilder - */ - static PKIHeader generatePkiHeader( - X500Name subjectDn, X500Name issuerDn, AlgorithmIdentifier protectionAlg, String senderKid) { - LOGGER.info("Generating a Pki Header Builder"); - PKIHeaderBuilder pkiHeaderBuilder = - new PKIHeaderBuilder( - PKIHeader.CMP_2000, new GeneralName(subjectDn), new GeneralName(issuerDn)); - - pkiHeaderBuilder.setMessageTime(new ASN1GeneralizedTime(new Date())); - pkiHeaderBuilder.setSenderNonce(new DEROctetString(createRandomBytes())); - pkiHeaderBuilder.setTransactionID(new DEROctetString(createRandomBytes())); - pkiHeaderBuilder.setProtectionAlg(protectionAlg); - pkiHeaderBuilder.setGeneralInfo(new InfoTypeAndValue(CMPObjectIdentifiers.it_implicitConfirm)); - pkiHeaderBuilder.setSenderKID(new DEROctetString(senderKid.getBytes())); - - return pkiHeaderBuilder.build(); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/Cmpv2HttpClient.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/Cmpv2HttpClient.java deleted file mode 100644 index 68c743d2..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/Cmpv2HttpClient.java +++ /dev/null @@ -1,83 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.impl; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.bouncycastle.asn1.cmp.PKIMessage; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class Cmpv2HttpClient { - - private static final Logger LOG = LoggerFactory.getLogger(Cmpv2HttpClient.class); - - private static final String CONTENT_TYPE = "Content-type"; - private static final String CMP_REQUEST_MIMETYPE = "application/pkixcmp"; - private final CloseableHttpClient httpClient; - - /** - * constructor for Cmpv2HttpClient - * - * @param httpClient CloseableHttpClient used for sending/recieve request. - */ - Cmpv2HttpClient(CloseableHttpClient httpClient) { - this.httpClient = httpClient; - } - - /** - * Send Post Request to Server - * - * @param pkiMessage PKIMessage to send to server - * @param urlString url for the server we're sending request - * @param caName name of CA server - * @return PKIMessage received from CMPServer - * @throws CmpClientException thrown if problems with connecting or parsing response to server - */ - public byte[] postRequest( - final PKIMessage pkiMessage, final String urlString, final String caName) - throws CmpClientException { - try (ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream()) { - final HttpPost postRequest = new HttpPost(urlString); - final byte[] requestBytes = pkiMessage.getEncoded(); - - postRequest.setEntity(new ByteArrayEntity(requestBytes)); - postRequest.setHeader(CONTENT_TYPE, CMP_REQUEST_MIMETYPE); - - try (CloseableHttpResponse response = httpClient.execute(postRequest)) { - response.getEntity().writeTo(byteArrOutputStream); - } - return byteArrOutputStream.toByteArray(); - } catch (IOException ioe) { - CmpClientException cmpClientException = - new CmpClientException( - String.format("IOException error while trying to connect CA %s", caName), ioe); - LOG.error("IOException error {}, while trying to connect CA {}", ioe.getMessage(), caName); - throw cmpClientException; - } - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CreateCertRequest.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CreateCertRequest.java deleted file mode 100644 index 74380d84..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/impl/CreateCertRequest.java +++ /dev/null @@ -1,128 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.impl; - -import static org.onap.aaf.certservice.cmpv2client.impl.CmpUtil.createRandomBytes; -import static org.onap.aaf.certservice.cmpv2client.impl.CmpUtil.createRandomInt; -import static org.onap.aaf.certservice.cmpv2client.impl.CmpUtil.generatePkiHeader; - -import java.security.KeyPair; -import java.util.Date; -import java.util.List; - -import org.bouncycastle.asn1.cmp.PKIBody; -import org.bouncycastle.asn1.cmp.PKIHeader; -import org.bouncycastle.asn1.cmp.PKIMessage; -import org.bouncycastle.asn1.crmf.CertReqMessages; -import org.bouncycastle.asn1.crmf.CertReqMsg; -import org.bouncycastle.asn1.crmf.CertRequest; -import org.bouncycastle.asn1.crmf.CertTemplateBuilder; -import org.bouncycastle.asn1.crmf.ProofOfPossession; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; - -/** - * Implementation of the CmpClient Interface conforming to RFC4210 (Certificate Management Protocol - * (CMP)) and RFC4211 (Certificate Request Message Format (CRMF)) standards. - */ -class CreateCertRequest { - - private X500Name issuerDn; - private X500Name subjectDn; - private List sansList; - private KeyPair subjectKeyPair; - private Date notBefore; - private Date notAfter; - private String initAuthPassword; - private String senderKid; - - private static final int ITERATIONS = createRandomInt(5000); - private static final byte[] SALT = createRandomBytes(); - private final int certReqId = createRandomInt(Integer.MAX_VALUE); - - public void setIssuerDn(X500Name issuerDn) { - this.issuerDn = issuerDn; - } - - public void setSubjectDn(X500Name subjectDn) { - this.subjectDn = subjectDn; - } - - public void setSansList(List sansList) { - this.sansList = sansList; - } - - public void setSubjectKeyPair(KeyPair subjectKeyPair) { - this.subjectKeyPair = subjectKeyPair; - } - - public void setNotBefore(Date notBefore) { - this.notBefore = notBefore; - } - - public void setNotAfter(Date notAfter) { - this.notAfter = notAfter; - } - - public void setInitAuthPassword(String initAuthPassword) { - this.initAuthPassword = initAuthPassword; - } - - public void setSenderKid(String senderKid) { - this.senderKid = senderKid; - } - - /** - * Method to create {@link PKIMessage} from {@link CertRequest},{@link ProofOfPossession}, {@link - * CertReqMsg}, {@link CertReqMessages}, {@link PKIHeader} and {@link PKIBody}. - * - * @return {@link PKIMessage} - */ - public PKIMessage generateCertReq() throws CmpClientException { - final CertTemplateBuilder certTemplateBuilder = - new CertTemplateBuilder() - .setIssuer(issuerDn) - .setSubject(subjectDn) - .setExtensions(CmpMessageHelper.generateExtension(sansList)) - .setValidity(CmpMessageHelper.generateOptionalValidity(notBefore, notAfter)) - .setPublicKey( - SubjectPublicKeyInfo.getInstance(subjectKeyPair.getPublic().getEncoded())); - - final CertRequest certRequest = new CertRequest(certReqId, certTemplateBuilder.build(), null); - final ProofOfPossession proofOfPossession = - CmpMessageHelper.generateProofOfPossession(certRequest, subjectKeyPair); - - final CertReqMsg certReqMsg = new CertReqMsg(certRequest, proofOfPossession, null); - final CertReqMessages certReqMessages = new CertReqMessages(certReqMsg); - - final PKIHeader pkiHeader = - generatePkiHeader( - subjectDn, - issuerDn, - CmpMessageHelper.protectionAlgoIdentifier(ITERATIONS, SALT), - senderKid); - final PKIBody pkiBody = new PKIBody(PKIBody.TYPE_INIT_REQ, certReqMessages); - - return CmpMessageHelper.protectPkiMessage( - pkiHeader, pkiBody, initAuthPassword, ITERATIONS, SALT); - } -} diff --git a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/model/Cmpv2CertificationModel.java b/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/model/Cmpv2CertificationModel.java deleted file mode 100644 index 5d48b978..00000000 --- a/certService/src/main/java/org/onap/aaf/certservice/cmpv2client/model/Cmpv2CertificationModel.java +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * 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. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.aaf.certservice.cmpv2client.model; - -import java.security.cert.X509Certificate; -import java.util.Collections; -import java.util.List; - -public class Cmpv2CertificationModel { - - private final List certificateChain; - private final List trustedCertificates; - - public Cmpv2CertificationModel(List certificateChain, List trustedCertificates) { - this.certificateChain = certificateChain; - this.trustedCertificates = trustedCertificates; - } - - public List getCertificateChain() { - return Collections.unmodifiableList(certificateChain); - } - - public List getTrustedCertificates() { - return Collections.unmodifiableList(trustedCertificates); - } -} diff --git a/certService/src/main/java/org/onap/oom/certservice/CertServiceApplication.java b/certService/src/main/java/org/onap/oom/certservice/CertServiceApplication.java new file mode 100644 index 00000000..c320d461 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/CertServiceApplication.java @@ -0,0 +1,37 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication +@PropertySource(value = {"classpath:application.properties"}) +public class CertServiceApplication { + + // We are excluding this line in Sonar due to fact that + // Spring is handling arguments + public static void main(String[] args) { // NOSONAR + SpringApplication.run(CertServiceApplication.class, args); + } + +} 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 new file mode 100644 index 00000000..d3a83ed1 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java @@ -0,0 +1,96 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +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.exception.DecryptionException; +import org.onap.oom.certservice.certification.exception.ErrorResponseModel; +import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +@Tag(name = "CertificationService") +public class CertificationController { + + private static final Logger LOGGER = LoggerFactory.getLogger(CertificationController.class); + + private final CertificationModelFactory certificationModelFactory; + + @Autowired + CertificationController(CertificationModelFactory certificationModelFactory) { + this.certificationModelFactory = certificationModelFactory; + } + + /** + * Request for signing certificate by given CA. + * + * @param caName the name of Certification Authority that will sign root certificate + * @param encodedCsr Certificate Sign Request encoded in Base64 form + * @param encodedPrivateKey Private key for CSR, needed for PoP, encoded in Base64 form + * @return JSON containing trusted certificates and certificate chain + */ + @GetMapping(value = "v1/certificate/{caName}", produces = "application/json") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Certificate successfully signed"), + @ApiResponse(responseCode = "400", description = "Given CSR or/and PK is incorrect", + content = @Content(schema = @Schema(implementation = ErrorResponseModel.class))), + @ApiResponse(responseCode = "404", description = "CA not found for given name", + content = @Content(schema = @Schema(implementation = ErrorResponseModel.class))), + @ApiResponse(responseCode = "500", description = "Something went wrong during connectiion to CMPv2 server", + content = @Content(schema = @Schema(implementation = ErrorResponseModel.class))) + }) + @Operation( + summary = "sign certificate", + description = "Web endpoint for requesting certificate signing. Used by system components to gain certificate signed by CA.", + tags = {"CertificationService"}) + public ResponseEntity 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).") + @RequestHeader("CSR") String encodedCsr, + @Parameter(description = "Private key in form of PEM object encoded in Base64 (with header and footer).") + @RequestHeader("PK") String encodedPrivateKey + ) throws DecryptionException, CmpClientException { + caName = caName.replaceAll("[\n|\r|\t]", "_"); + LOGGER.info("Received certificate signing request for CA named: {}", caName); + CertificationModel certificationModel = certificationModelFactory + .createCertificationModel(encodedCsr, encodedPrivateKey, caName); + return new ResponseEntity<>(certificationModel, HttpStatus.OK); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/api/ReadinessController.java b/certService/src/main/java/org/onap/oom/certservice/api/ReadinessController.java new file mode 100644 index 00000000..3be54fd2 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/api/ReadinessController.java @@ -0,0 +1,61 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.api; + +import io.swagger.v3.oas.annotations.Operation; +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.configuration.CmpServersConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Tag(name = "CertificationService") +public final class ReadinessController { + + private final CmpServersConfig cmpServersConfig; + + @Autowired + public ReadinessController(CmpServersConfig cmpServersConfig) { + this.cmpServersConfig = cmpServersConfig; + } + + @GetMapping(value = "/ready", produces = "application/json") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Configuration is loaded and service is ready to use"), + @ApiResponse(responseCode = "503", description = "Configuration loading failed and service is unavailable") + }) + @Operation( + summary = "Check if CertService application is ready", + description = "Web endpoint for checking if service is ready to be used.", + tags = {"CertificationService"}) + public ResponseEntity checkReady() { + if (cmpServersConfig.isReady()) { + return new ResponseEntity<>(HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); + } + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/api/ReloadConfigController.java b/certService/src/main/java/org/onap/oom/certservice/api/ReloadConfigController.java new file mode 100644 index 00000000..b510d4f0 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/api/ReloadConfigController.java @@ -0,0 +1,64 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +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.configuration.CmpServersConfig; +import org.onap.oom.certservice.certification.configuration.CmpServersConfigLoadingException; +import org.onap.oom.certservice.certification.exception.ErrorResponseModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Tag(name = "CertificationService") +public final class ReloadConfigController { + + private final CmpServersConfig cmpServersConfig; + + @Autowired + public ReloadConfigController(CmpServersConfig cmpServersConfig) { + this.cmpServersConfig = cmpServersConfig; + } + + @GetMapping(value = "/reload", produces = "application/json") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Configuration has been successfully reloaded"), + @ApiResponse(responseCode = "500", description = "Something went wrong during configuration loading", + content = @Content(schema = @Schema(implementation = ErrorResponseModel.class))) + }) + @Operation( + summary = "Reload CMPv2 servers configuration from configuration file", + description = "Web endpoint for performing configuration reload. Used to reload configuration from file.", + tags = {"CertificationService"}) + public ResponseEntity reloadConfiguration() throws CmpServersConfigLoadingException { + cmpServersConfig.reloadConfiguration(); + return new ResponseEntity<>(HttpStatus.OK); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/api/advice/CertificationExceptionAdvice.java b/certService/src/main/java/org/onap/oom/certservice/api/advice/CertificationExceptionAdvice.java new file mode 100644 index 00000000..5fb9d2ad --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/api/advice/CertificationExceptionAdvice.java @@ -0,0 +1,100 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.api.advice; + +import org.onap.oom.certservice.api.CertificationController; +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.ErrorResponseModel; +import org.onap.oom.certservice.certification.exception.KeyDecryptionException; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice(assignableTypes = CertificationController.class) +public final class CertificationExceptionAdvice { + + private static final Logger LOGGER = LoggerFactory.getLogger(CertificationExceptionAdvice.class); + + @ExceptionHandler(value = CsrDecryptionException.class) + public ResponseEntity handle(CsrDecryptionException exception) { + LOGGER.error("Exception occurred during decoding certificate sign request:", exception); + return getErrorResponseEntity( + "Wrong certificate signing request (CSR) format", + HttpStatus.BAD_REQUEST + ); + } + + @ExceptionHandler(value = KeyDecryptionException.class) + public ResponseEntity handle(KeyDecryptionException exception) { + LOGGER.error("Exception occurred during decoding key:", exception); + return getErrorResponseEntity( + "Wrong key (PK) format", + HttpStatus.BAD_REQUEST + ); + } + + @ExceptionHandler(value = Cmpv2ServerNotFoundException.class) + public ResponseEntity handle(Cmpv2ServerNotFoundException exception) { + LOGGER.error("Exception occurred selecting CMPv2 server:", exception); + return getErrorResponseEntity( + "Certification authority not found for given CAName", + HttpStatus.NOT_FOUND + ); + } + + @ExceptionHandler(value = RuntimeException.class) + public ResponseEntity handle(RuntimeException exception) throws CmpClientException { + throw new CmpClientException("Runtime exception occurred calling cmp client business logic", exception); + } + + @ExceptionHandler(value = CmpClientException.class) + public ResponseEntity handle(CmpClientException exception) { + LOGGER.error("Exception occurred calling cmp client:", exception); + return getErrorResponseEntity( + "Exception occurred during call to cmp client", + HttpStatus.INTERNAL_SERVER_ERROR + ); + } + + @ExceptionHandler(value = Cmpv2ClientAdapterException.class) + public ResponseEntity handle(Cmpv2ClientAdapterException exception) { + LOGGER.error("Exception occurred parsing cmp client response:", exception); + return getErrorResponseEntity( + "Exception occurred parsing cmp client response", + HttpStatus.INTERNAL_SERVER_ERROR + ); + } + + private ResponseEntity getErrorResponseEntity(String errorMessage, HttpStatus status) { + ErrorResponseModel errorResponse = new ErrorResponseModel(errorMessage); + return new ResponseEntity<>( + errorResponse, + status + ); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/api/advice/ReloadConfigExceptionAdvice.java b/certService/src/main/java/org/onap/oom/certservice/api/advice/ReloadConfigExceptionAdvice.java new file mode 100644 index 00000000..b52111de --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/api/advice/ReloadConfigExceptionAdvice.java @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.api.advice; + +import org.onap.oom.certservice.api.ReloadConfigController; +import org.onap.oom.certservice.certification.configuration.CmpServersConfigLoadingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice(assignableTypes = ReloadConfigController.class) +public final class ReloadConfigExceptionAdvice { + + private static final Logger LOGGER = LoggerFactory.getLogger(ReloadConfigExceptionAdvice.class); + + @ExceptionHandler(value = CmpServersConfigLoadingException.class) + public ResponseEntity handle(CmpServersConfigLoadingException exception) { + LOGGER.error(exception.getMessage(), exception.getCause()); + return new ResponseEntity<>(exception.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/api/configuration/OpenApiConfig.java b/certService/src/main/java/org/onap/oom/certservice/api/configuration/OpenApiConfig.java new file mode 100644 index 00000000..9a5840ab --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/api/configuration/OpenApiConfig.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.api.configuration; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class OpenApiConfig { + + @Bean + public OpenAPI customOpenApi() { + return new OpenAPI() + .components(new Components()) + .info( + new Info() + .title("CertService Documentation") + .description("Certification service API documentation") + .version("1.0.1") + ); + } + +} 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 new file mode 100644 index 00000000..93fa4c21 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/CertificateFactoryProvider.java @@ -0,0 +1,42 @@ +/* + * ============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/CertificationData.java b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationData.java new file mode 100644 index 00000000..11e81807 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationData.java @@ -0,0 +1,128 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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; + + +final class CertificationData { + + private CertificationData() { + } + + private static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"; + private static final String END_CERTIFICATE = "-----END CERTIFICATE-----"; + + static final String EXTRA_CA_CERT = "" + + BEGIN_CERTIFICATE + + "MIIDvzCCAqcCFF5DejiyfoNfPiiMmBXulniBewBGMA0GCSqGSIb3DQEBCwUAMIGb\n" + + "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\n" + + "LUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwE\n" + + "T05BUDEVMBMGA1UEAwwMbmV3Lm9uYXAub3JnMR4wHAYJKoZIhvcNAQkBFg90ZXN0\n" + + "ZXJAb25hcC5vcmcwHhcNMjAwMjEyMDk1OTM3WhcNMjEwMjExMDk1OTM3WjCBmzEL\n" + + "MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbi1G\n" + + "cmFuY2lzY28xGTAXBgNVBAoMEExpbnV4LUZvdW5kYXRpb24xDTALBgNVBAsMBE9O\n" + + "QVAxFTATBgNVBAMMDG5ldy5vbmFwLm9yZzEeMBwGCSqGSIb3DQEJARYPdGVzdGVy\n" + + "QG9uYXAub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtF4FXeDV\n" + + "ng/inC/bTACmZnLC9IiC7PyG/vVbMxxN1bvQLRAwC/Hbl3i9zD68Vs/jPPr/SDr9\n" + + "2rgItdDdUY1V30Y3PT06F11XdEaRb+t++1NX0rDf1AqPaBZgnBmB86s1wbqHdJTr\n" + + "wEImDZ5xMPfP3fiWy/9Yw/U7iRMIi1/oI0lWuHJV0bn908shuJ6dvInpRCoDnoTX\n" + + "YP/FiDSZCFVewQcq4TigB7kRqZrDcPZWbSlqHklDMXRwbCxAiFSziuX6TBwru9Rn\n" + + "HhIeXVSgMU1ZSSopVbJGtQ4zSsU1nvTK5Bhc2UHGcAOZy1xTN5D9EEbTqh7l+Wtx\n" + + "y8ojkEXvFG8lVwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAE+bUphwHit78LK8sb\n" + + "OMjt4DiEu32KeSJOpYgPLeBeAIynaNsa7sQrpuxerGNTmQWIcw6olXI0J+OOwkik\n" + + "II7elrYtd5G1uALxXWdamNsaY0Du34moVL1YjexJ7qQ4oBUxg2tuY8NAQGDK+23I\n" + + "nCA+ZwzdTJo73TYS6sx64d/YLWkX4nHGUoMlF+xUH34csDyhpuTSzQhC2quB5N8z\n" + + "tSFdpe4z2jqx07qo2EBFxi03EQ8Q0ex6l421QM2gbs7cZQ66K0DkpPcF2+iHZnyx\n" + + "xq1lnlsWHklElF2bhyXTn3fPp5wtan00P8IolKx7CAWb92QjkW6M0RvTW/xuwIzh\n" + + "0rTO\n" + + END_CERTIFICATE; + + static final String CA_CERT = "" + + BEGIN_CERTIFICATE + + "MIIDtzCCAp8CFAwqQddh4/iyGfP8UZ3dpXlxfAN8MA0GCSqGSIb3DQEBCwUAMIGX\n" + + "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\n" + + "LUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwE\n" + + "T05BUDERMA8GA1UEAwwIb25hcC5vcmcxHjAcBgkqhkiG9w0BCQEWD3Rlc3RlckBv\n" + + "bmFwLm9yZzAeFw0yMDAyMTIwOTM0MjdaFw0yMTAyMTEwOTM0MjdaMIGXMQswCQYD\n" + + "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuLUZyYW5j\n" + + "aXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwET05BUDER\n" + + "MA8GA1UEAwwIb25hcC5vcmcxHjAcBgkqhkiG9w0BCQEWD3Rlc3RlckBvbmFwLm9y\n" + + "ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCFrnO7/eT6V+7XkPPd\n" + + "eiL/6xXreuegvit/1/jTVjG+3AOVcmTn2WXwXXRcQLvkWQfJVPoltsY8E3FqFRti\n" + + "797XjY6cdQJFVDyzNU0+Fb4vJL9FK5wSvnS6EFjBEn3JvXRlENorDCs/mfjkjJoa\n" + + "Dl74gXQEJYcg4nsTeNIj7cm3Q7VK3mZt1t7LSJJ+czxv69UJDuNJpmQ/2WOKyLZA\n" + + "gTtBJ+Hyol45/OLsrqwq1dAn9ZRWIFPvRt/XQYH9bI/6MtqSreRVUrdYCiTe/XpP\n" + + "B/OM6NEi2+p5QLi3Yi70CEbqP3HqUVbkzF+r7bwIb6M5/HxfqzLmGwLvD+6rYnUn\n" + + "Bm8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAhXoO65DXth2X/zFRNsCNpLwmDy7r\n" + + "PxT9ZAIZAzSxx3/aCYiuTrKP1JnqjkO+F2IbikrI4n6sKO49SKnRf9SWTFhd+5dX\n" + + "vxq5y7MaqxHAY9J7+Qzq33+COVFQnaF7ddel2NbyUVb2b9ZINNsaZkkPXui6DtQ7\n" + + "/Fb/1tmAGWd3hMp75G2thBSzs816JMKKa9WD+4VGATEs6OSll4sv2fOZEn+0mAD3\n" + + "9q9c+WtLGIudOwcHwzPb2njtNntQSCK/tVOqbY+vzhMY3JW+p9oSrLDSdGC+pAKK\n" + + "m/wB+2VPIYcsPMtIhHC4tgoSaiCqjXYptaOh4b8ye8CPBUCpX/AYYkN0Ow==\n" + + END_CERTIFICATE; + + static final String INTERMEDIATE_CERT = "" + + BEGIN_CERTIFICATE + + "MIIDqTCCApGgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNVBAYTAlVT\n" + + "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw\n" + + "FwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQD\n" + + "DAhvbmFwLm9yZzEeMBwGCSqGSIb3DQEJARYPdGVzdGVyQG9uYXAub3JnMB4XDTIw\n" + + "MDIxMjA5NDAxMloXDTIyMTEwODA5NDAxMlowgYQxCzAJBgNVBAYTAlVTMRMwEQYD\n" + + "VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQK\n" + + "DBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQDDBVpbnRl\n" + + "cm1lZGlhdGUub25hcC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n" + + "AQC1oOYMZ6G+2DGDAizYnzdCNiogivlht1s4oqgem7fM1XFPxD2p31ATIibOdqr/\n" + + "gv1qemO9Q4r1xn6w1Ufq7T1K7PjnMzdSeTqZefurE2JM/HHx2QvW4TjMlz2ILgaD\n" + + "L1LN60kmMQSOi5VxKJpsrCQxbOsxhvefd212gny5AZMcjJe23kUd9OxUrtvpdLEv\n" + + "wI3vFEvT7oRUnEUg/XNz7qeg33vf1C39yMR+6O4s6oevgsEebVKjb+yOoS6zzGtz\n" + + "72wZjm07C54ZlO+4Uy+QAlMjRiU3mgWkKbkOy+4CvwehjhpTikdBs2DX39ZLGHhn\n" + + "L/0a2NYtGulp9XEqmTvRoI+PAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" + + "hvcNAQELBQADggEBADcitdJ6YswiV8jAD9GK0gf3+zqcGegt4kt+79JXlXYbb1sY\n" + + "q3o6prcB7nSUoClgF2xUPCslFGpM0Er9FCSFElQM/ru0l/KVmJS6kSpwEHvsYIH3\n" + + "q5anta+Pyk8JSQWAAw+qrind0uBQMnhR8Tn13tgV+Kjvg/xlH/nZIEdN5YtLB1cA\n" + + "beVsZRyRfVL9DeZU8s/MZ5wC3kgcEp5A4m5lg7HyBxBdqhzFcDr6xiy6OGqW8Yep\n" + + "xrwfc8Fw8a/lOv4U+tBeGNKPQDYaL9hh+oM+qMkNXsHXDqdJsuEGJtU4i3Wcwzoc\n" + + "XGN5NWV//4bP+NFmwgcn7AYCdRvz04A8GU/0Cwg=\n" + + END_CERTIFICATE; + + static final String ENTITY_CERT = "" + + BEGIN_CERTIFICATE + + "MIIDjDCCAnSgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwgYQxCzAJBgNVBAYTAlVT\n" + + "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw\n" + + "FwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQD\n" + + "DBVpbnRlcm1lZGlhdGUub25hcC5vcmcwHhcNMjAwMjEyMDk1MTI2WhcNMjIxMTA4\n" + + "MDk1MTI2WjB7MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG\n" + + "A1UEBwwNU2FuLUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjEN\n" + + "MAsGA1UECwwET05BUDEVMBMGA1UEAwwMdmlkLm9uYXAub3JnMIIBIjANBgkqhkiG\n" + + "9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+GIRzJzUOh0gtc+wzFJEdTnn+q5F10L0Yhr\n" + + "G1xKdjPieHIFGsoiXwcuCU8arNSqlz7ocx62KQRkcA8y6edlOAsYtdOEJvqEI9vc\n" + + "eyTB/HYsbzw3URPGch4AmibrQkKU9QvGwouHtHn4R2Ft2Y0tfEqv9hxj9v4njq4A\n" + + "EiDLAFLl5FmVyCZu/MtKngSgu1smcaFKTYySPMxytgJZexoa/ALZyyE0gRhsvwHm\n" + + "NLGCPt1bmE/PEGZybsCqliyTO0S56ncD55The7+D/UDS4kE1Wg0svlWon/YsE6QW\n" + + "B3oeJDX7Kr8ebDTIAErevIAD7Sm4ee5se2zxYrsYlj0MzHZtvwIDAQABoxAwDjAM\n" + + "BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCvQ1pTvjON6vSlcJRKSY4r\n" + + "8q7L4/9ZaVXWJAjzEYJtPIqsgGiPWz0vGfgklowU6tZxp9zRZFXfMil+mPQSe+yo\n" + + "ULrZSQ/z48YHPueE/BNO/nT4aaVBEhPLR5aVwC7uQVX8H+m1V1UGT8lk9vdI9rej\n" + + "CI9l524sLCpdE4dFXiWK2XHEZ0Vfylk221u3IYEogVVA+UMX7BFPSsOnI2vtYK/i\n" + + "lwZtlri8LtTusNe4oiTkYyq+RSyDhtAswg8ANgvfHolhCHoLFj6w1IkG88UCmbwN\n" + + "d7BoGMy06y5MJxyXEZG0vR7eNeLey0TIh+rAszAFPsIQvrOHW+HuA+WLQAj1mhnm\n" + + END_CERTIFICATE; + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java new file mode 100644 index 00000000..23440ac5 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java @@ -0,0 +1,70 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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 org.onap.oom.certservice.certification.configuration.Cmpv2ServerProvider; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.exception.DecryptionException; +import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.certification.model.CsrModel; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class CertificationModelFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(CertificationModelFactory.class); + + private final CsrModelFactory csrModelFactory; + private final Cmpv2ServerProvider cmpv2ServerProvider; + private final CertificationProvider certificationProvider; + + @Autowired + CertificationModelFactory( + CsrModelFactory csrModelFactory, + Cmpv2ServerProvider cmpv2ServerProvider, + CertificationProvider certificationProvider + ) { + this.cmpv2ServerProvider = cmpv2ServerProvider; + this.csrModelFactory = csrModelFactory; + this.certificationProvider = certificationProvider; + } + + public CertificationModel createCertificationModel(String encodedCsr, String encodedPrivateKey, String caName) + throws DecryptionException, CmpClientException { + CsrModel csrModel = csrModelFactory.createCsrModel( + new CsrModelFactory.StringBase64(encodedCsr), + new CsrModelFactory.StringBase64(encodedPrivateKey) + ); + LOGGER.debug("Received CSR meta data: \n{}", csrModel); + + Cmpv2Server cmpv2Server = cmpv2ServerProvider.getCmpv2Server(caName); + LOGGER.debug("Found server for given CA name: \n{}", cmpv2Server); + + LOGGER.info("Sending sign request for certification model for CA named: {}, and certificate signing request:\n{}", + caName, csrModel); + return certificationProvider.signCsr(csrModel, cmpv2Server); + } + +} 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 new file mode 100644 index 00000000..91148a22 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java @@ -0,0 +1,78 @@ +/* + * ============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 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.CsrModel; +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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.io.StringWriter; +import java.security.cert.X509Certificate; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class CertificationProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(CertificationProvider.class); + + private final CmpClient cmpClient; + + @Autowired + public CertificationProvider(CmpClient cmpClient) { + this.cmpClient = cmpClient; + } + + public CertificationModel signCsr(CsrModel csrModel, Cmpv2Server server) + throws CmpClientException { + Cmpv2CertificationModel certificates = cmpClient.createCertificate(csrModel, server); + return new CertificationModel(convertFromX509CertificateListToPemList(certificates.getCertificateChain()), + convertFromX509CertificateListToPemList(certificates.getTrustedCertificates())); + } + + private static List convertFromX509CertificateListToPemList(List certificates) { + return certificates.stream().map(CertificationProvider::convertFromX509CertificateToPem).filter(cert -> !cert.isEmpty()) + .collect(Collectors.toList()); + } + + private static String convertFromX509CertificateToPem(X509Certificate certificate) { + StringWriter sw = new StringWriter(); + try (PemWriter pw = new PemWriter(sw)) { + PemObjectGenerator gen = new JcaMiscPEMGenerator(certificate); + pw.writeObject(gen); + } catch (IOException e) { + LOGGER.error("Exception occurred during convert of X509 certificate", e); + } + return sw.toString(); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/CsrModelFactory.java b/certService/src/main/java/org/onap/oom/certservice/certification/CsrModelFactory.java new file mode 100644 index 00000000..758427f6 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/CsrModelFactory.java @@ -0,0 +1,113 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.util.Base64; +import java.util.Objects; +import java.util.Optional; + +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.util.io.pem.PemObject; +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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + + +@Service +public class CsrModelFactory { + + private final PemObjectFactory pemObjectFactory + = new PemObjectFactory(); + private final Pkcs10CertificationRequestFactory certificationRequestFactory + = new Pkcs10CertificationRequestFactory(); + + + public CsrModel createCsrModel(StringBase64 csr, StringBase64 privateKey) + throws DecryptionException { + PKCS10CertificationRequest decodedCsr = decodeCsr(csr); + PemObject decodedPrivateKey = decodePrivateKey(privateKey); + return new CsrModel.CsrModelBuilder(decodedCsr, decodedPrivateKey).build(); + } + + private PemObject decodePrivateKey(StringBase64 privateKey) + throws KeyDecryptionException { + + return privateKey.asString() + .flatMap(pemObjectFactory::createPemObject) + .orElseThrow( + () -> new KeyDecryptionException("Incorrect Key, decryption failed") + ); + } + + private PKCS10CertificationRequest decodeCsr(StringBase64 csr) + throws CsrDecryptionException { + return csr.asString() + .flatMap(pemObjectFactory::createPemObject) + .flatMap(certificationRequestFactory::createPkcs10CertificationRequest) + .orElseThrow( + () -> new CsrDecryptionException("Incorrect CSR, decryption failed") + ); + } + + public static class StringBase64 { + private final String value; + private final Base64.Decoder decoder = Base64.getDecoder(); + private static final Logger LOGGER = LoggerFactory.getLogger(StringBase64.class); + + public StringBase64(String value) { + this.value = value; + } + + public Optional asString() { + try { + String decodedString = new String(decoder.decode(value)); + return Optional.of(decodedString); + } catch (RuntimeException e) { + LOGGER.error("Exception occurred during decoding:", e); + return Optional.empty(); + } + } + + @Override + public boolean equals(Object otherObject) { + if (this == otherObject) { + return true; + } + if (otherObject == null || getClass() != otherObject.getClass()) { + return false; + } + StringBase64 that = (StringBase64) otherObject; + return Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + } + +} + + diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/PemObjectFactory.java b/certService/src/main/java/org/onap/oom/certservice/certification/PemObjectFactory.java new file mode 100644 index 00000000..24d32bdd --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/PemObjectFactory.java @@ -0,0 +1,49 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.IOException; +import java.io.StringReader; +import java.util.Optional; + +import org.bouncycastle.util.encoders.DecoderException; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class PemObjectFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(PemObjectFactory.class); + + public Optional createPemObject(String pem) { + + try (StringReader stringReader = new StringReader(pem); + PemReader pemReader = new PemReader(stringReader)) { + return Optional.ofNullable(pemReader.readPemObject()); + } catch (DecoderException | IOException e) { + LOGGER.error("Exception occurred during creation of PEM:", e); + return Optional.empty(); + } + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/Pkcs10CertificationRequestFactory.java b/certService/src/main/java/org/onap/oom/certservice/certification/Pkcs10CertificationRequestFactory.java new file mode 100644 index 00000000..c38eb0a1 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/Pkcs10CertificationRequestFactory.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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 org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.util.encoders.DecoderException; +import org.bouncycastle.util.io.pem.PemObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Optional; + +public class Pkcs10CertificationRequestFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(Pkcs10CertificationRequestFactory.class); + + public Optional createPkcs10CertificationRequest(PemObject pemObject) { + try { + LOGGER.debug("Creating certification request from pem object"); + return Optional.of(new PKCS10CertificationRequest(pemObject.getContent())); + } catch (DecoderException | IOException e) { + LOGGER.error("Exception occurred during creation of certification request:", e); + return Optional.empty(); + } + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/RsaContentSignerBuilder.java b/certService/src/main/java/org/onap/oom/certservice/certification/RsaContentSignerBuilder.java new file mode 100644 index 00000000..741b20ab --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/RsaContentSignerBuilder.java @@ -0,0 +1,46 @@ +/* + * ============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.IOException; +import java.security.PrivateKey; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.crypto.util.PrivateKeyFactory; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.springframework.stereotype.Component; + +@Component +public class RsaContentSignerBuilder { + + ContentSigner build(PKCS10CertificationRequest csr, PrivateKey privateKey) + throws IOException, OperatorCreationException { + AlgorithmIdentifier sigAlgId = csr.getSignatureAlgorithm(); + AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId); + + return new BcRSAContentSignerBuilder(sigAlgId, digAlgId) + .build(PrivateKeyFactory.createKey(privateKey.getEncoded())); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/X509CertificateBuilder.java b/certService/src/main/java/org/onap/oom/certservice/certification/X509CertificateBuilder.java new file mode 100644 index 00000000..67aecb7c --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/X509CertificateBuilder.java @@ -0,0 +1,56 @@ +/* + * ============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.IOException; +import java.math.BigInteger; +import java.security.SecureRandom; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Date; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.springframework.stereotype.Component; + +@Component +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 { + 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)), + new PKCS10CertificationRequest(csr.getEncoded()).getSubject(), + SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(csr.getSubjectPublicKeyInfo().getEncoded()))); + + } + + private BigInteger createSerial() { + byte[] serial = new byte[SECURE_NEXT_BYTES]; + new SecureRandom().nextBytes(serial); + return new BigInteger(serial).abs(); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpClientConfig.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpClientConfig.java new file mode 100644 index 00000000..9cf6fd15 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpClientConfig.java @@ -0,0 +1,50 @@ +/* + * ============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.configuration; + +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.onap.oom.certservice.cmpv2client.api.CmpClient; +import org.onap.oom.certservice.cmpv2client.impl.CmpClientImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.context.annotation.RequestScope; + +@Configuration +public class CmpClientConfig { + + @Bean + CmpClient cmpClient(CloseableHttpClient closeableHttpClient) { + return new CmpClientImpl(closeableHttpClient); + } + + @Bean + @RequestScope + CloseableHttpClient closeableHttpClient(HttpClientBuilder httpClientBuilder) { + return httpClientBuilder.build(); + } + + @Bean + HttpClientBuilder httpClientBuilder() { + return HttpClientBuilder.create(); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfig.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfig.java new file mode 100644 index 00000000..727f685d --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfig.java @@ -0,0 +1,87 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration; + +import java.io.File; +import java.util.Collections; +import java.util.List; +import javax.annotation.PostConstruct; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CmpServersConfig { + + private static final Logger LOGGER = LoggerFactory.getLogger(CmpServersConfig.class); + private static final String INIT_CONFIGURATION = "Loading initial configuration"; + private static final String RELOADING_CONFIGURATION = "Reloading configuration"; + private static final String LOADING_SUCCESS_MESSAGE = "CMP Servers configuration successfully loaded from file {}"; + private static final String CMP_SERVERS_CONFIG_FILENAME = "cmpServers.json"; + + private final String configPath; + private final CmpServersConfigLoader cmpServersConfigLoader; + + private List cmpServers; + private volatile boolean isReady; + + @Autowired + public CmpServersConfig(@Value("${app.config.path}") String configPath, + CmpServersConfigLoader cmpServersConfigLoader) { + this.cmpServersConfigLoader = cmpServersConfigLoader; + this.configPath = configPath; + } + + @PostConstruct + void init() { + try { + LOGGER.info(INIT_CONFIGURATION); + loadConfiguration(); + } catch (CmpServersConfigLoadingException e) { + LOGGER.error(e.getMessage(), e.getCause()); + } + } + + public void reloadConfiguration() throws CmpServersConfigLoadingException { + LOGGER.info(RELOADING_CONFIGURATION); + loadConfiguration(); + } + + + synchronized void loadConfiguration() throws CmpServersConfigLoadingException { + isReady = false; + String configFilePath = configPath + File.separator + CMP_SERVERS_CONFIG_FILENAME; + this.cmpServers = Collections.unmodifiableList(cmpServersConfigLoader.load(configFilePath)); + LOGGER.info(LOADING_SUCCESS_MESSAGE, configFilePath); + isReady = true; + } + + public List getCmpServers() { + return cmpServers; + } + + public boolean isReady() { + return isReady; + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoader.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoader.java new file mode 100644 index 00000000..72795b03 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoader.java @@ -0,0 +1,64 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; +import java.security.InvalidParameterException; +import java.util.List; + +import org.onap.oom.certservice.certification.configuration.model.CmpServers; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.configuration.validation.Cmpv2ServersConfigurationValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +class CmpServersConfigLoader { + + private static final String LOADING_EXCEPTION_MESSAGE = "Exception occurred during CMP Servers configuration loading"; + private static final String VALIDATION_EXCEPTION_MESSAGE = "Validation of CMPv2 servers configuration failed"; + + private final Cmpv2ServersConfigurationValidator validator; + + @Autowired + CmpServersConfigLoader(Cmpv2ServersConfigurationValidator validator) { + this.validator = validator; + } + + List load(String path) throws CmpServersConfigLoadingException { + try { + List servers = loadConfigFromFile(path).getCmpv2Servers(); + validator.validate(servers); + return servers; + } catch (IOException e) { + throw new CmpServersConfigLoadingException(LOADING_EXCEPTION_MESSAGE, e); + } catch (InvalidParameterException e) { + throw new CmpServersConfigLoadingException(VALIDATION_EXCEPTION_MESSAGE, e); + } + } + + private CmpServers loadConfigFromFile(String path) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(new File(path), CmpServers.class); + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoadingException.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoadingException.java new file mode 100644 index 00000000..de0a0729 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoadingException.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration; + +public class CmpServersConfigLoadingException extends Exception { + + public CmpServersConfigLoadingException(String message) { + super(message); + } + + public CmpServersConfigLoadingException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/Cmpv2ServerProvider.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/Cmpv2ServerProvider.java new file mode 100644 index 00000000..a8d43fe8 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/Cmpv2ServerProvider.java @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration; + +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.exception.Cmpv2ServerNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class Cmpv2ServerProvider { + + private final CmpServersConfig cmpServersConfig; + + @Autowired + Cmpv2ServerProvider(CmpServersConfig cmpServersConfig) { + this.cmpServersConfig = cmpServersConfig; + } + + public Cmpv2Server getCmpv2Server(String caName) { + return cmpServersConfig.getCmpServers().stream().filter(server -> server.getCaName().equals(caName)).findFirst() + .orElseThrow(() -> new Cmpv2ServerNotFoundException("No server found for given CA name")); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/Authentication.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/Authentication.java new file mode 100644 index 00000000..e354ca60 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/Authentication.java @@ -0,0 +1,60 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration.model; + +import javax.validation.constraints.NotNull; +import org.hibernate.validator.constraints.Length; + +public class Authentication { + + private static final int MAX_IAK_RV_LENGTH = 256; + + @NotNull + @Length(min = 1, max = MAX_IAK_RV_LENGTH) + private String iak; + @NotNull + @Length(min = 1, max = MAX_IAK_RV_LENGTH) + private String rv; + + public String getIak() { + return iak; + } + + public void setIak(String iak) { + this.iak = iak; + } + + public String getRv() { + return rv; + } + + public void setRv(String rv) { + this.rv = rv; + } + + @Override + public String toString() { + return "Authentication{" + + " iak=*****" + + ", rv=*****" + + '}'; + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/CaMode.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/CaMode.java new file mode 100644 index 00000000..9980ef50 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/CaMode.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration.model; + +public enum CaMode { + RA("RA"), CLIENT("Client"); + + private String profile; + + CaMode(String profile) { + this.profile = profile; + } + + public String getProfile() { + return profile; + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/CmpServers.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/CmpServers.java new file mode 100644 index 00000000..9fbe0eaf --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/CmpServers.java @@ -0,0 +1,37 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration.model; + +import java.util.List; + +public class CmpServers { + + private List cmpv2Servers; + + public List getCmpv2Servers() { + return cmpv2Servers; + } + + public void setCmpv2Servers(List cmpv2Servers) { + this.cmpv2Servers = cmpv2Servers; + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/Cmpv2Server.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/Cmpv2Server.java new file mode 100644 index 00000000..b27f2888 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/model/Cmpv2Server.java @@ -0,0 +1,98 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration.model; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import org.bouncycastle.asn1.x500.X500Name; +import org.hibernate.validator.constraints.Length; +import org.onap.oom.certservice.certification.configuration.validation.constraints.Cmpv2Url; + +public class Cmpv2Server { + + private static final int MAX_CA_NAME_LENGTH = 128; + + @NotNull + @Valid + private Authentication authentication; + @NotNull + private CaMode caMode; + @NotNull + @Length(min = 1, max = MAX_CA_NAME_LENGTH) + private String caName; + @NotNull + private X500Name issuerDN; + @Cmpv2Url + private String url; + + public Authentication getAuthentication() { + return authentication; + } + + public void setAuthentication(Authentication authentication) { + this.authentication = authentication; + } + + public CaMode getCaMode() { + return caMode; + } + + public void setCaMode(CaMode caMode) { + this.caMode = caMode; + } + + public String getCaName() { + return caName; + } + + public void setCaName(String caName) { + this.caName = caName; + } + + public X500Name getIssuerDN() { + return issuerDN; + } + + public void setIssuerDN(X500Name issuerDN) { + this.issuerDN = issuerDN; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + @Override + public String toString() { + return "Cmpv2Server{" + + "authentication=" + authentication + + ", caMode=" + caMode + + ", caName='" + caName + '\'' + + ", issuerDN='" + issuerDN + '\'' + + ", url='" + url + '\'' + + '}'; + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidator.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidator.java new file mode 100644 index 00000000..59014b45 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidator.java @@ -0,0 +1,68 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration.validation; + +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.validation.ConstraintViolation; +import javax.validation.Validator; +import java.security.InvalidParameterException; +import java.util.List; +import java.util.Set; + +@Service +public class Cmpv2ServersConfigurationValidator { + + private final Validator validator; + + @Autowired + public Cmpv2ServersConfigurationValidator(Validator validator) { + this.validator = validator; + } + + public void validate(List servers) { + servers.forEach(this::validateServer); + validateUniqueCaNames(servers); + } + + private void validateServer(Cmpv2Server serverDetails) { + Set> violations = validator.validate(serverDetails); + if (!violations.isEmpty()) { + throw new InvalidParameterException(violations.toString()); + } + } + + private void validateUniqueCaNames(List servers) { + long distinctCAs = getNumberOfUniqueCaNames(servers); + if (servers.size() != distinctCAs) { + throw new InvalidParameterException("CA names are not unique within given CMPv2 servers"); + } + } + + private long getNumberOfUniqueCaNames(List servers) { + return servers.stream().map(Cmpv2Server::getCaName) + .distinct() + .count(); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2Url.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2Url.java new file mode 100644 index 00000000..36e880e3 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2Url.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration.validation.constraints; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target({FIELD, ANNOTATION_TYPE}) +@Retention(RUNTIME) +@Constraint(validatedBy = Cmpv2UrlValidator.class) +public @interface Cmpv2Url { + String message() default "Server URL is invalid."; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidator.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidator.java new file mode 100644 index 00000000..67031682 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidator.java @@ -0,0 +1,55 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration.validation.constraints; + +import org.onap.oom.certservice.certification.configuration.validation.constraints.violations.PortNumberViolation; +import org.onap.oom.certservice.certification.configuration.validation.constraints.violations.RequestTypeViolation; +import org.onap.oom.certservice.certification.configuration.validation.constraints.violations.UrlServerViolation; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +class Cmpv2UrlValidator implements ConstraintValidator { + + private final List violations; + + Cmpv2UrlValidator() { + this.violations = Arrays.asList( + new PortNumberViolation(), + new RequestTypeViolation() + ); + } + + @Override + public boolean isValid(String url, ConstraintValidatorContext context) { + AtomicBoolean isValid = new AtomicBoolean(true); + violations.forEach(violation -> { + if (!violation.validate(url)) { + isValid.set(false); + } + }); + return isValid.get(); + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/PortNumberViolation.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/PortNumberViolation.java new file mode 100644 index 00000000..362a2bb8 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/PortNumberViolation.java @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration.validation.constraints.violations; + +import java.net.MalformedURLException; +import java.net.URL; + +public class PortNumberViolation implements UrlServerViolation { + + private static final int MIN_PORT = 1; + private static final int MAX_PORT = 65535; + private static final int PORT_UNDEFINED = -1; + + @Override + public boolean validate(String serverUrl) { + try { + URL url = new URL(serverUrl); + int port = url.getPort(); + return port >= MIN_PORT && port <= MAX_PORT || port == PORT_UNDEFINED; + } catch (MalformedURLException e) { + return false; + } + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolation.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolation.java new file mode 100644 index 00000000..7f7c5169 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolation.java @@ -0,0 +1,49 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration.validation.constraints.violations; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +public class RequestTypeViolation implements UrlServerViolation { + + private static final List VALID_REQUESTS = Collections.singletonList("http"); + + @Override + public boolean validate(String serverUrl) { + try { + AtomicBoolean isValid = new AtomicBoolean(false); + String protocol = new URL(serverUrl).getProtocol(); + VALID_REQUESTS.forEach(requestType -> { + if (protocol.equals(requestType)) { + isValid.set(true); + } + }); + return isValid.get(); + } catch (MalformedURLException e) { + return false; + } + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/UrlServerViolation.java b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/UrlServerViolation.java new file mode 100644 index 00000000..96d1688a --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/UrlServerViolation.java @@ -0,0 +1,25 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.configuration.validation.constraints.violations; + +public interface UrlServerViolation { + boolean validate(String url); +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/exception/Cmpv2ClientAdapterException.java b/certService/src/main/java/org/onap/oom/certservice/certification/exception/Cmpv2ClientAdapterException.java new file mode 100644 index 00000000..25ea7eb4 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/exception/Cmpv2ClientAdapterException.java @@ -0,0 +1,28 @@ +/* + * ============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.exception; + +public class Cmpv2ClientAdapterException extends Exception { + + public Cmpv2ClientAdapterException(Throwable cause) { + super(cause); + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/exception/Cmpv2ServerNotFoundException.java b/certService/src/main/java/org/onap/oom/certservice/certification/exception/Cmpv2ServerNotFoundException.java new file mode 100644 index 00000000..304b52a1 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/exception/Cmpv2ServerNotFoundException.java @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.exception; + +public class Cmpv2ServerNotFoundException extends RuntimeException { + public Cmpv2ServerNotFoundException(String message) { + super(message); + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/exception/CsrDecryptionException.java b/certService/src/main/java/org/onap/oom/certservice/certification/exception/CsrDecryptionException.java new file mode 100644 index 00000000..80e1b912 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/exception/CsrDecryptionException.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.exception; + +public class CsrDecryptionException extends DecryptionException { + public CsrDecryptionException(String message, Throwable cause) { + super(message, cause); + } + + public CsrDecryptionException(String message) { + super(message); + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/exception/DecryptionException.java b/certService/src/main/java/org/onap/oom/certservice/certification/exception/DecryptionException.java new file mode 100644 index 00000000..784009fb --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/exception/DecryptionException.java @@ -0,0 +1,33 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.exception; + +public class DecryptionException extends Exception { + + public DecryptionException(String message, Throwable cause) { + super(message, cause); + } + + public DecryptionException(String message) { + super(message); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/exception/ErrorResponseModel.java b/certService/src/main/java/org/onap/oom/certservice/certification/exception/ErrorResponseModel.java new file mode 100644 index 00000000..db659412 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/exception/ErrorResponseModel.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.exception; + +public class ErrorResponseModel { + + private final String errorMessage; + + public ErrorResponseModel(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getErrorMessage() { + return errorMessage; + } + +} + diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/exception/KeyDecryptionException.java b/certService/src/main/java/org/onap/oom/certservice/certification/exception/KeyDecryptionException.java new file mode 100644 index 00000000..eeb21da4 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/exception/KeyDecryptionException.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.exception; + +public class KeyDecryptionException extends DecryptionException { + public KeyDecryptionException(String message, Throwable cause) { + super(message, cause); + } + + public KeyDecryptionException(String message) { + super(message); + } +} 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/CertificationModel.java new file mode 100644 index 00000000..08a09a75 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/model/CertificationModel.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.model; + +import java.util.Collections; +import java.util.List; + +public class CertificationModel { + + private final List certificateChain; + private final List trustedCertificates; + + public CertificationModel(List certificateChain, List trustedCertificates) { + this.certificateChain = certificateChain; + this.trustedCertificates = trustedCertificates; + } + + public List getCertificateChain() { + return Collections.unmodifiableList(certificateChain); + } + + public List getTrustedCertificates() { + return Collections.unmodifiableList(trustedCertificates); + } + +} diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/model/CsrModel.java b/certService/src/main/java/org/onap/oom/certservice/certification/model/CsrModel.java new file mode 100644 index 00000000..7cba1949 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/certification/model/CsrModel.java @@ -0,0 +1,170 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * 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.model; + +import java.io.IOException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.Extensions; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.util.io.pem.PemObject; + +import org.onap.oom.certservice.certification.exception.CsrDecryptionException; +import org.onap.oom.certservice.certification.exception.DecryptionException; +import org.onap.oom.certservice.certification.exception.KeyDecryptionException; + + +public class CsrModel { + + private final PKCS10CertificationRequest csr; + private final X500Name subjectData; + private final PrivateKey privateKey; + private final PublicKey publicKey; + private final List sans; + + public CsrModel(PKCS10CertificationRequest csr, X500Name subjectData, PrivateKey privateKey, PublicKey publicKey, + List sans) { + this.csr = csr; + this.subjectData = subjectData; + this.privateKey = privateKey; + this.publicKey = publicKey; + this.sans = sans; + } + + public PKCS10CertificationRequest getCsr() { + return csr; + } + + public X500Name getSubjectData() { + return subjectData; + } + + public PrivateKey getPrivateKey() { + return privateKey; + } + + public PublicKey getPublicKey() { + return publicKey; + } + + public List getSans() { + return sans; + } + + @Override + public String toString() { + return "Subject: { " + subjectData + " ,SANs: " + sans + " }"; + } + + public static class CsrModelBuilder { + + private final PKCS10CertificationRequest csr; + private final PemObject privateKey; + + public CsrModel build() throws DecryptionException { + + X500Name subjectData = getSubjectData(); + PrivateKey javaPrivateKey = convertingPemPrivateKeyToJavaSecurityPrivateKey(getPrivateKey()); + PublicKey javaPublicKey = convertingPemPublicKeyToJavaSecurityPublicKey(getPublicKey()); + List sans = getSansData(); + + return new CsrModel(csr, subjectData, javaPrivateKey, javaPublicKey, sans); + } + + public CsrModelBuilder(PKCS10CertificationRequest csr, PemObject privateKey) { + this.csr = csr; + this.privateKey = privateKey; + } + + private PemObject getPublicKey() throws CsrDecryptionException { + try { + return new PemObject("PUBLIC KEY", csr.getSubjectPublicKeyInfo().getEncoded()); + } catch (IOException e) { + throw new CsrDecryptionException("Reading Public Key from CSR failed", e.getCause()); + } + } + + private PemObject getPrivateKey() { + return privateKey; + } + + private X500Name getSubjectData() { + return csr.getSubject(); + } + + private List getSansData() { + if (!isAttrsEmpty() && !isAttrsValuesEmpty()) { + Extensions extensions = Extensions.getInstance(csr.getAttributes()[0].getAttrValues().getObjectAt(0)); + GeneralName[] arrayOfAlternativeNames = + GeneralNames.fromExtensions(extensions, Extension.subjectAlternativeName).getNames(); + return Arrays.stream(arrayOfAlternativeNames).map(GeneralName::getName).map(Objects::toString) + .collect(Collectors.toList()); + } + return Collections.emptyList(); + } + + private boolean isAttrsValuesEmpty() { + return csr.getAttributes()[0].getAttrValues().size() == 0; + } + + private boolean isAttrsEmpty() { + return csr.getAttributes().length == 0; + } + + private PrivateKey convertingPemPrivateKeyToJavaSecurityPrivateKey(PemObject privateKey) + throws KeyDecryptionException { + try { + KeyFactory factory = KeyFactory.getInstance("RSA"); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey.getContent()); + return factory.generatePrivate(keySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new KeyDecryptionException("Converting Private Key failed", e.getCause()); + } + } + + private PublicKey convertingPemPublicKeyToJavaSecurityPublicKey(PemObject publicKey) + throws KeyDecryptionException { + try { + KeyFactory factory = KeyFactory.getInstance("RSA"); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey.getContent()); + return factory.generatePublic(keySpec); + } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { + throw new KeyDecryptionException("Converting Public Key from CSR failed", e.getCause()); + } + } + } + +} 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 new file mode 100644 index 00000000..d525c6e3 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.api; + +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.cmpv2client.exceptions.CmpClientException; +import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel; + +/** + * This class represent CmpV2Client Interface for obtaining X.509 Digital Certificates in a Public + * Key Infrastructure (PKI), making use of Certificate Management Protocol (CMPv2) operating on + * newest version: cmp2000(2). + */ +public interface CmpClient { + + /** + * Requests for a External Root CA Certificate to be created for the passed public keyPair wrapped + * in a CSRMeta with common details, accepts self-signed certificate. 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 server CMPv2 Server. Must not be {@code null}. + * @param notBefore An optional validity to set in the created certificate, Certificate not valid + * before this date. + * @param notAfter An optional validity to set in the created certificate, Certificate not valid + * after this date. + * @return model for certification containing certificate chain and trusted certificates + * @throws CmpClientException if client error occurs. + */ + Cmpv2CertificationModel createCertificate( + CsrModel csrModel, + Cmpv2Server server, + Date notBefore, + Date notAfter) + throws CmpClientException; + + /** + * Requests for a External Root CA Certificate to be created for the passed public keyPair wrapped + * in a CSRMeta with common details, accepts self-signed certificate. 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 server CMPv2 server. Must not be {@code null}. + * @return model for certification containing certificate chain and trusted certificates + * @throws CmpClientException if client error occurs. + */ + Cmpv2CertificationModel createCertificate( + CsrModel csrModel, + Cmpv2Server server) + throws CmpClientException; +} diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/exceptions/CmpClientException.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/exceptions/CmpClientException.java new file mode 100644 index 00000000..866377fc --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/exceptions/CmpClientException.java @@ -0,0 +1,50 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.exceptions; + +/** + * The CmpClientException wraps all exceptions occur internally to Cmpv2Client Api code. + */ +public class CmpClientException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Creates a new instance with detail message. + */ + public CmpClientException(String message) { + super(message); + } + + /** + * Creates a new instance with detail Throwable cause. + */ + public CmpClientException(Throwable cause) { + super(cause); + } + + /** + * Creates a new instance with detail message and Throwable cause. + */ + public CmpClientException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/exceptions/PkiErrorException.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/exceptions/PkiErrorException.java new file mode 100644 index 00000000..5dabf064 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/exceptions/PkiErrorException.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.exceptions; + +public class PkiErrorException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Creates a new instance with detail message. + */ + public PkiErrorException(String message) { + super(message); + } + + /** + * Creates a new instance with detail Throwable cause. + */ + public PkiErrorException(Throwable cause) { + super(cause); + } + + /** + * Creates a new instance with detail message and Throwable cause. + */ + public PkiErrorException(String message, Throwable cause) { + super(message, cause); + } +} 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 new file mode 100644 index 00000000..f5eddb58 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java @@ -0,0 +1,242 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.impl; + +import java.security.KeyPair; +import java.security.PublicKey; + +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.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Date; +import java.util.Objects; +import java.util.Optional; + +import org.apache.http.impl.client.CloseableHttpClient; +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.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.api.CmpClient; +import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implementation of the CmpClient Interface conforming to RFC4210 (Certificate Management Protocol + * (CMP)) and RFC4211 (Certificate Request Message Format (CRMF)) standards. + */ +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(); + + public CmpClientImpl(CloseableHttpClient httpClient) { + this.httpClient = httpClient; + } + + @Override + public Cmpv2CertificationModel createCertificate( + CsrModel csrModel, + Cmpv2Server server, + Date notBefore, + Date notAfter) + throws CmpClientException { + + validate(csrModel, server, httpClient, notBefore, notAfter); + KeyPair keyPair = new KeyPair(csrModel.getPublicKey(), csrModel.getPrivateKey()); + + final CreateCertRequest certRequest = + CmpMessageBuilder.of(CreateCertRequest::new) + .with(CreateCertRequest::setIssuerDn, server.getIssuerDN()) + .with(CreateCertRequest::setSubjectDn, csrModel.getSubjectData()) + .with(CreateCertRequest::setSansList, csrModel.getSans()) + .with(CreateCertRequest::setSubjectKeyPair, keyPair) + .with(CreateCertRequest::setNotBefore, notBefore) + .with(CreateCertRequest::setNotAfter, notAfter) + .with(CreateCertRequest::setInitAuthPassword, server.getAuthentication().getIak()) + .with(CreateCertRequest::setSenderKid, server.getAuthentication().getRv()) + .build(); + + final PKIMessage pkiMessage = certRequest.generateCertReq(); + Cmpv2HttpClient cmpv2HttpClient = new Cmpv2HttpClient(httpClient); + return retrieveCertificates(csrModel, server, pkiMessage, cmpv2HttpClient); + } + + @Override + public Cmpv2CertificationModel createCertificate(CsrModel csrModel, Cmpv2Server server) + throws CmpClientException { + return createCertificate(csrModel, server, null, null); + } + + 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); + verifyProtectionWithProtectionAlgo(respPkiMessage, initAuthPassword, header, protectionAlgo); + } + + 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 verifyProtectionWithProtectionAlgo( + PKIMessage respPkiMessage, + String initAuthPassword, + PKIHeader header, + AlgorithmIdentifier protectionAlgo) + throws CmpClientException { + if (Objects.nonNull(protectionAlgo)) { + LOG.debug("Verifying PasswordBased Protection of the Response."); + verifyPasswordBasedProtection(respPkiMessage, initAuthPassword, protectionAlgo); + checkImplicitConfirm(header); + } else { + LOG.error( + "Protection Algorithm is not available when expecting PBE protected response containing protection algorithm"); + throw new CmpClientException( + "Protection Algorithm is not available when expecting PBE protected response containing protection algorithm"); + } + } + + private Cmpv2CertificationModel checkCmpCertRepMessage(final PKIMessage respPkiMessage) + 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)) { + final CertResponse certResponse = + getCertificateResponseContainingNewCertificate(certRepMessage); + try { + return verifyReturnCertChainAndTrustStore(respPkiMessage, certRepMessage, certResponse); + } catch (IOException | CertificateParsingException ex) { + CmpClientException cmpClientException = + new CmpClientException( + "Exception occurred while retrieving Certificates from response", ex); + LOG.error("Exception occurred while retrieving Certificates from response", ex); + throw cmpClientException; + } + } else { + return new Cmpv2CertificationModel(Collections.emptyList(), Collections.emptyList()); + } + } + return new Cmpv2CertificationModel(Collections.emptyList(), Collections.emptyList()); + } + + private Cmpv2CertificationModel verifyReturnCertChainAndTrustStore( + 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(); + final Optional leafCertificate = + getCertFromByteArray(cmpCertificate.getEncoded(), X509Certificate.class); + if (leafCertificate.isPresent()) { + return verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate.get()); + } + return new Cmpv2CertificationModel(Collections.emptyList(), Collections.emptyList()); + } + + private CertResponse getCertificateResponseContainingNewCertificate( + 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/CmpMessageBuilder.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpMessageBuilder.java new file mode 100644 index 00000000..8ef15a12 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpMessageBuilder.java @@ -0,0 +1,57 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * Generic Builder Class for creating CMP Message. + */ +public final class CmpMessageBuilder { + + private final Supplier instantiator; + private final List> instanceModifiers = new ArrayList<>(); + + public CmpMessageBuilder(Supplier instantiator) { + this.instantiator = instantiator; + } + + public static CmpMessageBuilder of(Supplier instantiator) { + return new CmpMessageBuilder<>(instantiator); + } + + public CmpMessageBuilder with(BiConsumer consumer, U value) { + Consumer valueConsumer = instance -> consumer.accept(instance, value); + instanceModifiers.add(valueConsumer); + return this; + } + + public T build() { + T value = instantiator.get(); + instanceModifiers.forEach(modifier -> modifier.accept(value)); + instanceModifiers.clear(); + return value; + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpMessageHelper.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpMessageHelper.java new file mode 100644 index 00000000..844f85be --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpMessageHelper.java @@ -0,0 +1,246 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.impl; + +import static org.onap.oom.certservice.cmpv2client.impl.CmpUtil.generateProtectedBytes; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Signature; +import java.security.SignatureException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DEROutputStream; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.cmp.PBMParameter; +import org.bouncycastle.asn1.cmp.PKIBody; +import org.bouncycastle.asn1.cmp.PKIHeader; +import org.bouncycastle.asn1.cmp.PKIMessage; +import org.bouncycastle.asn1.crmf.CertRequest; +import org.bouncycastle.asn1.crmf.OptionalValidity; +import org.bouncycastle.asn1.crmf.POPOSigningKey; +import org.bouncycastle.asn1.crmf.ProofOfPossession; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.Extensions; +import org.bouncycastle.asn1.x509.ExtensionsGenerator; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.asn1.x509.KeyUsage; +import org.bouncycastle.asn1.x509.Time; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class CmpMessageHelper { + + private static final Logger LOG = LoggerFactory.getLogger(CmpMessageHelper.class); + private static final AlgorithmIdentifier OWF_ALGORITHM = + new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.3.14.3.2.26")); + private static final AlgorithmIdentifier MAC_ALGORITHM = + new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.840.113549.2.9")); + private static final ASN1ObjectIdentifier PASSWORD_BASED_MAC = + new ASN1ObjectIdentifier("1.2.840.113533.7.66.13"); + + private CmpMessageHelper() { + } + + /** + * Creates an Optional Validity, which is used to specify how long the returned cert should be + * valid for. + * + * @param notBefore Date specifying certificate is not valid before this date. + * @param notAfter Date specifying certificate is not valid after this date. + * @return {@link OptionalValidity} that can be set for certificate on external CA. + */ + public static OptionalValidity generateOptionalValidity( + final Date notBefore, final Date notAfter) { + LOG.info("Generating Optional Validity from Date objects"); + ASN1EncodableVector optionalValidityV = new ASN1EncodableVector(); + if (notBefore != null) { + Time nb = new Time(notBefore); + optionalValidityV.add(new DERTaggedObject(true, 0, nb)); + } + if (notAfter != null) { + Time na = new Time(notAfter); + optionalValidityV.add(new DERTaggedObject(true, 1, na)); + } + return OptionalValidity.getInstance(new DERSequence(optionalValidityV)); + } + + /** + * Create Extensions from Subject Alternative Names. + * + * @return {@link Extensions}. + */ + public static Extensions generateExtension(final List sansList) + throws CmpClientException { + LOG.info("Generating Extensions from Subject Alternative Names"); + final ExtensionsGenerator extGenerator = new ExtensionsGenerator(); + final GeneralName[] sansGeneralNames = getGeneralNames(sansList); + // KeyUsage + try { + final KeyUsage keyUsage = + new KeyUsage( + KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.nonRepudiation); + extGenerator.addExtension(Extension.keyUsage, false, new DERBitString(keyUsage)); + extGenerator.addExtension( + Extension.subjectAlternativeName, false, new GeneralNames(sansGeneralNames)); + } catch (IOException ioe) { + CmpClientException cmpClientException = + new CmpClientException( + "Exception occurred while creating extensions for PKIMessage", ioe); + LOG.error("Exception occurred while creating extensions for PKIMessage"); + throw cmpClientException; + } + return extGenerator.generate(); + } + + public static GeneralName[] getGeneralNames(List sansList) { + final List nameList = new ArrayList<>(); + for (String san : sansList) { + nameList.add(new GeneralName(GeneralName.dNSName, san)); + } + final GeneralName[] sansGeneralNames = new GeneralName[nameList.size()]; + nameList.toArray(sansGeneralNames); + return sansGeneralNames; + } + + /** + * Method generates Proof-of-Possession (POP) of Private Key. To allow a CA/RA to properly + * validity binding between an End Entity and a Key Pair, the PKI Operations specified here make + * it possible for an End Entity to prove that it has possession of the Private Key corresponding + * to the Public Key for which a Certificate is requested. + * + * @param certRequest Certificate request that requires proof of possession + * @param keypair keypair associated with the subject sending the certificate request + * @return {@link ProofOfPossession}. + * @throws CmpClientException A general-purpose Cmp client exception. + */ + public static ProofOfPossession generateProofOfPossession( + final CertRequest certRequest, final KeyPair keypair) throws CmpClientException { + ProofOfPossession proofOfPossession; + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + final DEROutputStream derOutputStream = new DEROutputStream(byteArrayOutputStream); + derOutputStream.writeObject(certRequest); + + byte[] popoProtectionBytes = byteArrayOutputStream.toByteArray(); + final String sigalg = PKCSObjectIdentifiers.sha256WithRSAEncryption.getId(); + final Signature signature = Signature.getInstance(sigalg, BouncyCastleProvider.PROVIDER_NAME); + signature.initSign(keypair.getPrivate()); + signature.update(popoProtectionBytes); + DERBitString bs = new DERBitString(signature.sign()); + + proofOfPossession = + new ProofOfPossession( + new POPOSigningKey( + null, new AlgorithmIdentifier(new ASN1ObjectIdentifier(sigalg)), bs)); + } catch (IOException + | NoSuchProviderException + | NoSuchAlgorithmException + | InvalidKeyException + | SignatureException ex) { + CmpClientException cmpClientException = + new CmpClientException( + "Exception occurred while creating proof of possession for PKIMessage", ex); + LOG.error("Exception occurred while creating proof of possession for PKIMessage"); + throw cmpClientException; + } + return proofOfPossession; + } + + /** + * Generic code to create Algorithm Identifier for protection of PKIMessage. + * + * @return Algorithm Identifier + */ + public static AlgorithmIdentifier protectionAlgoIdentifier(int iterations, byte[] salt) { + ASN1Integer iteration = new ASN1Integer(iterations); + DEROctetString derSalt = new DEROctetString(salt); + + PBMParameter pp = new PBMParameter(derSalt, OWF_ALGORITHM, iteration, MAC_ALGORITHM); + return new AlgorithmIdentifier(PASSWORD_BASED_MAC, pp); + } + + /** + * Adds protection to the PKIMessage via a specified protection algorithm. + * + * @param password password used to authenticate PkiMessage with external CA + * @param pkiHeader Header of PKIMessage containing generic details for any PKIMessage + * @param pkiBody Body of PKIMessage containing specific details for certificate request + * @return Protected Pki Message + * @throws CmpClientException Wraps several exceptions into one general-purpose exception. + */ + public static PKIMessage protectPkiMessage( + PKIHeader pkiHeader, PKIBody pkiBody, String password, int iterations, byte[] salt) + throws CmpClientException { + + byte[] raSecret = password.getBytes(); + byte[] basekey = new byte[raSecret.length + salt.length]; + System.arraycopy(raSecret, 0, basekey, 0, raSecret.length); + System.arraycopy(salt, 0, basekey, raSecret.length, salt.length); + byte[] out; + try { + MessageDigest dig = + MessageDigest.getInstance( + OWF_ALGORITHM.getAlgorithm().getId(), BouncyCastleProvider.PROVIDER_NAME); + for (int i = 0; i < iterations; i++) { + basekey = dig.digest(basekey); + dig.reset(); + } + byte[] protectedBytes = generateProtectedBytes(pkiHeader, pkiBody); + Mac mac = + Mac.getInstance(MAC_ALGORITHM.getAlgorithm().getId(), BouncyCastleProvider.PROVIDER_NAME); + SecretKey key = new SecretKeySpec(basekey, MAC_ALGORITHM.getAlgorithm().getId()); + mac.init(key); + mac.reset(); + mac.update(protectedBytes, 0, protectedBytes.length); + out = mac.doFinal(); + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException ex) { + CmpClientException cmpClientException = + new CmpClientException( + "Exception occurred while generating proof of possession for PKIMessage", ex); + LOG.error("Exception occured while generating the proof of possession for PKIMessage"); + throw cmpClientException; + } + DERBitString bs = new DERBitString(out); + + return new PKIMessage(pkiHeader, pkiBody, bs); + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseHelper.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseHelper.java new file mode 100644 index 00000000..db508603 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseHelper.java @@ -0,0 +1,335 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.impl; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertPath; +import java.security.cert.CertPathValidator; +import java.security.cert.CertPathValidatorException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.CertificateParsingException; +import java.security.cert.PKIXCertPathChecker; +import java.security.cert.PKIXCertPathValidatorResult; +import java.security.cert.PKIXParameters; +import java.security.cert.TrustAnchor; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import org.bouncycastle.asn1.cmp.CMPCertificate; +import org.bouncycastle.asn1.cmp.CertRepMessage; +import org.bouncycastle.asn1.cmp.ErrorMsgContent; +import org.bouncycastle.asn1.cmp.PKIBody; +import org.bouncycastle.asn1.cmp.PKIMessage; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.onap.oom.certservice.cmpv2client.exceptions.PkiErrorException; +import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class CmpResponseHelper { + + private static final Logger LOG = LoggerFactory.getLogger(CmpResponseHelper.class); + + private CmpResponseHelper() { + } + + static void checkIfCmpResponseContainsError(PKIMessage respPkiMessage) + throws CmpClientException { + if (respPkiMessage.getBody().getType() == PKIBody.TYPE_ERROR) { + final ErrorMsgContent errorMsgContent = + (ErrorMsgContent) respPkiMessage.getBody().getContent(); + PkiErrorException pkiErrorException = + new PkiErrorException( + errorMsgContent.getPKIStatusInfo().getStatusString().getStringAt(0).getString()); + CmpClientException cmpClientException = + new CmpClientException("Error in the PkiMessage response", pkiErrorException); + LOG.error("Error in the PkiMessage response: {} ", pkiErrorException.getMessage()); + throw cmpClientException; + } + } + + + /** + * Puts together certChain and Trust store and verifies the certChain + * + * @param respPkiMessage PKIMessage that may contain extra certs used for certchain + * @param certRepMessage CertRepMessage that should contain rootCA for certchain + * @param leafCertificate certificate returned from our original Cert Request + * @return model for certification containing certificate chain and trusted certificates + * @throws CertificateParsingException thrown if error occurs while parsing certificate + * @throws IOException thrown if IOException occurs while parsing certificate + * @throws CmpClientException thrown if error occurs during the verification of the certChain + */ + static Cmpv2CertificationModel verifyAndReturnCertChainAndTrustSTore( + PKIMessage respPkiMessage, CertRepMessage certRepMessage, X509Certificate leafCertificate) + throws CertificateParsingException, IOException, CmpClientException { + Map certificates = mapAllCertificates(respPkiMessage, certRepMessage); + return extractCertificationModel(certificates, leafCertificate); + } + + private static Map mapAllCertificates( + PKIMessage respPkiMessage, CertRepMessage certRepMessage + ) + throws IOException, CertificateParsingException, CmpClientException { + + Map certificates = new HashMap<>(); + + CMPCertificate[] extraCerts = respPkiMessage.getExtraCerts(); + certificates.putAll(mapCertificates(extraCerts)); + + CMPCertificate[] caPubsCerts = certRepMessage.getCaPubs(); + certificates.putAll(mapCertificates(caPubsCerts)); + + return certificates; + } + + private static Map mapCertificates( + CMPCertificate[] cmpCertificates) + throws CertificateParsingException, CmpClientException, IOException { + + Map certificates = new HashMap<>(); + if (cmpCertificates != null) { + for (CMPCertificate certificate : cmpCertificates) { + getCertFromByteArray(certificate.getEncoded(), X509Certificate.class) + .ifPresent(x509Certificate -> + certificates.put(extractSubjectDn(x509Certificate), x509Certificate) + ); + } + } + + return certificates; + } + + private static Cmpv2CertificationModel extractCertificationModel( + Map certificates, X509Certificate leafCertificate + ) + throws CmpClientException { + List certificateChain = new ArrayList<>(); + X509Certificate previousCertificateInChain; + X509Certificate nextCertificateInChain = leafCertificate; + do { + certificateChain.add(nextCertificateInChain); + certificates.remove(extractSubjectDn(nextCertificateInChain)); + previousCertificateInChain = nextCertificateInChain; + nextCertificateInChain = certificates.get(extractIssuerDn(nextCertificateInChain)); + verify(previousCertificateInChain, nextCertificateInChain, null); + } + while (!isSelfSign(nextCertificateInChain)); + List trustedCertificates = new ArrayList<>(certificates.values()); + + return new Cmpv2CertificationModel(certificateChain, trustedCertificates); + } + + private static boolean isSelfSign(X509Certificate certificate) { + return extractIssuerDn(certificate).equals(extractSubjectDn(certificate)); + } + + private static X500Name extractIssuerDn(X509Certificate x509Certificate) { + return X500Name.getInstance(x509Certificate.getIssuerDN()); + } + + private static X500Name extractSubjectDn(X509Certificate x509Certificate) { + return X500Name.getInstance(x509Certificate.getSubjectDN()); + } + + + /** + * Check the certificate with CA certificate. + * + * @param certificate X.509 certificate to verify. May not be null. + * @param caCertChain Collection of X509Certificates. May not be null, an empty list or a + * Collection with null entries. + * @param date Date to verify at, or null to use current time. + * @param pkixCertPathCheckers optional PKIXCertPathChecker implementations to use during cert + * path validation + * @throws CmpClientException if certificate could not be validated + */ + private static void verify( + X509Certificate certificate, + X509Certificate caCertChain, + Date date, + PKIXCertPathChecker... pkixCertPathCheckers) + throws CmpClientException { + try { + verifyCertificates(certificate, caCertChain, date, pkixCertPathCheckers); + } catch (CertPathValidatorException cpve) { + CmpClientException cmpClientException = + new CmpClientException( + "Invalid certificate or certificate not issued by specified CA: ", cpve); + LOG.error("Invalid certificate or certificate not issued by specified CA: ", cpve); + throw cmpClientException; + } catch (CertificateException ce) { + CmpClientException cmpClientException = + new CmpClientException("Something was wrong with the supplied certificate", ce); + LOG.error("Something was wrong with the supplied certificate", ce); + throw cmpClientException; + } catch (NoSuchProviderException nspe) { + CmpClientException cmpClientException = + new CmpClientException("BouncyCastle provider not found.", nspe); + LOG.error("BouncyCastle provider not found.", nspe); + throw cmpClientException; + } catch (NoSuchAlgorithmException nsae) { + CmpClientException cmpClientException = + new CmpClientException("Algorithm PKIX was not found.", nsae); + LOG.error("Algorithm PKIX was not found.", nsae); + throw cmpClientException; + } catch (InvalidAlgorithmParameterException iape) { + CmpClientException cmpClientException = + new CmpClientException( + "Either ca certificate chain was empty," + + " or the certificate was on an inappropriate type for a PKIX path checker.", + iape); + LOG.error( + "Either ca certificate chain was empty, " + + "or the certificate was on an inappropriate type for a PKIX path checker.", + iape); + throw cmpClientException; + } + } + + private static void verifyCertificates( + X509Certificate certificate, + X509Certificate caCertChain, + Date date, + PKIXCertPathChecker[] pkixCertPathCheckers) + throws CertificateException, NoSuchProviderException, InvalidAlgorithmParameterException, + NoSuchAlgorithmException, CertPathValidatorException { + if (caCertChain == null) { + final String noRootCaCertificateMessage = "Server response does not contain proper root CA certificate"; + throw new CertificateException(noRootCaCertificateMessage); + } + LOG.debug( + "Verifying certificate {} as part of cert chain with certificate {}", + certificate.getSubjectDN().getName(), + caCertChain.getSubjectDN().getName()); + CertPath cp = getCertPath(certificate); + PKIXParameters params = getPkixParameters(caCertChain, date, pkixCertPathCheckers); + CertPathValidator cpv = + CertPathValidator.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME); + PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult) cpv.validate(cp, params); + if (LOG.isDebugEnabled()) { + LOG.debug("Certificate verify result:{} ", result); + } + } + + private static PKIXParameters getPkixParameters( + X509Certificate caCertChain, Date date, PKIXCertPathChecker[] pkixCertPathCheckers) + throws InvalidAlgorithmParameterException { + TrustAnchor anchor = new TrustAnchor(caCertChain, null); + PKIXParameters params = new PKIXParameters(Collections.singleton(anchor)); + for (final PKIXCertPathChecker pkixCertPathChecker : pkixCertPathCheckers) { + params.addCertPathChecker(pkixCertPathChecker); + } + params.setRevocationEnabled(false); + params.setDate(date); + return params; + } + + private static CertPath getCertPath(X509Certificate certificate) + throws CertificateException, NoSuchProviderException { + ArrayList certlist = new ArrayList<>(); + certlist.add(certificate); + return CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME) + .generateCertPath(certlist); + } + + /** + * Returns a CertificateFactory that can be used to create certificates from byte arrays and such. + * + * @param provider Security provider that should be used to create certificates, default BC is + * null is passed. + * @return CertificateFactory for creating certificate + */ + private static CertificateFactory getCertificateFactory(final String provider) + throws CmpClientException { + LOG.debug("Creating certificate Factory to generate certificate using provider {}", provider); + final String prov; + prov = Objects.requireNonNullElse(provider, BouncyCastleProvider.PROVIDER_NAME); + try { + return CertificateFactory.getInstance("X.509", prov); + } catch (NoSuchProviderException nspe) { + CmpClientException cmpClientException = new CmpClientException("NoSuchProvider: ", nspe); + LOG.error("NoSuchProvider: ", nspe); + throw cmpClientException; + } catch (CertificateException ce) { + CmpClientException cmpClientException = new CmpClientException("CertificateException: ", ce); + LOG.error("CertificateException: ", ce); + throw cmpClientException; + } + } + + /** + * @param cert byte array that contains certificate + * @param returnType the type of Certificate to be returned, for example X509Certificate.class. + * Certificate.class can be used if certificate type is unknown. + * @throws CertificateParsingException if the byte array does not contain a proper certificate. + */ + static Optional getCertFromByteArray( + byte[] cert, Class returnType) throws CertificateParsingException, CmpClientException { + LOG.debug("Retrieving certificate of type {} from byte array.", returnType); + String prov = BouncyCastleProvider.PROVIDER_NAME; + + if (returnType.equals(X509Certificate.class)) { + return parseX509Certificate(prov, cert); + } else { + LOG.debug("Certificate of type {} was skipped, because type of certificate is not 'X509Certificate'.", returnType); + return Optional.empty(); + } + } + + + /** + * Parse a X509Certificate from an array of bytes + * + * @param provider a provider name + * @param cert a byte array containing an encoded certificate + * @return a decoded X509Certificate + * @throws CertificateParsingException if the byte array wasn't valid, or contained a certificate + * other than an X509 Certificate. + */ + private static Optional parseX509Certificate(String provider, byte[] cert) + throws CertificateParsingException, CmpClientException { + LOG.debug("Parsing X509Certificate from bytes with provider {}", provider); + final CertificateFactory cf = getCertificateFactory(provider); + X509Certificate result; + try { + result = (X509Certificate) Objects.requireNonNull(cf).generateCertificate(new ByteArrayInputStream(cert)); + return Optional.ofNullable(result); + } catch (CertificateException ce) { + throw new CertificateParsingException("Could not parse byte array as X509Certificate ", ce); + } + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseValidationHelper.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseValidationHelper.java new file mode 100644 index 00000000..c699b110 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseValidationHelper.java @@ -0,0 +1,241 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.util.Arrays; +import java.util.Objects; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DEROutputStream; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.cmp.CMPObjectIdentifiers; +import org.bouncycastle.asn1.cmp.InfoTypeAndValue; +import org.bouncycastle.asn1.cmp.PBMParameter; +import org.bouncycastle.asn1.cmp.PKIBody; +import org.bouncycastle.asn1.cmp.PKIHeader; +import org.bouncycastle.asn1.cmp.PKIMessage; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class CmpResponseValidationHelper { + + private static final Logger LOG = LoggerFactory.getLogger(CmpResponseValidationHelper.class); + + private CmpResponseValidationHelper() { + } + + /** + * Create a base key to use for verifying the PasswordBasedMac on a PKIMessage + * + * @param pbmParamSeq parameters recieved in PKIMessage used with password + * @param initAuthPassword password used to decrypt the basekey + * @return bytes representing the basekey + * @throws CmpClientException thrown if algorithem exceptions occur for the message digest + */ + public static byte[] getBaseKeyFromPbmParameters( + PBMParameter pbmParamSeq, String initAuthPassword) throws CmpClientException { + final int iterationCount = pbmParamSeq.getIterationCount().getPositiveValue().intValue(); + LOG.info("Iteration count is: {}", iterationCount); + final AlgorithmIdentifier owfAlg = pbmParamSeq.getOwf(); + LOG.info("One Way Function type is: {}", owfAlg.getAlgorithm().getId()); + final byte[] salt = pbmParamSeq.getSalt().getOctets(); + final byte[] raSecret = initAuthPassword != null ? initAuthPassword.getBytes() : new byte[0]; + byte[] basekey = new byte[raSecret.length + salt.length]; + System.arraycopy(raSecret, 0, basekey, 0, raSecret.length); + System.arraycopy(salt, 0, basekey, raSecret.length, salt.length); + try { + final MessageDigest messageDigest = + MessageDigest.getInstance( + owfAlg.getAlgorithm().getId(), BouncyCastleProvider.PROVIDER_NAME); + for (int i = 0; i < iterationCount; i++) { + basekey = messageDigest.digest(basekey); + messageDigest.reset(); + } + } catch (NoSuchAlgorithmException | NoSuchProviderException ex) { + LOG.error("ProtectionBytes don't match passwordBasedProtection, authentication failed"); + throw new CmpClientException( + "ProtectionBytes don't match passwordBasedProtection, authentication failed", ex); + } + return basekey; + } + + /** + * Verifies the signature of the response message using our public key + * + * @param respPkiMessage PKIMessage we wish to verify signature for + * @param pk public key used to verify signature. + * @throws CmpClientException + */ + public static void verifySignature(PKIMessage respPkiMessage, PublicKey pk) + throws CmpClientException { + final byte[] protBytes = getProtectedBytes(respPkiMessage); + final DERBitString derBitString = respPkiMessage.getProtection(); + try { + final Signature signature = + Signature.getInstance( + PKCSObjectIdentifiers.sha256WithRSAEncryption.getId(), + BouncyCastleProvider.PROVIDER_NAME); + signature.initVerify(pk); + signature.update(protBytes); + signature.verify(derBitString.getBytes()); + } catch (NoSuchAlgorithmException + | NoSuchProviderException + | InvalidKeyException + | SignatureException e) { + CmpClientException clientException = + new CmpClientException("Signature Verification failed", e); + LOG.error("Signature Verification failed", e); + throw clientException; + } + } + + /** + * Converts the header and the body of a PKIMessage to an ASN1Encodable and returns the as a byte + * array + * + * @param msg PKIMessage to get protected bytes from + * @return the PKIMessage's header and body in byte array + */ + public static byte[] getProtectedBytes(PKIMessage msg) throws CmpClientException { + return getProtectedBytes(msg.getHeader(), msg.getBody()); + } + + /** + * Converts the header and the body of a PKIMessage to an ASN1Encodable and returns the as a byte + * array + * + * @param header PKIHeader to be converted + * @param body PKIMessage to be converted + * @return the PKIMessage's header and body in byte array + */ + public static byte[] getProtectedBytes(PKIHeader header, PKIBody body) throws CmpClientException { + byte[] res; + ASN1EncodableVector encodableVector = new ASN1EncodableVector(); + encodableVector.add(header); + encodableVector.add(body); + ASN1Encodable protectedPart = new DERSequence(encodableVector); + try { + ByteArrayOutputStream bao = new ByteArrayOutputStream(); + DEROutputStream out = new DEROutputStream(bao); + out.writeObject(protectedPart); + res = bao.toByteArray(); + } catch (IOException ioe) { + CmpClientException cmpClientException = + new CmpClientException("Error occured while getting protected bytes", ioe); + LOG.error("Error occured while getting protected bytes", ioe); + throw cmpClientException; + } + return res; + } + + /** + * verify the password based protection within the response message + * + * @param respPkiMessage PKIMessage we want to verify password based protection for + * @param initAuthPassword password used to decrypt protection + * @param protectionAlgo protection algorithm we can use to decrypt protection + * @throws CmpClientException + */ + public static void verifyPasswordBasedProtection( + PKIMessage respPkiMessage, String initAuthPassword, AlgorithmIdentifier protectionAlgo) + throws CmpClientException { + final byte[] protectedBytes = getProtectedBytes(respPkiMessage); + final PBMParameter pbmParamSeq = PBMParameter.getInstance(protectionAlgo.getParameters()); + if (Objects.nonNull(pbmParamSeq)) { + try { + byte[] basekey = getBaseKeyFromPbmParameters(pbmParamSeq, initAuthPassword); + final Mac mac = getMac(protectedBytes, pbmParamSeq, basekey); + final byte[] outBytes = mac.doFinal(); + final byte[] protectionBytes = respPkiMessage.getProtection().getBytes(); + if (!Arrays.equals(outBytes, protectionBytes)) { + LOG.error("protectionBytes don't match passwordBasedProtection, authentication failed"); + throw new CmpClientException( + "protectionBytes don't match passwordBasedProtection, authentication failed"); + } + } catch (NoSuchProviderException | NoSuchAlgorithmException | InvalidKeyException ex) { + CmpClientException cmpClientException = + new CmpClientException("Error while validating CMP response ", ex); + LOG.error("Error while validating CMP response ", ex); + throw cmpClientException; + } + } + } + + public static void checkImplicitConfirm(PKIHeader header) { + InfoTypeAndValue[] infos = header.getGeneralInfo(); + if (Objects.nonNull(infos)) { + if (CMPObjectIdentifiers.it_implicitConfirm.equals(getImplicitConfirm(infos))) { + LOG.info("Implicit Confirm on certificate from server."); + } else { + LOG.debug("No Implicit confirm in Response"); + } + } else { + LOG.debug("No general Info in header of response, cannot verify implicit confirm"); + } + } + + public static ASN1ObjectIdentifier getImplicitConfirm(InfoTypeAndValue[] info) { + return info[0].getInfoType(); + } + + /** + * Get cryptographical Mac we can use to decrypt our PKIMessage + * + * @param protectedBytes Protected bytes representing the PKIMessage + * @param pbmParamSeq Parameters used to decrypt PKIMessage, including mac algorithm used + * @param basekey Key used alongside mac Oid to create secret key for decrypting PKIMessage + * @return Mac that's ready to return decrypted bytes + * @throws NoSuchAlgorithmException Possibly thrown trying to get mac instance + * @throws NoSuchProviderException Possibly thrown trying to get mac instance + * @throws InvalidKeyException Possibly thrown trying to initialize mac using secretkey + */ + public static Mac getMac(byte[] protectedBytes, PBMParameter pbmParamSeq, byte[] basekey) + throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException { + final AlgorithmIdentifier macAlg = pbmParamSeq.getMac(); + LOG.info("Mac type is: {}", macAlg.getAlgorithm().getId()); + final String macOid = macAlg.getAlgorithm().getId(); + final Mac mac = Mac.getInstance(macOid, BouncyCastleProvider.PROVIDER_NAME); + final SecretKey key = new SecretKeySpec(basekey, macOid); + mac.init(key); + mac.reset(); + mac.update(protectedBytes, 0, protectedBytes.length); + return mac; + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpUtil.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpUtil.java new file mode 100644 index 00000000..281f6f5e --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpUtil.java @@ -0,0 +1,153 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.SecureRandom; +import java.util.Date; +import java.util.Objects; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1GeneralizedTime; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DEROutputStream; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.cmp.CMPObjectIdentifiers; +import org.bouncycastle.asn1.cmp.InfoTypeAndValue; +import org.bouncycastle.asn1.cmp.PKIBody; +import org.bouncycastle.asn1.cmp.PKIHeader; +import org.bouncycastle.asn1.cmp.PKIHeaderBuilder; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.GeneralName; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class CmpUtil { + + private static final Logger LOGGER = LoggerFactory.getLogger(CmpUtil.class); + private static final SecureRandom SECURE_RANDOM = new SecureRandom(); + public static final int RANDOM_BYTE_LENGTH = 16; + public static final int RANDOM_SEED = 1000; + + private CmpUtil() { + } + + /** + * Validates specified object reference is not null. + * + * @param argument T - the type of the reference. + * @param message message - detail message to be used in the event that a NullPointerException is + * thrown. + * @return The Object if not null + */ + public static T notNull(T argument, String message) { + return Objects.requireNonNull(argument, message + " must not be null"); + } + + /** + * Validates String object reference is not null and not empty. + * + * @param stringArg String Object that need to be validated. + * @return boolean + */ + public static boolean isNullOrEmpty(String stringArg) { + return (stringArg != null && !stringArg.trim().isEmpty()); + } + + /** + * Creates a random number than can be used for sendernonce, transactionId and salts. + * + * @return bytes containing a random number string representing a nonce + */ + static byte[] createRandomBytes() { + LOGGER.info("Generating random array of bytes"); + byte[] randomBytes = new byte[RANDOM_BYTE_LENGTH]; + SECURE_RANDOM.nextBytes(randomBytes); + return randomBytes; + } + + /** + * Creates a random integer than can be used to represent a transactionId or determine the number + * iterations in a protection algorithm. + * + * @return bytes containing a random number string representing a nonce + */ + static int createRandomInt(int range) { + LOGGER.info("Generating random integer"); + return SECURE_RANDOM.nextInt(range) + RANDOM_SEED; + } + + /** + * Generates protected bytes of a combined PKIHeader and PKIBody. + * + * @param header Header of PKIMessage containing common parameters + * @param body Body of PKIMessage containing specific information for message + * @return bytes representing the PKIHeader and PKIBody thats to be protected + */ + static byte[] generateProtectedBytes(PKIHeader header, PKIBody body) throws CmpClientException { + LOGGER.info("Generating array of bytes representing PkiHeader and PkiBody"); + byte[] res; + ASN1EncodableVector vector = new ASN1EncodableVector(); + vector.add(header); + vector.add(body); + ASN1Encodable protectedPart = new DERSequence(vector); + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + DEROutputStream out = new DEROutputStream(baos); + out.writeObject(protectedPart); + res = baos.toByteArray(); + } catch (IOException ioe) { + CmpClientException cmpClientException = + new CmpClientException("IOException occurred while creating protectedBytes", ioe); + LOGGER.error("IOException occurred while creating protectedBytes"); + throw cmpClientException; + } + return res; + } + + /** + * Generates a PKIHeader Builder object. + * + * @param subjectDn distinguished name of Subject + * @param issuerDn distinguished name of external CA + * @param protectionAlg protection Algorithm used to protect PKIMessage + * @return PKIHeaderBuilder + */ + static PKIHeader generatePkiHeader( + X500Name subjectDn, X500Name issuerDn, AlgorithmIdentifier protectionAlg, String senderKid) { + LOGGER.info("Generating a Pki Header Builder"); + PKIHeaderBuilder pkiHeaderBuilder = + new PKIHeaderBuilder( + PKIHeader.CMP_2000, new GeneralName(subjectDn), new GeneralName(issuerDn)); + + pkiHeaderBuilder.setMessageTime(new ASN1GeneralizedTime(new Date())); + pkiHeaderBuilder.setSenderNonce(new DEROctetString(createRandomBytes())); + pkiHeaderBuilder.setTransactionID(new DEROctetString(createRandomBytes())); + pkiHeaderBuilder.setProtectionAlg(protectionAlg); + pkiHeaderBuilder.setGeneralInfo(new InfoTypeAndValue(CMPObjectIdentifiers.it_implicitConfirm)); + pkiHeaderBuilder.setSenderKID(new DEROctetString(senderKid.getBytes())); + + return pkiHeaderBuilder.build(); + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/Cmpv2HttpClient.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/Cmpv2HttpClient.java new file mode 100644 index 00000000..0f32c668 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/Cmpv2HttpClient.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.bouncycastle.asn1.cmp.PKIMessage; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class Cmpv2HttpClient { + + private static final Logger LOG = LoggerFactory.getLogger(Cmpv2HttpClient.class); + + private static final String CONTENT_TYPE = "Content-type"; + private static final String CMP_REQUEST_MIMETYPE = "application/pkixcmp"; + private final CloseableHttpClient httpClient; + + /** + * constructor for Cmpv2HttpClient + * + * @param httpClient CloseableHttpClient used for sending/recieve request. + */ + Cmpv2HttpClient(CloseableHttpClient httpClient) { + this.httpClient = httpClient; + } + + /** + * Send Post Request to Server + * + * @param pkiMessage PKIMessage to send to server + * @param urlString url for the server we're sending request + * @param caName name of CA server + * @return PKIMessage received from CMPServer + * @throws CmpClientException thrown if problems with connecting or parsing response to server + */ + public byte[] postRequest( + final PKIMessage pkiMessage, final String urlString, final String caName) + throws CmpClientException { + try (ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream()) { + final HttpPost postRequest = new HttpPost(urlString); + final byte[] requestBytes = pkiMessage.getEncoded(); + + postRequest.setEntity(new ByteArrayEntity(requestBytes)); + postRequest.setHeader(CONTENT_TYPE, CMP_REQUEST_MIMETYPE); + + try (CloseableHttpResponse response = httpClient.execute(postRequest)) { + response.getEntity().writeTo(byteArrOutputStream); + } + return byteArrOutputStream.toByteArray(); + } catch (IOException ioe) { + CmpClientException cmpClientException = + new CmpClientException( + String.format("IOException error while trying to connect CA %s", caName), ioe); + LOG.error("IOException error {}, while trying to connect CA {}", ioe.getMessage(), caName); + 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 new file mode 100644 index 00000000..a0ba13d6 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java @@ -0,0 +1,128 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.impl; + +import static org.onap.oom.certservice.cmpv2client.impl.CmpUtil.createRandomBytes; +import static org.onap.oom.certservice.cmpv2client.impl.CmpUtil.createRandomInt; +import static org.onap.oom.certservice.cmpv2client.impl.CmpUtil.generatePkiHeader; + +import java.security.KeyPair; +import java.util.Date; +import java.util.List; + +import org.bouncycastle.asn1.cmp.PKIBody; +import org.bouncycastle.asn1.cmp.PKIHeader; +import org.bouncycastle.asn1.cmp.PKIMessage; +import org.bouncycastle.asn1.crmf.CertReqMessages; +import org.bouncycastle.asn1.crmf.CertReqMsg; +import org.bouncycastle.asn1.crmf.CertRequest; +import org.bouncycastle.asn1.crmf.CertTemplateBuilder; +import org.bouncycastle.asn1.crmf.ProofOfPossession; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; + +/** + * Implementation of the CmpClient Interface conforming to RFC4210 (Certificate Management Protocol + * (CMP)) and RFC4211 (Certificate Request Message Format (CRMF)) standards. + */ +class CreateCertRequest { + + private X500Name issuerDn; + private X500Name subjectDn; + private List sansList; + private KeyPair subjectKeyPair; + private Date notBefore; + private Date notAfter; + private String initAuthPassword; + private String senderKid; + + private static final int ITERATIONS = createRandomInt(5000); + private static final byte[] SALT = createRandomBytes(); + private final int certReqId = createRandomInt(Integer.MAX_VALUE); + + public void setIssuerDn(X500Name issuerDn) { + this.issuerDn = issuerDn; + } + + public void setSubjectDn(X500Name subjectDn) { + this.subjectDn = subjectDn; + } + + public void setSansList(List sansList) { + this.sansList = sansList; + } + + public void setSubjectKeyPair(KeyPair subjectKeyPair) { + this.subjectKeyPair = subjectKeyPair; + } + + public void setNotBefore(Date notBefore) { + this.notBefore = notBefore; + } + + public void setNotAfter(Date notAfter) { + this.notAfter = notAfter; + } + + public void setInitAuthPassword(String initAuthPassword) { + this.initAuthPassword = initAuthPassword; + } + + public void setSenderKid(String senderKid) { + this.senderKid = senderKid; + } + + /** + * Method to create {@link PKIMessage} from {@link CertRequest},{@link ProofOfPossession}, {@link + * CertReqMsg}, {@link CertReqMessages}, {@link PKIHeader} and {@link PKIBody}. + * + * @return {@link PKIMessage} + */ + public PKIMessage generateCertReq() throws CmpClientException { + final CertTemplateBuilder certTemplateBuilder = + new CertTemplateBuilder() + .setIssuer(issuerDn) + .setSubject(subjectDn) + .setExtensions(CmpMessageHelper.generateExtension(sansList)) + .setValidity(CmpMessageHelper.generateOptionalValidity(notBefore, notAfter)) + .setPublicKey( + SubjectPublicKeyInfo.getInstance(subjectKeyPair.getPublic().getEncoded())); + + final CertRequest certRequest = new CertRequest(certReqId, certTemplateBuilder.build(), null); + final ProofOfPossession proofOfPossession = + CmpMessageHelper.generateProofOfPossession(certRequest, subjectKeyPair); + + final CertReqMsg certReqMsg = new CertReqMsg(certRequest, proofOfPossession, null); + final CertReqMessages certReqMessages = new CertReqMessages(certReqMsg); + + final PKIHeader pkiHeader = + generatePkiHeader( + subjectDn, + issuerDn, + CmpMessageHelper.protectionAlgoIdentifier(ITERATIONS, SALT), + senderKid); + final PKIBody pkiBody = new PKIBody(PKIBody.TYPE_INIT_REQ, certReqMessages); + + return CmpMessageHelper.protectPkiMessage( + pkiHeader, pkiBody, initAuthPassword, ITERATIONS, SALT); + } +} diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/model/Cmpv2CertificationModel.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/model/Cmpv2CertificationModel.java new file mode 100644 index 00000000..a40a7708 --- /dev/null +++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/model/Cmpv2CertificationModel.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.certservice.cmpv2client.model; + +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.List; + +public class Cmpv2CertificationModel { + + private final List certificateChain; + private final List trustedCertificates; + + public Cmpv2CertificationModel(List certificateChain, List trustedCertificates) { + this.certificateChain = certificateChain; + this.trustedCertificates = trustedCertificates; + } + + public List getCertificateChain() { + return Collections.unmodifiableList(certificateChain); + } + + public List getTrustedCertificates() { + return Collections.unmodifiableList(trustedCertificates); + } +} -- cgit 1.2.3-korg