You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2018/05/04 07:07:32 UTC
[cloudstack] 02/08: ca: Fixes #2530 have all IPs from KVM host in
issued X509 cert
This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch 4.11
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit eb75c1eff51e4e121f7ef690cb56b8b22d43f143
Author: Rohit Yadav <ro...@shapeblue.com>
AuthorDate: Mon Apr 30 17:40:20 2018 +0530
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 <ro...@shapeblue.com>
---
.../cloudstack/ca/provider/RootCAProvider.java | 49 +++++++++++++++++++---
scripts/util/keystore-setup | 3 +-
.../cloudstack/utils/security/CertUtils.java | 5 ++-
3 files changed, 49 insertions(+), 8 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 6584b35..f36d067 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
@@ -20,6 +20,7 @@ package org.apache.cloudstack.ca.provider;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigInteger;
+import java.net.InetAddress;
import java.security.InvalidKeyException;
import java.security.KeyManagementException;
import java.security.KeyPair;
@@ -34,6 +35,7 @@ import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -45,6 +47,7 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
+import javax.xml.bind.DatatypeConverter;
import org.apache.cloudstack.ca.CAManager;
import org.apache.cloudstack.framework.ca.CAProvider;
@@ -55,9 +58,15 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.utils.security.CertUtils;
import org.apache.cloudstack.utils.security.KeyStoreUtils;
import org.apache.log4j.Logger;
-import org.bouncycastle.jce.PKCS10CertificationRequest;
+import org.bouncycastle.asn1.pkcs.Attribute;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
@@ -137,7 +146,17 @@ public final class RootCAProvider extends AdapterBase implements CAProvider, Con
return new Certificate(clientCertificate, keyPair.getPrivate(), Collections.singletonList(caCertificate));
}
- 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 {
+ 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 {
+ final List<String> dnsNames = new ArrayList<>();
+ final List<String> ipAddresses = new ArrayList<>();
+
+ if (names != null) {
+ dnsNames.addAll(names);
+ }
+ if (ips != null) {
+ ipAddresses.addAll(ips);
+ }
+
PemObject pemObject = null;
try {
@@ -151,13 +170,33 @@ public final class RootCAProvider extends AdapterBase implements CAProvider, Con
throw new CloudRuntimeException("Unable to read/process CSR: " + csr);
}
- final PKCS10CertificationRequest request = new PKCS10CertificationRequest(pemObject.getContent());
+ final JcaPKCS10CertificationRequest request = new JcaPKCS10CertificationRequest(pemObject.getContent());
+ final String subject = request.getSubject().toString();
+ for (final Attribute attribute : request.getAttributes()) {
+ if (attribute == null) {
+ continue;
+ }
+ if (attribute.getAttrType().equals(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest)) {
+ final Extensions extensions = Extensions.getInstance(attribute.getAttrValues().getObjectAt(0));
+ final GeneralNames gns = GeneralNames.fromExtensions(extensions, Extension.subjectAlternativeName);
+ if (gns != null && gns.getNames() != null && gns.getNames().length > 0) {
+ for (final GeneralName name : gns.getNames()) {
+ if (name.getTagNo() == GeneralName.dNSName) {
+ dnsNames.add(name.getName().toString());
+ }
+ if (name.getTagNo() == GeneralName.iPAddress) {
+ final InetAddress address = InetAddress.getByAddress(DatatypeConverter.parseHexBinary(name.getName().toString().substring(1)));
+ ipAddresses.add(address.toString().replace("/", ""));
+ }
+ }
+ }
+ }
+ }
- final String subject = request.getCertificationRequestInfo().getSubject().toString();
final X509Certificate clientCertificate = CertUtils.generateV3Certificate(
caCertificate, caKeyPair, request.getPublicKey(),
subject, CAManager.CertSignatureAlgorithm.value(),
- validityDays, domainNames, ipAddresses);
+ validityDays, dnsNames, ipAddresses);
return new Certificate(clientCertificate, null, Collections.singletonList(caCertificate));
}
diff --git a/scripts/util/keystore-setup b/scripts/util/keystore-setup
index 48ce062..ce96336 100755
--- a/scripts/util/keystore-setup
+++ b/scripts/util/keystore-setup
@@ -42,7 +42,8 @@ keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyal
# Generate CSR
rm -f "$CSR_FILE"
-keytool -certreq -storepass "$KS_PASS" -alias "$ALIAS" -file $CSR_FILE -keystore "$KS_FILE" > /dev/null 2>&1
+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' ',')
+keytool -certreq -storepass "$KS_PASS" -alias "$ALIAS" -file $CSR_FILE -keystore "$KS_FILE" -ext san="$addresses" > /dev/null 2>&1
cat "$CSR_FILE"
# Fix file permissions
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 7e78362..aea65a7 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
@@ -40,6 +40,7 @@ import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import javax.security.auth.x500.X500Principal;
@@ -219,7 +220,7 @@ public class CertUtils {
final List<ASN1Encodable> subjectAlternativeNames = new ArrayList<ASN1Encodable>();
if (publicIPAddresses != null) {
- for (final String publicIPAddress: publicIPAddresses) {
+ for (final String publicIPAddress: new HashSet<>(publicIPAddresses)) {
if (Strings.isNullOrEmpty(publicIPAddress)) {
continue;
}
@@ -227,7 +228,7 @@ public class CertUtils {
}
}
if (dnsNames != null) {
- for (final String dnsName : dnsNames) {
+ for (final String dnsName : new HashSet<>(dnsNames)) {
if (Strings.isNullOrEmpty(dnsName)) {
continue;
}
--
To stop receiving notification emails like this one, please contact
rohit@apache.org.