From 12f4caebe89b04216ce586ffd9b77e1e39bd3915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benedikt-Alexander=20Mokro=C3=9F?= Date: Wed, 15 Sep 2021 18:56:22 +0200 Subject: [PATCH] Implemented Leonids proposal on reloading certificates. --- src/App.cpp | 13 ++++++++- src/AppComponent.hpp | 66 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/App.cpp b/src/App.cpp index 2a6fffa..d64c685 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -9,6 +9,15 @@ #include #include +void signal_handler(int signal) { + if (signal == SIGHUP) { + auto switcher = std::dynamic_pointer_cast(OATPP_GET_COMPONENT(std::shared_ptr, "sslProvider")); + if (switcher) { + switcher->resetProvider(AppComponent::createNewProvider()); + } + } +} + /** * run() method. * 1) set Environment components. @@ -21,12 +30,14 @@ void run() { oatpp::libressl::Callbacks::setDefaultCallbacks(); /* ignore SIGPIPE */ + #if !(defined(WIN32) || defined(_WIN32)) std::signal(SIGPIPE, SIG_IGN); #endif AppComponent components; // Create scope Environment components - + std::signal(SIGHUP, signal_handler); // Install signal-handler for SIGHUP SSL-Certificate reloading + /* create ApiControllers and add endpoints to router */ auto router = components.httpRouter.getObject(); diff --git a/src/AppComponent.hpp b/src/AppComponent.hpp index 8ce91b1..db57419 100644 --- a/src/AppComponent.hpp +++ b/src/AppComponent.hpp @@ -26,24 +26,72 @@ */ class AppComponent { public: - + /** - * Create ConnectionProvider component which listens on the port + * Helper-Function to create an SSL-Provider on the fly */ - OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionProvider)([] { - - OATPP_LOGD("oatpp::libressl::Config", "pem='%s'", CERT_PEM_PATH); - OATPP_LOGD("oatpp::libressl::Config", "crt='%s'", CERT_CRT_PATH); - auto config = oatpp::libressl::Config::createDefaultServerConfigShared(CERT_CRT_PATH, CERT_PEM_PATH /* private key */); - + static std::shared_ptr createNewProvider() { /** * if you see such error: * oatpp::libressl::server::ConnectionProvider:Error on call to 'tls_configure'. ssl context failure * It might be because you have several ssl libraries installed on your machine. * Try to make sure you are using libtls, libssl, and libcrypto from the same package */ + OATPP_LOGD("AppComponent::createNewProvider()", "(Re-)Loading Certificates"); + OATPP_LOGD("AppComponent::createNewProvider()", "pem='%s'", CERT_PEM_PATH); + OATPP_LOGD("AppComponent::createNewProvider()", "crt='%s'", CERT_CRT_PATH); + auto config = oatpp::libressl::Config::createDefaultServerConfigShared(CERT_CRT_PATH, CERT_PEM_PATH /* private key */); + return oatpp::libressl::server::ConnectionProvider::createShared(config, OATPP_GET_COMPONENT(std::shared_ptr, "streamProvider")); + } + + /** + * Proxy-Provider to quickly switch connection-providers using the component system. + */ + class ProxyConnectionProvider : public oatpp::network::ServerConnectionProvider { + private: + std::shared_ptr m_currentProvider; + public: + + std::shared_ptr get() override { + return m_currentProvider->get(); + } + + /* call this method when certificates changed and a new SSL connection provider created */ + void resetProvider(const std::shared_ptr& newProvider) { + m_currentProvider = newProvider; + } + + oatpp::async::CoroutineStarterForResult &> getAsync() override { + return m_currentProvider->getAsync(); + } + + void invalidate(const std::shared_ptr &resource) override { + m_currentProvider->invalidate(resource); + } + + void stop() override { + m_currentProvider->stop(); + } + + }; + + /** + * Create the streamProvider, this is the ConnectionProvider who does the actual socket handling which is passed to + * the sslProvider which does the SSL-Handshaking + */ + OATPP_CREATE_COMPONENT(std::shared_ptr, streamProvider)("streamProvider", []{ + return oatpp::network::tcp::server::ConnectionProvider::createShared({"0.0.0.0", 8443, oatpp::network::Address::IP_4}); + }()); + + /** + * Create ConnectionProvider "sslProvider" which does the SSL-Handshaking and can be replaced on the fly + * with new ssl certificates + */ + OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionProvider)("sslProvider", [] { + auto proxyProvider = std::make_shared(); + proxyProvider->resetProvider(createNewProvider()); - return oatpp::libressl::server::ConnectionProvider::createShared(config, {"0.0.0.0", 8443, oatpp::network::Address::IP_4}); + return proxyProvider; }()); /**