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 --- certService/Dockerfile | 4 +- certService/README.md | 19 +- certService/pom.xml | 14 +- .../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 ++ .../src/main/resources/application.properties | 8 +- certService/src/main/resources/log4j2.xml | 6 +- .../certservice/CertServiceApplicationTests.java | 34 -- .../api/CertificationControllerTest.java | 147 ----- .../certservice/api/ReadinessControllerTest.java | 59 -- .../api/ReloadConfigControllerTest.java | 77 --- .../advice/CertificationExceptionAdviceTest.java | 134 ----- .../advice/ReloadConfigExceptionAdviceTest.java | 56 -- .../CertificationModelFactoryTest.java | 220 -------- .../certification/CertificationProviderTest.java | 132 ----- .../certification/CsrModelFactoryTest.java | 147 ----- .../certification/PemObjectFactoryTest.java | 76 --- .../certification/RsaContentSignerBuilderTest.java | 63 --- .../aaf/certservice/certification/TestData.java | 95 ---- .../aaf/certservice/certification/TestUtils.java | 61 --- .../certification/X509CertificateBuilderTest.java | 69 --- .../configuration/CmpServersConfigLoaderTest.java | 117 ---- .../configuration/CmpServersConfigTest.java | 236 -------- .../configuration/Cmpv2ServerProviderTest.java | 100 ---- .../Cmpv2ServersConfigurationValidatorTest.java | 213 ------- .../constraints/Cmpv2UrlValidatorTest.java | 57 -- .../violations/PortNumberViolationTest.java | 76 --- .../violations/RequestTypeViolationTest.java | 56 -- .../certification/model/CsrModelTest.java | 185 ------- .../certservice/cmpv2client/Cmpv2ClientTest.java | 288 ---------- .../certservice/cmpv2client/external/RdnTest.java | 96 ---- .../cmpv2client/impl/CmpResponseHelperTest.java | 609 --------------------- .../certservice/CertServiceApplicationTests.java | 34 ++ .../api/CertificationControllerTest.java | 147 +++++ .../certservice/api/ReadinessControllerTest.java | 59 ++ .../api/ReloadConfigControllerTest.java | 77 +++ .../advice/CertificationExceptionAdviceTest.java | 134 +++++ .../advice/ReloadConfigExceptionAdviceTest.java | 56 ++ .../CertificationModelFactoryTest.java | 220 ++++++++ .../certification/CertificationProviderTest.java | 132 +++++ .../certification/CsrModelFactoryTest.java | 147 +++++ .../certification/PemObjectFactoryTest.java | 76 +++ .../certification/RsaContentSignerBuilderTest.java | 63 +++ .../oom/certservice/certification/TestData.java | 95 ++++ .../oom/certservice/certification/TestUtils.java | 61 +++ .../certification/X509CertificateBuilderTest.java | 69 +++ .../configuration/CmpServersConfigLoaderTest.java | 117 ++++ .../configuration/CmpServersConfigTest.java | 236 ++++++++ .../configuration/Cmpv2ServerProviderTest.java | 100 ++++ .../Cmpv2ServersConfigurationValidatorTest.java | 213 +++++++ .../constraints/Cmpv2UrlValidatorTest.java | 57 ++ .../violations/PortNumberViolationTest.java | 76 +++ .../violations/RequestTypeViolationTest.java | 56 ++ .../certification/model/CsrModelTest.java | 185 +++++++ .../certservice/cmpv2client/Cmpv2ClientTest.java | 288 ++++++++++ .../cmpv2client/impl/CmpResponseHelperTest.java | 609 +++++++++++++++++++++ .../src/test/resources/application.properties | 6 +- 159 files changed, 7295 insertions(+), 7608 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 delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/CertServiceApplicationTests.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/api/CertificationControllerTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/api/ReadinessControllerTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/api/ReloadConfigControllerTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/api/advice/CertificationExceptionAdviceTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/api/advice/ReloadConfigExceptionAdviceTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/CertificationModelFactoryTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/CertificationProviderTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/CsrModelFactoryTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/PemObjectFactoryTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/RsaContentSignerBuilderTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/TestData.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/TestUtils.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/X509CertificateBuilderTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoaderTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/configuration/Cmpv2ServerProviderTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidatorTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidatorTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/PortNumberViolationTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolationTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/certification/model/CsrModelTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/cmpv2client/Cmpv2ClientTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/cmpv2client/external/RdnTest.java delete mode 100644 certService/src/test/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseHelperTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/CertServiceApplicationTests.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/api/CertificationControllerTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/api/ReadinessControllerTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/api/ReloadConfigControllerTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/api/advice/CertificationExceptionAdviceTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/api/advice/ReloadConfigExceptionAdviceTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/CertificationModelFactoryTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/CertificationProviderTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/CsrModelFactoryTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/PemObjectFactoryTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/RsaContentSignerBuilderTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/TestData.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/TestUtils.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/X509CertificateBuilderTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoaderTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/configuration/Cmpv2ServerProviderTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidatorTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidatorTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/PortNumberViolationTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolationTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/certification/model/CsrModelTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java create mode 100644 certService/src/test/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseHelperTest.java (limited to 'certService') diff --git a/certService/Dockerfile b/certService/Dockerfile index 770dab97..d74b692d 100644 --- a/certService/Dockerfile +++ b/certService/Dockerfile @@ -10,6 +10,6 @@ RUN chown -R certService:certService /var/log USER certService:certService -COPY target/aaf-certservice-api-${VERSION}.jar ./opt/onap/aaf/certservice/aaf-certservice-api.jar +COPY target/oom-certservice-api-${VERSION}.jar ./opt/onap/oom/certservice/oom-certservice-api.jar -ENTRYPOINT ["java","-jar","./opt/onap/aaf/certservice/aaf-certservice-api.jar"] +ENTRYPOINT ["java","-jar","./opt/onap/oom/certservice/oom-certservice-api.jar"] diff --git a/certService/README.md b/certService/README.md index 645ca061..1b24747a 100644 --- a/certService/README.md +++ b/certService/README.md @@ -3,18 +3,18 @@ ### General description More information about the project and all its functionalities you can find under the wiki page: ``` - https://wiki.onap.org/display/DW/AAF+Certification+Service + https://wiki.onap.org/display/DW/OOM+Certification+Service ``` ### For developers - * AAF Cert Service Api is a Spring Boot application + * OOM Cert Service Api is a Spring Boot application * Code style Use Google code formatter in your IDE. For IntelliJ use [https://plugins.jetbrains.com/plugin/8527-google-java-format] For other IDEs use []https://github.com/google/google-java-format] ### Local project configuration - * Create directory on your system /etc/onap/aaf/certservice + * Create directory on your system /etc/onap/oom/certservice * Copy sample configuration test/resources/cmpServers.json to that directory ### Running Locally @@ -37,7 +37,7 @@ mvn clean package ### Building Docker image manually Go to the certService subfolder and execute following statement (1.0.0-SNAPSHOT is related to a current project.version parameter): ``` -docker build --build-arg VERSION=1.0.0-SNAPSHOT -t onap/org.onap.aaf.certservice.aaf-certservice-api . +docker build --build-arg VERSION=1.0.0-SNAPSHOT -t onap/org.onap.oom.certservice.oom-certservice-api . ``` ### Install the package into the local repository @@ -52,12 +52,13 @@ mvn clean install -P docker ### Running Docker container local ``` -docker run -p 8080:8080 --name aaf-certservice-api --mount type=bind,source=//cmpServers.json,target=/etc/onap/aaf/certservice/cmpServers.json onap/org.onap.aaf.certservice.aaf-certservice-api +docker run -p 8080:8080 --name oom-certservice-api --mount type=bind,source=//cmpServers.json,target=/etc/onap/ +oom/certservice/cmpServers.json onap/org.onap.oom.certservice.oom-certservice-api ``` ### Running Docker container from nexus ``` -docker run -p 8080:8080 --name aaf-certservice-api --mount type=bind,source=//cmpServers.json,target=/etc/onap/aaf/certservice/cmpServers.json nexus3.onap.org:10001/onap/org.onap.aaf.certservice.aaf-certservice-api:1.0.0 +docker run -p 8080:8080 --name oom-certservice-api --mount type=bind,source=//cmpServers.json,target=/etc/onap/oom/certservice/cmpServers.json nexus3.onap.org:10001/onap/org.onap.oom.certservice.oom-certservice-api:1.0.0 ``` ### Health Check @@ -76,16 +77,16 @@ curl localhost:8080/actuator/health path: ``` -var/log/onap/aaf/certservice/ +var/log/onap/oom/certservice/ ``` ### Logs in Docker container ``` -docker exec -it aaf-certservice-api bash +docker exec -it oom-certservice-api bash ``` path: ``` -cd /var/log/onap/aaf/certservice +cd /var/log/onap/oom/certservice ``` You should see: audit.log error.log debug.log diff --git a/certService/pom.xml b/certService/pom.xml index 9febd167..4d75fe90 100644 --- a/certService/pom.xml +++ b/certService/pom.xml @@ -16,14 +16,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.onap.aaf.certservice - aaf-certservice + org.onap.oom.platform.cert-service + oom-certservice 1.2.0-SNAPSHOT - aaf-certservice-api + oom-certservice-api 1.2.0-SNAPSHOT - aaf-certservice-api - AAF Certification Service Api + oom-certservice-api + OOM Certification Service Api jar @@ -182,12 +182,12 @@ ecomp-releases - AAF Release Repository + OOM Release Repository ${nexusproxy}${releaseNexusPath} ecomp-snapshots - AAF Snapshot Repository + OOM Snapshot Repository ${nexusproxy}${snapshotNexusPath} 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); + } +} diff --git a/certService/src/main/resources/application.properties b/certService/src/main/resources/application.properties index c5d14370..a7f5eea8 100644 --- a/certService/src/main/resources/application.properties +++ b/certService/src/main/resources/application.properties @@ -7,16 +7,16 @@ management.endpoints.web.exposure.include=health springdoc.show-actuator=true springdoc.swagger-ui.path=/docs -# AAF CertService app specific configuration -app.config.path=/etc/onap/aaf/certservice +# OOM CertService app specific configuration +app.config.path=/etc/onap/oom/certservice # Mutual TLS configuration server.ssl.enabled=true server.ssl.client-auth=need server.port=${HTTPS_PORT:8443} -server.ssl.key-store=${KEYSTORE_PATH:/etc/onap/aaf/certservice/certs/certServiceServer-keystore.jks} +server.ssl.key-store=${KEYSTORE_PATH:/etc/onap/oom/certservice/certs/certServiceServer-keystore.jks} server.ssl.key-store-password=${KEYSTORE_PASSWORD:secret} -server.ssl.trust-store=${TRUSTSTORE_PATH:/etc/onap/aaf/certservice/certs/truststore.jks} +server.ssl.trust-store=${TRUSTSTORE_PATH:/etc/onap/oom/certservice/certs/truststore.jks} server.ssl.trust-store-password=${TRUSTSTORE_PASSWORD:secret} diff --git a/certService/src/main/resources/log4j2.xml b/certService/src/main/resources/log4j2.xml index f814b4bd..3a5b1f65 100644 --- a/certService/src/main/resources/log4j2.xml +++ b/certService/src/main/resources/log4j2.xml @@ -10,7 +10,7 @@ pattern="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} %highlight{${LOG_LEVEL_PATTERN:-%5p}}{FATAL=red blink, ERROR=red, WARN=yellow bold, INFO=green, DEBUG=green bold, TRACE=blue} %style{${sys:PID}}{magenta} [%15.15t] %style{%-40.40C{1.}}{cyan} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/> - + @@ -19,7 +19,7 @@ - + @@ -27,7 +27,7 @@ - + diff --git a/certService/src/test/java/org/onap/aaf/certservice/CertServiceApplicationTests.java b/certService/src/test/java/org/onap/aaf/certservice/CertServiceApplicationTests.java deleted file mode 100644 index 0dc60aa5..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/CertServiceApplicationTests.java +++ /dev/null @@ -1,34 +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.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class CertServiceApplicationTests { - - @Test - // We are excluding this line in Sonar due to fact that - // this test checks if Spring context is loaded and does not require assertion - void contextLoads() { // NOSONAR - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/api/CertificationControllerTest.java b/certService/src/test/java/org/onap/aaf/certservice/api/CertificationControllerTest.java deleted file mode 100644 index 449670c3..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/api/CertificationControllerTest.java +++ /dev/null @@ -1,147 +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 static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.when; - -import java.util.Arrays; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.onap.aaf.certservice.certification.CertificationModelFactory; -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.DecryptionException; -import org.onap.aaf.certservice.certification.exception.KeyDecryptionException; -import org.onap.aaf.certservice.certification.model.CertificationModel; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; - -@ExtendWith(MockitoExtension.class) -class CertificationControllerTest { - - private static final String TEST_CA_NAME = "TestCa"; - private static final String TEST_ENCODED_CSR = "encodedCSR"; - private static final String TEST_ENCODED_PK = "encodedPK"; - private static final String TEST_WRONG_ENCODED_CSR = "wrongEncodedCSR"; - private static final String TEST_WRONG_ENCODED_PK = "wrongEncodedPK"; - private static final String TEST_WRONG_CA_NAME = "wrongTestCa"; - - private CertificationController certificationController; - - @Mock - private CertificationModelFactory certificationModelFactory; - - @BeforeEach - void serUp() { - certificationController = new CertificationController(certificationModelFactory); - } - - @Test - void shouldReturnDataAboutCsrBaseOnEncodedParameters() - throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { - // Given - CertificationModel testCertificationModel = new CertificationModel( - Arrays.asList("ENTITY_CERT", "INTERMEDIATE_CERT"), - Arrays.asList("CA_CERT", "EXTRA_CA_CERT") - ); - when(certificationModelFactory.createCertificationModel(TEST_ENCODED_CSR, TEST_ENCODED_PK, TEST_CA_NAME)) - .thenReturn(testCertificationModel); - - // When - ResponseEntity responseCertificationModel = - certificationController.signCertificate(TEST_CA_NAME, TEST_ENCODED_CSR, TEST_ENCODED_PK); - - // Then - assertEquals(HttpStatus.OK, responseCertificationModel.getStatusCode()); - assertThat(responseCertificationModel.getBody() - ).isEqualToComparingFieldByField(testCertificationModel); - - } - - @Test - void shouldThrowCsrDecryptionExceptionWhenCreatingCsrModelFails() - throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { - // Given - String expectedMessage = "Incorrect CSR, decryption failed"; - when(certificationModelFactory.createCertificationModel(TEST_WRONG_ENCODED_CSR, TEST_ENCODED_PK, TEST_CA_NAME)) - .thenThrow(new CsrDecryptionException(expectedMessage)); - - // When - Exception exception = assertThrows( - CsrDecryptionException.class, () -> - certificationController.signCertificate(TEST_CA_NAME, TEST_WRONG_ENCODED_CSR, TEST_ENCODED_PK) - ); - - String actualMessage = exception.getMessage(); - - // Then - assertEquals(expectedMessage, actualMessage); - } - - @Test - void shouldThrowPemDecryptionExceptionWhenCreatingPemModelFails() - throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { - // Given - String expectedMessage = "Incorrect PEM, decryption failed"; - when(certificationModelFactory.createCertificationModel(TEST_ENCODED_CSR, TEST_WRONG_ENCODED_PK, TEST_CA_NAME)) - .thenThrow(new KeyDecryptionException(expectedMessage)); - - // When - Exception exception = assertThrows( - KeyDecryptionException.class, () -> - certificationController.signCertificate(TEST_CA_NAME, TEST_ENCODED_CSR, TEST_WRONG_ENCODED_PK) - ); - - String actualMessage = exception.getMessage(); - - // Then - assertEquals(expectedMessage, actualMessage); - } - - @Test - void shouldThrowCmpv2ServerNotFoundWhenGivenWrongCaName() - throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { - // Given - String expectedMessage = "No server found for given CA name"; - when(certificationModelFactory.createCertificationModel(TEST_ENCODED_CSR, TEST_ENCODED_PK, TEST_WRONG_CA_NAME)) - .thenThrow(new Cmpv2ServerNotFoundException(expectedMessage)); - - // When - Exception exception = assertThrows( - Cmpv2ServerNotFoundException.class, () -> - certificationController.signCertificate(TEST_WRONG_CA_NAME, TEST_ENCODED_CSR, TEST_ENCODED_PK) - ); - - String actualMessage = exception.getMessage(); - - // Then - assertEquals(expectedMessage, actualMessage); - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/api/ReadinessControllerTest.java b/certService/src/test/java/org/onap/aaf/certservice/api/ReadinessControllerTest.java deleted file mode 100644 index d3ed7301..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/api/ReadinessControllerTest.java +++ /dev/null @@ -1,59 +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 static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; -import org.onap.aaf.certservice.certification.configuration.CmpServersConfig; -import org.springframework.http.HttpStatus; - -@ExtendWith(MockitoExtension.class) -public class ReadinessControllerTest { - - @Mock - private CmpServersConfig cmpServersConfig; - - @Test - public void shouldReturnStatusOkWhenConfigIsReady() { - // Given - Mockito.when(cmpServersConfig.isReady()).thenReturn(true); - - // Then - assertThat(new ReadinessController(cmpServersConfig).checkReady().getStatusCode()).isEqualTo(HttpStatus.OK); - ; - } - - @Test - public void shouldReturnStatusServiceUnavailableWhenConfigIsNotReady() { - // Given - Mockito.when(cmpServersConfig.isReady()).thenReturn(false); - - // Then - assertThat(new ReadinessController(cmpServersConfig).checkReady().getStatusCode()).isEqualTo(HttpStatus.SERVICE_UNAVAILABLE); - ; - } - -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/api/ReloadConfigControllerTest.java b/certService/src/test/java/org/onap/aaf/certservice/api/ReloadConfigControllerTest.java deleted file mode 100644 index 92c18e16..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/api/ReloadConfigControllerTest.java +++ /dev/null @@ -1,77 +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 static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.doThrow; - -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.onap.aaf.certservice.certification.configuration.CmpServersConfig; -import org.onap.aaf.certservice.certification.configuration.CmpServersConfigLoadingException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; - -@ExtendWith(MockitoExtension.class) -public class ReloadConfigControllerTest { - - private static final String ERROR_MESSAGE = "Exception occurred during CMP Servers configuration loading"; - - private ReloadConfigController reloadConfigController; - - @Mock - public CmpServersConfig cmpServersConfig; - - @BeforeEach - void setUp() { - this.reloadConfigController = new ReloadConfigController(cmpServersConfig); - } - - @Test - void shouldReturnStatusOkWhenSuccessfullyReloaded() throws CmpServersConfigLoadingException { - // When - ResponseEntity response = reloadConfigController.reloadConfiguration(); - - // Then - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - } - - @Test - void shouldRethrowSameErrorWhenFailedToReload() throws CmpServersConfigLoadingException { - // Given - doThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)).when(cmpServersConfig).reloadConfiguration(); - - // When - Exception exception = assertThrows( - CmpServersConfigLoadingException.class, - () -> reloadConfigController.reloadConfiguration()); - - // Then - Assertions.assertThat(exception.getMessage()).isEqualTo(ERROR_MESSAGE); - } - - -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/api/advice/CertificationExceptionAdviceTest.java b/certService/src/test/java/org/onap/aaf/certservice/api/advice/CertificationExceptionAdviceTest.java deleted file mode 100644 index f3c4ec7f..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/api/advice/CertificationExceptionAdviceTest.java +++ /dev/null @@ -1,134 +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 com.google.gson.Gson; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -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.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class CertificationExceptionAdviceTest { - - private CertificationExceptionAdvice certificationExceptionAdvice; - - @BeforeEach - void setUp() { - certificationExceptionAdvice = - new CertificationExceptionAdvice(); - } - - @Test - void shouldReturnResponseEntityWithAppropriateErrorMessageWhenGivenCsrDecryptionException() { - // Given - String expectedMessage = "Wrong certificate signing request (CSR) format"; - CsrDecryptionException csrDecryptionException = new CsrDecryptionException("test csr exception"); - - // When - ResponseEntity response = certificationExceptionAdvice.handle(csrDecryptionException); - - // Then - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertEquals(expectedMessage, response.getBody().getErrorMessage()); - } - - @Test - void shouldReturnResponseEntityWithAppropriateErrorMessageWhenGivenKeyDecryptionException() { - // Given - String expectedMessage = "Wrong key (PK) format"; - KeyDecryptionException csrDecryptionException = new KeyDecryptionException("test pk exception"); - - // When - ResponseEntity response = certificationExceptionAdvice.handle(csrDecryptionException); - - // Then - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertEquals(expectedMessage, response.getBody().getErrorMessage()); - } - - @Test - void shouldReturnResponseEntityWithAppropriateErrorMessageWhenGivenCaNameIsNotPresentInConfig() { - // Given - String expectedMessage = "Certification authority not found for given CAName"; - Cmpv2ServerNotFoundException csrDecryptionException = new Cmpv2ServerNotFoundException("test Ca exception"); - - // When - ResponseEntity response = certificationExceptionAdvice.handle(csrDecryptionException); - - // Then - assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); - assertEquals(expectedMessage, response.getBody().getErrorMessage()); - } - - @Test - void shouldReturnResponseEntityWithAppropriateErrorMessageWhenCallingCmpClientFail() { - // Given - String expectedMessage = "Exception occurred during call to cmp client"; - CmpClientException cmpClientException = new CmpClientException("Calling CMPv2 client failed"); - - // When - ResponseEntity response = certificationExceptionAdvice.handle(cmpClientException); - - // Then - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); - assertEquals(expectedMessage, response.getBody().getErrorMessage()); - } - - @Test - void shouldReturnResponseEntityWithAppropriateErrorMessageWhenModelTransformationInAdapterFail() { - // Given - String expectedMessage = "Exception occurred parsing cmp client response"; - Cmpv2ClientAdapterException cmpv2ClientAdapterException = new Cmpv2ClientAdapterException(new Throwable()); - - // When - ResponseEntity response = certificationExceptionAdvice.handle(cmpv2ClientAdapterException); - - // Then - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); - assertEquals(expectedMessage, response.getBody().getErrorMessage()); - } - - @Test - void shouldThrowCmpClientExceptionWhenNotHandledRunTimeExceptionOccur() { - // Given - String expectedMessage = "Runtime exception occurred calling cmp client business logic"; - RuntimeException runtimeException = new RuntimeException("Unknown runtime exception"); - - // When - Exception exception = assertThrows( - CmpClientException.class, () -> - certificationExceptionAdvice.handle(runtimeException) - ); - - // Then - assertEquals(expectedMessage, exception.getMessage()); - } - -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/api/advice/ReloadConfigExceptionAdviceTest.java b/certService/src/test/java/org/onap/aaf/certservice/api/advice/ReloadConfigExceptionAdviceTest.java deleted file mode 100644 index 9abecec9..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/api/advice/ReloadConfigExceptionAdviceTest.java +++ /dev/null @@ -1,56 +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.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.onap.aaf.certservice.certification.configuration.CmpServersConfigLoadingException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class ReloadConfigExceptionAdviceTest { - - private static final String ERROR_MESSAGE = "Exception occurred during CMP Servers configuration loading"; - - private ReloadConfigExceptionAdvice reloadConfigExceptionAdvice; - - @BeforeEach - void setUp() { - reloadConfigExceptionAdvice = - new ReloadConfigExceptionAdvice(); - } - - @Test - void shouldReturnErrorStatusAndMessageWhenExceptionOccurred() { - // Given - CmpServersConfigLoadingException exception = new CmpServersConfigLoadingException(ERROR_MESSAGE); - - // When - ResponseEntity response = reloadConfigExceptionAdvice.handle(exception); - - // Then - assertEquals(ERROR_MESSAGE, response.getBody()); - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); - } - -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/CertificationModelFactoryTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/CertificationModelFactoryTest.java deleted file mode 100644 index a63c8e0e..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/CertificationModelFactoryTest.java +++ /dev/null @@ -1,220 +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.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.onap.aaf.certservice.certification.configuration.Cmpv2ServerProvider; -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -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.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 java.util.Arrays; -import java.util.Base64; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.onap.aaf.certservice.certification.CertificationData.CA_CERT; -import static org.onap.aaf.certservice.certification.CertificationData.ENTITY_CERT; -import static org.onap.aaf.certservice.certification.CertificationData.INTERMEDIATE_CERT; -import static org.onap.aaf.certservice.certification.CertificationData.EXTRA_CA_CERT; -import static org.onap.aaf.certservice.certification.TestData.TEST_CSR; -import static org.onap.aaf.certservice.certification.TestData.TEST_PK; -import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_CSR; -import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_PEM; - -@ExtendWith(MockitoExtension.class) -class CertificationModelFactoryTest { - - private static final String TEST_CA = "testCA"; - private static final String ENCODED_CSR = getEncodedString(TEST_CSR); - private static final String ENCODED_PK = getEncodedString(TEST_PK); - private static final String ENCODED_WRONG_CSR = getEncodedString(TEST_WRONG_CSR); - private static final String ENCODED_WRONG_PK = getEncodedString(TEST_WRONG_PEM); - - private CertificationModelFactory certificationModelFactory; - - @Mock - private Cmpv2ServerProvider cmpv2ServerProvider; - @Mock - private CsrModelFactory csrModelFactory; - @Mock - private CertificationProvider certificationProvider; - - - private static String getEncodedString(String testCsr) { - return Base64.getEncoder().encodeToString(testCsr.getBytes()); - } - - @BeforeEach - void setUp() { - certificationModelFactory = - new CertificationModelFactory(csrModelFactory, cmpv2ServerProvider, certificationProvider); - } - - @Test - void shouldCreateProperCertificationModelWhenGivenProperCsrModelAndCaName() - throws CmpClientException, DecryptionException, Cmpv2ClientAdapterException { - - // Given - CsrModel csrModel = mockCsrFactoryModelCreation(); - Cmpv2Server testServer = mockCmpv2ProviderServerSelection(); - mockCertificateProviderCertificateSigning(csrModel, testServer); - - // When - CertificationModel certificationModel = - certificationModelFactory.createCertificationModel(ENCODED_CSR, ENCODED_PK, TEST_CA); - - // Then - assertEquals(2, certificationModel.getCertificateChain().size()); - assertThat(certificationModel.getCertificateChain()).contains(INTERMEDIATE_CERT, ENTITY_CERT); - assertEquals(2, certificationModel.getTrustedCertificates().size()); - assertThat(certificationModel.getTrustedCertificates()).contains(CA_CERT, EXTRA_CA_CERT); - } - - @Test - void shouldThrowDecryptionExceptionWhenGivenWrongEncodedCsr() - throws DecryptionException { - // Given - String expectedMessage = "Incorrect CSR, decryption failed"; - when( - csrModelFactory.createCsrModel( - eq(new CsrModelFactory.StringBase64(ENCODED_WRONG_CSR)), - eq(new CsrModelFactory.StringBase64(ENCODED_WRONG_PK)) - ) - ).thenThrow( - new CsrDecryptionException(expectedMessage) - ); - - // When - Exception exception = assertThrows( - DecryptionException.class, () -> - certificationModelFactory.createCertificationModel(ENCODED_WRONG_CSR, ENCODED_WRONG_PK, TEST_CA) - ); - - // Then - assertTrue(exception.getMessage().contains(expectedMessage)); - } - - @Test - void shouldThrowCmpv2ServerNotFoundExceptionWhenGivenWrongCaName() - throws DecryptionException { - // Given - String expectedMessage = "CA not found"; - mockCsrFactoryModelCreation(); - when( - cmpv2ServerProvider.getCmpv2Server(TEST_CA) - ).thenThrow( - new Cmpv2ServerNotFoundException(expectedMessage) - ); - - // When - Exception exception = assertThrows( - Cmpv2ServerNotFoundException.class, () -> - certificationModelFactory.createCertificationModel(ENCODED_CSR, ENCODED_PK, TEST_CA) - ); - - // Then - assertTrue(exception.getMessage().contains(expectedMessage)); - } - - @Test - void shouldThrowCmpClientExceptionWhenSigningCsrFailed() - throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { - // Given - String expectedMessage = "failed to sign certificate"; - CsrModel csrModel = mockCsrFactoryModelCreation(); - Cmpv2Server testServer = mockCmpv2ProviderServerSelection(); - when( - certificationProvider.signCsr(eq(csrModel), eq(testServer)) - ).thenThrow( - new CmpClientException(expectedMessage) - ); - - // When - Exception exception = assertThrows( - CmpClientException.class, () -> - certificationModelFactory.createCertificationModel(ENCODED_CSR, ENCODED_PK, TEST_CA) - ); - - // Then - assertTrue(exception.getMessage().contains(expectedMessage)); - } - - - private void mockCertificateProviderCertificateSigning(CsrModel csrModel, Cmpv2Server testServer) - throws CmpClientException, Cmpv2ClientAdapterException { - CertificationModel expectedCertificationModel = getCertificationModel(); - when( - certificationProvider.signCsr(eq(csrModel), eq(testServer)) - ).thenReturn(expectedCertificationModel); - } - - private Cmpv2Server mockCmpv2ProviderServerSelection() { - Cmpv2Server testServer = getCmpv2Server(); - when( - cmpv2ServerProvider.getCmpv2Server(eq(TEST_CA)) - ).thenReturn(testServer); - return testServer; - } - - private CsrModel mockCsrFactoryModelCreation() - throws DecryptionException { - CsrModel csrModel = getCsrModel(); - when( - csrModelFactory.createCsrModel( - eq(new CsrModelFactory.StringBase64(ENCODED_CSR)), - eq(new CsrModelFactory.StringBase64(ENCODED_PK)) - ) - ).thenReturn(csrModel); - return csrModel; - } - - private Cmpv2Server getCmpv2Server() { - return new Cmpv2Server(); - } - - private CsrModel getCsrModel() { - return mock(CsrModel.class); - } - - private CertificationModel getCertificationModel() { - List testTrustedCertificates = Arrays.asList(CA_CERT, EXTRA_CA_CERT); - List testCertificationChain = Arrays.asList(INTERMEDIATE_CERT, ENTITY_CERT); - return new CertificationModel(testCertificationChain, testTrustedCertificates); - } - - -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/CertificationProviderTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/CertificationProviderTest.java deleted file mode 100644 index a590c5ea..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/CertificationProviderTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * AAF Certification 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.apache.commons.io.IOUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.onap.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 java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchProviderException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Collections; -import java.util.Objects; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class CertificationProviderTest { - - @Mock - private CsrModel csrModel; - @Mock - private Cmpv2Server server; - @Mock - private CsrModel testCsrModel; - @Mock - private Cmpv2Server testServer; - @Mock - private CmpClient cmpClient; - - private CertificationProvider certificationProvider; - - @BeforeEach - public void init() { - certificationProvider = new CertificationProvider(cmpClient); - } - - @Test - void shouldConvertToCertificationModel() - throws CertificateException, NoSuchProviderException, IOException, CmpClientException { - // When - when( - cmpClient.createCertificate(any(CsrModel.class), any(Cmpv2Server.class)) - ).thenReturn(createCorrectClientResponse()); - - CertificationModel certificationModel = certificationProvider.signCsr(csrModel, server); - - // Then - InputStream certificate = getClass().getClassLoader().getResourceAsStream("certificateModelChain.first"); - InputStream trustedCertificate = - getClass().getClassLoader().getResourceAsStream("trustedCertificatesModel.first"); - String certificateModel = removeLineEndings(certificationModel.getCertificateChain().get(0)); - String expectedCertificate = - removeLineEndings(IOUtils.toString(Objects.requireNonNull(certificate), StandardCharsets.UTF_8)); - String trustedCertificateModel = removeLineEndings(certificationModel.getTrustedCertificates().get(0)); - String expectedTrustedCertificate = - removeLineEndings(IOUtils.toString(Objects.requireNonNull(trustedCertificate), StandardCharsets.UTF_8)); - - assertThat(certificateModel).isEqualTo(expectedCertificate); - assertThat(trustedCertificateModel).isEqualTo(expectedTrustedCertificate); - } - - - @Test - void certificationProviderThrowCmpClientWhenCallingClientFails() - throws CmpClientException { - // Given - String expectedErrorMessage = "connecting to CMP client failed"; - - when( - cmpClient.createCertificate(any(CsrModel.class), any(Cmpv2Server.class)) - ).thenThrow(new CmpClientException(expectedErrorMessage)); - - // When - Exception exception = assertThrows( - CmpClientException.class, () -> - certificationProvider.signCsr(testCsrModel, testServer) - ); - - // Then - assertThat(exception.getMessage()).isEqualTo(expectedErrorMessage); - } - - private Cmpv2CertificationModel createCorrectClientResponse() - throws CertificateException, NoSuchProviderException { - InputStream certificateChain = getClass().getClassLoader().getResourceAsStream("certificateChain.first"); - InputStream trustedCertificate = getClass().getClassLoader().getResourceAsStream("trustedCertificates.first"); - X509Certificate x509Certificate = new CertificateFactoryProvider().generateCertificate(certificateChain); - X509Certificate x509TrustedCertificate = - new CertificateFactoryProvider().generateCertificate(trustedCertificate); - return new Cmpv2CertificationModel( - Collections.singletonList(x509Certificate), - Collections.singletonList(x509TrustedCertificate)); - } - - private String removeLineEndings(String string) { - return string.replace("\n", "").replace("\r", ""); - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/CsrModelFactoryTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/CsrModelFactoryTest.java deleted file mode 100644 index d2c3c54c..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/CsrModelFactoryTest.java +++ /dev/null @@ -1,147 +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.util.encoders.Base64; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.onap.aaf.certservice.certification.CsrModelFactory.StringBase64; -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 static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.onap.aaf.certservice.certification.TestData.TEST_CSR; -import static org.onap.aaf.certservice.certification.TestData.TEST_PK; -import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_CSR; -import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_PEM; - - -class CsrModelFactoryTest { - - private CsrModelFactory csrModelFactory; - - @BeforeEach - void setUp() { - csrModelFactory = new CsrModelFactory(); - } - - @Test - void shouldDecryptCsrAndReturnStringWithDataAboutIt() throws DecryptionException { - // given - String encoderCsr = new String(Base64.encode(TEST_CSR.getBytes())); - String encoderPK = new String(Base64.encode(TEST_PK.getBytes())); - - // when - CsrModel decryptedCsr = csrModelFactory - .createCsrModel(new StringBase64(encoderCsr), new StringBase64(encoderPK)); - - // then - assertTrue( - decryptedCsr.toString() - .contains( - "C=US,ST=California,L=San-Francisco,O=Linux-Foundation," - + "OU=ONAP,CN=onap.org,E=tester@onap.org") - && - decryptedCsr.toString() - .contains("SANs: [gerrit.onap.org, test.onap.org, onap.com]") - ); - } - - @Test - void shouldThrowCsrDecryptionExceptionWhenCsrIsIncorrect() { - // given - String encoderPK = new String(Base64.encode(TEST_PK.getBytes())); - String wrongCsr = new String(Base64.encode(TEST_WRONG_CSR.getBytes())); - - // when - Exception exception = assertThrows( - CsrDecryptionException.class, () -> csrModelFactory - .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK)) - ); - - String expectedMessage = "Incorrect CSR, decryption failed"; - String actualMessage = exception.getMessage(); - - // then - assertTrue(actualMessage.contains(expectedMessage)); - } - - @Test - void shouldThrowKeyDecryptionExceptionWhenKeyIsIncorrect() { - // given - String encoderPK = new String(Base64.encode(TEST_WRONG_PEM.getBytes())); - String wrongCsr = new String(Base64.encode(TEST_CSR.getBytes())); - - // when - Exception exception = assertThrows( - KeyDecryptionException.class, () -> csrModelFactory - .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK)) - ); - - String expectedMessage = "Incorrect Key, decryption failed"; - String actualMessage = exception.getMessage(); - - // then - assertTrue(actualMessage.contains(expectedMessage)); - } - - - @Test - void shouldThrowCsrDecryptionExceptionWhenCsrIsNotInBase64Encoding() { - // given - String encoderPK = new String(Base64.encode(TEST_PK.getBytes())); - String wrongCsr = "Not Base 64 Csr"; - - // when - Exception exception = assertThrows( - CsrDecryptionException.class, () -> csrModelFactory - .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK)) - ); - - String expectedMessage = "Incorrect CSR, decryption failed"; - String actualMessage = exception.getMessage(); - - // then - assertTrue(actualMessage.contains(expectedMessage)); - } - - @Test - void shouldThrowKeyDecryptionExceptionWhenPkIsNotInBase64Encoding() { - // given - String encoderPK = "Not Base64 Key"; - String wrongCsr = new String(Base64.encode(TEST_CSR.getBytes())); - - // when - Exception exception = assertThrows( - KeyDecryptionException.class, () -> csrModelFactory - .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK)) - ); - - String expectedMessage = "Incorrect Key, decryption failed"; - String actualMessage = exception.getMessage(); - - // then - assertTrue(actualMessage.contains(expectedMessage)); - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/PemObjectFactoryTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/PemObjectFactoryTest.java deleted file mode 100644 index 90151b6d..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/PemObjectFactoryTest.java +++ /dev/null @@ -1,76 +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.util.io.pem.PemObject; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.onap.aaf.certservice.certification.exception.DecryptionException; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.onap.aaf.certservice.certification.TestData.TEST_PEM; -import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_PEM; -import static org.onap.aaf.certservice.certification.TestUtils.pemObjectToString; - - -class PemObjectFactoryTest { - - - private PemObjectFactory pemObjectFactory; - - @BeforeEach - void setUp() { - pemObjectFactory = new PemObjectFactory(); - } - - @Test - void shouldTransformStringInToPemObjectAndBackToString() throws DecryptionException { - // when - PemObject pemObject = pemObjectFactory.createPemObject(TEST_PEM).orElseThrow( - () -> new DecryptionException("Pem decryption failed") - ); - String parsedPemObject = pemObjectToString(pemObject); - - // then - assertEquals(TEST_PEM, parsedPemObject); - } - - @Test - void shouldThrowExceptionWhenParsingPemFailed() { - // given - String expectedMessage = "Unable to create PEM"; - - // when - Exception exception = assertThrows( - DecryptionException.class, () -> pemObjectFactory.createPemObject(TEST_WRONG_PEM).orElseThrow( - () -> new DecryptionException(expectedMessage) - ) - ); - - String actualMessage = exception.getMessage(); - - // then - assertTrue(actualMessage.contains(expectedMessage)); - } - -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/RsaContentSignerBuilderTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/RsaContentSignerBuilderTest.java deleted file mode 100644 index 0083968d..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/RsaContentSignerBuilderTest.java +++ /dev/null @@ -1,63 +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.operator.ContentSigner; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.onap.aaf.certservice.certification.RsaContentSignerBuilder; -import org.onap.aaf.certservice.certification.exception.DecryptionException; -import org.onap.aaf.certservice.certification.model.CsrModel; - -import java.io.IOException; -import java.security.PrivateKey; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.onap.aaf.certservice.certification.TestUtils.createCsrModel; - -class RsaContentSignerBuilderTest { - - private RsaContentSignerBuilder rsaContentSignerBuilder; - - @BeforeEach - void setUp() { - rsaContentSignerBuilder = new RsaContentSignerBuilder(); - } - - @Test - void shouldBuildProperContentSignerWhenProvidedCertificationRequestAndPrivateKey() - throws IOException, OperatorCreationException, DecryptionException { - // Given - CsrModel testCsrModel = createCsrModel(); - PKCS10CertificationRequest testCertificationRequest = testCsrModel.getCsr(); - PrivateKey testPrivateKey = testCsrModel.getPrivateKey(); - - // When - ContentSigner createdContentSigner = rsaContentSignerBuilder.build(testCertificationRequest, testPrivateKey); - - // Then - assertThat(createdContentSigner.getAlgorithmIdentifier()) - .isEqualTo(testCertificationRequest.getSignatureAlgorithm()); - } - -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/TestData.java b/certService/src/test/java/org/onap/aaf/certservice/certification/TestData.java deleted file mode 100644 index 6fea5b5a..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/TestData.java +++ /dev/null @@ -1,95 +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; - -public final class TestData { - - private TestData() { - } - - public static final String TEST_CSR = "" - + "-----BEGIN CERTIFICATE REQUEST-----\n" - + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh\n" - + "MRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQKDBBMaW51eC1Gb3VuZGF0\n" - + "aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQDDAhvbmFwLm9yZzEeMBwGCSqGSIb3\n" - + "DQEJARYPdGVzdGVyQG9uYXAub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" - + "CgKCAQEA13K1LrQ1L6eL7B8K4kucNct0sSjZe7Ww91V40s6mjcWajeFJk+pObZKz\n" - + "BfnImkVJwxdNMDD6tX16wykbGfQPyh4BBiAjLVk9XSeoPHFRBQ4LKTuyPtXhEXyr\n" - + "qwatYXGWZE554qq64pbReddOUJHgMc38SrOk/eMAKxB0uRrXpA0mPH7zwIZ4X8g2\n" - + "PoxJKI1BSYc8kOvvujsGSMw3e5nS8A+doFUwVi3jJMnaVCoZrvJbtREfXHZqBLQ5\n" - + "XQ8mNpIFfmGYF/tvW/O6LBdlZkuAQ9i4FBgf5+HdIVZOXrn09ksIZxW6vxIvAVi0\n" - + "5AOSgXictyphcNP2i/erBeCQCVB7MwIDAQABoEYwRAYJKoZIhvcNAQkOMTcwNTAz\n" - + "BgNVHREELDAqgg9nZXJyaXQub25hcC5vcmeCDXRlc3Qub25hcC5vcmeCCG9uYXAu\n" - + "Y29tMA0GCSqGSIb3DQEBCwUAA4IBAQBXH2nRwodQRJTuyrLe/VSg3PUdcPyAx2Ew\n" - + "63tWiGO+qWo8rK2a9Rr/t/zkQe2lx6NHqcMc2Rt6NeKGbrAvHGxTiYM35gktBdxG\n" - + "UaQS1ymrBWHAwbC+kv78r+5lCfafNm/EVdhUZbEw+crsw2wx4iKEW0byS4Ln0o5g\n" - + "aXVUW3i4G5FaYiYBUIDsujDdnH1IoxunEA6pDzDv1h6R9/TYu6Se8HToREIjOPBZ\n" - + "pDI5lDRu0YmI8r+TmAU3tTT1sY2WVxYDnhJut9ofegfMPQV4FIohxtPcCfoLSWti\n" - + "ml6jbcFqDvlzq3B3CXH9HU3jdJt33iSjCQGsSqy6bmCOdMS6XTPU\n" - + "-----END CERTIFICATE REQUEST-----\n"; - - public static final String TEST_WRONG_CSR = "" - + "-----BEGIN CERTIFICATE REQUEST-----\n" - + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh\n" - + "MRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQKDBBMaW51eC1Gb3VuZGF0\n" - + "aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQDDAhvbmFwLm9yZzEeMBwGCSqGSIb3\n" - + "-----END CERTIFICATE REQUEST-----\n"; - - public static final String TEST_PK = "-----BEGIN PRIVATE KEY-----\n" - + "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDXcrUutDUvp4vs\n" - + "HwriS5w1y3SxKNl7tbD3VXjSzqaNxZqN4UmT6k5tkrMF+ciaRUnDF00wMPq1fXrD\n" - + "KRsZ9A/KHgEGICMtWT1dJ6g8cVEFDgspO7I+1eERfKurBq1hcZZkTnniqrriltF5\n" - + "105QkeAxzfxKs6T94wArEHS5GtekDSY8fvPAhnhfyDY+jEkojUFJhzyQ6++6OwZI\n" - + "zDd7mdLwD52gVTBWLeMkydpUKhmu8lu1ER9cdmoEtDldDyY2kgV+YZgX+29b87os\n" - + "F2VmS4BD2LgUGB/n4d0hVk5eufT2SwhnFbq/Ei8BWLTkA5KBeJy3KmFw0/aL96sF\n" - + "4JAJUHszAgMBAAECggEAJ1StdsU3IGf5xzUzi3Q6JCfsOZs3eLoGgGB+Gh3XkfIM\n" - + "8PG7uOEBSEeLnv+me2NCv/a1BKMsYY1yp8YNSIOhjkhD75ZWVaUA6syejcox/DZA\n" - + "G1rmg0oQOF0GCcbCSBOwXMdmwNZiH5Ng0llX1qWKxAzSjeCVsjOKiFIMvO4Fh9D4\n" - + "9Io6/dRRNCxB6MEs1GT5IDfCV2PGDIalJ3znFqDnfdu9RDEDfNVHSUr6Jdu3Hrf5\n" - + "3qCcSEkMGuXYLotCNtTP1x0H0wW5gVpcbQEb29qdmHL1qkp3UiA3afsHnO/3k0gv\n" - + "gV5FxaldugyZAjqUGERdKaY6BMDJkDuu0qD0tPQK4QKBgQDuP5X5BcQ4iHNej+il\n" - + "xxT8QaEcZj0YEzcXzfm3ztZP7g+Jc1MbQXh6BuHLkXG5LeCwdnmk+LUD0MLoUSm3\n" - + "N2ZdtVuOHX7VEBrhrTwK/kMDpC7ganQzfvgOr9WQGmgGMRiUYAyK1J/x78yX967Z\n" - + "IAzdVZ/JSDdsyA983JckLL7CPQKBgQDngDkEJKYGfDt2mfItD8c8nhczGbDdoyYh\n" - + "s93ppTtgzFoNgFL4y/DOvisWMGgoeeYXSgH5uoPv6yY7IIkQzYySY6qQ3gmk1/X+\n" - + "bO+IsKVtlHBzqqojFteg3MfVojisMoAx6y5aBw1BXE2nAU8yWBTtuk+3KgGn9Oxk\n" - + "+Z4rdP06LwKBgA4b09zIW6NhaTubWBKhJHv/wvO0lj+bu7J8LyKUbBqVpXPlUXGW\n" - + "wfSv/aUZetuVfO3WRkPfupB8R16Ml+TSsgwwljhnRMCHUKA2qwyXnA5WJbSCeVkn\n" - + "Vrc/8Gy1M53SQHtg6L079DDWm44QS9ltzXU6Adlgnm+htVEWmxi4UZ+dAoGAfr6z\n" - + "+LG7+GcCA2AruEIgOe7wErkpHV+am+8nOymMxeV8FFJCmxbFQ9vYKTDdhfOfZvbM\n" - + "+BYG8E8VQmAAyyNOqENK+j+mlgrrEp4/0t2r5L/VhW5V8hoqelcGTc+gKZ8IkswJ\n" - + "N58Owc8wcJQF8TFKXBGaXVTxTSyKVIpZ778AeV8CgYAAvuicDkdwWv5EhDFf3aTI\n" - + "wfRFYflA6oiygnI63HzVyY4a+SyZs+nQpB5HBDo+Lyz8RaVRC5E7jQ8kiXJpxAu7\n" - + "1wnspz+pa3q61yR32N+zGuub71FXdLWSOlys6rzJqvqYihKxY22C2TyDyBCR2tMj\n" - + "mdnshXNAJfKkfghkJhFHrg==\n" - + "-----END PRIVATE KEY-----"; - - public static final String TEST_PEM = "" - + "-----BEGIN CERTIFICATE REQUEST-----\n" - + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh\n" - + "-----END CERTIFICATE REQUEST-----\n"; - - public static final String TEST_WRONG_PEM = "" - + "-----BEGIN WRONG REQUEST-----" - + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh" - + "-----END WRONG REQUEST-----"; - -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/TestUtils.java b/certService/src/test/java/org/onap/aaf/certservice/certification/TestUtils.java deleted file mode 100644 index a6e55c57..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/TestUtils.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.certification; - -import org.bouncycastle.util.encoders.Base64; -import org.bouncycastle.util.io.pem.PemObject; -import org.bouncycastle.util.io.pem.PemWriter; -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 java.io.IOException; -import java.io.StringWriter; - -import static org.onap.aaf.certservice.certification.TestData.TEST_CSR; -import static org.onap.aaf.certservice.certification.TestData.TEST_PK; - - -public final class TestUtils { - - private TestUtils() { - } - - public static String pemObjectToString(PemObject pemObject) throws KeyDecryptionException { - try (StringWriter output = new StringWriter()) { - PemWriter pemWriter = new PemWriter(output); - pemWriter.writeObject(pemObject); - pemWriter.close(); - return output.getBuffer().toString(); - - } catch (IOException e) { - throw new KeyDecryptionException("Writing PAM Object to string failed", e); - } - } - - public static CsrModel createCsrModel() throws DecryptionException { - CsrModelFactory csrModelFactory = new CsrModelFactory(); - String encoderCsr = new String(Base64.encode(TEST_CSR.getBytes())); - String encoderPK = new String(Base64.encode(TEST_PK.getBytes())); - return csrModelFactory - .createCsrModel(new CsrModelFactory.StringBase64(encoderCsr), new CsrModelFactory.StringBase64(encoderPK)); - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/X509CertificateBuilderTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/X509CertificateBuilderTest.java deleted file mode 100644 index 067f2f5f..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/X509CertificateBuilderTest.java +++ /dev/null @@ -1,69 +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.cert.X509CertificateHolder; -import org.bouncycastle.cert.X509v3CertificateBuilder; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.onap.aaf.certservice.certification.exception.DecryptionException; -import org.onap.aaf.certservice.certification.model.CsrModel; - -import java.io.IOException; -import java.security.PrivateKey; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.onap.aaf.certservice.certification.TestUtils.createCsrModel; - -public class X509CertificateBuilderTest { - - private X509CertificateBuilder certificateBuilder; - - - @BeforeEach - void setUp() { - certificateBuilder = new X509CertificateBuilder(); - } - - @Test - void shouldBuildCertificateBuilderWhenGivenProperCertificationRequest() - throws DecryptionException, IOException, OperatorCreationException { - // Given - CsrModel testCsrModel = createCsrModel(); - PKCS10CertificationRequest testCertificationRequest = testCsrModel.getCsr(); - PrivateKey testPrivateKey = testCsrModel.getPrivateKey(); - RsaContentSignerBuilder rsaContentSignerBuilder = new RsaContentSignerBuilder(); - ContentSigner createdContentSigner = rsaContentSignerBuilder.build(testCertificationRequest, testPrivateKey); - - // When - X509v3CertificateBuilder certificateBuilder = this.certificateBuilder.build(testCertificationRequest); - X509CertificateHolder certificateHolder = certificateBuilder.build(createdContentSigner); - - // Then - assertThat(certificateHolder.getIssuer()) - .isEqualToComparingFieldByField(testCsrModel.getSubjectData()); - assertThat(certificateHolder.getSubjectPublicKeyInfo()) - .isEqualToComparingFieldByField(testCertificationRequest.getSubjectPublicKeyInfo()); - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoaderTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoaderTest.java deleted file mode 100644 index 87964295..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoaderTest.java +++ /dev/null @@ -1,117 +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 static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import java.util.List; -import java.util.Map; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.onap.aaf.certservice.CertServiceApplication; -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -@ExtendWith(SpringExtension.class) -@ContextConfiguration(classes = CertServiceApplication.class) -class CmpServersConfigLoaderTest { - private static final String EXISTING_CONFIG_FILENAME = "cmpServers.json"; - private static final String INVALID_CONFIG_FILENAME = "invalidCmpServers.json"; - private static final String NONEXISTENT_CONFIG_FILENAME = "nonExistingCmpServers.json"; - - private static final Map EXPECTED_FIRST_CMP_SERVER = Map.of( - "CA_NAME", "TEST", - "URL", "http://127.0.0.1/ejbca/publicweb/cmp/cmp", - "ISSUER_DN", "CN=ManagementCA", - "CA_MODE", "CLIENT", - "IAK", "xxx", - "RV", "yyy" - ); - private static final Map EXPECTED_SECOND_CMP_SERVER = Map.of( - "CA_NAME", "TEST2", - "URL", "http://127.0.0.1/ejbca/publicweb/cmp/cmpRA", - "ISSUER_DN", "CN=ManagementCA2", - "CA_MODE", "RA", - "IAK", "xxx", - "RV", "yyy" - ); - - @Autowired - private CmpServersConfigLoader configLoader; - - @Test - void shouldLoadCmpServersConfigWhenFileAvailable() throws CmpServersConfigLoadingException { - // Given - String path = getResourcePath(EXISTING_CONFIG_FILENAME); - - // When - List cmpServers = configLoader.load(path); - - // Then - assertThat(cmpServers).isNotNull(); - assertThat(cmpServers).hasSize(2); - verifyThatCmpServerEquals(cmpServers.get(0), EXPECTED_FIRST_CMP_SERVER); - verifyThatCmpServerEquals(cmpServers.get(1), EXPECTED_SECOND_CMP_SERVER); - } - - @Test - void shouldThrowExceptionWhenFileMissing() { - // When - Exception exception = assertThrows( - CmpServersConfigLoadingException.class, - () -> configLoader.load(NONEXISTENT_CONFIG_FILENAME)); - - // Then - assertThat(exception.getMessage()).contains("Exception occurred during CMP Servers configuration loading"); - } - - @Test - void shouldThrowExceptionWhenConfigurationIsInvalid() { - // Given - String path = getResourcePath(INVALID_CONFIG_FILENAME); - - // When - Exception exception = assertThrows( - CmpServersConfigLoadingException.class, - () -> configLoader.load(path)); - - // Then - assertThat(exception.getMessage()).contains("Validation of CMPv2 servers configuration failed"); - assertThat(exception.getCause().getMessage()).contains("authentication"); - } - - private String getResourcePath(String configFilename) { - return getClass().getClassLoader().getResource(configFilename).getFile(); - } - - private void verifyThatCmpServerEquals(Cmpv2Server cmpv2Server, Map expected) { - assertThat(cmpv2Server.getCaName()).isEqualTo(expected.get("CA_NAME")); - assertThat(cmpv2Server.getUrl()).isEqualTo(expected.get("URL")); - assertThat(cmpv2Server.getIssuerDN().toString()).isEqualTo(expected.get("ISSUER_DN")); - assertThat(cmpv2Server.getCaMode().name()).isEqualTo(expected.get("CA_MODE")); - assertThat(cmpv2Server.getAuthentication().getIak()).isEqualTo(expected.get("IAK")); - assertThat(cmpv2Server.getAuthentication().getRv()).isEqualTo(expected.get("RV")); - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigTest.java deleted file mode 100644 index 511c3966..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigTest.java +++ /dev/null @@ -1,236 +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 static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.startsWith; - -import java.util.List; - -import org.bouncycastle.asn1.x500.X500Name; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; -import org.onap.aaf.certservice.certification.configuration.model.Authentication; -import org.onap.aaf.certservice.certification.configuration.model.CaMode; -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; - -@ExtendWith(MockitoExtension.class) -class CmpServersConfigTest { - - private static final String ERROR_MESSAGE = "Exception occurred during CMP Servers configuration loading"; - private static final String APP_CONFIG_PATH = "/fake/path/to/config"; - private static final List SAMPLE_CMP_SERVERS = generateTestConfiguration(); - - @Mock - private CmpServersConfigLoader cmpServersConfigLoader; - - private CmpServersConfig cmpServersConfig; - - @BeforeEach - void setUp() { - cmpServersConfig = new CmpServersConfig(APP_CONFIG_PATH, cmpServersConfigLoader); - } - - @Test - void shouldCallLoaderWithPathFromPropertiesWhenCreated() throws CmpServersConfigLoadingException { - // When - this.cmpServersConfig.init(); // Manual PostConstruct call - - // Then - Mockito.verify(cmpServersConfigLoader).load(startsWith(APP_CONFIG_PATH)); - } - - @Test - void shouldReturnLoadedServersWhenGetCalled() throws CmpServersConfigLoadingException { - // Given - Mockito.when(cmpServersConfigLoader.load(any())).thenReturn(SAMPLE_CMP_SERVERS); - this.cmpServersConfig.init(); // Manual PostConstruct call - - // When - List receivedCmpServers = this.cmpServersConfig.getCmpServers(); - - // Then - assertThat(receivedCmpServers).containsAll(SAMPLE_CMP_SERVERS); - } - - @Test - void shouldReturnLoadedServersAfterReloadWhenGetCalled() throws CmpServersConfigLoadingException { - // Given - Mockito.when(cmpServersConfigLoader.load(any())).thenReturn(SAMPLE_CMP_SERVERS); - List receivedCmpServers = this.cmpServersConfig.getCmpServers(); - assertThat(receivedCmpServers).isNull(); - - // When - this.cmpServersConfig.reloadConfiguration(); - receivedCmpServers = this.cmpServersConfig.getCmpServers(); - - // Then - assertThat(receivedCmpServers).containsAll(SAMPLE_CMP_SERVERS); - } - - @Test - void shouldRethrowExceptionWhenReloaded() throws CmpServersConfigLoadingException { - // Given - Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException( - ERROR_MESSAGE)); - - // Then - assertThrows( - CmpServersConfigLoadingException.class, - () -> cmpServersConfig.reloadConfiguration()); - } - - @Test - void shouldPassMessageToRethrownErrorWhenReloadingFails() throws CmpServersConfigLoadingException { - // Given - Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)); - - // When - Exception exception = assertThrows( - CmpServersConfigLoadingException.class, - () -> cmpServersConfig.reloadConfiguration()); - - // Then - assertThat(exception.getMessage()).isEqualTo(ERROR_MESSAGE); - } - - @Test - void shouldNotReturnIakAndRvWhenToStringMethodIsUsed() throws CmpServersConfigLoadingException { - // Given - Mockito.when(cmpServersConfigLoader.load(any())).thenReturn(SAMPLE_CMP_SERVERS); - this.cmpServersConfig.init(); // Manual PostConstruct call - - // When - List receivedCmpServers = this.cmpServersConfig.getCmpServers(); - - // Then - receivedCmpServers.forEach((server) -> assertThat(server.toString()) - .doesNotContain( - server.getAuthentication().getIak(), - server.getAuthentication().getRv() - )); - } - - @Test - void shouldRethrowErrorWhenLoadingFails() throws CmpServersConfigLoadingException { - // Given - Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)); - - // Then - assertThrows( - CmpServersConfigLoadingException.class, - () -> cmpServersConfig.loadConfiguration()); - } - - @Test - void shouldPassMessageToRethrownErrorWhenLoadingFails() throws CmpServersConfigLoadingException { - // Given - Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)); - - // When - Exception exception = assertThrows( - CmpServersConfigLoadingException.class, - () -> cmpServersConfig.loadConfiguration()); - - // Then - assertThat(exception.getMessage()).isEqualTo(ERROR_MESSAGE); - } - - @Test - void shouldBeNotReadyWhenCreated() { - assertThat(cmpServersConfig.isReady()).isFalse(); - } - - @Test - void shouldBeReadyWhenSuccessfullyInitialized() { - // When - this.cmpServersConfig.init(); // Manual PostConstruct call - - // Then - assertThat(cmpServersConfig.isReady()).isTrue(); - } - - @Test - void shouldNotBeReadyWhenFailedToInitialize() throws CmpServersConfigLoadingException { - // Given - Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)); - - // When - this.cmpServersConfig.init(); // Manual PostConstruct call - - // Then - assertThat(cmpServersConfig.isReady()).isFalse(); - } - - @Test - void shouldBeReadyWhenSuccessfullyReloaded() throws CmpServersConfigLoadingException { - // When - this.cmpServersConfig.reloadConfiguration(); - - // Then - assertThat(cmpServersConfig.isReady()).isTrue(); - } - - @Test - void shouldNotBeReadyWhenFailedToReload() throws CmpServersConfigLoadingException { - // Given - Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)); - - // When - assertThrows( - CmpServersConfigLoadingException.class, - () -> cmpServersConfig.loadConfiguration()); - - // Then - assertThat(cmpServersConfig.isReady()).isFalse(); - } - - private static List generateTestConfiguration() { - Cmpv2Server testServer1 = new Cmpv2Server(); - testServer1.setCaName("TEST_CA1"); - testServer1.setIssuerDN(new X500Name("CN=testIssuer")); - testServer1.setUrl("http://test.ca.server"); - Authentication testAuthentication1 = new Authentication(); - testAuthentication1.setIak("testIak"); - testAuthentication1.setRv("testRv"); - testServer1.setAuthentication(testAuthentication1); - testServer1.setCaMode(CaMode.RA); - - Cmpv2Server testServer2 = new Cmpv2Server(); - testServer2.setCaName("TEST_CA2"); - testServer2.setIssuerDN(new X500Name("CN=testIssuer2")); - testServer2.setUrl("http://test.ca.server"); - Authentication testAuthentication2 = new Authentication(); - testAuthentication2.setIak("test2Iak"); - testAuthentication2.setRv("test2Rv"); - testServer2.setAuthentication(testAuthentication2); - testServer2.setCaMode(CaMode.CLIENT); - - return List.of(testServer1, testServer2); - } - -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/Cmpv2ServerProviderTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/Cmpv2ServerProviderTest.java deleted file mode 100644 index b83fb9aa..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/Cmpv2ServerProviderTest.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.certification.configuration; - -import org.bouncycastle.asn1.x500.X500Name; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.onap.aaf.certservice.certification.configuration.model.Authentication; -import org.onap.aaf.certservice.certification.configuration.model.CaMode; -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.onap.aaf.certservice.certification.exception.Cmpv2ServerNotFoundException; - -import java.util.Collections; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class Cmpv2ServerProviderTest { - - private static final String TEST_CA = "testCA"; - - private Cmpv2ServerProvider cmpv2ServerProvider; - - @Mock - private CmpServersConfig cmpServersConfig; - - @BeforeEach - void setUp() { - cmpv2ServerProvider = - new Cmpv2ServerProvider(cmpServersConfig); - } - - @Test - void shouldReturnOptionalWithServerWhenServerWithGivenCaNameIsPresentInConfig() { - // Given - Cmpv2Server testServer = createTestServer(); - when(cmpServersConfig.getCmpServers()).thenReturn(Collections.singletonList(testServer)); - - // When - Cmpv2Server receivedServer = cmpv2ServerProvider - .getCmpv2Server(TEST_CA); - - // Then - assertThat(receivedServer).isEqualToComparingFieldByField(testServer); - } - - @Test - void shouldReturnEmptyOptionalWhenServerWithGivenCaNameIsNotPresentInConfig() { - // Given - String expectedMessage = "No server found for given CA name"; - when(cmpServersConfig.getCmpServers()).thenReturn(Collections.emptyList()); - - // When - Exception exception = assertThrows( - Cmpv2ServerNotFoundException.class, () -> - cmpv2ServerProvider.getCmpv2Server(TEST_CA) - ); - - // Then - assertTrue(exception.getMessage().contains(expectedMessage)); - } - - private Cmpv2Server createTestServer() { - Cmpv2Server testServer = new Cmpv2Server(); - testServer.setCaName(TEST_CA); - testServer.setIssuerDN(new X500Name("CN=testIssuer")); - testServer.setUrl("http://test.ca.server"); - Authentication testAuthentication = new Authentication(); - testAuthentication.setIak("testIak"); - testAuthentication.setRv("testRv"); - testServer.setAuthentication(testAuthentication); - testServer.setCaMode(CaMode.RA); - - return testServer; - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidatorTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidatorTest.java deleted file mode 100644 index 6db77753..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidatorTest.java +++ /dev/null @@ -1,213 +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.bouncycastle.asn1.x500.X500Name; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.onap.aaf.certservice.CertServiceApplication; -import org.onap.aaf.certservice.certification.configuration.model.Authentication; -import org.onap.aaf.certservice.certification.configuration.model.CaMode; -import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.security.InvalidParameterException; -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; - -@ExtendWith(SpringExtension.class) -@ContextConfiguration(classes = CertServiceApplication.class) -class Cmpv2ServersConfigurationValidatorTest { - - private static final String EMPTY_STRING = ""; - - @Autowired - private Cmpv2ServersConfigurationValidator validator; - - private Authentication authentication; - private Cmpv2Server server; - private List servers; - - @BeforeEach - private void init() { - setAuthentication(); - setServerConfiguration(); - servers = new ArrayList<>(); - servers.add(server); - } - - @Test - void shouldThrowExceptionWhenCaNamesAreNotUnique() { - // Given - servers.add(server); - - // When - Exception exception = assertThrows( - InvalidParameterException.class, - () -> validator.validate(servers)); - - // Then - assertThat(exception.getMessage()).contains("CA names are not unique within given CMPv2 servers"); - } - - @Test - void shouldThrowExceptionWhenWrongProtocolInUrl() { - // Given - server.setUrl("https://test.test.test:60000/"); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldThrowExceptionWhenWrongPortInUrl() { - // Given - server.setUrl("http://test.test.test:70000/"); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldThrowExceptionWhenWrongCaNameLength() { - // Given - server.setCaName(EMPTY_STRING); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldThrowExceptionWhenWrongRvLength() { - // Given - authentication.setRv(EMPTY_STRING); - - // Then - assertExceptionIsThrown(); - } - - - @Test - void shouldThrowExceptionWhenWrongIakLength() { - // Given - authentication.setIak(EMPTY_STRING); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldThrowExceptionWhenCaNameIsNull() { - // Given - server.setCaName(null); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldThrowExceptionWhenIssuerDnIsNull() { - // Given - server.setIssuerDN(null); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldThrowExceptionWhenCaModeIsNull() { - // Given - server.setCaMode(null); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldThrowExceptionWhenUrlIsNull() { - // Given - server.setUrl(null); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldThrowExceptionWhenAuthenticationIsNull() { - // Given - server.setAuthentication(null); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldThrowExceptionWhenIakIsNull() { - // Given - authentication.setIak(null); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldThrowExceptionWhenRvIsNull() { - // Given - authentication.setRv(null); - - // Then - assertExceptionIsThrown(); - } - - @Test - void shouldNotThrowExceptionWhenServerConfigurationIsValid() { - // Then - assertDoesNotThrow(() -> validator.validate(servers)); - } - - private void assertExceptionIsThrown() { - assertThrows(IllegalArgumentException.class, () -> validator.validate(servers)); - } - - private void setServerConfiguration() { - server = new Cmpv2Server(); - server.setCaMode(CaMode.CLIENT); - server.setCaName("TEST"); - server.setIssuerDN(new X500Name("CN=ManagementCA")); - server.setUrl("http://127.0.0.1/ejbca/publicweb/cmp/cmp"); - server.setAuthentication(authentication); - } - - private void setAuthentication() { - authentication = new Authentication(); - authentication.setRv("testRV"); - authentication.setIak("testIAK"); - } - -} \ No newline at end of file diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidatorTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidatorTest.java deleted file mode 100644 index 7082626f..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidatorTest.java +++ /dev/null @@ -1,57 +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.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - - -class Cmpv2UrlValidatorTest { - - private final Cmpv2UrlValidator validator = new Cmpv2UrlValidator(); - - @Test - void givenCorrectUrlWhenValidatingShouldReturnTrue() { - //given - String url = "http://127.0.0.1/ejbca/publicweb/cmp/cmp"; - - //when - boolean result = validator.isValid(url, null); - - //then - assertTrue(result); - } - - @Test - void givenIncorrectUrlWhenValidatingShouldReturnFalse() { - //given - String url = "httttp://127.0.0.1:80000/ejbca/publicweb/cmp/cmp"; - - //when - boolean result = validator.isValid(url, null); - - //then - assertFalse(result); - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/PortNumberViolationTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/PortNumberViolationTest.java deleted file mode 100644 index e729c738..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/PortNumberViolationTest.java +++ /dev/null @@ -1,76 +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 org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class PortNumberViolationTest { - - private final PortNumberViolation violation = new PortNumberViolation(); - - @Test - void givenValidPortShouldReturnTrue() { - //given - String validUrl1 = "http://127.0.0.1:8080/ejbca/publicweb/cmp/cmp"; - String validUrl2 = "http://127.0.0.1:1/ejbca/publicweb/cmp/cmp"; - String validUrl3 = "http://127.0.0.1:65535/ejbca/publicweb/cmp/cmp"; - - //when - boolean result1 = violation.validate(validUrl1); - boolean result2 = violation.validate(validUrl2); - boolean result3 = violation.validate(validUrl3); - - //then - assertTrue(result1); - assertTrue(result2); - assertTrue(result3); - } - - @Test - void givenEmptyPortShouldReturnTrue() { - //given - String validUrl = "http://127.0.0.1/ejbca/publicweb/cmp/cmp"; - - //when - boolean result = violation.validate(validUrl); - - //then - assertTrue(result); - } - - @Test - void givenInvalidPortShouldReturnFalse() { - //given - String invalidUrl1 = "http://127.0.0.1:0/ejbca/publicweb/cmp/cmp"; - String invalidUrl2 = "http://127.0.0.1:65536/ejbca/publicweb/cmp/cmp"; - - //when - boolean result1 = violation.validate(invalidUrl1); - boolean result2 = violation.validate(invalidUrl2); - - //then - assertFalse(result1); - assertFalse(result2); - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolationTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolationTest.java deleted file mode 100644 index dce66d52..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolationTest.java +++ /dev/null @@ -1,56 +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 org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - - -class RequestTypeViolationTest { - - private final RequestTypeViolation violation = new RequestTypeViolation(); - - @Test - void givenValidRequestTypeShouldReturnTrue() { - //given - String validUrl = "http://127.0.0.1/ejbca/publicweb/cmp/cmp"; - - //when - boolean result = violation.validate(validUrl); - - //then - assertTrue(result); - } - - @Test - void givenInvalidRequestTypeShouldReturnFalse() { - //given - String invalidUrl = "htestps://127.0.0.1/ejbca/publicweb/cmp/cmp"; - - //when - boolean result = violation.validate(invalidUrl); - - //then - assertFalse(result); - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/model/CsrModelTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/model/CsrModelTest.java deleted file mode 100644 index 08bc3368..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/model/CsrModelTest.java +++ /dev/null @@ -1,185 +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 org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.bouncycastle.util.io.pem.PemObject; -import org.junit.jupiter.api.Test; -import org.onap.aaf.certservice.certification.Pkcs10CertificationRequestFactory; -import org.onap.aaf.certservice.certification.PemObjectFactory; -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 java.io.IOException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.onap.aaf.certservice.certification.TestData.TEST_CSR; -import static org.onap.aaf.certservice.certification.TestData.TEST_PEM; -import static org.onap.aaf.certservice.certification.TestData.TEST_PK; - - -class CsrModelTest { - - private final Pkcs10CertificationRequestFactory certificationRequestFactory - = new Pkcs10CertificationRequestFactory(); - private final PemObjectFactory pemObjectFactory - = new PemObjectFactory(); - - @Test - void shouldByConstructedAndReturnProperFields() throws DecryptionException, IOException { - // Given - PemObject testPrivateKey = getPemPrivateKey(); - PemObject testPublicKey = generateTestPublicKey(); - PKCS10CertificationRequest testCsr = generateTestCertificationRequest(); - - // When - CsrModel csrModel = generateTestCsrModel(testCsr); - - // Then - assertThat(csrModel.getCsr()) - .isEqualTo(testCsr); - assertThat(csrModel.getPrivateKey().getEncoded()) - .contains(testPrivateKey.getContent()); - assertThat(csrModel.getPublicKey().getEncoded()) - .contains(testPublicKey.getContent()); - assertThat(csrModel.getSans()) - .contains( - "gerrit.onap.org", "test.onap.org", "onap.com"); - assertThat(csrModel.getSubjectData().toString()) - .contains( - "C=US,ST=California,L=San-Francisco,O=Linux-Foundation,OU=ONAP,CN=onap.org,E=tester@onap.org"); - } - - @Test - void shouldThrowExceptionWhenPublicKeyIsNotCorrect() throws DecryptionException, IOException { - // Given - PemObject testPrivateKey = getPemPrivateKey(); - PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class); - SubjectPublicKeyInfo wrongKryInfo = mock(SubjectPublicKeyInfo.class); - when(testCsr.getSubjectPublicKeyInfo()) - .thenReturn(wrongKryInfo); - when(wrongKryInfo.getEncoded()) - .thenThrow(new IOException()); - - // When - Exception exception = assertThrows( - CsrDecryptionException.class, - () -> new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build() - ); - - String expectedMessage = "Reading Public Key from CSR failed"; - String actualMessage = exception.getMessage(); - - // Then - assertTrue(actualMessage.contains(expectedMessage)); - } - - @Test - void shouldThrowExceptionWhenPrivateKeyPemIsNotProperPrivateKey() throws KeyDecryptionException, IOException { - // Given - PemObject testPrivateKey = getPemWrongKey(); - PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class); - SubjectPublicKeyInfo wrongKryInfo = mock(SubjectPublicKeyInfo.class); - when(testCsr.getSubjectPublicKeyInfo()) - .thenReturn(wrongKryInfo); - when(wrongKryInfo.getEncoded()) - .thenThrow(new IOException()); - - // When - Exception exception = assertThrows( - KeyDecryptionException.class, - () -> new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build() - ); - - String expectedMessage = "Converting Private Key failed"; - String actualMessage = exception.getMessage(); - - // Then - assertTrue(actualMessage.contains(expectedMessage)); - } - - @Test - void shouldThrowExceptionWhenPublicKeyPemIsNotProperPublicKey() throws KeyDecryptionException, IOException { - // Given - PemObject testPrivateKey = getPemPrivateKey(); - PemObject testPublicKey = getPemWrongKey(); - PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class); - SubjectPublicKeyInfo wrongKryInfo = mock(SubjectPublicKeyInfo.class); - when(testCsr.getSubjectPublicKeyInfo()) - .thenReturn(wrongKryInfo); - when(wrongKryInfo.getEncoded()) - .thenReturn(testPublicKey.getContent()); - - // When - Exception exception = assertThrows( - KeyDecryptionException.class, - () -> new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build() - ); - - String expectedMessage = "Converting Public Key from CSR failed"; - String actualMessage = exception.getMessage(); - - // Then - assertTrue(actualMessage.contains(expectedMessage)); - } - - private PemObject getPemPrivateKey() throws KeyDecryptionException { - PemObjectFactory pemObjectFactory = new PemObjectFactory(); - return pemObjectFactory.createPemObject(TEST_PK).orElseThrow( - () -> new KeyDecryptionException("Private key decoding fail") - ); - } - - private PemObject getPemWrongKey() throws KeyDecryptionException { - PemObjectFactory pemObjectFactory = new PemObjectFactory(); - return pemObjectFactory.createPemObject(TEST_PEM).orElseThrow( - () -> new KeyDecryptionException("Private key decoding fail") - ); - } - - private CsrModel generateTestCsrModel(PKCS10CertificationRequest testCsr) throws DecryptionException { - PemObject testPrivateKey = pemObjectFactory.createPemObject(TEST_PK).orElseThrow( - () -> new DecryptionException("Incorrect Private Key, decryption failed") - ); - return new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build(); - } - - private PemObject generateTestPublicKey() throws DecryptionException, IOException { - PKCS10CertificationRequest testCsr = generateTestCertificationRequest(); - return new PemObject("PUBLIC KEY", testCsr.getSubjectPublicKeyInfo().getEncoded()); - } - - private PKCS10CertificationRequest generateTestCertificationRequest() throws DecryptionException { - return pemObjectFactory.createPemObject(TEST_CSR) - .flatMap( - certificationRequestFactory::createPkcs10CertificationRequest - ).orElseThrow( - () -> new DecryptionException("Incorrect CSR, decryption failed") - ); - } - -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/cmpv2client/Cmpv2ClientTest.java b/certService/src/test/java/org/onap/aaf/certservice/cmpv2client/Cmpv2ClientTest.java deleted file mode 100644 index 05bda54b..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/cmpv2client/Cmpv2ClientTest.java +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2019 Ericsson Software Technology AB. 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 - */ - -package org.onap.aaf.certservice.cmpv2client; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import java.io.BufferedInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.Security; -import java.security.cert.X509Certificate; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.impl.client.CloseableHttpClient; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x500.X500NameBuilder; -import org.bouncycastle.asn1.x500.style.BCStyle; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.onap.aaf.certservice.certification.configuration.model.Authentication; -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.impl.CmpClientImpl; -import org.onap.aaf.certservice.cmpv2client.model.Cmpv2CertificationModel; - -class Cmpv2ClientTest { - - static { - Security.addProvider(new BouncyCastleProvider()); - } - - private CsrModel csrModel; - private Cmpv2Server server; - private Date notBefore; - private Date notAfter; - private X500Name dn; - - @Mock - X509Certificate cert; - - @Mock - CloseableHttpClient httpClient; - - @Mock - CloseableHttpResponse httpResponse; - - @Mock - HttpEntity httpEntity; - - private static KeyPair keyPair; - - @BeforeEach - void setUp() - throws NoSuchProviderException, NoSuchAlgorithmException, IOException, - InvalidKeySpecException { - keyPair = loadKeyPair(); - dn = new X500NameBuilder() - .addRDN(BCStyle.O, "TestOrganization") - .build(); - initMocks(this); - } - - public KeyPair loadKeyPair() - throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, - NoSuchProviderException { - - final InputStream privateInputStream = this.getClass().getResourceAsStream("/privateKey"); - final InputStream publicInputStream = this.getClass().getResourceAsStream("/publicKey"); - BufferedInputStream bis = new BufferedInputStream(privateInputStream); - byte[] privateBytes = IOUtils.toByteArray(bis); - bis = new BufferedInputStream(publicInputStream); - byte[] publicBytes = IOUtils.toByteArray(bis); - - KeyFactory keyFactory = KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME); - X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicBytes); - PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); - - PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateBytes); - PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec); - - return new KeyPair(publicKey, privateKey); - } - - @Test - void shouldReturnValidPkiMessageWhenCreateCertificateRequestMessageMethodCalledWithValidCsr() - throws Exception { - // given - Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00"); - Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00"); - setCsrModelAndServerValues( - "mypassword", - "senderKID", - "http://127.0.0.1/ejbca/publicweb/cmp/cmp", - beforeDate, - afterDate); - when(httpClient.execute(any())).thenReturn(httpResponse); - when(httpResponse.getEntity()).thenReturn(httpEntity); - - try (final InputStream is = - this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile"); - BufferedInputStream bis = new BufferedInputStream(is)) { - - byte[] ba = IOUtils.toByteArray(bis); - doAnswer( - invocation -> { - OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0]; - os.write(ba); - return null; - }) - .when(httpEntity) - .writeTo(any(OutputStream.class)); - } - CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient)); - // when - Cmpv2CertificationModel cmpClientResult = - cmpClient.createCertificate(csrModel, server, notBefore, notAfter); - // then - assertNotNull(cmpClientResult); - } - - @Test - void - shouldThrowCmpClientExceptionWhenCreateCertificateRequestMessageMethodCalledWithWrongProtectedBytesInResponse() - throws Exception { - // given - Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00"); - Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00"); - setCsrModelAndServerValues( - "password", - "senderKID", - "http://127.0.0.1/ejbca/publicweb/cmp/cmp", - beforeDate, - afterDate); - when(httpClient.execute(any())).thenReturn(httpResponse); - when(httpResponse.getEntity()).thenReturn(httpEntity); - - try (final InputStream is = - this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile"); - BufferedInputStream bis = new BufferedInputStream(is)) { - - byte[] ba = IOUtils.toByteArray(bis); - doAnswer( - invocation -> { - OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0]; - os.write(ba); - return null; - }) - .when(httpEntity) - .writeTo(any(OutputStream.class)); - } - CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient)); - // then - Assertions.assertThrows( - CmpClientException.class, - () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); - } - - @Test - void shouldThrowCmpClientExceptionWithPkiErrorExceptionWhenCmpClientCalledWithBadPassword() - throws Exception { - // given - Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00"); - Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00"); - setCsrModelAndServerValues( - "password", - "senderKID", - "http://127.0.0.1/ejbca/publicweb/cmp/cmp", - beforeDate, - afterDate); - when(httpClient.execute(any())).thenReturn(httpResponse); - when(httpResponse.getEntity()).thenReturn(httpEntity); - - try (final InputStream is = - this.getClass().getResourceAsStream("/ReturnedFailurePKIMessageBadPassword"); - BufferedInputStream bis = new BufferedInputStream(is)) { - - byte[] ba = IOUtils.toByteArray(bis); - doAnswer( - invocation -> { - OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0]; - os.write(ba); - return null; - }) - .when(httpEntity) - .writeTo(any(OutputStream.class)); - } - CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient)); - - // then - Assertions.assertThrows( - CmpClientException.class, - () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); - } - - @Test - void shouldThrowIllegalArgumentExceptionWhencreateCertificateCalledWithInvalidCsr() - throws ParseException { - // given - Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00"); - Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00"); - setCsrModelAndServerValues( - "password", - "senderKID", - "http://127.0.0.1/ejbca/publicweb/cmp/cmp", - beforeDate, - afterDate); - CmpClientImpl cmpClient = new CmpClientImpl(httpClient); - // then - Assertions.assertThrows( - IllegalArgumentException.class, - () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); - } - - @Test - void shouldThrowIoExceptionWhenCreateCertificateCalledWithNoServerAvailable() - throws IOException, ParseException { - // given - Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00"); - Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00"); - setCsrModelAndServerValues( - "myPassword", - "sender", - "http://127.0.0.1/ejbca/publicweb/cmp/cmpTest", - beforeDate, - afterDate); - when(httpClient.execute(any())).thenThrow(IOException.class); - CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient)); - // then - Assertions.assertThrows( - CmpClientException.class, - () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); - } - - private void setCsrModelAndServerValues(String iak, String rv, String externalCaUrl, Date notBefore, Date notAfter) { - csrModel = new CsrModel(null, dn, keyPair.getPrivate(), keyPair.getPublic(), Collections.emptyList()); - - Authentication authentication = new Authentication(); - authentication.setIak(iak); - authentication.setRv(rv); - server = new Cmpv2Server(); - server.setAuthentication(authentication); - server.setUrl(externalCaUrl); - server.setIssuerDN(dn); - this.notBefore = notBefore; - this.notAfter = notAfter; - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/cmpv2client/external/RdnTest.java b/certService/src/test/java/org/onap/aaf/certservice/cmpv2client/external/RdnTest.java deleted file mode 100644 index 6e42afe8..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/cmpv2client/external/RdnTest.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.cmpv2client.external; - -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.x500.style.BCStyle; -import org.bouncycastle.cert.CertException; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class RdnTest { - - @Test - void shouldCreateCorrectRdn() throws CertException { - // given - final String expectedValue = "ManagmentCA"; - final ASN1ObjectIdentifier expectedAoi = BCStyle.CN; - - //when - Rdn rdn1 = new Rdn("CN=ManagmentCA"); - Rdn rdn2 = new Rdn("CN = ManagmentCA "); - Rdn rdn3 = new Rdn("CN", "ManagmentCA"); - - //then - assertEquals(expectedValue, rdn1.getValue()); - assertEquals(expectedValue, rdn2.getValue()); - assertEquals(expectedValue, rdn3.getValue()); - assertEquals(expectedAoi, rdn1.getAoi()); - assertEquals(expectedAoi, rdn2.getAoi()); - assertEquals(expectedAoi, rdn3.getAoi()); - } - - @Test - void shouldCorrectlySplitAndTrimString() { - //given - String value1 = " T = Test"; - List expected1 = Arrays.asList("T", "Test"); - - String value2 = "This 123 is 99 tested 12345 string"; - List expected2 = Arrays.asList("This", "is 99 tested", "string"); - - //when - List actual1 = Rdn.parseRdn("=", value1); - List actual2 = Rdn.parseRdn("[0-9]{3,}", value2); - - //then - assertEquals(expected1, actual1); - assertEquals(expected2, actual2); - } - - @Test - void shouldConvertAoiStringToEnum() throws CertException { - Rdn rdn = new Rdn("CN", "ManagmentCA"); - - assertEquals(BCStyle.CN, rdn.getAoi("CN")); - assertEquals(BCStyle.C, rdn.getAoi("C")); - assertEquals(BCStyle.ST, rdn.getAoi("ST")); - assertEquals(BCStyle.L, rdn.getAoi("L")); - assertEquals(BCStyle.O, rdn.getAoi("O")); - assertEquals(BCStyle.OU, rdn.getAoi("OU")); - assertEquals(BCStyle.DC, rdn.getAoi("DC")); - assertEquals(BCStyle.GIVENNAME, rdn.getAoi("GN")); - assertEquals(BCStyle.SN, rdn.getAoi("SN")); - assertEquals(BCStyle.E, rdn.getAoi("E")); - assertEquals(BCStyle.E, rdn.getAoi("EMAIL")); - assertEquals(BCStyle.E, rdn.getAoi("EMAILADDRESS")); - assertEquals(BCStyle.INITIALS, rdn.getAoi("INITIALS")); - assertEquals(BCStyle.PSEUDONYM, rdn.getAoi("PSEUDONYM")); - assertEquals(BCStyle.GENERATION, rdn.getAoi("GENERATIONQUALIFIER")); - assertEquals(BCStyle.SERIALNUMBER, rdn.getAoi("SERIALNUMBER")); - assertThrows(CertException.class, () -> rdn.getAoi("INVALIDTAG")); - } -} diff --git a/certService/src/test/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseHelperTest.java b/certService/src/test/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseHelperTest.java deleted file mode 100644 index c41d6364..00000000 --- a/certService/src/test/java/org/onap/aaf/certservice/cmpv2client/impl/CmpResponseHelperTest.java +++ /dev/null @@ -1,609 +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.impl; - -import org.bouncycastle.asn1.cmp.CMPCertificate; -import org.bouncycastle.asn1.cmp.CertRepMessage; -import org.bouncycastle.asn1.cmp.PKIMessage; -import org.bouncycastle.util.io.pem.PemObject; -import org.bouncycastle.util.io.pem.PemReader; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException; -import org.onap.aaf.certservice.cmpv2client.model.Cmpv2CertificationModel; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.StringReader; -import java.security.NoSuchProviderException; -import java.security.Security; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; - -import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class CmpResponseHelperTest { - - - private static final String EXPECTED_ERROR_MESSAGE = "Something was wrong with the supplied certificate"; - - private static final String TEST_1LAYER_ENTITY_CERT = "" - + "-----BEGIN CERTIFICATE-----\n" - + "MIIEqDCCAxCgAwIBAgIUFioEkVJsxfZGGDMEyCA8Rin3uhQwDQYJKoZIhvcNAQEL\n" - + "BQAwYTEjMCEGCgmSJomT8ixkAQEME2MtMDM1ZDk4NTAwYzhiN2JiMjIxFTATBgNV\n" - + "BAMMDE1hbmFnZW1lbnRDQTEjMCEGA1UECgwaRUpCQ0EgQ29udGFpbmVyIFF1aWNr\n" - + "c3RhcnQwHhcNMjAwMzI0MTEzNTU0WhcNMjIwMzI0MTEzNTU0WjCBljEgMB4GCSqG\n" - + "SIb3DQEJARYRQ29tbW9uTmFtZUBjbi5jb20xDjAMBgNVBAMMBUNsMTIzMQ0wCwYD\n" - + "VQQLDARPTkFQMRkwFwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMRYwFAYDVQQHDA1T\n" - + "YW4tRnJhbmNpc2NvMRMwEQYDVQQIDApDYWxpZm9ybmlhMQswCQYDVQQGEwJVUzCC\n" - + "ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL94FcmRn/g9Y9ZrEL+jKiud\n" - + "xzDdtVLoF0ijZOGG0rnzyimzzwOjd8LA0jiZlYtpoDef95bbMeZJMKzE3bA8EMFp\n" - + "hynqUHs/KdsLBV+o3J6EzlpYHrwypX7kOriw9o4dmPAxvJHXTu3HC2SejJjHHArk\n" - + "FyahEJ03ypvCJx3iPvGXkLI9tZetobiVXslBJd5t0hQj+JQxzAlTwS0fV+xMowFT\n" - + "css2IlGXfQgd88cdhXBVOE0//qln1ko3G3KeH58iIWLqh9KG660SCeoTCop7bO1N\n" - + "abVrcXlgdE06hAvzTj3FoBxqO5KEWDPo2Dr11qRdq8bLP2T0EbTzAw4DPUwE+H8C\n" - + "AwEAAaOBoTCBnjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFDPaBc+EX/hCLe5c\n" - + "d+oZIxcQZ1tHMB8GA1UdEQQYMBaCBUNsMTIzgg10ZXN0Lm9uYXAub3JnMB0GA1Ud\n" - + "JQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAdBgNVHQ4EFgQU4dP1HuV9O+sHInl+\n" - + "WuvdDJ63lp8wDgYDVR0PAQH/BAQDAgXgMA0GCSqGSIb3DQEBCwUAA4IBgQBWTF8C\n" - + "sH0ir4bj7rTlJMf5o7apkXFeQ/c7+zXnSLCfXqwM6ad0EDh3FixfTC8IpW5CaENt\n" - + "zTR7IGJr06ccwLgsigR7FxJKnEkxJiBxzkE3zFOEel3KAnV2b7KvOP7cJAzsCdcS\n" - + "iZU475XHOw4Ox3k8fHzhTJJa0Tzw5EjQ3GO99HTiUClGrjJuYDLfen1q7IQSNuTY\n" - + "FzxJZjyqzi34pkKeCNSPRj8Z8Q5aZiWqlmzSJmZRT83xzzeW/pQ1JwvIrWwrbEjR\n" - + "FPXBlUa1n2HztkDgeBQfRyMAj5ixFV+s1Jj+cEYl3pjbugnuHfgBdSJokXFGBo6N\n" - + "8PTd1CnMGWcWiMyhbTwNm2UiSr5KhQbjABjiUzDp4C7jFhIzmu/4/tm2uA+y0xPN\n" - + "342uEZC0ZSZmpCIbQMhPaBNjSHeHj8NaLHjnt5jppLkMxScayRqMvSW07eNew2+k\n" - + "VYJD6z6gfy4y+Y5MSLfvddq1JdPDU86TFprtD1ydcUBS5tduYQG2+1bLgpE=" - + "\n-----END CERTIFICATE-----\n"; - - private static final String TEST_1LAYER_CA_CERT = "" - + "-----BEGIN CERTIFICATE-----\n" - + "MIIEszCCAxugAwIBAgIUEhkh+zJtXZN3K3kzQYcbp2smyIkwDQYJKoZIhvcNAQEL\n" - + "BQAwYTEjMCEGCgmSJomT8ixkAQEME2MtMDM1ZDk4NTAwYzhiN2JiMjIxFTATBgNV\n" - + "BAMMDE1hbmFnZW1lbnRDQTEjMCEGA1UECgwaRUpCQ0EgQ29udGFpbmVyIFF1aWNr\n" - + "c3RhcnQwHhcNMjAwMzI0MTAyODQyWhcNMzAwMzI0MTAyODQyWjBhMSMwIQYKCZIm\n" - + "iZPyLGQBAQwTYy0wMzVkOTg1MDBjOGI3YmIyMjEVMBMGA1UEAwwMTWFuYWdlbWVu\n" - + "dENBMSMwIQYDVQQKDBpFSkJDQSBDb250YWluZXIgUXVpY2tzdGFydDCCAaIwDQYJ\n" - + "KoZIhvcNAQEBBQADggGPADCCAYoCggGBAJyKZyKIRyW6cbga/I1YFJGCEEgs9JVU\n" - + "sV7MD5/yF4SIkJlZqFjJ9kfw8D5thg68zAx2vEWIpNTMroqb1eptIn/XsFoyM//6\n" - + "HzKrY3UUYWHx9sQMDZPenTL8LTRx+4szSen7rzrozH2pJat7kfX4EODEtQ6q7RQ2\n" - + "hmXoo7heeSgiHoeHsPGZixPGzcB27WBaY00Z/sP/n+f0CFaE04MKLw8WeQmq/RkC\n" - + "pj628+eBK0lGtEmUcT7z4CBy4x3hbhn9XHOb0+RlDk7rqFbsc09vHoZK2BfQ/r6e\n" - + "HguZjBQ5Ebqf6PiLF3HqkSW73toIdIy/olvQ2dLbOEyI4OnlObc+8xs/1AC7l9xX\n" - + "FkXY+NBv24KG1C2POXx14+ufHhWY0k2nIRUUlkUIJ7WGMWbuiNUXc1wSE1VrmY/c\n" - + "iXlhsJERqFc6bL/STlhOGuwmkdAD1/K8WS+o/QmIIX6cXlOR0U9bHMbD40F9fur6\n" - + "PV8wSKcQQNd0VHRLhmFwo4kkhZpDpuUp4QIDAQABo2MwYTAPBgNVHRMBAf8EBTAD\n" - + "AQH/MB8GA1UdIwQYMBaAFDPaBc+EX/hCLe5cd+oZIxcQZ1tHMB0GA1UdDgQWBBQz\n" - + "2gXPhF/4Qi3uXHfqGSMXEGdbRzAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL\n" - + "BQADggGBAFGsyu5nWycdk8iva+uY98QnPQe/M6uaUGUis0vGn9UYxoz5ddtpF3Z+\n" - + "MsHgbS51BH9iRYn4ZkQoRoukIjt1iO86d6sgpUS5AStCXsylL4DwAY5G/K5i/Qw5\n" - + "x0lP/tRYwqh2tUhmnx1xZLOWbRFZ63A0YHdguj3CqaXQ/cxafYZe0zcNhX3iH3gf\n" - + "5kHH8E682RT0x4ibb1JtPioQ48+pweyfMlOJkJ7WmZEfiVQitQSSNOnw1hRORiUz\n" - + "oFb0MlYHqe/9lIb9nmzD8QQ9q0H8J6RBCFsntx/Z6oUM8GHr80zAvNjqFfR14lOo\n" - + "jp05w2mr7wxIHFpM6h1HGY1QaeGp6W/fi+N7+gSL3nu1LzXVCYNCTcGkBDeasovB\n" - + "ma70KHGO4ZyRcEMKFCxxE8y4GZnw/EhMhDDevXAVsHEzr6XsBCJkC8e2l3iW5IKH\n" - + "4N/f/k06d4kS5pL290dJ450zx/mBxYGJm+pPHZfDszqVeKn1m1ZhGT80150OePGQ\n" - + "Cc2ir84HwQ==" - + "\n-----END CERTIFICATE-----\n"; - - private static final String TEST_2LAYER_ENTITY_CERT = "" - + "-----BEGIN CERTIFICATE-----\n" - + "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-----"; - - private static final String TEST_2LAYER_INTERMEDIATE_CERT = "" - + "-----BEGIN CERTIFICATE-----\n" - + "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-----"; - - private static final String TEST_2LAYER_CA_CERT = "" - + "-----BEGIN CERTIFICATE-----\n" - + "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-----"; - - - @BeforeAll - static void setUpSecurity() { - Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); - } - - - @Test - void returnListOfCertificationWhenGivenCaCertInCaPubsAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - PKIMessage respPkiMessage = mockExtraCerts(null); - - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); - CMPCertificate[] cmpCertificates = {caCmpCertificate}; - CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityCertificate(certs, TEST_1LAYER_ENTITY_CERT); - - assertThatRootCaAndTrustedCaAreInSecondList(certs, caCmpCertificate); - } - - @Test - void returnListOfCertificationWhenGivenCaCertInExtraCertsAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); - CMPCertificate[] extraCmpCertificates = {caCmpCertificate}; - PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); - - CertRepMessage certRepMessage = mockCaPubs(null); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityCertificate(certs, TEST_1LAYER_ENTITY_CERT); - - assertThatRootCaAndTrustedCaAreInSecondList(certs, caCmpCertificate); - } - - @Test - void returnListOfCertificationWhenGivenCaCertInExtraCertsAndExtraTrustAnchorInCaPubsAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); - CMPCertificate[] extraCmpCertificates = {caCmpCertificate}; - PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); - - CMPCertificate extraTrustAnchor = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); - CMPCertificate[] cmpCertificates = {extraTrustAnchor}; - CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityCertificate(certs, TEST_1LAYER_ENTITY_CERT); - - assertThatRootCaAndTrustedCaAreInSecondList( - certs, - caCmpCertificate, extraTrustAnchor - ); - } - - @Test - void returnListOfCertificationWhenGivenCaCertInExtraCertsAndExtraTrustAnchorInExtraCertsAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - CMPCertificate trustedCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); - CMPCertificate[] extraCmpCertificates = {caCmpCertificate, trustedCmpCertificate}; - PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); - - CertRepMessage certRepMessage = mockCaPubs(null); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityCertificate(certs, TEST_1LAYER_ENTITY_CERT); - - assertThatRootCaAndTrustedCaAreInSecondList( - certs, - caCmpCertificate, trustedCmpCertificate - ); - } - - @Test - void returnListOfCertificationWhenGivenCaCertAndIntermediateCertInExtraCertsAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); - CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); - CMPCertificate[] extraCmpCertificates = {caCmpCertificate, intermediateCmpCertificate}; - PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); - - CertRepMessage certRepMessage = mockCaPubs(null); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); - - assertThatRootCaAndTrustedCaAreInSecondList( - certs, - caCmpCertificate - ); - } - - @Test - void returnListOfCertificationWhenGivenCaCertAndIntermediateCertInCmpCertificatesAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - PKIMessage respPkiMessage = mockExtraCerts(null); - - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); - CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); - CMPCertificate[] cmpCertificates = {caCmpCertificate, intermediateCmpCertificate}; - CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); - - assertThatRootCaAndTrustedCaAreInSecondList( - certs, - caCmpCertificate - ); - } - - @Test - void returnListOfCertificationWhenGivenCaCertInCaPubsAndIntermediateCertInExtraCertsAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); - CMPCertificate[] extraCmpCertificates = {intermediateCmpCertificate}; - PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); - - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); - CMPCertificate[] cmpCertificates = {caCmpCertificate}; - CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); - - assertThatRootCaAndTrustedCaAreInSecondList( - certs, - caCmpCertificate - ); - } - - @Test - void returnListOfCertificationWhenGivenCaCertInCaPubsAndExtraCertsAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); - CMPCertificate[] extraCmpCertificates = {caCmpCertificate}; - PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); - CMPCertificate[] cmpCertificates = {mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT)}; - CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityCertificate(certs, TEST_1LAYER_ENTITY_CERT); - assertThatRootCaAndTrustedCaAreInSecondList(certs, mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT)); - - } - - @Test - void returnListOfCertificationWhenGivenCaCertAndIntermediateCertInExtraCertsAndIntermediateCertInCaPubsAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); - CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); - CMPCertificate[] extraCmpCertificates = {caCmpCertificate, intermediateCmpCertificate}; - PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); - CMPCertificate[] cmpCertificates = {intermediateCmpCertificate}; - CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); - assertThatRootCaAndTrustedCaAreInSecondList( - certs, - caCmpCertificate - ); - } - - @Test - void returnListOfCertificationWhenGivenCaCertAndExtraTrustAnchorInCaPubsAndIntermediateCertInExtraCertsAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); - CMPCertificate[] extraCmpCertificates = {intermediateCmpCertificate}; - PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); - - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); - CMPCertificate extraTrustAnchor = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); - CMPCertificate[] cmpCertificates = {caCmpCertificate, extraTrustAnchor}; - CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); - - assertThatRootCaAndTrustedCaAreInSecondList( - certs, - caCmpCertificate, extraTrustAnchor - ); - } - - @Test - void returnListOfCertificationWhenGivenCaCertAndFirstExtraTrustAnchorInCaPubsAndIntermediateCertAndSecondExtraTrustAnchorInExtraCertsAndEntityCertInLeafCertificate() - throws CertificateException, CmpClientException, IOException, NoSuchProviderException { - // given - CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); - CMPCertificate extraTrustAnchor01 = mockCmpCertificateFromPem(TEST_1LAYER_ENTITY_CERT); - CMPCertificate[] extraCmpCertificates = {intermediateCmpCertificate, extraTrustAnchor01}; - PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); - - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); - CMPCertificate extraTrustAnchor02 = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); - CMPCertificate[] cmpCertificates = {caCmpCertificate, extraTrustAnchor02}; - CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); - - // when - Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate); - - // then - assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); - - assertThatRootCaAndTrustedCaAreInSecondList( - certs, - caCmpCertificate, extraTrustAnchor01, extraTrustAnchor02 - ); - } - - @Test - void throwsExceptionWhenNoCaCertForEntityCertIsGivenAndOnlyExtraTrustAnchorIsReturned() - throws CertificateException, IOException, NoSuchProviderException { - // given - - PKIMessage respPkiMessage = mockExtraCerts(null); - - CMPCertificate trustedCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); - CMPCertificate[] cmpCertificates = {trustedCmpCertificate}; - CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); - - // when - Exception exception = assertThrows( - CmpClientException.class, - () -> CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate - ) - ); - - String actualMessage = exception.getMessage(); - - // then - assertThat(actualMessage).isEqualTo(EXPECTED_ERROR_MESSAGE); - } - - @Test - void throwsExceptionWhenBothExtraCertsAndCaPubsAreEmpty() - throws CertificateException, IOException, NoSuchProviderException { - // given - - PKIMessage respPkiMessage = mockExtraCerts(null); - CertRepMessage certRepMessage = mockCaPubs(null); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); - - // when - Exception exception = assertThrows( - CmpClientException.class, - () -> CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate - ) - ); - - String actualMessage = exception.getMessage(); - - // then - assertThat(actualMessage).isEqualTo(EXPECTED_ERROR_MESSAGE); - } - - @Test - void throwsExceptionWhenNoIntermediateCertForEntityCertIsGiven() - throws CertificateException, IOException, NoSuchProviderException { - // given - - PKIMessage respPkiMessage = mockExtraCerts(null); - - CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); - CMPCertificate[] cmpCertificates = {caCmpCertificate}; - CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); - - X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); - - // when - Exception exception = assertThrows( - CmpClientException.class, - () -> CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( - respPkiMessage, certRepMessage, leafCertificate - ) - ); - - String actualMessage = exception.getMessage(); - - // then - assertThat(actualMessage).isEqualTo(EXPECTED_ERROR_MESSAGE); - } - - - private void assertThatRootCaAndTrustedCaAreInSecondList( - Cmpv2CertificationModel certs, CMPCertificate... rootAndTrustedCerts - ) throws IOException { - assertThat(certs.getTrustedCertificates().size()).isEqualTo(rootAndTrustedCerts.length); - for (CMPCertificate certificate : rootAndTrustedCerts) { - assertThat(certs.getTrustedCertificates()) - .extracting(Certificate::getEncoded) - .contains(certificate.getEncoded()); - } - } - - private void assertThatChainContainsEntityCertificate( - Cmpv2CertificationModel certs, String entityCertificate - ) throws CertificateEncodingException, IOException { - assertThat(certs.getCertificateChain().size()).isEqualTo(1); - assertThat(certs.getCertificateChain().get(0).getEncoded()).isEqualTo(createPemObject(entityCertificate).getContent()); - } - - private void assertThatChainContainsEntityAndIntermediateCertificate( - Cmpv2CertificationModel certs, String entityCertificate, String intermediateCertificate - ) throws CertificateEncodingException, IOException { - assertThat(certs.getCertificateChain().size()).isEqualTo(2); - assertThat(certs.getCertificateChain().get(0).getEncoded()).isEqualTo(createPemObject(entityCertificate).getContent()); - assertThat(certs.getCertificateChain().get(1).getEncoded()).isEqualTo(createPemObject(intermediateCertificate).getContent()); - } - - private X509Certificate getX509CertificateFromPem(String pem) throws CertificateException, NoSuchProviderException, IOException { - return (X509Certificate) - CertificateFactory.getInstance("X.509", "BC").generateCertificate( - new ByteArrayInputStream(createPemObject(pem).getContent()) - ); - } - - private PKIMessage mockExtraCerts(CMPCertificate[] cmpCertificates) { - PKIMessage respPkiMessage = mock(PKIMessage.class); - when(respPkiMessage.getExtraCerts()).thenReturn(cmpCertificates); - return respPkiMessage; - } - - private CertRepMessage mockCaPubs(CMPCertificate[] cmpCertificates) { - CertRepMessage certRepMessage = mock(CertRepMessage.class); - when(certRepMessage.getCaPubs()).thenReturn(cmpCertificates); - return certRepMessage; - } - - private CMPCertificate mockCmpCertificateFromPem(String pem) throws IOException { - return mockCmpCertificate(createPemObject(pem).getContent()); - } - - private CMPCertificate mockCmpCertificate(byte[] encodedCertificate) throws IOException { - CMPCertificate cmpCertificate01 = mock(CMPCertificate.class); - when(cmpCertificate01.getEncoded()).thenReturn(encodedCertificate); - return cmpCertificate01; - } - - private PemObject createPemObject(String pem) throws IOException { - try (StringReader stringReader = new StringReader(pem); - PemReader pemReader = new PemReader(stringReader)) { - return pemReader.readPemObject(); - } - } -} diff --git a/certService/src/test/java/org/onap/oom/certservice/CertServiceApplicationTests.java b/certService/src/test/java/org/onap/oom/certservice/CertServiceApplicationTests.java new file mode 100644 index 00000000..abbcc3fa --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/CertServiceApplicationTests.java @@ -0,0 +1,34 @@ +/* + * ============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.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CertServiceApplicationTests { + + @Test + // We are excluding this line in Sonar due to fact that + // this test checks if Spring context is loaded and does not require assertion + void contextLoads() { // NOSONAR + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/api/CertificationControllerTest.java b/certService/src/test/java/org/onap/oom/certservice/api/CertificationControllerTest.java new file mode 100644 index 00000000..abd950e8 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/api/CertificationControllerTest.java @@ -0,0 +1,147 @@ +/* + * ============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 static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.when; + +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.oom.certservice.certification.CertificationModelFactory; +import org.onap.oom.certservice.certification.exception.Cmpv2ClientAdapterException; +import org.onap.oom.certservice.certification.exception.Cmpv2ServerNotFoundException; +import org.onap.oom.certservice.certification.exception.CsrDecryptionException; +import org.onap.oom.certservice.certification.exception.DecryptionException; +import org.onap.oom.certservice.certification.exception.KeyDecryptionException; +import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +@ExtendWith(MockitoExtension.class) +class CertificationControllerTest { + + private static final String TEST_CA_NAME = "TestCa"; + private static final String TEST_ENCODED_CSR = "encodedCSR"; + private static final String TEST_ENCODED_PK = "encodedPK"; + private static final String TEST_WRONG_ENCODED_CSR = "wrongEncodedCSR"; + private static final String TEST_WRONG_ENCODED_PK = "wrongEncodedPK"; + private static final String TEST_WRONG_CA_NAME = "wrongTestCa"; + + private CertificationController certificationController; + + @Mock + private CertificationModelFactory certificationModelFactory; + + @BeforeEach + void serUp() { + certificationController = new CertificationController(certificationModelFactory); + } + + @Test + void shouldReturnDataAboutCsrBaseOnEncodedParameters() + throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { + // Given + CertificationModel testCertificationModel = new CertificationModel( + Arrays.asList("ENTITY_CERT", "INTERMEDIATE_CERT"), + Arrays.asList("CA_CERT", "EXTRA_CA_CERT") + ); + when(certificationModelFactory.createCertificationModel(TEST_ENCODED_CSR, TEST_ENCODED_PK, TEST_CA_NAME)) + .thenReturn(testCertificationModel); + + // When + ResponseEntity responseCertificationModel = + certificationController.signCertificate(TEST_CA_NAME, TEST_ENCODED_CSR, TEST_ENCODED_PK); + + // Then + assertEquals(HttpStatus.OK, responseCertificationModel.getStatusCode()); + assertThat(responseCertificationModel.getBody() + ).isEqualToComparingFieldByField(testCertificationModel); + + } + + @Test + void shouldThrowCsrDecryptionExceptionWhenCreatingCsrModelFails() + throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { + // Given + String expectedMessage = "Incorrect CSR, decryption failed"; + when(certificationModelFactory.createCertificationModel(TEST_WRONG_ENCODED_CSR, TEST_ENCODED_PK, TEST_CA_NAME)) + .thenThrow(new CsrDecryptionException(expectedMessage)); + + // When + Exception exception = assertThrows( + CsrDecryptionException.class, () -> + certificationController.signCertificate(TEST_CA_NAME, TEST_WRONG_ENCODED_CSR, TEST_ENCODED_PK) + ); + + String actualMessage = exception.getMessage(); + + // Then + assertEquals(expectedMessage, actualMessage); + } + + @Test + void shouldThrowPemDecryptionExceptionWhenCreatingPemModelFails() + throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { + // Given + String expectedMessage = "Incorrect PEM, decryption failed"; + when(certificationModelFactory.createCertificationModel(TEST_ENCODED_CSR, TEST_WRONG_ENCODED_PK, TEST_CA_NAME)) + .thenThrow(new KeyDecryptionException(expectedMessage)); + + // When + Exception exception = assertThrows( + KeyDecryptionException.class, () -> + certificationController.signCertificate(TEST_CA_NAME, TEST_ENCODED_CSR, TEST_WRONG_ENCODED_PK) + ); + + String actualMessage = exception.getMessage(); + + // Then + assertEquals(expectedMessage, actualMessage); + } + + @Test + void shouldThrowCmpv2ServerNotFoundWhenGivenWrongCaName() + throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { + // Given + String expectedMessage = "No server found for given CA name"; + when(certificationModelFactory.createCertificationModel(TEST_ENCODED_CSR, TEST_ENCODED_PK, TEST_WRONG_CA_NAME)) + .thenThrow(new Cmpv2ServerNotFoundException(expectedMessage)); + + // When + Exception exception = assertThrows( + Cmpv2ServerNotFoundException.class, () -> + certificationController.signCertificate(TEST_WRONG_CA_NAME, TEST_ENCODED_CSR, TEST_ENCODED_PK) + ); + + String actualMessage = exception.getMessage(); + + // Then + assertEquals(expectedMessage, actualMessage); + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/api/ReadinessControllerTest.java b/certService/src/test/java/org/onap/oom/certservice/api/ReadinessControllerTest.java new file mode 100644 index 00000000..267a281b --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/api/ReadinessControllerTest.java @@ -0,0 +1,59 @@ +/* + * ============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 static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.oom.certservice.certification.configuration.CmpServersConfig; +import org.springframework.http.HttpStatus; + +@ExtendWith(MockitoExtension.class) +public class ReadinessControllerTest { + + @Mock + private CmpServersConfig cmpServersConfig; + + @Test + public void shouldReturnStatusOkWhenConfigIsReady() { + // Given + Mockito.when(cmpServersConfig.isReady()).thenReturn(true); + + // Then + assertThat(new ReadinessController(cmpServersConfig).checkReady().getStatusCode()).isEqualTo(HttpStatus.OK); + ; + } + + @Test + public void shouldReturnStatusServiceUnavailableWhenConfigIsNotReady() { + // Given + Mockito.when(cmpServersConfig.isReady()).thenReturn(false); + + // Then + assertThat(new ReadinessController(cmpServersConfig).checkReady().getStatusCode()).isEqualTo(HttpStatus.SERVICE_UNAVAILABLE); + ; + } + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/api/ReloadConfigControllerTest.java b/certService/src/test/java/org/onap/oom/certservice/api/ReloadConfigControllerTest.java new file mode 100644 index 00000000..8b367e1a --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/api/ReloadConfigControllerTest.java @@ -0,0 +1,77 @@ +/* + * ============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 static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.doThrow; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.oom.certservice.certification.configuration.CmpServersConfig; +import org.onap.oom.certservice.certification.configuration.CmpServersConfigLoadingException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +@ExtendWith(MockitoExtension.class) +public class ReloadConfigControllerTest { + + private static final String ERROR_MESSAGE = "Exception occurred during CMP Servers configuration loading"; + + private ReloadConfigController reloadConfigController; + + @Mock + public CmpServersConfig cmpServersConfig; + + @BeforeEach + void setUp() { + this.reloadConfigController = new ReloadConfigController(cmpServersConfig); + } + + @Test + void shouldReturnStatusOkWhenSuccessfullyReloaded() throws CmpServersConfigLoadingException { + // When + ResponseEntity response = reloadConfigController.reloadConfiguration(); + + // Then + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + + @Test + void shouldRethrowSameErrorWhenFailedToReload() throws CmpServersConfigLoadingException { + // Given + doThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)).when(cmpServersConfig).reloadConfiguration(); + + // When + Exception exception = assertThrows( + CmpServersConfigLoadingException.class, + () -> reloadConfigController.reloadConfiguration()); + + // Then + Assertions.assertThat(exception.getMessage()).isEqualTo(ERROR_MESSAGE); + } + + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/api/advice/CertificationExceptionAdviceTest.java b/certService/src/test/java/org/onap/oom/certservice/api/advice/CertificationExceptionAdviceTest.java new file mode 100644 index 00000000..081a01a0 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/api/advice/CertificationExceptionAdviceTest.java @@ -0,0 +1,134 @@ +/* + * ============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 com.google.gson.Gson; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CertificationExceptionAdviceTest { + + private CertificationExceptionAdvice certificationExceptionAdvice; + + @BeforeEach + void setUp() { + certificationExceptionAdvice = + new CertificationExceptionAdvice(); + } + + @Test + void shouldReturnResponseEntityWithAppropriateErrorMessageWhenGivenCsrDecryptionException() { + // Given + String expectedMessage = "Wrong certificate signing request (CSR) format"; + CsrDecryptionException csrDecryptionException = new CsrDecryptionException("test csr exception"); + + // When + ResponseEntity response = certificationExceptionAdvice.handle(csrDecryptionException); + + // Then + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + assertEquals(expectedMessage, response.getBody().getErrorMessage()); + } + + @Test + void shouldReturnResponseEntityWithAppropriateErrorMessageWhenGivenKeyDecryptionException() { + // Given + String expectedMessage = "Wrong key (PK) format"; + KeyDecryptionException csrDecryptionException = new KeyDecryptionException("test pk exception"); + + // When + ResponseEntity response = certificationExceptionAdvice.handle(csrDecryptionException); + + // Then + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + assertEquals(expectedMessage, response.getBody().getErrorMessage()); + } + + @Test + void shouldReturnResponseEntityWithAppropriateErrorMessageWhenGivenCaNameIsNotPresentInConfig() { + // Given + String expectedMessage = "Certification authority not found for given CAName"; + Cmpv2ServerNotFoundException csrDecryptionException = new Cmpv2ServerNotFoundException("test Ca exception"); + + // When + ResponseEntity response = certificationExceptionAdvice.handle(csrDecryptionException); + + // Then + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + assertEquals(expectedMessage, response.getBody().getErrorMessage()); + } + + @Test + void shouldReturnResponseEntityWithAppropriateErrorMessageWhenCallingCmpClientFail() { + // Given + String expectedMessage = "Exception occurred during call to cmp client"; + CmpClientException cmpClientException = new CmpClientException("Calling CMPv2 client failed"); + + // When + ResponseEntity response = certificationExceptionAdvice.handle(cmpClientException); + + // Then + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); + assertEquals(expectedMessage, response.getBody().getErrorMessage()); + } + + @Test + void shouldReturnResponseEntityWithAppropriateErrorMessageWhenModelTransformationInAdapterFail() { + // Given + String expectedMessage = "Exception occurred parsing cmp client response"; + Cmpv2ClientAdapterException cmpv2ClientAdapterException = new Cmpv2ClientAdapterException(new Throwable()); + + // When + ResponseEntity response = certificationExceptionAdvice.handle(cmpv2ClientAdapterException); + + // Then + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); + assertEquals(expectedMessage, response.getBody().getErrorMessage()); + } + + @Test + void shouldThrowCmpClientExceptionWhenNotHandledRunTimeExceptionOccur() { + // Given + String expectedMessage = "Runtime exception occurred calling cmp client business logic"; + RuntimeException runtimeException = new RuntimeException("Unknown runtime exception"); + + // When + Exception exception = assertThrows( + CmpClientException.class, () -> + certificationExceptionAdvice.handle(runtimeException) + ); + + // Then + assertEquals(expectedMessage, exception.getMessage()); + } + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/api/advice/ReloadConfigExceptionAdviceTest.java b/certService/src/test/java/org/onap/oom/certservice/api/advice/ReloadConfigExceptionAdviceTest.java new file mode 100644 index 00000000..0a339879 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/api/advice/ReloadConfigExceptionAdviceTest.java @@ -0,0 +1,56 @@ +/* + * ============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.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.oom.certservice.certification.configuration.CmpServersConfigLoadingException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ReloadConfigExceptionAdviceTest { + + private static final String ERROR_MESSAGE = "Exception occurred during CMP Servers configuration loading"; + + private ReloadConfigExceptionAdvice reloadConfigExceptionAdvice; + + @BeforeEach + void setUp() { + reloadConfigExceptionAdvice = + new ReloadConfigExceptionAdvice(); + } + + @Test + void shouldReturnErrorStatusAndMessageWhenExceptionOccurred() { + // Given + CmpServersConfigLoadingException exception = new CmpServersConfigLoadingException(ERROR_MESSAGE); + + // When + ResponseEntity response = reloadConfigExceptionAdvice.handle(exception); + + // Then + assertEquals(ERROR_MESSAGE, response.getBody()); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); + } + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/CertificationModelFactoryTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/CertificationModelFactoryTest.java new file mode 100644 index 00000000..8d28148b --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/CertificationModelFactoryTest.java @@ -0,0 +1,220 @@ +/* + * ============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.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.oom.certservice.certification.configuration.Cmpv2ServerProvider; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.exception.Cmpv2ClientAdapterException; +import org.onap.oom.certservice.certification.exception.Cmpv2ServerNotFoundException; +import org.onap.oom.certservice.certification.exception.CsrDecryptionException; +import org.onap.oom.certservice.certification.exception.DecryptionException; +import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.certification.model.CsrModel; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; + +import java.util.Arrays; +import java.util.Base64; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.onap.oom.certservice.certification.CertificationData.CA_CERT; +import static org.onap.oom.certservice.certification.CertificationData.ENTITY_CERT; +import static org.onap.oom.certservice.certification.CertificationData.INTERMEDIATE_CERT; +import static org.onap.oom.certservice.certification.CertificationData.EXTRA_CA_CERT; +import static org.onap.oom.certservice.certification.TestData.TEST_CSR; +import static org.onap.oom.certservice.certification.TestData.TEST_PK; +import static org.onap.oom.certservice.certification.TestData.TEST_WRONG_CSR; +import static org.onap.oom.certservice.certification.TestData.TEST_WRONG_PEM; + +@ExtendWith(MockitoExtension.class) +class CertificationModelFactoryTest { + + private static final String TEST_CA = "testCA"; + private static final String ENCODED_CSR = getEncodedString(TEST_CSR); + private static final String ENCODED_PK = getEncodedString(TEST_PK); + private static final String ENCODED_WRONG_CSR = getEncodedString(TEST_WRONG_CSR); + private static final String ENCODED_WRONG_PK = getEncodedString(TEST_WRONG_PEM); + + private CertificationModelFactory certificationModelFactory; + + @Mock + private Cmpv2ServerProvider cmpv2ServerProvider; + @Mock + private CsrModelFactory csrModelFactory; + @Mock + private CertificationProvider certificationProvider; + + + private static String getEncodedString(String testCsr) { + return Base64.getEncoder().encodeToString(testCsr.getBytes()); + } + + @BeforeEach + void setUp() { + certificationModelFactory = + new CertificationModelFactory(csrModelFactory, cmpv2ServerProvider, certificationProvider); + } + + @Test + void shouldCreateProperCertificationModelWhenGivenProperCsrModelAndCaName() + throws CmpClientException, DecryptionException, Cmpv2ClientAdapterException { + + // Given + CsrModel csrModel = mockCsrFactoryModelCreation(); + Cmpv2Server testServer = mockCmpv2ProviderServerSelection(); + mockCertificateProviderCertificateSigning(csrModel, testServer); + + // When + CertificationModel certificationModel = + certificationModelFactory.createCertificationModel(ENCODED_CSR, ENCODED_PK, TEST_CA); + + // Then + assertEquals(2, certificationModel.getCertificateChain().size()); + assertThat(certificationModel.getCertificateChain()).contains(INTERMEDIATE_CERT, ENTITY_CERT); + assertEquals(2, certificationModel.getTrustedCertificates().size()); + assertThat(certificationModel.getTrustedCertificates()).contains(CA_CERT, EXTRA_CA_CERT); + } + + @Test + void shouldThrowDecryptionExceptionWhenGivenWrongEncodedCsr() + throws DecryptionException { + // Given + String expectedMessage = "Incorrect CSR, decryption failed"; + when( + csrModelFactory.createCsrModel( + eq(new CsrModelFactory.StringBase64(ENCODED_WRONG_CSR)), + eq(new CsrModelFactory.StringBase64(ENCODED_WRONG_PK)) + ) + ).thenThrow( + new CsrDecryptionException(expectedMessage) + ); + + // When + Exception exception = assertThrows( + DecryptionException.class, () -> + certificationModelFactory.createCertificationModel(ENCODED_WRONG_CSR, ENCODED_WRONG_PK, TEST_CA) + ); + + // Then + assertTrue(exception.getMessage().contains(expectedMessage)); + } + + @Test + void shouldThrowCmpv2ServerNotFoundExceptionWhenGivenWrongCaName() + throws DecryptionException { + // Given + String expectedMessage = "CA not found"; + mockCsrFactoryModelCreation(); + when( + cmpv2ServerProvider.getCmpv2Server(TEST_CA) + ).thenThrow( + new Cmpv2ServerNotFoundException(expectedMessage) + ); + + // When + Exception exception = assertThrows( + Cmpv2ServerNotFoundException.class, () -> + certificationModelFactory.createCertificationModel(ENCODED_CSR, ENCODED_PK, TEST_CA) + ); + + // Then + assertTrue(exception.getMessage().contains(expectedMessage)); + } + + @Test + void shouldThrowCmpClientExceptionWhenSigningCsrFailed() + throws DecryptionException, CmpClientException, Cmpv2ClientAdapterException { + // Given + String expectedMessage = "failed to sign certificate"; + CsrModel csrModel = mockCsrFactoryModelCreation(); + Cmpv2Server testServer = mockCmpv2ProviderServerSelection(); + when( + certificationProvider.signCsr(eq(csrModel), eq(testServer)) + ).thenThrow( + new CmpClientException(expectedMessage) + ); + + // When + Exception exception = assertThrows( + CmpClientException.class, () -> + certificationModelFactory.createCertificationModel(ENCODED_CSR, ENCODED_PK, TEST_CA) + ); + + // Then + assertTrue(exception.getMessage().contains(expectedMessage)); + } + + + private void mockCertificateProviderCertificateSigning(CsrModel csrModel, Cmpv2Server testServer) + throws CmpClientException, Cmpv2ClientAdapterException { + CertificationModel expectedCertificationModel = getCertificationModel(); + when( + certificationProvider.signCsr(eq(csrModel), eq(testServer)) + ).thenReturn(expectedCertificationModel); + } + + private Cmpv2Server mockCmpv2ProviderServerSelection() { + Cmpv2Server testServer = getCmpv2Server(); + when( + cmpv2ServerProvider.getCmpv2Server(eq(TEST_CA)) + ).thenReturn(testServer); + return testServer; + } + + private CsrModel mockCsrFactoryModelCreation() + throws DecryptionException { + CsrModel csrModel = getCsrModel(); + when( + csrModelFactory.createCsrModel( + eq(new CsrModelFactory.StringBase64(ENCODED_CSR)), + eq(new CsrModelFactory.StringBase64(ENCODED_PK)) + ) + ).thenReturn(csrModel); + return csrModel; + } + + private Cmpv2Server getCmpv2Server() { + return new Cmpv2Server(); + } + + private CsrModel getCsrModel() { + return mock(CsrModel.class); + } + + private CertificationModel getCertificationModel() { + List testTrustedCertificates = Arrays.asList(CA_CERT, EXTRA_CA_CERT); + List testCertificationChain = Arrays.asList(INTERMEDIATE_CERT, ENTITY_CERT); + return new CertificationModel(testCertificationChain, testTrustedCertificates); + } + + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/CertificationProviderTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/CertificationProviderTest.java new file mode 100644 index 00000000..54744ba0 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/CertificationProviderTest.java @@ -0,0 +1,132 @@ +/* + * ============LICENSE_START======================================================= + * OOM Certification 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.apache.commons.io.IOUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.model.CertificationModel; +import org.onap.oom.certservice.certification.model.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 java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Objects; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class CertificationProviderTest { + + @Mock + private CsrModel csrModel; + @Mock + private Cmpv2Server server; + @Mock + private CsrModel testCsrModel; + @Mock + private Cmpv2Server testServer; + @Mock + private CmpClient cmpClient; + + private CertificationProvider certificationProvider; + + @BeforeEach + public void init() { + certificationProvider = new CertificationProvider(cmpClient); + } + + @Test + void shouldConvertToCertificationModel() + throws CertificateException, NoSuchProviderException, IOException, CmpClientException { + // When + when( + cmpClient.createCertificate(any(CsrModel.class), any(Cmpv2Server.class)) + ).thenReturn(createCorrectClientResponse()); + + CertificationModel certificationModel = certificationProvider.signCsr(csrModel, server); + + // Then + InputStream certificate = getClass().getClassLoader().getResourceAsStream("certificateModelChain.first"); + InputStream trustedCertificate = + getClass().getClassLoader().getResourceAsStream("trustedCertificatesModel.first"); + String certificateModel = removeLineEndings(certificationModel.getCertificateChain().get(0)); + String expectedCertificate = + removeLineEndings(IOUtils.toString(Objects.requireNonNull(certificate), StandardCharsets.UTF_8)); + String trustedCertificateModel = removeLineEndings(certificationModel.getTrustedCertificates().get(0)); + String expectedTrustedCertificate = + removeLineEndings(IOUtils.toString(Objects.requireNonNull(trustedCertificate), StandardCharsets.UTF_8)); + + assertThat(certificateModel).isEqualTo(expectedCertificate); + assertThat(trustedCertificateModel).isEqualTo(expectedTrustedCertificate); + } + + + @Test + void certificationProviderThrowCmpClientWhenCallingClientFails() + throws CmpClientException { + // Given + String expectedErrorMessage = "connecting to CMP client failed"; + + when( + cmpClient.createCertificate(any(CsrModel.class), any(Cmpv2Server.class)) + ).thenThrow(new CmpClientException(expectedErrorMessage)); + + // When + Exception exception = assertThrows( + CmpClientException.class, () -> + certificationProvider.signCsr(testCsrModel, testServer) + ); + + // Then + assertThat(exception.getMessage()).isEqualTo(expectedErrorMessage); + } + + private Cmpv2CertificationModel createCorrectClientResponse() + throws CertificateException, NoSuchProviderException { + InputStream certificateChain = getClass().getClassLoader().getResourceAsStream("certificateChain.first"); + InputStream trustedCertificate = getClass().getClassLoader().getResourceAsStream("trustedCertificates.first"); + X509Certificate x509Certificate = new CertificateFactoryProvider().generateCertificate(certificateChain); + X509Certificate x509TrustedCertificate = + new CertificateFactoryProvider().generateCertificate(trustedCertificate); + return new Cmpv2CertificationModel( + Collections.singletonList(x509Certificate), + Collections.singletonList(x509TrustedCertificate)); + } + + private String removeLineEndings(String string) { + return string.replace("\n", "").replace("\r", ""); + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/CsrModelFactoryTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/CsrModelFactoryTest.java new file mode 100644 index 00000000..75a6e81c --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/CsrModelFactoryTest.java @@ -0,0 +1,147 @@ +/* + * ============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.util.encoders.Base64; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.oom.certservice.certification.CsrModelFactory.StringBase64; +import org.onap.oom.certservice.certification.exception.CsrDecryptionException; +import org.onap.oom.certservice.certification.exception.DecryptionException; +import org.onap.oom.certservice.certification.exception.KeyDecryptionException; +import org.onap.oom.certservice.certification.model.CsrModel; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.onap.oom.certservice.certification.TestData.TEST_CSR; +import static org.onap.oom.certservice.certification.TestData.TEST_PK; +import static org.onap.oom.certservice.certification.TestData.TEST_WRONG_CSR; +import static org.onap.oom.certservice.certification.TestData.TEST_WRONG_PEM; + + +class CsrModelFactoryTest { + + private CsrModelFactory csrModelFactory; + + @BeforeEach + void setUp() { + csrModelFactory = new CsrModelFactory(); + } + + @Test + void shouldDecryptCsrAndReturnStringWithDataAboutIt() throws DecryptionException { + // given + String encoderCsr = new String(Base64.encode(TEST_CSR.getBytes())); + String encoderPK = new String(Base64.encode(TEST_PK.getBytes())); + + // when + CsrModel decryptedCsr = csrModelFactory + .createCsrModel(new StringBase64(encoderCsr), new StringBase64(encoderPK)); + + // then + assertTrue( + decryptedCsr.toString() + .contains( + "C=US,ST=California,L=San-Francisco,O=Linux-Foundation," + + "OU=ONAP,CN=onap.org,E=tester@onap.org") + && + decryptedCsr.toString() + .contains("SANs: [gerrit.onap.org, test.onap.org, onap.com]") + ); + } + + @Test + void shouldThrowCsrDecryptionExceptionWhenCsrIsIncorrect() { + // given + String encoderPK = new String(Base64.encode(TEST_PK.getBytes())); + String wrongCsr = new String(Base64.encode(TEST_WRONG_CSR.getBytes())); + + // when + Exception exception = assertThrows( + CsrDecryptionException.class, () -> csrModelFactory + .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK)) + ); + + String expectedMessage = "Incorrect CSR, decryption failed"; + String actualMessage = exception.getMessage(); + + // then + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + void shouldThrowKeyDecryptionExceptionWhenKeyIsIncorrect() { + // given + String encoderPK = new String(Base64.encode(TEST_WRONG_PEM.getBytes())); + String wrongCsr = new String(Base64.encode(TEST_CSR.getBytes())); + + // when + Exception exception = assertThrows( + KeyDecryptionException.class, () -> csrModelFactory + .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK)) + ); + + String expectedMessage = "Incorrect Key, decryption failed"; + String actualMessage = exception.getMessage(); + + // then + assertTrue(actualMessage.contains(expectedMessage)); + } + + + @Test + void shouldThrowCsrDecryptionExceptionWhenCsrIsNotInBase64Encoding() { + // given + String encoderPK = new String(Base64.encode(TEST_PK.getBytes())); + String wrongCsr = "Not Base 64 Csr"; + + // when + Exception exception = assertThrows( + CsrDecryptionException.class, () -> csrModelFactory + .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK)) + ); + + String expectedMessage = "Incorrect CSR, decryption failed"; + String actualMessage = exception.getMessage(); + + // then + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + void shouldThrowKeyDecryptionExceptionWhenPkIsNotInBase64Encoding() { + // given + String encoderPK = "Not Base64 Key"; + String wrongCsr = new String(Base64.encode(TEST_CSR.getBytes())); + + // when + Exception exception = assertThrows( + KeyDecryptionException.class, () -> csrModelFactory + .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK)) + ); + + String expectedMessage = "Incorrect Key, decryption failed"; + String actualMessage = exception.getMessage(); + + // then + assertTrue(actualMessage.contains(expectedMessage)); + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/PemObjectFactoryTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/PemObjectFactoryTest.java new file mode 100644 index 00000000..68cfa1a1 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/PemObjectFactoryTest.java @@ -0,0 +1,76 @@ +/* + * ============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.util.io.pem.PemObject; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.oom.certservice.certification.exception.DecryptionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.onap.oom.certservice.certification.TestData.TEST_PEM; +import static org.onap.oom.certservice.certification.TestData.TEST_WRONG_PEM; +import static org.onap.oom.certservice.certification.TestUtils.pemObjectToString; + + +class PemObjectFactoryTest { + + + private PemObjectFactory pemObjectFactory; + + @BeforeEach + void setUp() { + pemObjectFactory = new PemObjectFactory(); + } + + @Test + void shouldTransformStringInToPemObjectAndBackToString() throws DecryptionException { + // when + PemObject pemObject = pemObjectFactory.createPemObject(TEST_PEM).orElseThrow( + () -> new DecryptionException("Pem decryption failed") + ); + String parsedPemObject = pemObjectToString(pemObject); + + // then + assertEquals(TEST_PEM, parsedPemObject); + } + + @Test + void shouldThrowExceptionWhenParsingPemFailed() { + // given + String expectedMessage = "Unable to create PEM"; + + // when + Exception exception = assertThrows( + DecryptionException.class, () -> pemObjectFactory.createPemObject(TEST_WRONG_PEM).orElseThrow( + () -> new DecryptionException(expectedMessage) + ) + ); + + String actualMessage = exception.getMessage(); + + // then + assertTrue(actualMessage.contains(expectedMessage)); + } + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/RsaContentSignerBuilderTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/RsaContentSignerBuilderTest.java new file mode 100644 index 00000000..eebe1815 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/RsaContentSignerBuilderTest.java @@ -0,0 +1,63 @@ +/* + * ============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.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.oom.certservice.certification.RsaContentSignerBuilder; +import org.onap.oom.certservice.certification.exception.DecryptionException; +import org.onap.oom.certservice.certification.model.CsrModel; + +import java.io.IOException; +import java.security.PrivateKey; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.onap.oom.certservice.certification.TestUtils.createCsrModel; + +class RsaContentSignerBuilderTest { + + private RsaContentSignerBuilder rsaContentSignerBuilder; + + @BeforeEach + void setUp() { + rsaContentSignerBuilder = new RsaContentSignerBuilder(); + } + + @Test + void shouldBuildProperContentSignerWhenProvidedCertificationRequestAndPrivateKey() + throws IOException, OperatorCreationException, DecryptionException { + // Given + CsrModel testCsrModel = createCsrModel(); + PKCS10CertificationRequest testCertificationRequest = testCsrModel.getCsr(); + PrivateKey testPrivateKey = testCsrModel.getPrivateKey(); + + // When + ContentSigner createdContentSigner = rsaContentSignerBuilder.build(testCertificationRequest, testPrivateKey); + + // Then + assertThat(createdContentSigner.getAlgorithmIdentifier()) + .isEqualTo(testCertificationRequest.getSignatureAlgorithm()); + } + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/TestData.java b/certService/src/test/java/org/onap/oom/certservice/certification/TestData.java new file mode 100644 index 00000000..81c16128 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/TestData.java @@ -0,0 +1,95 @@ +/* + * ============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; + +public final class TestData { + + private TestData() { + } + + public static final String TEST_CSR = "" + + "-----BEGIN CERTIFICATE REQUEST-----\n" + + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh\n" + + "MRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQKDBBMaW51eC1Gb3VuZGF0\n" + + "aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQDDAhvbmFwLm9yZzEeMBwGCSqGSIb3\n" + + "DQEJARYPdGVzdGVyQG9uYXAub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" + + "CgKCAQEA13K1LrQ1L6eL7B8K4kucNct0sSjZe7Ww91V40s6mjcWajeFJk+pObZKz\n" + + "BfnImkVJwxdNMDD6tX16wykbGfQPyh4BBiAjLVk9XSeoPHFRBQ4LKTuyPtXhEXyr\n" + + "qwatYXGWZE554qq64pbReddOUJHgMc38SrOk/eMAKxB0uRrXpA0mPH7zwIZ4X8g2\n" + + "PoxJKI1BSYc8kOvvujsGSMw3e5nS8A+doFUwVi3jJMnaVCoZrvJbtREfXHZqBLQ5\n" + + "XQ8mNpIFfmGYF/tvW/O6LBdlZkuAQ9i4FBgf5+HdIVZOXrn09ksIZxW6vxIvAVi0\n" + + "5AOSgXictyphcNP2i/erBeCQCVB7MwIDAQABoEYwRAYJKoZIhvcNAQkOMTcwNTAz\n" + + "BgNVHREELDAqgg9nZXJyaXQub25hcC5vcmeCDXRlc3Qub25hcC5vcmeCCG9uYXAu\n" + + "Y29tMA0GCSqGSIb3DQEBCwUAA4IBAQBXH2nRwodQRJTuyrLe/VSg3PUdcPyAx2Ew\n" + + "63tWiGO+qWo8rK2a9Rr/t/zkQe2lx6NHqcMc2Rt6NeKGbrAvHGxTiYM35gktBdxG\n" + + "UaQS1ymrBWHAwbC+kv78r+5lCfafNm/EVdhUZbEw+crsw2wx4iKEW0byS4Ln0o5g\n" + + "aXVUW3i4G5FaYiYBUIDsujDdnH1IoxunEA6pDzDv1h6R9/TYu6Se8HToREIjOPBZ\n" + + "pDI5lDRu0YmI8r+TmAU3tTT1sY2WVxYDnhJut9ofegfMPQV4FIohxtPcCfoLSWti\n" + + "ml6jbcFqDvlzq3B3CXH9HU3jdJt33iSjCQGsSqy6bmCOdMS6XTPU\n" + + "-----END CERTIFICATE REQUEST-----\n"; + + public static final String TEST_WRONG_CSR = "" + + "-----BEGIN CERTIFICATE REQUEST-----\n" + + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh\n" + + "MRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQKDBBMaW51eC1Gb3VuZGF0\n" + + "aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQDDAhvbmFwLm9yZzEeMBwGCSqGSIb3\n" + + "-----END CERTIFICATE REQUEST-----\n"; + + public static final String TEST_PK = "-----BEGIN PRIVATE KEY-----\n" + + "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDXcrUutDUvp4vs\n" + + "HwriS5w1y3SxKNl7tbD3VXjSzqaNxZqN4UmT6k5tkrMF+ciaRUnDF00wMPq1fXrD\n" + + "KRsZ9A/KHgEGICMtWT1dJ6g8cVEFDgspO7I+1eERfKurBq1hcZZkTnniqrriltF5\n" + + "105QkeAxzfxKs6T94wArEHS5GtekDSY8fvPAhnhfyDY+jEkojUFJhzyQ6++6OwZI\n" + + "zDd7mdLwD52gVTBWLeMkydpUKhmu8lu1ER9cdmoEtDldDyY2kgV+YZgX+29b87os\n" + + "F2VmS4BD2LgUGB/n4d0hVk5eufT2SwhnFbq/Ei8BWLTkA5KBeJy3KmFw0/aL96sF\n" + + "4JAJUHszAgMBAAECggEAJ1StdsU3IGf5xzUzi3Q6JCfsOZs3eLoGgGB+Gh3XkfIM\n" + + "8PG7uOEBSEeLnv+me2NCv/a1BKMsYY1yp8YNSIOhjkhD75ZWVaUA6syejcox/DZA\n" + + "G1rmg0oQOF0GCcbCSBOwXMdmwNZiH5Ng0llX1qWKxAzSjeCVsjOKiFIMvO4Fh9D4\n" + + "9Io6/dRRNCxB6MEs1GT5IDfCV2PGDIalJ3znFqDnfdu9RDEDfNVHSUr6Jdu3Hrf5\n" + + "3qCcSEkMGuXYLotCNtTP1x0H0wW5gVpcbQEb29qdmHL1qkp3UiA3afsHnO/3k0gv\n" + + "gV5FxaldugyZAjqUGERdKaY6BMDJkDuu0qD0tPQK4QKBgQDuP5X5BcQ4iHNej+il\n" + + "xxT8QaEcZj0YEzcXzfm3ztZP7g+Jc1MbQXh6BuHLkXG5LeCwdnmk+LUD0MLoUSm3\n" + + "N2ZdtVuOHX7VEBrhrTwK/kMDpC7ganQzfvgOr9WQGmgGMRiUYAyK1J/x78yX967Z\n" + + "IAzdVZ/JSDdsyA983JckLL7CPQKBgQDngDkEJKYGfDt2mfItD8c8nhczGbDdoyYh\n" + + "s93ppTtgzFoNgFL4y/DOvisWMGgoeeYXSgH5uoPv6yY7IIkQzYySY6qQ3gmk1/X+\n" + + "bO+IsKVtlHBzqqojFteg3MfVojisMoAx6y5aBw1BXE2nAU8yWBTtuk+3KgGn9Oxk\n" + + "+Z4rdP06LwKBgA4b09zIW6NhaTubWBKhJHv/wvO0lj+bu7J8LyKUbBqVpXPlUXGW\n" + + "wfSv/aUZetuVfO3WRkPfupB8R16Ml+TSsgwwljhnRMCHUKA2qwyXnA5WJbSCeVkn\n" + + "Vrc/8Gy1M53SQHtg6L079DDWm44QS9ltzXU6Adlgnm+htVEWmxi4UZ+dAoGAfr6z\n" + + "+LG7+GcCA2AruEIgOe7wErkpHV+am+8nOymMxeV8FFJCmxbFQ9vYKTDdhfOfZvbM\n" + + "+BYG8E8VQmAAyyNOqENK+j+mlgrrEp4/0t2r5L/VhW5V8hoqelcGTc+gKZ8IkswJ\n" + + "N58Owc8wcJQF8TFKXBGaXVTxTSyKVIpZ778AeV8CgYAAvuicDkdwWv5EhDFf3aTI\n" + + "wfRFYflA6oiygnI63HzVyY4a+SyZs+nQpB5HBDo+Lyz8RaVRC5E7jQ8kiXJpxAu7\n" + + "1wnspz+pa3q61yR32N+zGuub71FXdLWSOlys6rzJqvqYihKxY22C2TyDyBCR2tMj\n" + + "mdnshXNAJfKkfghkJhFHrg==\n" + + "-----END PRIVATE KEY-----"; + + public static final String TEST_PEM = "" + + "-----BEGIN CERTIFICATE REQUEST-----\n" + + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh\n" + + "-----END CERTIFICATE REQUEST-----\n"; + + public static final String TEST_WRONG_PEM = "" + + "-----BEGIN WRONG REQUEST-----" + + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh" + + "-----END WRONG REQUEST-----"; + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/TestUtils.java b/certService/src/test/java/org/onap/oom/certservice/certification/TestUtils.java new file mode 100644 index 00000000..7c69bd52 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/TestUtils.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.certification; + +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemWriter; +import org.onap.oom.certservice.certification.exception.DecryptionException; +import org.onap.oom.certservice.certification.exception.KeyDecryptionException; +import org.onap.oom.certservice.certification.model.CsrModel; + +import java.io.IOException; +import java.io.StringWriter; + +import static org.onap.oom.certservice.certification.TestData.TEST_CSR; +import static org.onap.oom.certservice.certification.TestData.TEST_PK; + + +public final class TestUtils { + + private TestUtils() { + } + + public static String pemObjectToString(PemObject pemObject) throws KeyDecryptionException { + try (StringWriter output = new StringWriter()) { + PemWriter pemWriter = new PemWriter(output); + pemWriter.writeObject(pemObject); + pemWriter.close(); + return output.getBuffer().toString(); + + } catch (IOException e) { + throw new KeyDecryptionException("Writing PAM Object to string failed", e); + } + } + + public static CsrModel createCsrModel() throws DecryptionException { + CsrModelFactory csrModelFactory = new CsrModelFactory(); + String encoderCsr = new String(Base64.encode(TEST_CSR.getBytes())); + String encoderPK = new String(Base64.encode(TEST_PK.getBytes())); + return csrModelFactory + .createCsrModel(new CsrModelFactory.StringBase64(encoderCsr), new CsrModelFactory.StringBase64(encoderPK)); + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/X509CertificateBuilderTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/X509CertificateBuilderTest.java new file mode 100644 index 00000000..e980aa2c --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/X509CertificateBuilderTest.java @@ -0,0 +1,69 @@ +/* + * ============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.cert.X509CertificateHolder; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.oom.certservice.certification.exception.DecryptionException; +import org.onap.oom.certservice.certification.model.CsrModel; + +import java.io.IOException; +import java.security.PrivateKey; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.onap.oom.certservice.certification.TestUtils.createCsrModel; + +public class X509CertificateBuilderTest { + + private X509CertificateBuilder certificateBuilder; + + + @BeforeEach + void setUp() { + certificateBuilder = new X509CertificateBuilder(); + } + + @Test + void shouldBuildCertificateBuilderWhenGivenProperCertificationRequest() + throws DecryptionException, IOException, OperatorCreationException { + // Given + CsrModel testCsrModel = createCsrModel(); + PKCS10CertificationRequest testCertificationRequest = testCsrModel.getCsr(); + PrivateKey testPrivateKey = testCsrModel.getPrivateKey(); + RsaContentSignerBuilder rsaContentSignerBuilder = new RsaContentSignerBuilder(); + ContentSigner createdContentSigner = rsaContentSignerBuilder.build(testCertificationRequest, testPrivateKey); + + // When + X509v3CertificateBuilder certificateBuilder = this.certificateBuilder.build(testCertificationRequest); + X509CertificateHolder certificateHolder = certificateBuilder.build(createdContentSigner); + + // Then + assertThat(certificateHolder.getIssuer()) + .isEqualToComparingFieldByField(testCsrModel.getSubjectData()); + assertThat(certificateHolder.getSubjectPublicKeyInfo()) + .isEqualToComparingFieldByField(testCertificationRequest.getSubjectPublicKeyInfo()); + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoaderTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoaderTest.java new file mode 100644 index 00000000..b755b977 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigLoaderTest.java @@ -0,0 +1,117 @@ +/* + * ============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 static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.oom.certservice.CertServiceApplication; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = CertServiceApplication.class) +class CmpServersConfigLoaderTest { + private static final String EXISTING_CONFIG_FILENAME = "cmpServers.json"; + private static final String INVALID_CONFIG_FILENAME = "invalidCmpServers.json"; + private static final String NONEXISTENT_CONFIG_FILENAME = "nonExistingCmpServers.json"; + + private static final Map EXPECTED_FIRST_CMP_SERVER = Map.of( + "CA_NAME", "TEST", + "URL", "http://127.0.0.1/ejbca/publicweb/cmp/cmp", + "ISSUER_DN", "CN=ManagementCA", + "CA_MODE", "CLIENT", + "IAK", "xxx", + "RV", "yyy" + ); + private static final Map EXPECTED_SECOND_CMP_SERVER = Map.of( + "CA_NAME", "TEST2", + "URL", "http://127.0.0.1/ejbca/publicweb/cmp/cmpRA", + "ISSUER_DN", "CN=ManagementCA2", + "CA_MODE", "RA", + "IAK", "xxx", + "RV", "yyy" + ); + + @Autowired + private CmpServersConfigLoader configLoader; + + @Test + void shouldLoadCmpServersConfigWhenFileAvailable() throws CmpServersConfigLoadingException { + // Given + String path = getResourcePath(EXISTING_CONFIG_FILENAME); + + // When + List cmpServers = configLoader.load(path); + + // Then + assertThat(cmpServers).isNotNull(); + assertThat(cmpServers).hasSize(2); + verifyThatCmpServerEquals(cmpServers.get(0), EXPECTED_FIRST_CMP_SERVER); + verifyThatCmpServerEquals(cmpServers.get(1), EXPECTED_SECOND_CMP_SERVER); + } + + @Test + void shouldThrowExceptionWhenFileMissing() { + // When + Exception exception = assertThrows( + CmpServersConfigLoadingException.class, + () -> configLoader.load(NONEXISTENT_CONFIG_FILENAME)); + + // Then + assertThat(exception.getMessage()).contains("Exception occurred during CMP Servers configuration loading"); + } + + @Test + void shouldThrowExceptionWhenConfigurationIsInvalid() { + // Given + String path = getResourcePath(INVALID_CONFIG_FILENAME); + + // When + Exception exception = assertThrows( + CmpServersConfigLoadingException.class, + () -> configLoader.load(path)); + + // Then + assertThat(exception.getMessage()).contains("Validation of CMPv2 servers configuration failed"); + assertThat(exception.getCause().getMessage()).contains("authentication"); + } + + private String getResourcePath(String configFilename) { + return getClass().getClassLoader().getResource(configFilename).getFile(); + } + + private void verifyThatCmpServerEquals(Cmpv2Server cmpv2Server, Map expected) { + assertThat(cmpv2Server.getCaName()).isEqualTo(expected.get("CA_NAME")); + assertThat(cmpv2Server.getUrl()).isEqualTo(expected.get("URL")); + assertThat(cmpv2Server.getIssuerDN().toString()).isEqualTo(expected.get("ISSUER_DN")); + assertThat(cmpv2Server.getCaMode().name()).isEqualTo(expected.get("CA_MODE")); + assertThat(cmpv2Server.getAuthentication().getIak()).isEqualTo(expected.get("IAK")); + assertThat(cmpv2Server.getAuthentication().getRv()).isEqualTo(expected.get("RV")); + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigTest.java new file mode 100644 index 00000000..e938fdde --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/CmpServersConfigTest.java @@ -0,0 +1,236 @@ +/* + * ============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 static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.startsWith; + +import java.util.List; + +import org.bouncycastle.asn1.x500.X500Name; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.oom.certservice.certification.configuration.model.Authentication; +import org.onap.oom.certservice.certification.configuration.model.CaMode; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; + +@ExtendWith(MockitoExtension.class) +class CmpServersConfigTest { + + private static final String ERROR_MESSAGE = "Exception occurred during CMP Servers configuration loading"; + private static final String APP_CONFIG_PATH = "/fake/path/to/config"; + private static final List SAMPLE_CMP_SERVERS = generateTestConfiguration(); + + @Mock + private CmpServersConfigLoader cmpServersConfigLoader; + + private CmpServersConfig cmpServersConfig; + + @BeforeEach + void setUp() { + cmpServersConfig = new CmpServersConfig(APP_CONFIG_PATH, cmpServersConfigLoader); + } + + @Test + void shouldCallLoaderWithPathFromPropertiesWhenCreated() throws CmpServersConfigLoadingException { + // When + this.cmpServersConfig.init(); // Manual PostConstruct call + + // Then + Mockito.verify(cmpServersConfigLoader).load(startsWith(APP_CONFIG_PATH)); + } + + @Test + void shouldReturnLoadedServersWhenGetCalled() throws CmpServersConfigLoadingException { + // Given + Mockito.when(cmpServersConfigLoader.load(any())).thenReturn(SAMPLE_CMP_SERVERS); + this.cmpServersConfig.init(); // Manual PostConstruct call + + // When + List receivedCmpServers = this.cmpServersConfig.getCmpServers(); + + // Then + assertThat(receivedCmpServers).containsAll(SAMPLE_CMP_SERVERS); + } + + @Test + void shouldReturnLoadedServersAfterReloadWhenGetCalled() throws CmpServersConfigLoadingException { + // Given + Mockito.when(cmpServersConfigLoader.load(any())).thenReturn(SAMPLE_CMP_SERVERS); + List receivedCmpServers = this.cmpServersConfig.getCmpServers(); + assertThat(receivedCmpServers).isNull(); + + // When + this.cmpServersConfig.reloadConfiguration(); + receivedCmpServers = this.cmpServersConfig.getCmpServers(); + + // Then + assertThat(receivedCmpServers).containsAll(SAMPLE_CMP_SERVERS); + } + + @Test + void shouldRethrowExceptionWhenReloaded() throws CmpServersConfigLoadingException { + // Given + Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException( + ERROR_MESSAGE)); + + // Then + assertThrows( + CmpServersConfigLoadingException.class, + () -> cmpServersConfig.reloadConfiguration()); + } + + @Test + void shouldPassMessageToRethrownErrorWhenReloadingFails() throws CmpServersConfigLoadingException { + // Given + Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)); + + // When + Exception exception = assertThrows( + CmpServersConfigLoadingException.class, + () -> cmpServersConfig.reloadConfiguration()); + + // Then + assertThat(exception.getMessage()).isEqualTo(ERROR_MESSAGE); + } + + @Test + void shouldNotReturnIakAndRvWhenToStringMethodIsUsed() throws CmpServersConfigLoadingException { + // Given + Mockito.when(cmpServersConfigLoader.load(any())).thenReturn(SAMPLE_CMP_SERVERS); + this.cmpServersConfig.init(); // Manual PostConstruct call + + // When + List receivedCmpServers = this.cmpServersConfig.getCmpServers(); + + // Then + receivedCmpServers.forEach((server) -> assertThat(server.toString()) + .doesNotContain( + server.getAuthentication().getIak(), + server.getAuthentication().getRv() + )); + } + + @Test + void shouldRethrowErrorWhenLoadingFails() throws CmpServersConfigLoadingException { + // Given + Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)); + + // Then + assertThrows( + CmpServersConfigLoadingException.class, + () -> cmpServersConfig.loadConfiguration()); + } + + @Test + void shouldPassMessageToRethrownErrorWhenLoadingFails() throws CmpServersConfigLoadingException { + // Given + Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)); + + // When + Exception exception = assertThrows( + CmpServersConfigLoadingException.class, + () -> cmpServersConfig.loadConfiguration()); + + // Then + assertThat(exception.getMessage()).isEqualTo(ERROR_MESSAGE); + } + + @Test + void shouldBeNotReadyWhenCreated() { + assertThat(cmpServersConfig.isReady()).isFalse(); + } + + @Test + void shouldBeReadyWhenSuccessfullyInitialized() { + // When + this.cmpServersConfig.init(); // Manual PostConstruct call + + // Then + assertThat(cmpServersConfig.isReady()).isTrue(); + } + + @Test + void shouldNotBeReadyWhenFailedToInitialize() throws CmpServersConfigLoadingException { + // Given + Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)); + + // When + this.cmpServersConfig.init(); // Manual PostConstruct call + + // Then + assertThat(cmpServersConfig.isReady()).isFalse(); + } + + @Test + void shouldBeReadyWhenSuccessfullyReloaded() throws CmpServersConfigLoadingException { + // When + this.cmpServersConfig.reloadConfiguration(); + + // Then + assertThat(cmpServersConfig.isReady()).isTrue(); + } + + @Test + void shouldNotBeReadyWhenFailedToReload() throws CmpServersConfigLoadingException { + // Given + Mockito.when(cmpServersConfigLoader.load(any())).thenThrow(new CmpServersConfigLoadingException(ERROR_MESSAGE)); + + // When + assertThrows( + CmpServersConfigLoadingException.class, + () -> cmpServersConfig.loadConfiguration()); + + // Then + assertThat(cmpServersConfig.isReady()).isFalse(); + } + + private static List generateTestConfiguration() { + Cmpv2Server testServer1 = new Cmpv2Server(); + testServer1.setCaName("TEST_CA1"); + testServer1.setIssuerDN(new X500Name("CN=testIssuer")); + testServer1.setUrl("http://test.ca.server"); + Authentication testAuthentication1 = new Authentication(); + testAuthentication1.setIak("testIak"); + testAuthentication1.setRv("testRv"); + testServer1.setAuthentication(testAuthentication1); + testServer1.setCaMode(CaMode.RA); + + Cmpv2Server testServer2 = new Cmpv2Server(); + testServer2.setCaName("TEST_CA2"); + testServer2.setIssuerDN(new X500Name("CN=testIssuer2")); + testServer2.setUrl("http://test.ca.server"); + Authentication testAuthentication2 = new Authentication(); + testAuthentication2.setIak("test2Iak"); + testAuthentication2.setRv("test2Rv"); + testServer2.setAuthentication(testAuthentication2); + testServer2.setCaMode(CaMode.CLIENT); + + return List.of(testServer1, testServer2); + } + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/configuration/Cmpv2ServerProviderTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/Cmpv2ServerProviderTest.java new file mode 100644 index 00000000..dc6de3ba --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/Cmpv2ServerProviderTest.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.certification.configuration; + +import org.bouncycastle.asn1.x500.X500Name; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.oom.certservice.certification.configuration.model.Authentication; +import org.onap.oom.certservice.certification.configuration.model.CaMode; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.exception.Cmpv2ServerNotFoundException; + +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class Cmpv2ServerProviderTest { + + private static final String TEST_CA = "testCA"; + + private Cmpv2ServerProvider cmpv2ServerProvider; + + @Mock + private CmpServersConfig cmpServersConfig; + + @BeforeEach + void setUp() { + cmpv2ServerProvider = + new Cmpv2ServerProvider(cmpServersConfig); + } + + @Test + void shouldReturnOptionalWithServerWhenServerWithGivenCaNameIsPresentInConfig() { + // Given + Cmpv2Server testServer = createTestServer(); + when(cmpServersConfig.getCmpServers()).thenReturn(Collections.singletonList(testServer)); + + // When + Cmpv2Server receivedServer = cmpv2ServerProvider + .getCmpv2Server(TEST_CA); + + // Then + assertThat(receivedServer).isEqualToComparingFieldByField(testServer); + } + + @Test + void shouldReturnEmptyOptionalWhenServerWithGivenCaNameIsNotPresentInConfig() { + // Given + String expectedMessage = "No server found for given CA name"; + when(cmpServersConfig.getCmpServers()).thenReturn(Collections.emptyList()); + + // When + Exception exception = assertThrows( + Cmpv2ServerNotFoundException.class, () -> + cmpv2ServerProvider.getCmpv2Server(TEST_CA) + ); + + // Then + assertTrue(exception.getMessage().contains(expectedMessage)); + } + + private Cmpv2Server createTestServer() { + Cmpv2Server testServer = new Cmpv2Server(); + testServer.setCaName(TEST_CA); + testServer.setIssuerDN(new X500Name("CN=testIssuer")); + testServer.setUrl("http://test.ca.server"); + Authentication testAuthentication = new Authentication(); + testAuthentication.setIak("testIak"); + testAuthentication.setRv("testRv"); + testServer.setAuthentication(testAuthentication); + testServer.setCaMode(CaMode.RA); + + return testServer; + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidatorTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidatorTest.java new file mode 100644 index 00000000..b07c9035 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/Cmpv2ServersConfigurationValidatorTest.java @@ -0,0 +1,213 @@ +/* + * ============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.bouncycastle.asn1.x500.X500Name; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.oom.certservice.CertServiceApplication; +import org.onap.oom.certservice.certification.configuration.model.Authentication; +import org.onap.oom.certservice.certification.configuration.model.CaMode; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = CertServiceApplication.class) +class Cmpv2ServersConfigurationValidatorTest { + + private static final String EMPTY_STRING = ""; + + @Autowired + private Cmpv2ServersConfigurationValidator validator; + + private Authentication authentication; + private Cmpv2Server server; + private List servers; + + @BeforeEach + private void init() { + setAuthentication(); + setServerConfiguration(); + servers = new ArrayList<>(); + servers.add(server); + } + + @Test + void shouldThrowExceptionWhenCaNamesAreNotUnique() { + // Given + servers.add(server); + + // When + Exception exception = assertThrows( + InvalidParameterException.class, + () -> validator.validate(servers)); + + // Then + assertThat(exception.getMessage()).contains("CA names are not unique within given CMPv2 servers"); + } + + @Test + void shouldThrowExceptionWhenWrongProtocolInUrl() { + // Given + server.setUrl("https://test.test.test:60000/"); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldThrowExceptionWhenWrongPortInUrl() { + // Given + server.setUrl("http://test.test.test:70000/"); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldThrowExceptionWhenWrongCaNameLength() { + // Given + server.setCaName(EMPTY_STRING); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldThrowExceptionWhenWrongRvLength() { + // Given + authentication.setRv(EMPTY_STRING); + + // Then + assertExceptionIsThrown(); + } + + + @Test + void shouldThrowExceptionWhenWrongIakLength() { + // Given + authentication.setIak(EMPTY_STRING); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldThrowExceptionWhenCaNameIsNull() { + // Given + server.setCaName(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldThrowExceptionWhenIssuerDnIsNull() { + // Given + server.setIssuerDN(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldThrowExceptionWhenCaModeIsNull() { + // Given + server.setCaMode(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldThrowExceptionWhenUrlIsNull() { + // Given + server.setUrl(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldThrowExceptionWhenAuthenticationIsNull() { + // Given + server.setAuthentication(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldThrowExceptionWhenIakIsNull() { + // Given + authentication.setIak(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldThrowExceptionWhenRvIsNull() { + // Given + authentication.setRv(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + void shouldNotThrowExceptionWhenServerConfigurationIsValid() { + // Then + assertDoesNotThrow(() -> validator.validate(servers)); + } + + private void assertExceptionIsThrown() { + assertThrows(IllegalArgumentException.class, () -> validator.validate(servers)); + } + + private void setServerConfiguration() { + server = new Cmpv2Server(); + server.setCaMode(CaMode.CLIENT); + server.setCaName("TEST"); + server.setIssuerDN(new X500Name("CN=ManagementCA")); + server.setUrl("http://127.0.0.1/ejbca/publicweb/cmp/cmp"); + server.setAuthentication(authentication); + } + + private void setAuthentication() { + authentication = new Authentication(); + authentication.setRv("testRV"); + authentication.setIak("testIAK"); + } + +} \ No newline at end of file diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidatorTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidatorTest.java new file mode 100644 index 00000000..5022342f --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/Cmpv2UrlValidatorTest.java @@ -0,0 +1,57 @@ +/* + * ============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.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +class Cmpv2UrlValidatorTest { + + private final Cmpv2UrlValidator validator = new Cmpv2UrlValidator(); + + @Test + void givenCorrectUrlWhenValidatingShouldReturnTrue() { + //given + String url = "http://127.0.0.1/ejbca/publicweb/cmp/cmp"; + + //when + boolean result = validator.isValid(url, null); + + //then + assertTrue(result); + } + + @Test + void givenIncorrectUrlWhenValidatingShouldReturnFalse() { + //given + String url = "httttp://127.0.0.1:80000/ejbca/publicweb/cmp/cmp"; + + //when + boolean result = validator.isValid(url, null); + + //then + assertFalse(result); + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/PortNumberViolationTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/PortNumberViolationTest.java new file mode 100644 index 00000000..59bf40aa --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/PortNumberViolationTest.java @@ -0,0 +1,76 @@ +/* + * ============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 org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class PortNumberViolationTest { + + private final PortNumberViolation violation = new PortNumberViolation(); + + @Test + void givenValidPortShouldReturnTrue() { + //given + String validUrl1 = "http://127.0.0.1:8080/ejbca/publicweb/cmp/cmp"; + String validUrl2 = "http://127.0.0.1:1/ejbca/publicweb/cmp/cmp"; + String validUrl3 = "http://127.0.0.1:65535/ejbca/publicweb/cmp/cmp"; + + //when + boolean result1 = violation.validate(validUrl1); + boolean result2 = violation.validate(validUrl2); + boolean result3 = violation.validate(validUrl3); + + //then + assertTrue(result1); + assertTrue(result2); + assertTrue(result3); + } + + @Test + void givenEmptyPortShouldReturnTrue() { + //given + String validUrl = "http://127.0.0.1/ejbca/publicweb/cmp/cmp"; + + //when + boolean result = violation.validate(validUrl); + + //then + assertTrue(result); + } + + @Test + void givenInvalidPortShouldReturnFalse() { + //given + String invalidUrl1 = "http://127.0.0.1:0/ejbca/publicweb/cmp/cmp"; + String invalidUrl2 = "http://127.0.0.1:65536/ejbca/publicweb/cmp/cmp"; + + //when + boolean result1 = violation.validate(invalidUrl1); + boolean result2 = violation.validate(invalidUrl2); + + //then + assertFalse(result1); + assertFalse(result2); + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolationTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolationTest.java new file mode 100644 index 00000000..90475f84 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/configuration/validation/constraints/violations/RequestTypeViolationTest.java @@ -0,0 +1,56 @@ +/* + * ============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 org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +class RequestTypeViolationTest { + + private final RequestTypeViolation violation = new RequestTypeViolation(); + + @Test + void givenValidRequestTypeShouldReturnTrue() { + //given + String validUrl = "http://127.0.0.1/ejbca/publicweb/cmp/cmp"; + + //when + boolean result = violation.validate(validUrl); + + //then + assertTrue(result); + } + + @Test + void givenInvalidRequestTypeShouldReturnFalse() { + //given + String invalidUrl = "htestps://127.0.0.1/ejbca/publicweb/cmp/cmp"; + + //when + boolean result = violation.validate(invalidUrl); + + //then + assertFalse(result); + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/certification/model/CsrModelTest.java b/certService/src/test/java/org/onap/oom/certservice/certification/model/CsrModelTest.java new file mode 100644 index 00000000..7981b271 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/certification/model/CsrModelTest.java @@ -0,0 +1,185 @@ +/* + * ============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 org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.util.io.pem.PemObject; +import org.junit.jupiter.api.Test; +import org.onap.oom.certservice.certification.Pkcs10CertificationRequestFactory; +import org.onap.oom.certservice.certification.PemObjectFactory; +import org.onap.oom.certservice.certification.exception.CsrDecryptionException; +import org.onap.oom.certservice.certification.exception.DecryptionException; +import org.onap.oom.certservice.certification.exception.KeyDecryptionException; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.onap.oom.certservice.certification.TestData.TEST_CSR; +import static org.onap.oom.certservice.certification.TestData.TEST_PEM; +import static org.onap.oom.certservice.certification.TestData.TEST_PK; + + +class CsrModelTest { + + private final Pkcs10CertificationRequestFactory certificationRequestFactory + = new Pkcs10CertificationRequestFactory(); + private final PemObjectFactory pemObjectFactory + = new PemObjectFactory(); + + @Test + void shouldByConstructedAndReturnProperFields() throws DecryptionException, IOException { + // Given + PemObject testPrivateKey = getPemPrivateKey(); + PemObject testPublicKey = generateTestPublicKey(); + PKCS10CertificationRequest testCsr = generateTestCertificationRequest(); + + // When + CsrModel csrModel = generateTestCsrModel(testCsr); + + // Then + assertThat(csrModel.getCsr()) + .isEqualTo(testCsr); + assertThat(csrModel.getPrivateKey().getEncoded()) + .contains(testPrivateKey.getContent()); + assertThat(csrModel.getPublicKey().getEncoded()) + .contains(testPublicKey.getContent()); + assertThat(csrModel.getSans()) + .contains( + "gerrit.onap.org", "test.onap.org", "onap.com"); + assertThat(csrModel.getSubjectData().toString()) + .contains( + "C=US,ST=California,L=San-Francisco,O=Linux-Foundation,OU=ONAP,CN=onap.org,E=tester@onap.org"); + } + + @Test + void shouldThrowExceptionWhenPublicKeyIsNotCorrect() throws DecryptionException, IOException { + // Given + PemObject testPrivateKey = getPemPrivateKey(); + PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class); + SubjectPublicKeyInfo wrongKryInfo = mock(SubjectPublicKeyInfo.class); + when(testCsr.getSubjectPublicKeyInfo()) + .thenReturn(wrongKryInfo); + when(wrongKryInfo.getEncoded()) + .thenThrow(new IOException()); + + // When + Exception exception = assertThrows( + CsrDecryptionException.class, + () -> new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build() + ); + + String expectedMessage = "Reading Public Key from CSR failed"; + String actualMessage = exception.getMessage(); + + // Then + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + void shouldThrowExceptionWhenPrivateKeyPemIsNotProperPrivateKey() throws KeyDecryptionException, IOException { + // Given + PemObject testPrivateKey = getPemWrongKey(); + PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class); + SubjectPublicKeyInfo wrongKryInfo = mock(SubjectPublicKeyInfo.class); + when(testCsr.getSubjectPublicKeyInfo()) + .thenReturn(wrongKryInfo); + when(wrongKryInfo.getEncoded()) + .thenThrow(new IOException()); + + // When + Exception exception = assertThrows( + KeyDecryptionException.class, + () -> new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build() + ); + + String expectedMessage = "Converting Private Key failed"; + String actualMessage = exception.getMessage(); + + // Then + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + void shouldThrowExceptionWhenPublicKeyPemIsNotProperPublicKey() throws KeyDecryptionException, IOException { + // Given + PemObject testPrivateKey = getPemPrivateKey(); + PemObject testPublicKey = getPemWrongKey(); + PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class); + SubjectPublicKeyInfo wrongKryInfo = mock(SubjectPublicKeyInfo.class); + when(testCsr.getSubjectPublicKeyInfo()) + .thenReturn(wrongKryInfo); + when(wrongKryInfo.getEncoded()) + .thenReturn(testPublicKey.getContent()); + + // When + Exception exception = assertThrows( + KeyDecryptionException.class, + () -> new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build() + ); + + String expectedMessage = "Converting Public Key from CSR failed"; + String actualMessage = exception.getMessage(); + + // Then + assertTrue(actualMessage.contains(expectedMessage)); + } + + private PemObject getPemPrivateKey() throws KeyDecryptionException { + PemObjectFactory pemObjectFactory = new PemObjectFactory(); + return pemObjectFactory.createPemObject(TEST_PK).orElseThrow( + () -> new KeyDecryptionException("Private key decoding fail") + ); + } + + private PemObject getPemWrongKey() throws KeyDecryptionException { + PemObjectFactory pemObjectFactory = new PemObjectFactory(); + return pemObjectFactory.createPemObject(TEST_PEM).orElseThrow( + () -> new KeyDecryptionException("Private key decoding fail") + ); + } + + private CsrModel generateTestCsrModel(PKCS10CertificationRequest testCsr) throws DecryptionException { + PemObject testPrivateKey = pemObjectFactory.createPemObject(TEST_PK).orElseThrow( + () -> new DecryptionException("Incorrect Private Key, decryption failed") + ); + return new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build(); + } + + private PemObject generateTestPublicKey() throws DecryptionException, IOException { + PKCS10CertificationRequest testCsr = generateTestCertificationRequest(); + return new PemObject("PUBLIC KEY", testCsr.getSubjectPublicKeyInfo().getEncoded()); + } + + private PKCS10CertificationRequest generateTestCertificationRequest() throws DecryptionException { + return pemObjectFactory.createPemObject(TEST_CSR) + .flatMap( + certificationRequestFactory::createPkcs10CertificationRequest + ).orElseThrow( + () -> new DecryptionException("Incorrect CSR, decryption failed") + ); + } + +} diff --git a/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java b/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java new file mode 100644 index 00000000..984e8c77 --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2019 Ericsson Software Technology AB. 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 + */ + +package org.onap.oom.certservice.cmpv2client; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.impl.client.CloseableHttpClient; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x500.X500NameBuilder; +import org.bouncycastle.asn1.x500.style.BCStyle; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.onap.oom.certservice.certification.configuration.model.Authentication; +import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server; +import org.onap.oom.certservice.certification.model.CsrModel; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.onap.oom.certservice.cmpv2client.impl.CmpClientImpl; +import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel; + +class Cmpv2ClientTest { + + static { + Security.addProvider(new BouncyCastleProvider()); + } + + private CsrModel csrModel; + private Cmpv2Server server; + private Date notBefore; + private Date notAfter; + private X500Name dn; + + @Mock + X509Certificate cert; + + @Mock + CloseableHttpClient httpClient; + + @Mock + CloseableHttpResponse httpResponse; + + @Mock + HttpEntity httpEntity; + + private static KeyPair keyPair; + + @BeforeEach + void setUp() + throws NoSuchProviderException, NoSuchAlgorithmException, IOException, + InvalidKeySpecException { + keyPair = loadKeyPair(); + dn = new X500NameBuilder() + .addRDN(BCStyle.O, "TestOrganization") + .build(); + initMocks(this); + } + + public KeyPair loadKeyPair() + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, + NoSuchProviderException { + + final InputStream privateInputStream = this.getClass().getResourceAsStream("/privateKey"); + final InputStream publicInputStream = this.getClass().getResourceAsStream("/publicKey"); + BufferedInputStream bis = new BufferedInputStream(privateInputStream); + byte[] privateBytes = IOUtils.toByteArray(bis); + bis = new BufferedInputStream(publicInputStream); + byte[] publicBytes = IOUtils.toByteArray(bis); + + KeyFactory keyFactory = KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME); + X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicBytes); + PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); + + PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateBytes); + PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec); + + return new KeyPair(publicKey, privateKey); + } + + @Test + void shouldReturnValidPkiMessageWhenCreateCertificateRequestMessageMethodCalledWithValidCsr() + throws Exception { + // given + Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00"); + Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00"); + setCsrModelAndServerValues( + "mypassword", + "senderKID", + "http://127.0.0.1/ejbca/publicweb/cmp/cmp", + beforeDate, + afterDate); + when(httpClient.execute(any())).thenReturn(httpResponse); + when(httpResponse.getEntity()).thenReturn(httpEntity); + + try (final InputStream is = + this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile"); + BufferedInputStream bis = new BufferedInputStream(is)) { + + byte[] ba = IOUtils.toByteArray(bis); + doAnswer( + invocation -> { + OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0]; + os.write(ba); + return null; + }) + .when(httpEntity) + .writeTo(any(OutputStream.class)); + } + CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient)); + // when + Cmpv2CertificationModel cmpClientResult = + cmpClient.createCertificate(csrModel, server, notBefore, notAfter); + // then + assertNotNull(cmpClientResult); + } + + @Test + void + shouldThrowCmpClientExceptionWhenCreateCertificateRequestMessageMethodCalledWithWrongProtectedBytesInResponse() + throws Exception { + // given + Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00"); + Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00"); + setCsrModelAndServerValues( + "password", + "senderKID", + "http://127.0.0.1/ejbca/publicweb/cmp/cmp", + beforeDate, + afterDate); + when(httpClient.execute(any())).thenReturn(httpResponse); + when(httpResponse.getEntity()).thenReturn(httpEntity); + + try (final InputStream is = + this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile"); + BufferedInputStream bis = new BufferedInputStream(is)) { + + byte[] ba = IOUtils.toByteArray(bis); + doAnswer( + invocation -> { + OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0]; + os.write(ba); + return null; + }) + .when(httpEntity) + .writeTo(any(OutputStream.class)); + } + CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient)); + // then + Assertions.assertThrows( + CmpClientException.class, + () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); + } + + @Test + void shouldThrowCmpClientExceptionWithPkiErrorExceptionWhenCmpClientCalledWithBadPassword() + throws Exception { + // given + Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00"); + Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00"); + setCsrModelAndServerValues( + "password", + "senderKID", + "http://127.0.0.1/ejbca/publicweb/cmp/cmp", + beforeDate, + afterDate); + when(httpClient.execute(any())).thenReturn(httpResponse); + when(httpResponse.getEntity()).thenReturn(httpEntity); + + try (final InputStream is = + this.getClass().getResourceAsStream("/ReturnedFailurePKIMessageBadPassword"); + BufferedInputStream bis = new BufferedInputStream(is)) { + + byte[] ba = IOUtils.toByteArray(bis); + doAnswer( + invocation -> { + OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0]; + os.write(ba); + return null; + }) + .when(httpEntity) + .writeTo(any(OutputStream.class)); + } + CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient)); + + // then + Assertions.assertThrows( + CmpClientException.class, + () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); + } + + @Test + void shouldThrowIllegalArgumentExceptionWhencreateCertificateCalledWithInvalidCsr() + throws ParseException { + // given + Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00"); + Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00"); + setCsrModelAndServerValues( + "password", + "senderKID", + "http://127.0.0.1/ejbca/publicweb/cmp/cmp", + beforeDate, + afterDate); + CmpClientImpl cmpClient = new CmpClientImpl(httpClient); + // then + Assertions.assertThrows( + IllegalArgumentException.class, + () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); + } + + @Test + void shouldThrowIoExceptionWhenCreateCertificateCalledWithNoServerAvailable() + throws IOException, ParseException { + // given + Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00"); + Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00"); + setCsrModelAndServerValues( + "myPassword", + "sender", + "http://127.0.0.1/ejbca/publicweb/cmp/cmpTest", + beforeDate, + afterDate); + when(httpClient.execute(any())).thenThrow(IOException.class); + CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient)); + // then + Assertions.assertThrows( + CmpClientException.class, + () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter)); + } + + private void setCsrModelAndServerValues(String iak, String rv, String externalCaUrl, Date notBefore, Date notAfter) { + csrModel = new CsrModel(null, dn, keyPair.getPrivate(), keyPair.getPublic(), Collections.emptyList()); + + Authentication authentication = new Authentication(); + authentication.setIak(iak); + authentication.setRv(rv); + server = new Cmpv2Server(); + server.setAuthentication(authentication); + server.setUrl(externalCaUrl); + server.setIssuerDN(dn); + this.notBefore = notBefore; + this.notAfter = notAfter; + } +} diff --git a/certService/src/test/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseHelperTest.java b/certService/src/test/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseHelperTest.java new file mode 100644 index 00000000..6686191f --- /dev/null +++ b/certService/src/test/java/org/onap/oom/certservice/cmpv2client/impl/CmpResponseHelperTest.java @@ -0,0 +1,609 @@ +/*- + * ============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.impl; + +import org.bouncycastle.asn1.cmp.CMPCertificate; +import org.bouncycastle.asn1.cmp.CertRepMessage; +import org.bouncycastle.asn1.cmp.PKIMessage; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException; +import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.StringReader; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class CmpResponseHelperTest { + + + private static final String EXPECTED_ERROR_MESSAGE = "Something was wrong with the supplied certificate"; + + private static final String TEST_1LAYER_ENTITY_CERT = "" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIEqDCCAxCgAwIBAgIUFioEkVJsxfZGGDMEyCA8Rin3uhQwDQYJKoZIhvcNAQEL\n" + + "BQAwYTEjMCEGCgmSJomT8ixkAQEME2MtMDM1ZDk4NTAwYzhiN2JiMjIxFTATBgNV\n" + + "BAMMDE1hbmFnZW1lbnRDQTEjMCEGA1UECgwaRUpCQ0EgQ29udGFpbmVyIFF1aWNr\n" + + "c3RhcnQwHhcNMjAwMzI0MTEzNTU0WhcNMjIwMzI0MTEzNTU0WjCBljEgMB4GCSqG\n" + + "SIb3DQEJARYRQ29tbW9uTmFtZUBjbi5jb20xDjAMBgNVBAMMBUNsMTIzMQ0wCwYD\n" + + "VQQLDARPTkFQMRkwFwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMRYwFAYDVQQHDA1T\n" + + "YW4tRnJhbmNpc2NvMRMwEQYDVQQIDApDYWxpZm9ybmlhMQswCQYDVQQGEwJVUzCC\n" + + "ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL94FcmRn/g9Y9ZrEL+jKiud\n" + + "xzDdtVLoF0ijZOGG0rnzyimzzwOjd8LA0jiZlYtpoDef95bbMeZJMKzE3bA8EMFp\n" + + "hynqUHs/KdsLBV+o3J6EzlpYHrwypX7kOriw9o4dmPAxvJHXTu3HC2SejJjHHArk\n" + + "FyahEJ03ypvCJx3iPvGXkLI9tZetobiVXslBJd5t0hQj+JQxzAlTwS0fV+xMowFT\n" + + "css2IlGXfQgd88cdhXBVOE0//qln1ko3G3KeH58iIWLqh9KG660SCeoTCop7bO1N\n" + + "abVrcXlgdE06hAvzTj3FoBxqO5KEWDPo2Dr11qRdq8bLP2T0EbTzAw4DPUwE+H8C\n" + + "AwEAAaOBoTCBnjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFDPaBc+EX/hCLe5c\n" + + "d+oZIxcQZ1tHMB8GA1UdEQQYMBaCBUNsMTIzgg10ZXN0Lm9uYXAub3JnMB0GA1Ud\n" + + "JQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAdBgNVHQ4EFgQU4dP1HuV9O+sHInl+\n" + + "WuvdDJ63lp8wDgYDVR0PAQH/BAQDAgXgMA0GCSqGSIb3DQEBCwUAA4IBgQBWTF8C\n" + + "sH0ir4bj7rTlJMf5o7apkXFeQ/c7+zXnSLCfXqwM6ad0EDh3FixfTC8IpW5CaENt\n" + + "zTR7IGJr06ccwLgsigR7FxJKnEkxJiBxzkE3zFOEel3KAnV2b7KvOP7cJAzsCdcS\n" + + "iZU475XHOw4Ox3k8fHzhTJJa0Tzw5EjQ3GO99HTiUClGrjJuYDLfen1q7IQSNuTY\n" + + "FzxJZjyqzi34pkKeCNSPRj8Z8Q5aZiWqlmzSJmZRT83xzzeW/pQ1JwvIrWwrbEjR\n" + + "FPXBlUa1n2HztkDgeBQfRyMAj5ixFV+s1Jj+cEYl3pjbugnuHfgBdSJokXFGBo6N\n" + + "8PTd1CnMGWcWiMyhbTwNm2UiSr5KhQbjABjiUzDp4C7jFhIzmu/4/tm2uA+y0xPN\n" + + "342uEZC0ZSZmpCIbQMhPaBNjSHeHj8NaLHjnt5jppLkMxScayRqMvSW07eNew2+k\n" + + "VYJD6z6gfy4y+Y5MSLfvddq1JdPDU86TFprtD1ydcUBS5tduYQG2+1bLgpE=" + + "\n-----END CERTIFICATE-----\n"; + + private static final String TEST_1LAYER_CA_CERT = "" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIEszCCAxugAwIBAgIUEhkh+zJtXZN3K3kzQYcbp2smyIkwDQYJKoZIhvcNAQEL\n" + + "BQAwYTEjMCEGCgmSJomT8ixkAQEME2MtMDM1ZDk4NTAwYzhiN2JiMjIxFTATBgNV\n" + + "BAMMDE1hbmFnZW1lbnRDQTEjMCEGA1UECgwaRUpCQ0EgQ29udGFpbmVyIFF1aWNr\n" + + "c3RhcnQwHhcNMjAwMzI0MTAyODQyWhcNMzAwMzI0MTAyODQyWjBhMSMwIQYKCZIm\n" + + "iZPyLGQBAQwTYy0wMzVkOTg1MDBjOGI3YmIyMjEVMBMGA1UEAwwMTWFuYWdlbWVu\n" + + "dENBMSMwIQYDVQQKDBpFSkJDQSBDb250YWluZXIgUXVpY2tzdGFydDCCAaIwDQYJ\n" + + "KoZIhvcNAQEBBQADggGPADCCAYoCggGBAJyKZyKIRyW6cbga/I1YFJGCEEgs9JVU\n" + + "sV7MD5/yF4SIkJlZqFjJ9kfw8D5thg68zAx2vEWIpNTMroqb1eptIn/XsFoyM//6\n" + + "HzKrY3UUYWHx9sQMDZPenTL8LTRx+4szSen7rzrozH2pJat7kfX4EODEtQ6q7RQ2\n" + + "hmXoo7heeSgiHoeHsPGZixPGzcB27WBaY00Z/sP/n+f0CFaE04MKLw8WeQmq/RkC\n" + + "pj628+eBK0lGtEmUcT7z4CBy4x3hbhn9XHOb0+RlDk7rqFbsc09vHoZK2BfQ/r6e\n" + + "HguZjBQ5Ebqf6PiLF3HqkSW73toIdIy/olvQ2dLbOEyI4OnlObc+8xs/1AC7l9xX\n" + + "FkXY+NBv24KG1C2POXx14+ufHhWY0k2nIRUUlkUIJ7WGMWbuiNUXc1wSE1VrmY/c\n" + + "iXlhsJERqFc6bL/STlhOGuwmkdAD1/K8WS+o/QmIIX6cXlOR0U9bHMbD40F9fur6\n" + + "PV8wSKcQQNd0VHRLhmFwo4kkhZpDpuUp4QIDAQABo2MwYTAPBgNVHRMBAf8EBTAD\n" + + "AQH/MB8GA1UdIwQYMBaAFDPaBc+EX/hCLe5cd+oZIxcQZ1tHMB0GA1UdDgQWBBQz\n" + + "2gXPhF/4Qi3uXHfqGSMXEGdbRzAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL\n" + + "BQADggGBAFGsyu5nWycdk8iva+uY98QnPQe/M6uaUGUis0vGn9UYxoz5ddtpF3Z+\n" + + "MsHgbS51BH9iRYn4ZkQoRoukIjt1iO86d6sgpUS5AStCXsylL4DwAY5G/K5i/Qw5\n" + + "x0lP/tRYwqh2tUhmnx1xZLOWbRFZ63A0YHdguj3CqaXQ/cxafYZe0zcNhX3iH3gf\n" + + "5kHH8E682RT0x4ibb1JtPioQ48+pweyfMlOJkJ7WmZEfiVQitQSSNOnw1hRORiUz\n" + + "oFb0MlYHqe/9lIb9nmzD8QQ9q0H8J6RBCFsntx/Z6oUM8GHr80zAvNjqFfR14lOo\n" + + "jp05w2mr7wxIHFpM6h1HGY1QaeGp6W/fi+N7+gSL3nu1LzXVCYNCTcGkBDeasovB\n" + + "ma70KHGO4ZyRcEMKFCxxE8y4GZnw/EhMhDDevXAVsHEzr6XsBCJkC8e2l3iW5IKH\n" + + "4N/f/k06d4kS5pL290dJ450zx/mBxYGJm+pPHZfDszqVeKn1m1ZhGT80150OePGQ\n" + + "Cc2ir84HwQ==" + + "\n-----END CERTIFICATE-----\n"; + + private static final String TEST_2LAYER_ENTITY_CERT = "" + + "-----BEGIN CERTIFICATE-----\n" + + "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-----"; + + private static final String TEST_2LAYER_INTERMEDIATE_CERT = "" + + "-----BEGIN CERTIFICATE-----\n" + + "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-----"; + + private static final String TEST_2LAYER_CA_CERT = "" + + "-----BEGIN CERTIFICATE-----\n" + + "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-----"; + + + @BeforeAll + static void setUpSecurity() { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + } + + + @Test + void returnListOfCertificationWhenGivenCaCertInCaPubsAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + PKIMessage respPkiMessage = mockExtraCerts(null); + + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); + CMPCertificate[] cmpCertificates = {caCmpCertificate}; + CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityCertificate(certs, TEST_1LAYER_ENTITY_CERT); + + assertThatRootCaAndTrustedCaAreInSecondList(certs, caCmpCertificate); + } + + @Test + void returnListOfCertificationWhenGivenCaCertInExtraCertsAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); + CMPCertificate[] extraCmpCertificates = {caCmpCertificate}; + PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); + + CertRepMessage certRepMessage = mockCaPubs(null); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityCertificate(certs, TEST_1LAYER_ENTITY_CERT); + + assertThatRootCaAndTrustedCaAreInSecondList(certs, caCmpCertificate); + } + + @Test + void returnListOfCertificationWhenGivenCaCertInExtraCertsAndExtraTrustAnchorInCaPubsAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); + CMPCertificate[] extraCmpCertificates = {caCmpCertificate}; + PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); + + CMPCertificate extraTrustAnchor = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); + CMPCertificate[] cmpCertificates = {extraTrustAnchor}; + CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityCertificate(certs, TEST_1LAYER_ENTITY_CERT); + + assertThatRootCaAndTrustedCaAreInSecondList( + certs, + caCmpCertificate, extraTrustAnchor + ); + } + + @Test + void returnListOfCertificationWhenGivenCaCertInExtraCertsAndExtraTrustAnchorInExtraCertsAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + CMPCertificate trustedCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); + CMPCertificate[] extraCmpCertificates = {caCmpCertificate, trustedCmpCertificate}; + PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); + + CertRepMessage certRepMessage = mockCaPubs(null); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityCertificate(certs, TEST_1LAYER_ENTITY_CERT); + + assertThatRootCaAndTrustedCaAreInSecondList( + certs, + caCmpCertificate, trustedCmpCertificate + ); + } + + @Test + void returnListOfCertificationWhenGivenCaCertAndIntermediateCertInExtraCertsAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); + CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); + CMPCertificate[] extraCmpCertificates = {caCmpCertificate, intermediateCmpCertificate}; + PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); + + CertRepMessage certRepMessage = mockCaPubs(null); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); + + assertThatRootCaAndTrustedCaAreInSecondList( + certs, + caCmpCertificate + ); + } + + @Test + void returnListOfCertificationWhenGivenCaCertAndIntermediateCertInCmpCertificatesAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + PKIMessage respPkiMessage = mockExtraCerts(null); + + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); + CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); + CMPCertificate[] cmpCertificates = {caCmpCertificate, intermediateCmpCertificate}; + CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); + + assertThatRootCaAndTrustedCaAreInSecondList( + certs, + caCmpCertificate + ); + } + + @Test + void returnListOfCertificationWhenGivenCaCertInCaPubsAndIntermediateCertInExtraCertsAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); + CMPCertificate[] extraCmpCertificates = {intermediateCmpCertificate}; + PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); + + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); + CMPCertificate[] cmpCertificates = {caCmpCertificate}; + CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); + + assertThatRootCaAndTrustedCaAreInSecondList( + certs, + caCmpCertificate + ); + } + + @Test + void returnListOfCertificationWhenGivenCaCertInCaPubsAndExtraCertsAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); + CMPCertificate[] extraCmpCertificates = {caCmpCertificate}; + PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); + CMPCertificate[] cmpCertificates = {mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT)}; + CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityCertificate(certs, TEST_1LAYER_ENTITY_CERT); + assertThatRootCaAndTrustedCaAreInSecondList(certs, mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT)); + + } + + @Test + void returnListOfCertificationWhenGivenCaCertAndIntermediateCertInExtraCertsAndIntermediateCertInCaPubsAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); + CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); + CMPCertificate[] extraCmpCertificates = {caCmpCertificate, intermediateCmpCertificate}; + PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); + CMPCertificate[] cmpCertificates = {intermediateCmpCertificate}; + CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); + assertThatRootCaAndTrustedCaAreInSecondList( + certs, + caCmpCertificate + ); + } + + @Test + void returnListOfCertificationWhenGivenCaCertAndExtraTrustAnchorInCaPubsAndIntermediateCertInExtraCertsAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); + CMPCertificate[] extraCmpCertificates = {intermediateCmpCertificate}; + PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); + + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); + CMPCertificate extraTrustAnchor = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); + CMPCertificate[] cmpCertificates = {caCmpCertificate, extraTrustAnchor}; + CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); + + assertThatRootCaAndTrustedCaAreInSecondList( + certs, + caCmpCertificate, extraTrustAnchor + ); + } + + @Test + void returnListOfCertificationWhenGivenCaCertAndFirstExtraTrustAnchorInCaPubsAndIntermediateCertAndSecondExtraTrustAnchorInExtraCertsAndEntityCertInLeafCertificate() + throws CertificateException, CmpClientException, IOException, NoSuchProviderException { + // given + CMPCertificate intermediateCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_INTERMEDIATE_CERT); + CMPCertificate extraTrustAnchor01 = mockCmpCertificateFromPem(TEST_1LAYER_ENTITY_CERT); + CMPCertificate[] extraCmpCertificates = {intermediateCmpCertificate, extraTrustAnchor01}; + PKIMessage respPkiMessage = mockExtraCerts(extraCmpCertificates); + + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); + CMPCertificate extraTrustAnchor02 = mockCmpCertificateFromPem(TEST_1LAYER_CA_CERT); + CMPCertificate[] cmpCertificates = {caCmpCertificate, extraTrustAnchor02}; + CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); + + // when + Cmpv2CertificationModel certs = CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate); + + // then + assertThatChainContainsEntityAndIntermediateCertificate(certs, TEST_2LAYER_ENTITY_CERT, TEST_2LAYER_INTERMEDIATE_CERT); + + assertThatRootCaAndTrustedCaAreInSecondList( + certs, + caCmpCertificate, extraTrustAnchor01, extraTrustAnchor02 + ); + } + + @Test + void throwsExceptionWhenNoCaCertForEntityCertIsGivenAndOnlyExtraTrustAnchorIsReturned() + throws CertificateException, IOException, NoSuchProviderException { + // given + + PKIMessage respPkiMessage = mockExtraCerts(null); + + CMPCertificate trustedCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); + CMPCertificate[] cmpCertificates = {trustedCmpCertificate}; + CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); + + // when + Exception exception = assertThrows( + CmpClientException.class, + () -> CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate + ) + ); + + String actualMessage = exception.getMessage(); + + // then + assertThat(actualMessage).isEqualTo(EXPECTED_ERROR_MESSAGE); + } + + @Test + void throwsExceptionWhenBothExtraCertsAndCaPubsAreEmpty() + throws CertificateException, IOException, NoSuchProviderException { + // given + + PKIMessage respPkiMessage = mockExtraCerts(null); + CertRepMessage certRepMessage = mockCaPubs(null); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_1LAYER_ENTITY_CERT); + + // when + Exception exception = assertThrows( + CmpClientException.class, + () -> CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate + ) + ); + + String actualMessage = exception.getMessage(); + + // then + assertThat(actualMessage).isEqualTo(EXPECTED_ERROR_MESSAGE); + } + + @Test + void throwsExceptionWhenNoIntermediateCertForEntityCertIsGiven() + throws CertificateException, IOException, NoSuchProviderException { + // given + + PKIMessage respPkiMessage = mockExtraCerts(null); + + CMPCertificate caCmpCertificate = mockCmpCertificateFromPem(TEST_2LAYER_CA_CERT); + CMPCertificate[] cmpCertificates = {caCmpCertificate}; + CertRepMessage certRepMessage = mockCaPubs(cmpCertificates); + + X509Certificate leafCertificate = getX509CertificateFromPem(TEST_2LAYER_ENTITY_CERT); + + // when + Exception exception = assertThrows( + CmpClientException.class, + () -> CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore( + respPkiMessage, certRepMessage, leafCertificate + ) + ); + + String actualMessage = exception.getMessage(); + + // then + assertThat(actualMessage).isEqualTo(EXPECTED_ERROR_MESSAGE); + } + + + private void assertThatRootCaAndTrustedCaAreInSecondList( + Cmpv2CertificationModel certs, CMPCertificate... rootAndTrustedCerts + ) throws IOException { + assertThat(certs.getTrustedCertificates().size()).isEqualTo(rootAndTrustedCerts.length); + for (CMPCertificate certificate : rootAndTrustedCerts) { + assertThat(certs.getTrustedCertificates()) + .extracting(Certificate::getEncoded) + .contains(certificate.getEncoded()); + } + } + + private void assertThatChainContainsEntityCertificate( + Cmpv2CertificationModel certs, String entityCertificate + ) throws CertificateEncodingException, IOException { + assertThat(certs.getCertificateChain().size()).isEqualTo(1); + assertThat(certs.getCertificateChain().get(0).getEncoded()).isEqualTo(createPemObject(entityCertificate).getContent()); + } + + private void assertThatChainContainsEntityAndIntermediateCertificate( + Cmpv2CertificationModel certs, String entityCertificate, String intermediateCertificate + ) throws CertificateEncodingException, IOException { + assertThat(certs.getCertificateChain().size()).isEqualTo(2); + assertThat(certs.getCertificateChain().get(0).getEncoded()).isEqualTo(createPemObject(entityCertificate).getContent()); + assertThat(certs.getCertificateChain().get(1).getEncoded()).isEqualTo(createPemObject(intermediateCertificate).getContent()); + } + + private X509Certificate getX509CertificateFromPem(String pem) throws CertificateException, NoSuchProviderException, IOException { + return (X509Certificate) + CertificateFactory.getInstance("X.509", "BC").generateCertificate( + new ByteArrayInputStream(createPemObject(pem).getContent()) + ); + } + + private PKIMessage mockExtraCerts(CMPCertificate[] cmpCertificates) { + PKIMessage respPkiMessage = mock(PKIMessage.class); + when(respPkiMessage.getExtraCerts()).thenReturn(cmpCertificates); + return respPkiMessage; + } + + private CertRepMessage mockCaPubs(CMPCertificate[] cmpCertificates) { + CertRepMessage certRepMessage = mock(CertRepMessage.class); + when(certRepMessage.getCaPubs()).thenReturn(cmpCertificates); + return certRepMessage; + } + + private CMPCertificate mockCmpCertificateFromPem(String pem) throws IOException { + return mockCmpCertificate(createPemObject(pem).getContent()); + } + + private CMPCertificate mockCmpCertificate(byte[] encodedCertificate) throws IOException { + CMPCertificate cmpCertificate01 = mock(CMPCertificate.class); + when(cmpCertificate01.getEncoded()).thenReturn(encodedCertificate); + return cmpCertificate01; + } + + private PemObject createPemObject(String pem) throws IOException { + try (StringReader stringReader = new StringReader(pem); + PemReader pemReader = new PemReader(stringReader)) { + return pemReader.readPemObject(); + } + } +} diff --git a/certService/src/test/resources/application.properties b/certService/src/test/resources/application.properties index b70ab3b4..0bd9b36f 100644 --- a/certService/src/test/resources/application.properties +++ b/certService/src/test/resources/application.properties @@ -1,4 +1,4 @@ -# AAF CertService app specific configuration +# OOM CertService app specific configuration app.config.path=./src/test/resources # Mutual TLS configuration @@ -6,8 +6,8 @@ server.ssl.enabled=true server.ssl.client-auth=need server.port=${HTTPS_PORT:8443} -server.ssl.key-store=${KEYSTORE_PATH:/etc/onap/aaf/certservice/certs/certServiceServer-keystore.jks} +server.ssl.key-store=${KEYSTORE_PATH:/etc/onap/oom/certservice/certs/certServiceServer-keystore.jks} server.ssl.key-store-password=${KEYSTORE_PASSWORD:secret} -server.ssl.trust-store=${TRUSTSTORE_PATH:/etc/onap/aaf/certservice/certs/truststore.jks} +server.ssl.trust-store=${TRUSTSTORE_PATH:/etc/onap/oom/certservice/certs/truststore.jks} server.ssl.trust-store-password=${TRUSTSTORE_PASSWORD:secret} \ No newline at end of file -- cgit 1.2.3-korg