mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
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 <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
0fedbdd7a9
commit
c3ed1b38e5
@ -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");
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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.subjectKeyIdentifier,
|
||||
false,
|
||||
extUtils.createSubjectKeyIdentifier(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.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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user