This is an automated email from the ASF dual-hosted git repository.

bhaisaab pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new c3ed1b3  CLOUDSTACK-9993: Have basic constraint in CA certificate 
(#2286)
c3ed1b3 is described below

commit c3ed1b38e52b2b47578e7c3eecd4694360e97bfe
Author: Rohit Yadav <[email protected]>
AuthorDate: Wed Oct 11 17:41:37 2017 +0530

    CLOUDSTACK-9993: Have basic constraint in CA certificate (#2286)
    
    - Refactors V3 x509 cert generator to put basic constraint and key usage
      extensions when CA cert is created
    - Refactors root CA provider to use V3 generator to generate CA cert
    
    Signed-off-by: Rohit Yadav <[email protected]>
---
 .../cloudstack/ca/provider/RootCAProvider.java     | 38 ++++++--------
 .../ca/provider/RootCACustomTrustManagerTest.java  |  5 +-
 .../cloudstack/ca/provider/RootCAProviderTest.java |  2 +-
 .../apache/cloudstack/ca/CABackgroundTaskTest.java |  3 +-
 .../apache/cloudstack/ca/CAManagerImplTest.java    |  4 +-
 .../cloudstack/utils/security/CertUtils.java       | 60 +++++++++++++---------
 .../cloudstack/utils/security/CertUtilsTest.java   |  4 +-
 7 files changed, 61 insertions(+), 55 deletions(-)

diff --git 
a/plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCAProvider.java 
b/plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCAProvider.java
index f21cae3..93c8d9d 100644
--- 
a/plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCAProvider.java
+++ 
b/plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCAProvider.java
@@ -137,14 +137,9 @@ public final class RootCAProvider extends AdapterBase 
implements CAProvider, Con
 
         final KeyPair keyPair = 
CertUtils.generateRandomKeyPair(CAManager.CertKeySize.value());
         final X509Certificate clientCertificate = 
CertUtils.generateV3Certificate(
-                caCertificate,
-                caKeyPair.getPrivate(),
-                keyPair.getPublic(),
-                subject,
-                CAManager.CertSignatureAlgorithm.value(),
-                validityDays,
-                domainNames,
-                ipAddresses);
+                caCertificate, caKeyPair, keyPair.getPublic(),
+                subject, CAManager.CertSignatureAlgorithm.value(),
+                validityDays, domainNames, ipAddresses);
         return new Certificate(clientCertificate, keyPair.getPrivate(), 
Collections.singletonList(caCertificate));
     }
 
@@ -164,14 +159,11 @@ public final class RootCAProvider extends AdapterBase 
implements CAProvider, Con
 
         final PKCS10CertificationRequest request = new 
PKCS10CertificationRequest(pemObject.getContent());
 
+        final String subject = 
request.getCertificationRequestInfo().getSubject().toString();
         final X509Certificate clientCertificate = 
CertUtils.generateV3Certificate(
-                caCertificate, caKeyPair.getPrivate(),
-                request.getPublicKey(),
-                request.getCertificationRequestInfo().getSubject().toString(),
-                CAManager.CertSignatureAlgorithm.value(),
-                validityDays,
-                domainNames,
-                ipAddresses);
+                caCertificate, caKeyPair, request.getPublicKey(),
+                subject, CAManager.CertSignatureAlgorithm.value(),
+                validityDays, domainNames, ipAddresses);
         return new Certificate(clientCertificate, null, 
Collections.singletonList(caCertificate));
 
     }
@@ -257,6 +249,10 @@ public final class RootCAProvider extends AdapterBase 
implements CAProvider, Con
     /////////////// Root CA Config ///////////////////
     //////////////////////////////////////////////////
 
