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 zutil.plugin.PluginManager;
|
||||||
|
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
@ -80,37 +82,46 @@ public class HalServer {
|
||||||
// Initialize External HttpServer
|
// Initialize External HttpServer
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
if (HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_PORT) &&
|
if (HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_DOMAIN) && HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_PORT)) {
|
||||||
HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_DOMAIN)) {
|
String externalServerUrl = "https://" + HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_DOMAIN) +
|
||||||
|
":" + HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_PORT);
|
||||||
|
|
||||||
|
HalAcmeDataStore acmeDataStore = new HalAcmeDataStore();
|
||||||
|
X509Certificate certificate = acmeDataStore.getCertificate();
|
||||||
|
|
||||||
|
if (!AcmeClient.isCertificateValid(certificate)) {
|
||||||
|
// Prepare ACME Client
|
||||||
AcmeClient acme;
|
AcmeClient acme;
|
||||||
HttpServer tmpHttpServer = null;
|
HttpServer tmpHttpServer = null;
|
||||||
|
|
||||||
if ("dns".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, ""))) {
|
if ("dns".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, ""))) {
|
||||||
acme = new AcmeClient(new HalAcmeDataStore(), new AcmeManualDnsChallengeFactory(), AcmeClient.ACME_SERVER_LETSENCRYPT_STAGING);
|
acme = new AcmeClient(acmeDataStore, new AcmeManualDnsChallengeFactory(), AcmeClient.ACME_SERVER_LETSENCRYPT_STAGING);
|
||||||
} else if ("http".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, "http"))) {
|
} else if ("http".equals(HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE, "http"))) {
|
||||||
tmpHttpServer = new HttpServer(80);
|
tmpHttpServer = new HttpServer(80);
|
||||||
tmpHttpServer.start();
|
tmpHttpServer.start();
|
||||||
|
|
||||||
acme = new AcmeClient(new HalAcmeDataStore(), new AcmeHttpChallengeFactory(tmpHttpServer), AcmeClient.ACME_SERVER_LETSENCRYPT_STAGING);
|
acme = new AcmeClient(acmeDataStore, new AcmeHttpChallengeFactory(tmpHttpServer), AcmeClient.ACME_SERVER_LETSENCRYPT_STAGING);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Unknown config value for " + HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE + ": " +
|
throw new IllegalArgumentException("Unknown config value for " + externalServerUrl);
|
||||||
HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_ACME_TYPE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Request certificate and start the external webserver
|
||||||
|
|
||||||
acme.addDomain(HalContext.getStringProperty(CONFIG_HTTP_EXTERNAL_DOMAIN));
|
acme.addDomain(HalContext.getStringProperty(CONFIG_HTTP_EXTERNAL_DOMAIN));
|
||||||
acme.prepareRequest();
|
acme.prepareRequest();
|
||||||
Certificate certificate = acme.requestCertificate();
|
certificate = acme.requestCertificate();
|
||||||
|
acmeDataStore.storeCertificate(certificate);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
if (tmpHttpServer != null) {
|
||||||
|
tmpHttpServer.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
httpExternal = new HttpServer(HalContext.getIntegerProperty(CONFIG_HTTP_EXTERNAL_PORT), certificate);
|
httpExternal = new HttpServer(HalContext.getIntegerProperty(CONFIG_HTTP_EXTERNAL_PORT), certificate);
|
||||||
httpExternal.start();
|
httpExternal.start();
|
||||||
|
|
||||||
// Cleanup
|
logger.info("External https server up and running at: " + externalServerUrl);
|
||||||
|
|
||||||
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));
|
|
||||||
} else {
|
} else {
|
||||||
logger.warning("Missing '" + CONFIG_HTTP_EXTERNAL_PORT + "' and '" + CONFIG_HTTP_EXTERNAL_DOMAIN + "' configuration, will not setup external http server.");
|
logger.warning("Missing '" + CONFIG_HTTP_EXTERNAL_PORT + "' and '" + CONFIG_HTTP_EXTERNAL_DOMAIN + "' configuration, will not setup external http server.");
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,53 @@
|
||||||
package se.hal.util;
|
package se.hal.util;
|
||||||
|
|
||||||
|
import org.shredzone.acme4j.toolbox.AcmeUtils;
|
||||||
import org.shredzone.acme4j.util.KeyPairUtils;
|
import org.shredzone.acme4j.util.KeyPairUtils;
|
||||||
import se.hal.HalContext;
|
import se.hal.HalContext;
|
||||||
|
import zutil.io.StringInputStream;
|
||||||
import zutil.log.LogUtil;
|
import zutil.log.LogUtil;
|
||||||
import zutil.net.acme.AcmeDataStore;
|
import zutil.net.acme.AcmeDataStore;
|
||||||
import zutil.parser.Base64Decoder;
|
import zutil.parser.Base64Decoder;
|
||||||
import zutil.parser.Base64Encoder;
|
import zutil.parser.Base64Encoder;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.security.KeyPair;
|
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.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class HalAcmeDataStore implements AcmeDataStore {
|
public class HalAcmeDataStore implements AcmeDataStore {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
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_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_DOMAIN_KEY = "hal_core.http_external_domain_key";
|
||||||
|
private static final String CONFIG_HTTP_EXTERNAL_CERTIFICATE = "hal_core.http_external_certificate";
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyPair loadUserKeyPair() {
|
public URL getAccountLocation() {
|
||||||
return loadKeyPair(CONFIG_HTTP_EXTERNAL_USER_KEY);
|
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
|
@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);
|
return loadKeyPair(CONFIG_HTTP_EXTERNAL_DOMAIN_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,8 +66,9 @@ public class HalAcmeDataStore implements AcmeDataStore {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeUserKeyPair(KeyPair keyPair) {
|
public void storeAccountKeyPair(URL accountLocation, KeyPair accountKeyPair) {
|
||||||
storeKeyPair(keyPair, CONFIG_HTTP_EXTERNAL_USER_KEY);
|
HalContext.setProperty(CONFIG_HTTP_EXTERNAL_ACCOUNT_LOCATION, accountLocation.toString());
|
||||||
|
storeKeyPair(accountKeyPair, CONFIG_HTTP_EXTERNAL_ACCOUNT_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -63,4 +87,30 @@ public class HalAcmeDataStore implements AcmeDataStore {
|
||||||
logger.log(Level.SEVERE, "Was unable to store KeyPair to DB.", e);
|
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