add cert chain in db, and also open the api to upload a cert chain

This commit is contained in:
Edison Su 2012-02-09 14:15:11 -08:00
parent bdfb8a2e14
commit 1ab89dd436
17 changed files with 706 additions and 94 deletions

View File

@ -17,16 +17,51 @@
*/ */
package com.cloud.agent.api; package com.cloud.agent.api;
import com.cloud.agent.api.LogLevel.Log4jLevel;
public class SecStorageSetupCommand extends Command { public class SecStorageSetupCommand extends Command {
private String secUrl; 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() { public SecStorageSetupCommand() {
super(); super();
} }
public SecStorageSetupCommand(String secUrl) { public SecStorageSetupCommand(String secUrl, Certificates certs) {
super(); super();
this.secUrl = secUrl; this.secUrl = secUrl;
this.certs = certs;
} }
@Override @Override
@ -37,8 +72,13 @@ public class SecStorageSetupCommand extends Command {
public String getSecUrl() { public String getSecUrl() {
return secUrl; return secUrl;
} }
public Certificates getCerts() {
return this.certs;
}
public void setSecUrl(String secUrl) { public void setSecUrl(String secUrl) {
this.secUrl = secUrl; this.secUrl = secUrl;
} }
} }

View File

@ -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") @Parameter(name=ApiConstants.CERTIFICATE,type=CommandType.STRING,required=true,description="the custom cert to be uploaded")
private String certificate; 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; private String privateKey;
@Parameter(name=ApiConstants.DOMAIN_SUFFIX,type=CommandType.STRING,required=true,description="DNS domain suffix that the certificate is granted for") @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() { public String getDomainSuffix() {
return domainSuffix; return domainSuffix;
} }
public Integer getCertIndex() {
return index;
}
public String getAlias() {
return alias;
}
@Override @Override
public String getEventType() { public String getEventType() {

View File

@ -18,7 +18,12 @@
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() { config_httpd_conf() {
@ -45,33 +50,102 @@ config_apache2_conf() {
sed -i -e "s/Listen .*:80/Listen $ip:80/g" /etc/apache2/ports.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/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 -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.key/cert_apache.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.pem/cert_apache.crt/' /etc/apache2/sites-available/default-ssl
} }
copy_certs() { copy_certs() {
local certdir=$(dirname $0)/certs local certdir=$(dirname $0)/certs
local mydir=$(dirname $0) local mydir=$(dirname $0)
if [ -d $certdir ] && [ -f $certdir/realhostip.key ] && [ -f $certdir/realhostip.crt ] ; then if [ -d $certdir ] && [ -f $customPrivKey ] && [ -f $customPrivCert ] ; 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 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 $? return $?
fi fi
if [ ! -z customCertChain ] && [ -f $customCertChain ] ; then
cp $customCertChain /etc/httpd/ssl/certs
fi
return 1 return 1
} }
copy_certs_apache2() { copy_certs_apache2() {
local certdir=$(dirname $0)/certs local certdir=$(dirname $0)/certs
local mydir=$(dirname $0) local mydir=$(dirname $0)
if [ -d $certdir ] && [ -f $certdir/realhostip.key ] && [ -f $certdir/realhostip.crt ] ; then if [ -f $customPrivKey ] && [ -f $customPrivCert ] ; then
cp $certdir/realhostip.key /etc/ssl/private/ && cp $certdir/realhostip.crt /etc/ssl/certs/ cp $customPrivKey /etc/ssl/private/cert_apache.key && cp $customPrivCert /etc/ssl/certs/cert_apache.crt
return $?
fi 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 " cflag=
exit 0 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 fi
if [ -d /etc/apache2 ] if [ -d /etc/apache2 ]
@ -89,7 +163,11 @@ fi
if [ -d /etc/apache2 ] if [ -d /etc/apache2 ]
then then
config_apache2_conf $1 $2 config_apache2_conf $publicIp $hostName
/etc/init.d/apache2 stop
/etc/init.d/apache2 start
else else
config_httpd_conf $1 $2 config_httpd_conf $publicIp $hostName
fi fi

View File

@ -50,7 +50,7 @@ public class ConsoleProxySecureServerFactoryImpl implements ConsoleProxyServerFa
public void init(byte[] ksBits, String ksPassword) { public void init(byte[] ksBits, String ksPassword) {
s_logger.info("Start initializing SSL"); s_logger.info("Start initializing SSL");
// if(ksBits == null) { if(ksBits == null) {
try { try {
s_logger.info("Initializing SSL from built-in default certificate"); s_logger.info("Initializing SSL from built-in default certificate");
@ -76,7 +76,7 @@ public class ConsoleProxySecureServerFactoryImpl implements ConsoleProxyServerFa
} catch (Exception ioe) { } catch (Exception ioe) {
s_logger.error(ioe.toString(), ioe); s_logger.error(ioe.toString(), ioe);
} }
/*
} else { } else {
char[] passphrase = ksPassword != null ? ksPassword.toCharArray() : null; char[] passphrase = ksPassword != null ? ksPassword.toCharArray() : null;
try { try {
@ -100,7 +100,7 @@ public class ConsoleProxySecureServerFactoryImpl implements ConsoleProxyServerFa
s_logger.error("Unable to init factory due to exception ", e); s_logger.error("Unable to init factory due to exception ", e);
} }
} }
*/
} }
public HttpServer createHttpServerInstance(int port) throws IOException { public HttpServer createHttpServerInstance(int port) throws IOException {

View File

@ -17,8 +17,10 @@
*/ */
package com.cloud.storage.resource; package com.cloud.storage.resource;
import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigInteger; import java.math.BigInteger;
@ -55,6 +57,12 @@ import com.cloud.agent.api.SecStorageFirewallCfgCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig; import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig;
import com.cloud.agent.api.SecStorageSetupAnswer; import com.cloud.agent.api.SecStorageSetupAnswer;
import com.cloud.agent.api.SecStorageSetupCommand; import com.cloud.agent.api.SecStorageSetupCommand;
<<<<<<< HEAD
=======
import com.cloud.agent.api.SecStorageSetupCommand.Certificates;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig;
>>>>>>> 0776447... bug 13470: add cert chain in db, and also open the api to upload a cert chain
import com.cloud.agent.api.SecStorageVMSetupCommand; import com.cloud.agent.api.SecStorageVMSetupCommand;
import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand; import com.cloud.agent.api.StartupSecondaryStorageCommand;
@ -547,6 +555,38 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return new Answer(cmd, true, checksum); 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) { private Answer execute(SecStorageSetupCommand cmd) {
if (!_inSystemVM){ if (!_inSystemVM){
@ -565,6 +605,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
String dir = UUID.nameUUIDFromBytes(nfsPath.getBytes()).toString(); String dir = UUID.nameUUIDFromBytes(nfsPath.getBytes()).toString();
String root = _parent + "/" + dir; String root = _parent + "/" + dir;
mount(root, nfsPath); mount(root, nfsPath);
configCerts(cmd.getCerts());
return new SecStorageSetupAnswer(dir); return new SecStorageSetupAnswer(dir);
} catch (Exception e) { } catch (Exception e) {
String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString(); String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString();
@ -1034,13 +1077,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(); startAdditionalServices();
_params.put("install.numthreads", "50"); _params.put("install.numthreads", "50");
_params.put("secondary.storage.vm", "true"); _params.put("secondary.storage.vm", "true");
@ -1117,8 +1154,23 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
private void configureSSL() { private void configureSSL() {
Script command = new Script(_configSslScr); Script command = new Script(_configSslScr);
command.add(_publicIp); command.add("-i", _publicIp);
command.add(_hostname); 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(); String result = command.execute();
if (result != null) { if (result != null) {
s_logger.warn("Unable to configure httpd to use ssl"); s_logger.warn("Unable to configure httpd to use ssl");

View File

@ -275,66 +275,142 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
+ "fJ6GBCs1XgZLuhkKS8fPf+YmG2ZjHzYDjYoSx7paDXgEm+kbYIZdCK51lA0BUAjP\n" + "9ZMGhsu/PpAbh5U/DtcIqxY0xeqD4TeGsBzXg6uLhv+jKHDtXg5fYPe+z0n5DCEL\n" + "fJ6GBCs1XgZLuhkKS8fPf+YmG2ZjHzYDjYoSx7paDXgEm+kbYIZdCK51lA0BUAjP\n" + "9ZMGhsu/PpAbh5U/DtcIqxY0xeqD4TeGsBzXg6uLhv+jKHDtXg5fYPe+z0n5DCEL\n"
+ "k0fLF4+i/pt9hVCz0QrZ28RUhXf825+EOL0Gw+Uzt+7RV2cCaJrlu4cDrDom2FRy\n" + "E8I=\n" + "-----END CERTIFICATE-----\n"; + "k0fLF4+i/pt9hVCz0QrZ28RUhXf825+EOL0Gw+Uzt+7RV2cCaJrlu4cDrDom2FRy\n" + "E8I=\n" + "-----END CERTIFICATE-----\n";
*/ */
private final String keyContent = public static final String keyContent =
"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCGu5REMZSFQ6wD\n" + "-----BEGIN PRIVATE KEY-----\n" +
"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\n" + "gD+IYds5doiob/hcm1hnNB/3vk4=\n" +
"GI19ihoXr+8tRJilMCRQp4iFdi7acnek3/u0MaZ0ct8cVh9oMO+zVmTrpxJNTL6H\n" + "-----END PRIVATE KEY-----\n" ;
"He0z1VA4w/j4J5Z2P0KNLnKvRpayGWcf86YgSEmgU/ScwWzGL+cNgEKih74lSL4Z\n" +
"OK2Ayxxw3vbRyxQg6r1JUIKS\n";
private final String certContent = public static final String certContent =
"-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" +
"MIIFZTCCBE2gAwIBAgIHK35JiCqLMjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE\n" + "MIIFZTCCBE2gAwIBAgIHKBCduBUoKDANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE\n" +
"BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY\n" + "BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY\n" +
"BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm\n" + "BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm\n" +
"aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5\n" + "aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5\n" +
"IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky\n" + "IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky\n" +
"ODcwHhcNMTIwMjAyMDExMDE5WhcNMTcwMjA3MDUxMTIzWjBZMRkwFwYDVQQKDBAq\n" + "ODcwHhcNMTIwMjAzMDMzMDQwWhcNMTcwMjA3MDUxMTIzWjBZMRkwFwYDVQQKDBAq\n" +
"LnJlYWxob3N0aXAuY29tMSEwHwYDVQQLDBhEb21haW4gQ29udHJvbCBWYWxpZGF0\n" + "LnJlYWxob3N0aXAuY29tMSEwHwYDVQQLDBhEb21haW4gQ29udHJvbCBWYWxpZGF0\n" +
"ZWQxGTAXBgNVBAMMECoucmVhbGhvc3RpcC5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n" + "ZWQxGTAXBgNVBAMMECoucmVhbGhvc3RpcC5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n" +
"A4IBDwAwggEKAoIBAQCGu5REMZSFQ6wDFr7NPp9iibCYHZ6d1IV7s6Yvs6yvXmYw\n" + "A4IBDwAwggEKAoIBAQCDT9AtEfs+s/I8QXp6rrCw0iNJ0+GgsybNHheU+JpL39LM\n" +
"46c9JaJ8FN0NoHVzzDD2dELfpBxXRN7eq1rcP3ISDdDkhjngJoXEd2xaqgp0UxOS\n" + "TZykCrZhZnyDvwdxCoOfE38Sa32baHKNds+y2SHnMNsOkw8OcNucHEBX1FIpOBGp\n" +
"+AaamGG6sOleACn0XBF+XXaaD5vnFw7YnDUyJioWR5KdTzVajLVkdEP3uPmJbRdv\n" + "h9D6xC+umx9od6xMWETUv7j6h2u+WC3OhBM8fHCBqIiAol31/IkcqDxxsHlQ8S/o\n" +
"eEu8HMZpwhZyY4uAcH5nHxMJEj/mkZtFZJDi26ZjeonVOwnGm0NTbGCrfCneQEZC\n" + "CfTlXJUY6Yn628OA1XijKdRnadV0hZ829cv/PZKljjwQUTyrd0KHQeksBH+YAYSo\n" +
"/SENua3BklHXc07zl3TrWu8xhrVWGRbcknw0VmGaPmehtuzL9WsieWGG4KH9G1LC\n" + "2JUl8ekNLsOi8/cPtfojnltzRI1GXi0ZONs8VnDzJ0a2gqZY+uxlz+CGbLnGnlN4\n" +
"2w2mbib64nSluBEcHRCKOT2aMzo2FonKAZkkIE53AgMBAAGjggG+MIIBujAPBgNV\n" + "j9cBpE+MfUE+35Dq121sTpsSgF85Mz+pVhn2S633AgMBAAGjggG+MIIBujAPBgNV\n" +
"HRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV\n" + "HRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV\n" +
"HQ8BAf8EBAMCBaAwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5\n" + "HQ8BAf8EBAMCBaAwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5\n" +
"LmNvbS9nZHMxLTYzLmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkwNwYI\n" + "LmNvbS9nZHMxLTY0LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkwNwYI\n" +
"KwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3Np\n" + "KwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3Np\n" +
"dG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au\n" + "dG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au\n" +
"Z29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdv\n" + "Z29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdv\n" +
"ZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSME\n" + "ZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSME\n" +
"GDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zArBgNVHREEJDAighAqLnJlYWxob3N0\n" + "GDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zArBgNVHREEJDAighAqLnJlYWxob3N0\n" +
"aXAuY29tgg5yZWFsaG9zdGlwLmNvbTAdBgNVHQ4EFgQUwjwYIABbqSlCbCDr9E6F\n" + "aXAuY29tgg5yZWFsaG9zdGlwLmNvbTAdBgNVHQ4EFgQUZyJz9/QLy5TWIIscTXID\n" +
"htB12TAwDQYJKoZIhvcNAQEFBQADggEBALxCXsUGaxTwWIvQEJu6D4lIMrkYyQuy\n" + "E8Xk47YwDQYJKoZIhvcNAQEFBQADggEBAKiUV3KK16mP0NpS92fmQkCLqm+qUWyN\n" +
"Z2Cfd1/RLyX87ZkBR4iCO9MTezVFgDQj2rfSQGhnVLxD/1cGoivHKm3hmRX8gWh1\n" + "BfBVgf9/M5pcT8EiTZlS5nAtzAE/eRpBeR3ubLlaAogj4rdH7YYVJcDDLLoB2qM3\n" +
"d3vPco55XF8wWtQee822RB55h015kmrcv68yUIllrjDDuGfMc+QdIkxjIzDRWlEF\n" + "qeCHu8LFoblkb93UuFDWqRaVPmMlJRnhsRkL1oa2gM2hwQTkBDkP7w5FG1BELCgl\n" +
"mq8xEGIfabuflT2C58OU1ZHgQvBvK2iWGNgXSE9h0Bf8xwu/uYHgoWi5dBFm+woo\n" + "gZI2ij2yxjge6pOEwSyZCzzbCcg9pN+dNrYyGEtB4k+BBnPA3N4r14CWbk+uxjrQ\n" +
"GVNHaLNZBjwvKGvJN8zcmjjpYuYEfGVezm+kgGTBLpKthx5HV8vTrKnkmt0h/4pf\n" + "6j2Ip+b7wOc5IuMEMl8xwTyjuX3lsLbAZyFI9RCyofwA9NqIZ1GeB6Zd196rubQp\n" +
"ZumhNAbOBj753mNCMnNLo/+OAQNPR5QIGhjd4zMgUJT0e9GnQok7V98=\n" + "93cmBqGGjZUs3wMrGlm7xdjlX6GQ9UvmvkMub9+lL99A5W50QgCmFeI=\n" +
"-----END CERTIFICATE-----\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 @Inject
private KeystoreDao _ksDao; private KeystoreDao _ksDao;
@ -1250,6 +1326,12 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
KeystoreVO ksVo = _ksDao.findByName(CERTIFICATE_NAME); KeystoreVO ksVo = _ksDao.findByName(CERTIFICATE_NAME);
if (ksVo == null) { if (ksVo == null) {
_ksDao.save(CERTIFICATE_NAME, certContent, keyContent, "realhostip.com"); _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(); lock.unlock();
} }

View File

@ -18,9 +18,14 @@
package com.cloud.keystore; package com.cloud.keystore;
import java.util.List;
import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDao;
public interface KeystoreDao extends GenericDao<KeystoreVO, Long> { public interface KeystoreDao extends GenericDao<KeystoreVO, Long> {
KeystoreVO findByName(String name); KeystoreVO findByName(String name);
void save(String name, String certificate, String key, String domainSuffix); void save(String name, String certificate, String key, String domainSuffix);
void save(String alias, String certificate, Integer index,
String domainSuffix);
List<KeystoreVO> findCertChain();
} }

View File

@ -18,6 +18,8 @@
package com.cloud.keystore; package com.cloud.keystore;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.Comparator;
import java.util.List;
import javax.ejb.Local; 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.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import edu.emory.mathcs.backport.java.util.Collections;
@Local(value={KeystoreDao.class}) @Local(value={KeystoreDao.class})
public class KeystoreDaoImpl extends GenericDaoBase<KeystoreVO, Long> implements KeystoreDao { public class KeystoreDaoImpl extends GenericDaoBase<KeystoreVO, Long> implements KeystoreDao {
protected final SearchBuilder<KeystoreVO> FindByNameSearch; protected final SearchBuilder<KeystoreVO> FindByNameSearch;
protected final SearchBuilder<KeystoreVO> CertChainSearch;
public KeystoreDaoImpl() { public KeystoreDaoImpl() {
FindByNameSearch = createSearchBuilder(); FindByNameSearch = createSearchBuilder();
FindByNameSearch.and("name", FindByNameSearch.entity().getName(), Op.EQ); FindByNameSearch.and("name", FindByNameSearch.entity().getName(), Op.EQ);
FindByNameSearch.done(); FindByNameSearch.done();
CertChainSearch = createSearchBuilder();
CertChainSearch.and("key", CertChainSearch.entity().getKey(), Op.NULL);
CertChainSearch.done();
}
@Override
public List<KeystoreVO> findCertChain() {
SearchCriteria<KeystoreVO> sc = CertChainSearch.create();
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 @Override
@ -72,4 +93,24 @@ public class KeystoreDaoImpl extends GenericDaoBase<KeystoreVO, Long> implements
throw new CloudRuntimeException("Unable to save certificate under name " + name + " due to exception", e); 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);
}
}
} }

View File

@ -18,10 +18,14 @@
package com.cloud.keystore; package com.cloud.keystore;
import com.cloud.agent.api.SecStorageSetupCommand.Certificates;
import com.cloud.utils.component.Manager; import com.cloud.utils.component.Manager;
public interface KeystoreManager extends Manager { public interface KeystoreManager extends Manager {
boolean validateCertificate(String certificate, String key, String domainSuffix); boolean validateCertificate(String certificate, String key, String domainSuffix);
void saveCertificate(String name, String certificate, String key, String domainSuffix); void saveCertificate(String name, String certificate, String key, String domainSuffix);
byte[] getKeystoreBits(String name, String aliasForCertificateInStore, String storePassword); byte[] getKeystoreBits(String name, String aliasForCertificateInStore, String storePassword);
void saveCertificate(String name, String certificate, Integer index,
String domainSuffix);
Certificates getCertificates(String name);
} }

View File

@ -23,6 +23,8 @@ import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -32,6 +34,8 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger; 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.component.Inject;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.security.CertificateHelper; import com.cloud.utils.security.CertificateHelper;
@ -99,6 +103,17 @@ public class KeystoreManagerImpl implements KeystoreManager {
_ksDao.save(name, certificate, key, domainSuffix); _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 @Override
public byte[] getKeystoreBits(String name, String aliasForCertificateInStore, String storePassword) { public byte[] getKeystoreBits(String name, String aliasForCertificateInStore, String storePassword) {
assert(name != null); assert(name != null);
@ -109,8 +124,19 @@ public class KeystoreManagerImpl implements KeystoreManager {
if(ksVo == null) if(ksVo == null)
throw new CloudRuntimeException("Unable to find keystore " + name); throw new CloudRuntimeException("Unable to find keystore " + name);
List<Ternary<String, String, String>> certs = new ArrayList<Ternary<String, String, String>>();
List<KeystoreVO> certChains = _ksDao.findCertChain();
for (KeystoreVO ks : certChains) {
Ternary<String, String, String> cert = new Ternary<String, String, String>(ks.getName(), ks.getCertificate(), null);
certs.add(cert);
}
Ternary<String, String, String> cert = new Ternary<String, String, String>(ksVo.getName(), ksVo.getCertificate(), getKeyContent(ksVo.getKey()));
certs.add(cert);
try { try {
return CertificateHelper.buildAndSaveKeystore(aliasForCertificateInStore, ksVo.getCertificate(), getKeyContent(ksVo.getKey()), storePassword); return CertificateHelper.buildAndSaveKeystore(certs, storePassword);
} catch(KeyStoreException e) { } catch(KeyStoreException e) {
s_logger.warn("Unable to build keystore for " + name + " due to KeyStoreException"); s_logger.warn("Unable to build keystore for " + name + " due to KeyStoreException");
} catch(CertificateException e) { } catch(CertificateException e) {
@ -125,6 +151,28 @@ public class KeystoreManagerImpl implements KeystoreManager {
return null; 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<KeystoreVO> 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) { private static String getKeyContent(String key) {
Pattern regex = Pattern.compile("(^[\\-]+[^\\-]+[\\-]+[\\n]?)([^\\-]+)([\\-]+[^\\-]+[\\-]+$)"); Pattern regex = Pattern.compile("(^[\\-]+[^\\-]+[\\-]+[\\n]?)([^\\-]+)([\\-]+[^\\-]+[\\-]+$)");
Matcher m = regex.matcher(key); Matcher m = regex.matcher(key);

View File

@ -44,6 +44,9 @@ public class KeystoreVO {
@Column(name="domain_suffix") @Column(name="domain_suffix")
private String domainSuffix; private String domainSuffix;
@Column(name="seq")
private Integer index;
public KeystoreVO() { public KeystoreVO() {
} }
@ -87,4 +90,12 @@ public class KeystoreVO {
public void setDomainSuffix(String domainSuffix) { public void setDomainSuffix(String domainSuffix) {
this.domainSuffix = domainSuffix; this.domainSuffix = domainSuffix;
} }
public void setIndex(Integer index) {
this.index = index;
}
public Integer getIndex() {
return this.index;
}
} }

View File

@ -2992,11 +2992,29 @@ public class ManagementServerImpl implements ManagementServer {
@Override @Override
@DB @DB
public String uploadCertificate(UploadCustomCertificateCmd cmd) { 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"); 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); _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"; 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";

View File

@ -39,6 +39,7 @@ import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand; import com.cloud.agent.api.SecStorageFirewallCfgCommand;
import com.cloud.agent.api.SecStorageSetupAnswer; import com.cloud.agent.api.SecStorageSetupAnswer;
import com.cloud.agent.api.SecStorageSetupCommand; import com.cloud.agent.api.SecStorageSetupCommand;
import com.cloud.agent.api.SecStorageSetupCommand.Certificates;
import com.cloud.agent.api.SecStorageVMSetupCommand; import com.cloud.agent.api.SecStorageVMSetupCommand;
import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand; import com.cloud.agent.api.StartupSecondaryStorageCommand;
@ -53,6 +54,7 @@ import com.cloud.cluster.ManagementServerNode;
import com.cloud.configuration.Config; import com.cloud.configuration.Config;
import com.cloud.configuration.ZoneConfig; import com.cloud.configuration.ZoneConfig;
import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenterVO;
@ -70,6 +72,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.info.RunningHostCountInfo; import com.cloud.info.RunningHostCountInfo;
import com.cloud.info.RunningHostInfoAgregator; import com.cloud.info.RunningHostInfoAgregator;
import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo; import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo;
import com.cloud.keystore.KeystoreManager;
import com.cloud.network.NetworkManager; import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO; import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.TrafficType; import com.cloud.network.Networks.TrafficType;
@ -218,6 +221,8 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
NetworkOfferingDao _networkOfferingDao; NetworkOfferingDao _networkOfferingDao;
@Inject
KeystoreManager _keystoreMgr;
private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL; private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL;
private int _secStorageVmRamSize; private int _secStorageVmRamSize;
@ -280,7 +285,13 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
List<HostVO> ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); List<HostVO> ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId);
for( HostVO ssHost : ssHosts ) { for( HostVO ssHost : ssHosts ) {
String secUrl = ssHost.getStorageUrl(); 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); Answer answer = _agentMgr.easySend(ssHostId, setupCmd);
if (answer != null && answer.getResult()) { if (answer != null && answer.getResult()) {
@ -300,7 +311,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
} else if( cssHost.getType() == Host.Type.SecondaryStorage ) { } else if( cssHost.getType() == Host.Type.SecondaryStorage ) {
List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, zoneId, State.Running); List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, zoneId, State.Running);
String secUrl = cssHost.getStorageUrl(); String secUrl = cssHost.getStorageUrl();
SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(secUrl); SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(secUrl, null);
for ( SecondaryStorageVmVO ssVm : alreadyRunning ) { for ( SecondaryStorageVmVO ssVm : alreadyRunning ) {
HostVO host = _resourceMgr.findHostByName(ssVm.getInstanceName()); HostVO host = _resourceMgr.findHostByName(ssVm.getInstanceName());
Answer answer = _agentMgr.easySend(host.getId(), setupCmd); Answer answer = _agentMgr.easySend(host.getId(), setupCmd);

View File

@ -20,23 +20,164 @@ package com.cloud.upgrade.dao;
import java.io.File; import java.io.File;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import com.cloud.consoleproxy.ConsoleProxyManagerImpl;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script; import com.cloud.utils.script.Script;
public class Upgrade2213to2214 implements DbUpgrade { public class Upgrade2213to2214 implements DbUpgrade {
final static Logger s_logger = Logger.getLogger(Upgrade2213to2214.class); final static Logger s_logger = Logger.getLogger(Upgrade2213to2214.class);
@Override @Override
public String[] getUpgradableVersionRange() { public String[] getUpgradableVersionRange() {
return new String[] { "2.2.13", "2.2.14"}; return new String[] { "2.2.13", "2.2.14"};
} }
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 @Override
public String getUpgradedVersion() { public String getUpgradedVersion() {
return "2.2.14"; return "2.2.14";
@ -47,6 +188,7 @@ public class Upgrade2213to2214 implements DbUpgrade {
return true; return true;
} }
@Override @Override
public File[] getPrepareScripts() { public File[] getPrepareScripts() {
String script = Script.findScript("", "db/schema-2213to2214.sql"); String script = Script.findScript("", "db/schema-2213to2214.sql");
@ -57,6 +199,36 @@ public class Upgrade2213to2214 implements DbUpgrade {
return new File[] { new File(script) }; return new File[] { new File(script) };
} }
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 @Override
public void performDataMigration(Connection conn) { public void performDataMigration(Connection conn) {
fixIndexes(conn); fixIndexes(conn);

View File

@ -1811,8 +1811,9 @@ CREATE TABLE `cloud`.`keystore` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(64) NOT NULL COMMENT 'unique name for the certifiation', `name` varchar(64) NOT NULL COMMENT 'unique name for the certifiation',
`certificate` text NOT NULL COMMENT 'the actual certificate being stored in the db', `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', `domain_suffix` varchar(256) NOT NULL COMMENT 'DNS domain suffix associated with the certificate',
`seq` int,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE(name) UNIQUE(name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -80,4 +80,9 @@ ALTER TABLE `cloud`.`vm_instance` MODIFY `limit_cpu_use` tinyint(1) unsigned NOT
UPDATE `cloud`.`configuration` SET `value`='false' WHERE `name`='agent.lb.enabled'; 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;

View File

@ -3,6 +3,7 @@ package com.cloud.utils.security;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.security.Key; import java.security.Key;
import java.security.KeyFactory; import java.security.KeyFactory;
@ -14,9 +15,12 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec;
import java.util.List;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import com.cloud.utils.Ternary;
public class CertificateHelper { public class CertificateHelper {
public static byte[] buildAndSaveKeystore(String alias, String cert, String privateKey, String storePassword) throws KeyStoreException, CertificateException, public static byte[] buildAndSaveKeystore(String alias, String cert, String privateKey, String storePassword) throws KeyStoreException, CertificateException,
NoSuchAlgorithmException, InvalidKeySpecException, IOException { NoSuchAlgorithmException, InvalidKeySpecException, IOException {
@ -28,6 +32,32 @@ public class CertificateHelper {
return os.toByteArray(); return os.toByteArray();
} }
public static byte[] buildAndSaveKeystore(List<Ternary<String, String, String>> 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<String, String, String> 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<String, String, String> 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 { public static KeyStore loadKeystore(byte[] ksData, String storePassword) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
assert(ksData != null); assert(ksData != null);
KeyStore ks = KeyStore.getInstance("JKS"); KeyStore ks = KeyStore.getInstance("JKS");