+    private int getCaValidityDays() {
+        return 365 * caValidityYears;
+    }
+
     private char[] findKeyStorePassphrase() {
         char[] passphrase = KeyStoreUtils.defaultKeystorePassphrase;
         final String configuredPassphrase = 
DbProperties.getDbProperties().getProperty("db.cloud.keyStorePassphrase");
@@ -268,7 +264,7 @@ public final class RootCAProvider extends AdapterBase 
implements CAProvider, Con
 
     private boolean createManagementServerKeystore(final String 
keyStoreFilePath, final char[] passphrase) {
         final Certificate managementServerCertificate = 
issueCertificate(Collections.singletonList(NetUtils.getHostName()),
-                Collections.singletonList(NetUtils.getDefaultHostIp()), 
caValidityYears * 365);
+                Collections.singletonList(NetUtils.getDefaultHostIp()), 
getCaValidityDays());
         if (managementServerCertificate == null || 
managementServerCertificate.getPrivateKey() == null) {
             throw new CloudRuntimeException("Failed to generate certificate 
and setup management server keystore");
         }
@@ -347,12 +343,10 @@ public final class RootCAProvider extends AdapterBase 
implements CAProvider, Con
         }
         try {
             LOG.debug("Generating root CA certificate");
-            final X509Certificate rootCaCertificate = 
CertUtils.generateV1Certificate(
-                    caKeyPair,
-                    rootCAIssuerDN.value(),
-                    rootCAIssuerDN.value(),
-                    caValidityYears,
-                    CAManager.CertSignatureAlgorithm.value());
+            final X509Certificate rootCaCertificate = 
CertUtils.generateV3Certificate(
+                    null, caKeyPair, caKeyPair.getPublic(),
+                    rootCAIssuerDN.value(), 
CAManager.CertSignatureAlgorithm.value(),
+                    getCaValidityDays(), null, null);
             if (!configDao.update(rootCACertificate.key(), 
rootCACertificate.category(), 
CertUtils.x509CertificateToPem(rootCaCertificate))) {
                 LOG.error("Failed to update RootCA public/x509 certificate");
             }
diff --git 
a/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCACustomTrustManagerTest.java
 
b/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCACustomTrustManagerTest.java
index cab1941..8161d75 100644
--- 
a/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCACustomTrustManagerTest.java
+++ 
b/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCACustomTrustManagerTest.java
@@ -56,9 +56,8 @@ public class RootCACustomTrustManagerTest {
         certMap.clear();
         caKeypair = CertUtils.generateRandomKeyPair(1024);
         clientKeypair = CertUtils.generateRandomKeyPair(1024);
-        caCertificate = CertUtils.generateV1Certificate(caKeypair, "CN=ca", 
"CN=ca", 1,
-                "SHA256withRSA");
-        expiredClientCertificate = 
CertUtils.generateV3Certificate(caCertificate, caKeypair.getPrivate(), 
clientKeypair.getPublic(),
+        caCertificate = CertUtils.generateV3Certificate(null, caKeypair, 
caKeypair.getPublic(), "CN=ca", "SHA256withRSA", 365, null, null);
+        expiredClientCertificate = 
CertUtils.generateV3Certificate(caCertificate, caKeypair, 
clientKeypair.getPublic(),
                 "CN=cloudstack.apache.org", "SHA256withRSA", 0, 
Collections.singletonList("cloudstack.apache.org"), 
Collections.singletonList(clientIp));
     }
 
diff --git 
a/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCAProviderTest.java
 
b/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCAProviderTest.java
index 44e2bcf..d5d6428 100644
--- 
a/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCAProviderTest.java
+++ 
b/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCAProviderTest.java
@@ -66,7 +66,7 @@ public class RootCAProviderTest {
     @Before
     public void setUp() throws Exception {
         caKeyPair = CertUtils.generateRandomKeyPair(1024);
-        caCertificate = CertUtils.generateV1Certificate(caKeyPair, "CN=ca", 
"CN=ca", 1, "SHA256withRSA");
+        caCertificate = CertUtils.generateV3Certificate(null, caKeyPair, 
caKeyPair.getPublic(), "CN=ca", "SHA256withRSA", 365, null, null);
 
         provider = new RootCAProvider();
 
diff --git a/server/test/org/apache/cloudstack/ca/CABackgroundTaskTest.java 
b/server/test/org/apache/cloudstack/ca/CABackgroundTaskTest.java
index d2c800d..564bbe3 100644
--- a/server/test/org/apache/cloudstack/ca/CABackgroundTaskTest.java
+++ b/server/test/org/apache/cloudstack/ca/CABackgroundTaskTest.java
@@ -68,8 +68,7 @@ public class CABackgroundTaskTest {
         
host.setManagementServerId(ManagementServerNode.getManagementServerId());
         task = new CAManagerImpl.CABackgroundTask(caManager, hostDao);
         final KeyPair keypair = CertUtils.generateRandomKeyPair(1024);
-        expiredCertificate = CertUtils.generateV1Certificate(keypair, "CN=ca", 
"CN=ca", 0,
-                "SHA256withRSA");
+        expiredCertificate = CertUtils.generateV3Certificate(null, keypair, 
keypair.getPublic(), "CN=ca", "SHA256withRSA", 0, null, null);
 
         Mockito.when(hostDao.findByIp(Mockito.anyString())).thenReturn(host);
         Mockito.when(caManager.getActiveCertificatesMap()).thenReturn(certMap);
diff --git a/server/test/org/apache/cloudstack/ca/CAManagerImplTest.java 
b/server/test/org/apache/cloudstack/ca/CAManagerImplTest.java
index 87e128c..14ecc97 100644
--- a/server/test/org/apache/cloudstack/ca/CAManagerImplTest.java
+++ b/server/test/org/apache/cloudstack/ca/CAManagerImplTest.java
@@ -21,6 +21,7 @@ package org.apache.cloudstack.ca;
 
 import java.lang.reflect.Field;
 import java.math.BigInteger;
+import java.security.KeyPair;
 import java.security.cert.X509Certificate;
 import java.util.Collections;
 
@@ -108,7 +109,8 @@ public class CAManagerImplTest {
     public void testProvisionCertificate() throws Exception {
         final Host host = Mockito.mock(Host.class);
         Mockito.when(host.getPrivateIpAddress()).thenReturn("1.2.3.4");
-        final X509Certificate certificate = 
CertUtils.generateV1Certificate(CertUtils.generateRandomKeyPair(1024), "CN=ca", 
"CN=ca", 1, "SHA256withRSA");
+        final KeyPair keyPair = CertUtils.generateRandomKeyPair(1024);
+        final X509Certificate certificate = 
CertUtils.generateV3Certificate(null, keyPair, keyPair.getPublic(), "CN=ca", 
"SHA256withRSA", 365, null, null);
         Mockito.when(caProvider.issueCertificate(Mockito.anyString(), 
Mockito.anyList(), Mockito.anyList(), Mockito.anyInt())).thenReturn(new 
Certificate(certificate, null, Collections.singletonList(certificate)));
         Mockito.when(agentManager.send(Mockito.anyLong(), 
Mockito.any(SetupKeyStoreCommand.class))).thenReturn(new 
SetupKeystoreAnswer("someCsr"));
         
Mockito.when(agentManager.reconnect(Mockito.anyLong())).thenReturn(true);
diff --git 
a/utils/src/main/java/org/apache/cloudstack/utils/security/CertUtils.java 
b/utils/src/main/java/org/apache/cloudstack/utils/security/CertUtils.java
index c2ef9ed..7e78362 100644
--- a/utils/src/main/java/org/apache/cloudstack/utils/security/CertUtils.java
+++ b/utils/src/main/java/org/apache/cloudstack/utils/security/CertUtils.java
@@ -48,9 +48,11 @@ import org.apache.log4j.Logger;
 import org.bouncycastle.asn1.ASN1Encodable;
 import org.bouncycastle.asn1.DERSequence;
 import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.BasicConstraints;
 import org.bouncycastle.asn1.x509.Extension;
 import org.bouncycastle.asn1.x509.GeneralName;
 import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.KeyUsage;
 import org.bouncycastle.cert.X509CertificateHolder;
 import org.bouncycastle.cert.X509v1CertificateBuilder;
 import org.bouncycastle.cert.X509v3CertificateBuilder;
@@ -176,7 +178,7 @@ public class CertUtils {
     }
 
     public static X509Certificate generateV3Certificate(final X509Certificate 
caCert,
-                                                        final PrivateKey 
caPrivateKey,
+                                                        final KeyPair 
caKeyPair,
                                                         final PublicKey 
clientPublicKey,
                                                         final String subject,
                                                         final String 
signatureAlgorithm,
@@ -186,25 +188,34 @@ public class CertUtils {
 
         final DateTime now = DateTime.now(DateTimeZone.UTC);
         final BigInteger serial = generateRandomBigInt();
-        final X509v3CertificateBuilder certBuilder = new 
JcaX509v3CertificateBuilder(
-                caCert,
-                serial,
-                now.minusHours(12).toDate(),
-                now.plusDays(validityDays).toDate(),
-                new X500Principal(subject),
-                clientPublicKey);
-
         final JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
+        final X509v3CertificateBuilder certBuilder;
+        if (caCert == null) {
+            // Generate CA certificate
+            certBuilder = new JcaX509v3CertificateBuilder(
+                    new X500Name(subject),
+                    serial,
+                    now.minusHours(12).toDate(),
+                    now.plusDays(validityDays).toDate(),
+                    new X500Name(subject),
+                    clientPublicKey);
+
+            certBuilder.addExtension(Extension.basicConstraints, true, new 
BasicConstraints(true));
+            certBuilder.addExtension(Extension.keyUsage, true, new 
KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign));
+        } else {
+            // Generate client certificate
+            certBuilder = new JcaX509v3CertificateBuilder(
+                    caCert,
+                    serial,
+                    now.minusHours(12).toDate(),
+                    now.plusDays(validityDays).toDate(),
+                    new X500Principal(subject),
+                    clientPublicKey);
+
+            certBuilder.addExtension(Extension.authorityKeyIdentifier, false, 
extUtils.createAuthorityKeyIdentifier(caCert));
+        }
 
-        certBuilder.addExtension(
-                Extension.subjectKeyIdentifier,
-                false,
-                extUtils.createSubjectKeyIdentifier(clientPublicKey));
-
-        certBuilder.addExtension(
-                Extension.authorityKeyIdentifier,
-                false,
-                extUtils.createAuthorityKeyIdentifier(caCert));
+        certBuilder.addExtension(Extension.subjectKeyIdentifier, false, 
extUtils.createSubjectKeyIdentifier(clientPublicKey));
 
         final List<ASN1Encodable> subjectAlternativeNames = new 
ArrayList<ASN1Encodable>();
         if (publicIPAddresses != null) {
@@ -225,16 +236,17 @@ public class CertUtils {
         }
         if (subjectAlternativeNames.size() > 0) {
             final GeneralNames subjectAltNames = GeneralNames.getInstance(new 
DERSequence(subjectAlternativeNames.toArray(new ASN1Encodable[] {})));
-            certBuilder.addExtension(
-                    Extension.subjectAlternativeName,
-                    false,
-                    subjectAltNames);
+            certBuilder.addExtension(Extension.subjectAlternativeName, false, 
subjectAltNames);
         }
 
-        final ContentSigner signer = new 
JcaContentSignerBuilder(signatureAlgorithm).setProvider("BC").build(caPrivateKey);
+        final ContentSigner signer = new 
JcaContentSignerBuilder(signatureAlgorithm).setProvider("BC").build(caKeyPair.getPrivate());
         final X509CertificateHolder certHolder = certBuilder.build(signer);
         final X509Certificate cert = new 
JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
-        cert.verify(caCert.getPublicKey());
+        if (caCert != null) {
+            cert.verify(caCert.getPublicKey());
+        } else {
+            cert.verify(caKeyPair.getPublic());
+        }
         return cert;
     }
 }
diff --git 
a/utils/src/test/java/org/apache/cloudstack/utils/security/CertUtilsTest.java 
b/utils/src/test/java/org/apache/cloudstack/utils/security/CertUtilsTest.java
index 406f604..1fed176 100644
--- 
a/utils/src/test/java/org/apache/cloudstack/utils/security/CertUtilsTest.java
+++ 
b/utils/src/test/java/org/apache/cloudstack/utils/security/CertUtilsTest.java
@@ -39,7 +39,7 @@ public class CertUtilsTest {
     @Before
     public void setUp() throws Exception {
         caKeyPair = CertUtils.generateRandomKeyPair(1024);
-        caCertificate = CertUtils.generateV1Certificate(caKeyPair, "CN=test", 
"CN=test", 1, "SHA256WithRSAEncryption");
+        caCertificate = CertUtils.generateV3Certificate(null, caKeyPair, 
caKeyPair.getPublic(), "CN=test", "SHA256WithRSAEncryption", 365, null, null);
     }
 
     @Test
@@ -93,7 +93,7 @@ public class CertUtilsTest {
         final List<String> domainNames = Arrays.asList("domain1.com", 
"www.2.domain2.com", "3.domain3.com");
         final List<String> addressList = Arrays.asList("1.2.3.4", 
"192.168.1.1", "2a02:120b:2c16:f6d0:d9df:8ebc:e44a:f181");
 
-        final X509Certificate clientCert = 
CertUtils.generateV3Certificate(caCertificate, caKeyPair.getPrivate(), 
clientKeyPair.getPublic(),
+        final X509Certificate clientCert = 
CertUtils.generateV3Certificate(caCertificate, caKeyPair, 
clientKeyPair.getPublic(),
                 "CN=domain.example", "SHA256WithRSAEncryption", 10, 
domainNames, addressList);
 
         clientCert.verify(caKeyPair.getPublic());

-- 
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].

Reply via email to