aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/tests
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/src/tests
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/src/tests')
-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
6 files changed, 129 insertions, 0 deletions
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");