Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Leonids proposal on reloading certificates. #5

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
#include <iostream>
#include <csignal>

void signal_handler(int signal) {
if (signal == SIGHUP) {
auto switcher = std::dynamic_pointer_cast<AppComponent::ProxyConnectionProvider>(OATPP_GET_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, "sslProvider"));
if (switcher) {
switcher->resetProvider(AppComponent::createNewProvider());
}
}
}

/**
* run() method.
* 1) set Environment components.
Expand All @@ -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();
Expand Down
66 changes: 57 additions & 9 deletions src/AppComponent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<oatpp::network::ServerConnectionProvider>, 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<oatpp::network::ServerConnectionProvider> 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<oatpp::network::ServerConnectionProvider>, "streamProvider"));
}

/**
* Proxy-Provider to quickly switch connection-providers using the component system.
*/
class ProxyConnectionProvider : public oatpp::network::ServerConnectionProvider {
private:
std::shared_ptr<oatpp::network::ServerConnectionProvider> m_currentProvider;
public:

std::shared_ptr<oatpp::data::stream::IOStream> 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<oatpp::network::ServerConnectionProvider>& newProvider) {
m_currentProvider = newProvider;
}

oatpp::async::CoroutineStarterForResult<const std::shared_ptr<oatpp::data::stream::IOStream> &> getAsync() override {
return m_currentProvider->getAsync();
}

void invalidate(const std::shared_ptr<oatpp::data::stream::IOStream> &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<oatpp::network::ServerConnectionProvider>, 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<oatpp::network::ServerConnectionProvider>, serverConnectionProvider)("sslProvider", [] {
auto proxyProvider = std::make_shared<ProxyConnectionProvider>();
proxyProvider->resetProvider(createNewProvider());

return oatpp::libressl::server::ConnectionProvider::createShared(config, {"0.0.0.0", 8443, oatpp::network::Address::IP_4});
return proxyProvider;
}());

/**
Expand Down