CLOUDSTACK-6499:
Made changes so that uploading custom certificate works for ssvm.
    1. Reboot ssvm only when private key is passed meaning the server cert is 
passed. This is because while uploading the server cert is the last to be 
uploaded. And we want to propagate the entire chain once uploading is done.
    2. Change the SecStorageSetupCommand sent to ssvm so that it also carries 
the root cert apart from having the chain and the server cert and key.
    3. Change ssvm agent code to be able to configure root cert to the java key 
store.
    4. Change ssvm configure ssl script to insert the chain certs correctly.
    5. Fix order of chain certificates for apache webserver in SSVM
    6. Remove double encoding and decoding for uploadCustomCertificate API from 
UI and server code respectively, so that API call without UI works fine
    7. Java 1.7 - disable using SNI since copyTemplate doesnt work for SSL.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/2f96d430
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/2f96d430
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/2f96d430

Branch: refs/heads/4.4
Commit: 2f96d430c80121a4e1f5714915c30609f38fb11a
Parents: 35767d1
Author: Nitin Mehta <nitin.me...@citrix.com>
Authored: Thu Apr 24 17:20:41 2014 -0700
Committer: Daan Hoogland <d...@onecht.net>
Committed: Fri Apr 25 22:03:46 2014 +0200

----------------------------------------------------------------------
 .../security/keystore/KeystoreDao.java          |  2 ++
 .../security/keystore/KeystoreDaoImpl.java      | 19 +++++++++++
 .../security/keystore/KeystoreManager.java      | 11 +++++--
 .../security/keystore/KeystoreManagerImpl.java  | 19 +++++++----
 .../com/cloud/server/ManagementServerImpl.java  | 26 ++++++---------
 .../resource/NfsSecondaryStorageResource.java   | 33 ++++++++++++++++++--
 systemvm/scripts/_run.sh                        |  2 +-
 systemvm/scripts/config_ssl.sh                  | 15 +++++++--
 ui/scripts/ui-custom/physicalResources.js       |  4 +--
 9 files changed, 98 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f96d430/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDao.java
----------------------------------------------------------------------
diff --git 
a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDao.java
 
