Skip to content

Commit 684d2de

Browse files
committed
ca: Fixes #2530 have all IPs from KVM host in issued X509 cert
This ensures that certificate setup includes all the IP addresses (v4 and v6) when a (KVM) host is added to CloudStack. This fixes #2530. Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1 parent 62b3e4d commit 684d2de

2 files changed

Lines changed: 46 additions & 6 deletions

File tree

plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCAProvider.java

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.io.IOException;
2121
import java.io.StringReader;
2222
import java.math.BigInteger;
23+
import java.net.InetAddress;
2324
import java.security.InvalidKeyException;
2425
import java.security.KeyManagementException;
2526
import java.security.KeyPair;
@@ -34,6 +35,7 @@
3435
import java.security.cert.CertificateException;
3536
import java.security.cert.X509Certificate;
3637
import java.security.spec.InvalidKeySpecException;
38+
import java.util.ArrayList;
3739
import java.util.Collections;
3840
import java.util.List;
3941
import java.util.Map;
@@ -45,6 +47,7 @@
4547
import javax.net.ssl.SSLEngine;
4648
import javax.net.ssl.TrustManager;
4749
import javax.net.ssl.TrustManagerFactory;
50+
import javax.xml.bind.DatatypeConverter;
4851

4952
import org.apache.cloudstack.ca.CAManager;
5053
import org.apache.cloudstack.framework.ca.CAProvider;
@@ -55,9 +58,15 @@
5558
import org.apache.cloudstack.utils.security.CertUtils;
5659
import org.apache.cloudstack.utils.security.KeyStoreUtils;
5760
import org.apache.log4j.Logger;
58-
import org.bouncycastle.jce.PKCS10CertificationRequest;
61+
import org.bouncycastle.asn1.pkcs.Attribute;
62+
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
63+
import org.bouncycastle.asn1.x509.Extension;
64+
import org.bouncycastle.asn1.x509.Extensions;
65+
import org.bouncycastle.asn1.x509.GeneralName;
66+
import org.bouncycastle.asn1.x509.GeneralNames;
5967
import org.bouncycastle.jce.provider.BouncyCastleProvider;
6068
import org.bouncycastle.operator.OperatorCreationException;
69+
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
6170
import org.bouncycastle.util.io.pem.PemObject;
6271
import org.bouncycastle.util.io.pem.PemReader;
6372

@@ -137,7 +146,17 @@ private Certificate generateCertificate(final List<String> domainNames, final Li
137146
return new Certificate(clientCertificate, keyPair.getPrivate(), Collections.singletonList(caCertificate));
138147
}
139148

140-
private Certificate generateCertificateUsingCsr(final String csr, final List<String> domainNames, final List<String> ipAddresses, final int validityDays) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, CertificateException, SignatureException, IOException, OperatorCreationException {
149+
private Certificate generateCertificateUsingCsr(final String csr, final List<String> names, final List<String> ips, final int validityDays) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, CertificateException, SignatureException, IOException, OperatorCreationException {
150+
final List<String> dnsNames = new ArrayList<>();
151+
final List<String> ipAddresses = new ArrayList<>();
152+
153+
if (names != null) {
154+
dnsNames.addAll(names);
155+
}
156+
if (ips != null) {
157+
ipAddresses.addAll(ips);
158+
}
159+
141160
PemObject pemObject = null;
142161

143162
try {
@@ -151,13 +170,33 @@ private Certificate generateCertificateUsingCsr(final String csr, final List<Str
151170
throw new CloudRuntimeException("Unable to read/process CSR: " + csr);
152171
}
153172

154-
final PKCS10CertificationRequest request = new PKCS10CertificationRequest(pemObject.getContent());
173+
final JcaPKCS10CertificationRequest request = new JcaPKCS10CertificationRequest(pemObject.getContent());
174+
final String subject = request.getSubject().toString();
175+
for (final Attribute attribute : request.getAttributes()) {
176+
if (attribute == null) {
177+
continue;
178+
}
179+
if (attribute.getAttrType().equals(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest)) {
180+
final Extensions extensions = Extensions.getInstance(attribute.getAttrValues().getObjectAt(0));
181+
final GeneralNames gns = GeneralNames.fromExtensions(extensions, Extension.subjectAlternativeName);
182+
if (gns != null && gns.getNames() != null && gns.getNames().length > 0) {
183+
for (final GeneralName name : gns.getNames()) {
184+
if (name.getTagNo() == GeneralName.dNSName) {
185+
dnsNames.add(name.getName().toString());
186+
}
187+
if (name.getTagNo() == GeneralName.iPAddress) {
188+
final InetAddress address = InetAddress.getByAddress(DatatypeConverter.parseHexBinary(name.getName().toString().substring(1)));
189+
ipAddresses.add(address.toString().replace("/", ""));
190+
}
191+
}
192+
}
193+
}
194+
}
155195

156-
final String subject = request.getCertificationRequestInfo().getSubject().toString();
157196
final X509Certificate clientCertificate = CertUtils.generateV3Certificate(
158197
caCertificate, caKeyPair, request.getPublicKey(),
159198
subject, CAManager.CertSignatureAlgorithm.value(),
160-
validityDays, domainNames, ipAddresses);
199+
validityDays, dnsNames, ipAddresses);
161200
return new Certificate(clientCertificate, null, Collections.singletonList(caCertificate));
162201
}
163202

scripts/util/keystore-setup

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyal
4242

4343
# Generate CSR
4444
rm -f "$CSR_FILE"
45-
keytool -certreq -storepass "$KS_PASS" -alias "$ALIAS" -file $CSR_FILE -keystore "$KS_FILE" > /dev/null 2>&1
45+
addresses=$(ip address | grep inet | awk '{print $2}' | sed 's/\/.*//g' | grep -v '^169.254.' | grep -v '^127.0.0.1' | grep -v '^::1' | sed 's/^/ip:/g' | tr '\r\n' ',')
46+
keytool -certreq -storepass "$KS_PASS" -alias "$ALIAS" -file $CSR_FILE -keystore "$KS_FILE" -ext san="$addresses" > /dev/null 2>&1
4647
cat "$CSR_FILE"
4748

4849
# Fix file permissions

0 commit comments

Comments
 (0)