Refactor CSR model to be POJO
authorBartosz Gardziejewski <bartosz.gardziejewski@nokia.com>
Wed, 26 Feb 2020 13:46:14 +0000 (14:46 +0100)
committerZebek Bogumil <bogumil.zebek@nokia.com>
Thu, 27 Feb 2020 06:07:45 +0000 (07:07 +0100)
Issue-ID: AAF-997
Signed-off-by: Bartosz Gardziejewski <bartosz.gardziejewski@nokia.com>
Change-Id: Ia06dd580a64e56dcf1d8bf5f3db6fe6394cdb1c8

certService/src/main/java/org/onap/aaf/certservice/certification/CsrModelFactory.java
certService/src/main/java/org/onap/aaf/certservice/certification/configuration/model/Cmpv2Server.java
certService/src/main/java/org/onap/aaf/certservice/certification/model/CsrModel.java
certService/src/test/java/org/onap/aaf/certservice/certification/configuration/CmpServersConfigLoaderTest.java
certService/src/test/java/org/onap/aaf/certservice/certification/configuration/Cmpv2ServerProviderTest.java
certService/src/test/java/org/onap/aaf/certservice/certification/configuration/validation/Cmpv2ServerConfigurationValidatorTest.java
certService/src/test/java/org/onap/aaf/certservice/certification/model/CsrModelTest.java

