ssl certs are optional

This commit is contained in:
CJ Cobb
2021-06-17 01:30:30 +00:00
parent 0569f7d2e9
commit 6710c240aa
2 changed files with 110 additions and 134 deletions

View File

@@ -24,8 +24,8 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <server/HttpSession.h>
#include <server/SslHttpSession.h>
#include <server/PlainWsSession.h>
#include <server/SslHttpSession.h>
#include <server/SslWsSession.h>
#include <server/SubscriptionManager.h>
@@ -34,13 +34,15 @@
class SubscriptionManager;
template <class PlainSession, class SslSession>
class Detector : public std::enable_shared_from_this<Detector<PlainSession, SslSession>>
class Detector
: public std::enable_shared_from_this<Detector<PlainSession, SslSession>>
{
using std::enable_shared_from_this<Detector<PlainSession, SslSession>>::shared_from_this;
using std::enable_shared_from_this<
Detector<PlainSession, SslSession>>::shared_from_this;
boost::beast::tcp_stream stream_;
ssl::context& ctx_;
std::shared_ptr<BackendInterface> backend_;
std::optional<std::reference_wrapper<ssl::context>> ctx_;
std::shared_ptr<BackendInterface> backend_;
std::shared_ptr<SubscriptionManager> subscriptions_;
std::shared_ptr<ETLLoadBalancer> balancer_;
DOSGuard& dosGuard_;
@@ -49,7 +51,7 @@ class Detector : public std::enable_shared_from_this<Detector<PlainSession, SslS
public:
Detector(
tcp::socket&& socket,
ssl::context& ctx,
std::optional<std::reference_wrapper<ssl::context>> ctx,
std::shared_ptr<BackendInterface> backend,
std::shared_ptr<SubscriptionManager> subscriptions,
std::shared_ptr<ETLLoadBalancer> balancer,
@@ -68,33 +70,36 @@ public:
run()
{
// Set the timeout.
boost::beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
boost::beast::get_lowest_layer(stream_).expires_after(
std::chrono::seconds(30));
// Detect a TLS handshake
async_detect_ssl(
stream_,
buffer_,
boost::beast::bind_front_handler(
&Detector::on_detect,
shared_from_this()));
&Detector::on_detect, shared_from_this()));
}
void
on_detect(boost::beast::error_code ec, bool result)
{
if(ec)
if (ec)
return httpFail(ec, "detect");
if(result)
if (result)
{
if (!ctx_)
return httpFail(ec, "ssl not supported by this server");
// Launch SSL session
std::make_shared<SslSession>(
stream_.release_socket(),
ctx_,
*ctx_,
backend_,
subscriptions_,
balancer_,
dosGuard_,
std::move(buffer_))->run();
std::move(buffer_))
->run();
return;
}
@@ -105,17 +110,20 @@ public:
subscriptions_,
balancer_,
dosGuard_,
std::move(buffer_))->run();
std::move(buffer_))
->run();
}
};
template <class PlainSession, class SslSession>
class Listener : public std::enable_shared_from_this<Listener<PlainSession, SslSession>>
class Listener
: public std::enable_shared_from_this<Listener<PlainSession, SslSession>>
{
using std::enable_shared_from_this<Listener<PlainSession, SslSession>>::shared_from_this;
using std::enable_shared_from_this<
Listener<PlainSession, SslSession>>::shared_from_this;
net::io_context& ioc_;
ssl::context& ctx_;
std::optional<std::reference_wrapper<ssl::context>> ctx_;
tcp::acceptor acceptor_;
std::shared_ptr<BackendInterface> backend_;
std::shared_ptr<SubscriptionManager> subscriptions_;
@@ -125,7 +133,7 @@ class Listener : public std::enable_shared_from_this<Listener<PlainSession, SslS
public:
Listener(
net::io_context& ioc,
ssl::context& ctx,
std::optional<std::reference_wrapper<ssl::context>> ctx,
tcp::endpoint endpoint,
std::shared_ptr<BackendInterface> backend,
std::shared_ptr<SubscriptionManager> subscriptions,
@@ -143,7 +151,7 @@ public:
// Open the acceptor
acceptor_.open(endpoint.protocol(), ec);
if(ec)
if (ec)
{
httpFail(ec, "open");
return;
@@ -151,7 +159,7 @@ public:
// Allow address reuse
acceptor_.set_option(net::socket_base::reuse_address(true), ec);
if(ec)
if (ec)
{
httpFail(ec, "set_option");
return;
@@ -159,16 +167,15 @@ public:
// Bind to the server address
acceptor_.bind(endpoint, ec);
if(ec)
if (ec)
{
httpFail(ec, "bind");
return;
}
// Start listening for connections
acceptor_.listen(
net::socket_base::max_listen_connections, ec);
if(ec)
acceptor_.listen(net::socket_base::max_listen_connections, ec);
if (ec)
{
httpFail(ec, "listen");
return;
@@ -190,14 +197,13 @@ private:
acceptor_.async_accept(
net::make_strand(ioc_),
boost::beast::bind_front_handler(
&Listener::on_accept,
shared_from_this()));
&Listener::on_accept, shared_from_this()));
}
void
on_accept(boost::beast::error_code ec, tcp::socket socket)
{
if(ec)
if (ec)
{
httpFail(ec, "listener_accept");
}
@@ -210,7 +216,8 @@ private:
backend_,
subscriptions_,
balancer_,
dosGuard_)->run();
dosGuard_)
->run();
}
// Accept another connection
@@ -218,76 +225,75 @@ private:
}
};
namespace Server
namespace Server {
using WebsocketServer = Listener<WsUpgrader, SslWsUpgrader>;
using HttpServer = Listener<HttpSession, SslHttpSession>;
static std::shared_ptr<WebsocketServer>
make_WebSocketServer(
boost::json::object const& config,
boost::asio::io_context& ioc,
std::optional<std::reference_wrapper<ssl::context>> ctx,
std::shared_ptr<BackendInterface> backend,
std::shared_ptr<SubscriptionManager> subscriptions,
std::shared_ptr<ETLLoadBalancer> balancer,
DOSGuard& dosGuard)
{
using WebsocketServer = Listener<WsUpgrader, SslWsUpgrader>;
using HttpServer = Listener<HttpSession, SslHttpSession>;
if (!config.contains("websocket_public"))
return nullptr;
static std::shared_ptr<WebsocketServer>
make_WebSocketServer(
boost::json::object const& config,
boost::asio::io_context& ioc,
ssl::context& ctx,
std::shared_ptr<BackendInterface> backend,
std::shared_ptr<SubscriptionManager> subscriptions,
std::shared_ptr<ETLLoadBalancer> balancer,
DOSGuard& dosGuard)
{
if (!config.contains("websocket_public"))
return nullptr;
auto const& wsConfig = config.at("websocket_public").as_object();
auto const& wsConfig = config.at("websocket_public").as_object();
auto const address =
boost::asio::ip::make_address(wsConfig.at("ip").as_string().c_str());
auto const port =
static_cast<unsigned short>(wsConfig.at("port").as_int64());
auto const address =
boost::asio::ip::make_address(wsConfig.at("ip").as_string().c_str());
auto const port =
static_cast<unsigned short>(wsConfig.at("port").as_int64());
auto server = std::make_shared<WebsocketServer>(
ioc,
ctx,
boost::asio::ip::tcp::endpoint{address, port},
backend,
subscriptions,
balancer,
dosGuard);
auto server = std::make_shared<WebsocketServer>(
ioc,
ctx,
boost::asio::ip::tcp::endpoint{address, port},
backend,
subscriptions,
balancer,
dosGuard);
server->run();
return server;
}
static std::shared_ptr<HttpServer>
make_HttpServer(
boost::json::object const& config,
boost::asio::io_context& ioc,
ssl::context& ctx,
std::shared_ptr<BackendInterface> backend,
std::shared_ptr<SubscriptionManager> subscriptions,
std::shared_ptr<ETLLoadBalancer> balancer,
DOSGuard& dosGuard)
{
if (!config.contains("http_public"))
return nullptr;
auto const& httpConfig = config.at("http_public").as_object();
auto const address =
boost::asio::ip::make_address(httpConfig.at("ip").as_string().c_str());
auto const port =
static_cast<unsigned short>(httpConfig.at("port").as_int64());
auto server = std::make_shared<HttpServer>(
ioc,
ctx,
boost::asio::ip::tcp::endpoint{address, port},
backend,
subscriptions,
balancer,
dosGuard);
server->run();
return server;
}
server->run();
return server;
}
#endif // LISTENER_H
static std::shared_ptr<HttpServer>
make_HttpServer(
boost::json::object const& config,
boost::asio::io_context& ioc,
std::optional<std::reference_wrapper<ssl::context>> ctx,
std::shared_ptr<BackendInterface> backend,
std::shared_ptr<SubscriptionManager> subscriptions,
std::shared_ptr<ETLLoadBalancer> balancer,
DOSGuard& dosGuard)
{
if (!config.contains("http_public"))
return nullptr;
auto const& httpConfig = config.at("http_public").as_object();
auto const address =
boost::asio::ip::make_address(httpConfig.at("ip").as_string().c_str());
auto const port =
static_cast<unsigned short>(httpConfig.at("port").as_int64());
auto server = std::make_shared<HttpServer>(
ioc,
ctx,
boost::asio::ip::tcp::endpoint{address, port},
backend,
subscriptions,
balancer,
dosGuard);
server->run();
return server;
}
} // namespace Server
#endif // LISTENER_H

