diff --git a/api/src/com/cloud/agent/api/SecStorageSetupCommand.java b/api/src/com/cloud/agent/api/SecStorageSetupCommand.java
index 73a9d4e350b..aac0f4366aa 100644
--- a/api/src/com/cloud/agent/api/SecStorageSetupCommand.java
+++ b/api/src/com/cloud/agent/api/SecStorageSetupCommand.java
@@ -17,16 +17,51 @@
*/
package com.cloud.agent.api;
+import com.cloud.agent.api.LogLevel.Log4jLevel;
+
public class SecStorageSetupCommand extends Command {
private String secUrl;
+ private Certificates certs;
+
+ public static class Certificates {
+ @LogLevel(Log4jLevel.Off)
+ private String privKey;
+ @LogLevel(Log4jLevel.Off)
+ private String privCert;
+ @LogLevel(Log4jLevel.Off)
+ private String certChain;
+
+ public Certificates() {
+
+ }
+
+ public Certificates(String prvKey, String privCert, String certChain) {
+ this.privKey = prvKey;
+ this.privCert = privCert;
+ this.certChain = certChain;
+ }
+
+ public String getPrivKey() {
+ return this.privKey;
+ }
+
+ public String getPrivCert() {
+ return this.privCert;
+ }
+
+ public String getCertChain() {
+ return this.certChain;
+ }
+ }
public SecStorageSetupCommand() {
super();
}
-
- public SecStorageSetupCommand(String secUrl) {
+
+ public SecStorageSetupCommand(String secUrl, Certificates certs) {
super();
this.secUrl = secUrl;
+ this.certs = certs;
}
@Override
@@ -37,8 +72,13 @@ public class SecStorageSetupCommand extends Command {
public String getSecUrl() {
return secUrl;
}
+
+ public Certificates getCerts() {
+ return this.certs;
+ }
public void setSecUrl(String secUrl) {
this.secUrl = secUrl;
+
}
}
diff --git a/api/src/com/cloud/api/commands/UploadCustomCertificateCmd.java b/api/src/com/cloud/api/commands/UploadCustomCertificateCmd.java
index 5511a54d1b4..e94e31ea734 100644
--- a/api/src/com/cloud/api/commands/UploadCustomCertificateCmd.java
+++ b/api/src/com/cloud/api/commands/UploadCustomCertificateCmd.java
@@ -37,8 +37,14 @@ public class UploadCustomCertificateCmd extends BaseAsyncCmd {
@Parameter(name=ApiConstants.CERTIFICATE,type=CommandType.STRING,required=true,description="the custom cert to be uploaded")
private String certificate;
+
+ @Parameter(name=ApiConstants.ID,type=CommandType.INTEGER,required=false,description="the custom cert id in the chain")
+ private Integer index;
+
+ @Parameter(name=ApiConstants.NAME,type=CommandType.STRING,required=false,description="the alias of the certificate")
+ private String alias;
- @Parameter(name=ApiConstants.PRIVATE_KEY,type=CommandType.STRING,required=true,description="the private key for the certificate")
+ @Parameter(name=ApiConstants.PRIVATE_KEY,type=CommandType.STRING,required=false,description="the private key for the certificate")
private String privateKey;
@Parameter(name=ApiConstants.DOMAIN_SUFFIX,type=CommandType.STRING,required=true,description="DNS domain suffix that the certificate is granted for")
@@ -55,6 +61,14 @@ public class UploadCustomCertificateCmd extends BaseAsyncCmd {
public String getDomainSuffix() {
return domainSuffix;
}
+
+ public Integer getCertIndex() {
+ return index;
+ }
+
+ public String getAlias() {
+ return alias;
+ }
@Override
public String getEventType() {
diff --git a/console-proxy/scripts/config_ssl.sh b/console-proxy/scripts/config_ssl.sh
index 754631b6139..70021ef4f44 100755
--- a/console-proxy/scripts/config_ssl.sh
+++ b/console-proxy/scripts/config_ssl.sh
@@ -19,7 +19,12 @@
# along with this program. If not, see .
#
-
+help() {
+ printf " -c use customized key/cert\n"
+ printf " -k path of private key\n"
+ printf " -p path of certificate of public key\n"
+ printf " -t path of certificate chain\n"
+}
config_httpd_conf() {
@@ -46,33 +51,102 @@ config_apache2_conf() {
sed -i -e "s/Listen .*:80/Listen $ip:80/g" /etc/apache2/ports.conf
sed -i -e "s/Listen .*:443/Listen $ip:443/g" /etc/apache2/ports.conf
sed -i -e "s/NameVirtualHost .*:80/NameVirtualHost $ip:80/g" /etc/apache2/ports.conf
- sed -i 's/ssl-cert-snakeoil.key/realhostip.key/' /etc/apache2/sites-available/default-ssl
- sed -i 's/ssl-cert-snakeoil.pem/realhostip.crt/' /etc/apache2/sites-available/default-ssl
+ 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
}
copy_certs() {
local certdir=$(dirname $0)/certs
local mydir=$(dirname $0)
- if [ -d $certdir ] && [ -f $certdir/realhostip.key ] && [ -f $certdir/realhostip.crt ] ; then
- mkdir -p /etc/httpd/ssl/keys && mkdir -p /etc/httpd/ssl/certs && cp $certdir/realhostip.key /etc/httpd/ssl/keys && cp $certdir/realhostip.crt /etc/httpd/ssl/certs
+ if [ -d $certdir ] && [ -f $customPrivKey ] && [ -f $customPrivCert ] ; then
+ mkdir -p /etc/httpd/ssl/keys && mkdir -p /etc/httpd/ssl/certs && cp $customprivKey /etc/httpd/ssl/keys && cp $customPrivCert /etc/httpd/ssl/certs
return $?
fi
+ if [ ! -z customCertChain ] && [ -f $customCertChain ] ; then
+ cp $customCertChain /etc/httpd/ssl/certs
+ fi
return 1
}
copy_certs_apache2() {
local certdir=$(dirname $0)/certs
local mydir=$(dirname $0)
- if [ -d $certdir ] && [ -f $certdir/realhostip.key ] && [ -f $certdir/realhostip.crt ] ; then
- cp $certdir/realhostip.key /etc/ssl/private/ && cp $certdir/realhostip.crt /etc/ssl/certs/
- return $?
+ if [ -f $customPrivKey ] && [ -f $customPrivCert ] ; then
+ cp $customPrivKey /etc/ssl/private/cert_apache.key && cp $customPrivCert /etc/ssl/certs/cert_apache.crt
fi
- return 1
+ if [ ! -z "$customCertChain" ] && [ -f "$customCertChain" ] ; then
+ cp $customCertChain /etc/ssl/certs/cert_apache_chain.crt
+ fi
+ return 0
}
-if [ $# -ne 2 ] ; then
- echo $"Usage: `basename $0` ipaddr servername "
- exit 0
+
+cflag=
+cpkflag=
+cpcflag=
+cccflag=
+customPrivKey=$(dirname $0)/certs/realhostip.key
+customPrivCert=$(dirname $0)/certs/realhostip.crt
+customCertChain=
+publicIp=
+hostName=
+while getopts 'i:h:k:p:t:c' OPTION
+do
+ case $OPTION in
+ c) cflag=1
+ ;;
+ k) cpkflag=1
+ customPrivKey="$OPTARG"
+ ;;
+ p) cpcflag=1
+ customPrivCert="$OPTARG"
+ ;;
+ t) cccflag=1
+ customCertChain="$OPTARG"
+ ;;
+ i) publicIp="$OPTARG"
+ ;;
+ h) hostName="$OPTARG"
+ ;;
+ ?) help
+ ;;
+ esac
+done
+
+
+if [ -z "$publicIp" ] || [ -z "$hostName" ]
+then
+ help
+ exit 1
+fi
+
+if [ "$cflag" == "1" ]
+then
+ if [ "$cpkflag$cpcflag" != "11" ]
+ then
+ help
+ exit 1
+ fi
+ if [ ! -f "$customPrivKey" ]
+ then
+ printf "priviate key file is not exist\n"
+ exit 2
+ fi
+
+ if [ ! -f "$customPrivCert" ]
+ then
+ printf "public certificate is not exist\n"
+ exit 3
+ fi
+
+ if [ "$cccflag" == "1" ]
+ then
+ if [ ! -f "$customCertChain" ]
+ then
+ printf "certificate chain is not exist\n"
+ exit 4
+ fi
+ fi
fi
if [ -d /etc/apache2 ]
@@ -90,7 +164,11 @@ fi
if [ -d /etc/apache2 ]
then
- config_apache2_conf $1 $2
+ config_apache2_conf $publicIp $hostName
+ /etc/init.d/apache2 stop
+ /etc/init.d/apache2 start
else
- config_httpd_conf $1 $2
+ config_httpd_conf $publicIp $hostName
fi
+
+
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java
index e5aa7af1d91..42e5787c895 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java
@@ -50,7 +50,7 @@ public class ConsoleProxySecureServerFactoryImpl implements ConsoleProxyServerFa
public void init(byte[] ksBits, String ksPassword) {
s_logger.info("Start initializing SSL");
- // if(ksBits == null) {
+ if(ksBits == null) {
try {
s_logger.info("Initializing SSL from built-in default certificate");
@@ -76,7 +76,7 @@ public class ConsoleProxySecureServerFactoryImpl implements ConsoleProxyServerFa
} catch (Exception ioe) {
s_logger.error(ioe.toString(), ioe);
}
-/*
+
} else {
char[] passphrase = ksPassword != null ? ksPassword.toCharArray() : null;
try {
@@ -100,7 +100,7 @@ public class ConsoleProxySecureServerFactoryImpl implements ConsoleProxyServerFa
s_logger.error("Unable to init factory due to exception ", e);
}
}
-*/
+
}
public HttpServer createHttpServerInstance(int port) throws IOException {
diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
index 57068b18ecd..46a31055296 100755
--- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
+++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
@@ -17,8 +17,10 @@
*/
package com.cloud.storage.resource;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
@@ -52,6 +54,7 @@ import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand;
import com.cloud.agent.api.SecStorageSetupAnswer;
import com.cloud.agent.api.SecStorageSetupCommand;
+import com.cloud.agent.api.SecStorageSetupCommand.Certificates;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig;
import com.cloud.agent.api.SecStorageVMSetupCommand;
@@ -208,6 +211,38 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return new Answer(cmd, true, checksum);
}
+ private void configCerts(Certificates certs) {
+ if (certs == null) {
+ configureSSL();
+ } else {
+ String prvKey = certs.getPrivKey();
+ String pubCert = certs.getPrivCert();
+ String certChain = certs.getCertChain();
+
+ try {
+ File prvKeyFile = File.createTempFile("prvkey", null);
+ String prvkeyPath = prvKeyFile.getAbsolutePath();
+ BufferedWriter out = new BufferedWriter(new FileWriter(prvKeyFile));
+ out.write(prvKey);
+ out.close();
+
+ File pubCertFile = File.createTempFile("pubcert", null);
+ String pubCertFilePath = pubCertFile.getAbsolutePath();
+
+ out = new BufferedWriter(new FileWriter(pubCertFile));
+ out.write(pubCert);
+ out.close();
+
+ configureSSL(prvkeyPath, pubCertFilePath, null);
+
+ prvKeyFile.delete();
+ pubCertFile.delete();
+
+ } catch (IOException e) {
+ s_logger.debug("Failed to config ssl: " + e.toString());
+ }
+ }
+ }
private Answer execute(SecStorageSetupCommand cmd) {
if (!_inSystemVM){
@@ -226,6 +261,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
String dir = UUID.nameUUIDFromBytes(nfsPath.getBytes()).toString();
String root = _parent + "/" + dir;
mount(root, nfsPath);
+
+ configCerts(cmd.getCerts());
+
return new SecStorageSetupAnswer(dir);
} catch (Exception e) {
String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString();
@@ -556,13 +594,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
}
}
- String useSsl = (String)params.get("sslcopy");
- if (useSsl != null) {
- _sslCopy = Boolean.parseBoolean(useSsl);
- if (_sslCopy) {
- configureSSL();
- }
- }
+
startAdditionalServices();
_params.put("install.numthreads", "50");
_params.put("secondary.storage.vm", "true");
@@ -639,8 +671,23 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
private void configureSSL() {
Script command = new Script(_configSslScr);
- command.add(_publicIp);
- command.add(_hostname);
+ command.add("-i", _publicIp);
+ command.add("-h", _hostname);
+ String result = command.execute();
+ if (result != null) {
+ s_logger.warn("Unable to configure httpd to use ssl");
+ }
+ }
+
+ private void configureSSL(String prvkeyPath, String prvCertPath, String certChainPath) {
+ Script command = new Script(_configSslScr);
+ command.add("-i", _publicIp);
+ command.add("-h", _hostname);
+ command.add("-k", prvkeyPath);
+ command.add("-p", prvCertPath);
+ if (certChainPath != null) {
+ command.add("-t", certChainPath);
+ }
String result = command.execute();
if (result != null) {
s_logger.warn("Unable to configure httpd to use ssl");
diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
index 8fa485be9a5..218016129ab 100644
--- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
+++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
@@ -259,66 +259,142 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
+ "fJ6GBCs1XgZLuhkKS8fPf+YmG2ZjHzYDjYoSx7paDXgEm+kbYIZdCK51lA0BUAjP\n" + "9ZMGhsu/PpAbh5U/DtcIqxY0xeqD4TeGsBzXg6uLhv+jKHDtXg5fYPe+z0n5DCEL\n"
+ "k0fLF4+i/pt9hVCz0QrZ28RUhXf825+EOL0Gw+Uzt+7RV2cCaJrlu4cDrDom2FRy\n" + "E8I=\n" + "-----END CERTIFICATE-----\n";
*/
- private final String keyContent =
- "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCGu5REMZSFQ6wD\n" +
- "Fr7NPp9iibCYHZ6d1IV7s6Yvs6yvXmYw46c9JaJ8FN0NoHVzzDD2dELfpBxXRN7e\n" +
- "q1rcP3ISDdDkhjngJoXEd2xaqgp0UxOS+AaamGG6sOleACn0XBF+XXaaD5vnFw7Y\n" +
- "nDUyJioWR5KdTzVajLVkdEP3uPmJbRdveEu8HMZpwhZyY4uAcH5nHxMJEj/mkZtF\n" +
- "ZJDi26ZjeonVOwnGm0NTbGCrfCneQEZC/SENua3BklHXc07zl3TrWu8xhrVWGRbc\n" +
- "knw0VmGaPmehtuzL9WsieWGG4KH9G1LC2w2mbib64nSluBEcHRCKOT2aMzo2FonK\n" +
- "AZkkIE53AgMBAAECggEAXLH3awd1eE47rRBcC1d3TtMOVUmjlFDf2WCbCJykRS88\n" +
- "PYySxgX7iUTNZQ+tXxLv6M/KJpWBDiWK9EWOSJO6BmPNATy72tSGGcpUGPh+ItP5\n" +
- "Vpcf7ALE0i3fENYqBz3Ep1zkOVBd4ZrCkxK9opgRQqzRWTtiqL7AGbHIBUoVHI+b\n" +
- "Dk0bfl0936JpEMiFcI88KqckdFbY/cw+Uq7pRHPfUM5pB1AeMGqFVlqZbiDgMJm4\n" +
- "GJRqXU8Qrue9UB6YypS9q7x9Q7sB/W3ghTLefYLrWVyeX417xcdKpaI7jo/KqT9F\n" +
- "3m5uIphLe64HPLX50iWj9mIQ1vclsae3nIk/TObMcQKBgQC7FSgZdLdhxfPAC450\n" +
- "EVM4Wmhiq0LmI63IbdIO+exsOQmOsCaGDNgWD8/YFSO+71dXRCB2WFUWg5G0Fl6w\n" +
- "LKkQiSaNenJzT2NhL61+O4G2PPM3Sq1rlY0eB+8yq8tHxS1vO+zOcSdsUO+ES3FV\n" +
- "E36cQMXixVnfvAdp+wUbkNZxyQKBgQC4XY9ZpSWnhIma/4HLF34tAZKCoVJAvHYk\n" +
- "UpVIu9pixjQsmsEliTERvsWIfJQTpdsgkjkFHB3LzOsF2Wd2pXhBcMokLe8H9VNY\n" +
- "MTi0i9zeZMV4V9UzRhgs9n41MAN3bgg0Pgt6W5qNvguEl5aQp9inwqyVmFS4NGit\n" +
- "LNa8Kj7ePwKBgQCJ6LupoD96pMjdfediKk9VkFe4vJTRP+XghQw/G/8rfBROig2r\n" +
- "7ZXxFXDa0iKKoraYztC7TLxUn2JuBbuBVTq/xMqVqnjqBdC1mMbk8grZgy6rSLJ0\n" +
- "R0dCpwiuKrPsUS7/+4XCXOl50GPv+wktdPR1TM5TL7Xj1yEEABYwzuE1+QKBgHxy\n" +
- "uybZ8VbogjJcMnKywvsCSrFez7TfAih2jkpwc3OlMubA94us1bCSw6fj39h7ZjTQ\n" +
- "PykR15MQGbzzCYHvJAOYbPqK/wSyNrYbU5mbp1V/VERtlX5s3DjNkle4tz5Qybzp\n" +
- "/Ll1SBhRpli0MnAmvHpRUEoSb22AAwCSeci+A33lAoGBAJNAVW8kE9ocXw3I4aac\n" +
- "GI19ihoXr+8tRJilMCRQp4iFdi7acnek3/u0MaZ0ct8cVh9oMO+zVmTrpxJNTL6H\n" +
- "He0z1VA4w/j4J5Z2P0KNLnKvRpayGWcf86YgSEmgU/ScwWzGL+cNgEKih74lSL4Z\n" +
- "OK2Ayxxw3vbRyxQg6r1JUIKS\n";
+ public static final String keyContent =
+ "-----BEGIN PRIVATE KEY-----\n" +
+ "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCDT9AtEfs+s/I8QXp6rrCw0iNJ\n" +
+ "0+GgsybNHheU+JpL39LMTZykCrZhZnyDvwdxCoOfE38Sa32baHKNds+y2SHnMNsOkw8OcNucHEBX\n" +
+ "1FIpOBGph9D6xC+umx9od6xMWETUv7j6h2u+WC3OhBM8fHCBqIiAol31/IkcqDxxsHlQ8S/oCfTl\n" +
+ "XJUY6Yn628OA1XijKdRnadV0hZ829cv/PZKljjwQUTyrd0KHQeksBH+YAYSo2JUl8ekNLsOi8/cP\n" +
+ "tfojnltzRI1GXi0ZONs8VnDzJ0a2gqZY+uxlz+CGbLnGnlN4j9cBpE+MfUE+35Dq121sTpsSgF85\n" +
+ "Mz+pVhn2S633AgMBAAECggEAH/Szd9RxbVADenCA6wxKSa3KErRyq1YN8ksJeCKMAj0FIt0caruE\n" +
+ "qO11DebWW8cwQu1Otl/cYI6pmg24/BBldMrp9IELX/tNJo+lhPpRyGAxxC0eSXinFfoASb8d+jJd\n" +
+ "Bd1mmemM6fSxqRlxSP4LrzIhjhR1g2CiyYuTsiM9UtoVKGyHwe7KfFwirUOJo3Mr18zUVNm7YqY4\n" +
+ "IVhOSq59zkH3ULBlYq4bG50jpxa5mNSCZ7IpafPY/kE/CbR+FWNt30+rk69T+qb5abg6+XGm+OAm\n" +
+ "bnQ18yZEqX6nJLk7Ch0cfA5orGgrTMOrM71wK7tBBDQ308kOxDGebx6j0qD36QKBgQDTRDr8kuhA\n" +
+ "9sUyKr9vk2DQCMpNvEeiwI3JRMqmmxpNAtg01aJ3Ya57vX5Fc+zcuV87kP6FM1xgpHQvnw5LWo2J\n" +
+ "s7ANwQcP8ricEW5zkZhSjI4ssMeAubmsHOloGxmLFYZqwx0JI7CWViGTLMcUlqKblmHcjeQDeDfP\n" +
+ "P1TaCItFmwKBgQCfHZwVvIcaDs5vxVpZ4ftvflIrW8qq0uOVK6QIf9A/YTGhCXl2qxxTg2A6+0rg\n" +
+ "ZqI7zKzUDxIbVv0KlgCbpHDC9d5+sdtDB3wW2pimuJ3p1z4/RHb4n/lDwXCACZl1S5l24yXX2pFZ\n" +
+ "wdPCXmy5PYkHMssFLNhI24pprUIQs66M1QKBgQDQwjAjWisD3pRXESSfZRsaFkWJcM28hdbVFhPF\n" +
+ "c6gWhwQLmTp0CuL2RPXcPUPFi6sN2iWWi3zxxi9Eyz+9uBn6AsOpo56N5MME/LiOnETO9TKb+Ib6\n" +
+ "rQtKhjshcv3XkIqFPo2XdVvOAgglPO7vajX91iiXXuH7h7RmJud6l0y/lwKBgE+bi90gLuPtpoEr\n" +
+ "VzIDKz40ED5bNYHT80NNy0rpT7J2GVN9nwStRYXPBBVeZq7xCpgqpgmO5LtDAWULeZBlbHlOdBwl\n" +
+ "NhNKKl5wzdEUKwW0yBL1WSS5PQgWPwgARYP25/ggW22sj+49WIo1neXsEKPGWObk8e050f1fTt92\n" +
+ "Vo1lAoGAb1gCoyBCzvi7sqFxm4V5oapnJeiQQJFjhoYWqGa26rQ+AvXXNuBcigIeDXNJPctSF0Uc\n" +
+ "p11KbbCgiruBbckvM1vGsk6Sx4leRk+IFHRpJktFUek4o0eUg0shOsyyvyet48Dfg0a8FvcxROs0\n" +
+ "gD+IYds5doiob/hcm1hnNB/3vk4=\n" +
+ "-----END PRIVATE KEY-----\n" ;
- private final String certContent =
- "-----BEGIN CERTIFICATE-----\n" +
- "MIIFZTCCBE2gAwIBAgIHK35JiCqLMjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE\n" +
- "BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY\n" +
- "BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm\n" +
- "aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5\n" +
- "IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky\n" +
- "ODcwHhcNMTIwMjAyMDExMDE5WhcNMTcwMjA3MDUxMTIzWjBZMRkwFwYDVQQKDBAq\n" +
- "LnJlYWxob3N0aXAuY29tMSEwHwYDVQQLDBhEb21haW4gQ29udHJvbCBWYWxpZGF0\n" +
- "ZWQxGTAXBgNVBAMMECoucmVhbGhvc3RpcC5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n" +
- "A4IBDwAwggEKAoIBAQCGu5REMZSFQ6wDFr7NPp9iibCYHZ6d1IV7s6Yvs6yvXmYw\n" +
- "46c9JaJ8FN0NoHVzzDD2dELfpBxXRN7eq1rcP3ISDdDkhjngJoXEd2xaqgp0UxOS\n" +
- "+AaamGG6sOleACn0XBF+XXaaD5vnFw7YnDUyJioWR5KdTzVajLVkdEP3uPmJbRdv\n" +
- "eEu8HMZpwhZyY4uAcH5nHxMJEj/mkZtFZJDi26ZjeonVOwnGm0NTbGCrfCneQEZC\n" +
- "/SENua3BklHXc07zl3TrWu8xhrVWGRbcknw0VmGaPmehtuzL9WsieWGG4KH9G1LC\n" +
- "2w2mbib64nSluBEcHRCKOT2aMzo2FonKAZkkIE53AgMBAAGjggG+MIIBujAPBgNV\n" +
- "HRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV\n" +
- "HQ8BAf8EBAMCBaAwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5\n" +
- "LmNvbS9nZHMxLTYzLmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkwNwYI\n" +
- "KwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3Np\n" +
- "dG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au\n" +
- "Z29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdv\n" +
- "ZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSME\n" +
- "GDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zArBgNVHREEJDAighAqLnJlYWxob3N0\n" +
- "aXAuY29tgg5yZWFsaG9zdGlwLmNvbTAdBgNVHQ4EFgQUwjwYIABbqSlCbCDr9E6F\n" +
- "htB12TAwDQYJKoZIhvcNAQEFBQADggEBALxCXsUGaxTwWIvQEJu6D4lIMrkYyQuy\n" +
- "Z2Cfd1/RLyX87ZkBR4iCO9MTezVFgDQj2rfSQGhnVLxD/1cGoivHKm3hmRX8gWh1\n" +
- "d3vPco55XF8wWtQee822RB55h015kmrcv68yUIllrjDDuGfMc+QdIkxjIzDRWlEF\n" +
- "mq8xEGIfabuflT2C58OU1ZHgQvBvK2iWGNgXSE9h0Bf8xwu/uYHgoWi5dBFm+woo\n" +
- "GVNHaLNZBjwvKGvJN8zcmjjpYuYEfGVezm+kgGTBLpKthx5HV8vTrKnkmt0h/4pf\n" +
- "ZumhNAbOBj753mNCMnNLo/+OAQNPR5QIGhjd4zMgUJT0e9GnQok7V98=\n" +
- "-----END CERTIFICATE-----\n";
+ public static final String certContent =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFZTCCBE2gAwIBAgIHKBCduBUoKDANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE\n" +
+ "BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY\n" +
+ "BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm\n" +
+ "aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5\n" +
+ "IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky\n" +
+ "ODcwHhcNMTIwMjAzMDMzMDQwWhcNMTcwMjA3MDUxMTIzWjBZMRkwFwYDVQQKDBAq\n" +
+ "LnJlYWxob3N0aXAuY29tMSEwHwYDVQQLDBhEb21haW4gQ29udHJvbCBWYWxpZGF0\n" +
+ "ZWQxGTAXBgNVBAMMECoucmVhbGhvc3RpcC5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n" +
+ "A4IBDwAwggEKAoIBAQCDT9AtEfs+s/I8QXp6rrCw0iNJ0+GgsybNHheU+JpL39LM\n" +
+ "TZykCrZhZnyDvwdxCoOfE38Sa32baHKNds+y2SHnMNsOkw8OcNucHEBX1FIpOBGp\n" +
+ "h9D6xC+umx9od6xMWETUv7j6h2u+WC3OhBM8fHCBqIiAol31/IkcqDxxsHlQ8S/o\n" +
+ "CfTlXJUY6Yn628OA1XijKdRnadV0hZ829cv/PZKljjwQUTyrd0KHQeksBH+YAYSo\n" +
+ "2JUl8ekNLsOi8/cPtfojnltzRI1GXi0ZONs8VnDzJ0a2gqZY+uxlz+CGbLnGnlN4\n" +
+ "j9cBpE+MfUE+35Dq121sTpsSgF85Mz+pVhn2S633AgMBAAGjggG+MIIBujAPBgNV\n" +
+ "HRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV\n" +
+ "HQ8BAf8EBAMCBaAwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5\n" +
+ "LmNvbS9nZHMxLTY0LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkwNwYI\n" +
+ "KwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3Np\n" +
+ "dG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au\n" +
+ "Z29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdv\n" +
+ "ZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSME\n" +
+ "GDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zArBgNVHREEJDAighAqLnJlYWxob3N0\n" +
+ "aXAuY29tgg5yZWFsaG9zdGlwLmNvbTAdBgNVHQ4EFgQUZyJz9/QLy5TWIIscTXID\n" +
+ "E8Xk47YwDQYJKoZIhvcNAQEFBQADggEBAKiUV3KK16mP0NpS92fmQkCLqm+qUWyN\n" +
+ "BfBVgf9/M5pcT8EiTZlS5nAtzAE/eRpBeR3ubLlaAogj4rdH7YYVJcDDLLoB2qM3\n" +
+ "qeCHu8LFoblkb93UuFDWqRaVPmMlJRnhsRkL1oa2gM2hwQTkBDkP7w5FG1BELCgl\n" +
+ "gZI2ij2yxjge6pOEwSyZCzzbCcg9pN+dNrYyGEtB4k+BBnPA3N4r14CWbk+uxjrQ\n" +
+ "6j2Ip+b7wOc5IuMEMl8xwTyjuX3lsLbAZyFI9RCyofwA9NqIZ1GeB6Zd196rubQp\n" +
+ "93cmBqGGjZUs3wMrGlm7xdjlX6GQ9UvmvkMub9+lL99A5W50QgCmFeI=\n" +
+ "-----END CERTIFICATE-----\n";
+
+ public static final String rootCa =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx\n" +
+ "ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g\n" +
+ "RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw\n" +
+ "MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH\n" +
+ "QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j\n" +
+ "b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j\n" +
+ "b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj\n" +
+ "YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN\n" +
+ "AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H\n" +
+ "KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm\n" +
+ "VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR\n" +
+ "SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT\n" +
+ "cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ\n" +
+ "6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu\n" +
+ "MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS\n" +
+ "kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB\n" +
+ "BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f\n" +
+ "BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv\n" +
+ "c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH\n" +
+ "AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO\n" +
+ "BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG\n" +
+ "OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU\n" +
+ "A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o\n" +
+ "0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX\n" +
+ "RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH\n" +
+ "qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV\n" +
+ "U+4=\n" +
+ "-----END CERTIFICATE-----\n" +
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh\n" +
+ "bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu\n" +
+ "Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g\n" +
+ "QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe\n" +
+ "BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoX\n" +
+ "DTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBE\n" +
+ "YWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0\n" +
+ "aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC\n" +
+ "ggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv\n" +
+ "2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+q\n" +
+ "N1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiO\n" +
+ "r18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN\n" +
+ "f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEH\n" +
+ "U1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHU\n" +
+ "TBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMb\n" +
+ "VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwg\n" +
+ "SW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlv\n" +
+ "biBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEg\n" +
+ "MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUw\n" +
+ "AwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdv\n" +
+ "ZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMu\n" +
+ "Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUd\n" +
+ "IAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv\n" +
+ "bS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1\n" +
+ "QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4O\n" +
+ "WBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0Vmsf\n" +
+ "SxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==\n" +
+ "-----END CERTIFICATE-----\n" +
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0\n" +
+ "IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz\n" +
+ "BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y\n" +
+ "aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG\n" +
+ "9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy\n" +
+ "NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y\n" +
+ "azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs\n" +
+ "YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw\n" +
+ "Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl\n" +
+ "cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY\n" +
+ "dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9\n" +
+ "WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS\n" +
+ "v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v\n" +
+ "UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu\n" +
+ "IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC\n" +
+ "W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd\n" +
+ "-----END CERTIFICATE-----\n";
@Inject
private KeystoreDao _ksDao;
@@ -1224,6 +1300,12 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
KeystoreVO ksVo = _ksDao.findByName(CERTIFICATE_NAME);
if (ksVo == null) {
_ksDao.save(CERTIFICATE_NAME, certContent, keyContent, "realhostip.com");
+ KeystoreVO caRoot = new KeystoreVO();
+ caRoot.setCertificate(rootCa);
+ caRoot.setDomainSuffix("realhostip.com");
+ caRoot.setName("root");
+ caRoot.setIndex(0);
+ _ksDao.persist(caRoot);
}
lock.unlock();
}
diff --git a/server/src/com/cloud/keystore/KeystoreDao.java b/server/src/com/cloud/keystore/KeystoreDao.java
index d1b2889eb9e..4206730aa6e 100644
--- a/server/src/com/cloud/keystore/KeystoreDao.java
+++ b/server/src/com/cloud/keystore/KeystoreDao.java
@@ -18,9 +18,14 @@
package com.cloud.keystore;
+import java.util.List;
+
import com.cloud.utils.db.GenericDao;
public interface KeystoreDao extends GenericDao {
KeystoreVO findByName(String name);
void save(String name, String certificate, String key, String domainSuffix);
+ void save(String alias, String certificate, Integer index,
+ String domainSuffix);
+ List findCertChain();
}
diff --git a/server/src/com/cloud/keystore/KeystoreDaoImpl.java b/server/src/com/cloud/keystore/KeystoreDaoImpl.java
index 22421a9c55c..6399caf3aa6 100644
--- a/server/src/com/cloud/keystore/KeystoreDaoImpl.java
+++ b/server/src/com/cloud/keystore/KeystoreDaoImpl.java
@@ -18,6 +18,8 @@
package com.cloud.keystore;
import java.sql.PreparedStatement;
+import java.util.Comparator;
+import java.util.List;
import javax.ejb.Local;
@@ -29,14 +31,33 @@ import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
+import edu.emory.mathcs.backport.java.util.Collections;
+
@Local(value={KeystoreDao.class})
public class KeystoreDaoImpl extends GenericDaoBase implements KeystoreDao {
protected final SearchBuilder FindByNameSearch;
+ protected final SearchBuilder CertChainSearch;
public KeystoreDaoImpl() {
FindByNameSearch = createSearchBuilder();
FindByNameSearch.and("name", FindByNameSearch.entity().getName(), Op.EQ);
FindByNameSearch.done();
+
+ CertChainSearch = createSearchBuilder();
+ CertChainSearch.and("key", CertChainSearch.entity().getKey(), Op.NULL);
+ CertChainSearch.done();
+ }
+
+ @Override
+ public List findCertChain() {
+ SearchCriteria sc = CertChainSearch.create();
+ List 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
@@ -72,4 +93,24 @@ public class KeystoreDaoImpl extends GenericDaoBase implements
throw new CloudRuntimeException("Unable to save certificate under name " + name + " due to exception", e);
}
}
+
+ @Override
+ @DB
+ public void save(String alias, String certificate, Integer index, String domainSuffix) {
+ KeystoreVO ks = this.findByName(alias);
+ if (ks != null) {
+ ks.setCertificate(certificate);
+ ks.setName(alias);
+ ks.setIndex(index);
+ ks.setDomainSuffix(domainSuffix);
+ this.update(ks.getId(), ks);
+ } else {
+ KeystoreVO newks = new KeystoreVO();
+ newks.setCertificate(certificate);
+ newks.setName(alias);
+ newks.setIndex(index);
+ newks.setDomainSuffix(domainSuffix);
+ this.persist(newks);
+ }
+ }
}
diff --git a/server/src/com/cloud/keystore/KeystoreManager.java b/server/src/com/cloud/keystore/KeystoreManager.java
index 44491af07e8..78ab6fd2118 100644
--- a/server/src/com/cloud/keystore/KeystoreManager.java
+++ b/server/src/com/cloud/keystore/KeystoreManager.java
@@ -18,10 +18,14 @@
package com.cloud.keystore;
+import com.cloud.agent.api.SecStorageSetupCommand.Certificates;
import com.cloud.utils.component.Manager;
public interface KeystoreManager extends Manager {
boolean validateCertificate(String certificate, String key, String domainSuffix);
void saveCertificate(String name, String certificate, String key, String domainSuffix);
byte[] getKeystoreBits(String name, String aliasForCertificateInStore, String storePassword);
+ void saveCertificate(String name, String certificate, Integer index,
+ String domainSuffix);
+ Certificates getCertificates(String name);
}
diff --git a/server/src/com/cloud/keystore/KeystoreManagerImpl.java b/server/src/com/cloud/keystore/KeystoreManagerImpl.java
index 6fa2a690cfc..9495812b59b 100644
--- a/server/src/com/cloud/keystore/KeystoreManagerImpl.java
+++ b/server/src/com/cloud/keystore/KeystoreManagerImpl.java
@@ -23,6 +23,8 @@ import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.spec.InvalidKeySpecException;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -32,6 +34,8 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
+import com.cloud.agent.api.SecStorageSetupCommand;
+import com.cloud.utils.Ternary;
import com.cloud.utils.component.Inject;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.security.CertificateHelper;
@@ -99,6 +103,17 @@ public class KeystoreManagerImpl implements KeystoreManager {
_ksDao.save(name, certificate, key, domainSuffix);
}
+ @Override
+ public void saveCertificate(String name, String certificate, Integer index, String domainSuffix) {
+ if(name == null || name.isEmpty() ||
+ certificate == null || certificate.isEmpty() ||
+ index == null ||
+ domainSuffix == null || domainSuffix.isEmpty())
+ throw new CloudRuntimeException("invalid parameter in saveCerticate");
+
+ _ksDao.save(name, certificate, index, domainSuffix);
+ }
+
@Override
public byte[] getKeystoreBits(String name, String aliasForCertificateInStore, String storePassword) {
assert(name != null);
@@ -109,8 +124,19 @@ public class KeystoreManagerImpl implements KeystoreManager {
if(ksVo == null)
throw new CloudRuntimeException("Unable to find keystore " + name);
+ List> certs = new ArrayList>();
+ List certChains = _ksDao.findCertChain();
+
+ for (KeystoreVO ks : certChains) {
+ Ternary cert = new Ternary(ks.getName(), ks.getCertificate(), null);
+ certs.add(cert);
+ }
+
+ Ternary cert = new Ternary(ksVo.getName(), ksVo.getCertificate(), getKeyContent(ksVo.getKey()));
+ certs.add(cert);
+
try {
- return CertificateHelper.buildAndSaveKeystore(aliasForCertificateInStore, ksVo.getCertificate(), getKeyContent(ksVo.getKey()), storePassword);
+ return CertificateHelper.buildAndSaveKeystore(certs, storePassword);
} catch(KeyStoreException e) {
s_logger.warn("Unable to build keystore for " + name + " due to KeyStoreException");
} catch(CertificateException e) {
@@ -125,6 +151,28 @@ public class KeystoreManagerImpl implements KeystoreManager {
return null;
}
+ @Override
+ public SecStorageSetupCommand.Certificates getCertificates(String name) {
+ KeystoreVO ksVo = _ksDao.findByName(name);
+ if (ksVo == null) {
+ return null;
+ }
+ String prvKey = ksVo.getKey();
+ String prvCert = ksVo.getCertificate();
+ String certChain = null;
+ List certchains = _ksDao.findCertChain();
+ if (certchains.size() > 0) {
+ StringBuilder chains = new StringBuilder();
+ for (KeystoreVO cert : certchains) {
+ chains.append(cert.getCertificate());
+ chains.append("\n");
+ }
+ certChain = chains.toString();
+ }
+ SecStorageSetupCommand.Certificates certs = new SecStorageSetupCommand.Certificates(prvKey, prvCert, certChain);
+ return certs;
+ }
+
private static String getKeyContent(String key) {
Pattern regex = Pattern.compile("(^[\\-]+[^\\-]+[\\-]+[\\n]?)([^\\-]+)([\\-]+[^\\-]+[\\-]+$)");
Matcher m = regex.matcher(key);
diff --git a/server/src/com/cloud/keystore/KeystoreVO.java b/server/src/com/cloud/keystore/KeystoreVO.java
index 52e10b85fe1..4b252adfb56 100644
--- a/server/src/com/cloud/keystore/KeystoreVO.java
+++ b/server/src/com/cloud/keystore/KeystoreVO.java
@@ -44,6 +44,9 @@ public class KeystoreVO {
@Column(name="domain_suffix")
private String domainSuffix;
+
+ @Column(name="seq")
+ private Integer index;
public KeystoreVO() {
}
@@ -87,4 +90,12 @@ public class KeystoreVO {
public void setDomainSuffix(String domainSuffix) {
this.domainSuffix = domainSuffix;
}
+
+ public void setIndex(Integer index) {
+ this.index = index;
+ }
+
+ public Integer getIndex() {
+ return this.index;
+ }
}
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index ed1c562ccf7..7bafc01b036 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -4549,11 +4549,29 @@ public class ManagementServerImpl implements ManagementServer {
@Override
@DB
public String uploadCertificate(UploadCustomCertificateCmd cmd) {
- if (!_ksMgr.validateCertificate(cmd.getCertificate(), cmd.getPrivateKey(), cmd.getDomainSuffix())) {
+ if (cmd.getPrivateKey() != null && cmd.getAlias() != null) {
+ throw new InvalidParameterValueException("Can't change the alias for private key certification");
+ }
+
+ if (cmd.getPrivateKey() == null) {
+ if (cmd.getAlias() == null) {
+ throw new InvalidParameterValueException("alias can't be empty, if it's a certification chain");
+ }
+
+ if (cmd.getCertIndex() == null) {
+ throw new InvalidParameterValueException("index can't be empty, if it's a certifciation chain");
+ }
+ }
+
+ if (cmd.getPrivateKey() != null &&!_ksMgr.validateCertificate(cmd.getCertificate(), cmd.getPrivateKey(), cmd.getDomainSuffix())) {
throw new InvalidParameterValueException("Failed to pass certificate validation check");
}
- _ksMgr.saveCertificate(ConsoleProxyManager.CERTIFICATE_NAME, cmd.getCertificate(), cmd.getPrivateKey(), cmd.getDomainSuffix());
+ if (cmd.getPrivateKey() != null) {
+ _ksMgr.saveCertificate(ConsoleProxyManager.CERTIFICATE_NAME, cmd.getCertificate(), cmd.getPrivateKey(), cmd.getDomainSuffix());
+ } else {
+ _ksMgr.saveCertificate(cmd.getAlias(), cmd.getCertificate(), cmd.getCertIndex(), cmd.getDomainSuffix());
+ }
_consoleProxyMgr.setManagementState(ConsoleProxyManagementState.ResetSuspending);
return "Certificate has been updated, we will stop all running console proxy VMs to propagate the new certificate, please give a few minutes for console access service to be up again";
diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
index fd7cd4f7af2..64f2625ac7d 100755
--- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
+++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
@@ -36,6 +36,7 @@ import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand;
import com.cloud.agent.api.SecStorageSetupAnswer;
import com.cloud.agent.api.SecStorageSetupCommand;
+import com.cloud.agent.api.SecStorageSetupCommand.Certificates;
import com.cloud.agent.api.SecStorageVMSetupCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StopAnswer;
@@ -48,6 +49,7 @@ import com.cloud.cluster.ManagementServerNode;
import com.cloud.configuration.Config;
import com.cloud.configuration.ZoneConfig;
import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.DataCenterVO;
@@ -65,6 +67,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.info.RunningHostCountInfo;
import com.cloud.info.RunningHostInfoAgregator;
import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo;
+import com.cloud.keystore.KeystoreManager;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.TrafficType;
@@ -190,6 +193,8 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
@Inject
UserVmDetailsDao _vmDetailsDao;
+ @Inject
+ KeystoreManager _keystoreMgr;
private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL;
private int _secStorageVmRamSize;
@@ -250,7 +255,13 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
List ssHosts = _hostDao.listSecondaryStorageHosts(zoneId);
for( HostVO ssHost : ssHosts ) {
String secUrl = ssHost.getStorageUrl();
- SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(secUrl);
+ SecStorageSetupCommand setupCmd = null;
+ if (!_useSSlCopy) {
+ setupCmd = new SecStorageSetupCommand(secUrl, null);
+ } else {
+ Certificates certs = _keystoreMgr.getCertificates(ConsoleProxyManager.CERTIFICATE_NAME);
+ setupCmd = new SecStorageSetupCommand(secUrl, certs);
+ }
Answer answer = _agentMgr.easySend(ssHostId, setupCmd);
if (answer != null && answer.getResult()) {
@@ -270,7 +281,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
} else if( cssHost.getType() == Host.Type.SecondaryStorage ) {
List alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, zoneId, State.Running);
String secUrl = cssHost.getStorageUrl();
- SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(secUrl);
+ SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(secUrl, null);
for ( SecondaryStorageVmVO ssVm : alreadyRunning ) {
HostVO host = _hostDao.findByName(ssVm.getInstanceName());
Answer answer = _agentMgr.easySend(host.getId(), setupCmd);
diff --git a/server/src/com/cloud/upgrade/dao/Upgrade2213to2214.java b/server/src/com/cloud/upgrade/dao/Upgrade2213to2214.java
index bbc653ba1f1..644e5373a93 100644
--- a/server/src/com/cloud/upgrade/dao/Upgrade2213to2214.java
+++ b/server/src/com/cloud/upgrade/dao/Upgrade2213to2214.java
@@ -20,18 +20,157 @@ package com.cloud.upgrade.dao;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
+import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
+import com.cloud.consoleproxy.ConsoleProxyManagerImpl;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
public class Upgrade2213to2214 implements DbUpgrade {
final static Logger s_logger = Logger.getLogger(Upgrade2213to2214.class);
+ private final String priviateKey =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCDT9AtEfs+s/I8QXp6rrCw0iNJ\n" +
+ "0+GgsybNHheU+JpL39LMTZykCrZhZnyDvwdxCoOfE38Sa32baHKNds+y2SHnMNsOkw8OcNucHEBX\n" +
+ "1FIpOBGph9D6xC+umx9od6xMWETUv7j6h2u+WC3OhBM8fHCBqIiAol31/IkcqDxxsHlQ8S/oCfTl\n" +
+ "XJUY6Yn628OA1XijKdRnadV0hZ829cv/PZKljjwQUTyrd0KHQeksBH+YAYSo2JUl8ekNLsOi8/cP\n" +
+ "tfojnltzRI1GXi0ZONs8VnDzJ0a2gqZY+uxlz+CGbLnGnlN4j9cBpE+MfUE+35Dq121sTpsSgF85\n" +
+ "Mz+pVhn2S633AgMBAAECggEAH/Szd9RxbVADenCA6wxKSa3KErRyq1YN8ksJeCKMAj0FIt0caruE\n" +
+ "qO11DebWW8cwQu1Otl/cYI6pmg24/BBldMrp9IELX/tNJo+lhPpRyGAxxC0eSXinFfoASb8d+jJd\n" +
+ "Bd1mmemM6fSxqRlxSP4LrzIhjhR1g2CiyYuTsiM9UtoVKGyHwe7KfFwirUOJo3Mr18zUVNm7YqY4\n" +
+ "IVhOSq59zkH3ULBlYq4bG50jpxa5mNSCZ7IpafPY/kE/CbR+FWNt30+rk69T+qb5abg6+XGm+OAm\n" +
+ "bnQ18yZEqX6nJLk7Ch0cfA5orGgrTMOrM71wK7tBBDQ308kOxDGebx6j0qD36QKBgQDTRDr8kuhA\n" +
+ "9sUyKr9vk2DQCMpNvEeiwI3JRMqmmxpNAtg01aJ3Ya57vX5Fc+zcuV87kP6FM1xgpHQvnw5LWo2J\n" +
+ "s7ANwQcP8ricEW5zkZhSjI4ssMeAubmsHOloGxmLFYZqwx0JI7CWViGTLMcUlqKblmHcjeQDeDfP\n" +
+ "P1TaCItFmwKBgQCfHZwVvIcaDs5vxVpZ4ftvflIrW8qq0uOVK6QIf9A/YTGhCXl2qxxTg2A6+0rg\n" +
+ "ZqI7zKzUDxIbVv0KlgCbpHDC9d5+sdtDB3wW2pimuJ3p1z4/RHb4n/lDwXCACZl1S5l24yXX2pFZ\n" +
+ "wdPCXmy5PYkHMssFLNhI24pprUIQs66M1QKBgQDQwjAjWisD3pRXESSfZRsaFkWJcM28hdbVFhPF\n" +
+ "c6gWhwQLmTp0CuL2RPXcPUPFi6sN2iWWi3zxxi9Eyz+9uBn6AsOpo56N5MME/LiOnETO9TKb+Ib6\n" +
+ "rQtKhjshcv3XkIqFPo2XdVvOAgglPO7vajX91iiXXuH7h7RmJud6l0y/lwKBgE+bi90gLuPtpoEr\n" +
+ "VzIDKz40ED5bNYHT80NNy0rpT7J2GVN9nwStRYXPBBVeZq7xCpgqpgmO5LtDAWULeZBlbHlOdBwl\n" +
+ "NhNKKl5wzdEUKwW0yBL1WSS5PQgWPwgARYP25/ggW22sj+49WIo1neXsEKPGWObk8e050f1fTt92\n" +
+ "Vo1lAoGAb1gCoyBCzvi7sqFxm4V5oapnJeiQQJFjhoYWqGa26rQ+AvXXNuBcigIeDXNJPctSF0Uc\n" +
+ "p11KbbCgiruBbckvM1vGsk6Sx4leRk+IFHRpJktFUek4o0eUg0shOsyyvyet48Dfg0a8FvcxROs0\n" +
+ "gD+IYds5doiob/hcm1hnNB/3vk4=\n" +
+ "-----END PRIVATE KEY----- |\n" ;
+
+ private final String pubcertificate =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFZTCCBE2gAwIBAgIHKBCduBUoKDANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE\n" +
+ "BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY\n" +
+ "BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm\n" +
+ "aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5\n" +
+ "IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky\n" +
+ "ODcwHhcNMTIwMjAzMDMzMDQwWhcNMTcwMjA3MDUxMTIzWjBZMRkwFwYDVQQKDBAq\n" +
+ "LnJlYWxob3N0aXAuY29tMSEwHwYDVQQLDBhEb21haW4gQ29udHJvbCBWYWxpZGF0\n" +
+ "ZWQxGTAXBgNVBAMMECoucmVhbGhvc3RpcC5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n" +
+ "A4IBDwAwggEKAoIBAQCDT9AtEfs+s/I8QXp6rrCw0iNJ0+GgsybNHheU+JpL39LM\n" +
+ "TZykCrZhZnyDvwdxCoOfE38Sa32baHKNds+y2SHnMNsOkw8OcNucHEBX1FIpOBGp\n" +
+ "h9D6xC+umx9od6xMWETUv7j6h2u+WC3OhBM8fHCBqIiAol31/IkcqDxxsHlQ8S/o\n" +
+ "CfTlXJUY6Yn628OA1XijKdRnadV0hZ829cv/PZKljjwQUTyrd0KHQeksBH+YAYSo\n" +
+ "2JUl8ekNLsOi8/cPtfojnltzRI1GXi0ZONs8VnDzJ0a2gqZY+uxlz+CGbLnGnlN4\n" +
+ "j9cBpE+MfUE+35Dq121sTpsSgF85Mz+pVhn2S633AgMBAAGjggG+MIIBujAPBgNV\n" +
+ "HRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV\n" +
+ "HQ8BAf8EBAMCBaAwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5\n" +
+ "LmNvbS9nZHMxLTY0LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkwNwYI\n" +
+ "KwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3Np\n" +
+ "dG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au\n" +
+ "Z29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdv\n" +
+ "ZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSME\n" +
+ "GDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zArBgNVHREEJDAighAqLnJlYWxob3N0\n" +
+ "aXAuY29tgg5yZWFsaG9zdGlwLmNvbTAdBgNVHQ4EFgQUZyJz9/QLy5TWIIscTXID\n" +
+ "E8Xk47YwDQYJKoZIhvcNAQEFBQADggEBAKiUV3KK16mP0NpS92fmQkCLqm+qUWyN\n" +
+ "BfBVgf9/M5pcT8EiTZlS5nAtzAE/eRpBeR3ubLlaAogj4rdH7YYVJcDDLLoB2qM3\n" +
+ "qeCHu8LFoblkb93UuFDWqRaVPmMlJRnhsRkL1oa2gM2hwQTkBDkP7w5FG1BELCgl\n" +
+ "gZI2ij2yxjge6pOEwSyZCzzbCcg9pN+dNrYyGEtB4k+BBnPA3N4r14CWbk+uxjrQ\n" +
+ "6j2Ip+b7wOc5IuMEMl8xwTyjuX3lsLbAZyFI9RCyofwA9NqIZ1GeB6Zd196rubQp\n" +
+ "93cmBqGGjZUs3wMrGlm7xdjlX6GQ9UvmvkMub9+lL99A5W50QgCmFeI=\n" +
+ "-----END CERTIFICATE-----\n";
+
+ private final String rootCa =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx\n" +
+ "ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g\n" +
+ "RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw\n" +
+ "MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH\n" +
+ "QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j\n" +
+ "b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j\n" +
+ "b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj\n" +
+ "YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN\n" +
+ "AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H\n" +
+ "KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm\n" +
+ "VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR\n" +
+ "SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT\n" +
+ "cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ\n" +
+ "6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu\n" +
+ "MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS\n" +
+ "kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB\n" +
+ "BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f\n" +
+ "BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv\n" +
+ "c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH\n" +
+ "AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO\n" +
+ "BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG\n" +
+ "OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU\n" +
+ "A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o\n" +
+ "0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX\n" +
+ "RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH\n" +
+ "qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV\n" +
+ "U+4=\n" +
+ "-----END CERTIFICATE-----\n" +
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh\n" +
+ "bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu\n" +
+ "Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g\n" +
+ "QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe\n" +
+ "BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoX\n" +
+ "DTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBE\n" +
+ "YWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0\n" +
+ "aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC\n" +
+ "ggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv\n" +
+ "2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+q\n" +
+ "N1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiO\n" +
+ "r18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN\n" +
+ "f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEH\n" +
+ "U1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHU\n" +
+ "TBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMb\n" +
+ "VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwg\n" +
+ "SW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlv\n" +
+ "biBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEg\n" +
+ "MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUw\n" +
+ "AwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdv\n" +
+ "ZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMu\n" +
+ "Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUd\n" +
+ "IAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv\n" +
+ "bS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1\n" +
+ "QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4O\n" +
+ "WBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0Vmsf\n" +
+ "SxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==\n" +
+ "-----END CERTIFICATE-----\n" +
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0\n" +
+ "IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz\n" +
+ "BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y\n" +
+ "aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG\n" +
+ "9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy\n" +
+ "NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y\n" +
+ "azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs\n" +
+ "YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw\n" +
+ "Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl\n" +
+ "cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY\n" +
+ "dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9\n" +
+ "WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS\n" +
+ "v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v\n" +
+ "UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu\n" +
+ "IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC\n" +
+ "W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd\n" +
+ "-----END CERTIFICATE-----\n";
+
@Override
public String[] getUpgradableVersionRange() {
return new String[] { "2.2.13", "2.2.14"};
@@ -47,6 +186,35 @@ public class Upgrade2213to2214 implements DbUpgrade {
return true;
}
+ private void upgradeCerts(Connection conn) {
+ PreparedStatement pstmt;
+ try {
+ pstmt = conn.prepareStatement("select md5(`cloud`.`keystore`.key) from `cloud`.`keystore` where name = 'CPVMCertificate'");
+ ResultSet rs = pstmt.executeQuery();
+ while (rs.next()) {
+ String privateKeyMd5 = rs.getString(1);
+ if (privateKeyMd5.equalsIgnoreCase("b2d3089241ed0ea0336efeb125dbb610")) {
+ s_logger.debug("Need to upgrade cloudstack provided certificate");
+ pstmt = conn.prepareStatement("update `cloud`.`keystore` set `cloud`.`keystore`.key = ?, certificate = ? where name = 'CPVMCertificate'");
+ pstmt.setString(1, ConsoleProxyManagerImpl.keyContent);
+ pstmt.setString(2, ConsoleProxyManagerImpl.certContent);
+ pstmt.executeUpdate();
+
+ pstmt = conn.prepareStatement("insert into `cloud`.`keystore` (name, certificate, seq, domain_suffix) VALUES (?,?,?,?)");
+ pstmt.setString(1, "root");
+ pstmt.setString(2, ConsoleProxyManagerImpl.rootCa);
+ pstmt.setInt(3, 0);
+ pstmt.setString(4, "realhostip.com");
+ pstmt.executeUpdate();
+ }
+ }
+ rs.close();
+ pstmt.close();
+ } catch (SQLException e) {
+ s_logger.debug("Failed to upgrade keystore: " + e.toString());
+ }
+
+ }
@Override
public File[] getPrepareScripts() {
String script = Script.findScript("", "db/schema-2213to2214.sql");
@@ -54,12 +222,14 @@ public class Upgrade2213to2214 implements DbUpgrade {
throw new CloudRuntimeException("Unable to find db/schema-2213to2214.sql");
}
+
return new File[] { new File(script) };
}
@Override
public void performDataMigration(Connection conn) {
fixIndexes(conn);
+ upgradeCerts(conn);
}
@Override
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index 5f526b5e650..e4238e60a94 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -1619,8 +1619,9 @@ CREATE TABLE `cloud`.`keystore` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(64) NOT NULL COMMENT 'unique name for the certifiation',
`certificate` text NOT NULL COMMENT 'the actual certificate being stored in the db',
- `key` text NOT NULL COMMENT 'private key associated wih the certificate',
+ `key` text COMMENT 'private key associated wih the certificate',
`domain_suffix` varchar(256) NOT NULL COMMENT 'DNS domain suffix associated with the certificate',
+ `seq` int,
PRIMARY KEY (`id`),
UNIQUE(name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/setup/db/db/schema-2213to2214.sql b/setup/db/db/schema-2213to2214.sql
index 1bbf44a5075..9fe9c2d596b 100644
--- a/setup/db/db/schema-2213to2214.sql
+++ b/setup/db/db/schema-2213to2214.sql
@@ -61,4 +61,6 @@ ALTER TABLE `cloud`.`vm_instance` MODIFY `limit_cpu_use` tinyint(1) unsigned NOT
UPDATE `cloud`.`configuration` SET `value`='false' WHERE `name`='agent.lb.enabled';
-ALTER TABLE `cloud_usage`.`user_statistics` MODIFY `device_type` varchar(32) NOT NULL;
+ALTER TABLE `cloud_usage`.`user_statistics` MODIFY `device_type` varchar(32) NOT NULL;
+ALTER TABLE `cloud`.`keystore` ADD seq int;
+ALTER TABLE `cloud`.`keystore` MODIFY `cloud`.`keystore`.`key` text;
diff --git a/utils/src/com/cloud/utils/security/CertificateHelper.java b/utils/src/com/cloud/utils/security/CertificateHelper.java
index 8ba7c99154c..3d3deff0b55 100644
--- a/utils/src/com/cloud/utils/security/CertificateHelper.java
+++ b/utils/src/com/cloud/utils/security/CertificateHelper.java
@@ -3,6 +3,7 @@ package com.cloud.utils.security;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
@@ -14,9 +15,12 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.List;
import org.apache.commons.codec.binary.Base64;
+import com.cloud.utils.Ternary;
+
public class CertificateHelper {
public static byte[] buildAndSaveKeystore(String alias, String cert, String privateKey, String storePassword) throws KeyStoreException, CertificateException,
NoSuchAlgorithmException, InvalidKeySpecException, IOException {
@@ -28,6 +32,32 @@ public class CertificateHelper {
return os.toByteArray();
}
+ public static byte[] buildAndSaveKeystore(List> certs, String storePassword) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, InvalidKeySpecException {
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(null, storePassword != null ? storePassword.toCharArray() : null);
+
+ //name,cert,key
+ for (Ternary cert : certs) {
+ if (cert.third() == null) {
+ Certificate c = buildCertificate(cert.second());
+ ks.setCertificateEntry(cert.first(), c);
+ } else {
+ Certificate[] c = new Certificate[certs.size()];
+ int i = certs.size();
+ for (Ternary ct : certs) {
+ c[i - 1] = buildCertificate(ct.second());
+ i--;
+ }
+ ks.setKeyEntry(cert.first(), buildPrivateKey(cert.third()), storePassword != null ? storePassword.toCharArray() : null, c );
+ }
+ }
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ ks.store(os, storePassword != null ? storePassword.toCharArray() : null);
+ os.close();
+ return os.toByteArray();
+ }
+
public static KeyStore loadKeystore(byte[] ksData, String storePassword) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
assert(ksData != null);
KeyStore ks = KeyStore.getInstance("JKS");