diff options
Diffstat (limited to 'certService')
25 files changed, 858 insertions, 131 deletions
diff --git a/certService/Dockerfile b/certService/Dockerfile index 70617ede..4bb1bf6e 100644 --- a/certService/Dockerfile +++ b/certService/Dockerfile @@ -1,6 +1,6 @@ FROM docker.io/openjdk:11-jre-slim -ARG VERSION=0.0.1-SNAPSHOT +ARG VERSION=${version} RUN groupadd certService && useradd -g certService certService @@ -8,6 +8,6 @@ RUN chown -R certService:certService /var/log USER certService:certService -COPY target/cert-service-${VERSION}.jar ./opt/onap/aaf/certservice/cert-service.jar +COPY target/aaf-certservice-api-${VERSION}.jar ./opt/onap/aaf/certservice/aaf-certservice-api.jar -ENTRYPOINT ["java","-jar","./opt/onap/aaf/certservice/cert-service.jar"] +ENTRYPOINT ["java","-jar","./opt/onap/aaf/certservice/aaf-certservice-api.jar"] diff --git a/certService/README.md b/certService/README.md index db96fa98..443390b3 100644 --- a/certService/README.md +++ b/certService/README.md @@ -1,7 +1,13 @@ # Cert service +### General description +More information about the project and all its functionalities you can find under the wiki page: + ``` + https://wiki.onap.org/display/DW/AAF+Certification+Service + ``` + ### For developers - * AAF Cert Service is a Spring Boot application + * AAF Cert Service Api is a Spring Boot application * Code style Use Google code formatter in your IDE. For IntelliJ use [https://plugins.jetbrains.com/plugin/8527-google-java-format] @@ -20,9 +26,9 @@ ``` ### Building Docker image manually +Go to the certService subfolder and execute following statement (1.0.0-SNAPSHOT is related to a current project.version parameter): ``` - docker build -t cert-service . - + docker build --build-arg VERSION=1.0.0-SNAPSHOT -t onap/org.onap.aaf.certservice.aaf-certservice-api . ``` ### Install the package into the local repository @@ -37,12 +43,18 @@ ``` -### Running Docker container +### Running Docker container local + ``` + docker run -p 8080:8080 --name aaf-certservice-api onap/org.onap.aaf.certservice.aaf-certservice-api + ``` - docker run -p 8080:8080 --name cert-service cert-service +### Running Docker container from nexus ``` + docker run -p 8080:8080 --name aaf-certservice-api nexus3.onap.org:10001/onap/org.onap.aaf.certservice.aaf-certservice-api:1.0.0 + ``` + ### Health Check Browser: @@ -81,7 +93,7 @@ path: ``` ### Logs in Docker container ``` - docker exec -it cert-service bash + docker exec -it aaf-certservice-api bash ``` path: @@ -96,6 +108,18 @@ audit.log error.log trace.log ``` https://sonarcloud.io/dashboard?id=onap_aaf-certservice ``` + + ### Maven artifacts + All maven artifacts are deployed under nexus uri: + ``` + https://nexus.onap.org/content/repositories/snapshots/org/onap/aaf/certservice/ + ``` + + ### Docker artifacts + All docker images are hosted under nexus3 uri: + ``` + https://nexus3.onap.org/repository/docker.snapshot/v2/onap/org.onap.aaf.certservice.aaf-certservice-api/ + ``` ### RestAPI API is described by Swagger ( OpenAPI 3.0 ) on endpoint /docs diff --git a/certService/pom.xml b/certService/pom.xml index 38c356c4..3f17f390 100644 --- a/certService/pom.xml +++ b/certService/pom.xml @@ -16,31 +16,16 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> - <groupId>org.onap.aaf</groupId> - <artifactId>aaf-certservice-parent</artifactId> - <version>0.0.1-SNAPSHOT</version> + <groupId>org.onap.aaf.certservice</groupId> + <artifactId>aaf-certservice</artifactId> + <version>1.0.0-SNAPSHOT</version> </parent> - <artifactId>cert-service</artifactId> - <version>0.0.1-SNAPSHOT</version> - <name>cert-service</name> - <description>Certification service</description> + <artifactId>aaf-certservice-api</artifactId> + <version>1.0.0-SNAPSHOT</version> + <name>aaf-certservice-api</name> + <description>AAF Certification Service Api</description> <packaging>jar</packaging> - <properties> - <java.version>11</java.version> - <assertj-core.version>3.11.1</assertj-core.version> - <mockito-core.version>3.2.4</mockito-core.version> - <spring-core.version>5.2.3.RELEASE</spring-core.version> - <spring-boot-starter.version>2.2.4.RELEASE</spring-boot-starter.version> - <maven-javadoc-plugin.version>3.0.1</maven-javadoc-plugin.version> - <maven-surefire-plugin.version>3.0.0-M1</maven-surefire-plugin.version> - <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> - <dependencyManagement> <dependencies> <dependency> @@ -115,6 +100,11 @@ <artifactId>bcprov-jdk15on</artifactId> <version>${bouncycastle.version}</version> </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>${gson.version}</version> + </dependency> </dependencies> <build> @@ -134,7 +124,6 @@ <artifactId>maven-surefire-plugin</artifactId> <version>${maven-surefire-plugin.version}</version> </plugin> - </plugins> </pluginManagement> <plugins> @@ -147,6 +136,18 @@ <goal>repackage</goal> </goals> </execution> + <execution> + <id>pre-integration-test</id> + <goals> + <goal>start</goal> + </goals> + </execution> + <execution> + <id>post-integration-test</id> + <goals> + <goal>stop</goal> + </goals> + </execution> </executions> </plugin> <plugin> @@ -173,15 +174,46 @@ </execution> </executions> </plugin> + <plugin> + <groupId>org.springdoc</groupId> + <artifactId>springdoc-openapi-maven-plugin</artifactId> + <version>${springdoc-openapi-maven-plugin.version}</version> + <executions> + <execution> + <phase>integration-test</phase> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + <configuration> + <apiDocsUrl>${springdoc-openapi-maven-plugin.apiDocsUrl}</apiDocsUrl> + <outputFileName>api-docs.json</outputFileName> + <outputDir>${project.build.directory}</outputDir> + </configuration> + </plugin> </plugins> </build> <profiles> <profile> + <id>docker-staging</id> + <properties> + <docker.tag>${project.version}-STAGING-${maven.build.timestamp}</docker.tag> + <docker.latest.tag>${project.version}-STAGING-latest</docker.latest.tag> + </properties> + </profile> + + <profile> <id>docker</id> <activation> <activeByDefault>false</activeByDefault> </activation> + <properties> + <os.detected.name>linux</os.detected.name> + <os.detected.arch>x86_64</os.detected.arch> + <os.detected.classifier>${os.detected.name}-${os.detected.arch}</os.detected.classifier> + </properties> <build> <plugins> <plugin> @@ -190,38 +222,38 @@ <version>${docker-maven-plugin.version}</version> <executions> <execution> - <id>start</id> - <phase>pre-integration-test</phase> + <id>docker-build-image</id> + <phase>package</phase> <goals> <goal>build</goal> - <goal>start</goal> </goals> </execution> <execution> - <id>stop</id> - <phase>post-integration-test</phase> + <id>docker-push-image</id> + <phase>deploy</phase> <goals> - <goal>stop</goal> + <goal>push</goal> </goals> </execution> </executions> <configuration> + <skipPush>${skipDockerPush}</skipPush> + <verbose>true</verbose> + <imagePullPolicy>IfNotPresent</imagePullPolicy> <images> <image> - <name>cert-service</name> + <alias>${project.artifactId}</alias> + <name>${docker-image.namespace}/${docker-image.name} + </name> + <registry>${docker-image.registry}</registry> <build> - <dockerFile>${project.basedir}/Dockerfile</dockerFile > + <dockerFileDir>${project.basedir}</dockerFileDir> + <tags> + <tag>${project.version}-${maven.build.timestamp}Z</tag> + <tag>${project.version}</tag> + <tag>${docker-image.latest}</tag> + </tags> </build> - <run> - <ports> - <port>8080:8080</port> - </ports> - <wait> - <!-- Check for this URL to return a 200 return code .... --> - <url>http://localhost:8080/actuator/health</url> - <time>120000</time> - </wait> - </run> </image> </images> </configuration> @@ -230,4 +262,22 @@ </build> </profile> </profiles> + + <distributionManagement> + <repository> + <id>ecomp-releases</id> + <name>AAF Release Repository</name> + <url>${nexusproxy}${releaseNexusPath}</url> + </repository> + <snapshotRepository> + <id>ecomp-snapshots</id> + <name>AAF Snapshot Repository</name> + <url>${nexusproxy}${snapshotNexusPath}</url> + </snapshotRepository> + <site> + <id>ecomp-site</id> + <url>dav:${nexusproxy}${sitePath}</url> + </site> + </distributionManagement> + </project> diff --git a/certService/src/main/java/org/onap/aaf/certservice/CertServiceApplication.java b/certService/src/main/java/org/onap/aaf/certservice/CertServiceApplication.java index c121e7c9..e6b27ca8 100644 --- a/certService/src/main/java/org/onap/aaf/certservice/CertServiceApplication.java +++ b/certService/src/main/java/org/onap/aaf/certservice/CertServiceApplication.java @@ -26,7 +26,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class CertServiceApplication { - public static void main(String[] args) { + // We are excluding this line in Sonar due to fact that + // Spring is handling arguments + public static void main(String[] args) { // NOSONAR SpringApplication.run(CertServiceApplication.class, args); } diff --git a/certService/src/main/java/org/onap/aaf/certservice/api/CertificationService.java b/certService/src/main/java/org/onap/aaf/certservice/api/CertificationService.java index a46e07fc..d1a4a17a 100644 --- a/certService/src/main/java/org/onap/aaf/certservice/api/CertificationService.java +++ b/certService/src/main/java/org/onap/aaf/certservice/api/CertificationService.java @@ -20,9 +20,12 @@ package org.onap.aaf.certservice.api; +import com.google.gson.Gson; +import org.onap.aaf.certservice.certification.CertificationModelFactory; 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.exceptions.DecryptionException; +import org.onap.aaf.certservice.certification.model.CertificationModel; import org.onap.aaf.certservice.certification.model.CsrModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,10 +44,12 @@ public class CertificationService { private static final Logger LOGGER = LoggerFactory.getLogger(CertificationService.class); private final CsrModelFactory csrModelFactory; + private final CertificationModelFactory certificationModelFactory; @Autowired - CertificationService(CsrModelFactory csrModelFactory) { + CertificationService(CsrModelFactory csrModelFactory, CertificationModelFactory certificationModelFactory) { this.csrModelFactory = csrModelFactory; + this.certificationModelFactory = certificationModelFactory; } /** @@ -56,26 +61,24 @@ public class CertificationService { * @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}") + @GetMapping(value = "v1/certificate/{caName}", produces = "application/json; charset=utf-8") public ResponseEntity<String> signCertificate( @PathVariable String caName, @RequestHeader("CSR") String encodedCsr, @RequestHeader("PK") String encodedPrivateKey - ) { + ) throws DecryptionException { + caName = caName.replaceAll("[\n|\r|\t]", "_"); LOGGER.info("Received certificate signing request for CA named: {}", caName); + CsrModel csrModel = csrModelFactory.createCsrModel( + new StringBase64(encodedCsr), + new StringBase64(encodedPrivateKey) + ); + LOGGER.debug("Received CSR meta data: \n{}", csrModel); + CertificationModel certificationModel = certificationModelFactory + .createCertificationModel(csrModel,caName); + return new ResponseEntity<>(new Gson().toJson(certificationModel), HttpStatus.OK); - 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/CertificationData.java b/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationData.java new file mode 100644 index 00000000..a347762e --- /dev/null +++ b/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationData.java @@ -0,0 +1,127 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.certification; + + +final class CertificationData { + + private CertificationData() {} + + private static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"; + private static final String END_CERTIFICATE = "-----END CERTIFICATE-----"; + + static final String EXTRA_CA_CERT = "" + + BEGIN_CERTIFICATE + + "MIIDvzCCAqcCFF5DejiyfoNfPiiMmBXulniBewBGMA0GCSqGSIb3DQEBCwUAMIGb\n" + + "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\n" + + "LUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwE\n" + + "T05BUDEVMBMGA1UEAwwMbmV3Lm9uYXAub3JnMR4wHAYJKoZIhvcNAQkBFg90ZXN0\n" + + "ZXJAb25hcC5vcmcwHhcNMjAwMjEyMDk1OTM3WhcNMjEwMjExMDk1OTM3WjCBmzEL\n" + + "MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbi1G\n" + + "cmFuY2lzY28xGTAXBgNVBAoMEExpbnV4LUZvdW5kYXRpb24xDTALBgNVBAsMBE9O\n" + + "QVAxFTATBgNVBAMMDG5ldy5vbmFwLm9yZzEeMBwGCSqGSIb3DQEJARYPdGVzdGVy\n" + + "QG9uYXAub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtF4FXeDV\n" + + "ng/inC/bTACmZnLC9IiC7PyG/vVbMxxN1bvQLRAwC/Hbl3i9zD68Vs/jPPr/SDr9\n" + + "2rgItdDdUY1V30Y3PT06F11XdEaRb+t++1NX0rDf1AqPaBZgnBmB86s1wbqHdJTr\n" + + "wEImDZ5xMPfP3fiWy/9Yw/U7iRMIi1/oI0lWuHJV0bn908shuJ6dvInpRCoDnoTX\n" + + "YP/FiDSZCFVewQcq4TigB7kRqZrDcPZWbSlqHklDMXRwbCxAiFSziuX6TBwru9Rn\n" + + "HhIeXVSgMU1ZSSopVbJGtQ4zSsU1nvTK5Bhc2UHGcAOZy1xTN5D9EEbTqh7l+Wtx\n" + + "y8ojkEXvFG8lVwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAE+bUphwHit78LK8sb\n" + + "OMjt4DiEu32KeSJOpYgPLeBeAIynaNsa7sQrpuxerGNTmQWIcw6olXI0J+OOwkik\n" + + "II7elrYtd5G1uALxXWdamNsaY0Du34moVL1YjexJ7qQ4oBUxg2tuY8NAQGDK+23I\n" + + "nCA+ZwzdTJo73TYS6sx64d/YLWkX4nHGUoMlF+xUH34csDyhpuTSzQhC2quB5N8z\n" + + "tSFdpe4z2jqx07qo2EBFxi03EQ8Q0ex6l421QM2gbs7cZQ66K0DkpPcF2+iHZnyx\n" + + "xq1lnlsWHklElF2bhyXTn3fPp5wtan00P8IolKx7CAWb92QjkW6M0RvTW/xuwIzh\n" + + "0rTO\n" + + END_CERTIFICATE; + + static final String CA_CERT = "" + + BEGIN_CERTIFICATE + + "MIIDtzCCAp8CFAwqQddh4/iyGfP8UZ3dpXlxfAN8MA0GCSqGSIb3DQEBCwUAMIGX\n" + + "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\n" + + "LUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwE\n" + + "T05BUDERMA8GA1UEAwwIb25hcC5vcmcxHjAcBgkqhkiG9w0BCQEWD3Rlc3RlckBv\n" + + "bmFwLm9yZzAeFw0yMDAyMTIwOTM0MjdaFw0yMTAyMTEwOTM0MjdaMIGXMQswCQYD\n" + + "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuLUZyYW5j\n" + + "aXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjENMAsGA1UECwwET05BUDER\n" + + "MA8GA1UEAwwIb25hcC5vcmcxHjAcBgkqhkiG9w0BCQEWD3Rlc3RlckBvbmFwLm9y\n" + + "ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCFrnO7/eT6V+7XkPPd\n" + + "eiL/6xXreuegvit/1/jTVjG+3AOVcmTn2WXwXXRcQLvkWQfJVPoltsY8E3FqFRti\n" + + "797XjY6cdQJFVDyzNU0+Fb4vJL9FK5wSvnS6EFjBEn3JvXRlENorDCs/mfjkjJoa\n" + + "Dl74gXQEJYcg4nsTeNIj7cm3Q7VK3mZt1t7LSJJ+czxv69UJDuNJpmQ/2WOKyLZA\n" + + "gTtBJ+Hyol45/OLsrqwq1dAn9ZRWIFPvRt/XQYH9bI/6MtqSreRVUrdYCiTe/XpP\n" + + "B/OM6NEi2+p5QLi3Yi70CEbqP3HqUVbkzF+r7bwIb6M5/HxfqzLmGwLvD+6rYnUn\n" + + "Bm8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAhXoO65DXth2X/zFRNsCNpLwmDy7r\n" + + "PxT9ZAIZAzSxx3/aCYiuTrKP1JnqjkO+F2IbikrI4n6sKO49SKnRf9SWTFhd+5dX\n" + + "vxq5y7MaqxHAY9J7+Qzq33+COVFQnaF7ddel2NbyUVb2b9ZINNsaZkkPXui6DtQ7\n" + + "/Fb/1tmAGWd3hMp75G2thBSzs816JMKKa9WD+4VGATEs6OSll4sv2fOZEn+0mAD3\n" + + "9q9c+WtLGIudOwcHwzPb2njtNntQSCK/tVOqbY+vzhMY3JW+p9oSrLDSdGC+pAKK\n" + + "m/wB+2VPIYcsPMtIhHC4tgoSaiCqjXYptaOh4b8ye8CPBUCpX/AYYkN0Ow==\n" + + END_CERTIFICATE; + + static final String INTERMEDIATE_CERT = "" + + BEGIN_CERTIFICATE + + "MIIDqTCCApGgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNVBAYTAlVT\n" + + "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw\n" + + "FwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMREwDwYDVQQD\n" + + "DAhvbmFwLm9yZzEeMBwGCSqGSIb3DQEJARYPdGVzdGVyQG9uYXAub3JnMB4XDTIw\n" + + "MDIxMjA5NDAxMloXDTIyMTEwODA5NDAxMlowgYQxCzAJBgNVBAYTAlVTMRMwEQYD\n" + + "VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkwFwYDVQQK\n" + + "DBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQDDBVpbnRl\n" + + "cm1lZGlhdGUub25hcC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n" + + "AQC1oOYMZ6G+2DGDAizYnzdCNiogivlht1s4oqgem7fM1XFPxD2p31ATIibOdqr/\n" + + "gv1qemO9Q4r1xn6w1Ufq7T1K7PjnMzdSeTqZefurE2JM/HHx2QvW4TjMlz2ILgaD\n" + + "L1LN60kmMQSOi5VxKJpsrCQxbOsxhvefd212gny5AZMcjJe23kUd9OxUrtvpdLEv\n" + + "wI3vFEvT7oRUnEUg/XNz7qeg33vf1C39yMR+6O4s6oevgsEebVKjb+yOoS6zzGtz\n" + + "72wZjm07C54ZlO+4Uy+QAlMjRiU3mgWkKbkOy+4CvwehjhpTikdBs2DX39ZLGHhn\n" + + "L/0a2NYtGulp9XEqmTvRoI+PAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" + + "hvcNAQELBQADggEBADcitdJ6YswiV8jAD9GK0gf3+zqcGegt4kt+79JXlXYbb1sY\n" + + "q3o6prcB7nSUoClgF2xUPCslFGpM0Er9FCSFElQM/ru0l/KVmJS6kSpwEHvsYIH3\n" + + "q5anta+Pyk8JSQWAAw+qrind0uBQMnhR8Tn13tgV+Kjvg/xlH/nZIEdN5YtLB1cA\n" + + "beVsZRyRfVL9DeZU8s/MZ5wC3kgcEp5A4m5lg7HyBxBdqhzFcDr6xiy6OGqW8Yep\n" + + "xrwfc8Fw8a/lOv4U+tBeGNKPQDYaL9hh+oM+qMkNXsHXDqdJsuEGJtU4i3Wcwzoc\n" + + "XGN5NWV//4bP+NFmwgcn7AYCdRvz04A8GU/0Cwg=\n" + + END_CERTIFICATE; + + static final String ENTITY_CERT = "" + + BEGIN_CERTIFICATE + + "MIIDjDCCAnSgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwgYQxCzAJBgNVBAYTAlVT\n" + + "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4tRnJhbmNpc2NvMRkw\n" + + "FwYDVQQKDBBMaW51eC1Gb3VuZGF0aW9uMQ0wCwYDVQQLDARPTkFQMR4wHAYDVQQD\n" + + "DBVpbnRlcm1lZGlhdGUub25hcC5vcmcwHhcNMjAwMjEyMDk1MTI2WhcNMjIxMTA4\n" + + "MDk1MTI2WjB7MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG\n" + + "A1UEBwwNU2FuLUZyYW5jaXNjbzEZMBcGA1UECgwQTGludXgtRm91bmRhdGlvbjEN\n" + + "MAsGA1UECwwET05BUDEVMBMGA1UEAwwMdmlkLm9uYXAub3JnMIIBIjANBgkqhkiG\n" + + "9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+GIRzJzUOh0gtc+wzFJEdTnn+q5F10L0Yhr\n" + + "G1xKdjPieHIFGsoiXwcuCU8arNSqlz7ocx62KQRkcA8y6edlOAsYtdOEJvqEI9vc\n" + + "eyTB/HYsbzw3URPGch4AmibrQkKU9QvGwouHtHn4R2Ft2Y0tfEqv9hxj9v4njq4A\n" + + "EiDLAFLl5FmVyCZu/MtKngSgu1smcaFKTYySPMxytgJZexoa/ALZyyE0gRhsvwHm\n" + + "NLGCPt1bmE/PEGZybsCqliyTO0S56ncD55The7+D/UDS4kE1Wg0svlWon/YsE6QW\n" + + "B3oeJDX7Kr8ebDTIAErevIAD7Sm4ee5se2zxYrsYlj0MzHZtvwIDAQABoxAwDjAM\n" + + "BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCvQ1pTvjON6vSlcJRKSY4r\n" + + "8q7L4/9ZaVXWJAjzEYJtPIqsgGiPWz0vGfgklowU6tZxp9zRZFXfMil+mPQSe+yo\n" + + "ULrZSQ/z48YHPueE/BNO/nT4aaVBEhPLR5aVwC7uQVX8H+m1V1UGT8lk9vdI9rej\n" + + "CI9l524sLCpdE4dFXiWK2XHEZ0Vfylk221u3IYEogVVA+UMX7BFPSsOnI2vtYK/i\n" + + "lwZtlri8LtTusNe4oiTkYyq+RSyDhtAswg8ANgvfHolhCHoLFj6w1IkG88UCmbwN\n" + + "d7BoGMy06y5MJxyXEZG0vR7eNeLey0TIh+rAszAFPsIQvrOHW+HuA+WLQAj1mhnm\n" + + END_CERTIFICATE; + +} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationModelFactory.java b/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationModelFactory.java new file mode 100644 index 00000000..1b10c379 --- /dev/null +++ b/certService/src/main/java/org/onap/aaf/certservice/certification/CertificationModelFactory.java @@ -0,0 +1,51 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.certification; + +import org.onap.aaf.certservice.certification.model.CertificationModel; +import org.onap.aaf.certservice.certification.model.CsrModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.Arrays; + +import static org.onap.aaf.certservice.certification.CertificationData.CA_CERT; +import static org.onap.aaf.certservice.certification.CertificationData.ENTITY_CERT; +import static org.onap.aaf.certservice.certification.CertificationData.INTERMEDIATE_CERT; +import static org.onap.aaf.certservice.certification.CertificationData.EXTRA_CA_CERT; + +@Service +public class CertificationModelFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(CertificationModelFactory.class); + + + public CertificationModel createCertificationModel(CsrModel csr, String caName) { + LOGGER.info("Generating certificates for CA named: {}, and certificate signing request:\n{}", + caName, csr); + return new CertificationModel( + Arrays.asList(ENTITY_CERT, INTERMEDIATE_CERT), + Arrays.asList(CA_CERT, EXTRA_CA_CERT) + ); + } + +} 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 index 80858f4d..6794bd6b 100644 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java +++ b/certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java @@ -20,12 +20,13 @@ 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.exceptions.DecryptionException; +import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException; import org.onap.aaf.certservice.certification.model.CsrModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,21 +37,35 @@ import org.springframework.stereotype.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); - } + private final PemObjectFactory pemObjectFactory + = new PemObjectFactory(); + private final PKCS10CertificationRequestFactory certificationRequestFactory + = new PKCS10CertificationRequestFactory(); + + + public CsrModel createCsrModel(StringBase64 csr, StringBase64 privateKey) + throws DecryptionException { + LOGGER.debug("Decoded CSR: \n{}", csr); + PKCS10CertificationRequest decodedCsr = decodeCsr(csr); + PemObject decodedPrivateKey = decodePrivateKey(privateKey); + return new CsrModel(decodedCsr, decodedPrivateKey); + } + + private PemObject decodePrivateKey(StringBase64 privateKey) + throws KeyDecryptionException { + return pemObjectFactory.createPemObject(privateKey.asString()).orElseThrow( + () -> new KeyDecryptionException("Incorrect Key, decryption failed") + ); + } + + private PKCS10CertificationRequest decodeCsr(StringBase64 csr) + throws CsrDecryptionException { + return pemObjectFactory.createPemObject(csr.asString()) + .flatMap( + certificationRequestFactory::createKCS10CertificationRequest + ).orElseThrow( + () -> new CsrDecryptionException("Incorrect CSR, decryption failed") + ); } public static class StringBase64 { @@ -65,6 +80,7 @@ public class CsrModelFactory { return new String(decoder.decode(value)); } } + } diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/PKCS10CertificationRequestFactory.java b/certService/src/main/java/org/onap/aaf/certservice/certification/PKCS10CertificationRequestFactory.java new file mode 100644 index 00000000..8f89de2f --- /dev/null +++ b/certService/src/main/java/org/onap/aaf/certservice/certification/PKCS10CertificationRequestFactory.java @@ -0,0 +1,38 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.certification; + +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.util.io.pem.PemObject; + +import java.io.IOException; +import java.util.Optional; + +public class PKCS10CertificationRequestFactory { + + public Optional<PKCS10CertificationRequest> createKCS10CertificationRequest(PemObject pemObject) { + try { + return Optional.of(new PKCS10CertificationRequest(pemObject.getContent())); + } catch (IOException e) { + return Optional.empty(); + } + } +} 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 index e3339cc4..514101b9 100644 --- a/certService/src/main/java/org/onap/aaf/certservice/certification/PemObjectFactory.java +++ b/certService/src/main/java/org/onap/aaf/certservice/certification/PemObjectFactory.java @@ -22,22 +22,21 @@ package org.onap.aaf.certservice.certification; import java.io.IOException; import java.io.StringReader; +import java.util.Optional; 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 { + public Optional<PemObject> createPemObject(String pem) { try (StringReader stringReader = new StringReader(pem); PemReader pemReader = new PemReader(stringReader)) { - return pemReader.readPemObject(); + return Optional.ofNullable(pemReader.readPemObject()); } catch (IOException e) { - throw new CsrDecryptionException("Unable to create PEM", e); + return Optional.empty(); } } diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/CertificationExceptionController.java b/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/CertificationExceptionController.java new file mode 100644 index 00000000..7d2c43ed --- /dev/null +++ b/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/CertificationExceptionController.java @@ -0,0 +1,56 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.certification.exceptions; + +import com.google.gson.Gson; +import org.onap.aaf.certservice.certification.model.ErrorResponseModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class CertificationExceptionController { + + private static final Logger LOGGER = LoggerFactory.getLogger(CertificationExceptionController.class); + + @ExceptionHandler(value = CsrDecryptionException.class) + public ResponseEntity<String> handle(CsrDecryptionException exception) { + LOGGER.error("Exception occurred during decoding certificate sign request:", exception); + return getErrorResponseEntity("Wrong certificate signing request (CSR) format"); + } + + @ExceptionHandler(value = KeyDecryptionException.class) + public ResponseEntity<String> handle(KeyDecryptionException exception) { + LOGGER.error("Exception occurred during decoding key:", exception); + return getErrorResponseEntity("Wrong key (PK) format"); + } + + private ResponseEntity<String> getErrorResponseEntity(String errorMessage) { + ErrorResponseModel errorResponse = new ErrorResponseModel(errorMessage); + return new ResponseEntity<>( + new Gson().toJson(errorResponse), + HttpStatus.BAD_REQUEST + ); + } +} 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 index fb16ad91..929fbdb6 100644 --- 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 @@ -20,8 +20,11 @@ package org.onap.aaf.certservice.certification.exceptions; -public class CsrDecryptionException extends Exception { +public class CsrDecryptionException extends DecryptionException { public CsrDecryptionException(String message, Throwable cause) { super(message, cause); } + public CsrDecryptionException(String message) { + super(message); + } } diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/DecryptionException.java b/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/DecryptionException.java new file mode 100644 index 00000000..8f5f48e6 --- /dev/null +++ b/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/DecryptionException.java @@ -0,0 +1,30 @@ +/* + * ============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 DecryptionException extends Exception { + public DecryptionException(String message, Throwable cause) { + super(message, cause); + } + public DecryptionException(String message) { + super(message); + } +} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/KeyDecryptionException.java b/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/KeyDecryptionException.java new file mode 100644 index 00000000..15d53935 --- /dev/null +++ b/certService/src/main/java/org/onap/aaf/certservice/certification/exceptions/KeyDecryptionException.java @@ -0,0 +1,30 @@ +/* + * ============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 KeyDecryptionException extends DecryptionException { + public KeyDecryptionException(String message, Throwable cause) { + super(message, cause); + } + public KeyDecryptionException(String message) { + super(message); + } +} diff --git a/certService/src/main/java/org/onap/aaf/certservice/certification/model/CertificationModel.java b/certService/src/main/java/org/onap/aaf/certservice/certification/model/CertificationModel.java new file mode 100644 index 00000000..b851d0d9 --- /dev/null +++ b/certService/src/main/java/org/onap/aaf/certservice/certification/model/CertificationModel.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.certification.model; + +import java.util.Collections; +import java.util.List; + +public class CertificationModel { + + private final List<String> certificateChain; + private final List<String> trustedCertificates; + + public CertificationModel(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/certService/src/main/java/org/onap/aaf/certservice/certification/model/ErrorResponseModel.java b/certService/src/main/java/org/onap/aaf/certservice/certification/model/ErrorResponseModel.java new file mode 100644 index 00000000..bca7915d --- /dev/null +++ b/certService/src/main/java/org/onap/aaf/certservice/certification/model/ErrorResponseModel.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.certification.model; + +public class ErrorResponseModel { + + private final String errorMessage; + + public ErrorResponseModel(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getErrorMessage() { + return errorMessage; + } + +} + diff --git a/certService/src/main/resources/application.properties b/certService/src/main/resources/application.properties index a157ae66..b9ce108a 100644 --- a/certService/src/main/resources/application.properties +++ b/certService/src/main/resources/application.properties @@ -2,3 +2,4 @@ management.endpoints.enabled-by-default=false management.endpoint.health.enabled=true springdoc.swagger-ui.path=/docs +springdoc.show-actuator=true diff --git a/certService/src/test/java/org/onap/aaf/certservice/CertServiceApplicationTests.java b/certService/src/test/java/org/onap/aaf/certservice/CertServiceApplicationTests.java index fe2dcfe2..ae284da3 100644 --- a/certService/src/test/java/org/onap/aaf/certservice/CertServiceApplicationTests.java +++ b/certService/src/test/java/org/onap/aaf/certservice/CertServiceApplicationTests.java @@ -27,7 +27,8 @@ import org.springframework.boot.test.context.SpringBootTest; class CertServiceApplicationTests { @Test - void contextLoads() { + // We are excluding this line in Sonar due to fact that + // this test checks if Spring context is loaded and does not require assertion + void contextLoads() { // NOSONAR } - } diff --git a/certService/src/test/java/org/onap/aaf/certservice/api/CertificationServiceTest.java b/certService/src/test/java/org/onap/aaf/certservice/api/CertificationServiceTest.java index 99ca09b9..0bb99d9f 100644 --- a/certService/src/test/java/org/onap/aaf/certservice/api/CertificationServiceTest.java +++ b/certService/src/test/java/org/onap/aaf/certservice/api/CertificationServiceTest.java @@ -20,21 +20,28 @@ package org.onap.aaf.certservice.api; +import com.google.gson.Gson; 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.CertificationModelFactory; 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.exceptions.DecryptionException; +import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException; +import org.onap.aaf.certservice.certification.model.CertificationModel; 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.assertTrue; +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; @@ -47,50 +54,80 @@ class CertificationServiceTest { @Mock private CsrModelFactory csrModelFactory; + @Mock + private CertificationModelFactory certificationModelFactory; + @BeforeEach void serUp() { MockitoAnnotations.initMocks(this); - certificationService = new CertificationService(csrModelFactory); + certificationService = new CertificationService(csrModelFactory, certificationModelFactory); } @Test - void shouldReturnDataAboutCsrBaseOnEncodedParameters() throws CsrDecryptionException { + void shouldReturnDataAboutCsrBaseOnEncodedParameters() throws DecryptionException { // given final String testStringCsr = "testData"; + final String testCaName = "TestCa"; CsrModel mockedCsrModel = mock(CsrModel.class); + CertificationModel testCertificationModel = new CertificationModel( + Arrays.asList("ENTITY_CERT", "INTERMEDIATE_CERT"), + Arrays.asList("CA_CERT", "EXTRA_CA_CERT") + ); when(mockedCsrModel.toString()).thenReturn(testStringCsr); when(csrModelFactory.createCsrModel(any(StringBase64.class), any(StringBase64.class))) .thenReturn(mockedCsrModel); + when(certificationModelFactory.createCertificationModel(mockedCsrModel, testCaName)) + .thenReturn(testCertificationModel); // when ResponseEntity<String> testResponse = - certificationService.signCertificate("TestCa", "encryptedCSR", "encryptedPK"); + certificationService.signCertificate(testCaName, "encryptedCSR", "encryptedPK"); + + CertificationModel responseCertificationModel = new Gson().fromJson(testResponse.getBody(), CertificationModel.class); // then - assertEquals(testResponse.getStatusCode(), HttpStatus.OK); - assertTrue( - testResponse.toString().contains(testStringCsr) - ); + assertEquals(HttpStatus.OK, testResponse.getStatusCode()); + assertThat(responseCertificationModel + ).isEqualToComparingFieldByField(testCertificationModel); + } @Test - void shouldReturnBadRequestWhenCreatingCsrModelFails() throws CsrDecryptionException { + void shouldThrowCsrDecryptionExceptionWhenCreatingCsrModelFails() throws DecryptionException { // given + String expectedMessage = "Incorrect CSR, decryption failed"; when(csrModelFactory.createCsrModel(any(StringBase64.class), any(StringBase64.class))) - .thenThrow(new CsrDecryptionException("creation fail",new IOException())); + .thenThrow(new CsrDecryptionException(expectedMessage,new IOException())); // when - ResponseEntity<String> testResponse = - certificationService.signCertificate("TestCa", "encryptedCSR", "encryptedPK"); + Exception exception = assertThrows( + CsrDecryptionException.class, () -> certificationService. + signCertificate("TestCa", "encryptedCSR", "encryptedPK") + ); - String expectedMessage = "Wrong certificate signing request (CSR) format"; + String actualMessage = exception.getMessage(); // then - assertEquals(HttpStatus.BAD_REQUEST, testResponse.getStatusCode()); - assertTrue( - testResponse.toString().contains(expectedMessage) + assertEquals(expectedMessage, actualMessage); + } + + @Test + void shouldThrowPemDecryptionExceptionWhenCreatingPemModelFails() throws DecryptionException { + // given + String expectedMessage = "Incorrect PEM, decryption failed"; + when(csrModelFactory.createCsrModel(any(StringBase64.class), any(StringBase64.class))) + .thenThrow(new KeyDecryptionException(expectedMessage,new IOException())); + + // when + Exception exception = assertThrows( + KeyDecryptionException.class, () -> certificationService. + signCertificate("TestCa", "encryptedCSR", "encryptedPK") ); + String actualMessage = exception.getMessage(); + + // then + assertEquals(expectedMessage, actualMessage); } } diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/CertificationModelFactoryTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/CertificationModelFactoryTest.java new file mode 100644 index 00000000..2953af78 --- /dev/null +++ b/certService/src/test/java/org/onap/aaf/certservice/certification/CertificationModelFactoryTest.java @@ -0,0 +1,63 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.certification; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.certification.model.CertificationModel; +import org.onap.aaf.certservice.certification.model.CsrModel; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.onap.aaf.certservice.certification.CertificationData.CA_CERT; +import static org.onap.aaf.certservice.certification.CertificationData.ENTITY_CERT; +import static org.onap.aaf.certservice.certification.CertificationData.INTERMEDIATE_CERT; +import static org.onap.aaf.certservice.certification.CertificationData.EXTRA_CA_CERT; + + +class CertificationModelFactoryTest { + + + private CertificationModelFactory certificationModelFactory; + + @BeforeEach + void setUp() { + certificationModelFactory = new CertificationModelFactory(); + } + + @Test + void shouldCreateProperCertificationModelWhenGivenProperCsrModelAndCaName() { + // given + final String testCaName = "testCA"; + CsrModel mockedCsrModel = mock(CsrModel.class); + + // when + CertificationModel certificationModel = certificationModelFactory.createCertificationModel(mockedCsrModel ,testCaName); + + //then + assertEquals(2, certificationModel.getCertificateChain().size()); + assertThat(certificationModel.getCertificateChain()).contains(INTERMEDIATE_CERT, ENTITY_CERT); + assertEquals(2, certificationModel.getTrustedCertificates().size()); + assertThat(certificationModel.getTrustedCertificates()).contains(CA_CERT, EXTRA_CA_CERT); + } + +} 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 index 8b5f5dc5..77594ed7 100644 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/CsrModelFactoryTest.java +++ b/certService/src/test/java/org/onap/aaf/certservice/certification/CsrModelFactoryTest.java @@ -25,6 +25,8 @@ 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.exceptions.DecryptionException; +import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException; import org.onap.aaf.certservice.certification.model.CsrModel; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -32,6 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.onap.aaf.certservice.certification.TestData.TEST_CSR; import static org.onap.aaf.certservice.certification.TestData.TEST_PK; import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_CSR; +import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_PEM; class CsrModelFactoryTest { @@ -44,7 +47,7 @@ class CsrModelFactoryTest { } @Test - void shouldDecryptCsrAndReturnStringWithDataAboutIt() throws CsrDecryptionException { + void shouldDecryptCsrAndReturnStringWithDataAboutIt() throws DecryptionException { // given String encoderCsr = new String(Base64.encode(TEST_CSR.getBytes())); String encoderPK = new String(Base64.encode(TEST_PK.getBytes())); @@ -65,9 +68,8 @@ class CsrModelFactoryTest { ); } - @Test - void shouldThrowCsrDecryptionExceptionWhenCsrAreIncorrect() { + void shouldThrowCsrDecryptionExceptionWhenCsrIsIncorrect() { // given String encoderPK = new String(Base64.encode(TEST_PK.getBytes())); String wrongCsr = new String(Base64.encode(TEST_WRONG_CSR.getBytes())); @@ -85,4 +87,23 @@ class CsrModelFactoryTest { assertTrue(actualMessage.contains(expectedMessage)); } + @Test + void shouldThrowKeyDecryptionExceptionWhenKeyIsIncorrect() { + // given + String encoderPK = new String(Base64.encode(TEST_WRONG_PEM.getBytes())); + String wrongCsr = new String(Base64.encode(TEST_CSR.getBytes())); + + // when + Exception exception = assertThrows( + KeyDecryptionException.class, () -> csrModelFactory + .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK)) + ); + + String expectedMessage = "Incorrect Key, decryption failed"; + String actualMessage = exception.getMessage(); + + // then + assertTrue(actualMessage.contains(expectedMessage)); + } + } 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 index 67d7f1dc..0b70475c 100644 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/PemObjectFactoryTest.java +++ b/certService/src/test/java/org/onap/aaf/certservice/certification/PemObjectFactoryTest.java @@ -23,7 +23,8 @@ 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 org.onap.aaf.certservice.certification.exceptions.DecryptionException; +import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -44,9 +45,11 @@ class PemObjectFactoryTest { } @Test - void shouldTransformStringInToPemObjectAndBackToString() throws CsrDecryptionException { + void shouldTransformStringInToPemObjectAndBackToString() throws DecryptionException { // when - PemObject pemObject = pemObjectFactory.createPmObject(TEST_PEM); + PemObject pemObject = pemObjectFactory.createPemObject(TEST_PEM).orElseThrow( + () -> new DecryptionException("Pem decryption failed") + ); String parsedPemObject = pemObjectToString(pemObject); // then @@ -55,12 +58,16 @@ class PemObjectFactoryTest { @Test void shouldThrowExceptionWhenParsingPemFailed() { + // given + String expectedMessage = "Unable to create PEM"; + // when Exception exception = assertThrows( - CsrDecryptionException.class, () -> pemObjectFactory.createPmObject(TEST_WRONG_PEM) + DecryptionException.class, () -> pemObjectFactory.createPemObject(TEST_WRONG_PEM).orElseThrow( + () -> new DecryptionException(expectedMessage) + ) ); - String expectedMessage = "Unable to create PEM"; String actualMessage = exception.getMessage(); // then 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 index 156cf8ba..39554417 100644 --- a/certService/src/test/java/org/onap/aaf/certservice/certification/TestUtils.java +++ b/certService/src/test/java/org/onap/aaf/certservice/certification/TestUtils.java @@ -22,7 +22,7 @@ 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 org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException; import java.io.IOException; import java.io.StringWriter; @@ -33,7 +33,7 @@ public final class TestUtils { private TestUtils() { } - public static String pemObjectToString(PemObject pemObject) throws CsrDecryptionException { + public static String pemObjectToString(PemObject pemObject) throws KeyDecryptionException { try (StringWriter output = new StringWriter()) { PemWriter pemWriter = new PemWriter(output); pemWriter.writeObject(pemObject); @@ -41,7 +41,7 @@ public final class TestUtils { return output.getBuffer().toString(); } catch (IOException e) { - throw new CsrDecryptionException("Writing PAM Object to string failed", e); + throw new KeyDecryptionException("Writing PAM Object to string failed", e); } } } diff --git a/certService/src/test/java/org/onap/aaf/certservice/certification/exception/CertificationExceptionControllerTest.java b/certService/src/test/java/org/onap/aaf/certservice/certification/exception/CertificationExceptionControllerTest.java new file mode 100644 index 00000000..58e59f45 --- /dev/null +++ b/certService/src/test/java/org/onap/aaf/certservice/certification/exception/CertificationExceptionControllerTest.java @@ -0,0 +1,74 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.certification.exception; + +import com.google.gson.Gson; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.certification.exceptions.CertificationExceptionController; +import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException; +import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException; +import org.onap.aaf.certservice.certification.model.ErrorResponseModel; +import org.springframework.http.ResponseEntity; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CertificationExceptionControllerTest { + + private CertificationExceptionController certificationExceptionController; + + @BeforeEach + void setUp() { + certificationExceptionController = + new CertificationExceptionController(); + } + + @Test + void shouldReturnResponseEntityWithAppropriateErrorMessageWhenGivenCsrDecryptionException() { + // given + String expectedMessage = "Wrong certificate signing request (CSR) format"; + CsrDecryptionException csrDecryptionException = new CsrDecryptionException("test csr exception"); + + // when + ResponseEntity<String> responseEntity = certificationExceptionController.handle(csrDecryptionException); + + ErrorResponseModel response = new Gson().fromJson(responseEntity.getBody(), ErrorResponseModel.class); + + // then + assertEquals(expectedMessage, response.getErrorMessage()); + } + + @Test + void shouldReturnResponseEntityWithAppropriateErrorMessageWhenGivenKeyDecryptionException() { + // given + String expectedMessage = "Wrong key (PK) format"; + KeyDecryptionException csrDecryptionException = new KeyDecryptionException("test pk exception"); + + // when + ResponseEntity<String> responseEntity = certificationExceptionController.handle(csrDecryptionException); + + ErrorResponseModel response = new Gson().fromJson(responseEntity.getBody(), ErrorResponseModel.class); + + // then + assertEquals(expectedMessage, response.getErrorMessage()); + } + +} 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 index ffce61d8..7df785d2 100644 --- 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 @@ -24,8 +24,11 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.bouncycastle.util.io.pem.PemObject; import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.certification.PKCS10CertificationRequestFactory; import org.onap.aaf.certservice.certification.PemObjectFactory; import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException; +import org.onap.aaf.certservice.certification.exceptions.DecryptionException; +import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException; import java.io.IOException; @@ -42,9 +45,12 @@ import static org.onap.aaf.certservice.certification.TestUtils.pemObjectToString class CsrModelTest { - + private final PKCS10CertificationRequestFactory certificationRequestFactory + = new PKCS10CertificationRequestFactory(); + private final PemObjectFactory pemObjectFactory + = new PemObjectFactory(); @Test - void shouldByConstructedAndReturnProperFields() throws CsrDecryptionException, IOException { + void shouldByConstructedAndReturnProperFields() throws DecryptionException, IOException { // given PemObject testPublicKey = generateTestPublicKey(); @@ -68,7 +74,7 @@ class CsrModelTest { } @Test - void shouldThrowExceptionWhenKeyIsNotCorrect() throws IOException, CsrDecryptionException { + void shouldThrowExceptionWhenPublicKeyIsNotCorrect() throws KeyDecryptionException, IOException { // given PemObjectFactory pemObjectFactory = new PemObjectFactory(); PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class); @@ -77,7 +83,9 @@ class CsrModelTest { .thenReturn(wrongKryInfo); when(wrongKryInfo.getEncoded()) .thenThrow(new IOException()); - PemObject testPrivateKey = pemObjectFactory.createPmObject(TEST_PK); + PemObject testPrivateKey = pemObjectFactory.createPemObject(TEST_PK).orElseThrow( + () -> new KeyDecryptionException("Private key decoding fail") + ); CsrModel csrModel = new CsrModel(testCsr, testPrivateKey); // when @@ -93,20 +101,26 @@ class CsrModelTest { assertTrue(actualMessage.contains(expectedMessage)); } - private CsrModel generateTestCsrModel() throws CsrDecryptionException, IOException { - PemObjectFactory pemObjectFactory = new PemObjectFactory(); - PKCS10CertificationRequest testCsr = new PKCS10CertificationRequest( - pemObjectFactory.createPmObject(TEST_CSR).getContent() + private CsrModel generateTestCsrModel() throws DecryptionException { + PemObject testPrivateKey = pemObjectFactory.createPemObject(TEST_PK).orElseThrow( + () -> new DecryptionException("Incorrect Private Key, decryption failed") ); - PemObject testPrivateKey = pemObjectFactory.createPmObject(TEST_PK); + PKCS10CertificationRequest testCsr = generateTestCertificationRequest(); return new CsrModel(testCsr, testPrivateKey); } - private PemObject generateTestPublicKey() throws CsrDecryptionException, IOException { - PemObjectFactory pemObjectFactory = new PemObjectFactory(); - PKCS10CertificationRequest testCsr = new PKCS10CertificationRequest( - pemObjectFactory.createPmObject(TEST_CSR).getContent() - ); + private PemObject generateTestPublicKey() throws DecryptionException, IOException { + PKCS10CertificationRequest testCsr = generateTestCertificationRequest(); return new PemObject("PUBLIC KEY", testCsr.getSubjectPublicKeyInfo().getEncoded()); } + + private PKCS10CertificationRequest generateTestCertificationRequest() throws DecryptionException { + return pemObjectFactory.createPemObject(TEST_CSR) + .flatMap( + certificationRequestFactory::createKCS10CertificationRequest + ).orElseThrow( + () -> new DecryptionException("Incorrect CSR, decryption failed") + ); + } + } |