View File

@@ -28,8 +28,7 @@
#include <functional>
#include <iostream>
#include <memory>
#include <etl/ReportingETL.h>
#include <server/Listener.h>
#include <server/listener.h>
#include <sstream>
#include <string>
#include <thread>
@@ -71,7 +70,7 @@ parse_certs(const char* certFilename, const char* keyFilename)
std::string cert = contents.str();
std::ifstream readKey(keyFilename, std::ios::in | std::ios::binary);
if(!readKey)
if (!readKey)
return {};
contents.str("");
@@ -85,8 +84,7 @@ parse_certs(const char* certFilename, const char* keyFilename)
boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2);
ctx.use_certificate_chain(
boost::asio::buffer(cert.data(), cert.size()));
ctx.use_certificate_chain(boost::asio::buffer(cert.data(), cert.size()));
ctx.use_private_key(
boost::asio::buffer(key.data(), key.size()),
@@ -95,7 +93,6 @@ parse_certs(const char* certFilename, const char* keyFilename)
return ctx;
}
void
initLogLevel(int level)
{
@@ -159,6 +156,9 @@ main(int argc, char* argv[])
auto const threads = std::max<int>(1, std::atoi(argv[1]));
auto const config = parse_config(argv[2]);
auto ctx = parse_certs(argv[3], argv[4]);
auto ctxRef = ctx
? std::optional<std::reference_wrapper<ssl::context>>{ctx.value()}
: std::nullopt;
if (argc > 5)
{
@@ -174,11 +174,6 @@ main(int argc, char* argv[])
std::cerr << "Ccouldnt parse config. Exiting..." << std::endl;
return EXIT_FAILURE;
}
if (!ctx)
{
std::cerr << "Couldn't parse SSL certificates" << std::endl;
return EXIT_FAILURE;
}
boost::asio::io_context ioc{threads};
@@ -193,41 +188,16 @@ main(int argc, char* argv[])
NetworkValidatedLedgers::make_ValidatedLedgers()};
auto balancer = ETLLoadBalancer::make_ETLLoadBalancer(
*config,
ioc,
backend,
subscriptions,
ledgers
);
*config, ioc, backend, subscriptions, ledgers);
auto etl = ReportingETL::make_ReportingETL(
*config,
ioc,
backend,
subscriptions,
balancer,
ledgers
);
*config, ioc, backend, subscriptions, balancer, ledgers);
auto wsServer = Server::make_WebSocketServer(
*config,
ioc,
*ctx,
backend,
subscriptions,
balancer,
dosGuard
);
*config, ioc, ctxRef, backend, subscriptions, balancer, dosGuard);
auto httpServer = Server::make_HttpServer(
*config,
ioc,
*ctx,
backend,
subscriptions,
balancer,
dosGuard
);
*config, ioc, ctxRef, backend, subscriptions, balancer, dosGuard);
// Blocks until stopped.
// When stopped, shared_ptrs fall out of scope