diff --git a/server/src/com/cloud/keystore/KeystoreDao.java b/server/src/com/cloud/keystore/KeystoreDao.java
new file mode 100644
index 00000000000..d1b2889eb9e
--- /dev/null
+++ b/server/src/com/cloud/keystore/KeystoreDao.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package com.cloud.keystore;
+
+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);
+}
diff --git a/server/src/com/cloud/keystore/KeystoreDaoImpl.java b/server/src/com/cloud/keystore/KeystoreDaoImpl.java
new file mode 100644
index 00000000000..d7a15d3de68
--- /dev/null
+++ b/server/src/com/cloud/keystore/KeystoreDaoImpl.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+package com.cloud.keystore;
+
+import java.sql.PreparedStatement;
+
+import javax.ejb.Local;
+
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@Local(value={KeystoreDao.class})
+public class KeystoreDaoImpl extends GenericDaoBase implements KeystoreDao {
+
+ protected final SearchBuilder FindByNameSearch;
+
+ public KeystoreDaoImpl() {
+ FindByNameSearch = createSearchBuilder();
+ FindByNameSearch.and("name", FindByNameSearch.entity().getName(), Op.EQ);
+ FindByNameSearch.done();
+ }
+
+ @Override
+ public KeystoreVO findByName(String name) {
+ assert(name != null);
+
+ SearchCriteria sc = FindByNameSearch.create();
+ sc.setParameters("name", name);
+ return findOneBy(sc);
+ }
+
+
+ @Override
+ @DB
+ public void save(String name, String certificate, String key, String domainSuffix) {
+ Transaction txn = Transaction.currentTxn();
+ try {
+ txn.start();
+
+ String sql = "INSERT INTO keystore (`name`, `certificate`, `key`, `domain_suffix`) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE `certificate`=?, `key`=?, `domain_suffix`=?";
+ PreparedStatement pstmt = txn.prepareAutoCloseStatement(sql);
+ pstmt.setString(1, name);
+ pstmt.setString(2, certificate);
+ pstmt.setString(3, key);
+ pstmt.setString(4, domainSuffix);
+ pstmt.setString(5, certificate);
+ pstmt.setString(6, key);
+ pstmt.setString(7, domainSuffix);
+
+ pstmt.executeUpdate();
+ txn.commit();
+ } catch(Exception e) {
+ txn.rollback();
+ throw new CloudRuntimeException("Unable to save certificate under name " + name + " due to exception", e);
+ }
+ }
+}
diff --git a/server/src/com/cloud/keystore/KeystoreManager.java b/server/src/com/cloud/keystore/KeystoreManager.java
new file mode 100644
index 00000000000..79e4db49a22
--- /dev/null
+++ b/server/src/com/cloud/keystore/KeystoreManager.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package com.cloud.keystore;
+
+import com.cloud.utils.component.Manager;
+
+public interface KeystoreManager extends Manager {
+ void saveCertificate(String name, String certificate, String key, String domainSuffix);
+ byte[] getKeystoreBits(String name, String aliasForCertificateInStore, String storePassword);
+}
diff --git a/server/src/com/cloud/keystore/KeystoreManagerImpl.java b/server/src/com/cloud/keystore/KeystoreManagerImpl.java
new file mode 100644
index 00000000000..cad54c57a4d
--- /dev/null
+++ b/server/src/com/cloud/keystore/KeystoreManagerImpl.java
@@ -0,0 +1,114 @@
+/**
+ * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+package com.cloud.keystore;
+
+import java.io.IOException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.component.Inject;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.security.CertificateHelper;
+
+@Local(value=KeystoreManager.class)
+public class KeystoreManagerImpl implements KeystoreManager {
+ private static final Logger s_logger = Logger.getLogger(KeystoreManagerImpl.class);
+
+ private String _name;
+ @Inject private KeystoreDao _ksDao;
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ _name = name;
+
+ return true;
+ }
+
+ @Override
+ public boolean start() {
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return _name;
+ }
+
+ @Override
+ public void saveCertificate(String name, String certificate, String key, String domainSuffix) {
+ if(name == null || name.isEmpty() ||
+ certificate == null || certificate.isEmpty() ||
+ key == null || key.isEmpty() ||
+ domainSuffix == null || domainSuffix.isEmpty())
+ throw new CloudRuntimeException("invalid parameter in saveCerticate");
+
+
+ _ksDao.save(name, certificate, key, domainSuffix);
+ }
+
+ @Override
+ public byte[] getKeystoreBits(String name, String aliasForCertificateInStore, String storePassword) {
+ assert(name != null);
+ assert(aliasForCertificateInStore != null);
+ assert(storePassword != null);
+
+ KeystoreVO ksVo = _ksDao.findByName(name);
+ if(ksVo == null)
+ throw new CloudRuntimeException("Unable to find keystore " + name);
+
+ try {
+ return CertificateHelper.buildAndSaveKeystore(aliasForCertificateInStore, ksVo.getCertificate(), getKeyContent(ksVo.getKey()), storePassword);
+ } catch(KeyStoreException e) {
+ s_logger.warn("Unable to build keystore for " + name + " due to KeyStoreException");
+ } catch(CertificateException e) {
+ s_logger.warn("Unable to build keystore for " + name + " due to CertificateException");
+ } catch(NoSuchAlgorithmException e) {
+ s_logger.warn("Unable to build keystore for " + name + " due to NoSuchAlgorithmException");
+ } catch(InvalidKeySpecException e) {
+ s_logger.warn("Unable to build keystore for " + name + " due to InvalidKeySpecException");
+ } catch(IOException e) {
+ s_logger.warn("Unable to build keystore for " + name + " due to IOException");
+ }
+ return null;
+ }
+
+ private static String getKeyContent(String key) {
+ Pattern regex = Pattern.compile("(^[\\-]+[^\\-]+[\\-]+[\\n]?)([^\\-]+)([\\-]+[^\\-]+[\\-]+$)");
+ Matcher m = regex.matcher(key);
+ if(m.find())
+ return m.group(2);
+
+ return key;
+ }
+}
+
diff --git a/server/src/com/cloud/keystore/KeystoreVO.java b/server/src/com/cloud/keystore/KeystoreVO.java
new file mode 100644
index 00000000000..52e10b85fe1
--- /dev/null
+++ b/server/src/com/cloud/keystore/KeystoreVO.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package com.cloud.keystore;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="keystore")
+public class KeystoreVO {
+ @Id
+ @GeneratedValue(strategy=GenerationType.IDENTITY)
+ @Column(name="id")
+ private Long id;
+
+ @Column(name="name")
+ private String name;
+
+ @Column(name="certificate",length=65535)
+ private String certificate;
+
+ @Column(name="key",length=65535)
+ private String key;
+
+ @Column(name="domain_suffix")
+ private String domainSuffix;
+
+ public KeystoreVO() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getCertificate() {
+ return certificate;
+ }
+
+ public void setCertificate(String certificate) {
+ this.certificate = certificate;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getDomainSuffix() {
+ return domainSuffix;
+ }
+
+ public void setDomainSuffix(String domainSuffix) {
+ this.domainSuffix = domainSuffix;
+ }
+}
diff --git a/server/test/com/cloud/keystore/KeystoreTest.java b/server/test/com/cloud/keystore/KeystoreTest.java
new file mode 100644
index 00000000000..d33bd906459
--- /dev/null
+++ b/server/test/com/cloud/keystore/KeystoreTest.java
@@ -0,0 +1,157 @@
+/**
+ * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+package com.cloud.keystore;
+
+import java.security.KeyStore;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import junit.framework.TestCase;
+
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.Before;
+
+import com.cloud.configuration.DefaultInterceptorLibrary;
+import com.cloud.utils.component.ComponentLocator;
+import com.cloud.utils.component.MockComponentLocator;
+import com.cloud.utils.security.CertificateHelper;
+
+public class KeystoreTest extends TestCase {
+ private final static Logger s_logger = Logger.getLogger(KeystoreTest.class);
+
+ private String keyContent =
+ "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALV5vGlkiWwoZX4hTRplPXP8qtST\n" +
+ "hwZhko8noeY5vf8ECwmd+vrCTw/JvnOtkx/8oYNbg/SeUt1EfOsk6gqJdBblGFBZRMcUJlIpqE9z\n" +
+ "uv68U9G8Gfi/qvRSY336hibw0J5bZ4vn1QqmyHDB+Czea9AjFUV7AEVG15+vED7why+/AgMBAAEC\n" +
+ "gYBmFBPnNKYYMKDmUdUNA+WNWJK/ADzzWe8WlzR6TACTcbLDthl289WFC/YVG42mcHRpbxDKiEQU\n" +
+ "MnIR0rHTO34Qb/2HcuyweStU2gqR6omxBvMnFpJr90nD1HcOMJzeLHsphau0/EmKKey+gk4PyieD\n" +
+ "KqTM7LTjjHv8xPM4n+WAAQJBAOMNCeFKlJ4kMokWhU74B5/w/NGyT1BHUN0VmilHSiJC8JqS4BiI\n" +
+ "ZpAeET3VmilO6QTGh2XVhEDGteu3uZR6ipUCQQDMnRzMgQ/50LFeIQo4IBtwlEouczMlPQF4c21R\n" +
+ "1d720moxILVPT0NJZTQUDDmmgbL+B7CgtcCR2NlP5sKPZVADAkEAh4Xq1cy8dMBKYcVNgNtPQcqI\n" +
+ "PWpfKR3ISI5yXB0vRNAL6Vet5zbTcUZhKDVtNSbis3UEsGYH8NorEC2z2cpjGQJANhJi9Ow6c5Mh\n" +
+ "/DURBUn+1l5pyCKrZnDbvaALSLATLvjmFTuGjoHszy2OeKnOZmEqExWnKKE/VYuPyhy6V7i3TwJA\n" +
+ "f8skDgtPK0OsBCa6IljPaHoWBjPc4kFkSTSS1d56hUcWSikTmiuKdLyBb85AADSZYsvHWrte4opN\n" +
+ "dhNukMJuRA==\n";
+
+ private String certContent =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIE3jCCA8agAwIBAgIFAqv56tIwDQYJKoZIhvcNAQEFBQAwgcoxCzAJBgNVBAYT\n" +
+ "AlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYD\n" +
+ "VQQKExFHb0RhZGR5LmNvbSwgSW5jLjEzMDEGA1UECxMqaHR0cDovL2NlcnRpZmlj\n" +
+ "YXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5MTAwLgYDVQQDEydHbyBEYWRkeSBT\n" +
+ "ZWN1cmUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxETAPBgNVBAUTCDA3OTY5Mjg3\n" +
+ "MB4XDTA5MDIxMTA0NTc1NloXDTEyMDIwNzA1MTEyM1owWTEZMBcGA1UECgwQKi5y\n" +
+ "ZWFsaG9zdGlwLmNvbTEhMB8GA1UECwwYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVk\n" +
+ "MRkwFwYDVQQDDBAqLnJlYWxob3N0aXAuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GN\n" +
+ "ADCBiQKBgQC1ebxpZIlsKGV+IU0aZT1z/KrUk4cGYZKPJ6HmOb3/BAsJnfr6wk8P\n" +
+ "yb5zrZMf/KGDW4P0nlLdRHzrJOoKiXQW5RhQWUTHFCZSKahPc7r+vFPRvBn4v6r0\n" +
+ "UmN9+oYm8NCeW2eL59UKpshwwfgs3mvQIxVFewBFRtefrxA+8IcvvwIDAQABo4IB\n" +
+ "vTCCAbkwDwYDVR0TAQH/BAUwAwEBADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\n" +
+ "BQUHAwIwDgYDVR0PAQH/BAQDAgWgMDIGA1UdHwQrMCkwJ6AloCOGIWh0dHA6Ly9j\n" +
+ "cmwuZ29kYWRkeS5jb20vZ2RzMS0yLmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0B\n" +
+ "BxcBMDkwNwYIKwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j\n" +
+ "b20vcmVwb3NpdG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0\n" +
+ "cDovL29jc3AuZ29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlm\n" +
+ "aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNy\n" +
+ "dDAfBgNVHSMEGDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zArBgNVHREEJDAighAq\n" +
+ "LnJlYWxob3N0aXAuY29tgg5yZWFsaG9zdGlwLmNvbTAdBgNVHQ4EFgQUHxwmdK5w\n" +
+ "9/YVeZ/3fHyi6nQfzoYwDQYJKoZIhvcNAQEFBQADggEBABv/XinvId6oWXJtmku+\n" +
+ "7m90JhSVH0ycoIGjgdaIkcExQGP08MCilbUsPcbhLheSFdgn/cR4e1MP083lacoj\n" +
+ "OGauY7b8f/cuquGkT49Ns14awPlEzRjjycQEjjLxFEuL5CFWa2t2gKRE1dSfhDQ+\n" +
+ "fJ6GBCs1XgZLuhkKS8fPf+YmG2ZjHzYDjYoSx7paDXgEm+kbYIZdCK51lA0BUAjP\n" +
+ "9ZMGhsu/PpAbh5U/DtcIqxY0xeqD4TeGsBzXg6uLhv+jKHDtXg5fYPe+z0n5DCEL\n" +
+ "k0fLF4+i/pt9hVCz0QrZ28RUhXf825+EOL0Gw+Uzt+7RV2cCaJrlu4cDrDom2FRy\n" +
+ "E8I=\n" +
+ "-----END CERTIFICATE-----\n";
+
+ @Override
+ @Before
+ public void setUp() {
+ MockComponentLocator locator = new MockComponentLocator("management-server");
+ locator.addDao("keystoreDao", KeystoreDaoImpl.class);
+ locator.addManager("KeystoreManager", KeystoreManagerImpl.class);
+ locator.makeActive(new DefaultInterceptorLibrary());
+ }
+
+ @Override
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ public void testKeystoreSave() throws Exception {
+ KeystoreVO ksVo;
+
+ ComponentLocator locator = ComponentLocator.getCurrentLocator();
+
+ KeystoreDao ksDao = locator.getDao(KeystoreDao.class);
+ ksDao.save("CPVMCertificate", "CPVMCertificate", "KeyForCertificate", "realhostip.com");
+ ksVo = ksDao.findByName("CPVMCertificate");
+ assertTrue(ksVo != null);
+ assertTrue(ksVo.getCertificate().equals("CPVMCertificate"));
+ assertTrue(ksVo.getKey().equals("KeyForCertificate"));
+ assertTrue(ksVo.getDomainSuffix().equals("realhostip.com"));
+
+ ksDao.save("CPVMCertificate", "CPVMCertificate Again", "KeyForCertificate Again", "again.realhostip.com");
+
+ ksVo = ksDao.findByName("CPVMCertificate");
+ assertTrue(ksVo != null);
+ assertTrue(ksVo.getCertificate().equals("CPVMCertificate Again"));
+ assertTrue(ksVo.getKey().equals("KeyForCertificate Again"));
+ assertTrue(ksVo.getDomainSuffix().equals("again.realhostip.com"));
+
+ ksDao.expunge(ksVo.getId());
+ }
+
+ public void testStripeKey() throws Exception {
+ Pattern regex = Pattern.compile("(^[\\-]+[^\\-]+[\\-]+[\\n]?)([^\\-]+)([\\-]+[^\\-]+[\\-]+$)");
+ Matcher m = regex.matcher("-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAm4bLUORp9oM65GV9XrPrbs+K563DjUR1M8mP1HaE+Y4lX5pk\nvQjC/xoEqSs5pxDDWXAkoexvxij8A4AWcsKU1Q+ep2E+GcytBoz8XINGvgb8cQNn\n/4PlVWKp7j5SDDNCfleYvmiRn8k6P4mxVJOHKzwb/IwQcKghyqAF1w==\n-----END RSA PRIVATE KEY-----");
+ if(m.find()) {
+ String content = m.group(2);
+ assertTrue(content.startsWith("MIIEpAIBAAKCAQE"));
+ assertTrue(content.endsWith("KghyqAF1w==\n"));
+ } else {
+ assertTrue(false);
+ }
+ }
+
+ public void testKeystoreManager() throws Exception {
+ ComponentLocator locator = ComponentLocator.getCurrentLocator();
+
+ KeystoreManagerImpl ksMgr = ComponentLocator.inject(KeystoreManagerImpl.class);
+ assertTrue(ksMgr.configure("TaskManager", new HashMap()));
+ assertTrue(ksMgr.start());
+
+ ksMgr.saveCertificate("CPVMCertificate", certContent, keyContent, "realhostip.com");
+
+ byte[] ksBits = ksMgr.getKeystoreBits("CPVMCertificate", "realhostip", "vmops.com");
+ assertTrue(ksBits != null);
+
+ try {
+ KeyStore ks = CertificateHelper.loadKeystore(ksBits, "vmops.com");
+ assertTrue(ks != null);
+ } catch(Exception e) {
+ assertTrue(false);
+ }
+
+ KeystoreDao ksDao = locator.getDao(KeystoreDao.class);
+ KeystoreVO ksVo = ksDao.findByName("CPVMCertificate");
+ ksDao.expunge(ksVo.getId());
+ }
+}
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index a7f7fbb529d..0c635b3426e 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -1494,4 +1494,14 @@ CREATE TABLE `cloud`.`cmd_exec_log` (
CONSTRAINT `fk_cmd_exec_log_ref__inst_id` FOREIGN KEY (`instance_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+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',
+ `domain_suffix` varchar(256) NOT NULL COMMENT 'DNS domain suffix associated with the certificate',
+ PRIMARY KEY (`id`),
+ UNIQUE(name)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
SET foreign_key_checks = 1;