summaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorTor Brede Vekterli <vekterli@oath.com>2018-12-03 15:02:00 +0000
committerTor Brede Vekterli <vekterli@oath.com>2018-12-03 15:24:12 +0000
commit3c86000931f45a0f0aa82a6cdf59ea82ea53b47e (patch)
treecbfb0867dfd696cddc6adf5782fc405432f0aa07 /vespalib
parent5bf52410ce593878770d945f2a7941dc2082b466 (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')
-rw-r--r--vespalib/CMakeLists.txt1
-rw-r--r--vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/CMakeLists.txt10
-rw-r--r--vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/auto_reloading_tls_crypto_engine_test.cpp87
-rw-r--r--vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_ca.pem12
-rw-r--r--vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_config.json7
-rw-r--r--vespalib/src/tests/net/tls/auto_reloading_tls_crypto_engine/test_key.pem5
-rw-r--r--vespalib/src/tests/net/tls/transport_options/transport_options_reading_test.cpp8
-rw-r--r--vespalib/src/vespa/vespalib/net/crypto_engine.cpp4
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/CMakeLists.txt1
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.cpp109
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h48
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/impl/openssl_tls_context_impl.cpp3
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/impl/openssl_tls_context_impl.h7
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.h4
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.cpp12
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.h2
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/tls_context.h2
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.h11
-rw-r--r--vespalib/src/vespa/vespalib/net/tls/transport_security_options.h4
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