diff --git a/hal-core/src/se/hal/HalServer.java b/hal-core/src/se/hal/HalServer.java index a87bd79b..de6d582f 100644 --- a/hal-core/src/se/hal/HalServer.java +++ b/hal-core/src/se/hal/HalServer.java @@ -1,17 +1,13 @@ package se.hal; +import se.hal.daemon.HalExternalWebDaemon; import se.hal.intf.*; import se.hal.page.HalAlertManager; import se.hal.struct.PluginConfig; -import se.hal.util.HalAcmeDataStore; import zutil.db.DBConnection; import zutil.io.file.FileUtil; import zutil.log.LogUtil; -import zutil.net.acme.AcmeChallengeFactory; -import zutil.net.acme.AcmeClient; -import zutil.net.acme.AcmeHttpChallengeFactory; -import zutil.net.acme.AcmeManualDnsChallengeFactory; import zutil.net.http.HttpPage; import zutil.net.http.HttpServer; import zutil.net.http.page.HttpFilePage; @@ -19,9 +15,6 @@ import zutil.net.http.page.HttpRedirectPage; 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; @@ -31,8 +24,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.logging.Level; import java.util.logging.Logger; -import static se.hal.HalContext.CONFIG_HTTP_EXTERNAL_DOMAIN; -import static se.hal.HalContext.CONFIG_HTTP_EXTERNAL_PORT; /** * Main class for Hal @@ -46,12 +37,10 @@ public class HalServer { private static List daemons = new ArrayList<>(); private static HttpServer http; - private static HttpServer httpExternal; - + private static HalExternalWebDaemon httpExternal; private static PluginManager pluginManager; - public static void main(String[] args) { try { // ------------------------------------ @@ -78,54 +67,6 @@ public class HalServer { logger.info("Working directory: " + FileUtil.find(".").getAbsolutePath()); - // ------------------------------------ - // Initialize External HttpServer - // ------------------------------------ - - 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); - - HalAcmeDataStore acmeDataStore = new HalAcmeDataStore(); - X509Certificate certificate = acmeDataStore.getCertificate(); - - 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()); - } 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)); - } 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(); - } - } - - httpExternal = new HttpServer(HalContext.getIntegerProperty(CONFIG_HTTP_EXTERNAL_PORT), acmeDataStore.getDomainKeyPair().getPrivate(), certificate); - httpExternal.start(); - - 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."); - } - // ------------------------------------ // Initialize Plugins // ------------------------------------ @@ -166,6 +107,9 @@ public class HalServer { for (Iterator it = pluginManager.getSingletonIterator(HalDaemon.class); it.hasNext(); ) { HalDaemon daemon = it.next(); registerDaemon(daemon); + + if (daemon instanceof HalExternalWebDaemon) // Keep a reference of the external web server + httpExternal = (HalExternalWebDaemon) daemon; } // ------------------------------------ diff --git a/hal-core/src/se/hal/daemon/HalExternalWebDaemon.java b/hal-core/src/se/hal/daemon/HalExternalWebDaemon.java new file mode 100644 index 00000000..80274644 --- /dev/null +++ b/hal-core/src/se/hal/daemon/HalExternalWebDaemon.java @@ -0,0 +1,96 @@ +package se.hal.daemon; + +import org.shredzone.acme4j.exception.AcmeException; +import se.hal.HalContext; +import se.hal.intf.HalDaemon; +import se.hal.util.HalAcmeDataStore; +import zutil.log.LogUtil; +import zutil.net.acme.AcmeClient; +import zutil.net.acme.AcmeHttpChallengeFactory; +import zutil.net.acme.AcmeManualDnsChallengeFactory; +import zutil.net.http.HttpPage; +import zutil.net.http.HttpServer; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.cert.X509Certificate; +import java.util.concurrent.ScheduledExecutorService; +import java.util.logging.Logger; + +import static se.hal.HalContext.CONFIG_HTTP_EXTERNAL_DOMAIN; +import static se.hal.HalContext.CONFIG_HTTP_EXTERNAL_PORT; + + +public class HalExternalWebDaemon implements HalDaemon { + private static final Logger logger = LogUtil.getLogger(); + + private HttpServer httpExternal; + private String externalServerUrl; + private HalAcmeDataStore acmeDataStore = new HalAcmeDataStore(); + private X509Certificate certificate; + + @Override + public void initiate(ScheduledExecutorService executor) { + // ------------------------------------ + // Initialize External HttpServer + // ------------------------------------ + + try { + if (HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_DOMAIN) && HalContext.containsProperty(CONFIG_HTTP_EXTERNAL_PORT)) { + externalServerUrl = "https://" + HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_DOMAIN) + ":" + HalContext.getStringProperty(HalContext.CONFIG_HTTP_EXTERNAL_PORT); + certificate = acmeDataStore.getCertificate(); + + renewCertificate(); + startHttpServer(); + } else { + logger.warning("Missing '" + CONFIG_HTTP_EXTERNAL_PORT + "' and '" + CONFIG_HTTP_EXTERNAL_DOMAIN + "' configuration, will not setup external http server."); + } + } catch (Exception e) { + logger.severe("Was unable to initiate external web server."); + } + } + + private void renewCertificate() throws AcmeException, IOException { + 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()); + } 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)); + } 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(); + } + } + } + + private void startHttpServer() throws GeneralSecurityException, IOException { + httpExternal = new HttpServer(HalContext.getIntegerProperty(CONFIG_HTTP_EXTERNAL_PORT), acmeDataStore.getDomainKeyPair().getPrivate(), certificate); + httpExternal.start(); + + logger.info("External https server up and running at: " + externalServerUrl); + } + + + public void setPage(String url, HttpPage page) { + if (httpExternal != null) + httpExternal.setPage(url, page); + } +} diff --git a/hal-core/src/se/hal/plugin.json b/hal-core/src/se/hal/plugin.json index c1958105..88c2a685 100644 --- a/hal-core/src/se/hal/plugin.json +++ b/hal-core/src/se/hal/plugin.json @@ -8,6 +8,7 @@ {"se.hal.intf.HalAbstractControllerManager": "se.hal.EventControllerManager"}, {"se.hal.intf.HalAbstractControllerManager": "se.hal.SensorControllerManager"}, + {"se.hal.intf.HalDaemon": "se.hal.daemon.HalExternalWebDaemon"}, {"se.hal.intf.HalDaemon": "se.hal.daemon.HalMulticastDnsDaemon"}, {"se.hal.intf.HalDaemon": "se.hal.daemon.SensorDataAggregatorDaemon"}, {"se.hal.intf.HalDaemon": "se.hal.daemon.SensorDataCleanupDaemon"},