[OOM-CERT-SERVICE] Code refactor
[oom/platform/cert-service.git] / certService / src / main / java / org / onap / oom / certservice / cmpv2client / impl / CmpClientImpl.java
index 549cf6b..bbca91b 100644 (file)
@@ -25,45 +25,31 @@ package org.onap.oom.certservice.cmpv2client.impl;
 import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseHelper.checkIfCmpResponseContainsError;
 import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseHelper.getCertFromByteArray;
 import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseHelper.verifyAndReturnCertChainAndTrustSTore;
-import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.checkImplicitConfirm;
-import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.verifyPasswordBasedProtection;
-import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.verifySignature;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
+import java.security.Security;
 import java.security.cert.CertificateParsingException;
 import java.security.cert.X509Certificate;
-import java.security.spec.InvalidKeySpecException;
 import java.util.Collections;
 import java.util.Date;
 import java.util.Objects;
 import java.util.Optional;
-import org.apache.commons.codec.binary.Base64;
 import org.apache.http.impl.client.CloseableHttpClient;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
 import org.bouncycastle.asn1.cmp.CMPCertificate;
 import org.bouncycastle.asn1.cmp.CertRepMessage;
 import org.bouncycastle.asn1.cmp.CertResponse;
 import org.bouncycastle.asn1.cmp.PKIBody;
-import org.bouncycastle.asn1.cmp.PKIHeader;
 import org.bouncycastle.asn1.cmp.PKIMessage;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
 import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.util.io.pem.PemReader;
-import org.onap.oom.certservice.certification.configuration.model.CaMode;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server;
-import org.onap.oom.certservice.certification.exception.KeyDecryptionException;
-import org.onap.oom.certservice.certification.model.CertificateUpdateModel;
 import org.onap.oom.certservice.certification.model.CsrModel;
+import org.onap.oom.certservice.certification.model.OldCertificateModel;
 import org.onap.oom.certservice.cmpv2client.api.CmpClient;
 import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException;
-import org.onap.oom.certservice.cmpv2client.exceptions.CmpServerException;
 import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel;
