Use existing certificate instead of doing the process all the time
This commit is contained in:
parent
d9ce3af5aa
commit
c197606204
2 changed files with 92 additions and 31 deletions
|
|
@ -20,6 +20,8 @@ import zutil.plugin.PluginData;
|
|||
import zutil.plugin.PluginManager;
|
||||
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
|
@ -80,37 +82,46 @@ public class HalServer {
|
|||
// Initialize External HttpServer
|
||||
// ------------------------------------
|
||||
|
||||
if (HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_PORT) &&
|
||||
HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_DOMAIN)) {
|
||||
AcmeClient acme;
|
||||
HttpServer tmpHttpServer = null;
|
||||
if (HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_DOMAIN) && HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_PORT)) {
|
||||
String externalServerUrl = "https://" + HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_DOMAIN) +
|
||||
":" + HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_PORT);
|
||||
|
||||
if ("dns".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, ""))) {
|
||||
acme = new AcmeClient(new HalAcmeDataStore(), new AcmeManualDnsChallengeFactory(), AcmeClient.ACME_SERVER_LETSENCRYPT_STAGING);
|
||||
} else if ("http".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, "http"))) {
|
||||
tmpHttpServer = new HttpServer(80);
|
||||
tmpHttpServer.start();
|
||||
HalAcmeDataStore acmeDataStore = new HalAcmeDataStore();
|
||||
X509Certificate certificate = acmeDataStore.getCertificate();
|
||||
|
||||
acme = new AcmeClient(new HalAcmeDataStore(), new AcmeHttpChallengeFactory(tmpHttpServer), AcmeClient.ACME_SERVER_LETSENCRYPT_STAGING);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown config value for " + HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE + ": " +
|
||||
HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE));
|
||||
if (!AcmeClient.isCertificateValid(certificate)) {
|
||||
// Prepare ACME Client
|
||||
AcmeClient acme;
|
||||
HttpServer tmpHttpServer = null;
|
||||
|
||||
if ("dns".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, ""))) {
|
||||
acme = new AcmeClient(acmeDataStore, new AcmeManualDnsChallengeFactory(), AcmeClient.ACME_SERVER_LETSENCRYPT_STAGING);
|
||||
} else if ("http".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, "http"))) {
|
||||
tmpHttpServer = new HttpServer(80);
|
||||
tmpHttpServer.start();
|
||||
|
||||
acme = new AcmeClient(acmeDataStore, new AcmeHttpChallengeFactory(tmpHttpServer), AcmeClient.ACME_SERVER_LETSENCRYPT_STAGING);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown config value for " + externalServerUrl);
|
||||
}
|
||||
|
||||
// Request certificate and start the external webserver
|
||||
|
||||
acme.addDomain(HalContext.getStringProperty(CONFIG_HTTP_EXTERNAL_DOMAIN));
|
||||
acme.prepareRequest();
|
||||
certificate = acme.requestCertificate();
|
||||
acmeDataStore.storeCertificate(certificate);
|
||||
|
||||
// Cleanup
|
||||
if (tmpHttpServer != null) {
|
||||
tmpHttpServer.close();
|
||||
}
|
||||
}
|
||||
|
||||
acme.addDomain(HalContext.getStringProperty(CONFIG_HTTP_EXTERNAL_DOMAIN));
|
||||
acme.prepareRequest();
|
||||
Certificate certificate = acme.requestCertificate();
|
||||
|
||||
httpExternal = new HttpServer(HalContext.getIntegerProperty(CONFIG_HTTP_EXTERNAL_PORT), certificate);
|
||||
httpExternal.start();
|
||||
|
||||
// Cleanup
|
||||
|
||||
if ("http".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, "http"))) {
|
||||
tmpHttpServer.close();
|
||||
}
|
||||
|
||||
logger.info("External https server up and running at: https://" + HalContext.getStringProperty(CONFIG_HTTP_EXTERNAL_DOMAIN) + ":" + HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_PORT));
|
||||
logger.info("External https server up and running at: " + externalServerUrl);
|
||||
} else {
|
||||
logger.warning("Missing '" + CONFIG_HTTP_EXTERNAL_PORT + "' and '" + CONFIG_HTTP_EXTERNAL_DOMAIN + "' configuration, will not setup external http server.");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,30 +1,53 @@
|
|||
package se.hal.util;
|
||||
|
||||
import org.shredzone.acme4j.toolbox.AcmeUtils;
|
||||
import org.shredzone.acme4j.util.KeyPairUtils;
|
||||
import se.hal.HalContext;
|
||||
import zutil.io.StringInputStream;
|
||||
import zutil.log.LogUtil;
|
||||
import zutil.net.acme.AcmeDataStore;
|
||||
import zutil.parser.Base64Decoder;
|
||||
import zutil.parser.Base64Encoder;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.KeyPair;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class HalAcmeDataStore implements AcmeDataStore {
|
||||
private static final Logger logger = LogUtil.getLogger();
|
||||
|
||||
private static final String CONFIG_HTTP_EXTERNAL_USER_KEY = "hal_core.http_external_user_key";
|
||||
private static final String CONFIG_HTTP_EXTERNAL_DOMAIN_KEY = "hal_core.http_external_domain_key";
|
||||
private static final String CONFIG_HTTP_EXTERNAL_ACCOUNT_LOCATION = "hal_core.http_external_account_location";
|
||||
private static final String CONFIG_HTTP_EXTERNAL_ACCOUNT_KEY = "hal_core.http_external_account_key";
|
||||
private static final String CONFIG_HTTP_EXTERNAL_DOMAIN_KEY = "hal_core.http_external_domain_key";
|
||||
private static final String CONFIG_HTTP_EXTERNAL_CERTIFICATE = "hal_core.http_external_certificate";
|
||||
|
||||
|
||||
@Override
|
||||
public KeyPair loadUserKeyPair() {
|
||||
return loadKeyPair(CONFIG_HTTP_EXTERNAL_USER_KEY);
|
||||
public URL getAccountLocation() {
|
||||
try {
|
||||
if (HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_ACCOUNT_LOCATION))
|
||||
return new URL(HalContext.getStringProperty(CONFIG_HTTP_EXTERNAL_ACCOUNT_LOCATION));
|
||||
} catch (MalformedURLException e) {
|
||||
logger.log(Level.SEVERE, "Unable to create account URL.", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyPair loadDomainKeyPair() {
|
||||
public KeyPair getAccountKeyPair() {
|
||||
return loadKeyPair(CONFIG_HTTP_EXTERNAL_ACCOUNT_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyPair getDomainKeyPair() {
|
||||
return loadKeyPair(CONFIG_HTTP_EXTERNAL_DOMAIN_KEY);
|
||||
}
|
||||
|
||||
|
|
@ -43,8 +66,9 @@ public class HalAcmeDataStore implements AcmeDataStore {
|
|||
|
||||
|
||||
@Override
|
||||
public void storeUserKeyPair(KeyPair keyPair) {
|
||||
storeKeyPair(keyPair, CONFIG_HTTP_EXTERNAL_USER_KEY);
|
||||
public void storeAccountKeyPair(URL accountLocation, KeyPair accountKeyPair) {
|
||||
HalContext.setProperty(CONFIG_HTTP_EXTERNAL_ACCOUNT_LOCATION, accountLocation.toString());
|
||||
storeKeyPair(accountKeyPair, CONFIG_HTTP_EXTERNAL_ACCOUNT_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -63,4 +87,30 @@ public class HalAcmeDataStore implements AcmeDataStore {
|
|||
logger.log(Level.SEVERE, "Was unable to store KeyPair to DB.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public X509Certificate getCertificate() {
|
||||
if (HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_CERTIFICATE)) {
|
||||
try {
|
||||
CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
||||
X509Certificate certificate = (X509Certificate) factory.generateCertificate(
|
||||
new StringInputStream(HalContext.getStringProperty(CONFIG_HTTP_EXTERNAL_CERTIFICATE)));
|
||||
return certificate;
|
||||
} catch (CertificateException e) {
|
||||
logger.log(Level.SEVERE, "Was unable to read certificate from DB.", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeCertificate(X509Certificate certificate) {
|
||||
try (StringWriter out = new StringWriter()) {
|
||||
AcmeUtils.writeToPem(certificate.getEncoded(), AcmeUtils.PemLabel.CERTIFICATE, out);
|
||||
HalContext.setProperty(CONFIG_HTTP_EXTERNAL_CERTIFICATE, out.toString());
|
||||
} catch (IOException | CertificateEncodingException e) {
|
||||
logger.log(Level.SEVERE, "Was unable to store certificate to DB.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue