diff options
75 files changed, 2862 insertions, 279 deletions
diff --git a/certService/Dockerfile b/certService/Dockerfile index 5060c6bf..770dab97 100644 --- a/certService/Dockerfile +++ b/certService/Dockerfile @@ -4,7 +4,7 @@ ARG VERSION=${version} RUN groupadd certService && useradd -g certService certService -RUN apt-get update && apt-get install -y vim +RUN apt-get update && apt-get install -y vim curl RUN chown -R certService:certService /var/log diff --git a/certService/README.md b/certService/README.md index 23cb2cf6..4780a904 100644 --- a/certService/README.md +++ b/certService/README.md @@ -84,15 +84,23 @@ curl localhost:8080/actuator/health ``` Should return {"status":"UP"} -### Running CSITs -Pull csit repository +### AAF CertService CSITs +#### CSIT repository ``` https://gerrit.onap.org/r/admin/repos/integration/csit ``` -Go to created directory and run + +####How to run tests locally +1. Checkout CSIT repository +2. Configure CSIT local environment +3. Inside CSIT directory execute ``` -sudo ./run-csit.sh plans/aaf/cert-service +sudo ./run-csit.sh plans/aaf/certservice ``` + +####Jenkins build +https://jenkins.onap.org/view/CSIT/job/aaf-master-csit-certservice/ + ### Logs locally path: diff --git a/certService/src/main/java/org/onap/aaf/certservice/api/CertificationService.java b/certService/src/main/java/org/onap/aaf/certservice/api/CertificationController.java index 945fc6d1..e663909c 100644 --- a/certService/src/main/java/org/onap/aaf/certservice/api/CertificationService.java +++ b/certService/src/main/java/org/onap/aaf/certservice/api/CertificationController.java @@ -39,15 +39,15 @@ import org.springframework.web.bind.annotation.RestController; @RestController -public class CertificationService { +public class CertificationController { - private static final Logger LOGGER = LoggerFactory.getLogger(CertificationService.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CertificationController.class); private final CsrModelFactory csrModelFactory; private final CertificationModelFactory certificationModelFactory; @Autowired - CertificationService(CsrModelFactory csrModelFactory, CertificationModelFactory certificationModelFactory) { + CertificationController(CsrModelFactory csrModelFactory, CertificationModelFactory certificationModelFactory) { this.csrModelFactory = csrModelFactory; this.certificationModelFactory = certificationModelFactory; } @@ -81,5 +81,4 @@ public class CertificationService { } - } 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 new file mode 100644 index 00000000..5390a00c --- /dev/null +++ b/certService/src/main/java/org/onap/aaf/certservice/api/ReloadConfigController.java @@ -0,0 +1,58 @@ +/* + * ============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 org.onap.aaf.certservice.certification.configuration.CmpServersConfig; +import org.onap.aaf.certservice.certification.configuration.CmpServersConfigLoadingException; +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.ExceptionHandler; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class ReloadConfigController { + + private static final Logger LOGGER = LoggerFactory.getLogger(ReloadConfigController.class); + + private final CmpServersConfig cmpServersConfig; + + @Autowired + public ReloadConfigController(CmpServersConfig cmpServersConfig) { + this.cmpServersConfig = cmpServersConfig; + } + + @GetMapping("/reload") + public ResponseEntity<String> reloadConfiguration() throws CmpServersConfigLoadingException { + cmpServersConfig.reloadConfiguration(); + return new ResponseEntity<>(HttpStatus.OK); + } + + @ExceptionHandler(value = CmpServersConfigLoadingException.class) + public ResponseEntity<String> 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/certification/configuration/CmpServersConfig.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfig.java index 25e69251..a304b5a6 100644 --- 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 @@ -20,34 +20,31 @@ 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.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent; import org.springframework.context.annotation.Configuration; -import javax.annotation.PostConstruct; -import java.io.File; -import java.util.Collections; -import java.util.List; -import org.springframework.context.event.EventListener; - @Configuration public class CmpServersConfig { private static final Logger LOGGER = LoggerFactory.getLogger(CmpServersConfig.class); + 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 static final String INIT_CONFIGURATION = "Loading initial configuration"; private static final String REFRESHING_CONFIGURATION = "Refreshing configuration"; - private String configPath; - private List<Cmpv2Server> cmpServers; + private final String configPath; private final CmpServersConfigLoader cmpServersConfigLoader; + private List<Cmpv2Server> cmpServers; + @Autowired public CmpServersConfig(@Value("${app.config.path}") String configPath, CmpServersConfigLoader cmpServersConfigLoader) { @@ -56,18 +53,28 @@ public class CmpServersConfig { } @PostConstruct - void loadConfiguration() { - String configFilePath = configPath + File.separator + CMP_SERVERS_CONFIG_FILENAME; - this.cmpServers = Collections.unmodifiableList(cmpServersConfigLoader.load(configFilePath)); + void init() { + LOGGER.info(INIT_CONFIGURATION); + try { + loadConfiguration(); + } catch (CmpServersConfigLoadingException e) { + LOGGER.error(e.getMessage(), e.getCause()); + } } - @EventListener - public void onRefreshScope(final RefreshScopeRefreshedEvent event) { + public void reloadConfiguration() throws CmpServersConfigLoadingException { LOGGER.info(REFRESHING_CONFIGURATION); loadConfiguration(); } + void loadConfiguration() throws CmpServersConfigLoadingException { + String configFilePath = configPath + File.separator + CMP_SERVERS_CONFIG_FILENAME; + this.cmpServers = Collections.unmodifiableList(cmpServersConfigLoader.load(configFilePath)); + LOGGER.info(LOADING_SUCCESS_MESSAGE, configFilePath); + } + public List<Cmpv2Server> getCmpServers() { return cmpServers; } + } 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 index a6dd5fcf..1072d630 100644 --- 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 @@ -24,20 +24,18 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.IOException; import java.security.InvalidParameterException; -import java.util.ArrayList; 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.Cmpv2ServerConfigurationValidator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component class CmpServersConfigLoader { - private static final Logger LOGGER = LoggerFactory.getLogger(CmpServersConfigLoader.class); + 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 Cmpv2ServerConfigurationValidator validator; @@ -46,20 +44,16 @@ class CmpServersConfigLoader { this.validator = validator; } - List<Cmpv2Server> load(String path) { - List<Cmpv2Server> servers = new ArrayList<>(); + List<Cmpv2Server> load(String path) throws CmpServersConfigLoadingException { try { - servers = loadConfigFromFile(path).getCmpv2Servers(); + List<Cmpv2Server> servers = loadConfigFromFile(path).getCmpv2Servers(); servers.forEach(validator::validate); - LOGGER.info(String.format("CMP Servers configuration successfully loaded from file '%s'", path)); + return servers; } catch (IOException e) { - LOGGER.error("Exception occurred during CMP Servers configuration loading: ", e); + throw new CmpServersConfigLoadingException(LOADING_EXCEPTION_MESSAGE, e); } catch (InvalidParameterException e) { - LOGGER.error("Validation of CMPv2 servers configuration failed:", e); - throw e; + throw new CmpServersConfigLoadingException(VALIDATION_EXCEPTION_MESSAGE, e); } - - return servers; } private CmpServers loadConfigFromFile(String path) throws IOException { 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 new file mode 100644 index 00000000..b7c3638d --- /dev/null +++ b/certService/src/main/java/org/onap/aaf/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.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/model/Authentication.java b/certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/Authentication.java index af254d61..3785cf8e 100644 --- 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 @@ -20,12 +20,15 @@ package org.onap.aaf.certservice.certification.configuration.model; +import javax.validation.constraints.NotNull; import org.hibernate.validator.constraints.Length; public class Authentication { + @NotNull @Length(min = 1, max = 256) private String iak; + @NotNull @Length(min = 1, max = 256) private String rv; 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 index 9f8f9796..20b83b82 100644 --- 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 @@ -20,19 +20,23 @@ 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; -import javax.validation.Valid; - public class Cmpv2Server { + @NotNull @Valid private Authentication authentication; + @NotNull private CaMode caMode; + @NotNull @Length(min = 1, max = 128) private String caName; + @NotNull private X500Name issuerDN; @Cmpv2URL private String url; diff --git a/certService/src/main/resources/application.properties b/certService/src/main/resources/application.properties index ac81c3a0..aac9b96f 100644 --- a/certService/src/main/resources/application.properties +++ b/certService/src/main/resources/application.properties @@ -3,7 +3,7 @@ springdoc.show-actuator=true management.endpoints.enabled-by-default=true management.endpoint.configprops.enabled=true -management.endpoints.web.exposure.include=refresh,health +management.endpoints.web.exposure.include=health # Swagger configuration diff --git a/certService/src/test/java/org/onap/aaf/certservice/api/CertificationServiceTest.java b/certService/src/test/java/org/onap/aaf/certservice/api/CertificationControllerTest.java index ee1ce1ef..2fc6d665 100644 --- a/certService/src/test/java/org/onap/aaf/certservice/api/CertificationServiceTest.java +++ b/certService/src/test/java/org/onap/aaf/certservice/api/CertificationControllerTest.java @@ -20,11 +20,21 @@ 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.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import com.google.gson.Gson; +import java.io.IOException; +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.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.onap.aaf.certservice.certification.CertificationModelFactory; import org.onap.aaf.certservice.certification.CsrModelFactory; import org.onap.aaf.certservice.certification.CsrModelFactory.StringBase64; @@ -36,20 +46,11 @@ import org.onap.aaf.certservice.certification.model.CsrModel; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import java.io.IOException; -import java.util.Arrays; - -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.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class CertificationServiceTest { +@ExtendWith(MockitoExtension.class) +class CertificationControllerTest { - private CertificationService certificationService; + private CertificationController certificationController; @Mock private CsrModelFactory csrModelFactory; @@ -58,9 +59,8 @@ class CertificationServiceTest { private CertificationModelFactory certificationModelFactory; @BeforeEach - void serUp() { - MockitoAnnotations.initMocks(this); - certificationService = new CertificationService(csrModelFactory, certificationModelFactory); + void setUp() { + certificationController = new CertificationController(csrModelFactory, certificationModelFactory); } @Test @@ -81,7 +81,7 @@ class CertificationServiceTest { // when ResponseEntity<String> testResponse = - certificationService.signCertificate(testCaName, "encryptedCSR", "encryptedPK"); + certificationController.signCertificate(testCaName, "encryptedCSR", "encryptedPK"); CertificationModel responseCertificationModel = new Gson().fromJson(testResponse.getBody(), CertificationModel.class); @@ -101,7 +101,7 @@ class CertificationServiceTest { // when Exception exception = assertThrows( - CsrDecryptionException.class, () -> certificationService. + CsrDecryptionException.class, () -> certificationController. signCertificate("TestCa", "encryptedCSR", "encryptedPK") ); @@ -120,7 +120,7 @@ class CertificationServiceTest { // when Exception exception = assertThrows( - KeyDecryptionException.class, () -> certificationService. + KeyDecryptionException.class, () -> certificationController. signCertificate("TestCa", "encryptedCSR", "encryptedPK") ); 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 new file mode 100644 index 00000000..17db24b8 --- /dev/null +++ b/certService/src/test/java/org/onap/aaf/certservice/api/ReloadConfigControllerTest.java @@ -0,0 +1,89 @@ +/* + * ============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.assertEquals; +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 + public void setUp() { + this.reloadConfigController = new ReloadConfigController(cmpServersConfig); + } + + @Test + public void shouldReturnStatusOkWhenSuccessfullyReloaded() throws CmpServersConfigLoadingException { + // When + ResponseEntity<String> response = reloadConfigController.reloadConfiguration(); + + // Then + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + + @Test + public 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); + } + + @Test + void shouldReturnErrorStatusAndMessageWhenExceptionOccurred() { + // Given + CmpServersConfigLoadingException exception = new CmpServersConfigLoadingException(ERROR_MESSAGE); + + // When + ResponseEntity<String> response = reloadConfigController.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/configuration/CmpServersConfigLoaderTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoaderTest.java index cf8c07a1..c78f6ceb 100644 --- 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 @@ -20,26 +20,26 @@ 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.context.annotation.PropertySource; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = CertServiceApplication.class) class CmpServersConfigLoaderTest { private static final String EXISTING_CONFIG_FILENAME = "cmpServers.json"; - private static final String NONEXISTING_CONFIG_FILENAME = "nonexisting_cmpServers.json"; + private static final String INVALID_CONFIG_FILENAME = "invalidCmpServers.json"; + private static final String NONEXISTENT_CONFIG_FILENAME = "nonExisting_cmpServers.json"; + private static final Map<String, String> EXPECTED_FIRST_CMP_SERVER = Map.of( "CA_NAME", "TEST", "URL", "http://127.0.0.1/ejbca/publicweb/cmp/cmp", @@ -61,9 +61,9 @@ class CmpServersConfigLoaderTest { private CmpServersConfigLoader configLoader; @Test - public void shouldLoadCmpServersConfigWhenFileAvailable() { + void shouldLoadCmpServersConfigWhenFileAvailable() throws CmpServersConfigLoadingException { // Given - String path = getClass().getClassLoader().getResource(EXISTING_CONFIG_FILENAME).getFile(); + String path = getResourcePath(EXISTING_CONFIG_FILENAME); // When List<Cmpv2Server> cmpServers = configLoader.load(path); @@ -75,14 +75,33 @@ class CmpServersConfigLoaderTest { verifyThatCmpServerEquals(cmpServers.get(1), EXPECTED_SECOND_CMP_SERVER); } - @Test() - public void shouldReturnEmptyListWhenFileMissing() { + @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 - List<Cmpv2Server> cmpServers = configLoader.load(NONEXISTING_CONFIG_FILENAME); + Exception exception = assertThrows( + CmpServersConfigLoadingException.class, + () -> configLoader.load(path)); // Then - assertThat(cmpServers).isNotNull(); - assertThat(cmpServers).isEmpty(); + assertThat(exception.getMessage()).contains("Validation of CMPv2 servers configuration failed"); + } + + private String getResourcePath(String invalidConfigFilename) { + return getClass().getClassLoader().getResource(invalidConfigFilename).getFile(); } private void verifyThatCmpServerEquals(Cmpv2Server cmpv2Server, Map<String, String> expected) { 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 index 43094f09..5d850fe9 100644 --- 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 @@ -20,54 +20,167 @@ 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.onap.aaf.certservice.CertServiceApplication; +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.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.startsWith; -@ExtendWith(SpringExtension.class) -@ContextConfiguration(classes = CertServiceApplication.class) -@TestPropertySource(properties = {"app.config.path=/fake/path/to/config"}) +@ExtendWith(MockitoExtension.class) class CmpServersConfigTest { - private static final List<Cmpv2Server> SAMPLE_CMP_SERVERS = List.of( - new Cmpv2Server(), - new Cmpv2Server() - ); + 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<Cmpv2Server> SAMPLE_CMP_SERVERS = generateTestConfiguration(); - @MockBean + @Mock private CmpServersConfigLoader cmpServersConfigLoader; - @Autowired private CmpServersConfig cmpServersConfig; + @BeforeEach + void setUp() { + cmpServersConfig = new CmpServersConfig(APP_CONFIG_PATH, cmpServersConfigLoader); + } + @Test - public void shouldCallLoaderWithPathFromPropertiesWhenCreated() { - Mockito.verify(cmpServersConfigLoader).load(startsWith("/fake/path/to/config")); + void shouldCallLoaderWithPathFromPropertiesWhenCreated() throws CmpServersConfigLoadingException { + // When + this.cmpServersConfig.init(); // Manual PostConstruct call + + // Then + Mockito.verify(cmpServersConfigLoader).load(startsWith(APP_CONFIG_PATH)); } @Test - public void shouldReturnLoadedServersWhenGetCalled() { + void shouldReturnLoadedServersWhenGetCalled() throws CmpServersConfigLoadingException { // Given Mockito.when(cmpServersConfigLoader.load(any())).thenReturn(SAMPLE_CMP_SERVERS); - this.cmpServersConfig.loadConfiguration(); // Manual PostConstruct call + this.cmpServersConfig.init(); // Manual PostConstruct call // When List<Cmpv2Server> receivedCmpServers = this.cmpServersConfig.getCmpServers(); // Then - assertThat(receivedCmpServers).hasSize(SAMPLE_CMP_SERVERS.size()); + assertThat(receivedCmpServers).containsAll(SAMPLE_CMP_SERVERS); } -}
\ No newline at end of file + + @Test + void shouldReturnLoadedServersAfterReloadWhenGetCalled() throws CmpServersConfigLoadingException { + // Given + Mockito.when(cmpServersConfigLoader.load(any())).thenReturn(SAMPLE_CMP_SERVERS); + List<Cmpv2Server> 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<Cmpv2Server> 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); + } + + private static List<Cmpv2Server> 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/validation/Cmpv2ServerConfigurationValidatorTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServerConfigurationValidatorTest.java index 18097608..10a7ba46 100644 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServerConfigurationValidatorTest.java +++ b/certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServerConfigurationValidatorTest.java @@ -20,6 +20,9 @@ package org.onap.aaf.certservice.certification.configuration.validation; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + import org.bouncycastle.asn1.x500.X500Name; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -32,13 +35,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; - @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = CertServiceApplication.class) class Cmpv2ServerConfigurationValidatorTest { + private static final String EMPTY_STRING = ""; + @Autowired private Cmpv2ServerConfigurationValidator validator; @@ -52,53 +54,121 @@ class Cmpv2ServerConfigurationValidatorTest { } @Test - public void givenValidServerDetailsWhenValidatingShouldNotThrowAnyException() { - //then + public void shouldNotThrowExceptionWhenServerConfigurationIsValid() { + // Then assertDoesNotThrow(() -> validator.validate(server)); } @Test - public void givenWrongProtocolInURLServerDetailsWhenValidatingShouldThrowException() { - //given + public void shouldThrowExceptionWhenWrongProtocolInURL() { + // Given server.setUrl("https://test.test.test:60000/"); - //then - assertThrows(IllegalArgumentException.class, () -> {validator.validate(server);}); + // Then + assertExceptionIsThrown(); } @Test - public void givenWrongPortInURLServerDetailsWhenValidatingShouldThrowException() { - //given + public void shouldThrowExceptionWhenWrongPortInURL() { + // Given server.setUrl("http://test.test.test:70000/"); - //then - assertThrows(IllegalArgumentException.class, () -> validator.validate(server)); + // Then + assertExceptionIsThrown(); } @Test - public void givenWrongCANameLengthInURLServerDetailsWhenValidatingShouldThrowException() { - //given - server.setCaName(""); + public void shouldThrowExceptionWhenWrongCANameLength() { + // Given + server.setCaName(EMPTY_STRING); - //then - assertThrows(IllegalArgumentException.class, () -> validator.validate(server)); + // Then + assertExceptionIsThrown(); } @Test - public void givenWrongRVLengthInURLServerDetailsWhenValidatingShouldThrowException() { - //given - authentication.setRv(""); + public void shouldThrowExceptionWhenWrongRVLength() { + // Given + authentication.setRv(EMPTY_STRING); - //then - assertThrows(IllegalArgumentException.class, () -> validator.validate(server)); + // Then + assertExceptionIsThrown(); } + @Test - public void givenWrongIAKLengthInURLServerDetailsWhenValidatingShouldThrowException() { - //given - authentication.setIak(""); + public void shouldThrowExceptionWhenWrongIAKLength() { + // Given + authentication.setIak(EMPTY_STRING); + + // Then + assertExceptionIsThrown(); + } + + @Test + public void shouldThrowExceptionWhenCaNameIsNull() { + // Given + server.setCaName(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + public void shouldThrowExceptionWhenIssuerDnIsNull() { + // Given + server.setIssuerDN(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + public void shouldThrowExceptionWhenCaModeIsNull() { + // Given + server.setCaMode(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + public void shouldThrowExceptionWhenUrlIsNull() { + // Given + server.setUrl(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + public void shouldThrowExceptionWhenAuthenticationIsNull() { + // Given + server.setAuthentication(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + public void shouldThrowExceptionWhenIakIsNull() { + // Given + authentication.setIak(null); + + // Then + assertExceptionIsThrown(); + } + + @Test + public void shouldThrowExceptionWhenRvIsNull() { + // Given + authentication.setRv(null); + + // Then + assertExceptionIsThrown(); + } - //then + private void assertExceptionIsThrown() { assertThrows(IllegalArgumentException.class, () -> validator.validate(server)); } 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 index a2a03860..78368d8a 100644 --- 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 @@ -27,7 +27,7 @@ import static org.junit.jupiter.api.Assertions.*; class Cmpv2URLValidatorTest { - private Cmpv2URLValidator validator = new Cmpv2URLValidator(); + private final Cmpv2URLValidator validator = new Cmpv2URLValidator(); @Test public void givenCorrectURLWhenValidatingShouldReturnTrue() { 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 index 8ae4cd88..d1850473 100644 --- 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 @@ -27,7 +27,7 @@ import static org.junit.jupiter.api.Assertions.*; class PortNumberViolationTest { - private PortNumberViolation violation = new PortNumberViolation(); + private final PortNumberViolation violation = new PortNumberViolation(); @Test public void givenValidPortShouldReturnTrue() { 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 index 9e220560..cba2f340 100644 --- 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 @@ -26,7 +26,7 @@ import static org.junit.jupiter.api.Assertions.*; class RequestTypeViolationTest { - private RequestTypeViolation violation = new RequestTypeViolation(); + private final RequestTypeViolation violation = new RequestTypeViolation(); @Test public void givenValidRequestTypeShouldReturnTrue() { diff --git a/certService/src/test/resources/application.properties b/certService/src/test/resources/application.properties new file mode 100644 index 00000000..39001571 --- /dev/null +++ b/certService/src/test/resources/application.properties @@ -0,0 +1,2 @@ +# AAF CertService app specific configuration +app.config.path=./src/test/resources diff --git a/certService/src/test/resources/invalidCmpServers.json b/certService/src/test/resources/invalidCmpServers.json new file mode 100644 index 00000000..ac4b34af --- /dev/null +++ b/certService/src/test/resources/invalidCmpServers.json @@ -0,0 +1,19 @@ +{ + "cmpv2Servers": [ + { + "caName": " ", + "url": "http://127.0.0.1/ejbca/publicweb/cmp/cmp", + "issuerDN": "CN=ManagementCA", + "caMode": "CLIENT" + }, + { + "caName": "TEST2", + "url": "http://127.0.0.1/ejbca/publicweb/cmp/cmpRA", + "caMode": "RA", + "authentication": { + "iak": "xxx", + "rv": "yyy" + } + } + ] +}
\ No newline at end of file diff --git a/certServiceClient/pom.xml b/certServiceClient/pom.xml index 5392163c..4b7c0cf9 100644 --- a/certServiceClient/pom.xml +++ b/certServiceClient/pom.xml @@ -146,16 +146,16 @@ <artifactId>bcpkix-jdk15on</artifactId> </dependency> <dependency> - <groupId>org.assertj</groupId> - <artifactId>assertj-core</artifactId> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> </dependency> <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-engine</artifactId> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-api</artifactId> + <artifactId>junit-jupiter</artifactId> </dependency> <dependency> <groupId>org.mockito</groupId> @@ -173,6 +173,14 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + </dependency> </dependencies> </project>
\ No newline at end of file diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/CertServiceClient.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/CertServiceClient.java index f8867846..d3d7f26d 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/CertServiceClient.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/CertServiceClient.java @@ -19,22 +19,30 @@ package org.onap.aaf.certservice.client; +import java.security.KeyPair; import org.onap.aaf.certservice.client.api.ExitableException; +import org.onap.aaf.certservice.client.certification.PrivateKeyToPemEncoder; +import org.onap.aaf.certservice.client.certification.CsrFactory; import org.onap.aaf.certservice.client.certification.KeyPairFactory; +import org.onap.aaf.certservice.client.certification.conversion.KeystoreTruststoreCreator; +import org.onap.aaf.certservice.client.certification.conversion.KeystoreTruststoreCreatorFactory; +import org.onap.aaf.certservice.client.common.Base64Encoder; import org.onap.aaf.certservice.client.configuration.EnvsForClient; import org.onap.aaf.certservice.client.configuration.EnvsForCsr; import org.onap.aaf.certservice.client.configuration.factory.ClientConfigurationFactory; import org.onap.aaf.certservice.client.configuration.factory.CsrConfigurationFactory; import org.onap.aaf.certservice.client.configuration.model.ClientConfiguration; import org.onap.aaf.certservice.client.configuration.model.CsrConfiguration; - -import java.security.KeyPair; +import org.onap.aaf.certservice.client.httpclient.CloseableHttpClientProvider; +import org.onap.aaf.certservice.client.httpclient.HttpClient; +import org.onap.aaf.certservice.client.httpclient.model.CertServiceResponse; import static org.onap.aaf.certservice.client.api.ExitCode.SUCCESS_EXIT_CODE; import static org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants.KEY_SIZE; import static org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants.RSA_ENCRYPTION_ALGORITHM; public class CertServiceClient { + private AppExitHandler appExitHandler; public CertServiceClient(AppExitHandler appExitHandler) { @@ -43,14 +51,31 @@ public class CertServiceClient { public void run() { KeyPairFactory keyPairFactory = new KeyPairFactory(RSA_ENCRYPTION_ALGORITHM, KEY_SIZE); + PrivateKeyToPemEncoder pkEncoder = new PrivateKeyToPemEncoder(); + Base64Encoder base64Encoder = new Base64Encoder(); try { ClientConfiguration clientConfiguration = new ClientConfigurationFactory(new EnvsForClient()).create(); CsrConfiguration csrConfiguration = new CsrConfigurationFactory(new EnvsForCsr()).create(); KeyPair keyPair = keyPairFactory.create(); + CsrFactory csrFactory = new CsrFactory(csrConfiguration); + + CloseableHttpClientProvider provider = new CloseableHttpClientProvider( + clientConfiguration.getRequestTimeout()); + HttpClient httpClient = new HttpClient(provider, clientConfiguration.getUrlToCertService()); + + CertServiceResponse certServiceData = + httpClient.retrieveCertServiceData( + clientConfiguration.getCaName(), + base64Encoder.encode(csrFactory.createCsrInPem(keyPair)), + base64Encoder.encode(pkEncoder.encodePrivateKeyToPem(keyPair.getPrivate()))); + + KeystoreTruststoreCreator filesCreator = new KeystoreTruststoreCreatorFactory( + clientConfiguration.getCertsOutputPath()).create(); + filesCreator.createKeystore(certServiceData.getCertificateChain(), keyPair.getPrivate()); + filesCreator.createTruststore(certServiceData.getTrustedCertificates()); } catch (ExitableException e) { appExitHandler.exit(e.applicationExitCode()); } appExitHandler.exit(SUCCESS_EXIT_CODE.getValue()); } - } diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/api/ExitCode.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/api/ExitCode.java index 295738f4..670cbe90 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/api/ExitCode.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/api/ExitCode.java @@ -22,7 +22,12 @@ public enum ExitCode { SUCCESS_EXIT_CODE(0), CLIENT_CONFIGURATION_EXCEPTION(1), CSR_CONFIGURATION_EXCEPTION(2), - KEY_PAIR_GENERATION_EXCEPTION(3); + KEY_PAIR_GENERATION_EXCEPTION(3), + CSR_GENERATION_EXCEPTION(4), + CERT_SERVICE_API_CONNECTION_EXCEPTION(5), + HTTP_CLIENT_EXCEPTION(6), + PKCS12_CONVERSION_EXCEPTION(7), + PK_TO_PEM_ENCODING_EXCEPTION(8); private final int value; diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/api/ExitableException.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/api/ExitableException.java index 51981a48..f9166c96 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/api/ExitableException.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/api/ExitableException.java @@ -26,6 +26,5 @@ public abstract class ExitableException extends Exception { public ExitableException(String message) { super(message); } - public abstract int applicationExitCode(); } diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/CsrFactory.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/CsrFactory.java new file mode 100644 index 00000000..83fa6d44 --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/CsrFactory.java @@ -0,0 +1,154 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification; + +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +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.openssl.jcajce.JcaPEMWriter; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; + +import org.onap.aaf.certservice.client.certification.exception.CsrGenerationException; +import org.onap.aaf.certservice.client.configuration.model.CsrConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.security.auth.x500.X500Principal; +import java.io.IOException; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.security.KeyPair; +import java.util.Base64; +import java.util.Optional; + +import static org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants.COMMON_NAME; +import static org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants.COUNTRY; +import static org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants.LOCATION; +import static org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants.ORGANIZATION; +import static org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants.ORGANIZATION_UNIT; +import static org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants.SIGN_ALGORITHM; +import static org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants.STATE; + + +public class CsrFactory { + + private final Logger LOGGER = LoggerFactory.getLogger(CsrFactory.class); + private static final String SANS_DELIMITER = ":"; + private final CsrConfiguration configuration; + + + public CsrFactory(CsrConfiguration configuration) { + this.configuration = configuration; + } + + + public String createCsrInPem(KeyPair keyPair) throws CsrGenerationException { + PKCS10CertificationRequest request; + String csrParameters = getMandatoryParameters().append(getOptionalParameters()).toString(); + X500Principal subject = new X500Principal(csrParameters); + request = createPKCS10Csr(subject, keyPair); + return convertPKC10CsrToPem(request); + } + + + private StringBuilder getMandatoryParameters() { + return new StringBuilder(String.format("%s=%s, %s=%s, %s=%s, %s=%s", + COMMON_NAME, configuration.getCommonName(), + COUNTRY, configuration.getCountry(), + STATE, configuration.getState(), + ORGANIZATION, configuration.getOrganization())); + } + + private String getOptionalParameters() { + StringBuilder optionalParameters = new StringBuilder(); + Optional.ofNullable(configuration.getOrganizationUnit()) + .filter(CsrFactory::isParameterPresent) + .map(unit -> optionalParameters.append(String.format(", %s=%s", ORGANIZATION_UNIT, unit))); + Optional.ofNullable(configuration.getLocation()) + .filter(CsrFactory::isParameterPresent) + .map(location -> optionalParameters.append(String.format(", %s=%s", LOCATION, location))); + return optionalParameters.toString(); + } + + private PKCS10CertificationRequest createPKCS10Csr(X500Principal subject, KeyPair keyPair) throws CsrGenerationException { + JcaPKCS10CertificationRequestBuilder builder = new JcaPKCS10CertificationRequestBuilder(subject, keyPair.getPublic()); + + if (isParameterPresent(configuration.getSans())) { + builder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, generateSansExtension()); + } + + return builder.build(getContentSigner(keyPair)); + } + + private ContentSigner getContentSigner(KeyPair keyPair) throws CsrGenerationException { + ContentSigner contentSigner; + try { + contentSigner = new JcaContentSignerBuilder(SIGN_ALGORITHM).build(keyPair.getPrivate()); + } catch (OperatorCreationException e) { + LOGGER.error("Creation of PKCS10Csr failed, exception message: {}", e.getMessage()); + throw new CsrGenerationException(e); + + } + return contentSigner; + } + + private String convertPKC10CsrToPem(PKCS10CertificationRequest request) throws CsrGenerationException { + final StringWriter stringWriter = new StringWriter(); + try (JcaPEMWriter pemWriter = new JcaPEMWriter(stringWriter)) { + pemWriter.writeObject(request); + } catch (IOException e) { + LOGGER.error("Conversion to PEM failed, exception message: {}", e.getMessage()); + throw new CsrGenerationException(e); + } + return stringWriter.toString(); + } + + private Extensions generateSansExtension() throws CsrGenerationException { + ExtensionsGenerator generator = new ExtensionsGenerator(); + try { + generator.addExtension(Extension.subjectAlternativeName, false, createGeneralNames()); + } catch (IOException e) { + LOGGER.error("Generation of SANs parameter failed, exception message: {}", e.getMessage()); + throw new CsrGenerationException(e); + } + return generator.generate(); + } + + private GeneralNames createGeneralNames() { + String[] sansTable = this.configuration.getSans().split(SANS_DELIMITER); + int length = sansTable.length; + GeneralName[] generalNames = new GeneralName[length]; + for (int i = 0; i < length; i++) { + generalNames[i] = new GeneralName(GeneralName.dNSName, sansTable[i]); + } + return new GeneralNames(generalNames); + } + + private static Boolean isParameterPresent(String parameter) { + return parameter != null && !"".equals(parameter); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/EncryptionAlgorithmConstants.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/EncryptionAlgorithmConstants.java index 2afdbee0..96b3650c 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/EncryptionAlgorithmConstants.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/EncryptionAlgorithmConstants.java @@ -16,9 +16,22 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aaf.certservice.client.certification; -public class EncryptionAlgorithmConstants { +public final class EncryptionAlgorithmConstants { + + private EncryptionAlgorithmConstants() {} + public static final String RSA_ENCRYPTION_ALGORITHM = "RSA"; + public static final String SIGN_ALGORITHM = "SHA1withRSA"; public static final int KEY_SIZE = 2048; + + public static final String COMMON_NAME = "CN"; + public static final String ORGANIZATION = "O"; + public static final String ORGANIZATION_UNIT = "OU"; + public static final String LOCATION = "L"; + public static final String STATE = "ST"; + public static final String COUNTRY = "C"; + } diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/PrivateKeyToPemEncoder.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/PrivateKeyToPemEncoder.java new file mode 100644 index 00000000..77995958 --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/PrivateKeyToPemEncoder.java @@ -0,0 +1,51 @@ +/* + * ============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification; + + + +import java.io.IOException; +import java.io.StringWriter; +import java.security.PrivateKey; + +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; +import org.bouncycastle.util.io.pem.PemObject; +import org.onap.aaf.certservice.client.certification.exception.PkEncodingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PrivateKeyToPemEncoder { + + public static final String PEM_OBJECT_TYPE = "RSA PRIVATE KEY"; + private final Logger LOGGER = LoggerFactory.getLogger(PrivateKeyToPemEncoder.class); + + public String encodePrivateKeyToPem(PrivateKey pk) throws PkEncodingException { + LOGGER.info("Encoding PrivateKey to PEM"); + StringWriter stringWriter = new StringWriter(); + try (JcaPEMWriter pemWriter = new JcaPEMWriter(stringWriter)) { + pemWriter.writeObject(new PemObject(PEM_OBJECT_TYPE, pk.getEncoded())); + } catch (IOException e) { + LOGGER.error("Exception occurred during encoding PrivateKey to PEM", e); + throw new PkEncodingException(e); + } + return stringWriter.toString(); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreator.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreator.java new file mode 100644 index 00000000..6dc2ef87 --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreator.java @@ -0,0 +1,55 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +import java.security.PrivateKey; +import java.util.List; +import org.onap.aaf.certservice.client.certification.exception.PemToPKCS12ConverterException; + +public class KeystoreTruststoreCreator { + + private static final String CERTIFICATE_ALIAS = "certificate"; + private static final String TRUSTED_CERTIFICATE_ALIAS = "trusted-certificate-"; + private static final int PASSWORD_LENGTH = 24; + private final RandomPasswordGenerator generator; + private final PemToPKCS12Converter converter; + private final PKCS12FilesCreator creator; + + public KeystoreTruststoreCreator(PKCS12FilesCreator creator, RandomPasswordGenerator generator, + PemToPKCS12Converter converter) { + this.generator = generator; + this.converter = converter; + this.creator = creator; + } + + public void createKeystore(List<String> data, PrivateKey privateKey) + throws PemToPKCS12ConverterException { + Password password = generator.generate(PASSWORD_LENGTH); + creator.saveKeystoreData(converter.convertKeystore(data, password, CERTIFICATE_ALIAS, privateKey), + password.getPassword()); + } + + public void createTruststore(List<String> data) + throws PemToPKCS12ConverterException { + Password password = generator.generate(PASSWORD_LENGTH); + creator.saveTruststoreData(converter.convertTruststore(data, password, TRUSTED_CERTIFICATE_ALIAS), + password.getPassword()); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreatorFactory.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreatorFactory.java new file mode 100644 index 00000000..8c719535 --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreatorFactory.java @@ -0,0 +1,35 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +public class KeystoreTruststoreCreatorFactory { + private final String outputPath; + + public KeystoreTruststoreCreatorFactory(String outputPath) { + this.outputPath = outputPath; + } + + public KeystoreTruststoreCreator create() { + return new KeystoreTruststoreCreator( + new PKCS12FilesCreator(outputPath), + new RandomPasswordGenerator(), + new PemToPKCS12Converter()); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/PKCS12FilesCreator.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/PKCS12FilesCreator.java new file mode 100644 index 00000000..d8c41bfd --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/PKCS12FilesCreator.java @@ -0,0 +1,73 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; + +import org.onap.aaf.certservice.client.certification.exception.PemToPKCS12ConverterException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class PKCS12FilesCreator { + + private static final String KEYSTORE_JKS = "keystore.jks"; + private static final String KEYSTORE_PASS = "keystore.pass"; + private static final String TRUSTSTORE_JKS = "truststore.jks"; + private static final String TRUSTSTORE_PASS = "truststore.pass"; + private final String keystoreJksPath; + private final String keystorePassPath; + private final String truststoreJksPath; + private final String truststorePassPath; + private final Logger LOGGER = LoggerFactory.getLogger(PKCS12FilesCreator.class); + + + PKCS12FilesCreator(String path) { + keystoreJksPath = Path.of(path, KEYSTORE_JKS).toString(); + keystorePassPath = Path.of(path, KEYSTORE_PASS).toString(); + truststoreJksPath = Path.of(path, TRUSTSTORE_JKS).toString(); + truststorePassPath = Path.of(path, TRUSTSTORE_PASS).toString(); + } + + void saveKeystoreData(byte[] keystoreData, String keystorePassword) throws PemToPKCS12ConverterException { + LOGGER.debug("Creating PKCS12 keystore files and saving data. Keystore path: {}", keystoreJksPath); + + saveDataToLocation(keystoreData, keystoreJksPath); + saveDataToLocation(keystorePassword.getBytes(), keystorePassPath); + } + + void saveTruststoreData(byte[] truststoreData, String truststorePassword) + throws PemToPKCS12ConverterException { + LOGGER.debug("Creating PKCS12 truststore files and saving data. Truststore path: {}", truststoreJksPath); + + saveDataToLocation(truststoreData, truststoreJksPath); + saveDataToLocation(truststorePassword.getBytes(), truststorePassPath); + } + + private void saveDataToLocation(byte[] data, String path) throws PemToPKCS12ConverterException { + try (FileOutputStream fos = new FileOutputStream(path)) { + fos.write(data); + } catch (IOException e) { + LOGGER.error("PKCS12 files creation failed", e); + throw new PemToPKCS12ConverterException(e); + } + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/Password.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/Password.java new file mode 100644 index 00000000..f0ee419c --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/Password.java @@ -0,0 +1,42 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +class Password { + private final static String PASSWORD_PATTERN = "[\\w$#]{16,}"; + private final String password; + + Password(String password) { + this.password = password; + } + + String getPassword() { + return password; + } + + char[] toCharArray() { + return password.toCharArray(); + } + + boolean isCorrectPasswordPattern() { + return password.matches(PASSWORD_PATTERN); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/PemToPKCS12Converter.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/PemToPKCS12Converter.java new file mode 100644 index 00000000..eab9bf7c --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/PemToPKCS12Converter.java @@ -0,0 +1,133 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.StringReader; +import java.security.KeyStore; +import java.security.KeyStore.LoadStoreParameter; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.util.List; +import java.util.Optional; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMParser; +import org.onap.aaf.certservice.client.certification.exception.PemToPKCS12ConverterException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class PemToPKCS12Converter { + + private final static String PKCS12 = "PKCS12"; + private final static String PASSWORD_ERROR_MSG = "Password should be min. 16 chars long and should contain only alphanumeric characters and special characters like Underscore (_), Dollar ($) and Pound (#)"; + private final LoadStoreParameter EMPTY_KEYSTORE_CONFIGURATION = null; + private final Logger LOGGER = LoggerFactory.getLogger(PemToPKCS12Converter.class); + + byte[] convertKeystore(List<String> certificateChain, Password password, String alias, PrivateKey privateKey) + throws PemToPKCS12ConverterException { + LOGGER.debug("Converting PEM certificates to PKCS12 keystore."); + return convert(certificateChain, password, certs -> getKeyStore(alias, password, certs, privateKey)); + } + + byte[] convertTruststore(List<String> trustAnchors, Password password, String alias) + throws PemToPKCS12ConverterException { + LOGGER.debug("Converting PEM certificates to PKCS12 truststore."); + return convert(trustAnchors, password, certs -> getTrustStore(alias, certs)); + } + + private byte[] convert(List<String> certificates, Password password, StoreEntryOperation operation) + throws PemToPKCS12ConverterException { + checkPassword(password); + final Certificate[] X509Certificates = convertToCertificateArray(certificates); + return getKeyStoreBytes(password, operation, X509Certificates); + } + + private void checkPassword(Password password) throws PemToPKCS12ConverterException { + if (!password.isCorrectPasswordPattern()) { + LOGGER.error(PASSWORD_ERROR_MSG); + throw new PemToPKCS12ConverterException(PASSWORD_ERROR_MSG); + } + } + + private byte[] getKeyStoreBytes(Password password, StoreEntryOperation op, Certificate[] x509Certificates) + throws PemToPKCS12ConverterException { + try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { + KeyStore ks = op.getStore(x509Certificates); + ks.store(bos, password.toCharArray()); + return bos.toByteArray(); + } catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException e) { + LOGGER.error("Pem to PKCS12 converter failed", e); + throw new PemToPKCS12ConverterException(e); + } + } + + private KeyStore getKeyStore(String alias, Password password, Certificate[] certificates, PrivateKey privateKey) + throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { + KeyStore ks = getKeyStoreInstance(); + ks.setKeyEntry(alias, privateKey, password.toCharArray(), certificates); + return ks; + } + + private KeyStore getTrustStore(String alias, Certificate[] certificates) + throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { + KeyStore ks = getKeyStoreInstance(); + long i = 1L; + for (Certificate c : certificates) { + ks.setCertificateEntry(alias + i++, c); + } + return ks; + } + + private KeyStore getKeyStoreInstance() + throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { + KeyStore ks = KeyStore.getInstance(PKCS12); + ks.load(EMPTY_KEYSTORE_CONFIGURATION); + return ks; + } + + private Certificate[] convertToCertificateArray(List<String> certificates) + throws PemToPKCS12ConverterException { + Certificate[] parsedCertificates = new Certificate[certificates.size()]; + for (String certificate : certificates) { + parsedCertificates[certificates.indexOf(certificate)] = parseCertificate(certificate); + } + return parsedCertificates; + } + + private Certificate parseCertificate(String certificate) throws PemToPKCS12ConverterException { + try (PEMParser pem = new PEMParser(new StringReader(certificate))) { + X509CertificateHolder certHolder = Optional.ofNullable((X509CertificateHolder) pem.readObject()) + .orElseThrow( + () -> new PemToPKCS12ConverterException("The certificate couldn't be parsed correctly. " + certificate)); + return new JcaX509CertificateConverter() + .setProvider(new BouncyCastleProvider()) + .getCertificate(certHolder); + } catch (IOException | CertificateException e) { + LOGGER.error("Certificates conversion failed", e); + throw new PemToPKCS12ConverterException(e); + } + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/RandomPasswordGenerator.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/RandomPasswordGenerator.java new file mode 100644 index 00000000..5db7b26f --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/RandomPasswordGenerator.java @@ -0,0 +1,47 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +import java.security.SecureRandom; +import org.apache.commons.lang3.RandomStringUtils; + +class RandomPasswordGenerator { + + private static final String ALPHA = "abcdefghijklmnopqrstuvwxyz"; + private static final String NUMBERS = "0123456789"; + private static final String SPECIAL_CHARS = "_$#"; + private static final char[] SET_OF_CHARS = (ALPHA + ALPHA.toUpperCase() + NUMBERS + SPECIAL_CHARS).toCharArray(); + private static final char START_POSITION_IN_ASCII_CHARS = 0; + private static final char END_POSITION_IN_ASCII_CHARS = 0; + private static final boolean USE_LETTERS_ONLY = false; + private static final boolean USE_NUMBERS_ONLY = false; + + Password generate(int passwordLength) { + return new Password(RandomStringUtils.random( + passwordLength, + START_POSITION_IN_ASCII_CHARS, + END_POSITION_IN_ASCII_CHARS, + USE_LETTERS_ONLY, + USE_NUMBERS_ONLY, + SET_OF_CHARS, + new SecureRandom())); + } +} + diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/StoreEntryOperation.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/StoreEntryOperation.java new file mode 100644 index 00000000..6ee7817b --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/conversion/StoreEntryOperation.java @@ -0,0 +1,34 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; + +@FunctionalInterface +public interface StoreEntryOperation { + + KeyStore getStore(Certificate[] certificates) + throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException; +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/exception/CsrGenerationException.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/exception/CsrGenerationException.java new file mode 100644 index 00000000..c1d4afd2 --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/exception/CsrGenerationException.java @@ -0,0 +1,35 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.exception; + +import org.onap.aaf.certservice.client.api.ExitCode; +import org.onap.aaf.certservice.client.api.ExitableException; + +public class CsrGenerationException extends ExitableException { + private static final ExitCode EXIT_CODE = ExitCode.CSR_GENERATION_EXCEPTION; + + public CsrGenerationException(Throwable e) { + super(e); + } + + public int applicationExitCode() { + return EXIT_CODE.getValue(); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/exception/PemToPKCS12ConverterException.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/exception/PemToPKCS12ConverterException.java new file mode 100644 index 00000000..87020d6f --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/exception/PemToPKCS12ConverterException.java @@ -0,0 +1,39 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.exception; + +import org.onap.aaf.certservice.client.api.ExitCode; +import org.onap.aaf.certservice.client.api.ExitableException; + +public class PemToPKCS12ConverterException extends ExitableException { + private static final ExitCode EXIT_CODE = ExitCode.PKCS12_CONVERSION_EXCEPTION; + + public PemToPKCS12ConverterException(Throwable e) { + super(e); + } + public PemToPKCS12ConverterException(String message) { + super(message); + } + + @Override + public int applicationExitCode() { + return EXIT_CODE.getValue(); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/exception/PkEncodingException.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/exception/PkEncodingException.java new file mode 100644 index 00000000..596a6a44 --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/certification/exception/PkEncodingException.java @@ -0,0 +1,35 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.exception; + +import org.onap.aaf.certservice.client.api.ExitCode; +import org.onap.aaf.certservice.client.api.ExitableException; + +public class PkEncodingException extends ExitableException { + private static final ExitCode EXIT_CODE = ExitCode.PK_TO_PEM_ENCODING_EXCEPTION; + + public PkEncodingException(Throwable e) { + super(e); + } + + public int applicationExitCode() { + return EXIT_CODE.getValue(); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/common/Base64Encoder.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/common/Base64Encoder.java new file mode 100644 index 00000000..1f90db1b --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/common/Base64Encoder.java @@ -0,0 +1,28 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.common; + +import org.bouncycastle.util.encoders.Base64; + +public class Base64Encoder { + public String encode(String string){ + return new String(Base64.encode(string.getBytes())); + } +}
\ No newline at end of file diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvProvider.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvProvider.java index beccd383..25a152bf 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvProvider.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvProvider.java @@ -19,8 +19,15 @@ */ package org.onap.aaf.certservice.client.configuration; +import java.util.Optional; + public class EnvProvider { - public String readEnvVariable(String envVariable) { - return System.getProperty(envVariable); + public Optional<String> readEnvVariable(String envVariableName) { + return Optional.ofNullable(System.getenv(envVariableName)) + .filter(EnvProvider::isEnvPresent); + } + + private static Boolean isEnvPresent(String envValue) { + return !"".equals(envValue); } } diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvValidationUtils.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvValidationUtils.java index b87df5be..b0405274 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvValidationUtils.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvValidationUtils.java @@ -27,17 +27,13 @@ public final class EnvValidationUtils { private EnvValidationUtils() {} public static Boolean isPathValid(String path) { - return path.matches("^/|(/[a-zA-Z0-9_-]+)+$"); + return path.matches("^/|(/[a-zA-Z0-9_-]+)+/?$"); } public static Boolean isAlphaNumeric(String caName) { return caName.matches("^[a-zA-Z0-9]*$"); } - public static Boolean isEnvExists(String envValue) { - return envValue != null && !"".equals(envValue); - } - public static Boolean isCountryValid(String country) { return country.matches("^([A-Z][A-Z])$"); } diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvsForClient.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvsForClient.java index aad64f5b..1ce76370 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvsForClient.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvsForClient.java @@ -19,33 +19,31 @@ */ package org.onap.aaf.certservice.client.configuration; +import java.util.Optional; + public class EnvsForClient { - private static final EnvProvider envProvider = new EnvProvider(); - private final String urlToCertService; - private final String requestTimeOut; - private final String outputPath; - private final String caName; + private final EnvProvider envProvider = new EnvProvider(); public EnvsForClient() { - this.urlToCertService = envProvider.readEnvVariable(ClientConfigurationEnvs.REQUEST_URL.toString()); - this.requestTimeOut = envProvider.readEnvVariable(ClientConfigurationEnvs.REQUEST_TIMEOUT.toString()); - this.outputPath = envProvider.readEnvVariable(ClientConfigurationEnvs.OUTPUT_PATH.toString()); - this.caName = envProvider.readEnvVariable(ClientConfigurationEnvs.CA_NAME.toString()); } - public String getUrlToCertService() { - return urlToCertService; + public Optional<String> getUrlToCertService() { + return readEnv(ClientConfigurationEnvs.REQUEST_URL); + } + + public Optional<String> getRequestTimeOut() { + return readEnv(ClientConfigurationEnvs.REQUEST_TIMEOUT); } - public String getRequestTimeOut() { - return requestTimeOut; + public Optional<String> getOutputPath() { + return readEnv(ClientConfigurationEnvs.OUTPUT_PATH); } - public String getOutputPath() { - return outputPath; + public Optional<String> getCaName() { + return readEnv(ClientConfigurationEnvs.CA_NAME); } - public String getCaName() { - return caName; + private Optional<String> readEnv(ClientConfigurationEnvs envName) { + return envProvider.readEnvVariable(envName.toString()); } } diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvsForCsr.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvsForCsr.java index 0c948d3f..77efc198 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvsForCsr.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/EnvsForCsr.java @@ -19,52 +19,42 @@ */ package org.onap.aaf.certservice.client.configuration; +import java.util.Optional; public class EnvsForCsr { private final EnvProvider envProvider = new EnvProvider(); - private String commonName; - private String organization; - private String organizationUnit; - private String location; - private String state; - private String country; - private String subjectAlternativesName; - public EnvsForCsr() { - this.commonName = envProvider.readEnvVariable(CsrConfigurationEnvs.COMMON_NAME.toString()); - this.organization = envProvider.readEnvVariable(CsrConfigurationEnvs.ORGANIZATION.toString()); - this.organizationUnit = envProvider.readEnvVariable(CsrConfigurationEnvs.ORGANIZATION_UNIT.toString()); - this.location = envProvider.readEnvVariable(CsrConfigurationEnvs.LOCATION.toString()); - this.state = envProvider.readEnvVariable(CsrConfigurationEnvs.STATE.toString()); - this.country = envProvider.readEnvVariable(CsrConfigurationEnvs.COUNTRY.toString()); - this.subjectAlternativesName = envProvider.readEnvVariable(CsrConfigurationEnvs.SANS.toString()); + public EnvsForCsr() {} + + public Optional<String> getCommonName() { + return readEnv(CsrConfigurationEnvs.COMMON_NAME); } - public String getCommonName() { - return commonName; + public Optional<String> getOrganization() { + return readEnv(CsrConfigurationEnvs.ORGANIZATION); } - public String getOrganization() { - return organization; + public Optional<String> getOrganizationUnit() { + return readEnv(CsrConfigurationEnvs.ORGANIZATION_UNIT); } - public String getOrganizationUnit() { - return organizationUnit; + public Optional<String> getLocation() { + return readEnv(CsrConfigurationEnvs.LOCATION); } - public String getLocation() { - return location; + public Optional<String> getState() { + return readEnv(CsrConfigurationEnvs.STATE); } - public String getState() { - return state; + public Optional<String> getCountry() { + return readEnv(CsrConfigurationEnvs.COUNTRY); } - public String getCountry() { - return country; + public Optional<String> getSubjectAlternativesName() { + return readEnv(CsrConfigurationEnvs.SANS); } - public String getSubjectAlternativesName() { - return subjectAlternativesName; + private Optional<String> readEnv(CsrConfigurationEnvs envName) { + return envProvider.readEnvVariable(envName.toString()); } } diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/factory/ClientConfigurationFactory.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/factory/ClientConfigurationFactory.java index 96b1fb8b..3bd15288 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/factory/ClientConfigurationFactory.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/factory/ClientConfigurationFactory.java @@ -20,14 +20,15 @@ package org.onap.aaf.certservice.client.configuration.factory; + + +import java.util.Optional; import org.onap.aaf.certservice.client.configuration.ClientConfigurationEnvs; import org.onap.aaf.certservice.client.configuration.EnvValidationUtils; import org.onap.aaf.certservice.client.configuration.EnvsForClient; import org.onap.aaf.certservice.client.configuration.exception.ClientConfigurationException; import org.onap.aaf.certservice.client.configuration.model.ClientConfiguration; -import java.util.Optional; - public class ClientConfigurationFactory implements AbstractConfigurationFactory<ClientConfiguration> { private final EnvsForClient envsForClient; @@ -42,18 +43,18 @@ public class ClientConfigurationFactory implements AbstractConfigurationFactory< ClientConfiguration configuration = new ClientConfiguration(); - Optional.ofNullable(envsForClient.getUrlToCertService()).filter(EnvValidationUtils::isEnvExists) + envsForClient.getUrlToCertService() .map(configuration::setUrlToCertService); - Optional.ofNullable(envsForClient.getRequestTimeOut()).filter(EnvValidationUtils::isEnvExists) + envsForClient.getRequestTimeOut() .map(timeout -> configuration.setRequestTimeout(Integer.valueOf(timeout))); - Optional.ofNullable(envsForClient.getOutputPath()).filter(EnvValidationUtils::isEnvExists) + envsForClient.getOutputPath() .filter(EnvValidationUtils::isPathValid) .map(configuration::setCertsOutputPath) .orElseThrow(() -> new ClientConfigurationException(ClientConfigurationEnvs.OUTPUT_PATH + " is invalid.")); - Optional.ofNullable(envsForClient.getCaName()).filter(EnvValidationUtils::isEnvExists) + envsForClient.getCaName() .filter(EnvValidationUtils::isAlphaNumeric) .map(configuration::setCaName) .orElseThrow(() -> new ClientConfigurationException(ClientConfigurationEnvs.CA_NAME + " is invalid.")); diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/factory/CsrConfigurationFactory.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/factory/CsrConfigurationFactory.java index 61e1b3c3..1e5d5c53 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/factory/CsrConfigurationFactory.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/factory/CsrConfigurationFactory.java @@ -43,32 +43,32 @@ public class CsrConfigurationFactory implements AbstractConfigurationFactory<Csr CsrConfiguration configuration = new CsrConfiguration(); - Optional.ofNullable(envsForCsr.getCommonName()).filter(EnvValidationUtils::isEnvExists) + envsForCsr.getCommonName() .filter(EnvValidationUtils::isCommonNameValid) .map(configuration::setCommonName) .orElseThrow(() -> new CsrConfigurationException(CsrConfigurationEnvs.COMMON_NAME + " is invalid.")); - Optional.ofNullable(envsForCsr.getOrganization()).filter(EnvValidationUtils::isEnvExists) + envsForCsr.getOrganization() .filter(org -> !EnvValidationUtils.isSpecialCharsPresent(org)) .map(configuration::setOrganization) .orElseThrow(() -> new CsrConfigurationException(CsrConfigurationEnvs.ORGANIZATION + " is invalid.")); - Optional.ofNullable(envsForCsr.getState()).filter(EnvValidationUtils::isEnvExists) + envsForCsr.getState() .map(configuration::setState) .orElseThrow(() -> new CsrConfigurationException(CsrConfigurationEnvs.STATE + " is invalid.")); - Optional.ofNullable(envsForCsr.getCountry()).filter(EnvValidationUtils::isEnvExists) + envsForCsr.getCountry() .filter(EnvValidationUtils::isCountryValid) .map(configuration::setCountry) .orElseThrow(() -> new CsrConfigurationException(CsrConfigurationEnvs.COUNTRY + " is invalid.")); - Optional.ofNullable(envsForCsr.getOrganizationUnit()).filter(EnvValidationUtils::isEnvExists) + envsForCsr.getOrganizationUnit() .map(configuration::setOrganizationUnit); - Optional.ofNullable(envsForCsr.getLocation()).filter(EnvValidationUtils::isEnvExists) + envsForCsr.getLocation() .map(configuration::setLocation); - Optional.ofNullable(envsForCsr.getSubjectAlternativesName()).filter(EnvValidationUtils::isEnvExists) + envsForCsr.getSubjectAlternativesName() .map(configuration::setSubjectAlternativeNames); return configuration; diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/model/CsrConfiguration.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/model/CsrConfiguration.java index 30caf42a..aaaf10fa 100644 --- a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/model/CsrConfiguration.java +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/configuration/model/CsrConfiguration.java @@ -29,7 +29,7 @@ public class CsrConfiguration implements ConfigurationModel { private String country; private String organizationUnit; private String location; - private String subjectAlternativeNames; + private String sans; public String getCommonName() { @@ -86,12 +86,12 @@ public class CsrConfiguration implements ConfigurationModel { return this; } - public String getSubjectAlternativeNames() { - return subjectAlternativeNames; + public String getSans() { + return sans; } public CsrConfiguration setSubjectAlternativeNames(String subjectAlternativeNames) { - this.subjectAlternativeNames = subjectAlternativeNames; + this.sans = subjectAlternativeNames; return this; } } diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/CloseableHttpClientProvider.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/CloseableHttpClientProvider.java new file mode 100644 index 00000000..ff29a14d --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/CloseableHttpClientProvider.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.httpclient; + +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; + +public class CloseableHttpClientProvider { + + private final int timeout; + + public CloseableHttpClientProvider(int timeout) { + this.timeout = timeout; + } + + public CloseableHttpClient getClient() { + RequestConfig config = + RequestConfig.custom().setConnectionRequestTimeout(timeout).build(); + return HttpClientBuilder.create().setDefaultRequestConfig(config).build(); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/HttpClient.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/HttpClient.java new file mode 100644 index 00000000..30f881bb --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/HttpClient.java @@ -0,0 +1,117 @@ +/* + * ============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.httpclient; + +import com.google.gson.Gson; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.onap.aaf.certservice.client.httpclient.exception.CertServiceApiResponseException; +import org.onap.aaf.certservice.client.httpclient.exception.HttpClientException; +import org.onap.aaf.certservice.client.httpclient.model.CertServiceResponse; +import org.onap.aaf.certservice.client.httpclient.model.ErrorCertServiceResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +public class HttpClient { + + private static final String CSR_HEADER_NAME = "CSR"; + private static final String PK_HEADER_NAME = "PK"; + private static final String CHARSET_UTF_8 = "UTF-8"; + + private final Logger LOGGER = LoggerFactory.getLogger(HttpClient.class); + + private final Gson gson = new Gson(); + private final CloseableHttpClientProvider httpClientProvider; + private final String certServiceAddress; + + public HttpClient(CloseableHttpClientProvider httpClientProvider, String certServiceAddress) { + this.httpClientProvider = httpClientProvider; + this.certServiceAddress = certServiceAddress; + } + + public CertServiceResponse retrieveCertServiceData(String caName, String csr, String encodedPk) + throws CertServiceApiResponseException, HttpClientException { + + try (CloseableHttpClient httpClient = httpClientProvider.getClient()) { + LOGGER.info("Sending request to API. Url: {}{} ", certServiceAddress, caName); + HttpResponse httpResponse = httpClient.execute(createHttpRequest(caName, csr, encodedPk)); + LOGGER.info("Received response from API"); + return extractCertServiceResponse(httpResponse); + + } catch (IOException e) { + LOGGER.error("Failed execute request to API for URL: {}{} . Exception message: {}", + certServiceAddress, caName, e.getMessage()); + throw new HttpClientException(e); + } + } + + private int getStatusCode(HttpResponse httpResponse) { + return httpResponse.getStatusLine().getStatusCode(); + } + + private CertServiceResponse extractCertServiceResponse(HttpResponse httpResponse) + throws CertServiceApiResponseException, HttpClientException { + int httpResponseCode = getStatusCode(httpResponse); + if (HttpStatus.SC_OK != httpResponseCode) { + LOGGER.error("Error on API response. Response Code: {}", httpResponseCode); + throw generateApiResponseException(httpResponse); + } + String jsonResponse = getStringResponse(httpResponse.getEntity()); + return gson.fromJson(jsonResponse, CertServiceResponse.class); + } + + private String getStringResponse(HttpEntity httpEntity) throws HttpClientException { + try { + return EntityUtils.toString(httpEntity, CHARSET_UTF_8); + } catch (IOException e) { + LOGGER.error("Cannot parse response to string", e); + throw new HttpClientException(e); + } + } + + private HttpGet createHttpRequest(String caName, String csr, String pk) { + String url = certServiceAddress + caName; + HttpGet httpGet = new HttpGet(url); + httpGet.addHeader(CSR_HEADER_NAME, csr); + httpGet.addHeader(PK_HEADER_NAME, pk); + return httpGet; + } + + + private CertServiceApiResponseException generateApiResponseException(HttpResponse httpResponse) + throws HttpClientException { + String stringResponse = getStringResponse(httpResponse.getEntity()); + ErrorCertServiceResponse errorCertServiceResponse = + gson.fromJson(stringResponse, ErrorCertServiceResponse.class); + + String messageFromApi = errorCertServiceResponse.getMessage(); + String path = errorCertServiceResponse.getPath(); + int httpResponseCode = getStatusCode(httpResponse); + + return new CertServiceApiResponseException(certServiceAddress + path, httpResponseCode, messageFromApi); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/exception/CertServiceApiResponseException.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/exception/CertServiceApiResponseException.java new file mode 100644 index 00000000..40470af3 --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/exception/CertServiceApiResponseException.java @@ -0,0 +1,42 @@ +/* + * ============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.httpclient.exception; + +import org.onap.aaf.certservice.client.api.ExitCode; +import org.onap.aaf.certservice.client.api.ExitableException; + +public class CertServiceApiResponseException extends ExitableException { + private final ExitCode EXIT_CODE = ExitCode.CERT_SERVICE_API_CONNECTION_EXCEPTION; + + public CertServiceApiResponseException(String url, int responseCode, String messageFromAPI) { + + super(String.format("Request failed for URL '%s'. Response code: %d . Message from API: %s", + url, + responseCode, + messageFromAPI)); + } + + @Override + public int applicationExitCode() { + return EXIT_CODE.getValue(); + } + +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/exception/HttpClientException.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/exception/HttpClientException.java new file mode 100644 index 00000000..d6fb1461 --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/exception/HttpClientException.java @@ -0,0 +1,37 @@ +/* + * ============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.httpclient.exception; + +import org.onap.aaf.certservice.client.api.ExitCode; +import org.onap.aaf.certservice.client.api.ExitableException; + +public class HttpClientException extends ExitableException { + private final ExitCode EXIT_CODE = ExitCode.HTTP_CLIENT_EXCEPTION; + + public HttpClientException(Throwable e) { + super(e); + } + + @Override + public int applicationExitCode() { + return EXIT_CODE.getValue(); + } +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/model/CertServiceResponse.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/model/CertServiceResponse.java new file mode 100644 index 00000000..4ca17999 --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/model/CertServiceResponse.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.httpclient.model; + +import java.util.Collections; +import java.util.List; + +public class CertServiceResponse { + + private final List<String> certificateChain; + private final List<String> trustedCertificates; + + public CertServiceResponse(List<String> certificateChain, List<String> trustedCertificates) { + this.certificateChain = certificateChain; + this.trustedCertificates = trustedCertificates; + } + + public List<String> getCertificateChain() { + return Collections.unmodifiableList(certificateChain); + } + + public List<String> getTrustedCertificates() { + return Collections.unmodifiableList(trustedCertificates); + } + +} diff --git a/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/model/ErrorCertServiceResponse.java b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/model/ErrorCertServiceResponse.java new file mode 100644 index 00000000..6fe99ce5 --- /dev/null +++ b/certServiceClient/src/main/java/org/onap/aaf/certservice/client/httpclient/model/ErrorCertServiceResponse.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.httpclient.model; + +public class ErrorCertServiceResponse { + + private final String message; + private final String path; + + public ErrorCertServiceResponse(String message, String path) { + this.message = message; + this.path = path; + } + + public String getMessage() { + return message; + } + + public String getPath() { + return path; + } +} diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/CerServiceRequestTestData.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/CerServiceRequestTestData.java new file mode 100644 index 00000000..8f252c31 --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/CerServiceRequestTestData.java @@ -0,0 +1,89 @@ +/* + * ============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +public final class CerServiceRequestTestData { + + private static final String RESOURCE_PATH = "src/test/resources/"; + + // Request parameters + public static final String CA_NAME = "TestCA"; + public static final String CSR = getCsrValue(); + public static final String PK = getPkValue(); + + // Correct response data + public static final String CORRECT_RESPONSE = getCorrectResponse(); + public static final String EXPECTED_FIRST_ELEMENT_OF_CERTIFICATE_CHAIN = + getExpectedFirstElementOfCertificateChain(); + public static final String EXPECTED_FIRST_ELEMENT_OF_TRUSTED_CERTIFICATES = + getExpectedFirstElementOfTrustedCertificates(); + + // Error response data + public static final String MISSING_PK_RESPONSE = getMissingPkResponse(); + + private CerServiceRequestTestData() { + } + + private static String getMissingPkResponse() { + String fileName = "missingPkResponse"; + return readFromFile(RESOURCE_PATH + fileName); + } + + private static String getExpectedFirstElementOfTrustedCertificates() { + + String fileName = "expectedFirstElementOfTrustedCertificates"; + return readFromFile(RESOURCE_PATH + fileName); + } + + private static String getExpectedFirstElementOfCertificateChain() { + String fileName = "expectedFirstElementOfCertificateChain"; + return readFromFile(RESOURCE_PATH + fileName); + } + + private static String getCorrectResponse() { + String fileName = "correctResponse"; + return readFromFile(RESOURCE_PATH + fileName); + } + + private static String getPkValue() { + String fileName = "testPk"; + return readFromFile(RESOURCE_PATH + fileName); + } + + private static String getCsrValue() { + String fileName = "testCsr"; + return readFromFile(RESOURCE_PATH + fileName); + } + + private static String readFromFile(String path) { + try { + return Files.readString(Paths.get(path), StandardCharsets.UTF_8); + } catch (IOException e) { + e.printStackTrace(); + return "File not found"; + } + } +} diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/CsrFactoryTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/CsrFactoryTest.java new file mode 100644 index 00000000..809a91f2 --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/CsrFactoryTest.java @@ -0,0 +1,58 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification; + + +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.client.certification.exception.CsrGenerationException; +import org.onap.aaf.certservice.client.certification.exception.KeyPairGenerationException; +import org.onap.aaf.certservice.client.configuration.model.CsrConfiguration; + +import java.security.KeyPair; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +public class CsrFactoryTest { + + CsrConfiguration config = mock(CsrConfiguration.class); + + + + @Test + void createEncodedCsr_shouldSucceedWhenAllFieldsAreSetCorrectly() throws KeyPairGenerationException, CsrGenerationException { + + KeyPair keyPair = + new KeyPairFactory(EncryptionAlgorithmConstants.RSA_ENCRYPTION_ALGORITHM, EncryptionAlgorithmConstants.KEY_SIZE).create(); + + when(config.getCommonName()).thenReturn("onap.org"); + when(config.getSans()).thenReturn("onapexample.com:onapexample.com.pl:onapexample.pl"); + when(config.getCountry()).thenReturn("US"); + when(config.getLocation()).thenReturn("San-Francisco"); + when(config.getOrganization()).thenReturn("Linux-Foundation"); + when(config.getOrganizationUnit()).thenReturn("ONAP"); + when(config.getState()).thenReturn("California"); + + assertThat(new CsrFactory(config).createCsrInPem(keyPair)).isNotEmpty(); + } +} + diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/PrivateKeyToPemEncoderTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/PrivateKeyToPemEncoderTest.java new file mode 100644 index 00000000..def9c1d5 --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/PrivateKeyToPemEncoderTest.java @@ -0,0 +1,66 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification; + + +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.client.certification.exception.PkEncodingException; + +import java.io.IOException; +import java.io.StringReader; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; + +import static org.assertj.core.api.Assertions.assertThat; + +class PrivateKeyToPemEncoderTest { + + private static final String ENCRYPTION_ALGORITHM = "RSA"; + private static final String RESOURCES_DIR = "src/test/resources/"; + private static final String PRIVATE_KEY_PEM_PATH = RESOURCES_DIR + "rsaPrivateKeyPem"; + + @Test + public void shouldReturnProperlyEncodedPrivateKey() throws InvalidKeySpecException, NoSuchAlgorithmException, PkEncodingException, IOException { + //given + String expectedPem = Files.readString(Paths.get(PRIVATE_KEY_PEM_PATH)); + PrivateKeyToPemEncoder testedPkEncoder = new PrivateKeyToPemEncoder(); + //when + PrivateKey privateKey = extractPrivateKeyFromPem(expectedPem); + String resultPkInPem = testedPkEncoder.encodePrivateKeyToPem(privateKey); + //then + assertThat(resultPkInPem).isEqualTo(expectedPem); + } + + private PrivateKey extractPrivateKeyFromPem(String pem) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { + PemReader pemReader = new PemReader(new StringReader(pem)); + PemObject pemObject = pemReader.readPemObject(); + pemReader.close(); + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(pemObject.getContent()); + KeyFactory kf = KeyFactory.getInstance(ENCRYPTION_ALGORITHM); + return kf.generatePrivate(spec); + } +}
\ No newline at end of file diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreatorTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreatorTest.java new file mode 100644 index 00000000..04bccf0b --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreatorTest.java @@ -0,0 +1,80 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.security.PrivateKey; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.client.certification.exception.PemToPKCS12ConverterException; + +class KeystoreTruststoreCreatorTest { + + private PKCS12FilesCreator filesCreator = mock(PKCS12FilesCreator.class); + private RandomPasswordGenerator passwordGenerator = mock(RandomPasswordGenerator.class); + private PemToPKCS12Converter converter = mock(PemToPKCS12Converter.class); + private PrivateKey privateKey = mock(PrivateKey.class); + + @Test + void createKeystoreShouldCallRequiredMethods() throws PemToPKCS12ConverterException { + // given + final Password password = new Password("d9D_u8LooYaXH4G48DtN#vw0"); + final List<String> certificates = List.of("a", "b"); + final int passwordLength = 24; + final String alias = "certificate"; + final byte[] keystoreBytes = "this is a keystore test".getBytes(); + KeystoreTruststoreCreator creator = new KeystoreTruststoreCreator(filesCreator, passwordGenerator, converter); + + // when + when(passwordGenerator.generate(passwordLength)).thenReturn(password); + when(converter.convertKeystore(certificates, password, alias, privateKey)).thenReturn(keystoreBytes); + creator.createKeystore(certificates, privateKey); + + // then + verify(passwordGenerator, times(1)).generate(passwordLength); + verify(converter, times(1)).convertKeystore(certificates, password, alias, privateKey); + verify(filesCreator, times(1)).saveKeystoreData(keystoreBytes, password.getPassword()); + } + + @Test + void createTruststoreShouldCallRequiredMethods() throws PemToPKCS12ConverterException { + // given + final Password password = new Password("d9D_u8LooYaXH4G48DtN#vw0"); + final List<String> certificates = List.of("a", "b"); + final int passwordLength = 24; + final String alias = "trusted-certificate-"; + final byte[] truststoreBytes = "this is a truststore test".getBytes(); + KeystoreTruststoreCreator creator = new KeystoreTruststoreCreator(filesCreator, passwordGenerator, converter); + + // when + when(passwordGenerator.generate(passwordLength)).thenReturn(password); + when(converter.convertTruststore(certificates, password, alias)).thenReturn(truststoreBytes); + creator.createTruststore(certificates); + + // then + verify(passwordGenerator, times(1)).generate(passwordLength); + verify(converter, times(1)).convertTruststore(certificates, password, alias); + verify(filesCreator, times(1)).saveTruststoreData(truststoreBytes, password.getPassword()); + } +}
\ No newline at end of file diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PKCS12FilesCreatorTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PKCS12FilesCreatorTest.java new file mode 100644 index 00000000..8e6e03c6 --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PKCS12FilesCreatorTest.java @@ -0,0 +1,111 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.client.certification.exception.PemToPKCS12ConverterException; + +class PKCS12FilesCreatorTest { + + private static final String RESOURCES_PATH = "src/test/resources"; + private static final String OUTPUT_PATH = RESOURCES_PATH + "/generatedFiles/"; + private static final String KEYSTORE_PATH = OUTPUT_PATH + "keystore.jks"; + private static final String KEYSTORE_PASS_PATH = OUTPUT_PATH + "keystore.pass"; + private static final String TRUSTSTORE_PATH = OUTPUT_PATH + "truststore.jks"; + private static final String TRUSTSTORE_PASS_PATH = OUTPUT_PATH + "truststore.pass"; + private static final String ERROR_MESSAGE = "java.io.FileNotFoundException: src/test/resources/generatedFiles/thisPathDoesNotExist/keystore.jks (No such file or directory)"; + + private File outputDirectory = new File(OUTPUT_PATH); + + @BeforeEach + void createDirectory() { + outputDirectory.mkdir(); + } + + @AfterEach + void cleanUpFiles() { + List.of(outputDirectory.listFiles()).forEach(f -> f.delete()); + outputDirectory.delete(); + } + + @Test + void saveKeystoreDataShouldCreateFilesWithDataInGivenLocation() throws PemToPKCS12ConverterException, IOException { + // given + final byte[] data = new byte[]{-128, 1, 127}; + final String password = "onap123"; + File keystore = new File(KEYSTORE_PATH); + File keystorePass = new File(KEYSTORE_PASS_PATH); + PKCS12FilesCreator filesCreator = new PKCS12FilesCreator(OUTPUT_PATH); + + // when + filesCreator.saveKeystoreData(data, password); + + // then + assertTrue(keystore.exists()); + assertTrue(keystorePass.exists()); + assertArrayEquals(data, Files.readAllBytes(Path.of(KEYSTORE_PATH))); + assertEquals(password, Files.readString(Path.of(KEYSTORE_PASS_PATH), StandardCharsets.UTF_8)); + } + + @Test + void saveTruststoreDataShouldCreateFilesWithDataInGivenLocation() + throws PemToPKCS12ConverterException, IOException { + // given + final byte[] data = new byte[]{-128, 1, 2, 3, 127}; + final String password = "nokia321"; + File truststore = new File(TRUSTSTORE_PATH); + File truststorePass = new File(TRUSTSTORE_PASS_PATH); + PKCS12FilesCreator filesCreator = new PKCS12FilesCreator(OUTPUT_PATH); + + // when + filesCreator.saveTruststoreData(data, password); + + // then + assertTrue(truststore.exists()); + assertTrue(truststorePass.exists()); + assertArrayEquals(data, Files.readAllBytes(Path.of(TRUSTSTORE_PATH))); + assertEquals(password, Files.readString(Path.of(TRUSTSTORE_PASS_PATH), StandardCharsets.UTF_8)); + } + + @Test + void saveKeystoreDataShouldThrowPemToPKCS12ConverterExceptionWhenOutputDirectoryDoesNotExist() { + // given + final byte[] data = new byte[]{-128, 1, 2, 3, 0}; + final String password = "123aikon"; + PKCS12FilesCreator filesCreator = new PKCS12FilesCreator(OUTPUT_PATH + "thisPathDoesNotExist/"); + + // when then + assertThatThrownBy(() -> filesCreator.saveKeystoreData(data, password)) + .isInstanceOf(PemToPKCS12ConverterException.class).hasMessage(ERROR_MESSAGE); + } +}
\ No newline at end of file diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PemToPKCS12ConverterTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PemToPKCS12ConverterTest.java new file mode 100644 index 00000000..35043409 --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PemToPKCS12ConverterTest.java @@ -0,0 +1,197 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +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.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.util.List; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants; +import org.onap.aaf.certservice.client.certification.exception.PemToPKCS12ConverterException; + +class PemToPKCS12ConverterTest { + + private static final String RESOURCES_PATH = "src/test/resources"; + private static final String CERT1_PATH = RESOURCES_PATH + "/cert1.pem"; + private static final String CERT2_PATH = RESOURCES_PATH + "/cert2.pem"; + private static final String KEY_PATH = RESOURCES_PATH + "/privateKey"; + private static final String EXPECTED_KEYSTORE_PATH = RESOURCES_PATH + "/expectedKeystore.jks"; + private static final String EXPECTED_TRUSTSTORE_PATH = RESOURCES_PATH + "/expectedTruststore.jks"; + private static final String PKCS12 = "PKCS12"; + private static final String PKCS8 = "PKCS#8"; + private static final String KEY_ERROR_MSG = "java.security.KeyStoreException: Key protection algorithm not found: java.lang.NullPointerException"; + private static final String CERTIFICATES_ERROR_MSG = "The certificate couldn't be parsed correctly. certificate1"; + private static final String PASSWORD_ERROR_MSG = "Password should be min. 16 chars long and should contain only alphanumeric characters and special characters like Underscore (_), Dollar ($) and Pound (#)"; + private static byte[] key; + private PrivateKey privateKey = mock(PrivateKey.class); + + @BeforeAll + static void setUpForAll() throws IOException { + key = Files.readAllBytes(Path.of(KEY_PATH)); + } + + @Test + void convertKeystoreShouldReturnKeystoreWithGivenPrivateKeyAndCertificateChain() + throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, PemToPKCS12ConverterException { + // given + final String alias = "keystore-entry"; + final Password password = new Password("d9D_u8LooYaXH4G48DtN#vw0"); + final List<String> certificateChain = getCertificates(); + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + final KeyStore expectedKeyStore = KeyStore.getInstance(PKCS12); + expectedKeyStore.load(new ByteArrayInputStream(Files.readAllBytes(Path.of(EXPECTED_KEYSTORE_PATH))), + password.toCharArray()); + final Certificate[] expectedChain = expectedKeyStore.getCertificateChain(alias); + privateKeyMockSetup(); + + // when + final byte[] result = converter.convertKeystore(certificateChain, password, alias, privateKey); + + // then + final KeyStore actualKeyStore = KeyStore.getInstance(PKCS12); + actualKeyStore.load(new ByteArrayInputStream(result), password.toCharArray()); + final Certificate[] actualChain = actualKeyStore.getCertificateChain(alias); + + assertArrayEquals(key, actualKeyStore.getKey(alias, password.toCharArray()).getEncoded()); + assertEquals(2, expectedChain.length); + assertArrayEquals(expectedChain, actualChain); + } + + @Test + void convertKeystoreShouldThrowPemToPKCS12ConverterExceptionBecauseOfWrongPassword() throws IOException { + // given + final String alias = "keystore-entry"; + final Password password = new Password("apple"); + final List<String> certificateChain = getCertificates(); + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + privateKeyMockSetup(); + + // when + Exception exception = assertThrows(PemToPKCS12ConverterException.class, () -> + converter.convertKeystore(certificateChain, password, alias, privateKey) + ); + + // then + assertEquals(PASSWORD_ERROR_MSG, exception.getMessage()); + } + + @Test + void convertTruststoreShouldReturnTruststoreWithGivenCertificatesArray() + throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, PemToPKCS12ConverterException { + + // given + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + final String alias = "trusted-certificate-"; + final String alias1 = alias + 1; + final String alias2 = alias + 2; + final Password password = new Password("9z6oFx1epRSCuBWU4Er8i_0y"); + final List<String> trustedCertificates = getCertificates(); + final KeyStore expectedTrustStore = KeyStore.getInstance(PKCS12); + expectedTrustStore.load(new ByteArrayInputStream(Files.readAllBytes(Path.of(EXPECTED_TRUSTSTORE_PATH))), + password.toCharArray()); + + // when + final byte[] result = converter.convertTruststore(trustedCertificates, password, alias); + + // then + final KeyStore actualKeyStore = KeyStore.getInstance(PKCS12); + actualKeyStore.load(new ByteArrayInputStream(result), password.toCharArray()); + + assertTrue(actualKeyStore.containsAlias(alias1)); + assertTrue(actualKeyStore.containsAlias(alias2)); + assertEquals(expectedTrustStore.getCertificate(alias1), actualKeyStore.getCertificate(alias1)); + assertEquals(expectedTrustStore.getCertificate(alias2), actualKeyStore.getCertificate(alias2)); + } + + @Test + void convertTruststoreShouldThrowPemToPKCS12ConverterExceptionBecauseOfWrongPassword() throws IOException { + // given + final String alias = "trusted-certificate-"; + final Password password = new Password("nokia"); + final List<String> trustedCertificates = getCertificates(); + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + + // when then + assertThatThrownBy(() -> + converter.convertTruststore(trustedCertificates, password, alias)) + .isInstanceOf(PemToPKCS12ConverterException.class).hasMessage(PASSWORD_ERROR_MSG); + } + + @Test + void convertKeystoreShouldThrowPemToPKCS12ConverterExceptionBecauseOfWrongPrivateKey() throws IOException { + // given + final String alias = "keystore-entry"; + final Password password = new Password("d9D_u8LooYaXH4G48DtN#vw0"); + final List<String> certificateChain = getCertificates(); + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + + // when then + assertThatThrownBy(() -> converter.convertKeystore(certificateChain, password, alias, privateKey)) + .isInstanceOf(PemToPKCS12ConverterException.class).hasMessage(KEY_ERROR_MSG); + } + + @Test + void convertKeystoreShouldThrowPemToPKCS12ConverterExceptionBecauseOfWrongCertificates() { + // given + final String alias = "keystore-entry"; + final Password password = new Password("d9D_u8LooYaXH4G48DtN#vw0"); + final List<String> certificateChain = List.of("certificate1", "certificate2"); + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + privateKeyMockSetup(); + + // when then + assertThatThrownBy(() -> converter.convertKeystore(certificateChain, password, alias, privateKey)) + .isInstanceOf(PemToPKCS12ConverterException.class).hasMessage(CERTIFICATES_ERROR_MSG); + } + + private void privateKeyMockSetup() { + when(privateKey.getEncoded()).thenReturn(key); + when(privateKey.getAlgorithm()).thenReturn(EncryptionAlgorithmConstants.RSA_ENCRYPTION_ALGORITHM); + when(privateKey.getFormat()).thenReturn(PKCS8); + } + + private List<String> getCertificates() throws IOException { + return List.of( + Files.readString( + Path.of(CERT1_PATH), StandardCharsets.UTF_8), + Files.readString( + Path.of(CERT2_PATH), StandardCharsets.UTF_8) + ); + } +}
\ No newline at end of file diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/RandomPasswordGeneratorTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/RandomPasswordGeneratorTest.java new file mode 100644 index 00000000..169ce98a --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/RandomPasswordGeneratorTest.java @@ -0,0 +1,32 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.certification.conversion; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; + +class RandomPasswordGeneratorTest { + + @Test + void shouldGenerateRandomPasswordOfGivenLengthMatchingThePattern() { + Password password = new RandomPasswordGenerator().generate(24); + assertTrue(password.isCorrectPasswordPattern()); + } +}
\ No newline at end of file diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/EnvValidationUtilsTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/EnvValidationUtilsTest.java new file mode 100644 index 00000000..8f4fe6a3 --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/EnvValidationUtilsTest.java @@ -0,0 +1,41 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.configuration; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class EnvValidationUtilsTest { + + @ParameterizedTest + @ValueSource(strings = {"/var/log", "/", "/var/log/", "/second_var", "/second-var"}) + public void shouldAcceptValidPath(String path){ + assertTrue(EnvValidationUtils.isPathValid(path)); + } + + @ParameterizedTest + @ValueSource(strings = {"/var/log?", "", "var_", "var", "//", "/var//log"}) + public void shouldRejectInvalidPath(String path){ + assertFalse(EnvValidationUtils.isPathValid(path)); + } +}
\ No newline at end of file diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/model/ClientConfigurationFactoryTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/model/ClientConfigurationFactoryTest.java index f355de1a..2c875c24 100644 --- a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/model/ClientConfigurationFactoryTest.java +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/model/ClientConfigurationFactoryTest.java @@ -26,6 +26,8 @@ import org.onap.aaf.certservice.client.configuration.EnvsForClient; import org.onap.aaf.certservice.client.configuration.exception.ClientConfigurationException; import org.onap.aaf.certservice.client.configuration.factory.ClientConfigurationFactory; +import java.util.Optional; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.Mockito.mock; @@ -33,22 +35,22 @@ import static org.mockito.Mockito.when; public class ClientConfigurationFactoryTest { - final String CA_NAME_VALID = "caaaftest2"; - final String TIME_OUT_VALID = "30000"; - final String OUTPUT_PATH_VALID = "/opt/app/osaaf"; - final String URL_TO_CERT_SERVICE_VALID = "http://cert-service:8080/v1/certificate/"; - final String CA_NAME_INVALID = "caaaftest2#$"; - final String OUTPUT_PATH_INVALID = "/opt//app/osaaf"; + private final String CA_NAME_VALID = "caaaftest2"; + private final String TIME_OUT_VALID = "30000"; + private final String OUTPUT_PATH_VALID = "/opt/app/osaaf"; + private final String URL_TO_CERT_SERVICE_VALID = "http://cert-service:8080/v1/certificate/"; + private final String CA_NAME_INVALID = "caaaftest2#$"; + private final String OUTPUT_PATH_INVALID = "/opt//app/osaaf"; private EnvsForClient envsForClient = mock(EnvsForClient.class); @Test void create_shouldReturnSuccessWhenAllVariablesAreSetAndValid() throws ClientConfigurationException { // given - when(envsForClient.getCaName()).thenReturn(CA_NAME_VALID); - when(envsForClient.getOutputPath()).thenReturn(OUTPUT_PATH_VALID); - when(envsForClient.getRequestTimeOut()).thenReturn(TIME_OUT_VALID); - when(envsForClient.getUrlToCertService()).thenReturn(URL_TO_CERT_SERVICE_VALID); + when(envsForClient.getCaName()).thenReturn(Optional.of(CA_NAME_VALID)); + when(envsForClient.getOutputPath()).thenReturn(Optional.of(OUTPUT_PATH_VALID)); + when(envsForClient.getRequestTimeOut()).thenReturn(Optional.of(TIME_OUT_VALID)); + when(envsForClient.getUrlToCertService()).thenReturn(Optional.of(URL_TO_CERT_SERVICE_VALID)); // when ClientConfiguration configuration = new ClientConfigurationFactory(envsForClient).create(); @@ -63,8 +65,8 @@ public class ClientConfigurationFactoryTest { @Test void create_shouldReturnSuccessWhenDefaultVariablesAreNotSet() throws ClientConfigurationException { // given - when(envsForClient.getCaName()).thenReturn(CA_NAME_VALID); - when(envsForClient.getOutputPath()).thenReturn(OUTPUT_PATH_VALID); + when(envsForClient.getCaName()).thenReturn(Optional.of(CA_NAME_VALID)); + when(envsForClient.getOutputPath()).thenReturn(Optional.of(OUTPUT_PATH_VALID)); // when ClientConfiguration configuration = new ClientConfigurationFactory(envsForClient).create(); @@ -79,7 +81,7 @@ public class ClientConfigurationFactoryTest { @Test void create_shouldReturnClientExceptionWhenRequiredVariableIsNotSet() { // given - when(envsForClient.getOutputPath()).thenReturn(OUTPUT_PATH_VALID); + when(envsForClient.getOutputPath()).thenReturn(Optional.of(OUTPUT_PATH_VALID)); // when ClientConfigurationFactory configurationFactory = new ClientConfigurationFactory(envsForClient); @@ -93,10 +95,10 @@ public class ClientConfigurationFactoryTest { @Test void create_shouldReturnClientExceptionWhenCANameContainsSpecialCharacters() { // given - when(envsForClient.getCaName()).thenReturn(CA_NAME_INVALID); - when(envsForClient.getOutputPath()).thenReturn(OUTPUT_PATH_VALID); - when(envsForClient.getRequestTimeOut()).thenReturn(TIME_OUT_VALID); - when(envsForClient.getUrlToCertService()).thenReturn(URL_TO_CERT_SERVICE_VALID); + when(envsForClient.getCaName()).thenReturn(Optional.of(CA_NAME_INVALID)); + when(envsForClient.getOutputPath()).thenReturn(Optional.of(OUTPUT_PATH_VALID)); + when(envsForClient.getRequestTimeOut()).thenReturn(Optional.of(TIME_OUT_VALID)); + when(envsForClient.getUrlToCertService()).thenReturn(Optional.of(URL_TO_CERT_SERVICE_VALID)); // when ClientConfigurationFactory configurationFactory = new ClientConfigurationFactory(envsForClient); @@ -110,10 +112,10 @@ public class ClientConfigurationFactoryTest { @Test void create_shouldReturnClientExceptionWhenOutputPathContainsSpecialCharacters() { // given - when(envsForClient.getCaName()).thenReturn(CA_NAME_VALID); - when(envsForClient.getOutputPath()).thenReturn(OUTPUT_PATH_INVALID); - when(envsForClient.getRequestTimeOut()).thenReturn(TIME_OUT_VALID); - when(envsForClient.getUrlToCertService()).thenReturn(URL_TO_CERT_SERVICE_VALID); + when(envsForClient.getCaName()).thenReturn(Optional.of(CA_NAME_VALID)); + when(envsForClient.getOutputPath()).thenReturn(Optional.of(OUTPUT_PATH_INVALID)); + when(envsForClient.getRequestTimeOut()).thenReturn(Optional.of(TIME_OUT_VALID)); + when(envsForClient.getUrlToCertService()).thenReturn(Optional.of(URL_TO_CERT_SERVICE_VALID)); // when ClientConfigurationFactory configurationFactory = new ClientConfigurationFactory(envsForClient); diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/model/CsrConfigurationFactoryTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/model/CsrConfigurationFactoryTest.java index d6bf431b..bb566e81 100644 --- a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/model/CsrConfigurationFactoryTest.java +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/configuration/model/CsrConfigurationFactoryTest.java @@ -20,12 +20,18 @@ package org.onap.aaf.certservice.client.configuration.model; +import org.assertj.core.api.Condition; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.client.api.ExitCode; import org.onap.aaf.certservice.client.configuration.CsrConfigurationEnvs; import org.onap.aaf.certservice.client.configuration.EnvsForCsr; import org.onap.aaf.certservice.client.configuration.exception.CsrConfigurationException; import org.onap.aaf.certservice.client.configuration.factory.CsrConfigurationFactory; +import java.util.Optional; +import java.util.function.Predicate; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.Mockito.mock; @@ -33,35 +39,42 @@ import static org.mockito.Mockito.when; public class CsrConfigurationFactoryTest { - final String COMMON_NAME_VALID = "onap.org"; - final String SANS_VALID = "test-name"; - final String COUNTRY_VALID = "US"; - final String LOCATION_VALID = "San-Francisco"; - final String ORGANIZATION_VALID = "Linux-Foundation"; - final String ORGANIZATION_UNIT_VALID = "ONAP"; - final String STATE_VALID = "California"; - final String COMMON_NAME_INVALID = "onap.org*&"; + private final String COMMON_NAME_VALID = "onap.org"; + private final String SANS_VALID = "test-name"; + private final String COUNTRY_VALID = "US"; + private final String LOCATION_VALID = "San-Francisco"; + private final String ORGANIZATION_VALID = "Linux-Foundation"; + private final String ORGANIZATION_UNIT_VALID = "ONAP"; + private final String STATE_VALID = "California"; + private final String COMMON_NAME_INVALID = "onap.org*&"; + private final String COUNTRY_INVALID = "PLA"; + private final String ORGANIZATION_INVALID = "Linux?Foundation"; private EnvsForCsr envsForCsr = mock(EnvsForCsr.class); - + private CsrConfigurationFactory testedFactory; + private Condition<CsrConfigurationException> expectedExitCodeCondition = new Condition<>("Correct exit code"){ + @Override + public boolean matches(CsrConfigurationException e) { + return e.applicationExitCode() == ExitCode.CSR_CONFIGURATION_EXCEPTION.getValue(); + } + }; + + @BeforeEach + void setUp() { + testedFactory = new CsrConfigurationFactory(envsForCsr); + } @Test - void create_shouldReturnSuccessWhenAllVariablesAreSetAndValid() throws CsrConfigurationException { + void shouldReturnCorrectConfiguration_WhenAllVariablesAreSetAndValid() throws CsrConfigurationException { // given - when(envsForCsr.getCommonName()).thenReturn(COMMON_NAME_VALID); - when(envsForCsr.getSubjectAlternativesName()).thenReturn(SANS_VALID); - when(envsForCsr.getCountry()).thenReturn(COUNTRY_VALID); - when(envsForCsr.getLocation()).thenReturn(LOCATION_VALID); - when(envsForCsr.getOrganization()).thenReturn(ORGANIZATION_VALID); - when(envsForCsr.getOrganizationUnit()).thenReturn(ORGANIZATION_UNIT_VALID); - when(envsForCsr.getState()).thenReturn(STATE_VALID); + mockEnvsWithAllValidParameters(); // when - CsrConfiguration configuration = new CsrConfigurationFactory(envsForCsr).create(); + CsrConfiguration configuration = testedFactory.create(); // then assertThat(configuration.getCommonName()).isEqualTo(COMMON_NAME_VALID); - assertThat(configuration.getSubjectAlternativeNames()).isEqualTo(SANS_VALID); + assertThat(configuration.getSans()).isEqualTo(SANS_VALID); assertThat(configuration.getCountry()).isEqualTo(COUNTRY_VALID); assertThat(configuration.getLocation()).isEqualTo(LOCATION_VALID); assertThat(configuration.getOrganization()).isEqualTo(ORGANIZATION_VALID); @@ -70,15 +83,12 @@ public class CsrConfigurationFactoryTest { } @Test - void create_shouldReturnSuccessWhenNotRequiredVariablesAreNotSet() throws CsrConfigurationException { + void shouldReturnCorrectConfiguration_WhenNotRequiredVariablesAreNotSet() throws CsrConfigurationException { // given - when(envsForCsr.getCommonName()).thenReturn(COMMON_NAME_VALID); - when(envsForCsr.getState()).thenReturn(STATE_VALID); - when(envsForCsr.getCountry()).thenReturn(COUNTRY_VALID); - when(envsForCsr.getOrganization()).thenReturn(ORGANIZATION_VALID); + mockEnvsWithValidRequiredParameters(); // when - CsrConfiguration configuration = new CsrConfigurationFactory(envsForCsr).create(); + CsrConfiguration configuration = testedFactory.create(); // then assertThat(configuration.getCommonName()).isEqualTo(COMMON_NAME_VALID); @@ -89,22 +99,89 @@ public class CsrConfigurationFactoryTest { @Test - void create_shouldReturnCsrConfigurationExceptionWhenCommonNameContainsSpecialCharacters() { + void shouldThrowCsrConfigurationException_WhenCommonNameInvalid() { // given - when(envsForCsr.getCommonName()).thenReturn(COMMON_NAME_INVALID); - when(envsForCsr.getSubjectAlternativesName()).thenReturn(SANS_VALID); - when(envsForCsr.getCountry()).thenReturn(COUNTRY_VALID); - when(envsForCsr.getLocation()).thenReturn(LOCATION_VALID); - when(envsForCsr.getOrganization()).thenReturn(ORGANIZATION_VALID); - when(envsForCsr.getOrganizationUnit()).thenReturn(ORGANIZATION_UNIT_VALID); - when(envsForCsr.getState()).thenReturn(SANS_VALID); + mockEnvsWithInvalidCommonName(); - // when - CsrConfigurationFactory configurationFactory = new CsrConfigurationFactory(envsForCsr); + // when/then + assertThatExceptionOfType(CsrConfigurationException.class) + .isThrownBy(testedFactory::create) + .withMessageContaining(CsrConfigurationEnvs.COMMON_NAME + " is invalid.") + .has(expectedExitCodeCondition); + } + + @Test + void shouldThrowCsrConfigurationException_WhenOrganizationInvalid() { + // given + mockEnvsWithInvalidOrganization(); // when/then assertThatExceptionOfType(CsrConfigurationException.class) - .isThrownBy(configurationFactory::create) - .withMessageContaining(CsrConfigurationEnvs.COMMON_NAME + " is invalid."); + .isThrownBy(testedFactory::create) + .withMessageContaining(CsrConfigurationEnvs.ORGANIZATION + " is invalid.") + .has(expectedExitCodeCondition); + + } + + @Test + void shouldThrowCsrConfigurationException_WhenCountryInvalid() { + // given + mockEnvsWithInvalidCountry(); + + // when/then + assertThatExceptionOfType(CsrConfigurationException.class) + .isThrownBy(testedFactory::create) + .withMessageContaining(CsrConfigurationEnvs.COUNTRY + " is invalid.") + .has(expectedExitCodeCondition); + + } + + @Test + void shouldThrowCsrConfigurationExceptionWhenStateInvalid() { + // given + mockEnvsWithInvalidState(); + // when/then + assertThatExceptionOfType(CsrConfigurationException.class) + .isThrownBy(testedFactory::create) + .withMessageContaining(CsrConfigurationEnvs.STATE + " is invalid.") + .has(expectedExitCodeCondition); + } + + private void mockEnvsWithAllValidParameters() { + mockEnvsWithValidRequiredParameters(); + mockEnvsWithValidOptionalParameters(); + } + + private void mockEnvsWithValidOptionalParameters() { + when(envsForCsr.getOrganizationUnit()).thenReturn(Optional.of(ORGANIZATION_UNIT_VALID)); + when(envsForCsr.getLocation()).thenReturn(Optional.of(LOCATION_VALID)); + when(envsForCsr.getSubjectAlternativesName()).thenReturn(Optional.of(SANS_VALID)); + } + + private void mockEnvsWithValidRequiredParameters() { + when(envsForCsr.getCommonName()).thenReturn(Optional.of(COMMON_NAME_VALID)); + when(envsForCsr.getCountry()).thenReturn(Optional.of(COUNTRY_VALID)); + when(envsForCsr.getOrganization()).thenReturn(Optional.of(ORGANIZATION_VALID)); + when(envsForCsr.getState()).thenReturn(Optional.of(STATE_VALID)); + } + + private void mockEnvsWithInvalidCommonName() { + mockEnvsWithAllValidParameters(); + when(envsForCsr.getCommonName()).thenReturn(Optional.of(COMMON_NAME_INVALID)); + } + + private void mockEnvsWithInvalidCountry() { + mockEnvsWithAllValidParameters(); + when(envsForCsr.getCountry()).thenReturn(Optional.of(COUNTRY_INVALID)); + } + + private void mockEnvsWithInvalidOrganization() { + mockEnvsWithAllValidParameters(); + when(envsForCsr.getOrganization()).thenReturn(Optional.of(ORGANIZATION_INVALID)); + } + + private void mockEnvsWithInvalidState() { + mockEnvsWithAllValidParameters(); + when(envsForCsr.getState()).thenReturn(Optional.empty()); } } diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/httpclient/HttpClientTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/httpclient/HttpClientTest.java new file mode 100644 index 00000000..461b7a34 --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/httpclient/HttpClientTest.java @@ -0,0 +1,157 @@ +/* + * ============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * 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.client.httpclient; + +import org.apache.http.HttpEntity; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.client.api.ExitCode; +import org.onap.aaf.certservice.client.httpclient.exception.CertServiceApiResponseException; +import org.onap.aaf.certservice.client.httpclient.exception.HttpClientException; +import org.onap.aaf.certservice.client.httpclient.model.CertServiceResponse; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.List; + +import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; +import static java.net.HttpURLConnection.HTTP_OK; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.onap.aaf.certservice.client.CerServiceRequestTestData.CA_NAME; +import static org.onap.aaf.certservice.client.CerServiceRequestTestData.CORRECT_RESPONSE; +import static org.onap.aaf.certservice.client.CerServiceRequestTestData.CSR; +import static org.onap.aaf.certservice.client.CerServiceRequestTestData.EXPECTED_FIRST_ELEMENT_OF_CERTIFICATE_CHAIN; +import static org.onap.aaf.certservice.client.CerServiceRequestTestData.EXPECTED_FIRST_ELEMENT_OF_TRUSTED_CERTIFICATES; +import static org.onap.aaf.certservice.client.CerServiceRequestTestData.MISSING_PK_RESPONSE; +import static org.onap.aaf.certservice.client.CerServiceRequestTestData.PK; + +class HttpClientTest { + + private HttpClient httpClient; + private CloseableHttpClient closeableHttpClient; + private HttpEntity httpEntity; + private StatusLine statusLine; + private CloseableHttpResponse httpResponse; + + @BeforeEach + void setUp() { + + closeableHttpClient = mock(CloseableHttpClient.class); + httpEntity = mock(HttpEntity.class); + statusLine = mock(StatusLine.class); + httpResponse = mock(CloseableHttpResponse.class); + + CloseableHttpClientProvider httpClientProvider = mock(CloseableHttpClientProvider.class); + + when(httpClientProvider.getClient()).thenReturn(closeableHttpClient); + String testCertServiceAddress = ""; + httpClient = new HttpClient(httpClientProvider, testCertServiceAddress); + } + + @Test + void shouldReturnCorrectListsOfCertificatedChainsAndTrustedCertificates_WhenRequestDataIsCorrect() + throws Exception { + + // given + mockServerResponse(HTTP_OK, CORRECT_RESPONSE); + + // when + CertServiceResponse certServiceResponse = + httpClient.retrieveCertServiceData(CA_NAME, CSR, PK); + List<String> certificateChain = certServiceResponse.getCertificateChain(); + List<String> trustedCertificate = certServiceResponse.getTrustedCertificates(); + + // then + assertNotNull(certServiceResponse); + + final int expectedTwoElements = 2; + assertEquals(expectedTwoElements, certificateChain.size()); + assertEquals(expectedTwoElements, trustedCertificate.size()); + + assertEquals(EXPECTED_FIRST_ELEMENT_OF_CERTIFICATE_CHAIN, certificateChain.get(0)); + assertEquals(EXPECTED_FIRST_ELEMENT_OF_TRUSTED_CERTIFICATES, trustedCertificate.get(0)); + } + + @Test + void shouldThrowCertServiceApiResponseException_WhenPkHeaderIsMissing() throws Exception { + + // given + mockServerResponse(HTTP_BAD_REQUEST, MISSING_PK_RESPONSE); + + // when + CertServiceApiResponseException exception = + assertThrows(CertServiceApiResponseException.class, + () -> httpClient.retrieveCertServiceData(CA_NAME, CSR, "")); + + // then + assertEquals(ExitCode.CERT_SERVICE_API_CONNECTION_EXCEPTION.getValue(), exception.applicationExitCode()); + } + + @Test + void shouldThrowHttpClientException_WhenCannotExecuteRequestToAPI() throws Exception{ + + //given + when(closeableHttpClient.execute(any(HttpGet.class))).thenThrow(IOException.class); + + //when + HttpClientException exception = + assertThrows(HttpClientException.class, + () -> httpClient.retrieveCertServiceData(CA_NAME, CSR, "")); + + //then + assertEquals(ExitCode.HTTP_CLIENT_EXCEPTION.getValue(), exception.applicationExitCode()); + } + + @Test + void shouldThrowHttpClientException_WhenCannotParseResponseToString() throws Exception{ + + //given + mockServerResponse(HTTP_OK, CORRECT_RESPONSE); + when(httpEntity.getContent()).thenThrow(IOException.class); + + //when + HttpClientException exception = + assertThrows(HttpClientException.class, + () -> httpClient.retrieveCertServiceData(CA_NAME, CSR, "")); + + //then + assertEquals(ExitCode.HTTP_CLIENT_EXCEPTION.getValue(), exception.applicationExitCode()); + } + + private void mockServerResponse(int serverCodeResponse, String stringResponse) + throws IOException { + when(statusLine.getStatusCode()).thenReturn(serverCodeResponse); + when(httpResponse.getStatusLine()).thenReturn(statusLine); + when(httpResponse.getEntity()).thenReturn(httpEntity); + when(closeableHttpClient.execute(any(HttpGet.class))).thenReturn(httpResponse); + + when(httpEntity.getContent()).thenReturn(new ByteArrayInputStream(stringResponse.getBytes())); + } +} diff --git a/certServiceClient/src/test/resources/cert1.pem b/certServiceClient/src/test/resources/cert1.pem new file mode 100644 index 00000000..cd5f3841 --- /dev/null +++ b/certServiceClient/src/test/resources/cert1.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDjDCCAnSgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwgYQxCzAJBgNVBAYTAlVT +MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw +FwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQD +DBVpbnRlcm1lZGlhdGUub25hcC5vcmcwHhcNMjAwMjEyMDk1MTI2WhcNMjIxMTA4 +MDk1MTI2WjB7MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG +A1UEBwwNU2FuLUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjEN +MAsGA1UECwwET05BUDEVMBMGA1UEAwwMdmlkLm9uYXAub3JnMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+GIRzJzUOh0gtc+wzFJEdTnn+q5F10L0Yhr +G1xKdjPieHIFGsoiXwcuCU8arNSqlz7ocx62KQRkcA8y6edlOAsYtdOEJvqEI9vc +eyTB/HYsbzw3URPGch4AmibrQkKU9QvGwouHtHn4R2Ft2Y0tfEqv9hxj9v4njq4A +EiDLAFLl5FmVyCZu/MtKngSgu1smcaFKTYySPMxytgJZexoa/ALZyyE0gRhsvwHm +NLGCPt1bmE/PEGZybsCqliyTO0S56ncD55The7+D/UDS4kE1Wg0svlWon/YsE6QW +B3oeJDX7Kr8ebDTIAErevIAD7Sm4ee5se2zxYrsYlj0MzHZtvwIDAQABoxAwDjAM +BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCvQ1pTvjON6vSlcJRKSY4r +8q7L4/9ZaVXWJAjzEYJtPIqsgGiPWz0vGfgklowU6tZxp9zRZFXfMil+mPQSe+yo +ULrZSQ/z48YHPueE/BNO/nT4aaVBEhPLR5aVwC7uQVX8H+m1V1UGT8lk9vdI9rej +CI9l524sLCpdE4dFXiWK2XHEZ0Vfylk221u3IYEogVVA+UMX7BFPSsOnI2vtYK/i +lwZtlri8LtTusNe4oiTkYyq+RSyDhtAswg8ANgvfHolhCHoLFj6w1IkG88UCmbwN +d7BoGMy06y5MJxyXEZG0vR7eNeLey0TIh+rAszAFPsIQvrOHW+HuA+WLQAj1mhnm +-----END CERTIFICATE----- diff --git a/certServiceClient/src/test/resources/cert2.pem b/certServiceClient/src/test/resources/cert2.pem new file mode 100644 index 00000000..92ebc821 --- /dev/null +++ b/certServiceClient/src/test/resources/cert2.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDqTCCApGgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNVBAYTAlVT +MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw +FwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQD +DAhvbmFwLm9yZzEeMBwGCSqGSIb3DQEJARYPdGVzdGVyQG9uYXAub3JnMB4XDTIw +MDIxMjA5NDAxMloXDTIyMTEwODA5NDAxMlowgYQxCzAJBgNVBAYTAlVTMRMwEQYD +VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQK +DBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQDDBVpbnRl +cm1lZGlhdGUub25hcC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQC1oOYMZ6G+2DGDAizYnzdCNiogivlht1s4oqgem7fM1XFPxD2p31ATIibOdqr/ +gv1qemO9Q4r1xn6w1Ufq7T1K7PjnMzdSeTqZefurE2JM/HHx2QvW4TjMlz2ILgaD +L1LN60kmMQSOi5VxKJpsrCQxbOsxhvefd212gny5AZMcjJe23kUd9OxUrtvpdLEv +wI3vFEvT7oRUnEUg/XNz7qeg33vf1C39yMR+6O4s6oevgsEebVKjb+yOoS6zzGtz +72wZjm07C54ZlO+4Uy+QAlMjRiU3mgWkKbkOy+4CvwehjhpTikdBs2DX39ZLGHhn +L/0a2NYtGulp9XEqmTvRoI+PAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBADcitdJ6YswiV8jAD9GK0gf3+zqcGegt4kt+79JXlXYbb1sY +q3o6prcB7nSUoClgF2xUPCslFGpM0Er9FCSFElQM/ru0l/KVmJS6kSpwEHvsYIH3 +q5anta+Pyk8JSQWAAw+qrind0uBQMnhR8Tn13tgV+Kjvg/xlH/nZIEdN5YtLB1cA +beVsZRyRfVL9DeZU8s/MZ5wC3kgcEp5A4m5lg7HyBxBdqhzFcDr6xiy6OGqW8Yep +xrwfc8Fw8a/lOv4U+tBeGNKPQDYaL9hh+oM+qMkNXsHXDqdJsuEGJtU4i3Wcwzoc +XGN5NWV//4bP+NFmwgcn7AYCdRvz04A8GU/0Cwg= +-----END CERTIFICATE----- diff --git a/certServiceClient/src/test/resources/correctResponse b/certServiceClient/src/test/resources/correctResponse new file mode 100644 index 00000000..c7bf349e --- /dev/null +++ b/certServiceClient/src/test/resources/correctResponse @@ -0,0 +1,10 @@ +{ + "certificateChain": [ + "-----BEGIN CERTIFICATE-----\nMIIDjDCCAnSgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwgYQxCzAJBgNVBAYTAlVT\nMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw\nFwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQD\nDBVpbnRlcm1lZGlhdGUub25hcC5vcmcwHhcNMjAwMjEyMDk1MTI2WhcNMjIxMTA4\nMDk1MTI2WjB7MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG\nA1UEBwwNU2FuLUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjEN\nMAsGA1UECwwET05BUDEVMBMGA1UEAwwMdmlkLm9uYXAub3JnMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+GIRzJzUOh0gtc+wzFJEdTnn+q5F10L0Yhr\nG1xKdjPieHIFGsoiXwcuCU8arNSqlz7ocx62KQRkcA8y6edlOAsYtdOEJvqEI9vc\neyTB/HYsbzw3URPGch4AmibrQkKU9QvGwouHtHn4R2Ft2Y0tfEqv9hxj9v4njq4A\nEiDLAFLl5FmVyCZu/MtKngSgu1smcaFKTYySPMxytgJZexoa/ALZyyE0gRhsvwHm\nNLGCPt1bmE/PEGZybsCqliyTO0S56ncD55The7+D/UDS4kE1Wg0svlWon/YsE6QW\nB3oeJDX7Kr8ebDTIAErevIAD7Sm4ee5se2zxYrsYlj0MzHZtvwIDAQABoxAwDjAM\nBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCvQ1pTvjON6vSlcJRKSY4r\n8q7L4/9ZaVXWJAjzEYJtPIqsgGiPWz0vGfgklowU6tZxp9zRZFXfMil+mPQSe+yo\nULrZSQ/z48YHPueE/BNO/nT4aaVBEhPLR5aVwC7uQVX8H+m1V1UGT8lk9vdI9rej\nCI9l524sLCpdE4dFXiWK2XHEZ0Vfylk221u3IYEogVVA+UMX7BFPSsOnI2vtYK/i\nlwZtlri8LtTusNe4oiTkYyq+RSyDhtAswg8ANgvfHolhCHoLFj6w1IkG88UCmbwN\nd7BoGMy06y5MJxyXEZG0vR7eNeLey0TIh+rAszAFPsIQvrOHW+HuA+WLQAj1mhnm\n-----END CERTIFICATE-----", + "-----BEGIN CERTIFICATE-----\nMIIDqTCCApGgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNVBAYTAlVT\nMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw\nFwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQD\nDAhvbmFwLm9yZzEeMBwGCSqGSIb3DQEJARYPdGVzdGVyQG9uYXAub3JnMB4XDTIw\nMDIxMjA5NDAxMloXDTIyMTEwODA5NDAxMlowgYQxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQK\nDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQDDBVpbnRl\ncm1lZGlhdGUub25hcC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\nAQC1oOYMZ6G+2DGDAizYnzdCNiogivlht1s4oqgem7fM1XFPxD2p31ATIibOdqr/\ngv1qemO9Q4r1xn6w1Ufq7T1K7PjnMzdSeTqZefurE2JM/HHx2QvW4TjMlz2ILgaD\nL1LN60kmMQSOi5VxKJpsrCQxbOsxhvefd212gny5AZMcjJe23kUd9OxUrtvpdLEv\nwI3vFEvT7oRUnEUg/XNz7qeg33vf1C39yMR+6O4s6oevgsEebVKjb+yOoS6zzGtz\n72wZjm07C54ZlO+4Uy+QAlMjRiU3mgWkKbkOy+4CvwehjhpTikdBs2DX39ZLGHhn\nL/0a2NYtGulp9XEqmTvRoI+PAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZI\nhvcNAQELBQADggEBADcitdJ6YswiV8jAD9GK0gf3+zqcGegt4kt+79JXlXYbb1sY\nq3o6prcB7nSUoClgF2xUPCslFGpM0Er9FCSFElQM/ru0l/KVmJS6kSpwEHvsYIH3\nq5anta+Pyk8JSQWAAw+qrind0uBQMnhR8Tn13tgV+Kjvg/xlH/nZIEdN5YtLB1cA\nbeVsZRyRfVL9DeZU8s/MZ5wC3kgcEp5A4m5lg7HyBxBdqhzFcDr6xiy6OGqW8Yep\nxrwfc8Fw8a/lOv4U+tBeGNKPQDYaL9hh+oM+qMkNXsHXDqdJsuEGJtU4i3Wcwzoc\nXGN5NWV//4bP+NFmwgcn7AYCdRvz04A8GU/0Cwg=\n-----END CERTIFICATE-----" + ], + "trustedCertificates": [ + "-----BEGIN CERTIFICATE-----\nMIIDtzCCAp8CFAwqQddh4/iyGfP8UZ3dpXlxfAN8MA0GCSqGSIb3DQEBCwUAMIGX\nMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\nLUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwE\nT05BUDERMA8GA1UEAwwIb25hcC5vcmcxHjAcBgkqhkiG9w0BCQEWD3Rlc3RlckBv\nbmFwLm9yZzAeFw0yMDAyMTIwOTM0MjdaFw0yMTAyMTEwOTM0MjdaMIGXMQswCQYD\nVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuLUZyYW5j\naXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwET05BUDER\nMA8GA1UEAwwIb25hcC5vcmcxHjAcBgkqhkiG9w0BCQEWD3Rlc3RlckBvbmFwLm9y\nZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCFrnO7/eT6V+7XkPPd\neiL/6xXreuegvit/1/jTVjG+3AOVcmTn2WXwXXRcQLvkWQfJVPoltsY8E3FqFRti\n797XjY6cdQJFVDyzNU0+Fb4vJL9FK5wSvnS6EFjBEn3JvXRlENorDCs/mfjkjJoa\nDl74gXQEJYcg4nsTeNIj7cm3Q7VK3mZt1t7LSJJ+czxv69UJDuNJpmQ/2WOKyLZA\ngTtBJ+Hyol45/OLsrqwq1dAn9ZRWIFPvRt/XQYH9bI/6MtqSreRVUrdYCiTe/XpP\nB/OM6NEi2+p5QLi3Yi70CEbqP3HqUVbkzF+r7bwIb6M5/HxfqzLmGwLvD+6rYnUn\nBm8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAhXoO65DXth2X/zFRNsCNpLwmDy7r\nPxT9ZAIZAzSxx3/aCYiuTrKP1JnqjkO+F2IbikrI4n6sKO49SKnRf9SWTFhd+5dX\nvxq5y7MaqxHAY9J7+Qzq33+COVFQnaF7ddel2NbyUVb2b9ZINNsaZkkPXui6DtQ7\n/Fb/1tmAGWd3hMp75G2thBSzs816JMKKa9WD+4VGATEs6OSll4sv2fOZEn+0mAD3\n9q9c+WtLGIudOwcHwzPb2njtNntQSCK/tVOqbY+vzhMY3JW+p9oSrLDSdGC+pAKK\nm/wB+2VPIYcsPMtIhHC4tgoSaiCqjXYptaOh4b8ye8CPBUCpX/AYYkN0Ow==\n-----END CERTIFICATE-----", + "-----BEGIN CERTIFICATE-----\nMIIDvzCCAqcCFF5DejiyfoNfPiiMmBXulniBewBGMA0GCSqGSIb3DQEBCwUAMIGb\nMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\nLUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwE\nT05BUDEVMBMGA1UEAwwMbmV3Lm9uYXAub3JnMR4wHAYJKoZIhvcNAQkBFg90ZXN0\nZXJAb25hcC5vcmcwHhcNMjAwMjEyMDk1OTM3WhcNMjEwMjExMDk1OTM3WjCBmzEL\nMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbi1G\ncmFuY2lzY28xGTAXBgNVBAoMEExpbnV4LUZvdW5kYXRpb24xDTALBgNVBAsMBE9O\nQVAxFTATBgNVBAMMDG5ldy5vbmFwLm9yZzEeMBwGCSqGSIb3DQEJARYPdGVzdGVy\nQG9uYXAub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtF4FXeDV\nng/inC/bTACmZnLC9IiC7PyG/vVbMxxN1bvQLRAwC/Hbl3i9zD68Vs/jPPr/SDr9\n2rgItdDdUY1V30Y3PT06F11XdEaRb+t++1NX0rDf1AqPaBZgnBmB86s1wbqHdJTr\nwEImDZ5xMPfP3fiWy/9Yw/U7iRMIi1/oI0lWuHJV0bn908shuJ6dvInpRCoDnoTX\nYP/FiDSZCFVewQcq4TigB7kRqZrDcPZWbSlqHklDMXRwbCxAiFSziuX6TBwru9Rn\nHhIeXVSgMU1ZSSopVbJGtQ4zSsU1nvTK5Bhc2UHGcAOZy1xTN5D9EEbTqh7l+Wtx\ny8ojkEXvFG8lVwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAE+bUphwHit78LK8sb\nOMjt4DiEu32KeSJOpYgPLeBeAIynaNsa7sQrpuxerGNTmQWIcw6olXI0J+OOwkik\nII7elrYtd5G1uALxXWdamNsaY0Du34moVL1YjexJ7qQ4oBUxg2tuY8NAQGDK+23I\nnCA+ZwzdTJo73TYS6sx64d/YLWkX4nHGUoMlF+xUH34csDyhpuTSzQhC2quB5N8z\ntSFdpe4z2jqx07qo2EBFxi03EQ8Q0ex6l421QM2gbs7cZQ66K0DkpPcF2+iHZnyx\nxq1lnlsWHklElF2bhyXTn3fPp5wtan00P8IolKx7CAWb92QjkW6M0RvTW/xuwIzh\n0rTO\n-----END CERTIFICATE-----" + ] +}
\ No newline at end of file diff --git a/certServiceClient/src/test/resources/expectedFirstElementOfCertificateChain b/certServiceClient/src/test/resources/expectedFirstElementOfCertificateChain new file mode 100644 index 00000000..1cbbc8d3 --- /dev/null +++ b/certServiceClient/src/test/resources/expectedFirstElementOfCertificateChain @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDjDCCAnSgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwgYQxCzAJBgNVBAYTAlVT +MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw +FwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQD +DBVpbnRlcm1lZGlhdGUub25hcC5vcmcwHhcNMjAwMjEyMDk1MTI2WhcNMjIxMTA4 +MDk1MTI2WjB7MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG +A1UEBwwNU2FuLUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjEN +MAsGA1UECwwET05BUDEVMBMGA1UEAwwMdmlkLm9uYXAub3JnMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+GIRzJzUOh0gtc+wzFJEdTnn+q5F10L0Yhr +G1xKdjPieHIFGsoiXwcuCU8arNSqlz7ocx62KQRkcA8y6edlOAsYtdOEJvqEI9vc +eyTB/HYsbzw3URPGch4AmibrQkKU9QvGwouHtHn4R2Ft2Y0tfEqv9hxj9v4njq4A +EiDLAFLl5FmVyCZu/MtKngSgu1smcaFKTYySPMxytgJZexoa/ALZyyE0gRhsvwHm +NLGCPt1bmE/PEGZybsCqliyTO0S56ncD55The7+D/UDS4kE1Wg0svlWon/YsE6QW +B3oeJDX7Kr8ebDTIAErevIAD7Sm4ee5se2zxYrsYlj0MzHZtvwIDAQABoxAwDjAM +BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCvQ1pTvjON6vSlcJRKSY4r +8q7L4/9ZaVXWJAjzEYJtPIqsgGiPWz0vGfgklowU6tZxp9zRZFXfMil+mPQSe+yo +ULrZSQ/z48YHPueE/BNO/nT4aaVBEhPLR5aVwC7uQVX8H+m1V1UGT8lk9vdI9rej +CI9l524sLCpdE4dFXiWK2XHEZ0Vfylk221u3IYEogVVA+UMX7BFPSsOnI2vtYK/i +lwZtlri8LtTusNe4oiTkYyq+RSyDhtAswg8ANgvfHolhCHoLFj6w1IkG88UCmbwN +d7BoGMy06y5MJxyXEZG0vR7eNeLey0TIh+rAszAFPsIQvrOHW+HuA+WLQAj1mhnm +-----END CERTIFICATE-----
\ No newline at end of file diff --git a/certServiceClient/src/test/resources/expectedFirstElementOfTrustedCertificates b/certServiceClient/src/test/resources/expectedFirstElementOfTrustedCertificates new file mode 100644 index 00000000..2d36a220 --- /dev/null +++ b/certServiceClient/src/test/resources/expectedFirstElementOfTrustedCertificates @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDtzCCAp8CFAwqQddh4/iyGfP8UZ3dpXlxfAN8MA0GCSqGSIb3DQEBCwUAMIGX +MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu +LUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwE +T05BUDERMA8GA1UEAwwIb25hcC5vcmcxHjAcBgkqhkiG9w0BCQEWD3Rlc3RlckBv +bmFwLm9yZzAeFw0yMDAyMTIwOTM0MjdaFw0yMTAyMTEwOTM0MjdaMIGXMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuLUZyYW5j +aXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwET05BUDER +MA8GA1UEAwwIb25hcC5vcmcxHjAcBgkqhkiG9w0BCQEWD3Rlc3RlckBvbmFwLm9y +ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCFrnO7/eT6V+7XkPPd +eiL/6xXreuegvit/1/jTVjG+3AOVcmTn2WXwXXRcQLvkWQfJVPoltsY8E3FqFRti +797XjY6cdQJFVDyzNU0+Fb4vJL9FK5wSvnS6EFjBEn3JvXRlENorDCs/mfjkjJoa +Dl74gXQEJYcg4nsTeNIj7cm3Q7VK3mZt1t7LSJJ+czxv69UJDuNJpmQ/2WOKyLZA +gTtBJ+Hyol45/OLsrqwq1dAn9ZRWIFPvRt/XQYH9bI/6MtqSreRVUrdYCiTe/XpP +B/OM6NEi2+p5QLi3Yi70CEbqP3HqUVbkzF+r7bwIb6M5/HxfqzLmGwLvD+6rYnUn +Bm8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAhXoO65DXth2X/zFRNsCNpLwmDy7r +PxT9ZAIZAzSxx3/aCYiuTrKP1JnqjkO+F2IbikrI4n6sKO49SKnRf9SWTFhd+5dX +vxq5y7MaqxHAY9J7+Qzq33+COVFQnaF7ddel2NbyUVb2b9ZINNsaZkkPXui6DtQ7 +/Fb/1tmAGWd3hMp75G2thBSzs816JMKKa9WD+4VGATEs6OSll4sv2fOZEn+0mAD3 +9q9c+WtLGIudOwcHwzPb2njtNntQSCK/tVOqbY+vzhMY3JW+p9oSrLDSdGC+pAKK +m/wB+2VPIYcsPMtIhHC4tgoSaiCqjXYptaOh4b8ye8CPBUCpX/AYYkN0Ow== +-----END CERTIFICATE-----
\ No newline at end of file diff --git a/certServiceClient/src/test/resources/expectedKeystore.jks b/certServiceClient/src/test/resources/expectedKeystore.jks Binary files differnew file mode 100644 index 00000000..95359b0e --- /dev/null +++ b/certServiceClient/src/test/resources/expectedKeystore.jks diff --git a/certServiceClient/src/test/resources/expectedTruststore.jks b/certServiceClient/src/test/resources/expectedTruststore.jks Binary files differnew file mode 100644 index 00000000..ab7d93d9 --- /dev/null +++ b/certServiceClient/src/test/resources/expectedTruststore.jks diff --git a/certServiceClient/src/test/resources/missingPkResponse b/certServiceClient/src/test/resources/missingPkResponse new file mode 100644 index 00000000..c53358e0 --- /dev/null +++ b/certServiceClient/src/test/resources/missingPkResponse @@ -0,0 +1,7 @@ +{ + "timestamp": "2020-02-25T06:36:23.651+0000", + "status": 400, + "error": "Bad Request", + "message": "Missing request header 'PK' for method parameter of type String", + "path": "//v1/certificate/TestCA" +}
\ No newline at end of file diff --git a/certServiceClient/src/test/resources/privateKey b/certServiceClient/src/test/resources/privateKey Binary files differnew file mode 100644 index 00000000..463a27d3 --- /dev/null +++ b/certServiceClient/src/test/resources/privateKey diff --git a/certServiceClient/src/test/resources/rsaPrivateKeyPem b/certServiceClient/src/test/resources/rsaPrivateKeyPem new file mode 100644 index 00000000..a99cc3c8 --- /dev/null +++ b/certServiceClient/src/test/resources/rsaPrivateKeyPem @@ -0,0 +1,28 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCwooLW/yfXHIGs +djOW6zCM6mzGq4ZkFr0LMVBE+Y9dckGsYJzCrfC4pQtFjcvTlwalu6/YOgieR/zY +bgVF7Ic0IYV+BssO+t6Zx2xYli4NIGc5kJgDrKtR6lWvH8AMnQEr+QiDElLBWobU ++QGn5v8A528Ow5yD1fmxKTqqvWS4v1rOShGCIdse5ViraGjnMFxOV6u6pGqa17v7 +dTh0XIUyF/o3aSbmBHXkmvQ4pu/K1ncsF2zHIqUWAc7j8y1u5uE5o8b+dUzkcS4t +QKfjFKP81I7XQNmpGZ8REzWyaYVk3RrMCju6iVgdKrs198Wif0b7wGswFv4BFhOp +2jceFUwfAgMBAAECggEABjDb9x8gTVjRbrMB4eNCY14ADAKNBksJuy+ySYiZrsPH +a3xDYktoaYBXYcuzfioH8J0gb6qxDKMnSIqqoqXEo14daKpiSZcfYDJuKLiyyoD9 +PTZFLbPKmWdmM2ogeBC0rs7eroFg5yf+G87ScQkWnPh/mvveK3y/cKcqSDu1IQh8 +3b8KQshC5g4iBqCfOMW3ASF03M4zmM3brKMWsdsAWEbFHQ34H10FXTHrAINpWIZK +s2NL3z9tK6hXrwlZdKH6R/JWczSO7O5MBjLfeXZK7q3Tw4qtFWWjcNwfPlUZKMAS +3fZFamFwY//qW+0yuCO59o70d9Pjm6p0DWsfOs9t8QKBgQD1iRdGV4xZXZT9Q4Wh +LQMnChjuNHcmhdBYbmC03j3AffQwkQ1dKt++9uWYdy9dO9v1w7aygAMQI36jkDvR +UJ1Rnmt9gQpeOL/wHP3R0uHbTtxLeGnX3Oo1Yx7Wfl98rq4mmBxjO5Lgft/6kTgz +XgeiNDWi53KwDEOoFaZhWihZ6QKBgQC4Ka5Hc9wXD/5utpvNs5ut+9zjY0kx6kr8 +SyDZExbVR1ohtvSQ2sd2JvZPyFS0VbvYfFPhyCYcWW9LDEX168CZT5aHgcNop1Iu +Szq8nYrljFa5Ibdlpf0qxC6JgObC2XytUR0O7BaXHBWpl0/wLpLTcfU2wTDLRoH8 +JLu7P3MoxwKBgQCI9DWqQ60CL8Op3J7NvviyLtynCVaogx0qJi8E062oD9lDubS1 +kfOJZde8ykX+ACR5mffu6p5KwzGg9BOZdhi57N5R+8cXtRnCSbl97t2R4RPZeMm4 +4P02WBpcU9LZDeoPlurGovUTCVHPRm8Nn9YsMGj2e5ip/71BJQpP5OT6+QKBgQCP +NYJb+AG3QW22hHQmArxWEFxVyrh5g1sqU/XIOCryUVkKjK4kEq02+NdjdUJBNcYs +c4n7MlxIgVelQXcJ5HlR/uzslQDy2eJzM3cKg2wmUvqBXnGyLuDvJ72UmdNYxC1K +zZ/OIdLzURibV5oHCQCOQrjQCm06NasQ+zOtSYrwswKBgQCUHhgxynFNyidxPFzX +V0X5xCbJ3jvJNjZFRsItQ97vEAkfJqxCnOZKMti0JWSlLBEViaKnqaA+ZE/SeJ/k +Jut5h9gu4QIdeF4mf9v3tjuEQP7RaMCD6xnFZnebkQf6wlZz5VaXME4ICpi1Cnk7 +DySS9CMoRnwdwY7hAbfPtupKDA== +-----END RSA PRIVATE KEY----- diff --git a/certServiceClient/src/test/resources/testCsr b/certServiceClient/src/test/resources/testCsr new file mode 100644 index 00000000..aa9387bf --- /dev/null +++ b/certServiceClient/src/test/resources/testCsr @@ -0,0 +1 @@ +LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJRExEQ0NBaFFDQVFBd2daQXhDekFKQmdOVkJBWVRBbEJNTVJZd0ZBWURWUVFJREExTWIzZGxjaTFUYVd4bGMybGhNUkF3RGdZRFZRUUhEQWRYY205amJHRjNNUTR3REFZRFZRUUtEQVZPYjJ0cFlURU5NQXNHQTFVRUN3d0VUMDVCVURFWE1CVUdBMVVFQXd3T2RHVnpkQzV1YjJ0cFlTNWpiMjB4SHpBZEJna3Foa2lHOXcwQkNRRVdFSFJsYzNSbGNrQnViMnRwWVM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFERzMwWUZKMDk3bS83dDJQV1pFbExBNmJ5bFc5Z1k0cDNod3NidC9paENqKzFqRG9YRFdpQk0wMXVGd1BqWmNiaXhwR3BQdXdVU3ZWREUzOUtwUDFHS3NCYVcrMHdLZG02Sit4YmN6ZTBEc0N6QUhCTnNYVXJEK3VzZC9jVUxOVm5UeXRZYzZubkF1VSswQzg0U1l6OGVkVHJ4UWVkSmF4MDBaS3YrdHluVnZvWUtyVVFsMlFrTDI4bFhhaWsxdWIzd1FGeFNQdndEM2xuMU81N2k0Wk9hOHlNcWx2NlpsTkxZYng2UFhsc1RqanBWTldPUllPKzdzeWdieEZ0bHYvbEgyN1BISHZJT3BUUmtGd0lVLzRHWXU2blQ0bDBqYkl0VEE0b2dhUFR6b3hodG5jaStLT1VVeVZ4OWk4eWd3cVBUb3d5UFkyNGpSb2xTd3RBQWpDYkJBZ01CQUFHZ1ZqQlVCZ2txaGtpRzl3MEJDUTR4UnpCRk1FTUdBMVVkRVFROE1EcUNEM1JsYzNReUxtNXZhMmxoTG1OdmJZSVBkR1Z6ZEM1dWIyc3VhWFF1WTI5dGdoWjBaWE4wTG1sdWRDNXVaWFF1Ym05cmFXRXVZMjl0TUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBUmRlNnpiT2R2TXdKSkFETGV0TmlXT0p3TU9Ec0RJeFduUDBjbXkwTVovb21KK21JZFJSb1NZV0t2VDl5OXd3a3A1Sllzb2htMUN4c0RvS1pBZHFWWTloeENMSUJWRktEL2FveUlRUzRhM3prZFBVa0lnWW00UzJxMkI3bTFjT2YxTHpYNzVSQ3BKN3N2SDZ3RFlqV2dEOTBsVW5uamphNUF2VnJTWnRCVUhEQWZsUG5DTmhXU3hMREhTSkZhWHhERkpGbjhpT1FhdDkvUmNERHc2M0lrbWVaLzBWWDhVRjRsaWp2VWcxSGc4WUFrdXVOQnNwTmRDY2FFVFZFUHJwS3BjaFQxdDg1YnA2RnppSHczc3ZCVTM2cmhzUGNQVU5IM1NYT2tVcmZlOXp0RmJzUFB4dmJtZWx1MWEwS2FudmhDbEU0Z1dMT2tWb1k2Q0hlUktYeU0KLS0tLS1FTkQgQ0VSVElGSUNBVEUgUkVRVUVTVC0tLS0t
\ No newline at end of file diff --git a/certServiceClient/src/test/resources/testPk b/certServiceClient/src/test/resources/testPk new file mode 100644 index 00000000..36bc9834 --- /dev/null +++ b/certServiceClient/src/test/resources/testPk @@ -0,0 +1 @@ +LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRREczMFlGSjA5N20vN3QyUFdaRWxMQTZieWxXOWdZNHAzaHdzYnQvaWhDaisxakRvWERXaUJNMDF1RndQalpjYml4cEdwUHV3VVN2VkRFMzlLcFAxR0tzQmFXKzB3S2RtNkoreGJjemUwRHNDekFIQk5zWFVyRCt1c2QvY1VMTlZuVHl0WWM2bm5BdVUrMEM4NFNZejhlZFRyeFFlZEpheDAwWkt2K3R5blZ2b1lLclVRbDJRa0wyOGxYYWlrMXViM3dRRnhTUHZ3RDNsbjFPNTdpNFpPYTh5TXFsdjZabE5MWWJ4NlBYbHNUampwVk5XT1JZTys3c3lnYnhGdGx2L2xIMjdQSEh2SU9wVFJrRndJVS80R1l1Nm5UNGwwamJJdFRBNG9nYVBUem94aHRuY2krS09VVXlWeDlpOHlnd3FQVG93eVBZMjRqUm9sU3d0QUFqQ2JCQWdNQkFBRUNnZ0VBTHdIcHFDQXhubk15SUFCdmxSNEtwNFRZVFhIWE01S2xaUTdJUE1zZHN4WVlNNWprTDFmbldLR0ErYTJ5Wkp1SDM1MlFiNFl5WGNxWUErRXdCMGRyTzlBQmx2Q1JlY3VpdDBTOWs3V3ROM2oyS3ZhMzlKNWNwTlJ6ck9RbUprOFhDNFBmZG5oS0RTOEFVdnVUV3k5UVpSK3FyZ280NUZiSVVYRVdZcC9pNkoyMGR3WW44Sm9HamV5WkFBdVhKQktOYzRJNDRndmNQUHJ4ZHBzMUh6dG5WU2RXbE1wL2lDZnc2YnNlRG94aCtkcXYrTXBrbUhROEV6WVZyVUNmbnhsTWNoMmtwenJpOXdTS3ZrZmMzckFieUpTWnhPQ3hYd2ZvTit3M05JQlpOQzh3WStIZC9nVzJPdFNkY2JOaHJ5UWdjMUVWVGtBdVdzTG1jNXZiTjRZQUVRS0JnUUR1WUdCUmVGZ3FUT1BhNHJJVEZhY1BSZm1qdGNmRnpqSEJLNDA5emhSL0VEWERDNGdxVmpxYWZGSkNIWFp4USt2Q1N3UXBvYVpQcTgraWFmc0pVTUdlcjhLNGdQR0xJTmVueFF2ZEF2c2M4NnA2MzZlakYxbFVLdzA4Rmhzam5zL3pyeGxhZnB3eWpGb0RIcFBoWGg2R25sNGx1NmEycGF2bm8wK3dzWGNRZFFLQmdRRFZremhzY1h1SG0wMnZTTE9KN1RZOHEzQSthbUZrb2hBOVY0YmpJYVpBZ2ZoVHZjMS9aSWM4THNRQmZBL2RKZ0R1eldOYjVqckJ5S0NQMWZDU1FZZ2VybmpSYXFRRlB6ZC82bmswSWZzNjUreUJ6bHlBVDVQNjB0Qjk2NEhsSjBYODRnc1owZlMweFlBRTNxWW83UG1QRUNDRXJPQ05FZTlLRXZabjBVanpuUUtCZ1FEYVAyMFFTbkhXVU0yeFl5c05KQjd2Y2U3TlA2cW5aVkRTZnJCemJOSUJQL01wSDg3TWpHUmRld1BKT3JadG4zVWtUNUNCR1ZwdXlXeHlWRHdlWEV6Wm9DeFV4dUhmc3ZNZnpONCt2UEx5bi9sdlJJUjBZdlZMaFpzNWJ6ZnIxZ1NwSktDKzVQclhvUDdzcWp0VTlOcFlBSGxNYk5HSG1vbVlyRUpURVRoazNRS0JnR1FCRm5kNHY4M2tnNENpK3lhSFExRXZPVlNRZldBZ25wZ0todWVObHdvM2tXNnN2aTk3Zy9ORE5wWTNZRG8rRkV1OU1sd1N0c3FNUmRwejQ3eW9JTE8xSUc5MmpxekNTQnVHVUJDQUpPSVZQT0lmSGFNYklBQmZmQzZwK3QyeEFRMkRUbzFkaVVhbi8rVEgyR2ZyWm9OOW1xeGxRcFBycE84N1o5Tis1TGpsQW9HQVhFQXI5Vmo5WmF3bE5yV0VZYjgyN1J6NVNFZkFjSmFFeTVhVzFUVWNzZVc0bWgwYmNuTzVCSHQvYTFmN3VoQmJoY2xQVFlPOTBSNGpLcUtGK2lVa2VDRHV0TmcrM09ncTdKaS9PWk5vajRSaUM1WWV4TWs5d1kxc3NVV0pqbDVoUURpd1BRQU5Zc09TSWxOT3Z2SWpydG81RnhNWVN5UndHamYrYnRSTzIyYz0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQ
\ No newline at end of file @@ -53,6 +53,7 @@ <springdoc-openapi-maven-plugin.version>0.2</springdoc-openapi-maven-plugin.version> <gson.version>2.8.6</gson.version> <httpcomponents.version>4.5.6</httpcomponents.version> + <commons-lang3.version>3.9</commons-lang3.version> <commons-io.version>2.6</commons-io.version> <docker-maven-plugin.version>0.33.0</docker-maven-plugin.version> <junit.version>5.5.2</junit.version> @@ -235,6 +236,11 @@ <version>${httpcomponents.version}</version> </dependency> <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>${commons-lang3.version}</version> + </dependency> + <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>${commons-io.version}</version> @@ -257,13 +263,7 @@ </dependency> <dependency> <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-engine</artifactId> - <version>${junit.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-api</artifactId> + <artifactId>junit-jupiter</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> |