diff options
author | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-08-22 13:55:17 +0000 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-08-22 14:11:59 +0000 |
commit | 55e0f93a74214caf22c4fd79d60e1b0b6836a99c (patch) | |
tree | 0a59f93c8c46f98007057ab9e49a789867e2018d /vespalib | |
parent | b4117991e6d98dbc9a93625f6dc7170cdd1484dc (diff) |
Support capability enforcement environment variable in C++
Mirrors Java enforce/log-only/disable semantics, defaulting to enforce.
Also fixes an issue where connection auth context and capabilities
would not be set if a server socket was running in mixed-mode. This
is not a problem in practice since mixed-mode is inherently completely
insecure since it must accept plain-text clients, which implicitly
have all capabilities granted.
Diffstat (limited to 'vespalib')
9 files changed, 109 insertions, 8 deletions
diff --git a/vespalib/src/vespa/vespalib/net/tls/CMakeLists.txt b/vespalib/src/vespa/vespalib/net/tls/CMakeLists.txt index 5be2e0d4387..5e91f682f36 100644 --- a/vespalib/src/vespa/vespalib/net/tls/CMakeLists.txt +++ b/vespalib/src/vespa/vespalib/net/tls/CMakeLists.txt @@ -4,6 +4,7 @@ vespa_add_library(vespalib_vespalib_net_tls OBJECT authorization_mode.cpp auto_reloading_tls_crypto_engine.cpp capability.cpp + capability_env_config.cpp capability_set.cpp crypto_codec.cpp crypto_codec_adapter.cpp diff --git a/vespalib/src/vespa/vespalib/net/tls/capability_env_config.cpp b/vespalib/src/vespa/vespalib/net/tls/capability_env_config.cpp new file mode 100644 index 00000000000..ec97882ca64 --- /dev/null +++ b/vespalib/src/vespa/vespalib/net/tls/capability_env_config.cpp @@ -0,0 +1,46 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "capability_env_config.h" +#include <vespa/vespalib/stllike/string.h> +#include <cstdlib> + +#include <vespa/log/log.h> +LOG_SETUP(".vespalib.net.tls.capability_env_config"); + +namespace vespalib::net::tls { + +namespace { + +CapabilityEnforcementMode parse_enforcement_mode_from_env() noexcept { + const char* env = getenv("VESPA_TLS_CAPABILITIES_ENFORCEMENT_MODE"); + vespalib::string mode = env ? env : ""; + if (mode == "enforce") { + return CapabilityEnforcementMode::Enforce; + } else if (mode == "log_only") { + return CapabilityEnforcementMode::LogOnly; + } else if (mode == "disable") { + return CapabilityEnforcementMode::Disable; + } else if (!mode.empty()) { + LOG(warning, "VESPA_TLS_CAPABILITIES_ENFORCEMENT_MODE environment variable has " + "an unsupported value (%s). Falling back to 'enforce'", mode.c_str()); + } + return CapabilityEnforcementMode::Enforce; +} + +} + +const char* to_string(CapabilityEnforcementMode mode) noexcept { + switch (mode) { + case CapabilityEnforcementMode::Enforce: return "Enforce"; + case CapabilityEnforcementMode::LogOnly: return "LogOnly"; + case CapabilityEnforcementMode::Disable: return "Disable"; + default: abort(); + } +} + +CapabilityEnforcementMode capability_enforcement_mode_from_env() noexcept { + static const CapabilityEnforcementMode mode = parse_enforcement_mode_from_env(); + return mode; +} + +} diff --git a/vespalib/src/vespa/vespalib/net/tls/capability_env_config.h b/vespalib/src/vespa/vespalib/net/tls/capability_env_config.h new file mode 100644 index 00000000000..e66fca9656b --- /dev/null +++ b/vespalib/src/vespa/vespalib/net/tls/capability_env_config.h @@ -0,0 +1,16 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +namespace vespalib::net::tls { + +enum class CapabilityEnforcementMode { + Disable, + LogOnly, + Enforce +}; + +const char* to_string(CapabilityEnforcementMode mode) noexcept; + +CapabilityEnforcementMode capability_enforcement_mode_from_env() noexcept; + +} 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 be692e8df35..04613cb3a65 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 @@ -5,6 +5,7 @@ #include "tls_crypto_socket.h" #include "protocol_snooping.h" #include <vespa/vespalib/data/smart_buffer.h> +#include <vespa/vespalib/net/connection_auth_context.h> #include <vespa/vespalib/util/size_literals.h> namespace vespalib { @@ -94,4 +95,8 @@ MaybeTlsCryptoSocket::MaybeTlsCryptoSocket(SocketHandle socket, std::shared_ptr< { } +std::unique_ptr<net::ConnectionAuthContext> MaybeTlsCryptoSocket::make_auth_context() { + return _socket->make_auth_context(); +} + } // namespace vespalib 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 ba706cb3cd7..1928307e5ad 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 @@ -33,6 +33,7 @@ public: ssize_t flush() override { return _socket->flush(); } ssize_t half_close() override { return _socket->half_close(); } void drop_empty_buffers() override { _socket->drop_empty_buffers(); } + std::unique_ptr<net::ConnectionAuthContext> make_auth_context() override; }; } // namespace vespalib diff --git a/vespalib/src/vespa/vespalib/net/tls/transport_security_options.cpp b/vespalib/src/vespa/vespalib/net/tls/transport_security_options.cpp index 3b3fdd579d1..f3ae1a05919 100644 --- a/vespalib/src/vespa/vespalib/net/tls/transport_security_options.cpp +++ b/vespalib/src/vespa/vespalib/net/tls/transport_security_options.cpp @@ -29,6 +29,15 @@ TransportSecurityOptions::TransportSecurityOptions(vespalib::string ca_certs_pem { } +TransportSecurityOptions::TransportSecurityOptions(const TransportSecurityOptions&) = default; +TransportSecurityOptions& TransportSecurityOptions::operator=(const TransportSecurityOptions&) = default; +TransportSecurityOptions::TransportSecurityOptions(TransportSecurityOptions&&) noexcept = default; +TransportSecurityOptions& TransportSecurityOptions::operator=(TransportSecurityOptions&&) noexcept = default; + +TransportSecurityOptions::~TransportSecurityOptions() { + secure_memzero(&_private_key_pem[0], _private_key_pem.size()); +} + TransportSecurityOptions TransportSecurityOptions::copy_without_private_key() const { return TransportSecurityOptions(_ca_certs_pem, _cert_chain_pem, "", _authorized_peers, _disable_hostname_validation); @@ -62,8 +71,4 @@ TransportSecurityOptions::Params::Params(Params&&) noexcept = default; TransportSecurityOptions::Params& TransportSecurityOptions::Params::operator=(TransportSecurityOptions::Params&&) noexcept = default; -TransportSecurityOptions::~TransportSecurityOptions() { - secure_memzero(&_private_key_pem[0], _private_key_pem.size()); -} - } // vespalib::net::tls 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 84fc9c1cbbe..4694373671b 100644 --- a/vespalib/src/vespa/vespalib/net/tls/transport_security_options.h +++ b/vespalib/src/vespa/vespalib/net/tls/transport_security_options.h @@ -46,6 +46,10 @@ public: }; explicit TransportSecurityOptions(Params params); + TransportSecurityOptions(const TransportSecurityOptions&); + TransportSecurityOptions& operator=(const TransportSecurityOptions&); + TransportSecurityOptions(TransportSecurityOptions&&) noexcept; + TransportSecurityOptions& operator=(TransportSecurityOptions&&) noexcept; ~TransportSecurityOptions(); diff --git a/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.cpp b/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.cpp index 29043dc42a5..1210b1d7c87 100644 --- a/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.cpp +++ b/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.cpp @@ -1,17 +1,20 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "make_tls_options_for_testing.h" +#include "peer_policy_utils.h" #include <vespa/vespalib/crypto/private_key.h> #include <vespa/vespalib/crypto/x509_certificate.h> namespace { using namespace vespalib::crypto; +using namespace vespalib::net::tls; struct TransientCryptoCredentials { CertKeyWrapper root_ca; CertKeyWrapper host_creds; vespalib::net::tls::TransportSecurityOptions cached_transport_options; + vespalib::net::tls::TransportSecurityOptions cached_constrained_transport_options; TransientCryptoCredentials(); ~TransientCryptoCredentials(); @@ -29,14 +32,16 @@ struct TransientCryptoCredentials { return {std::move(cert), std::move(key)}; } - static CertKeyWrapper make_host_creds(const CertKeyWrapper& root_ca_creds) { + static CertKeyWrapper make_host_creds(const CertKeyWrapper& root_ca_creds, + const vespalib::string& extra_san_entry) { auto dn = X509Certificate::DistinguishedName() .country("US").state("CA").locality("Sunnyvale") .organization("Wile E. Coyote, Ltd.") .organizational_unit("Unit Testing and Anvil Dropping Division") .add_common_name("localhost"); // Should technically not be needed, but including it anyway. auto subject = X509Certificate::SubjectInfo(std::move(dn)); - subject.add_subject_alt_name("DNS:localhost"); + subject.add_subject_alt_name("DNS:localhost") + .add_subject_alt_name(extra_san_entry); auto key = PrivateKey::generate_p256_ec_key(); auto params = X509Certificate::Params::issued_by(std::move(subject), key, root_ca_creds.cert, root_ca_creds.key); params.valid_for = std::chrono::hours(1); @@ -49,12 +54,18 @@ struct TransientCryptoCredentials { TransientCryptoCredentials::TransientCryptoCredentials() : root_ca(make_root_ca()), - host_creds(make_host_creds(root_ca)), + host_creds(make_host_creds(root_ca, "DNS:anvils.example")), cached_transport_options(vespalib::net::tls::TransportSecurityOptions::Params(). ca_certs_pem(root_ca.cert->to_pem()). cert_chain_pem(host_creds.cert->to_pem()). private_key_pem(host_creds.key->private_to_pem()). - authorized_peers(vespalib::net::tls::AuthorizedPeers::allow_all_authenticated())) + authorized_peers(vespalib::net::tls::AuthorizedPeers::allow_all_authenticated())), + cached_constrained_transport_options(vespalib::net::tls::TransportSecurityOptions::Params(). + ca_certs_pem(root_ca.cert->to_pem()). + cert_chain_pem(host_creds.cert->to_pem()). + private_key_pem(host_creds.key->private_to_pem()). + authorized_peers(authorized_peers({policy_with({required_san_dns("anvils.example")}, + CapabilitySet::telemetry())}))) {} TransientCryptoCredentials::~TransientCryptoCredentials() = default; @@ -74,4 +85,8 @@ vespalib::net::tls::TransportSecurityOptions make_tls_options_for_testing() { return TransientCryptoCredentials::instance().cached_transport_options; } +vespalib::net::tls::TransportSecurityOptions make_telemetry_only_capability_tls_options_for_testing() { + return TransientCryptoCredentials::instance().cached_constrained_transport_options; +} + } // namespace vespalib::test diff --git a/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.h b/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.h index 055d9cbdfa6..5a07f796991 100644 --- a/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.h +++ b/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.h @@ -20,4 +20,12 @@ extern SocketSpec local_spec; **/ vespalib::net::tls::TransportSecurityOptions make_tls_options_for_testing(); +/** + * Make security options whose authz rules only grant the telemetry capability + * set to the included certificate. + * + * Only useful for testing capability propagation and filtering. + */ +vespalib::net::tls::TransportSecurityOptions make_telemetry_only_capability_tls_options_for_testing(); + } // namespace vespalib::test |