b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDao.java
index e60e4b0..67eea92 100644
--- 
a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDao.java
+++ 
b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDao.java
@@ -28,4 +28,6 @@ public interface KeystoreDao extends GenericDao<KeystoreVO, 
Long> {
     void save(String alias, String certificate, Integer index, String 
domainSuffix);
 
     List<KeystoreVO> findCertChain();
+
+    List<KeystoreVO> findCertChain(String domainSuffix);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f96d430/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDaoImpl.java
----------------------------------------------------------------------
diff --git 
a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDaoImpl.java
 
b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDaoImpl.java
index cd24611..b856582 100644
--- 
a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDaoImpl.java
+++ 
b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDaoImpl.java
@@ -38,6 +38,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
 public class KeystoreDaoImpl extends GenericDaoBase<KeystoreVO, Long> 
implements KeystoreDao {
     protected final SearchBuilder<KeystoreVO> FindByNameSearch;
     protected final SearchBuilder<KeystoreVO> CertChainSearch;
+    protected final SearchBuilder<KeystoreVO> CertChainSearchForDomainSuffix;
 
     public KeystoreDaoImpl() {
         FindByNameSearch = createSearchBuilder();
@@ -47,6 +48,11 @@ public class KeystoreDaoImpl extends 
GenericDaoBase<KeystoreVO, Long> implements
         CertChainSearch = createSearchBuilder();
         CertChainSearch.and("key", CertChainSearch.entity().getKey(), Op.NULL);
         CertChainSearch.done();
+
+        CertChainSearchForDomainSuffix = createSearchBuilder();
+        CertChainSearchForDomainSuffix.and("key", 
CertChainSearchForDomainSuffix.entity().getKey(), Op.NULL);
+        CertChainSearchForDomainSuffix.and("domainSuffix", 
CertChainSearchForDomainSuffix.entity().getDomainSuffix(), Op.EQ);
+        CertChainSearchForDomainSuffix.done();
     }
 
     @Override
@@ -65,6 +71,19 @@ public class KeystoreDaoImpl extends 
GenericDaoBase<KeystoreVO, Long> implements
     }
 
     @Override
+    public List<KeystoreVO> findCertChain(String domainSuffix) {
+        SearchCriteria<KeystoreVO> sc =  
CertChainSearchForDomainSuffix.create();
+        sc.setParameters("domainSuffix", domainSuffix);
+        List<KeystoreVO> ks = listBy(sc);
+        Collections.sort(ks, new Comparator() { public int compare(Object o1, 
Object o2) {
+            Integer seq1 = ((KeystoreVO)o1).getIndex();
+            Integer seq2 = ((KeystoreVO)o2).getIndex();
+            return seq1.compareTo(seq2);
+        }});
+        return ks;
+    }
+
+    @Override
     public KeystoreVO findByName(String name) {
         assert (name != null);
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f96d430/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManager.java
----------------------------------------------------------------------
diff --git 
a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManager.java
 
b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManager.java
index 3b99947..c44347c 100644
--- 
a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManager.java
+++ 
b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManager.java
@@ -28,15 +28,18 @@ public interface KeystoreManager extends Manager {
         private String privCert;
         @LogLevel(Log4jLevel.Off)
         private String certChain;
+        @LogLevel(Log4jLevel.Off)
+        private String rootCACert;
 
         public Certificates() {
 
         }
 
-        public Certificates(String prvKey, String privCert, String certChain) {
-            privKey = prvKey;
+        public Certificates(String prvKey, String privCert, String certChain, 
String rootCACert) {
+            this.privKey = prvKey;
             this.privCert = privCert;
             this.certChain = certChain;
+            this.rootCACert = rootCACert;
         }
 
         public String getPrivKey() {
@@ -50,6 +53,10 @@ public interface KeystoreManager extends Manager {
         public String getCertChain() {
             return certChain;
         }
+
+        public String getRootCACert() {
+            return rootCACert;
+        }
     }
 
     boolean validateCertificate(String certificate, String key, String 
domainSuffix);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f96d430/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManagerImpl.java
 
b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManagerImpl.java
index 3060834..374c080 100644
--- 
a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManagerImpl.java
+++ 
b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManagerImpl.java
@@ -23,6 +23,7 @@ import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateException;
 import java.security.spec.InvalidKeySpecException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -30,6 +31,7 @@ import java.util.regex.Pattern;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
@@ -129,17 +131,22 @@ public class KeystoreManagerImpl extends ManagerBase 
implements KeystoreManager
         }
         String prvKey = ksVo.getKey();
         String prvCert = ksVo.getCertificate();
+        String domainSuffix = ksVo.getDomainSuffix();
         String certChain = null;
-        List<KeystoreVO> certchains = _ksDao.findCertChain();
+        String rootCert = null;
+        List<KeystoreVO> certchains = _ksDao.findCertChain(domainSuffix);
         if (certchains.size() > 0) {
-            StringBuilder chains = new StringBuilder();
+            ArrayList<String> chains = new ArrayList<String>();
             for (KeystoreVO cert : certchains) {
-                chains.append(cert.getCertificate());
-                chains.append("\n");
+                if (chains.size() == 0) {// For the first time it will be 
length 0
+                    rootCert = cert.getCertificate();
+                }
+                chains.add(cert.getCertificate());
             }
-            certChain = chains.toString();
+            Collections.reverse(chains);
+            certChain = StringUtils.join(chains, "\n");
         }
-        Certificates certs = new Certificates(prvKey, prvCert, certChain);
+        Certificates certs = new Certificates(prvKey, prvCert, certChain, 
rootCert);
         return certs;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f96d430/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java 
b/server/src/com/cloud/server/ManagementServerImpl.java
index b6fc280..6b37f45 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -16,9 +16,7 @@
 // under the License.
 package com.cloud.server;
 
-import java.io.UnsupportedEncodingException;
 import java.lang.reflect.Field;
-import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -3450,16 +3448,6 @@ public class ManagementServerImpl extends ManagerBase 
implements ManagementServe
 
         String certificate = cmd.getCertificate();
         String key = cmd.getPrivateKey();
-        try {
-            if (certificate != null) {
-                certificate = URLDecoder.decode(certificate, "UTF-8");
-            }
-            if (key != null) {
-                key = URLDecoder.decode(key, "UTF-8");
-            }
-        } catch (UnsupportedEncodingException e) {
-        } finally {
-        }
 
         if (cmd.getPrivateKey() != null && 
!_ksMgr.validateCertificate(certificate, key, cmd.getDomainSuffix())) {
             throw new InvalidParameterValueException("Failed to pass 
certificate validation check");
@@ -3467,16 +3455,20 @@ public class ManagementServerImpl extends ManagerBase 
implements ManagementServe
 
         if (cmd.getPrivateKey() != null) {
             _ksMgr.saveCertificate(ConsoleProxyManager.CERTIFICATE_NAME, 
certificate, key, cmd.getDomainSuffix());
+
+            // Reboot ssvm here since private key is present - meaning server 
cert being passed
+            List<SecondaryStorageVmVO> alreadyRunning = 
_secStorageVmDao.getSecStorageVmListInStates(null, State.Running, 
State.Migrating, State.Starting);
+            for (SecondaryStorageVmVO ssVmVm : alreadyRunning) {
+                _secStorageVmMgr.rebootSecStorageVm(ssVmVm.getId());
+            }
         } else {
             _ksMgr.saveCertificate(cmd.getAlias(), certificate, 
cmd.getCertIndex(), cmd.getDomainSuffix());
         }
 
         
_consoleProxyMgr.setManagementState(ConsoleProxyManagementState.ResetSuspending);
-        List<SecondaryStorageVmVO> alreadyRunning = 
_secStorageVmDao.getSecStorageVmListInStates(null, State.Running, 
State.Migrating, State.Starting);
-        for (SecondaryStorageVmVO ssVmVm : alreadyRunning) {
-            _secStorageVmMgr.rebootSecStorageVm(ssVmVm.getId());
-        }
-        return "Certificate has been updated, we will stop all running console 
proxy VMs and secondary storage VMs to propagate the new certificate, please 
give a few minutes for console access service to be up again";
+        return "Certificate has been successfully updated, if its the server 
certificate we would reboot all " +
+                "running console proxy VMs and secondary storage VMs to 
propagate the new certificate, " +
+                "please give a few minutes for console access and storage 
services service to be up and working again";
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f96d430/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
----------------------------------------------------------------------
diff --git 
a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
 
b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
index f35b3f5..6927f02 100755
--- 
a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
+++ 
b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
@@ -1188,6 +1188,8 @@ public class NfsSecondaryStorageResource extends 
ServerResourceBase implements S
         } else {
             String prvKey = certs.getPrivKey();
             String pubCert = certs.getPrivCert();
+            String certChain = certs.getCertChain();
+            String rootCACert = certs.getRootCACert();
 
             try {
                 File prvKeyFile = File.createTempFile("prvkey", null);
@@ -1203,10 +1205,34 @@ public class NfsSecondaryStorageResource extends 
ServerResourceBase implements S
                 out.write(pubCert);
                 out.close();
 
-                configureSSL(prvkeyPath, pubCertFilePath, null);
+                String certChainFilePath = null, rootCACertFilePath = null;
+                File certChainFile = null, rootCACertFile = null;
+                if(certChain != null){
+                    certChainFile = File.createTempFile("certchain", null);
+                    certChainFilePath = certChainFile.getAbsolutePath();
+                    out = new BufferedWriter(new FileWriter(certChainFile));
+                    out.write(certChain);
+                    out.close();
+                }
+
+                if(rootCACert != null){
+                    rootCACertFile = File.createTempFile("rootcert", null);
+                    rootCACertFilePath = rootCACertFile.getAbsolutePath();
+                    out = new BufferedWriter(new FileWriter(rootCACertFile));
+                    out.write(rootCACert);
+                    out.close();
+                }
+
+                configureSSL(prvkeyPath, pubCertFilePath, certChainFilePath, 
rootCACertFilePath);
 
                 prvKeyFile.delete();
                 pubCertFile.delete();
+                if(certChainFile != null){
+                    certChainFile.delete();
+                }
+                if(rootCACertFile != null){
+                    rootCACertFile.delete();
+                }
 
             } catch (IOException e) {
                 s_logger.debug("Failed to config ssl: " + e.toString());
@@ -2064,7 +2090,7 @@ public class NfsSecondaryStorageResource extends 
ServerResourceBase implements S
         }
     }
 
-    private void configureSSL(String prvkeyPath, String prvCertPath, String 
certChainPath) {
+    private void configureSSL(String prvkeyPath, String prvCertPath, String 
certChainPath, String rootCACert) {
         if (!_inSystemVM) {
             return;
         }
@@ -2076,6 +2102,9 @@ public class NfsSecondaryStorageResource extends 
ServerResourceBase implements S
         if (certChainPath != null) {
             command.add("-t", certChainPath);
         }
+        if (rootCACert != null) {
+            command.add("-u", rootCACert);
+        }
         String result = command.execute();
         if (result != null) {
             s_logger.warn("Unable to configure httpd to use ssl");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f96d430/systemvm/scripts/_run.sh
----------------------------------------------------------------------
diff --git a/systemvm/scripts/_run.sh b/systemvm/scripts/_run.sh
index 1a37c7d..3792261 100755
--- a/systemvm/scripts/_run.sh
+++ b/systemvm/scripts/_run.sh
@@ -68,4 +68,4 @@ if [ "$(uname -m | grep '64')" == "" ]; then
   fi
 fi
 
-java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore 
-Dlog.home=$LOGHOME -mx${maxmem}m -cp $CP com.cloud.agent.AgentShell $keyvalues 
$@
+java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore 
-Djsse.enableSNIExtension=false -Dlog.home=$LOGHOME -mx${maxmem}m -cp $CP 
com.cloud.agent.AgentShell $keyvalues $@

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f96d430/systemvm/scripts/config_ssl.sh
----------------------------------------------------------------------
diff --git a/systemvm/scripts/config_ssl.sh b/systemvm/scripts/config_ssl.sh
index e474787..6971055 100755
--- a/systemvm/scripts/config_ssl.sh
+++ b/systemvm/scripts/config_ssl.sh
@@ -24,6 +24,7 @@ help() {
    printf " -k path of private key\n"
    printf " -p path of certificate of public key\n"
    printf " -t path of certificate chain\n"
+   printf " -u path of root ca certificate \n"
 }
 
 
@@ -53,6 +54,10 @@ config_apache2_conf() {
   sed -i -e "s/NameVirtualHost .*:80/NameVirtualHost $ip:80/g" 
/etc/apache2/ports.conf
   sed -i  's/ssl-cert-snakeoil.key/cert_apache.key/' 
/etc/apache2/sites-available/default-ssl
   sed -i  's/ssl-cert-snakeoil.pem/cert_apache.crt/' 
/etc/apache2/sites-available/default-ssl
+  if [ -f /etc/ssl/certs/cert_apache_chain.crt ]
+  then
+    sed -i -e "s/#SSLCertificateChainFile.*/SSLCertificateChainFile 
\/etc\/ssl\/certs\/cert_apache_chain.crt/" 
/etc/apache2/sites-available/default-ssl
+  fi
 }
 
 copy_certs() {
@@ -88,12 +93,13 @@ cccflag=
 customPrivKey=$(dirname $0)/certs/realhostip.key
 customPrivCert=$(dirname $0)/certs/realhostip.crt
 customCertChain=
+customCACert=
 publicIp=
 hostName=
 keyStore=$(dirname $0)/certs/realhostip.keystore
 aliasName="CPVMCertificate"
 storepass="vmops.com"
-while getopts 'i:h:k:p:t:c' OPTION
+while getopts 'i:h:k:p:t:u:c' OPTION
 do
   case $OPTION in
      c) cflag=1
@@ -107,6 +113,9 @@ do
      t) cccflag=1
         customCertChain="$OPTARG"
         ;;
+     u) ccacflag=1
+        customCACert="$OPTARG"
+        ;;
      i) publicIp="$OPTARG"
         ;;
      h) hostName="$OPTARG"
@@ -165,10 +174,10 @@ then
   exit 2
 fi
 
-if [ -f "$customPrivCert" ]
+if [ -f "$customCACert" ]
 then
   keytool -delete -alias $aliasName -keystore $keyStore -storepass $storepass 
-noprompt
-  keytool -import -alias $aliasName -keystore $keyStore -storepass $storepass 
-noprompt -file $customPrivCert
+  keytool -import -alias $aliasName -keystore $keyStore -storepass $storepass 
-noprompt -file $customCACert
 fi
 
 if [ -d /etc/apache2 ]

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f96d430/ui/scripts/ui-custom/physicalResources.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/physicalResources.js 
b/ui/scripts/ui-custom/physicalResources.js
index fcc2f6a..06fcca7 100644
--- a/ui/scripts/ui-custom/physicalResources.js
+++ b/ui/scripts/ui-custom/physicalResources.js
@@ -117,8 +117,8 @@
                             type: "POST",
                             url: createURL('uploadCustomCertificate'),
                             data: {
-                                certificate: 
encodeURIComponent(args.data.certificate),
-                                privatekey: 
encodeURIComponent(args.data.privatekey),
+                                certificate: args.data.certificate,
+                                privatekey: args.data.privatekey,
                                 domainsuffix: args.data.domainsuffix
                             },
                             dataType: 'json',

Reply via email to