+import org.onap.oom.certservice.cmpv2client.validation.CmpCertificationValidator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -75,55 +61,56 @@ public class CmpClientImpl implements CmpClient {
 
     private static final Logger LOG = LoggerFactory.getLogger(CmpClientImpl.class);
     private final CloseableHttpClient httpClient;
-
-    private static final String DEFAULT_CA_NAME = "Certification Authority";
-    private static final String DEFAULT_PROFILE = CaMode.RA.getProfile();
-    private static final ASN1ObjectIdentifier PASSWORD_BASED_MAC = new ASN1ObjectIdentifier("1.2.840.113533.7.66.13");
+    private final CmpCertificationValidator validator;
 
     public CmpClientImpl(CloseableHttpClient httpClient) {
         this.httpClient = httpClient;
+        this.validator = new CmpCertificationValidator();
+    }
+
+    static {
+        Security.addProvider(new BouncyCastleProvider());
     }
 
     @Override
-    public Cmpv2CertificationModel createCertificate(
+    public Cmpv2CertificationModel executeInitializationRequest(
             CsrModel csrModel,
             Cmpv2Server server,
             Date notBefore,
             Date notAfter)
             throws CmpClientException {
 
-        validate(csrModel, server, httpClient, notBefore, notAfter);
+        validator.validate(csrModel, server, httpClient, notBefore, notAfter);
         final CreateCertRequest certRequest = getIakRvRequest(csrModel, server, notBefore, notAfter, PKIBody.TYPE_INIT_REQ);
         return executeCmpRequest(csrModel, server, certRequest);
     }
 
     @Override
-    public Cmpv2CertificationModel createCertificate(CsrModel csrModel, Cmpv2Server server)
+    public Cmpv2CertificationModel executeInitializationRequest(CsrModel csrModel, Cmpv2Server server)
             throws CmpClientException {
-        return createCertificate(csrModel, server, null, null);
+        return executeInitializationRequest(csrModel, server, null, null);
     }
 
     @Override
-    public Cmpv2CertificationModel updateCertificate(CsrModel csrModel, Cmpv2Server cmpv2Server,
-        CertificateUpdateModel certificateUpdateModel) throws CmpClientException {
-        validate(csrModel, cmpv2Server, httpClient, null, null);
+    public Cmpv2CertificationModel executeKeyUpdateRequest(CsrModel csrModel, Cmpv2Server cmpv2Server,
+        OldCertificateModel oldCertificateModel) throws CmpClientException {
+        validator.validate(csrModel, cmpv2Server, httpClient, null, null);
 
-        final PkiMessageProtection pkiMessageProtection = getSignatureProtection(certificateUpdateModel);
+        final PkiMessageProtection pkiMessageProtection = getSignatureProtection(oldCertificateModel);
         final CreateCertRequest certRequest =
             getCmpMessageBuilderWithCommonRequestValues(csrModel, cmpv2Server)
                 .with(CreateCertRequest::setCmpRequestType, PKIBody.TYPE_KEY_UPDATE_REQ)
-                .with(CreateCertRequest::setExtraCerts, getCMPCertificateFromPem(certificateUpdateModel.getEncodedOldCert()))
+                .with(CreateCertRequest::setExtraCerts, getCMPCertificate(oldCertificateModel.getOldCertificate()))
                 .with(CreateCertRequest::setProtection, pkiMessageProtection)
                 .build();
 
         return executeCmpRequest(csrModel, cmpv2Server, certRequest);
-
     }
 
     @Override
-    public Cmpv2CertificationModel certificationRequest(CsrModel csrModel, Cmpv2Server cmpv2Server) throws CmpClientException {
+    public Cmpv2CertificationModel executeCertificationRequest(CsrModel csrModel, Cmpv2Server cmpv2Server) throws CmpClientException {
 
-        validate(csrModel, cmpv2Server, httpClient, null, null);
+        validator.validate(csrModel, cmpv2Server, httpClient, null, null);
         final CreateCertRequest certRequest = getIakRvRequest(csrModel, cmpv2Server, null, null, PKIBody.TYPE_CERT_REQ);
         return executeCmpRequest(csrModel, cmpv2Server, certRequest);
     }
@@ -163,86 +150,48 @@ public class CmpClientImpl implements CmpClient {
             .with(CreateCertRequest::setSubjectKeyPair, keyPair);
     }
 
-    private SignatureProtection getSignatureProtection(CertificateUpdateModel certificateUpdateModel)
-        throws CmpClientException {
-        try {
-            PrivateKey oldPrivateKey = certificateUpdateModel.getOldPrivateKeyObject();
-            return new SignatureProtection(oldPrivateKey);
-        } catch (NoSuchAlgorithmException | KeyDecryptionException | InvalidKeySpecException e) {
-            throw new CmpClientException("Cannot parse old private key ", e);
-        }
-
+    private SignatureProtection getSignatureProtection(OldCertificateModel oldCertificateModel) {
+            return new SignatureProtection(oldCertificateModel.getOldPrivateKey());
     }
 
-    private CMPCertificate[] getCMPCertificateFromPem(String encodedCertPem) throws CmpClientException {
-        try {
-            Certificate certificate = Certificate.getInstance(
-                new PemReader(
-                    new InputStreamReader(
-                        new ByteArrayInputStream(
-                            Base64.decodeBase64(encodedCertPem))))
-                .readPemObject().getContent());
-            CMPCertificate cert = new CMPCertificate(certificate);
+    private CMPCertificate[] getCMPCertificate(Certificate oldCertificate) {
+            CMPCertificate cert = new CMPCertificate(oldCertificate);
             return new CMPCertificate[]{cert};
-        } catch (IOException | NullPointerException e ) {
-            throw new CmpClientException("Cannot parse old certificate", e);
-        }
-    }
-
-    private void checkCmpResponse(
-            final PKIMessage respPkiMessage, final PublicKey publicKey, final String initAuthPassword)
-            throws CmpClientException {
-        final PKIHeader header = respPkiMessage.getHeader();
-        final AlgorithmIdentifier protectionAlgo = header.getProtectionAlg();
-        verifySignatureWithPublicKey(respPkiMessage, publicKey);
-        if (isPasswordBasedMacAlgorithm(protectionAlgo)) {
-            LOG.info("CMP response is protected by Password Base Mac Algorithm. Attempt to verify protection");
-            verifyPasswordBasedMacProtection(respPkiMessage, initAuthPassword, header, protectionAlgo);
-        }
     }
 
-    private boolean isPasswordBasedMacAlgorithm(AlgorithmIdentifier protectionAlgo) throws CmpClientException {
-        if (Objects.isNull(protectionAlgo)) {
-            LOG.error("CMP response does not contain Protection Algorithm field");
-            throw new CmpClientException("CMP response does not contain Protection Algorithm field");
-        }
-        return PASSWORD_BASED_MAC.equals(protectionAlgo.getAlgorithm());
-    }
-
-    private void verifySignatureWithPublicKey(PKIMessage respPkiMessage, PublicKey publicKey)
+    private Cmpv2CertificationModel retrieveCertificates(
+            CsrModel csrModel, Cmpv2Server server, PKIMessage pkiMessage, Cmpv2HttpClient cmpv2HttpClient)
             throws CmpClientException {
-        if (Objects.nonNull(publicKey)) {
-            LOG.debug("Verifying signature of the response.");
-            verifySignature(respPkiMessage, publicKey);
-        } else {
-            LOG.error("Public Key is not available, therefore cannot verify signature");
-            throw new CmpClientException(
-                    "Public Key is not available, therefore cannot verify signature");
+        final byte[] respBytes = cmpv2HttpClient.postRequest(pkiMessage, server.getUrl(), server.getCaName());
+        try {
+            final PKIMessage respPkiMessage = PKIMessage.getInstance(respBytes);
+            LOG.info("Received response from Server");
+            checkIfCmpResponseContainsError(respPkiMessage);
+            validator.checkCmpResponse(respPkiMessage, csrModel.getPublicKey(), server.getAuthentication().getIak());
+            return checkCmpCertRepMessage(respPkiMessage);
+        } catch (IllegalArgumentException iae) {
+            CmpClientException cmpClientException =
+                    new CmpClientException(
+                            "Error encountered while processing response from CA server ", iae);
+            LOG.error("Error encountered while processing response from CA server ", iae);
+            throw cmpClientException;
         }
     }
 
-    private void verifyPasswordBasedMacProtection(PKIMessage respPkiMessage, String initAuthPassword,
-        PKIHeader header, AlgorithmIdentifier protectionAlgo)
-        throws CmpClientException {
-        LOG.debug("Verifying PasswordBased Protection of the Response.");
-        verifyPasswordBasedProtection(respPkiMessage, initAuthPassword, protectionAlgo);
-        checkImplicitConfirm(header);
-    }
-
     private Cmpv2CertificationModel checkCmpCertRepMessage(final PKIMessage respPkiMessage)
-            throws CmpClientException {
+        throws CmpClientException {
         final PKIBody pkiBody = respPkiMessage.getBody();
         if (Objects.nonNull(pkiBody) && pkiBody.getContent() instanceof CertRepMessage) {
             final CertRepMessage certRepMessage = (CertRepMessage) pkiBody.getContent();
             if (Objects.nonNull(certRepMessage)) {
                 try {
                     CertResponse certResponse = getCertificateResponseContainingNewCertificate(certRepMessage);
-                    checkServerResponse(certResponse);
+                    validator.checkServerResponse(certResponse);
                     return verifyReturnCertChainAndTrustStore(respPkiMessage, certRepMessage, certResponse);
                 } catch (IOException | CertificateParsingException ex) {
                     CmpClientException cmpClientException =
-                            new CmpClientException(
-                                    "Exception occurred while retrieving Certificates from response", ex);
+                        new CmpClientException(
+                            "Exception occurred while retrieving Certificates from response", ex);
                     LOG.error("Exception occurred while retrieving Certificates from response", ex);
                     throw cmpClientException;
                 }
@@ -253,98 +202,23 @@ public class CmpClientImpl implements CmpClient {
         return new Cmpv2CertificationModel(Collections.emptyList(), Collections.emptyList());
     }
 
-    private void checkServerResponse(CertResponse certResponse) {
-        if (certResponse.getStatus() != null && certResponse.getStatus().getStatus() != null) {
-            logServerResponse(certResponse);
-            if (certResponse.getStatus().getStatus().intValue() == PkiStatus.REJECTED.getCode()) {
-                String serverMessage = certResponse.getStatus().getStatusString().getStringAt(0).getString();
-                throw new CmpServerException(Optional.ofNullable(serverMessage).orElse("N/A"));
-            }
-        }
-    }
-
-    private void logServerResponse(CertResponse certResponse) {
-        if (LOG.isInfoEnabled()) {
-            LOG.info("Response status code: {}", certResponse.getStatus().getStatus());
-        }
-        if (certResponse.getStatus().getStatusString() != null) {
-            String serverMessage = certResponse.getStatus().getStatusString().getStringAt(0).getString();
-            LOG.warn("Response status text: {}", serverMessage);
-        }
-        if (LOG.isWarnEnabled() && certResponse.getStatus().getFailInfo() != null) {
-            LOG.warn("Response fail info:   {}", certResponse.getStatus().getFailInfo());
-        }
-    }
-
     private Cmpv2CertificationModel verifyReturnCertChainAndTrustStore(
-            PKIMessage respPkiMessage, CertRepMessage certRepMessage, CertResponse certResponse)
-            throws CertificateParsingException, CmpClientException, IOException {
+        PKIMessage respPkiMessage, CertRepMessage certRepMessage, CertResponse certResponse)
+        throws CertificateParsingException, CmpClientException, IOException {
         LOG.info("Verifying certificates returned as part of CertResponse.");
         final CMPCertificate cmpCertificate =
-                certResponse.getCertifiedKeyPair().getCertOrEncCert().getCertificate();
+            certResponse.getCertifiedKeyPair().getCertOrEncCert().getCertificate();
         final Optional<X509Certificate> leafCertificate =
-                getCertFromByteArray(cmpCertificate.getEncoded(), X509Certificate.class);
+            getCertFromByteArray(cmpCertificate.getEncoded(), X509Certificate.class);
         if (leafCertificate.isPresent()) {
             return verifyAndReturnCertChainAndTrustSTore(
-                    respPkiMessage, certRepMessage, leafCertificate.get());
+                respPkiMessage, certRepMessage, leafCertificate.get());
         }
         return new Cmpv2CertificationModel(Collections.emptyList(), Collections.emptyList());
     }
 
     private CertResponse getCertificateResponseContainingNewCertificate(
-            CertRepMessage certRepMessage) {
+        CertRepMessage certRepMessage) {
         return certRepMessage.getResponse()[0];
     }
-
-    /**
-     * Validate inputs for Certificate Creation.
-     *
-     * @param csrModel Certificate Signing Request model. Must not be {@code null}.
-     * @param server   CMPv2 Server. Must not be {@code null}.
-     * @throws IllegalArgumentException if Before Date is set after the After Date.
-     */
-    private static void validate(
-            final CsrModel csrModel,
-            final Cmpv2Server server,
-            final CloseableHttpClient httpClient,
-            final Date notBefore,
-            final Date notAfter) {
-
-        String caName = CmpUtil.isNullOrEmpty(server.getCaName()) ? server.getCaName() : DEFAULT_CA_NAME;
-        String profile = server.getCaMode() != null ? server.getCaMode().getProfile() : DEFAULT_PROFILE;
-        LOG.info(
-                "Validate before creating Certificate Request for CA :{} in Mode {} ", caName, profile);
-
-        CmpUtil.notNull(csrModel, "CsrModel Instance");
-        CmpUtil.notNull(csrModel.getSubjectData(), "Subject DN");
-        CmpUtil.notNull(csrModel.getPrivateKey(), "Subject private key");
-        CmpUtil.notNull(csrModel.getPublicKey(), "Subject public key");
-        CmpUtil.notNull(server.getIssuerDN(), "Issuer DN");
-        CmpUtil.notNull(server.getUrl(), "External CA URL");
-        CmpUtil.notNull(server.getAuthentication().getIak(), "IAK/RV Password");
-        CmpUtil.notNull(httpClient, "Closeable Http Client");
-
-        if (notBefore != null && notAfter != null && notBefore.compareTo(notAfter) > 0) {
-            throw new IllegalArgumentException("Before Date is set after the After Date");
-        }
-    }
-
-    private Cmpv2CertificationModel retrieveCertificates(
-            CsrModel csrModel, Cmpv2Server server, PKIMessage pkiMessage, Cmpv2HttpClient cmpv2HttpClient)
-            throws CmpClientException {
-        final byte[] respBytes = cmpv2HttpClient.postRequest(pkiMessage, server.getUrl(), server.getCaName());
-        try {
-            final PKIMessage respPkiMessage = PKIMessage.getInstance(respBytes);
-            LOG.info("Received response from Server");
-            checkIfCmpResponseContainsError(respPkiMessage);
-            checkCmpResponse(respPkiMessage, csrModel.getPublicKey(), server.getAuthentication().getIak());
-            return checkCmpCertRepMessage(respPkiMessage);
-        } catch (IllegalArgumentException iae) {
-            CmpClientException cmpClientException =
-                    new CmpClientException(
-                            "Error encountered while processing response from CA server ", iae);
-            LOG.error("Error encountered while processing response from CA server ", iae);
-            throw cmpClientException;
-        }
-    }
 }