package com.intrbiz.bergamot.agent.manager.signer; import java.security.PublicKey; import java.security.cert.Certificate; import java.util.UUID; import org.apache.log4j.Logger; import com.intrbiz.bergamot.agent.manager.config.CertDNCfg; import com.intrbiz.bergamot.agent.manager.store.BergamotKeyStore; import com.intrbiz.bergamot.crypto.util.CertificatePair; import com.intrbiz.bergamot.crypto.util.RSAUtil; import com.intrbiz.bergamot.crypto.util.RSAUtil.KeyType; import com.intrbiz.bergamot.crypto.util.SerialNum; public class CertificateManager { private Logger logger = Logger.getLogger(CertificateManager.class); private final BergamotKeyStore keyStore; private final CertDNCfg certDN; public CertificateManager(BergamotKeyStore keyStore, CertDNCfg certDN) { this.keyStore = keyStore; this.certDN = certDN; } public String buildDN(String orgUnit, String commonName) { return RSAUtil.buildDN( this.certDN.getCountry(), this.certDN.getState(), this.certDN.getLocality(), this.certDN.getOrganisation(), orgUnit, commonName ); } public String buildRootCADN() { return this.buildDN("Bergamot Monitoring", "Bergamot Monitoring Root CA"); } public String buildSiteCADN(String siteName) { return this.buildDN("Bergamot Monitoring", siteName + " Site CA"); } public String buildDN(String commonName) { return this.buildDN("Bergamot Monitoring", commonName); } public void generateRootCA() { synchronized (this) { if (! this.keyStore.hasRootCA()) { try { logger.info("Generating Root CA: " + this.buildRootCADN()); // generate the root CA CertificatePair root = RSAUtil.generateCertificate(this.buildRootCADN(), SerialNum.randomSerialNum(), 365 * 15, 4096, KeyType.CA, null); // store this.keyStore.storeRootCA(root); } catch (Exception e) { throw new RuntimeException("Failed to generate Root CA", e); } } } } public Certificate generateSiteCA(UUID siteId, String siteName) { if (this.keyStore.hasSiteCA(siteId)) throw new RuntimeException("Certificate already exists for site: " + siteId); // first we need the root CA CertificatePair root = this.keyStore.loadRootCA(); // generate the site CA try { logger.info("Generating Site CA: " + this.buildSiteCADN(siteName)); // generate the site CA CertificatePair site = RSAUtil.generateCertificate(this.buildSiteCADN(siteName), new SerialNum(siteId, 1), 365 * 10, 2048, KeyType.INTERMEDIATE, root); // store this.keyStore.storeSiteCA(siteId, site); // return the cert return site.getCertificate(); } catch (Exception e) { throw new RuntimeException("Failed to generate Site CA", e); } } public Certificate signAgent(UUID siteId, UUID agentId, String commonName, PublicKey key) { if (! this.keyStore.hasSiteCA(siteId)) throw new RuntimeException("No certificate exists for site: " + siteId); // do we already have a agent cert if (this.keyStore.hasAgent(siteId, agentId)) { // load the current cert to get the serial number to revision CertificatePair currentCrt = this.keyStore.loadAgent(siteId, agentId); SerialNum currentSerial = SerialNum.fromBigInt(currentCrt.getCertificate().getSerialNumber()); // we need the CA to sign CertificatePair site = this.keyStore.loadSiteCA(siteId); // sign the agent cert try { String dn = this.buildDN(commonName); logger.info("Signing Agent: " + siteId + "::" + agentId + " " + dn); // sign the agent CertificatePair agent = RSAUtil.generateCertificate(dn, currentSerial.revision(), 365 * 5, 2048, KeyType.CLIENT, key, site); // store this.keyStore.storeAgent(siteId, agentId, agent); // return the cert return agent.getCertificate(); } catch (Exception e) { throw new RuntimeException("Failed to sign agent", e); } } else { // first we need the root CA CertificatePair site = this.keyStore.loadSiteCA(siteId); // sign the agent cert try { String dn = this.buildDN(commonName); logger.info("Signing Agent: " + siteId + "::" + agentId + " " + dn); // sign the agent CertificatePair agent = RSAUtil.generateCertificate(dn, SerialNum.version2(agentId, 1, SerialNum.MODE_AGENT), 365 * 5, 2048, KeyType.CLIENT, key, site); // store this.keyStore.storeAgent(siteId, agentId, agent); // return the cert return agent.getCertificate(); } catch (Exception e) { throw new RuntimeException("Failed to sign agent", e); } } } public Certificate signTemplate(UUID siteId, UUID templateId, String templateName, PublicKey key) { if (! this.keyStore.hasSiteCA(siteId)) throw new RuntimeException("No certificate exists for site: " + siteId); // do we already have a agent cert if (this.keyStore.hasTemplate(siteId, templateId)) { // load the current cert to get the serial number to revision CertificatePair currentCrt = this.keyStore.loadTemplate(siteId, templateId); SerialNum currentSerial = SerialNum.fromBigInt(currentCrt.getCertificate().getSerialNumber()); // we need the CA to sign CertificatePair site = this.keyStore.loadSiteCA(siteId); // sign the agent cert try { String dn = this.buildDN("Template: " + templateName); logger.info("Signing Template: " + siteId + "::" + templateId + " " + dn); // sign the agent CertificatePair agent = RSAUtil.generateCertificate(dn, currentSerial.revision(), 365 * 5, 2048, KeyType.CLIENT, key, site); // store this.keyStore.storeTemplate(siteId, templateId, agent); // return the cert return agent.getCertificate(); } catch (Exception e) { throw new RuntimeException("Failed to sign template", e); } } else { // first we need the root CA CertificatePair site = this.keyStore.loadSiteCA(siteId); // sign the agent cert try { String dn = this.buildDN("Template: " + templateName); logger.info("Signing Template: " + siteId + "::" + templateId + " " + dn); // sign the agent CertificatePair agent = RSAUtil.generateCertificate(dn, SerialNum.version2(templateId, 1, SerialNum.MODE_TEMPLATE), 365 * 5, 2048, KeyType.CLIENT, key, site); // store this.keyStore.storeTemplate(siteId, templateId, agent); // return the cert return agent.getCertificate(); } catch (Exception e) { throw new RuntimeException("Failed to sign agent", e); } } } public CertificatePair signServer(String commonName, PublicKey key) { if (this.keyStore.hasServer(commonName)) { // load the old cert to revision the serial CertificatePair current = this.keyStore.loadServer(commonName); SerialNum currentSerial = SerialNum.fromBigInt(current.getCertificate().getSerialNumber()); // we need the root CA to sign CertificatePair root = this.keyStore.loadRootCA(); // sign the cert incrementing the serial try { logger.info("Signing Server: " + commonName + " " + this.buildDN(commonName)); // sign the agent CertificatePair server = RSAUtil.generateCertificate(this.buildDN(commonName), currentSerial.revision(), 365 * 5, 2048, KeyType.SERVER, key, root); // store this.keyStore.storeServer(commonName, server); // return the cert return server; } catch (Exception e) { throw new RuntimeException("Failed to sign agent", e); } } else { // first we need the root CA CertificatePair root = this.keyStore.loadRootCA(); // sign the server cert try { logger.info("Signing Server: " + commonName + " " + this.buildDN(commonName)); // sign the agent CertificatePair server = RSAUtil.generateCertificate(this.buildDN(commonName), SerialNum.fromName(commonName), 365 * 5, 2048, KeyType.SERVER, key, root); // store this.keyStore.storeServer(commonName, server); // return the cert return server; } catch (Exception e) { throw new RuntimeException("Failed to sign agent", e); } } } }