index bca30de..6f356c1 100644 (file)
@@ -47,7 +47,7 @@ public class CsrModelFactory {
             throws DecryptionException {
         PKCS10CertificationRequest decodedCsr = decodeCsr(csr);
         PemObject decodedPrivateKey = decodePrivateKey(privateKey);
-        return new CsrModel(decodedCsr, decodedPrivateKey);
+        return new CsrModel.CsrModelBuilder(decodedCsr, decodedPrivateKey).build();
     }
 
     private PemObject decodePrivateKey(StringBase64 privateKey)
index 9a9f9c5..9f8f979 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.aaf.certservice.certification.configuration.model;
 
+import org.bouncycastle.asn1.x500.X500Name;
 import org.hibernate.validator.constraints.Length;
 import org.onap.aaf.certservice.certification.configuration.validation.constraints.Cmpv2URL;
 
@@ -32,8 +33,7 @@ public class Cmpv2Server {
     private CaMode caMode;
     @Length(min = 1, max = 128)
     private String caName;
-    @Length(min = 4, max = 256)
-    private String issuerDN;
+    private X500Name issuerDN;
     @Cmpv2URL
     private String url;
 
@@ -61,11 +61,11 @@ public class Cmpv2Server {
         this.caName = caName;
     }
 
-    public String getIssuerDN() {
+    public X500Name getIssuerDN() {
         return issuerDN;
     }
 
-    public void setIssuerDN(String issuerDN) {
+    public void setIssuerDN(X500Name issuerDN) {
         this.issuerDN = issuerDN;
     }
 
index 2421c5a..b59f4e3 100644 (file)
 package org.onap.aaf.certservice.certification.model;
 
 import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
@@ -35,50 +42,127 @@ import org.bouncycastle.pkcs.PKCS10CertificationRequest;
 import org.bouncycastle.util.io.pem.PemObject;
 
 import org.onap.aaf.certservice.certification.exception.CsrDecryptionException;
+import org.onap.aaf.certservice.certification.exception.DecryptionException;
+import org.onap.aaf.certservice.certification.exception.KeyDecryptionException;
 
 
 public class CsrModel {
 
     private final PKCS10CertificationRequest csr;
-    private final PemObject privateKey;
+    private final X500Name subjectData;
+    private final PrivateKey privateKey;
+    private final PublicKey publicKey;
+    private final List<String> sans;
 
-    public CsrModel(PKCS10CertificationRequest csr, PemObject privateKey) {
+    CsrModel(
+            PKCS10CertificationRequest csr, X500Name subjectData,
+            PrivateKey privateKey, PublicKey publicKey, List<String> sans) {
         this.csr = csr;
+        this.subjectData = subjectData;
         this.privateKey = privateKey;
+        this.publicKey = publicKey;
+        this.sans = sans;
     }
 
-    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 PKCS10CertificationRequest getCsr() {
+        return csr;
     }
 
-    public PemObject getPrivateKey() {
-        return privateKey;
+    public X500Name getSubjectData() {
+        return subjectData;
     }
 
-    public X500Name getSubjectData() {
-        return csr.getSubject();
+    public PrivateKey getPrivateKey() {
+        return privateKey;
     }
 
-    public List<String> getSansData() {
-        Extensions extensions =
-                Extensions.getInstance(csr.getAttributes()[0].getAttrValues().getObjectAt(0));
-        GeneralName[] arrayOfAlternativeNames =
-                GeneralNames.fromExtensions(extensions, Extension.subjectAlternativeName).getNames();
+    public PublicKey getPublicKey() {
+        return publicKey;
+    }
 
-        return Arrays.stream(arrayOfAlternativeNames)
-                .map(GeneralName::getName)
-                .map(Objects::toString)
-                .collect(Collectors.toList());
+    public List<String> getSans() {
+        return sans;
     }
 
     @Override
     public String toString() {
-        return "Subject: { " + getSubjectData().toString()
-                + " ,SANs: " + getSansData().toString() + " }";
+        return "Subject: { " + subjectData
+                + " ,SANs: " + sans + " }";
+    }
+
+    public static class CsrModelBuilder {
+
+        private final PKCS10CertificationRequest csr;
+        private final PemObject privateKey;
+
+        public CsrModel build()
+                throws DecryptionException
+        {
+
+            X500Name subjectData = getSubjectData();
+            PrivateKey javaPrivateKey = convertingPemPrivateKeyToJavaSecurityPrivateKey(getPrivateKey());
+            PublicKey javaPublicKey = convertingPemPublicKeyToJavaSecurityPublicKey(getPublicKey());
+            List<String> sans = getSansData();
+
+            return new CsrModel(csr, subjectData, javaPrivateKey, javaPublicKey, sans);
+        }
+
+        public CsrModelBuilder(PKCS10CertificationRequest csr, PemObject privateKey) {
+            this.csr = csr;
+            this.privateKey = privateKey;
+        }
+
+        private PemObject getPublicKey() throws CsrDecryptionException {
+            try {
+                return new PemObject("PUBLIC KEY", csr.getSubjectPublicKeyInfo().getEncoded());
+            } catch (IOException e) {
+                throw new CsrDecryptionException("Reading Public Key from CSR failed", e.getCause());
+            }
+        }
+
+        private PemObject getPrivateKey() {
+            return privateKey;
+        }
+
+        private X500Name getSubjectData() {
+            return csr.getSubject();
+        }
+
+        private List<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());
+        }
+
+        private PrivateKey convertingPemPrivateKeyToJavaSecurityPrivateKey(PemObject privateKey)
+                throws KeyDecryptionException
+        {
+            try {
+                KeyFactory factory = KeyFactory.getInstance("RSA");
+                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey.getContent());
+                return factory.generatePrivate(keySpec);
+            } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+                throw new KeyDecryptionException("Converting Private Key failed", e.getCause());
+            }
+        }
+
+        private PublicKey convertingPemPublicKeyToJavaSecurityPublicKey(PemObject publicKey)
+                throws KeyDecryptionException
+        {
+            try {
+                KeyFactory factory = KeyFactory.getInstance("RSA");
+                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey.getContent());
+                return factory.generatePublic(keySpec);
+            } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
+                throw new KeyDecryptionException("Converting Public Key from CSR failed", e.getCause());
+            }
+        }
     }
 
 }
index b4eec40..cf8c07a 100644 (file)
@@ -88,9 +88,9 @@ class CmpServersConfigLoaderTest {
     private void verifyThatCmpServerEquals(Cmpv2Server cmpv2Server, Map<String, String> expected) {
         assertThat(cmpv2Server.getCaName()).isEqualTo(expected.get("CA_NAME"));
         assertThat(cmpv2Server.getUrl()).isEqualTo(expected.get("URL"));
-        assertThat(cmpv2Server.getIssuerDN()).isEqualTo(expected.get("ISSUER_DN"));
+        assertThat(cmpv2Server.getIssuerDN().toString()).isEqualTo(expected.get("ISSUER_DN"));
         assertThat(cmpv2Server.getCaMode().name()).isEqualTo(expected.get("CA_MODE"));
         assertThat(cmpv2Server.getAuthentication().getIak()).isEqualTo(expected.get("IAK"));
         assertThat(cmpv2Server.getAuthentication().getRv()).isEqualTo(expected.get("RV"));
     }
-}
\ No newline at end of file
+}
index d3c09e9..20a8578 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.aaf.certservice.certification.configuration;
 
+import org.bouncycastle.asn1.x500.X500Name;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -83,7 +84,7 @@ class Cmpv2ServerProviderTest {
     private Cmpv2Server createTestServer() {
         Cmpv2Server testServer = new Cmpv2Server();
         testServer.setCaName(TEST_CA);
-        testServer.setIssuerDN("testIssuer");
+        testServer.setIssuerDN(new X500Name("CN=testIssuer"));
         testServer.setUrl("http://test.ca.server");
         Authentication testAuthentication = new Authentication();
         testAuthentication.setIak("testIak");
index ea15740..1809760 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.aaf.certservice.certification.configuration.validation;
 
+import org.bouncycastle.asn1.x500.X500Name;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -83,15 +84,6 @@ class Cmpv2ServerConfigurationValidatorTest {
         assertThrows(IllegalArgumentException.class, () -> validator.validate(server));
     }
 
-    @Test
-    public void givenWrongIssuerDNLengthInURLServerDetailsWhenValidatingShouldThrowException() {
-        //given
-        server.setIssuerDN("123");
-
-        //then
-        assertThrows(IllegalArgumentException.class, () -> validator.validate(server));
-    }
-
     @Test
     public void givenWrongRVLengthInURLServerDetailsWhenValidatingShouldThrowException() {
         //given
@@ -114,7 +106,7 @@ class Cmpv2ServerConfigurationValidatorTest {
         server = new Cmpv2Server();
         server.setCaMode(CaMode.CLIENT);
         server.setCaName("TEST");
-        server.setIssuerDN("CN=ManagementCA");
+        server.setIssuerDN(new X500Name("CN=ManagementCA"));
         server.setUrl("http://127.0.0.1/ejbca/publicweb/cmp/cmp");
         server.setAuthentication(authentication);
     }
@@ -124,4 +116,4 @@ class Cmpv2ServerConfigurationValidatorTest {
         authentication.setRv("testRV");
         authentication.setIak("testIAK");
     }
-}
\ No newline at end of file
+}
index bde1dcc..f47f495 100644 (file)
@@ -33,14 +33,13 @@ import org.onap.aaf.certservice.certification.exception.KeyDecryptionException;
 import java.io.IOException;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.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_PEM;
 import static org.onap.aaf.certservice.certification.TestData.TEST_PK;
-import static org.onap.aaf.certservice.certification.TestUtils.pemObjectToString;
 
 
 class CsrModelTest {
@@ -52,20 +51,21 @@ class CsrModelTest {
     @Test
     void shouldByConstructedAndReturnProperFields() throws DecryptionException, IOException {
         // given
+        PemObject testPrivateKey = getPemPrivateKey();
         PemObject testPublicKey = generateTestPublicKey();
+        PKCS10CertificationRequest testCsr = generateTestCertificationRequest();
 
         // when
-        CsrModel csrModel = generateTestCsrModel();
-
+        CsrModel csrModel = generateTestCsrModel(testCsr);
 
         // then
-        assertEquals(
-                pemObjectToString(csrModel.getPrivateKey()).trim(),
-                TEST_PK.trim());
-        assertEquals(
-                pemObjectToString(csrModel.getPublicKey()).trim(),
-                pemObjectToString((testPublicKey)).trim());
-        assertThat(csrModel.getSansData())
+        assertThat(csrModel.getCsr())
+                .isEqualTo(testCsr);
+        assertThat(csrModel.getPrivateKey().getEncoded())
+                .contains(testPrivateKey.getContent());
+        assertThat(csrModel.getPublicKey().getEncoded())
+                .contains(testPublicKey.getContent());
+        assertThat(csrModel.getSans())
                 .contains(
                         "gerrit.onap.org", "test.onap.org", "onap.com");
         assertThat(csrModel.getSubjectData().toString())
@@ -74,24 +74,20 @@ class CsrModelTest {
     }
 
     @Test
-    void shouldThrowExceptionWhenPublicKeyIsNotCorrect() throws KeyDecryptionException, IOException {
+    void shouldThrowExceptionWhenPublicKeyIsNotCorrect() throws DecryptionException, IOException {
         // given
-        PemObjectFactory pemObjectFactory = new PemObjectFactory();
+        PemObject testPrivateKey = getPemPrivateKey();
         PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class);
         SubjectPublicKeyInfo wrongKryInfo = mock(SubjectPublicKeyInfo.class);
         when(testCsr.getSubjectPublicKeyInfo())
                 .thenReturn(wrongKryInfo);
         when(wrongKryInfo.getEncoded())
                 .thenThrow(new IOException());
-        PemObject testPrivateKey = pemObjectFactory.createPemObject(TEST_PK).orElseThrow(
-                () -> new KeyDecryptionException("Private key decoding fail")
-        );
-        CsrModel csrModel = new CsrModel(testCsr, testPrivateKey);
 
         // when
         Exception exception = assertThrows(
                 CsrDecryptionException.class,
-                csrModel::getPublicKey
+                () -> new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build()
         );
 
         String expectedMessage = "Reading Public Key from CSR failed";
@@ -101,12 +97,74 @@ class CsrModelTest {
         assertTrue(actualMessage.contains(expectedMessage));
     }
 
-    private CsrModel generateTestCsrModel() throws DecryptionException {
+    @Test
+    void shouldThrowExceptionWhenPrivateKeyPemIsNotProperPrivateKey() throws KeyDecryptionException, IOException {
+        // given
+        PemObject testPrivateKey = getPemWrongKey();
+        PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class);
+        SubjectPublicKeyInfo wrongKryInfo = mock(SubjectPublicKeyInfo.class);
+        when(testCsr.getSubjectPublicKeyInfo())
+                .thenReturn(wrongKryInfo);
+        when(wrongKryInfo.getEncoded())
+                .thenThrow(new IOException());
+
+        // when
+        Exception exception = assertThrows(
+                KeyDecryptionException.class,
+                () -> new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build()
+        );
+
+        String expectedMessage = "Converting Private Key failed";
+        String actualMessage = exception.getMessage();
+
+        // then
+        assertTrue(actualMessage.contains(expectedMessage));
+    }
+
+    @Test
+    void shouldThrowExceptionWhenPublicKeyPemIsNotProperPublicKey() throws KeyDecryptionException, IOException {
+        // given
+        PemObject testPrivateKey = getPemPrivateKey();
+        PemObject testPublicKey = getPemWrongKey();
+        PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class);
+        SubjectPublicKeyInfo wrongKryInfo = mock(SubjectPublicKeyInfo.class);
+        when(testCsr.getSubjectPublicKeyInfo())
+                .thenReturn(wrongKryInfo);
+        when(wrongKryInfo.getEncoded())
+                .thenReturn(testPublicKey.getContent());
+
+        // when
+        Exception exception = assertThrows(
+                KeyDecryptionException.class,
+                () -> new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build()
+        );
+
+        String expectedMessage = "Converting Public Key from CSR failed";
+        String actualMessage = exception.getMessage();
+
+        // then
+        assertTrue(actualMessage.contains(expectedMessage));
+    }
+
+    private PemObject getPemPrivateKey() throws KeyDecryptionException {
+        PemObjectFactory pemObjectFactory = new PemObjectFactory();
+        return pemObjectFactory.createPemObject(TEST_PK).orElseThrow(
+                () -> new KeyDecryptionException("Private key decoding fail")
+        );
+    }
+
+    private PemObject getPemWrongKey() throws KeyDecryptionException {
+        PemObjectFactory pemObjectFactory = new PemObjectFactory();
+        return pemObjectFactory.createPemObject(TEST_PEM).orElseThrow(
+                () -> new KeyDecryptionException("Private key decoding fail")
+        );
+    }
+
+    private CsrModel generateTestCsrModel(PKCS10CertificationRequest testCsr) throws DecryptionException {
         PemObject testPrivateKey = pemObjectFactory.createPemObject(TEST_PK).orElseThrow(
                 () -> new DecryptionException("Incorrect Private Key, decryption failed")
         );
-        PKCS10CertificationRequest testCsr = generateTestCertificationRequest();
-        return new CsrModel(testCsr, testPrivateKey);
+        return new CsrModel.CsrModelBuilder(testCsr, testPrivateKey).build();
     }
 
     private PemObject generateTestPublicKey() throws DecryptionException, IOException {