aboutsummaryrefslogtreecommitdiffstats
path: root/certService
diff options
context:
space:
mode:
authorBartosz Gardziejewski <bartosz.gardziejewski@nokia.com>2020-02-11 13:27:08 +0100
committerBartosz Gardziejewski <bartosz.gardziejewski@nokia.com>2020-02-11 13:29:13 +0100
commitbddd4f0e38e09fb8479e9f97313fdb41297c2990 (patch)
treea74810e1817d4e848ea37a15a7331cfc811b7bfd /certService
parent5dfe938a07dcaa2e0a2da4cf40d434ab200667b2 (diff)
Add decoding CSR received from client.
Issue-ID: AAF-995 Signed-off-by: Bartosz Gardziejewski <bartosz.gardziejewski@nokia.com> Change-Id: I7c868f4835397f58ae4e6fad0e764e21d886d3d3
Diffstat (limited to 'certService')
-rw-r--r--certService/README.md16
-rw-r--r--certService/pom.xml12
-rw-r--r--certService/src/main/java/org/onap/aaf/certservice/api/CertificationService.java82
-rw-r--r--certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java70
-rw-r--r--certService/src/main/java/org/onap/aaf/certservice/certification/PemObjectFactory.java44
-rw-r--r--certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/CsrDecryptionException.java27
-rw-r--r--certService/src/main/java/org/onap/aaf/certservice/certification/model/CsrModel.java85
-rw-r--r--certService/src/main/java/org/onap/aaf/certservice/rest/CertificationService.java61
-rw-r--r--certService/src/test/java/org/onap/aaf/certservice/api/CertificationServiceTest.java96
-rw-r--r--certService/src/test/java/org/onap/aaf/certservice/certification/CsrModelFactoryTest.java88
-rw-r--r--certService/src/test/java/org/onap/aaf/certservice/certification/PemObjectFactoryTest.java70
-rw-r--r--certService/src/test/java/org/onap/aaf/certservice/certification/TestData.java95
-rw-r--r--certService/src/test/java/org/onap/aaf/certservice/certification/TestUtils.java47
-rw-r--r--certService/src/test/java/org/onap/aaf/certservice/certification/model/CsrModelTest.java112
14 files changed, 842 insertions, 63 deletions
diff --git a/certService/README.md b/certService/README.md
index 25bb6720..db96fa98 100644
--- a/certService/README.md
+++ b/certService/README.md
@@ -95,4 +95,18 @@ audit.log error.log trace.log
### Sonar results
```
https://sonarcloud.io/dashboard?id=onap_aaf-certservice
- ``` \ No newline at end of file
+ ```
+
+### RestAPI
+API is described by Swagger ( OpenAPI 3.0 ) on endpoint /docs
+( endpoint is defined in properties as springdoc.swagger-ui.path )
+
+ ```
+ http://localchost:8080/docs
+
+ ```
+
+### Sonar results
+ ```
+ https://sonarcloud.io/dashboard?id=onap_aaf-certservice
+ ```
diff --git a/certService/pom.xml b/certService/pom.xml
index 8402d749..38c356c4 100644
--- a/certService/pom.xml
+++ b/certService/pom.xml
@@ -20,7 +20,6 @@
<artifactId>aaf-certservice-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
- <groupId>org.onap.aaf</groupId>
<artifactId>cert-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cert-service</name>
@@ -38,6 +37,7 @@
<spring-boot-starter-actuator.version>2.2.4.RELEASE</spring-boot-starter-actuator.version>
<spring-boot-starter-log4j2.version>2.1.5.RELEASE</spring-boot-starter-log4j2.version>
<springdoc-openapi-ui.version>1.2.21</springdoc-openapi-ui.version>
+ <bouncycastle.version>1.60</bouncycastle.version>
<docker-maven-plugin.version>0.33.0</docker-maven-plugin.version>
</properties>
@@ -105,6 +105,16 @@
<artifactId>springdoc-openapi-ui</artifactId>
<version>${springdoc-openapi-ui.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <version>${bouncycastle.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk15on</artifactId>
+ <version>${bouncycastle.version}</version>
+ </dependency>
</dependencies>
<build>
diff --git a/certService/src/main/java/org/onap/aaf/certservice/api/CertificationService.java b/certService/src/main/java/org/onap/aaf/certservice/api/CertificationService.java
new file mode 100644
index 00000000..a46e07fc
--- /dev/null
+++ b/certService/src/main/java/org/onap/aaf/certservice/api/CertificationService.java
@@ -0,0 +1,82 @@
+/*
+ * ============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.CsrModelFactory;
+import org.onap.aaf.certservice.certification.CsrModelFactory.StringBase64;
+import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
+import org.onap.aaf.certservice.certification.model.CsrModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RestController;
+
+
+@RestController
+public class CertificationService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CertificationService.class);
+
+ private final CsrModelFactory csrModelFactory;
+
+ @Autowired
+ CertificationService(CsrModelFactory csrModelFactory) {
+ this.csrModelFactory = csrModelFactory;
+ }
+
+ /**
+ * Request for signing certificate by given CA.
+ *
+ *
+ * @param caName the name of Certification Authority that will sign root certificate
+ * @param encodedCsr Certificate Sign Request encoded in Base64 form
+ * @param encodedPrivateKey Private key for CSR, needed for PoP, encoded in Base64 form
+ * @return JSON containing trusted certificates and certificate chain
+ */
+ @GetMapping("v1/certificate/{caName}")
+ public ResponseEntity<String> signCertificate(
+ @PathVariable String caName,
+ @RequestHeader("CSR") String encodedCsr,
+ @RequestHeader("PK") String encodedPrivateKey
+ ) {
+ caName = caName.replaceAll("[\n|\r|\t]", "_");
+ LOGGER.info("Received certificate signing request for CA named: {}", caName);
+
+ try {
+ CsrModel csrModel = csrModelFactory.createCsrModel(
+ new StringBase64(encodedCsr),
+ new StringBase64(encodedPrivateKey)
+ );
+ LOGGER.debug("Received CSR meta data: \n{}", csrModel);
+ return new ResponseEntity<>(csrModel.toString(), HttpStatus.OK);
+ } catch (CsrDecryptionException e) {
+ LOGGER.error("Exception occurred during certificate signing:", e);
+ return new ResponseEntity<>("Wrong certificate signing request (CSR) format", HttpStatus.BAD_REQUEST);
+ }
+ }
+
+
+}
diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java b/certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java
new file mode 100644
index 00000000..80858f4d
--- /dev/null
+++ b/certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java
@@ -0,0 +1,70 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification;
+
+import java.io.IOException;
+import java.util.Base64;
+
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
+import org.onap.aaf.certservice.certification.model.CsrModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+
+@Service
+public class CsrModelFactory {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CsrModelFactory.class);
+ private final PemObjectFactory pemObjectFactory = new PemObjectFactory();
+
+ public CsrModel createCsrModel(StringBase64 csr, StringBase64 privateKey) throws CsrDecryptionException {
+ LOGGER.debug("Decoded CSR: \n{}", csr.asString());
+
+ try {
+ PemObject pemObject = pemObjectFactory.createPmObject(csr.asString());
+ PKCS10CertificationRequest decodedCsr = new PKCS10CertificationRequest(
+ pemObject.getContent()
+ );
+ PemObject decodedPrivateKey = pemObjectFactory.createPmObject(privateKey.asString());
+ return new CsrModel(decodedCsr, decodedPrivateKey);
+ } catch (IOException e) {
+ throw new CsrDecryptionException("Incorrect CSR, decryption failed", e);
+ }
+ }
+
+ public static class StringBase64 {
+ private final String value;
+ private final Base64.Decoder decoder = Base64.getDecoder();
+
+ public StringBase64(String value) {
+ this.value = value;
+ }
+
+ public String asString() {
+ return new String(decoder.decode(value));
+ }
+ }
+}
+
+
diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/PemObjectFactory.java b/certService/src/main/java/org/onap/aaf/certservice/certification/PemObjectFactory.java
new file mode 100644
index 00000000..e3339cc4
--- /dev/null
+++ b/certService/src/main/java/org/onap/aaf/certservice/certification/PemObjectFactory.java
@@ -0,0 +1,44 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.bouncycastle.util.io.pem.PemObject;
+import org.bouncycastle.util.io.pem.PemReader;
+
+import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
+
+
+public class PemObjectFactory {
+
+ public PemObject createPmObject(String pem) throws CsrDecryptionException {
+
+ try (StringReader stringReader = new StringReader(pem);
+ PemReader pemReader = new PemReader(stringReader)) {
+ return pemReader.readPemObject();
+ } catch (IOException e) {
+ throw new CsrDecryptionException("Unable to create PEM", e);
+ }
+ }
+
+}
diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/CsrDecryptionException.java b/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/CsrDecryptionException.java
new file mode 100644
index 00000000..fb16ad91
--- /dev/null
+++ b/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/CsrDecryptionException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification.exceptions;
+
+public class CsrDecryptionException extends Exception {
+ public CsrDecryptionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/model/CsrModel.java b/certService/src/main/java/org/onap/aaf/certservice/certification/model/CsrModel.java
new file mode 100644
index 00000000..ef76144b
--- /dev/null
+++ b/certService/src/main/java/org/onap/aaf/certservice/certification/model/CsrModel.java
@@ -0,0 +1,85 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification.model;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.bouncycastle.util.io.pem.PemObject;
+
+import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
+
+
+public class CsrModel {
+
+
+ private final PKCS10CertificationRequest csr;
+ private final PemObject privateKey;
+
+ public CsrModel(PKCS10CertificationRequest csr, PemObject privateKey) {
+ this.csr = csr;
+ this.privateKey = privateKey;
+ }
+
+ public PemObject getPublicKey() throws CsrDecryptionException {
+ try {
+ return new PemObject("PUBLIC KEY", csr.getSubjectPublicKeyInfo().getEncoded());
+ } catch (IOException e) {
+ throw new CsrDecryptionException("Reading Public Key from CSR failed", e.getCause());
+ }
+ }
+
+ public PemObject getPrivateKey() {
+ return privateKey;
+ }
+
+ public X500Name getSubjectData() {
+ return csr.getSubject();
+ }
+
+ public List<String> getSansData() {
+ Extensions extensions =
+ Extensions.getInstance(csr.getAttributes()[0].getAttrValues().getObjectAt(0));
+ GeneralName[] arrayOfAlternativeNames =
+ GeneralNames.fromExtensions(extensions, Extension.subjectAlternativeName).getNames();
+
+ return Arrays.stream(arrayOfAlternativeNames)
+ .map(GeneralName::getName)
+ .map(Objects::toString)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public String toString() {
+ return "Subject: { " + getSubjectData().toString()
+ + " ,SANs: " + getSansData().toString() + " }";
+ }
+
+}
diff --git a/certService/src/main/java/org/onap/aaf/certservice/rest/CertificationService.java b/certService/src/main/java/org/onap/aaf/certservice/rest/CertificationService.java
deleted file mode 100644
index 7a93bffa..00000000
--- a/certService/src/main/java/org/onap/aaf/certservice/rest/CertificationService.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * PROJECT
- * ================================================================================
- * Copyright (C) 2020 Nokia. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.aaf.certservice.rest;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.util.Base64;
-
-@RestController
-public class CertificationService {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(CertificationService.class);
- private static final Base64.Decoder DECODER = Base64.getDecoder();
-
- @GetMapping("/csr/{caName}")
- public ResponseEntity<String> getEncodesCSR(
- @PathVariable String caName,
- @RequestHeader("CSR") String encodedCSR,
- @RequestHeader("PK") String encodedPrivateKey
- ) {
-
- String csr = decode(encodedCSR);
- String privateKey = decode(encodedPrivateKey);
-
- LOGGER.info("Received CSR for CA named: {}",caName);
- LOGGER.debug("Decoded received CSR: \n{}", csr);
-
- return new ResponseEntity<>(csr, HttpStatus.OK);
-
- }
-
- private String decode(String encodedData) {
- return new String(DECODER.decode(encodedData));
- }
-
-}
diff --git a/certService/src/test/java/org/onap/aaf/certservice/api/CertificationServiceTest.java b/certService/src/test/java/org/onap/aaf/certservice/api/CertificationServiceTest.java
new file mode 100644
index 00000000..99ca09b9
--- /dev/null
+++ b/certService/src/test/java/org/onap/aaf/certservice/api/CertificationServiceTest.java
@@ -0,0 +1,96 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.api;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.aaf.certservice.certification.CsrModelFactory;
+import org.onap.aaf.certservice.certification.CsrModelFactory.StringBase64;
+import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
+import org.onap.aaf.certservice.certification.model.CsrModel;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+class CertificationServiceTest {
+
+ private CertificationService certificationService;
+
+ @Mock
+ private CsrModelFactory csrModelFactory;
+
+ @BeforeEach
+ void serUp() {
+ MockitoAnnotations.initMocks(this);
+ certificationService = new CertificationService(csrModelFactory);
+ }
+
+ @Test
+ void shouldReturnDataAboutCsrBaseOnEncodedParameters() throws CsrDecryptionException {
+ // given
+ final String testStringCsr = "testData";
+ CsrModel mockedCsrModel = mock(CsrModel.class);
+ when(mockedCsrModel.toString()).thenReturn(testStringCsr);
+ when(csrModelFactory.createCsrModel(any(StringBase64.class), any(StringBase64.class)))
+ .thenReturn(mockedCsrModel);
+
+ // when
+ ResponseEntity<String> testResponse =
+ certificationService.signCertificate("TestCa", "encryptedCSR", "encryptedPK");
+
+ // then
+ assertEquals(testResponse.getStatusCode(), HttpStatus.OK);
+ assertTrue(
+ testResponse.toString().contains(testStringCsr)
+ );
+ }
+
+ @Test
+ void shouldReturnBadRequestWhenCreatingCsrModelFails() throws CsrDecryptionException {
+ // given
+ when(csrModelFactory.createCsrModel(any(StringBase64.class), any(StringBase64.class)))
+ .thenThrow(new CsrDecryptionException("creation fail",new IOException()));
+
+ // when
+ ResponseEntity<String> testResponse =
+ certificationService.signCertificate("TestCa", "encryptedCSR", "encryptedPK");
+
+ String expectedMessage = "Wrong certificate signing request (CSR) format";
+
+ // then
+ assertEquals(HttpStatus.BAD_REQUEST, testResponse.getStatusCode());
+ assertTrue(
+ testResponse.toString().contains(expectedMessage)
+ );
+
+ }
+
+}
diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/CsrModelFactoryTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/CsrModelFactoryTest.java
new file mode 100644
index 00000000..8b5f5dc5
--- /dev/null
+++ b/certService/src/test/java/org/onap/aaf/certservice/certification/CsrModelFactoryTest.java
@@ -0,0 +1,88 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.onap.aaf.certservice.certification.CsrModelFactory.StringBase64;
+import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
+import org.onap.aaf.certservice.certification.model.CsrModel;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.onap.aaf.certservice.certification.TestData.TEST_CSR;
+import static org.onap.aaf.certservice.certification.TestData.TEST_PK;
+import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_CSR;
+
+
+class CsrModelFactoryTest {
+
+ private CsrModelFactory csrModelFactory;
+
+ @BeforeEach
+ void setUp() {
+ csrModelFactory = new CsrModelFactory();
+ }
+
+ @Test
+ void shouldDecryptCsrAndReturnStringWithDataAboutIt() throws CsrDecryptionException {
+ // given
+ String encoderCsr = new String(Base64.encode(TEST_CSR.getBytes()));
+ String encoderPK = new String(Base64.encode(TEST_PK.getBytes()));
+
+ // when
+ CsrModel decryptedCsr = csrModelFactory
+ .createCsrModel(new StringBase64(encoderCsr), new StringBase64(encoderPK));
+
+ // then
+ assertTrue(
+ decryptedCsr.toString()
+ .contains(
+ "C=US,ST=California,L=San-Francisco,O=Linux-Foundation,"
+ + "OU=ONAP,CN=onap.org,E=tester@onap.org")
+ &&
+ decryptedCsr.toString()
+ .contains("SANs: [gerrit.onap.org, test.onap.org, onap.com]")
+ );
+ }
+
+
+ @Test
+ void shouldThrowCsrDecryptionExceptionWhenCsrAreIncorrect() {
+ // given
+ String encoderPK = new String(Base64.encode(TEST_PK.getBytes()));
+ String wrongCsr = new String(Base64.encode(TEST_WRONG_CSR.getBytes()));
+
+ // when
+ Exception exception = assertThrows(
+ CsrDecryptionException.class, () -> csrModelFactory
+ .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK))
+ );
+
+ String expectedMessage = "Incorrect CSR, decryption failed";
+ String actualMessage = exception.getMessage();
+
+ // then
+ assertTrue(actualMessage.contains(expectedMessage));
+ }
+
+}
diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/PemObjectFactoryTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/PemObjectFactoryTest.java
new file mode 100644
index 00000000..67d7f1dc
--- /dev/null
+++ b/certService/src/test/java/org/onap/aaf/certservice/certification/PemObjectFactoryTest.java
@@ -0,0 +1,70 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification;
+
+import org.bouncycastle.util.io.pem.PemObject;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.onap.aaf.certservice.certification.TestData.TEST_PEM;
+import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_PEM;
+import static org.onap.aaf.certservice.certification.TestUtils.pemObjectToString;
+
+
+class PemObjectFactoryTest {
+
+
+ private PemObjectFactory pemObjectFactory;
+
+ @BeforeEach
+ void setUp() {
+ pemObjectFactory = new PemObjectFactory();
+ }
+
+ @Test
+ void shouldTransformStringInToPemObjectAndBackToString() throws CsrDecryptionException {
+ // when
+ PemObject pemObject = pemObjectFactory.createPmObject(TEST_PEM);
+ String parsedPemObject = pemObjectToString(pemObject);
+
+ // then
+ assertEquals(TEST_PEM, parsedPemObject);
+ }
+
+ @Test
+ void shouldThrowExceptionWhenParsingPemFailed() {
+ // when
+ Exception exception = assertThrows(
+ CsrDecryptionException.class, () -> pemObjectFactory.createPmObject(TEST_WRONG_PEM)
+ );
+
+ String expectedMessage = "Unable to create PEM";
+ String actualMessage = exception.getMessage();
+
+ // then
+ assertTrue(actualMessage.contains(expectedMessage));
+ }
+
+}
diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/TestData.java b/certService/src/test/java/org/onap/aaf/certservice/certification/TestData.java
new file mode 100644
index 00000000..6fea5b5a
--- /dev/null
+++ b/certService/src/test/java/org/onap/aaf/certservice/certification/TestData.java
@@ -0,0 +1,95 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification;
+
+public final class TestData {
+
+ private TestData() {
+ }
+
+ public static final String TEST_CSR = ""
+ + "-----BEGIN CERTIFICATE REQUEST-----\n"
+ + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh\n"
+ + "MRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQKDBBMaW51eC1Gb3VuZGF0\n"
+ + "aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQDDAhvbmFwLm9yZzEeMBwGCSqGSIb3\n"
+ + "DQEJARYPdGVzdGVyQG9uYXAub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"
+ + "CgKCAQEA13K1LrQ1L6eL7B8K4kucNct0sSjZe7Ww91V40s6mjcWajeFJk+pObZKz\n"
+ + "BfnImkVJwxdNMDD6tX16wykbGfQPyh4BBiAjLVk9XSeoPHFRBQ4LKTuyPtXhEXyr\n"
+ + "qwatYXGWZE554qq64pbReddOUJHgMc38SrOk/eMAKxB0uRrXpA0mPH7zwIZ4X8g2\n"
+ + "PoxJKI1BSYc8kOvvujsGSMw3e5nS8A+doFUwVi3jJMnaVCoZrvJbtREfXHZqBLQ5\n"
+ + "XQ8mNpIFfmGYF/tvW/O6LBdlZkuAQ9i4FBgf5+HdIVZOXrn09ksIZxW6vxIvAVi0\n"
+ + "5AOSgXictyphcNP2i/erBeCQCVB7MwIDAQABoEYwRAYJKoZIhvcNAQkOMTcwNTAz\n"
+ + "BgNVHREELDAqgg9nZXJyaXQub25hcC5vcmeCDXRlc3Qub25hcC5vcmeCCG9uYXAu\n"
+ + "Y29tMA0GCSqGSIb3DQEBCwUAA4IBAQBXH2nRwodQRJTuyrLe/VSg3PUdcPyAx2Ew\n"
+ + "63tWiGO+qWo8rK2a9Rr/t/zkQe2lx6NHqcMc2Rt6NeKGbrAvHGxTiYM35gktBdxG\n"
+ + "UaQS1ymrBWHAwbC+kv78r+5lCfafNm/EVdhUZbEw+crsw2wx4iKEW0byS4Ln0o5g\n"
+ + "aXVUW3i4G5FaYiYBUIDsujDdnH1IoxunEA6pDzDv1h6R9/TYu6Se8HToREIjOPBZ\n"
+ + "pDI5lDRu0YmI8r+TmAU3tTT1sY2WVxYDnhJut9ofegfMPQV4FIohxtPcCfoLSWti\n"
+ + "ml6jbcFqDvlzq3B3CXH9HU3jdJt33iSjCQGsSqy6bmCOdMS6XTPU\n"
+ + "-----END CERTIFICATE REQUEST-----\n";
+
+ public static final String TEST_WRONG_CSR = ""
+ + "-----BEGIN CERTIFICATE REQUEST-----\n"
+ + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh\n"
+ + "MRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQKDBBMaW51eC1Gb3VuZGF0\n"
+ + "aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQDDAhvbmFwLm9yZzEeMBwGCSqGSIb3\n"
+ + "-----END CERTIFICATE REQUEST-----\n";
+
+ public static final String TEST_PK = "-----BEGIN PRIVATE KEY-----\n"
+ + "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDXcrUutDUvp4vs\n"
+ + "HwriS5w1y3SxKNl7tbD3VXjSzqaNxZqN4UmT6k5tkrMF+ciaRUnDF00wMPq1fXrD\n"
+ + "KRsZ9A/KHgEGICMtWT1dJ6g8cVEFDgspO7I+1eERfKurBq1hcZZkTnniqrriltF5\n"
+ + "105QkeAxzfxKs6T94wArEHS5GtekDSY8fvPAhnhfyDY+jEkojUFJhzyQ6++6OwZI\n"
+ + "zDd7mdLwD52gVTBWLeMkydpUKhmu8lu1ER9cdmoEtDldDyY2kgV+YZgX+29b87os\n"
+ + "F2VmS4BD2LgUGB/n4d0hVk5eufT2SwhnFbq/Ei8BWLTkA5KBeJy3KmFw0/aL96sF\n"
+ + "4JAJUHszAgMBAAECggEAJ1StdsU3IGf5xzUzi3Q6JCfsOZs3eLoGgGB+Gh3XkfIM\n"
+ + "8PG7uOEBSEeLnv+me2NCv/a1BKMsYY1yp8YNSIOhjkhD75ZWVaUA6syejcox/DZA\n"
+ + "G1rmg0oQOF0GCcbCSBOwXMdmwNZiH5Ng0llX1qWKxAzSjeCVsjOKiFIMvO4Fh9D4\n"
+ + "9Io6/dRRNCxB6MEs1GT5IDfCV2PGDIalJ3znFqDnfdu9RDEDfNVHSUr6Jdu3Hrf5\n"
+ + "3qCcSEkMGuXYLotCNtTP1x0H0wW5gVpcbQEb29qdmHL1qkp3UiA3afsHnO/3k0gv\n"
+ + "gV5FxaldugyZAjqUGERdKaY6BMDJkDuu0qD0tPQK4QKBgQDuP5X5BcQ4iHNej+il\n"
+ + "xxT8QaEcZj0YEzcXzfm3ztZP7g+Jc1MbQXh6BuHLkXG5LeCwdnmk+LUD0MLoUSm3\n"
+ + "N2ZdtVuOHX7VEBrhrTwK/kMDpC7ganQzfvgOr9WQGmgGMRiUYAyK1J/x78yX967Z\n"
+ + "IAzdVZ/JSDdsyA983JckLL7CPQKBgQDngDkEJKYGfDt2mfItD8c8nhczGbDdoyYh\n"
+ + "s93ppTtgzFoNgFL4y/DOvisWMGgoeeYXSgH5uoPv6yY7IIkQzYySY6qQ3gmk1/X+\n"
+ + "bO+IsKVtlHBzqqojFteg3MfVojisMoAx6y5aBw1BXE2nAU8yWBTtuk+3KgGn9Oxk\n"
+ + "+Z4rdP06LwKBgA4b09zIW6NhaTubWBKhJHv/wvO0lj+bu7J8LyKUbBqVpXPlUXGW\n"
+ + "wfSv/aUZetuVfO3WRkPfupB8R16Ml+TSsgwwljhnRMCHUKA2qwyXnA5WJbSCeVkn\n"
+ + "Vrc/8Gy1M53SQHtg6L079DDWm44QS9ltzXU6Adlgnm+htVEWmxi4UZ+dAoGAfr6z\n"
+ + "+LG7+GcCA2AruEIgOe7wErkpHV+am+8nOymMxeV8FFJCmxbFQ9vYKTDdhfOfZvbM\n"
+ + "+BYG8E8VQmAAyyNOqENK+j+mlgrrEp4/0t2r5L/VhW5V8hoqelcGTc+gKZ8IkswJ\n"
+ + "N58Owc8wcJQF8TFKXBGaXVTxTSyKVIpZ778AeV8CgYAAvuicDkdwWv5EhDFf3aTI\n"
+ + "wfRFYflA6oiygnI63HzVyY4a+SyZs+nQpB5HBDo+Lyz8RaVRC5E7jQ8kiXJpxAu7\n"
+ + "1wnspz+pa3q61yR32N+zGuub71FXdLWSOlys6rzJqvqYihKxY22C2TyDyBCR2tMj\n"
+ + "mdnshXNAJfKkfghkJhFHrg==\n"
+ + "-----END PRIVATE KEY-----";
+
+ public static final String TEST_PEM = ""
+ + "-----BEGIN CERTIFICATE REQUEST-----\n"
+ + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh\n"
+ + "-----END CERTIFICATE REQUEST-----\n";
+
+ public static final String TEST_WRONG_PEM = ""
+ + "-----BEGIN WRONG REQUEST-----"
+ + "MIIDIzCCAgsCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh"
+ + "-----END WRONG REQUEST-----";
+
+}
diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/TestUtils.java b/certService/src/test/java/org/onap/aaf/certservice/certification/TestUtils.java
new file mode 100644
index 00000000..156cf8ba
--- /dev/null
+++ b/certService/src/test/java/org/onap/aaf/certservice/certification/TestUtils.java
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification;
+
+import org.bouncycastle.util.io.pem.PemObject;
+import org.bouncycastle.util.io.pem.PemWriter;
+import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+
+public final class TestUtils {
+
+ private TestUtils() {
+ }
+
+ public static String pemObjectToString(PemObject pemObject) throws CsrDecryptionException {
+ try (StringWriter output = new StringWriter()) {
+ PemWriter pemWriter = new PemWriter(output);
+ pemWriter.writeObject(pemObject);
+ pemWriter.close();
+ return output.getBuffer().toString();
+
+ } catch (IOException e) {
+ throw new CsrDecryptionException("Writing PAM Object to string failed", e);
+ }
+ }
+}
diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/model/CsrModelTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/model/CsrModelTest.java
new file mode 100644
index 00000000..ffce61d8
--- /dev/null
+++ b/certService/src/test/java/org/onap/aaf/certservice/certification/model/CsrModelTest.java
@@ -0,0 +1,112 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification.model;
+
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.junit.jupiter.api.Test;
+import org.onap.aaf.certservice.certification.PemObjectFactory;
+import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
+
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.onap.aaf.certservice.certification.TestData.TEST_CSR;
+import static org.onap.aaf.certservice.certification.TestData.TEST_PK;
+import static org.onap.aaf.certservice.certification.TestUtils.pemObjectToString;
+
+
+class CsrModelTest {
+
+
+ @Test
+ void shouldByConstructedAndReturnProperFields() throws CsrDecryptionException, IOException {
+ // given
+ PemObject testPublicKey = generateTestPublicKey();
+
+ // when
+ CsrModel csrModel = generateTestCsrModel();
+
+
+ // then
+ assertEquals(
+ pemObjectToString(csrModel.getPrivateKey()).trim(),
+ TEST_PK.trim());
+ assertEquals(
+ pemObjectToString(csrModel.getPublicKey()).trim(),
+ pemObjectToString((testPublicKey)).trim());
+ assertThat(csrModel.getSansData())
+ .contains(
+ "gerrit.onap.org", "test.onap.org", "onap.com");
+ assertThat(csrModel.getSubjectData().toString())
+ .contains(
+ "C=US,ST=California,L=San-Francisco,O=Linux-Foundation,OU=ONAP,CN=onap.org,E=tester@onap.org");
+ }
+
+ @Test
+ void shouldThrowExceptionWhenKeyIsNotCorrect() throws IOException, CsrDecryptionException {
+ // given
+ PemObjectFactory pemObjectFactory = new PemObjectFactory();
+ PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class);
+ SubjectPublicKeyInfo wrongKryInfo = mock(SubjectPublicKeyInfo.class);
+ when(testCsr.getSubjectPublicKeyInfo())
+ .thenReturn(wrongKryInfo);
+ when(wrongKryInfo.getEncoded())
+ .thenThrow(new IOException());
+ PemObject testPrivateKey = pemObjectFactory.createPmObject(TEST_PK);
+ CsrModel csrModel = new CsrModel(testCsr, testPrivateKey);
+
+ // when
+ Exception exception = assertThrows(
+ CsrDecryptionException.class,
+ csrModel::getPublicKey
+ );
+
+ String expectedMessage = "Reading Public Key from CSR failed";
+ String actualMessage = exception.getMessage();
+
+ // then
+ assertTrue(actualMessage.contains(expectedMessage));
+ }
+
+ private CsrModel generateTestCsrModel() throws CsrDecryptionException, IOException {
+ PemObjectFactory pemObjectFactory = new PemObjectFactory();
+ PKCS10CertificationRequest testCsr = new PKCS10CertificationRequest(
+ pemObjectFactory.createPmObject(TEST_CSR).getContent()
+ );
+ PemObject testPrivateKey = pemObjectFactory.createPmObject(TEST_PK);
+ return new CsrModel(testCsr, testPrivateKey);
+ }
+
+ private PemObject generateTestPublicKey() throws CsrDecryptionException, IOException {
+ PemObjectFactory pemObjectFactory = new PemObjectFactory();
+ PKCS10CertificationRequest testCsr = new PKCS10CertificationRequest(
+ pemObjectFactory.createPmObject(TEST_CSR).getContent()
+ );
+ return new PemObject("PUBLIC KEY", testCsr.getSubjectPublicKeyInfo().getEncoded());
+ }
+}