From 3c86000931f45a0f0aa82a6cdf59ea82ea53b47e Mon Sep 17 00:00:00 2001 From: Tor Brede Vekterli Date: Mon, 3 Dec 2018 15:02:00 +0000 Subject: Support auto-reloading of TLS config in C++ implementation By default reloads every 60 minutes. This also reloads all peer authorization rules. Files referenced by the TLS config are reloaded transitively. If reloading fails a warning will be logged and the existing config will continue to be in effect until the next reload time. --- vespalib/CMakeLists.txt | 1 + .../CMakeLists.txt | 10 ++ .../auto_reloading_tls_crypto_engine_test.cpp | 87 ++++++++++++++++ .../auto_reloading_tls_crypto_engine/test_ca.pem | 12 +++ .../test_config.json | 7 ++ .../auto_reloading_tls_crypto_engine/test_key.pem | 5 + .../transport_options_reading_test.cpp | 8 ++ vespalib/src/vespa/vespalib/net/crypto_engine.cpp | 4 +- vespalib/src/vespa/vespalib/net/tls/CMakeLists.txt | 1 + .../net/tls/auto_reloading_tls_crypto_engine.cpp | 109 +++++++++++++++++++++ .../net/tls/auto_reloading_tls_crypto_engine.h | 48 +++++++++ .../net/tls/impl/openssl_tls_context_impl.cpp | 3 +- .../net/tls/impl/openssl_tls_context_impl.h | 7 ++ .../vespalib/net/tls/maybe_tls_crypto_engine.h | 4 +- .../vespalib/net/tls/maybe_tls_crypto_socket.cpp | 12 +-- .../vespalib/net/tls/maybe_tls_crypto_socket.h | 2 +- vespalib/src/vespa/vespalib/net/tls/tls_context.h | 2 +- .../src/vespa/vespalib/net/tls/tls_crypto_engine.h | 11 ++- .../vespalib/net/tls/transport_security_options.h | 4 + 19 files changed, 322 insertions(+), 15 deletions(-) create mode 100644 vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/CMakeLists.txt create mode 100644 vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/auto_reloading_tls_crypto_engine_test.cpp create mode 100644 vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_ca.pem create mode 100644 vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_config.json create mode 100644 vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_key.pem create mode 100644 vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.cpp create mode 100644 vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h (limited to 'vespalib') diff --git a/vespalib/CMakeLists.txt b/vespalib/CMakeLists.txt index 8bd3dda4e5a..3427e9353b8 100644 --- a/vespalib/CMakeLists.txt +++ b/vespalib/CMakeLists.txt @@ -60,6 +60,7 @@ vespa_define_module( src/tests/net/socket src/tests/net/socket_spec src/tests/net/sync_crypto_socket + src/tests/net/tls/auto_reloading_tls_crypto_engine src/tests/net/tls/direct_buffer_bio src/tests/net/tls/openssl_impl src/tests/net/tls/policy_checking_certificate_verifier diff --git a/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/CMakeLists.txt b/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/CMakeLists.txt new file mode 100644 index 00000000000..c3361ee1fa3 --- /dev/null +++ b/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(vespalib_net_tls_auto_reloading_tls_crypto_engine_test_app TEST + SOURCES + auto_reloading_tls_crypto_engine_test.cpp + DEPENDS + vespalib +) +vespa_add_test(NAME vespalib_net_tls_auto_reloading_tls_crypto_engine_test_app + COMMAND vespalib_net_tls_auto_reloading_tls_crypto_engine_test_app) + diff --git a/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/auto_reloading_tls_crypto_engine_test.cpp b/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/auto_reloading_tls_crypto_engine_test.cpp new file mode 100644 index 00000000000..7926f71e812 --- /dev/null +++ b/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/auto_reloading_tls_crypto_engine_test.cpp @@ -0,0 +1,87 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace vespalib; +using namespace vespalib::net::tls; +using namespace std::chrono_literals; + +constexpr const char* cert1_pem = R"(-----BEGIN CERTIFICATE----- +MIIBszCCAVgCCQCXsYrXQWS0bzAKBggqhkjOPQQDAjBkMQswCQYDVQQGEwJVUzEU +MBIGA1UEBwwLTG9vbmV5VmlsbGUxDTALBgNVBAoMBEFDTUUxFTATBgNVBAsMDEFD +TUUgdGVzdCBDQTEZMBcGA1UEAwwQYWNtZS5leGFtcGxlLmNvbTAeFw0xODExMzAx +NDA0MzdaFw00NjA0MTcxNDA0MzdaMF4xCzAJBgNVBAYTAlVTMRQwEgYDVQQHDAtM +b29uZXlWaWxsZTEeMBwGA1UECgwVV2lsZS4gRS4gQ295b3RlLCBMdGQuMRkwFwYD +VQQDDBB3aWxlLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +cQN3UOKg30+h1EYgAxQukAYgzbx7VmcrOBheD7AaJoTUnaRn9xQ6j0t4eKNa6x/1 +K7luNL+AfaJiCQLrbalVoDAKBggqhkjOPQQDAgNJADBGAiEAyzvCt9qJCtY/7Qi1 +2Jzb1BTvAPOszeBFRzovMatQSUICIQDuT6cyV3yigoxLZbn5In3Sx+qUPFPCMI8O +X5yKMXNkmQ== +-----END CERTIFICATE-----)"; + +constexpr const char* cert2_pem = R"(-----BEGIN CERTIFICATE----- +MIIBsjCCAVgCCQCXsYrXQWS0cDAKBggqhkjOPQQDAjBkMQswCQYDVQQGEwJVUzEU +MBIGA1UEBwwLTG9vbmV5VmlsbGUxDTALBgNVBAoMBEFDTUUxFTATBgNVBAsMDEFD +TUUgdGVzdCBDQTEZMBcGA1UEAwwQYWNtZS5leGFtcGxlLmNvbTAeFw0xODExMzAx +NDA0MzdaFw00NjA0MTcxNDA0MzdaMF4xCzAJBgNVBAYTAlVTMRQwEgYDVQQHDAtM +b29uZXlWaWxsZTEeMBwGA1UECgwVV2lsZS4gRS4gQ295b3RlLCBMdGQuMRkwFwYD +VQQDDBB3aWxlLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +cQN3UOKg30+h1EYgAxQukAYgzbx7VmcrOBheD7AaJoTUnaRn9xQ6j0t4eKNa6x/1 +K7luNL+AfaJiCQLrbalVoDAKBggqhkjOPQQDAgNIADBFAiEAluT52NkVdGBRZJxo +PhL9XBnJJfzvG5GKXIK/iZgFuYkCIFLp+SIQ5Nc1+NzrU2ii/mkzCgC4N/nOWu9H +88OP2wnm +-----END CERTIFICATE-----)"; + +void write_file(vespalib::stringref path, vespalib::stringref data) { + File f(path); + f.open(File::CREATE | File::TRUNC); + f.write(data.data(), data.size(), 0); +} + +struct Fixture { + std::unique_ptr engine; + explicit Fixture(AutoReloadingTlsCryptoEngine::TimeInterval reload_interval) { + write_file("test_cert.pem", cert1_pem); + // Must be done after file has been written + engine = std::make_unique("test_config.json", reload_interval); + } + + ~Fixture() { + engine.reset(); + if (fileExists("test_cert.pem")) { + unlink("test_cert.pem"); // just crash the test if this throws + } + } + + vespalib::string current_cert_chain() const { + auto impl = engine->acquire_current_engine(); + auto& ctx_impl = dynamic_cast(*impl->tls_context()); + return ctx_impl.transport_security_options().cert_chain_pem(); + } +}; + +TEST_FF("Config reloading transitively loads updated files", Fixture(50ms), TimeBomb(60)) { + auto current_certs = f1.current_cert_chain(); + ASSERT_EQUAL(cert1_pem, current_certs); + + write_file("test_cert.pem.tmp", cert2_pem); + rename("test_cert.pem.tmp", "test_cert.pem", false, false); // We expect this to be an atomic rename under the hood + + current_certs = f1.current_cert_chain(); + while (current_certs != cert2_pem) { + std::this_thread::sleep_for(10ms); + current_certs = f1.current_cert_chain(); + } + // If the config is never reloaded, test will go boom. +} + +TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_ca.pem b/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_ca.pem new file mode 100644 index 00000000000..e6f03fd52e3 --- /dev/null +++ b/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_ca.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuDCCAV4CCQDDjrv2sJswHTAKBggqhkjOPQQDAjBkMQswCQYDVQQGEwJVUzEU +MBIGA1UEBwwLTG9vbmV5VmlsbGUxDTALBgNVBAoMBEFDTUUxFTATBgNVBAsMDEFD +TUUgdGVzdCBDQTEZMBcGA1UEAwwQYWNtZS5leGFtcGxlLmNvbTAeFw0xODExMzAx +NDA0MzdaFw00NjA0MTcxNDA0MzdaMGQxCzAJBgNVBAYTAlVTMRQwEgYDVQQHDAtM +b29uZXlWaWxsZTENMAsGA1UECgwEQUNNRTEVMBMGA1UECwwMQUNNRSB0ZXN0IENB +MRkwFwYDVQQDDBBhY21lLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D +AQcDQgAEtCn9+LpDQIHZwS2UQq0oh3Q3zetb/9fjgSjZH3aRA3Cpy9I6j5ydTSIA +ox1VX9OjvM4RRjUtjBDgA/+TwJcD2DAKBggqhkjOPQQDAgNIADBFAiA0xOB7h7FH +rrPVNbyWdPyCB4y6P+BsOywyPXzE+p6TvQIhAJfuj53MUlBkE0Hc5bvWI5VK4Qmb +8Q4SAXR9bhPcnpz6 +-----END CERTIFICATE----- diff --git a/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_config.json b/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_config.json new file mode 100644 index 00000000000..2b2322d928f --- /dev/null +++ b/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_config.json @@ -0,0 +1,7 @@ +{ + "files":{ + "private-key": "test_key.pem", + "ca-certificates": "test_ca.pem", + "certificates": "test_cert.pem" + } +} diff --git a/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_key.pem b/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_key.pem new file mode 100644 index 00000000000..a90d7834216 --- /dev/null +++ b/vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHSvTpHIslB+IHRZHMMBuu5Tj2iMVsH9eFNk3RwCp1r3oAoGCCqGSM49 +AwEHoUQDQgAEcQN3UOKg30+h1EYgAxQukAYgzbx7VmcrOBheD7AaJoTUnaRn9xQ6 +j0t4eKNa6x/1K7luNL+AfaJiCQLrbalVoA== +-----END EC PRIVATE KEY----- diff --git a/vespalib/src/tests/net/tls/transport_options/transport_options_reading_test.cpp b/vespalib/src/tests/net/tls/transport_options/transport_options_reading_test.cpp index 1a442dc54f0..c1e2c0b5f49 100644 --- a/vespalib/src/tests/net/tls/transport_options/transport_options_reading_test.cpp +++ b/vespalib/src/tests/net/tls/transport_options/transport_options_reading_test.cpp @@ -19,6 +19,14 @@ TEST("can load TLS credentials via config file") { EXPECT_EQUAL("My certificate chain\n", opts->cert_chain_pem()); } +TEST("copying options without private key does, in fact, not include private key") { + auto opts = read_options_from_json_file("ok_config.json"); + auto cloned = opts->copy_without_private_key(); + EXPECT_EQUAL("", cloned.private_key_pem()); + EXPECT_EQUAL("My CA certificates\n", cloned.ca_certs_pem()); + EXPECT_EQUAL("My certificate chain\n", cloned.cert_chain_pem()); +} + TEST("missing JSON file throws exception") { EXPECT_EXCEPTION(read_options_from_json_file("missing_config.json"), IllegalArgumentException, "TLS config file 'missing_config.json' could not be read"); diff --git a/vespalib/src/vespa/vespalib/net/crypto_engine.cpp b/vespalib/src/vespa/vespalib/net/crypto_engine.cpp index cdce2d41bf6..cb779e4a6b0 100644 --- a/vespalib/src/vespa/vespalib/net/crypto_engine.cpp +++ b/vespalib/src/vespa/vespalib/net/crypto_engine.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -188,8 +189,7 @@ CryptoEngine::SP create_default_crypto_engine() { return std::make_shared(); } LOG(debug, "Using TLS crypto engine with config file '%s'", cfg_file.c_str()); - auto tls_opts = net::tls::read_options_from_json_file(cfg_file); - auto tls = std::make_shared(*tls_opts); + auto tls = std::make_shared(cfg_file); env = getenv("VESPA_TLS_INSECURE_MIXED_MODE"); vespalib::string mixed_mode = env ? env : ""; if (mixed_mode == "plaintext_client_mixed_server") { diff --git a/vespalib/src/vespa/vespalib/net/tls/CMakeLists.txt b/vespalib/src/vespa/vespalib/net/tls/CMakeLists.txt index 170d2148cfa..5db7558ef8b 100644 --- a/vespalib/src/vespa/vespalib/net/tls/CMakeLists.txt +++ b/vespalib/src/vespa/vespalib/net/tls/CMakeLists.txt @@ -1,6 +1,7 @@ # Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. vespa_add_library(vespalib_vespalib_net_tls OBJECT SOURCES + auto_reloading_tls_crypto_engine.cpp crypto_codec.cpp crypto_codec_adapter.cpp crypto_exception.cpp diff --git a/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.cpp b/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.cpp new file mode 100644 index 00000000000..665b19cdaaf --- /dev/null +++ b/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.cpp @@ -0,0 +1,109 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "auto_reloading_tls_crypto_engine.h" +#include "tls_context.h" +#include "tls_crypto_engine.h" +#include "transport_security_options.h" +#include "transport_security_options_reading.h" + +#include +#include + +#include +LOG_SETUP(".vespalib.net.tls.auto_reloading_tls_crypto_engine"); + +namespace vespalib::net::tls { + +namespace { + +std::shared_ptr tls_engine_from_config_file(const vespalib::string& config_file_path) { + auto tls_opts = net::tls::read_options_from_json_file(config_file_path); + return std::make_shared(*tls_opts); +} + +std::shared_ptr try_create_engine_from_tls_config(const vespalib::string& config_file_path) { + try { + return tls_engine_from_config_file(config_file_path); + } catch (std::exception& e) { + LOG(warning, "Failed to reload TLS config file (%s): '%s'. Old config remains in effect.", + config_file_path.c_str(), e.what()); + return {}; + } +} + +// Unlocks on construction, re-locks on destruction. +struct UnlockGuard { + std::unique_lock& _lock; + explicit UnlockGuard(std::unique_lock& lock) : _lock(lock) { + _lock.unlock(); + } + ~UnlockGuard() { + _lock.lock(); + } +}; + +} // anonymous namespace + +AutoReloadingTlsCryptoEngine::AutoReloadingTlsCryptoEngine(vespalib::string config_file_path, + TimeInterval reload_interval) + : _mutex(), + _cond(), + _shutdown(false), + _config_file_path(std::move(config_file_path)), + _current_engine(tls_engine_from_config_file(_config_file_path)), + _reload_interval(reload_interval), + _reload_thread([this](){ run_reload_loop(); }) +{ +} + +AutoReloadingTlsCryptoEngine::~AutoReloadingTlsCryptoEngine() { + { + std::unique_lock lock(_mutex); + _shutdown = true; + _cond.notify_all(); + } + _reload_thread.join(); +} + +std::chrono::steady_clock::time_point AutoReloadingTlsCryptoEngine::make_future_reload_time_point() const noexcept { + return std::chrono::steady_clock::now() + _reload_interval; +} + +void AutoReloadingTlsCryptoEngine::run_reload_loop() { + std::unique_lock lock(_mutex); + auto reload_at_time = make_future_reload_time_point(); + while (!_shutdown) { + if (_cond.wait_until(lock, reload_at_time) == std::cv_status::timeout) { + LOG(debug, "TLS config reload time reached, reloading file '%s'", _config_file_path.c_str()); + try_replace_current_engine(lock); + reload_at_time = make_future_reload_time_point(); + } // else: spurious wakeup or shutdown + } +} + +void AutoReloadingTlsCryptoEngine::try_replace_current_engine(std::unique_lock& held_lock) { + std::shared_ptr new_engine; + { + UnlockGuard guard(held_lock); + new_engine = try_create_engine_from_tls_config(_config_file_path); + } + if (new_engine) { + _current_engine = std::move(new_engine); + } +} + +AutoReloadingTlsCryptoEngine::EngineSP AutoReloadingTlsCryptoEngine::acquire_current_engine() const { + std::lock_guard guard(_mutex); + return _current_engine; +} + +CryptoSocket::UP AutoReloadingTlsCryptoEngine::create_crypto_socket(SocketHandle socket, bool is_server) { + return acquire_current_engine()->create_crypto_socket(std::move(socket), is_server); +} + +std::unique_ptr +AutoReloadingTlsCryptoEngine::create_tls_crypto_socket(SocketHandle socket, bool is_server) { + return acquire_current_engine()->create_tls_crypto_socket(std::move(socket), is_server); +} + +} diff --git a/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h b/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h new file mode 100644 index 00000000000..327179dbd17 --- /dev/null +++ b/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h @@ -0,0 +1,48 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace vespalib::net::tls { + +class AutoReloadingTlsCryptoEngine : public AbstractTlsCryptoEngine { +public: + using EngineSP = std::shared_ptr; + using TimeInterval = std::chrono::steady_clock::duration; +private: + mutable std::mutex _mutex; + std::condition_variable _cond; + bool _shutdown; + const vespalib::string _config_file_path; + EngineSP _current_engine; // Access must be under _mutex + TimeInterval _reload_interval; + std::thread _reload_thread; + + void run_reload_loop(); + void try_replace_current_engine(std::unique_lock& held_lock); + std::chrono::steady_clock::time_point make_future_reload_time_point() const noexcept; + +public: + explicit AutoReloadingTlsCryptoEngine(vespalib::string config_file_path, + TimeInterval reload_interval = std::chrono::seconds(3600)); + ~AutoReloadingTlsCryptoEngine() override; + + AutoReloadingTlsCryptoEngine(const AutoReloadingTlsCryptoEngine&) = delete; + AutoReloadingTlsCryptoEngine& operator=(const AutoReloadingTlsCryptoEngine&) = delete; + AutoReloadingTlsCryptoEngine(AutoReloadingTlsCryptoEngine&&) = delete; + AutoReloadingTlsCryptoEngine& operator=(AutoReloadingTlsCryptoEngine&&) = delete; + + EngineSP acquire_current_engine() const; + + CryptoSocket::UP create_crypto_socket(SocketHandle socket, bool is_server) override; + std::unique_ptr create_tls_crypto_socket(SocketHandle socket, bool is_server) override; +}; + +} diff --git a/vespalib/src/vespa/vespalib/net/tls/impl/openssl_tls_context_impl.cpp b/vespalib/src/vespa/vespalib/net/tls/impl/openssl_tls_context_impl.cpp index 9ebe8c540f1..1fa4fc097e0 100644 --- a/vespalib/src/vespa/vespalib/net/tls/impl/openssl_tls_context_impl.cpp +++ b/vespalib/src/vespa/vespalib/net/tls/impl/openssl_tls_context_impl.cpp @@ -189,7 +189,8 @@ OpenSslTlsContextImpl::OpenSslTlsContextImpl( const TransportSecurityOptions& ts_opts, std::shared_ptr cert_verify_callback) : _ctx(new_tls_ctx_with_auto_init()), - _cert_verify_callback(std::move(cert_verify_callback)) + _cert_verify_callback(std::move(cert_verify_callback)), + _redacted_transport_options(ts_opts.copy_without_private_key()) { if (!_ctx) { throw CryptoException("Failed to create new TLS context"); diff --git a/vespalib/src/vespa/vespalib/net/tls/impl/openssl_tls_context_impl.h b/vespalib/src/vespa/vespalib/net/tls/impl/openssl_tls_context_impl.h index 0ff8dd5932e..5dddbc80ef2 100644 --- a/vespalib/src/vespa/vespalib/net/tls/impl/openssl_tls_context_impl.h +++ b/vespalib/src/vespa/vespalib/net/tls/impl/openssl_tls_context_impl.h @@ -3,6 +3,7 @@ #include "openssl_typedefs.h" #include +#include #include #include @@ -11,12 +12,18 @@ namespace vespalib::net::tls::impl { class OpenSslTlsContextImpl : public TlsContext { SslCtxPtr _ctx; std::shared_ptr _cert_verify_callback; + TransportSecurityOptions _redacted_transport_options; public: OpenSslTlsContextImpl(const TransportSecurityOptions& ts_opts, std::shared_ptr cert_verify_callback); ~OpenSslTlsContextImpl() override; ::SSL_CTX* native_context() const noexcept { return _ctx.get(); } + // Transport options this context was created with, but with the private key + // information scrubbed away. + const TransportSecurityOptions& transport_security_options() const noexcept { + return _redacted_transport_options; + } private: // Note: single use per instance; does _not_ clear existing chain! void add_certificate_authorities(stringref ca_pem); diff --git a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.h b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.h index 8e76460231c..29909fa115d 100644 --- a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.h +++ b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.h @@ -19,11 +19,11 @@ class MaybeTlsCryptoEngine : public CryptoEngine { private: std::shared_ptr _null_engine; - std::shared_ptr _tls_engine; + std::shared_ptr _tls_engine; bool _use_tls_when_client; public: - MaybeTlsCryptoEngine(std::shared_ptr tls_engine, + MaybeTlsCryptoEngine(std::shared_ptr tls_engine, bool use_tls_when_client) : _null_engine(std::make_shared()), _tls_engine(std::move(tls_engine)), diff --git a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.cpp b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.cpp index cd5c4114844..4b9bc8a30b4 100644 --- a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.cpp +++ b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.cpp @@ -14,10 +14,10 @@ class MyCryptoSocket : public CryptoSocket private: static constexpr size_t SNOOP_SIZE = net::tls::snooping::min_header_bytes_to_observe(); - CryptoSocket::UP &_self; - SocketHandle _socket; - std::shared_ptr _factory; - SmartBuffer _buffer; + CryptoSocket::UP &_self; + SocketHandle _socket; + std::shared_ptr _factory; + SmartBuffer _buffer; bool is_blocked(ssize_t res, int error) const { return ((res < 0) && ((error == EWOULDBLOCK) || (error == EAGAIN))); @@ -28,7 +28,7 @@ private: } public: - MyCryptoSocket(CryptoSocket::UP &self, SocketHandle socket, std::shared_ptr tls_engine) + MyCryptoSocket(CryptoSocket::UP &self, SocketHandle socket, std::shared_ptr tls_engine) : _self(self), _socket(std::move(socket)), _factory(std::move(tls_engine)), _buffer(4096) { static_assert(SNOOP_SIZE == 8); @@ -83,7 +83,7 @@ public: } // namespace vespalib:: -MaybeTlsCryptoSocket::MaybeTlsCryptoSocket(SocketHandle socket, std::shared_ptr tls_engine) +MaybeTlsCryptoSocket::MaybeTlsCryptoSocket(SocketHandle socket, std::shared_ptr tls_engine) : _socket(std::make_unique(_socket, std::move(socket), std::move(tls_engine))) { } diff --git a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.h b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.h index 9d3a190829a..bd4ea9d7d50 100644 --- a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.h +++ b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.h @@ -22,7 +22,7 @@ class MaybeTlsCryptoSocket : public CryptoSocket private: CryptoSocket::UP _socket; public: - MaybeTlsCryptoSocket(SocketHandle socket, std::shared_ptr tls_engine); + MaybeTlsCryptoSocket(SocketHandle socket, std::shared_ptr tls_engine); int get_fd() const override { return _socket->get_fd(); } HandshakeResult handshake() override { return _socket->handshake(); } size_t min_read_buffer_size() const override { return _socket->min_read_buffer_size(); } diff --git a/vespalib/src/vespa/vespalib/net/tls/tls_context.h b/vespalib/src/vespa/vespalib/net/tls/tls_context.h index 09fe31efd8e..ff9ee91f7da 100644 --- a/vespalib/src/vespa/vespalib/net/tls/tls_context.h +++ b/vespalib/src/vespa/vespalib/net/tls/tls_context.h @@ -6,7 +6,7 @@ namespace vespalib::net::tls { class TransportSecurityOptions; -class CertificateVerificationCallback; +struct CertificateVerificationCallback; struct TlsContext { virtual ~TlsContext() = default; diff --git a/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.h b/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.h index 07715b6995f..151b3ef128b 100644 --- a/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.h +++ b/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.h @@ -9,19 +9,26 @@ namespace vespalib { +class AbstractTlsCryptoEngine : public CryptoEngine { +public: + virtual std::unique_ptr create_tls_crypto_socket(SocketHandle socket, bool is_server) = 0; +}; + /** * Crypto engine implementing TLS. **/ -class TlsCryptoEngine : public CryptoEngine +class TlsCryptoEngine : public AbstractTlsCryptoEngine { private: std::shared_ptr _tls_ctx; public: explicit TlsCryptoEngine(net::tls::TransportSecurityOptions tls_opts); - std::unique_ptr create_tls_crypto_socket(SocketHandle socket, bool is_server); + std::unique_ptr create_tls_crypto_socket(SocketHandle socket, bool is_server) override; CryptoSocket::UP create_crypto_socket(SocketHandle socket, bool is_server) override { return create_tls_crypto_socket(std::move(socket), is_server); } + + std::shared_ptr tls_context() const noexcept { return _tls_ctx; }; }; } // namespace vespalib diff --git a/vespalib/src/vespa/vespalib/net/tls/transport_security_options.h b/vespalib/src/vespa/vespalib/net/tls/transport_security_options.h index 16427fcbf1d..0502276f7a6 100644 --- a/vespalib/src/vespa/vespalib/net/tls/transport_security_options.h +++ b/vespalib/src/vespa/vespalib/net/tls/transport_security_options.h @@ -45,6 +45,10 @@ public: const vespalib::string& cert_chain_pem() const noexcept { return _cert_chain_pem; } const vespalib::string& private_key_pem() const noexcept { return _private_key_pem; } const AuthorizedPeers& authorized_peers() const noexcept { return _authorized_peers; } + + TransportSecurityOptions copy_without_private_key() const { + return TransportSecurityOptions(_ca_certs_pem, _cert_chain_pem, "", _authorized_peers); + } }; } // vespalib::net::tls -- cgit v1.2.3