diff options
author | Tor Brede Vekterli <vekterli@oath.com> | 2018-12-03 15:02:00 +0000 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@oath.com> | 2018-12-03 15:24:12 +0000 |
commit | 3c86000931f45a0f0aa82a6cdf59ea82ea53b47e (patch) | |
tree | cbfb0867dfd696cddc6adf5782fc405432f0aa07 /vespalib | |
parent | 5bf52410ce593878770d945f2a7941dc2082b466 (diff) |
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.
Diffstat (limited to 'vespalib')
19 files changed, 322 insertions, 15 deletions
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 <vespa/vespalib/io/fileutil.h> +#include <vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h> +#include <vespa/vespalib/net/tls/transport_security_options.h> +#include <vespa/vespalib/net/tls/transport_security_options_reading.h> +#include <vespa/vespalib/net/tls/impl/openssl_tls_context_impl.h> +#include <vespa/vespalib/testkit/test_kit.h> + +#include <chrono> + +#include <openssl/ssl.h> + +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<AutoReloadingTlsCryptoEngine> 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<AutoReloadingTlsCryptoEngine>("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::OpenSslTlsContextImpl&>(*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 <thread> #include <vespa/vespalib/xxhash/xxhash.h> #include <vespa/vespalib/stllike/string.h> +#include <vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h> #include <vespa/vespalib/net/tls/transport_security_options.h> #include <vespa/vespalib/net/tls/transport_security_options_reading.h> #include <vespa/vespalib/net/tls/tls_crypto_engine.h> @@ -188,8 +189,7 @@ CryptoEngine::SP create_default_crypto_engine() { return std::make_shared<NullCryptoEngine>(); } 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<TlsCryptoEngine>(*tls_opts); + auto tls = std::make_shared<net::tls::AutoReloadingTlsCryptoEngine>(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 <functional> +#include <stdexcept> + +#include <vespa/log/log.h> +LOG_SETUP(".vespalib.net.tls.auto_reloading_tls_crypto_engine"); + +namespace vespalib::net::tls { + +namespace { + +std::shared_ptr<TlsCryptoEngine> 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<TlsCryptoEngine>(*tls_opts); +} + +std::shared_ptr<TlsCryptoEngine> 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<std::mutex>& _lock; + explicit UnlockGuard(std::unique_lock<std::mutex>& 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<std::mutex>& held_lock) { + std::shared_ptr<TlsCryptoEngine> 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<TlsCryptoSocket> +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 <vespa/vespalib/net/tls/tls_crypto_engine.h> +#include <vespa/vespalib/stllike/string.h> + +#include <chrono> +#include <condition_variable> +#include <mutex> +#include <thread> + +namespace vespalib::net::tls { + +class AutoReloadingTlsCryptoEngine : public AbstractTlsCryptoEngine { +public: + using EngineSP = std::shared_ptr<TlsCryptoEngine>; + 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<std::mutex>& 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<TlsCryptoSocket> 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<CertificateVerificationCallback> 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 <vespa/vespalib/net/tls/tls_context.h> +#include <vespa/vespalib/net/tls/transport_security_options.h> #include <vespa/vespalib/net/tls/certificate_verification_callback.h> #include <vespa/vespalib/stllike/string.h> @@ -11,12 +12,18 @@ namespace vespalib::net::tls::impl { class OpenSslTlsContextImpl : public TlsContext { SslCtxPtr _ctx; std::shared_ptr<CertificateVerificationCallback> _cert_verify_callback; + TransportSecurityOptions _redacted_transport_options; public: OpenSslTlsContextImpl(const TransportSecurityOptions& ts_opts, std::shared_ptr<CertificateVerificationCallback> 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<NullCryptoEngine> _null_engine; - std::shared_ptr<TlsCryptoEngine> _tls_engine; + std::shared_ptr<AbstractTlsCryptoEngine> _tls_engine; bool _use_tls_when_client; public: - MaybeTlsCryptoEngine(std::shared_ptr<TlsCryptoEngine> tls_engine, + MaybeTlsCryptoEngine(std::shared_ptr<AbstractTlsCryptoEngine> tls_engine, bool use_tls_when_client) : _null_engine(std::make_shared<NullCryptoEngine>()), _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<TlsCryptoEngine> _factory; - SmartBuffer _buffer; + CryptoSocket::UP &_self; + SocketHandle _socket; + std::shared_ptr<AbstractTlsCryptoEngine> _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<TlsCryptoEngine> tls_engine) + MyCryptoSocket(CryptoSocket::UP &self, SocketHandle socket, std::shared_ptr<AbstractTlsCryptoEngine> 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::<unnamed> -MaybeTlsCryptoSocket::MaybeTlsCryptoSocket(SocketHandle socket, std::shared_ptr<TlsCryptoEngine> tls_engine) +MaybeTlsCryptoSocket::MaybeTlsCryptoSocket(SocketHandle socket, std::shared_ptr<AbstractTlsCryptoEngine> tls_engine) : _socket(std::make_unique<MyCryptoSocket>(_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<TlsCryptoEngine> tls_engine); + MaybeTlsCryptoSocket(SocketHandle socket, std::shared_ptr<AbstractTlsCryptoEngine> 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<TlsCryptoSocket> 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<net::tls::TlsContext> _tls_ctx; public: explicit TlsCryptoEngine(net::tls::TransportSecurityOptions tls_opts); - std::unique_ptr<TlsCryptoSocket> create_tls_crypto_socket(SocketHandle socket, bool is_server); + std::unique_ptr<TlsCryptoSocket> 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<net::tls::TlsContext> 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 |