diff --git a/include/envoy/secret/BUILD b/include/envoy/secret/BUILD new file mode 100644 index 000000000000..c4dcf8404fd6 --- /dev/null +++ b/include/envoy/secret/BUILD @@ -0,0 +1,18 @@ +licenses(["notice"]) # Apache 2 + +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_library", + "envoy_package", +) + +envoy_package() + +envoy_cc_library( + name = "secret_manager_interface", + hdrs = ["secret_manager.h"], + deps = [ + "//include/envoy/ssl:tls_certificate_config_interface", + "@envoy_api//envoy/api/v2/auth:cert_cc", + ], +) diff --git a/include/envoy/secret/secret_manager.h b/include/envoy/secret/secret_manager.h new file mode 100644 index 000000000000..d7f978874121 --- /dev/null +++ b/include/envoy/secret/secret_manager.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "envoy/api/v2/auth/cert.pb.h" +#include "envoy/ssl/tls_certificate_config.h" + +namespace Envoy { +namespace Secret { + +/** + * A manager for static secrets. + * + * TODO(jaebong) Support dynamic secrets. + */ +class SecretManager { +public: + virtual ~SecretManager() {} + + /** + * @param secret a protobuf message of envoy::api::v2::auth::Secret. + * @throw an EnvoyException if the secret is invalid or not supported. + */ + virtual void addOrUpdateSecret(const envoy::api::v2::auth::Secret& secret) PURE; + + /** + * @param name a name of the Ssl::TlsCertificateConfig. + * @return the TlsCertificate secret. Returns nullptr if the secret is not found. + */ + virtual const Ssl::TlsCertificateConfig* findTlsCertificate(const std::string& name) const PURE; +}; + +} // namespace Secret +} // namespace Envoy diff --git a/include/envoy/server/BUILD b/include/envoy/server/BUILD index cef8702255a1..766c7ace2698 100644 --- a/include/envoy/server/BUILD +++ b/include/envoy/server/BUILD @@ -96,6 +96,7 @@ envoy_cc_library( "//include/envoy/local_info:local_info_interface", "//include/envoy/ratelimit:ratelimit_interface", "//include/envoy/runtime:runtime_interface", + "//include/envoy/secret:secret_manager_interface", "//include/envoy/ssl:context_manager_interface", "//include/envoy/thread_local:thread_local_interface", "//include/envoy/tracing:http_tracer_interface", @@ -172,6 +173,7 @@ envoy_cc_library( hdrs = ["transport_socket_config.h"], deps = [ "//include/envoy/network:transport_socket_interface", + "//include/envoy/secret:secret_manager_interface", "//include/envoy/ssl:context_manager_interface", "//source/common/protobuf", ], diff --git a/include/envoy/server/instance.h b/include/envoy/server/instance.h index bc0dfdb0400b..8f784fdba816 100644 --- a/include/envoy/server/instance.h +++ b/include/envoy/server/instance.h @@ -11,6 +11,7 @@ #include "envoy/network/listen_socket.h" #include "envoy/ratelimit/ratelimit.h" #include "envoy/runtime/runtime.h" +#include "envoy/secret/secret_manager.h" #include "envoy/server/admin.h" #include "envoy/server/drain_manager.h" #include "envoy/server/hot_restart.h" @@ -113,6 +114,11 @@ class Instance { */ virtual ListenerManager& listenerManager() PURE; + /** + * @return the server's secret manager + */ + virtual Secret::SecretManager& secretManager() PURE; + /** * @return the server's CLI options. */ diff --git a/include/envoy/server/transport_socket_config.h b/include/envoy/server/transport_socket_config.h index 811aececd048..4e85386cb16d 100644 --- a/include/envoy/server/transport_socket_config.h +++ b/include/envoy/server/transport_socket_config.h @@ -3,6 +3,7 @@ #include #include "envoy/network/transport_socket.h" +#include "envoy/secret/secret_manager.h" #include "envoy/ssl/context_manager.h" #include "common/protobuf/protobuf.h" @@ -19,7 +20,7 @@ class TransportSocketFactoryContext { virtual ~TransportSocketFactoryContext() {} /** - * @return Ssl::ContextManager& the SSL context manager + * @return Ssl::ContextManager& the SSL context manager. */ virtual Ssl::ContextManager& sslContextManager() PURE; @@ -27,6 +28,11 @@ class TransportSocketFactoryContext { * @return Stats::Scope& the transport socket's stats scope. */ virtual Stats::Scope& statsScope() const PURE; + + /** + * Return the instance of secret manager. + */ + virtual Secret::SecretManager& secretManager() PURE; }; class TransportSocketConfigFactory { diff --git a/include/envoy/ssl/BUILD b/include/envoy/ssl/BUILD index f6b94ea22bd9..9e7dac730ea8 100644 --- a/include/envoy/ssl/BUILD +++ b/include/envoy/ssl/BUILD @@ -32,3 +32,8 @@ envoy_cc_library( "//include/envoy/stats:stats_interface", ], ) + +envoy_cc_library( + name = "tls_certificate_config_interface", + hdrs = ["tls_certificate_config.h"], +) diff --git a/include/envoy/ssl/tls_certificate_config.h b/include/envoy/ssl/tls_certificate_config.h new file mode 100644 index 000000000000..6a5c8c842a06 --- /dev/null +++ b/include/envoy/ssl/tls_certificate_config.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +#include "envoy/common/pure.h" + +namespace Envoy { +namespace Ssl { + +class TlsCertificateConfig { +public: + virtual ~TlsCertificateConfig() {} + + /** + * @return a string of certificate chain + */ + virtual const std::string& certificateChain() const PURE; + + /** + * @return a string of private key + */ + virtual const std::string& privateKey() const PURE; +}; + +typedef std::unique_ptr TlsCertificateConfigPtr; + +} // namespace Ssl +} // namespace Envoy diff --git a/include/envoy/upstream/BUILD b/include/envoy/upstream/BUILD index 6629093ae755..60f3c7ba4bdc 100644 --- a/include/envoy/upstream/BUILD +++ b/include/envoy/upstream/BUILD @@ -22,6 +22,7 @@ envoy_cc_library( "//include/envoy/http:conn_pool_interface", "//include/envoy/local_info:local_info_interface", "//include/envoy/runtime:runtime_interface", + "//include/envoy/secret:secret_manager_interface", "//include/envoy/server:admin_interface", "@envoy_api//envoy/api/v2:cds_cc", "@envoy_api//envoy/config/bootstrap/v2:bootstrap_cc", diff --git a/include/envoy/upstream/cluster_manager.h b/include/envoy/upstream/cluster_manager.h index 0c1e33e890ec..f2ec6e672953 100644 --- a/include/envoy/upstream/cluster_manager.h +++ b/include/envoy/upstream/cluster_manager.h @@ -15,6 +15,7 @@ #include "envoy/http/conn_pool.h" #include "envoy/local_info/local_info.h" #include "envoy/runtime/runtime.h" +#include "envoy/secret/secret_manager.h" #include "envoy/server/admin.h" #include "envoy/upstream/load_balancer.h" #include "envoy/upstream/thread_local_cluster.h" @@ -57,6 +58,8 @@ class ClusterUpdateCallbacksHandle { typedef std::unique_ptr ClusterUpdateCallbacksHandlePtr; +class ClusterManagerFactory; + /** * Manages connection pools and load balancing for upstream clusters. The cluster manager is * persistent and shared among multiple ongoing requests/connections. @@ -188,6 +191,8 @@ class ClusterManager { */ virtual ClusterUpdateCallbacksHandlePtr addThreadLocalClusterUpdateCallbacks(ClusterUpdateCallbacks& callbacks) PURE; + + virtual ClusterManagerFactory& clusterManagerFactory() PURE; }; typedef std::unique_ptr ClusterManagerPtr; @@ -257,6 +262,11 @@ class ClusterManagerFactory { virtual CdsApiPtr createCds(const envoy::api::v2::core::ConfigSource& cds_config, const absl::optional& eds_config, ClusterManager& cm) PURE; + + /** + * Returns the secret manager. + */ + virtual Secret::SecretManager& secretManager() PURE; }; } // namespace Upstream diff --git a/source/common/secret/BUILD b/source/common/secret/BUILD new file mode 100644 index 000000000000..4f1eff746d6d --- /dev/null +++ b/source/common/secret/BUILD @@ -0,0 +1,21 @@ +licenses(["notice"]) # Apache 2 + +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_library", + "envoy_package", +) + +envoy_package() + +envoy_cc_library( + name = "secret_manager_impl_lib", + srcs = ["secret_manager_impl.cc"], + hdrs = ["secret_manager_impl.h"], + deps = [ + "//include/envoy/secret:secret_manager_interface", + "//source/common/common:minimal_logger_lib", + "//source/common/ssl:tls_certificate_config_impl_lib", + "@envoy_api//envoy/api/v2/auth:cert_cc", + ], +) diff --git a/source/common/secret/secret_manager_impl.cc b/source/common/secret/secret_manager_impl.cc new file mode 100644 index 000000000000..3e6689a369da --- /dev/null +++ b/source/common/secret/secret_manager_impl.cc @@ -0,0 +1,28 @@ +#include "common/secret/secret_manager_impl.h" + +#include "envoy/common/exception.h" + +#include "common/ssl/tls_certificate_config_impl.h" + +namespace Envoy { +namespace Secret { + +void SecretManagerImpl::addOrUpdateSecret(const envoy::api::v2::auth::Secret& secret) { + switch (secret.type_case()) { + case envoy::api::v2::auth::Secret::TypeCase::kTlsCertificate: + tls_certificate_secrets_[secret.name()] = + std::make_unique(secret.tls_certificate()); + break; + default: + throw EnvoyException("Secret type not implemented"); + } +} + +const Ssl::TlsCertificateConfig* +SecretManagerImpl::findTlsCertificate(const std::string& name) const { + auto secret = tls_certificate_secrets_.find(name); + return (secret != tls_certificate_secrets_.end()) ? secret->second.get() : nullptr; +} + +} // namespace Secret +} // namespace Envoy diff --git a/source/common/secret/secret_manager_impl.h b/source/common/secret/secret_manager_impl.h new file mode 100644 index 000000000000..b9406754a8c4 --- /dev/null +++ b/source/common/secret/secret_manager_impl.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include "envoy/secret/secret_manager.h" +#include "envoy/ssl/tls_certificate_config.h" + +#include "common/common/logger.h" + +namespace Envoy { +namespace Secret { + +class SecretManagerImpl : public SecretManager, Logger::Loggable { +public: + void addOrUpdateSecret(const envoy::api::v2::auth::Secret& secret) override; + const Ssl::TlsCertificateConfig* findTlsCertificate(const std::string& name) const override; + +private: + std::unordered_map tls_certificate_secrets_; +}; + +} // namespace Secret +} // namespace Envoy diff --git a/source/common/ssl/BUILD b/source/common/ssl/BUILD index 01d794bb3229..486d0da347dc 100644 --- a/source/common/ssl/BUILD +++ b/source/common/ssl/BUILD @@ -33,8 +33,10 @@ envoy_cc_library( "ssl", ], deps = [ + "//include/envoy/secret:secret_manager_interface", "//include/envoy/ssl:context_config_interface", "//source/common/common:assert_lib", + "//source/common/common:empty_string", "//source/common/config:datasource_lib", "//source/common/config:tls_context_json_lib", "//source/common/json:json_loader_lib", @@ -66,3 +68,14 @@ envoy_cc_library( "//source/common/common:hex_lib", ], ) + +envoy_cc_library( + name = "tls_certificate_config_impl_lib", + srcs = ["tls_certificate_config_impl.cc"], + hdrs = ["tls_certificate_config_impl.h"], + deps = [ + "//include/envoy/ssl:tls_certificate_config_interface", + "//source/common/config:datasource_lib", + "@envoy_api//envoy/api/v2/auth:cert_cc", + ], +) diff --git a/source/common/ssl/context_config_impl.cc b/source/common/ssl/context_config_impl.cc index b5dfb220dcb6..374cd2945b50 100644 --- a/source/common/ssl/context_config_impl.cc +++ b/source/common/ssl/context_config_impl.cc @@ -1,8 +1,10 @@ #include "common/ssl/context_config_impl.h" +#include #include #include "common/common/assert.h" +#include "common/common/empty_string.h" #include "common/config/datasource.h" #include "common/config/tls_context_json.h" #include "common/protobuf/utility.h" @@ -12,6 +14,29 @@ namespace Envoy { namespace Ssl { +namespace { + +std::string readConfig( + const envoy::api::v2::auth::CommonTlsContext& config, Secret::SecretManager& secret_manager, + const std::function& + read_inline_config, + const std::function& read_secret) { + if (!config.tls_certificates().empty()) { + return read_inline_config(config.tls_certificates()[0]); + } else if (!config.tls_certificate_sds_secret_configs().empty()) { + auto name = config.tls_certificate_sds_secret_configs()[0].name(); + const Ssl::TlsCertificateConfig* secret = secret_manager.findTlsCertificate(name); + if (!secret) { + throw EnvoyException(fmt::format("Static secret is not defined: {}", name)); + } + return read_secret(*secret); + } else { + return EMPTY_STRING; + } +} + +} // namespace + const std::string ContextConfigImpl::DEFAULT_CIPHER_SUITES = "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]:" "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:" @@ -28,7 +53,8 @@ const std::string ContextConfigImpl::DEFAULT_CIPHER_SUITES = const std::string ContextConfigImpl::DEFAULT_ECDH_CURVES = "X25519:P-256"; -ContextConfigImpl::ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContext& config) +ContextConfigImpl::ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContext& config, + Secret::SecretManager& secret_manager) : alpn_protocols_(RepeatedPtrUtil::join(config.alpn_protocols(), ",")), alt_alpn_protocols_(config.deprecated_v1().alt_alpn_protocols()), cipher_suites_(StringUtil::nonEmptyStringOrDefault( @@ -41,18 +67,26 @@ ContextConfigImpl::ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContex Config::DataSource::read(config.validation_context().crl(), true)), certificate_revocation_list_path_( Config::DataSource::getPath(config.validation_context().crl())), - cert_chain_( - config.tls_certificates().empty() - ? "" - : Config::DataSource::read(config.tls_certificates()[0].certificate_chain(), true)), + cert_chain_(readConfig( + config, secret_manager, + [](const envoy::api::v2::auth::TlsCertificate& tls_certificate) -> std::string { + return Config::DataSource::read(tls_certificate.certificate_chain(), true); + }, + [](const Ssl::TlsCertificateConfig& secret) -> std::string { + return secret.certificateChain(); + })), cert_chain_path_( config.tls_certificates().empty() ? "" : Config::DataSource::getPath(config.tls_certificates()[0].certificate_chain())), - private_key_( - config.tls_certificates().empty() - ? "" - : Config::DataSource::read(config.tls_certificates()[0].private_key(), true)), + private_key_(readConfig( + config, secret_manager, + [](const envoy::api::v2::auth::TlsCertificate& tls_certificate) -> std::string { + return Config::DataSource::read(tls_certificate.private_key(), true); + }, + [](const Ssl::TlsCertificateConfig& secret) -> std::string { + return secret.privateKey(); + })), private_key_path_( config.tls_certificates().empty() ? "" @@ -105,30 +139,34 @@ unsigned ContextConfigImpl::tlsVersionFromProto( } ClientContextConfigImpl::ClientContextConfigImpl( - const envoy::api::v2::auth::UpstreamTlsContext& config) - : ContextConfigImpl(config.common_tls_context()), server_name_indication_(config.sni()), - allow_renegotiation_(config.allow_renegotiation()) { + const envoy::api::v2::auth::UpstreamTlsContext& config, Secret::SecretManager& secret_manager) + : ContextConfigImpl(config.common_tls_context(), secret_manager), + server_name_indication_(config.sni()), allow_renegotiation_(config.allow_renegotiation()) { // BoringSSL treats this as a C string, so embedded NULL characters will not // be handled correctly. if (server_name_indication_.find('\0') != std::string::npos) { throw EnvoyException("SNI names containing NULL-byte are not allowed"); } // TODO(PiotrSikora): Support multiple TLS certificates. - if (config.common_tls_context().tls_certificates().size() > 1) { + if ((config.common_tls_context().tls_certificates().size() + + config.common_tls_context().tls_certificate_sds_secret_configs().size()) > 1) { throw EnvoyException("Multiple TLS certificates are not supported for client contexts"); } } -ClientContextConfigImpl::ClientContextConfigImpl(const Json::Object& config) - : ClientContextConfigImpl([&config] { - envoy::api::v2::auth::UpstreamTlsContext upstream_tls_context; - Config::TlsContextJson::translateUpstreamTlsContext(config, upstream_tls_context); - return upstream_tls_context; - }()) {} +ClientContextConfigImpl::ClientContextConfigImpl(const Json::Object& config, + Secret::SecretManager& secret_manager) + : ClientContextConfigImpl( + [&config] { + envoy::api::v2::auth::UpstreamTlsContext upstream_tls_context; + Config::TlsContextJson::translateUpstreamTlsContext(config, upstream_tls_context); + return upstream_tls_context; + }(), + secret_manager) {} ServerContextConfigImpl::ServerContextConfigImpl( - const envoy::api::v2::auth::DownstreamTlsContext& config) - : ContextConfigImpl(config.common_tls_context()), + const envoy::api::v2::auth::DownstreamTlsContext& config, Secret::SecretManager& secret_manager) + : ContextConfigImpl(config.common_tls_context(), secret_manager), require_client_certificate_( PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, require_client_certificate, false)), session_ticket_keys_([&config] { @@ -153,17 +191,21 @@ ServerContextConfigImpl::ServerContextConfigImpl( return ret; }()) { // TODO(PiotrSikora): Support multiple TLS certificates. - if (config.common_tls_context().tls_certificates().size() != 1) { + if ((config.common_tls_context().tls_certificates().size() + + config.common_tls_context().tls_certificate_sds_secret_configs().size()) != 1) { throw EnvoyException("A single TLS certificate is required for server contexts"); } } -ServerContextConfigImpl::ServerContextConfigImpl(const Json::Object& config) - : ServerContextConfigImpl([&config] { - envoy::api::v2::auth::DownstreamTlsContext downstream_tls_context; - Config::TlsContextJson::translateDownstreamTlsContext(config, downstream_tls_context); - return downstream_tls_context; - }()) {} +ServerContextConfigImpl::ServerContextConfigImpl(const Json::Object& config, + Secret::SecretManager& secret_manager) + : ServerContextConfigImpl( + [&config] { + envoy::api::v2::auth::DownstreamTlsContext downstream_tls_context; + Config::TlsContextJson::translateDownstreamTlsContext(config, downstream_tls_context); + return downstream_tls_context; + }(), + secret_manager) {} // Append a SessionTicketKey to keys, initializing it with key_data. // Throws if key_data is invalid. diff --git a/source/common/ssl/context_config_impl.h b/source/common/ssl/context_config_impl.h index b46523664914..2628f39b2e00 100644 --- a/source/common/ssl/context_config_impl.h +++ b/source/common/ssl/context_config_impl.h @@ -4,6 +4,7 @@ #include #include "envoy/api/v2/auth/cert.pb.h" +#include "envoy/secret/secret_manager.h" #include "envoy/ssl/context_config.h" #include "common/json/json_loader.h" @@ -54,7 +55,8 @@ class ContextConfigImpl : public virtual Ssl::ContextConfig { unsigned maxProtocolVersion() const override { return max_protocol_version_; }; protected: - ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContext& config); + ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContext& config, + Secret::SecretManager& secret_manager); private: static unsigned @@ -86,8 +88,10 @@ class ContextConfigImpl : public virtual Ssl::ContextConfig { class ClientContextConfigImpl : public ContextConfigImpl, public ClientContextConfig { public: - explicit ClientContextConfigImpl(const envoy::api::v2::auth::UpstreamTlsContext& config); - explicit ClientContextConfigImpl(const Json::Object& config); + explicit ClientContextConfigImpl(const envoy::api::v2::auth::UpstreamTlsContext& config, + Secret::SecretManager& secret_manager); + explicit ClientContextConfigImpl(const Json::Object& config, + Secret::SecretManager& secret_manager); // Ssl::ClientContextConfig const std::string& serverNameIndication() const override { return server_name_indication_; } @@ -100,8 +104,10 @@ class ClientContextConfigImpl : public ContextConfigImpl, public ClientContextCo class ServerContextConfigImpl : public ContextConfigImpl, public ServerContextConfig { public: - explicit ServerContextConfigImpl(const envoy::api::v2::auth::DownstreamTlsContext& config); - explicit ServerContextConfigImpl(const Json::Object& config); + explicit ServerContextConfigImpl(const envoy::api::v2::auth::DownstreamTlsContext& config, + Secret::SecretManager& secret_manager); + explicit ServerContextConfigImpl(const Json::Object& config, + Secret::SecretManager& secret_manager); // Ssl::ServerContextConfig bool requireClientCertificate() const override { return require_client_certificate_; } diff --git a/source/common/ssl/tls_certificate_config_impl.cc b/source/common/ssl/tls_certificate_config_impl.cc new file mode 100644 index 000000000000..4f0afeb49733 --- /dev/null +++ b/source/common/ssl/tls_certificate_config_impl.cc @@ -0,0 +1,16 @@ +#include "common/ssl/tls_certificate_config_impl.h" + +#include "envoy/common/exception.h" + +#include "common/config/datasource.h" + +namespace Envoy { +namespace Ssl { + +TlsCertificateConfigImpl::TlsCertificateConfigImpl( + const envoy::api::v2::auth::TlsCertificate& config) + : certificate_chain_(Config::DataSource::read(config.certificate_chain(), true)), + private_key_(Config::DataSource::read(config.private_key(), true)) {} + +} // namespace Ssl +} // namespace Envoy diff --git a/source/common/ssl/tls_certificate_config_impl.h b/source/common/ssl/tls_certificate_config_impl.h new file mode 100644 index 000000000000..b8875ffd6998 --- /dev/null +++ b/source/common/ssl/tls_certificate_config_impl.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include "envoy/api/v2/auth/cert.pb.h" +#include "envoy/ssl/tls_certificate_config.h" + +namespace Envoy { +namespace Ssl { + +class TlsCertificateConfigImpl : public TlsCertificateConfig { +public: + TlsCertificateConfigImpl(const envoy::api::v2::auth::TlsCertificate& config); + + const std::string& certificateChain() const override { return certificate_chain_; } + const std::string& privateKey() const override { return private_key_; } + +private: + const std::string certificate_chain_; + const std::string private_key_; +}; + +} // namespace Ssl +} // namespace Envoy diff --git a/source/common/upstream/BUILD b/source/common/upstream/BUILD index d7491ec73f6b..43271f502efb 100644 --- a/source/common/upstream/BUILD +++ b/source/common/upstream/BUILD @@ -190,6 +190,7 @@ envoy_cc_library( hdrs = ["original_dst_cluster.h"], deps = [ ":upstream_includes", + "//include/envoy/secret:secret_manager_interface", "//source/common/common:empty_string", "//source/common/network:address_lib", "//source/common/network:utility_lib", @@ -265,6 +266,7 @@ envoy_cc_library( "//include/envoy/config:grpc_mux_interface", "//include/envoy/config:subscription_interface", "//include/envoy/local_info:local_info_interface", + "//include/envoy/secret:secret_manager_interface", "//source/common/config:metadata_lib", "//source/common/config:subscription_factory_lib", "//source/common/config:utility_lib", diff --git a/source/common/upstream/cluster_manager_impl.h b/source/common/upstream/cluster_manager_impl.h index 28a6740cbdd0..4c149edaaa2f 100644 --- a/source/common/upstream/cluster_manager_impl.h +++ b/source/common/upstream/cluster_manager_impl.h @@ -13,6 +13,7 @@ #include "envoy/http/codes.h" #include "envoy/local_info/local_info.h" #include "envoy/runtime/runtime.h" +#include "envoy/secret/secret_manager.h" #include "envoy/ssl/context_manager.h" #include "envoy/thread_local/thread_local.h" #include "envoy/upstream/cluster_manager.h" @@ -35,10 +36,12 @@ class ProdClusterManagerFactory : public ClusterManagerFactory { Network::DnsResolverSharedPtr dns_resolver, Ssl::ContextManager& ssl_context_manager, Event::Dispatcher& main_thread_dispatcher, - const LocalInfo::LocalInfo& local_info) + const LocalInfo::LocalInfo& local_info, + Secret::SecretManager& secret_manager) : main_thread_dispatcher_(main_thread_dispatcher), runtime_(runtime), stats_(stats), tls_(tls), random_(random), dns_resolver_(dns_resolver), - ssl_context_manager_(ssl_context_manager), local_info_(local_info) {} + ssl_context_manager_(ssl_context_manager), local_info_(local_info), + secret_manager_(secret_manager) {} // Upstream::ClusterManagerFactory ClusterManagerPtr @@ -56,6 +59,7 @@ class ProdClusterManagerFactory : public ClusterManagerFactory { CdsApiPtr createCds(const envoy::api::v2::core::ConfigSource& cds_config, const absl::optional& eds_config, ClusterManager& cm) override; + Secret::SecretManager& secretManager() override { return secret_manager_; } protected: Event::Dispatcher& main_thread_dispatcher_; @@ -68,6 +72,7 @@ class ProdClusterManagerFactory : public ClusterManagerFactory { Network::DnsResolverSharedPtr dns_resolver_; Ssl::ContextManager& ssl_context_manager_; const LocalInfo::LocalInfo& local_info_; + Secret::SecretManager& secret_manager_; }; /** @@ -192,6 +197,8 @@ class ClusterManagerImpl : public ClusterManager, Logger::Loggable void { cleanup(); })) { diff --git a/source/common/upstream/original_dst_cluster.h b/source/common/upstream/original_dst_cluster.h index 57560a0960f2..5cb5107a3a4a 100644 --- a/source/common/upstream/original_dst_cluster.h +++ b/source/common/upstream/original_dst_cluster.h @@ -5,6 +5,7 @@ #include #include +#include "envoy/secret/secret_manager.h" #include "envoy/thread_local/thread_local.h" #include "common/common/empty_string.h" diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc index edfbbfec2cba..ea36ac333fe2 100644 --- a/source/common/upstream/upstream_impl.cc +++ b/source/common/upstream/upstream_impl.cc @@ -11,6 +11,7 @@ #include "envoy/event/dispatcher.h" #include "envoy/event/timer.h" #include "envoy/network/dns.h" +#include "envoy/secret/secret_manager.h" #include "envoy/server/transport_socket_config.h" #include "envoy/ssl/context_manager.h" #include "envoy/upstream/health_checker.h" @@ -256,7 +257,8 @@ ClusterLoadReportStats ClusterInfoImpl::generateLoadReportStats(Stats::Scope& sc ClusterInfoImpl::ClusterInfoImpl(const envoy::api::v2::Cluster& config, const envoy::api::v2::core::BindConfig& bind_config, Runtime::Loader& runtime, Stats::Store& stats, - Ssl::ContextManager& ssl_context_manager, bool added_via_api) + Ssl::ContextManager& ssl_context_manager, + Secret::SecretManager& secret_manager, bool added_via_api) : runtime_(runtime), name_(config.name()), type_(config.type()), max_requests_per_connection_( PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, max_requests_per_connection, 0)), @@ -279,7 +281,8 @@ ClusterInfoImpl::ClusterInfoImpl(const envoy::api::v2::Cluster& config, lb_subset_(LoadBalancerSubsetInfoImpl(config.lb_subset_config())), metadata_(config.metadata()), common_lb_config_(config.common_lb_config()), cluster_socket_options_(parseClusterSocketOptions(config, bind_config)), - drain_connections_on_host_removal_(config.drain_connections_on_host_removal()) { + drain_connections_on_host_removal_(config.drain_connections_on_host_removal()), + secret_manager_(secret_manager) { // If the cluster doesn't have a transport socket configured, override with the default transport // socket implementation based on the tls_context. We copy by value first then override if @@ -425,9 +428,11 @@ ClusterSharedPtr ClusterImplBase::create(const envoy::api::v2::Cluster& cluster, ClusterImplBase::ClusterImplBase(const envoy::api::v2::Cluster& cluster, const envoy::api::v2::core::BindConfig& bind_config, Runtime::Loader& runtime, Stats::Store& stats, - Ssl::ContextManager& ssl_context_manager, bool added_via_api) - : runtime_(runtime), info_(new ClusterInfoImpl(cluster, bind_config, runtime, stats, - ssl_context_manager, added_via_api)) { + Ssl::ContextManager& ssl_context_manager, + Secret::SecretManager& secret_manager, bool added_via_api) + : runtime_(runtime), + info_(new ClusterInfoImpl(cluster, bind_config, runtime, stats, ssl_context_manager, + secret_manager, added_via_api)) { // Create the default (empty) priority set before registering callbacks to // avoid getting an update the first time it is accessed. priority_set_.getOrCreateHostSet(0); @@ -635,7 +640,8 @@ StaticClusterImpl::StaticClusterImpl(const envoy::api::v2::Cluster& cluster, Runtime::Loader& runtime, Stats::Store& stats, Ssl::ContextManager& ssl_context_manager, ClusterManager& cm, bool added_via_api) - : ClusterImplBase(cluster, cm.bindConfig(), runtime, stats, ssl_context_manager, added_via_api), + : ClusterImplBase(cluster, cm.bindConfig(), runtime, stats, ssl_context_manager, + cm.clusterManagerFactory().secretManager(), added_via_api), initial_hosts_(new HostVector()) { for (const auto& host : cluster.hosts()) { @@ -793,7 +799,7 @@ StrictDnsClusterImpl::StrictDnsClusterImpl(const envoy::api::v2::Cluster& cluste ClusterManager& cm, Event::Dispatcher& dispatcher, bool added_via_api) : BaseDynamicClusterImpl(cluster, cm.bindConfig(), runtime, stats, ssl_context_manager, - added_via_api), + cm.clusterManagerFactory().secretManager(), added_via_api), dns_resolver_(dns_resolver), dns_refresh_rate_ms_( std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(cluster, dns_refresh_rate, 5000))) { diff --git a/source/common/upstream/upstream_impl.h b/source/common/upstream/upstream_impl.h index 12984dd0634a..6540b8ac4ca8 100644 --- a/source/common/upstream/upstream_impl.h +++ b/source/common/upstream/upstream_impl.h @@ -17,6 +17,7 @@ #include "envoy/local_info/local_info.h" #include "envoy/network/dns.h" #include "envoy/runtime/runtime.h" +#include "envoy/secret/secret_manager.h" #include "envoy/server/transport_socket_config.h" #include "envoy/ssl/context_manager.h" #include "envoy/thread_local/thread_local.h" @@ -312,7 +313,7 @@ class ClusterInfoImpl : public ClusterInfo, ClusterInfoImpl(const envoy::api::v2::Cluster& config, const envoy::api::v2::core::BindConfig& bind_config, Runtime::Loader& runtime, Stats::Store& stats, Ssl::ContextManager& ssl_context_manager, - bool added_via_api); + Secret::SecretManager& secret_manager, bool added_via_api); static ClusterStats generateStats(Stats::Scope& scope); static ClusterLoadReportStats generateLoadReportStats(Stats::Scope& scope); @@ -362,6 +363,8 @@ class ClusterInfoImpl : public ClusterInfo, bool drainConnectionsOnHostRemoval() const override { return drain_connections_on_host_removal_; } + Secret::SecretManager& secretManager() override { return secret_manager_; } + private: struct ResourceManagers { ResourceManagers(const envoy::api::v2::Cluster& config, Runtime::Loader& runtime, @@ -401,6 +404,7 @@ class ClusterInfoImpl : public ClusterInfo, const envoy::api::v2::Cluster::CommonLbConfig common_lb_config_; const Network::ConnectionSocket::OptionsSharedPtr cluster_socket_options_; const bool drain_connections_on_host_removal_; + Secret::SecretManager& secret_manager_; }; /** @@ -454,7 +458,7 @@ class ClusterImplBase : public Cluster, protected Logger::Loggable( Ssl::ClientContextConfigImpl( MessageUtil::downcastAndValidate( - message)), + message), + context.secretManager()), context.sslContextManager(), context.statsScope()); } @@ -37,7 +38,8 @@ Network::TransportSocketFactoryPtr DownstreamSslSocketFactory::createTransportSo return std::make_unique( Ssl::ServerContextConfigImpl( MessageUtil::downcastAndValidate( - message)), + message), + context.secretManager()), context.sslContextManager(), context.statsScope(), server_names); } diff --git a/source/server/BUILD b/source/server/BUILD index c17bbbc310e9..a4f655db76ad 100644 --- a/source/server/BUILD +++ b/source/server/BUILD @@ -277,6 +277,7 @@ envoy_cc_library( "//source/common/protobuf:utility_lib", "//source/common/router:rds_lib", "//source/common/runtime:runtime_lib", + "//source/common/secret:secret_manager_impl_lib", "//source/common/singleton:manager_impl_lib", "//source/common/stats:thread_local_store_lib", "//source/common/upstream:cluster_manager_lib", diff --git a/source/server/config_validation/cluster_manager.cc b/source/server/config_validation/cluster_manager.cc index 0a6476cad3df..d39ba5542e64 100644 --- a/source/server/config_validation/cluster_manager.cc +++ b/source/server/config_validation/cluster_manager.cc @@ -7,9 +7,9 @@ ValidationClusterManagerFactory::ValidationClusterManagerFactory( Runtime::Loader& runtime, Stats::Store& stats, ThreadLocal::Instance& tls, Runtime::RandomGenerator& random, Network::DnsResolverSharedPtr dns_resolver, Ssl::ContextManager& ssl_context_manager, Event::Dispatcher& main_thread_dispatcher, - const LocalInfo::LocalInfo& local_info) + const LocalInfo::LocalInfo& local_info, Secret::SecretManager& secret_manager) : ProdClusterManagerFactory(runtime, stats, tls, random, dns_resolver, ssl_context_manager, - main_thread_dispatcher, local_info) {} + main_thread_dispatcher, local_info, secret_manager) {} ClusterManagerPtr ValidationClusterManagerFactory::clusterManagerFromProto( const envoy::config::bootstrap::v2::Bootstrap& bootstrap, Stats::Store& stats, diff --git a/source/server/config_validation/cluster_manager.h b/source/server/config_validation/cluster_manager.h index 26a42708544c..85bc6429dc7e 100644 --- a/source/server/config_validation/cluster_manager.h +++ b/source/server/config_validation/cluster_manager.h @@ -1,5 +1,6 @@ #pragma once +#include "envoy/secret/secret_manager.h" #include "envoy/upstream/cluster_manager.h" #include "common/upstream/cluster_manager_impl.h" @@ -20,7 +21,8 @@ class ValidationClusterManagerFactory : public ProdClusterManagerFactory { Network::DnsResolverSharedPtr dns_resolver, Ssl::ContextManager& ssl_context_manager, Event::Dispatcher& main_thread_dispatcher, - const LocalInfo::LocalInfo& local_info); + const LocalInfo::LocalInfo& local_info, + Secret::SecretManager& secret_manager); ClusterManagerPtr clusterManagerFromProto(const envoy::config::bootstrap::v2::Bootstrap& bootstrap, diff --git a/source/server/config_validation/server.cc b/source/server/config_validation/server.cc index 1e933a68b89b..885c0b997a39 100644 --- a/source/server/config_validation/server.cc +++ b/source/server/config_validation/server.cc @@ -78,10 +78,11 @@ void ValidationInstance::initialize(Options& options, Configuration::InitialImpl initial_config(bootstrap); thread_local_.registerThread(*dispatcher_, true); runtime_loader_ = component_factory.createRuntime(*this, initial_config); + secret_manager_.reset(new Secret::SecretManagerImpl()); ssl_context_manager_.reset(new Ssl::ContextManagerImpl(*runtime_loader_)); cluster_manager_factory_.reset(new Upstream::ValidationClusterManagerFactory( runtime(), stats(), threadLocal(), random(), dnsResolver(), sslContextManager(), dispatcher(), - localInfo())); + localInfo(), *secret_manager_)); Configuration::MainImpl* main_config = new Configuration::MainImpl(); config_.reset(main_config); diff --git a/source/server/config_validation/server.h b/source/server/config_validation/server.h index 03783bc131f0..23f4669872d0 100644 --- a/source/server/config_validation/server.h +++ b/source/server/config_validation/server.h @@ -11,6 +11,7 @@ #include "common/common/assert.h" #include "common/router/rds_impl.h" #include "common/runtime/runtime_impl.h" +#include "common/secret/secret_manager_impl.h" #include "common/ssl/context_manager_impl.h" #include "common/stats/stats_impl.h" #include "common/thread_local/thread_local_impl.h" @@ -73,6 +74,7 @@ class ValidationInstance : Logger::Loggable, HotRestart& hotRestart() override { NOT_IMPLEMENTED; } Init::Manager& initManager() override { return init_manager_; } ListenerManager& listenerManager() override { return listener_manager_; } + Secret::SecretManager& secretManager() override { return *secret_manager_; } Runtime::RandomGenerator& random() override { return random_generator_; } RateLimit::ClientPtr rateLimitClient(const absl::optional& timeout) override { @@ -149,6 +151,7 @@ class ValidationInstance : Logger::Loggable, std::unique_ptr cluster_manager_factory_; InitManagerImpl init_manager_; ListenerManagerImpl listener_manager_; + std::unique_ptr secret_manager_; }; } // namespace Server diff --git a/source/server/configuration_impl.cc b/source/server/configuration_impl.cc index e4296bd0d316..0746d48d9d6d 100644 --- a/source/server/configuration_impl.cc +++ b/source/server/configuration_impl.cc @@ -46,6 +46,13 @@ bool FilterChainUtility::buildFilterChain( void MainImpl::initialize(const envoy::config::bootstrap::v2::Bootstrap& bootstrap, Instance& server, Upstream::ClusterManagerFactory& cluster_manager_factory) { + const auto& secrets = bootstrap.static_resources().secrets(); + ENVOY_LOG(info, "loading {} static secret(s)", secrets.size()); + for (ssize_t i = 0; i < secrets.size(); i++) { + ENVOY_LOG(debug, "static secret #{}: {}", i, secrets[i].name()); + server.secretManager().addOrUpdateSecret(secrets[i]); + } + cluster_manager_ = cluster_manager_factory.clusterManagerFromProto( bootstrap, server.stats(), server.threadLocal(), server.runtime(), server.random(), server.localInfo(), server.accessLogManager(), server.admin()); diff --git a/source/server/listener_manager_impl.h b/source/server/listener_manager_impl.h index 95c8911fbdbb..aba7e93ce21a 100644 --- a/source/server/listener_manager_impl.h +++ b/source/server/listener_manager_impl.h @@ -298,6 +298,7 @@ class ListenerImpl : public Network::ListenerConfig, // Configuration::TransportSocketFactoryContext Ssl::ContextManager& sslContextManager() override { return parent_.server_.sslContextManager(); } Stats::Scope& statsScope() const override { return *listener_scope_; } + Secret::SecretManager& secretManager() override { return parent_.server_.secretManager(); } private: void addFilterChain(const std::vector& server_names, diff --git a/source/server/server.cc b/source/server/server.cc index e2aa2072b69b..058463a028af 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -55,6 +55,7 @@ InstanceImpl::InstanceImpl(Options& options, Network::Address::InstanceConstShar handler_(new ConnectionHandlerImpl(ENVOY_LOGGER(), *dispatcher_)), random_generator_(std::move(random_generator)), listener_component_factory_(*this), worker_factory_(thread_local_, *api_, hooks), + secret_manager_(new Secret::SecretManagerImpl()), dns_resolver_(dispatcher_->createDnsResolver({})), access_log_manager_(*api_, *dispatcher_, access_log_lock, store), terminated_(false) { @@ -265,7 +266,7 @@ void InstanceImpl::initialize(Options& options, cluster_manager_factory_.reset(new Upstream::ProdClusterManagerFactory( runtime(), stats(), threadLocal(), random(), dnsResolver(), sslContextManager(), dispatcher(), - localInfo())); + localInfo(), secretManager())); // Now the configuration gets parsed. The configuration may start setting thread local data // per above. See MainImpl::initialize() for why we do this pointer dance. diff --git a/source/server/server.h b/source/server/server.h index 2252aed2c541..16f47450e08e 100644 --- a/source/server/server.h +++ b/source/server/server.h @@ -19,6 +19,7 @@ #include "common/access_log/access_log_manager_impl.h" #include "common/common/logger_delegates.h" #include "common/runtime/runtime_impl.h" +#include "common/secret/secret_manager_impl.h" #include "common/ssl/context_manager_impl.h" #include "server/http/admin.h" @@ -151,6 +152,7 @@ class InstanceImpl : Logger::Loggable, public Instance { HotRestart& hotRestart() override { return restarter_; } Init::Manager& initManager() override { return init_manager_; } ListenerManager& listenerManager() override { return *listener_manager_; } + Secret::SecretManager& secretManager() override { return *secret_manager_; } Runtime::RandomGenerator& random() override { return *random_generator_; } RateLimit::ClientPtr rateLimitClient(const absl::optional& timeout) override { @@ -201,6 +203,7 @@ class InstanceImpl : Logger::Loggable, public Instance { ProdListenerComponentFactory listener_component_factory_; ProdWorkerFactory worker_factory_; std::unique_ptr listener_manager_; + std::unique_ptr secret_manager_; std::unique_ptr config_; Network::DnsResolverSharedPtr dns_resolver_; Event::TimerPtr stat_flush_timer_; diff --git a/test/common/grpc/BUILD b/test/common/grpc/BUILD index 6b56d57f48cc..87a75d94944f 100644 --- a/test/common/grpc/BUILD +++ b/test/common/grpc/BUILD @@ -82,6 +82,7 @@ envoy_cc_test_library( hdrs = ["grpc_client_integration.h"], deps = [ "//source/common/common:assert_lib", + "//test/mocks/secret:secret_mocks", "//test/test_common:utility_lib", ], ) diff --git a/test/common/grpc/grpc_client_integration_test_harness.h b/test/common/grpc/grpc_client_integration_test_harness.h index dcc3f56a4881..e7f23bb54c89 100644 --- a/test/common/grpc/grpc_client_integration_test_harness.h +++ b/test/common/grpc/grpc_client_integration_test_harness.h @@ -11,6 +11,7 @@ #include "test/integration/fake_upstream.h" #include "test/mocks/grpc/mocks.h" #include "test/mocks/local_info/mocks.h" +#include "test/mocks/secret/mocks.h" #include "test/mocks/tracing/mocks.h" #include "test/mocks/upstream/mocks.h" #include "test/proto/helloworld.pb.h" @@ -441,7 +442,7 @@ class GrpcSslClientIntegrationTest : public GrpcClientIntegrationTest { tls_cert->mutable_private_key()->set_filename( TestEnvironment::runfilesPath("test/config/integration/certs/clientkey.pem")); } - Ssl::ClientContextConfigImpl cfg(tls_context); + Ssl::ClientContextConfigImpl cfg(tls_context, secret_manager_); mock_cluster_info_->transport_socket_factory_ = std::make_unique(cfg, context_manager_, *stats_store_); @@ -470,7 +471,8 @@ class GrpcSslClientIntegrationTest : public GrpcClientIntegrationTest { validation_context->mutable_trusted_ca()->set_filename( TestEnvironment::runfilesPath("test/config/integration/certs/cacert.pem")); } - Ssl::ServerContextConfigImpl cfg(tls_context); + + Ssl::ServerContextConfigImpl cfg(tls_context, secret_manager_); static Stats::Scope* upstream_stats_store = new Stats::IsolatedStoreImpl(); return std::make_unique( @@ -478,6 +480,7 @@ class GrpcSslClientIntegrationTest : public GrpcClientIntegrationTest { } bool use_client_cert_{}; + Secret::MockSecretManager secret_manager_; Ssl::ContextManagerImpl context_manager_{runtime_}; }; diff --git a/test/common/secret/BUILD b/test/common/secret/BUILD new file mode 100644 index 000000000000..c65489952a84 --- /dev/null +++ b/test/common/secret/BUILD @@ -0,0 +1,23 @@ +licenses(["notice"]) # Apache 2 + +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_test", + "envoy_package", +) + +envoy_package() + +envoy_cc_test( + name = "secret_manager_impl_test", + srcs = ["secret_manager_impl_test.cc"], + data = [ + "//test/common/ssl/test_data:certs", + ], + deps = [ + "//source/common/secret:secret_manager_impl_lib", + "//test/test_common:environment_lib", + "//test/test_common:registry_lib", + "//test/test_common:utility_lib", + ], +) diff --git a/test/common/secret/secret_manager_impl_test.cc b/test/common/secret/secret_manager_impl_test.cc new file mode 100644 index 000000000000..4c82c3deb817 --- /dev/null +++ b/test/common/secret/secret_manager_impl_test.cc @@ -0,0 +1,73 @@ +#include + +#include "envoy/api/v2/auth/cert.pb.h" +#include "envoy/common/exception.h" + +#include "common/secret/secret_manager_impl.h" + +#include "test/test_common/environment.h" +#include "test/test_common/utility.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Secret { +namespace { + +class SecretManagerImplTest : public testing::Test {}; + +TEST_F(SecretManagerImplTest, SecretLoadSuccess) { + envoy::api::v2::auth::Secret secret_config; + + std::string yaml = + R"EOF( +name: "abc.com" +tls_certificate: + certificate_chain: + filename: "test/common/ssl/test_data/selfsigned_cert.pem" + private_key: + filename: "test/common/ssl/test_data/selfsigned_key.pem" +)EOF"; + + MessageUtil::loadFromYaml(yaml, secret_config); + + std::unique_ptr secret_manager(new SecretManagerImpl()); + + secret_manager->addOrUpdateSecret(secret_config); + + ASSERT_EQ(secret_manager->findTlsCertificate("undefined"), nullptr); + + ASSERT_NE(secret_manager->findTlsCertificate("abc.com"), nullptr); + + EXPECT_EQ( + TestEnvironment::readFileToStringForTest("test/common/ssl/test_data/selfsigned_cert.pem"), + secret_manager->findTlsCertificate("abc.com")->certificateChain()); + + EXPECT_EQ( + TestEnvironment::readFileToStringForTest("test/common/ssl/test_data/selfsigned_key.pem"), + secret_manager->findTlsCertificate("abc.com")->privateKey()); +} + +TEST_F(SecretManagerImplTest, NotImplementedException) { + envoy::api::v2::auth::Secret secret_config; + + std::string yaml = + R"EOF( +name: "abc.com" +session_ticket_keys: + keys: + - filename: "test/common/ssl/test_data/selfsigned_cert.pem" +)EOF"; + + MessageUtil::loadFromYaml(yaml, secret_config); + + std::unique_ptr secret_manager(new SecretManagerImpl()); + + EXPECT_THROW_WITH_MESSAGE(secret_manager->addOrUpdateSecret(secret_config), EnvoyException, + "Secret type not implemented"); +} + +} // namespace +} // namespace Secret +} // namespace Envoy diff --git a/test/common/ssl/BUILD b/test/common/ssl/BUILD index 0e94952fe3a8..8a9265f691da 100644 --- a/test/common/ssl/BUILD +++ b/test/common/ssl/BUILD @@ -35,6 +35,7 @@ envoy_cc_test( "//test/mocks/buffer:buffer_mocks", "//test/mocks/network:network_mocks", "//test/mocks/runtime:runtime_mocks", + "//test/mocks/secret:secret_mocks", "//test/mocks/server:server_mocks", "//test/mocks/stats:stats_mocks", "//test/test_common:environment_lib", @@ -55,10 +56,12 @@ envoy_cc_test( ], deps = [ "//source/common/json:json_loader_lib", + "//source/common/secret:secret_manager_impl_lib", "//source/common/ssl:context_config_lib", "//source/common/ssl:context_lib", "//source/common/stats:stats_lib", "//test/mocks/runtime:runtime_mocks", + "//test/mocks/secret:secret_mocks", "//test/test_common:environment_lib", ], ) diff --git a/test/common/ssl/context_impl_test.cc b/test/common/ssl/context_impl_test.cc index 6e11f18a35ef..5f6002a40987 100644 --- a/test/common/ssl/context_impl_test.cc +++ b/test/common/ssl/context_impl_test.cc @@ -2,12 +2,14 @@ #include #include "common/json/json_loader.h" +#include "common/secret/secret_manager_impl.h" #include "common/ssl/context_config_impl.h" #include "common/ssl/context_impl.h" #include "common/stats/stats_impl.h" #include "test/common/ssl/ssl_certs_test.h" #include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" #include "test/test_common/environment.h" #include "test/test_common/utility.h" @@ -77,7 +79,7 @@ TEST_F(SslContextImplTest, TestCipherSuites) { )EOF"; Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - ClientContextConfigImpl cfg(*loader); + ClientContextConfigImpl cfg(*loader, secret_manager_); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -93,7 +95,7 @@ TEST_F(SslContextImplTest, TestExpiringCert) { )EOF"; Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - ClientContextConfigImpl cfg(*loader); + ClientContextConfigImpl cfg(*loader, secret_manager_); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -116,7 +118,7 @@ TEST_F(SslContextImplTest, TestExpiredCert) { )EOF"; Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - ClientContextConfigImpl cfg(*loader); + ClientContextConfigImpl cfg(*loader, secret_manager_); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -134,7 +136,7 @@ TEST_F(SslContextImplTest, TestGetCertInformation) { )EOF"; Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - ClientContextConfigImpl cfg(*loader); + ClientContextConfigImpl cfg(*loader, secret_manager_); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -160,7 +162,7 @@ TEST_F(SslContextImplTest, TestGetCertInformation) { TEST_F(SslContextImplTest, TestNoCert) { Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString("{}"); - ClientContextConfigImpl cfg(*loader); + ClientContextConfigImpl cfg(*loader, secret_manager_); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -173,6 +175,7 @@ class SslServerContextImplTicketTest : public SslContextImplTest { public: static void loadConfig(ServerContextConfigImpl& cfg) { Runtime::MockLoader runtime; + Secret::MockSecretManager secret_manager; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; ServerContextPtr server_ctx( @@ -188,13 +191,15 @@ class SslServerContextImplTicketTest : public SslContextImplTest { server_cert->mutable_private_key()->set_filename( TestEnvironment::substitute("{{ test_tmpdir }}/unittestkey.pem")); - ServerContextConfigImpl server_context_config(cfg); + Secret::MockSecretManager secret_manager; + ServerContextConfigImpl server_context_config(cfg, secret_manager); loadConfig(server_context_config); } static void loadConfigJson(const std::string& json) { Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - ServerContextConfigImpl cfg(*loader); + Secret::MockSecretManager secret_manager; + ServerContextConfigImpl cfg(*loader, secret_manager); loadConfig(cfg); } }; @@ -346,26 +351,33 @@ TEST_F(SslServerContextImplTicketTest, VerifySanWithNoCA) { "is insecure and not allowed"); } +class ClientContextConfigImplTest : public SslCertsTest {}; + // Validate that empty SNI (according to C string rules) fails config validation. TEST(ClientContextConfigImplTest, EmptyServerNameIndication) { envoy::api::v2::auth::UpstreamTlsContext tls_context; + Secret::MockSecretManager secret_manager; + tls_context.set_sni(std::string("\000", 1)); - EXPECT_THROW_WITH_MESSAGE(ClientContextConfigImpl client_context_config(tls_context), - EnvoyException, "SNI names containing NULL-byte are not allowed"); + EXPECT_THROW_WITH_MESSAGE( + ClientContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, + "SNI names containing NULL-byte are not allowed"); tls_context.set_sni(std::string("a\000b", 3)); - EXPECT_THROW_WITH_MESSAGE(ClientContextConfigImpl client_context_config(tls_context), - EnvoyException, "SNI names containing NULL-byte are not allowed"); + EXPECT_THROW_WITH_MESSAGE( + ClientContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, + "SNI names containing NULL-byte are not allowed"); } // Validate that values other than a hex-encoded SHA-256 fail config validation. TEST(ClientContextConfigImplTest, InvalidCertificateHash) { envoy::api::v2::auth::UpstreamTlsContext tls_context; + Secret::MockSecretManager secret_manager; tls_context.mutable_common_tls_context() ->mutable_validation_context() // This is valid hex-encoded string, but it doesn't represent SHA-256 (80 vs 64 chars). ->add_verify_certificate_hash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - ClientContextConfigImpl client_context_config(tls_context); + ClientContextConfigImpl client_context_config(tls_context, secret_manager); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -376,11 +388,12 @@ TEST(ClientContextConfigImplTest, InvalidCertificateHash) { // Validate that values other than a base64-encoded SHA-256 fail config validation. TEST(ClientContextConfigImplTest, InvalidCertificateSpki) { envoy::api::v2::auth::UpstreamTlsContext tls_context; + Secret::MockSecretManager secret_manager; tls_context.mutable_common_tls_context() ->mutable_validation_context() // Not a base64-encoded string. ->add_verify_certificate_spki("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - ClientContextConfigImpl client_context_config(tls_context); + ClientContextConfigImpl client_context_config(tls_context, secret_manager); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -392,11 +405,74 @@ TEST(ClientContextConfigImplTest, InvalidCertificateSpki) { // TODO(PiotrSikora): Support multiple TLS certificates. TEST(ClientContextConfigImplTest, MultipleTlsCertificates) { envoy::api::v2::auth::UpstreamTlsContext tls_context; + Secret::MockSecretManager secret_manager; tls_context.mutable_common_tls_context()->add_tls_certificates(); tls_context.mutable_common_tls_context()->add_tls_certificates(); - EXPECT_THROW_WITH_MESSAGE(ClientContextConfigImpl client_context_config(tls_context), - EnvoyException, - "Multiple TLS certificates are not supported for client contexts"); + EXPECT_THROW_WITH_MESSAGE( + ClientContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, + "Multiple TLS certificates are not supported for client contexts"); +} + +TEST(ClientContextConfigImplTest, StaticTlsCertificates) { + envoy::api::v2::auth::Secret secret_config; + + std::string yaml = R"EOF( +name: "abc.com" +tls_certificate: + certificate_chain: + filename: "test/common/ssl/test_data/selfsigned_cert.pem" + private_key: + filename: "test/common/ssl/test_data/selfsigned_key.pem" +)EOF"; + + MessageUtil::loadFromYaml(yaml, secret_config); + + std::unique_ptr secret_manager(new Secret::SecretManagerImpl()); + secret_manager->addOrUpdateSecret(secret_config); + + envoy::api::v2::auth::UpstreamTlsContext tls_context; + tls_context.mutable_common_tls_context() + ->mutable_tls_certificate_sds_secret_configs() + ->Add() + ->set_name("abc.com"); + + ClientContextConfigImpl client_context_config(tls_context, *secret_manager.get()); + + EXPECT_EQ( + TestEnvironment::readFileToStringForTest("test/common/ssl/test_data/selfsigned_cert.pem"), + client_context_config.certChain()); + EXPECT_EQ( + TestEnvironment::readFileToStringForTest("test/common/ssl/test_data/selfsigned_key.pem"), + client_context_config.privateKey()); +} + +TEST(ClientContextConfigImplTest, MissingStaticSecretTlsCertificates) { + envoy::api::v2::auth::Secret secret_config; + + std::string yaml = R"EOF( +name: "abc.com" +tls_certificate: + certificate_chain: + filename: "test/common/ssl/test_data/selfsigned_cert.pem" + private_key: + filename: "test/common/ssl/test_data/selfsigned_key.pem" +)EOF"; + + MessageUtil::loadFromYaml(yaml, secret_config); + + std::unique_ptr secret_manager(new Secret::SecretManagerImpl()); + + secret_manager->addOrUpdateSecret(secret_config); + + envoy::api::v2::auth::UpstreamTlsContext tls_context; + tls_context.mutable_common_tls_context() + ->mutable_tls_certificate_sds_secret_configs() + ->Add() + ->set_name("missing"); + + EXPECT_THROW_WITH_MESSAGE( + ClientContextConfigImpl client_context_config(tls_context, *secret_manager.get()), + EnvoyException, "Static secret is not defined: missing"); } // Multiple TLS certificates are not yet supported, but one is expected for @@ -404,21 +480,23 @@ TEST(ClientContextConfigImplTest, MultipleTlsCertificates) { // TODO(PiotrSikora): Support multiple TLS certificates. TEST(ServerContextConfigImplTest, MultipleTlsCertificates) { envoy::api::v2::auth::DownstreamTlsContext tls_context; - EXPECT_THROW_WITH_MESSAGE(ServerContextConfigImpl client_context_config(tls_context), - EnvoyException, - "A single TLS certificate is required for server contexts"); + Secret::MockSecretManager secret_manager; + EXPECT_THROW_WITH_MESSAGE( + ServerContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, + "A single TLS certificate is required for server contexts"); tls_context.mutable_common_tls_context()->add_tls_certificates(); tls_context.mutable_common_tls_context()->add_tls_certificates(); - EXPECT_THROW_WITH_MESSAGE(ServerContextConfigImpl client_context_config(tls_context), - EnvoyException, - "A single TLS certificate is required for server contexts"); + EXPECT_THROW_WITH_MESSAGE( + ServerContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, + "A single TLS certificate is required for server contexts"); } // TlsCertificate messages must have a cert for servers. TEST(ServerContextImplTest, TlsCertificateNonEmpty) { envoy::api::v2::auth::DownstreamTlsContext tls_context; + Secret::MockSecretManager secret_manager; tls_context.mutable_common_tls_context()->add_tls_certificates(); - ServerContextConfigImpl client_context_config(tls_context); + ServerContextConfigImpl client_context_config(tls_context, secret_manager); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -431,15 +509,16 @@ TEST(ServerContextImplTest, TlsCertificateNonEmpty) { // Cannot ignore certificate expiration without a trusted CA. TEST(ServerContextConfigImplTest, InvalidIgnoreCertsNoCA) { envoy::api::v2::auth::DownstreamTlsContext tls_context; + Secret::MockSecretManager secret_manager; envoy::api::v2::auth::CertificateValidationContext* server_validation_ctx = tls_context.mutable_common_tls_context()->mutable_validation_context(); server_validation_ctx->set_allow_expired_certificate(true); - EXPECT_THROW_WITH_MESSAGE(ServerContextConfigImpl server_context_config(tls_context), - EnvoyException, - "Certificate validity period is always ignored without trusted CA"); + EXPECT_THROW_WITH_MESSAGE( + ServerContextConfigImpl server_context_config(tls_context, secret_manager), EnvoyException, + "Certificate validity period is always ignored without trusted CA"); envoy::api::v2::auth::TlsCertificate* server_cert = tls_context.mutable_common_tls_context()->add_tls_certificates(); @@ -450,19 +529,19 @@ TEST(ServerContextConfigImplTest, InvalidIgnoreCertsNoCA) { server_validation_ctx->set_allow_expired_certificate(false); - EXPECT_NO_THROW(ServerContextConfigImpl server_context_config(tls_context)); + EXPECT_NO_THROW(ServerContextConfigImpl server_context_config(tls_context, secret_manager)); server_validation_ctx->set_allow_expired_certificate(true); - EXPECT_THROW_WITH_MESSAGE(ServerContextConfigImpl server_context_config(tls_context), - EnvoyException, - "Certificate validity period is always ignored without trusted CA"); + EXPECT_THROW_WITH_MESSAGE( + ServerContextConfigImpl server_context_config(tls_context, secret_manager), EnvoyException, + "Certificate validity period is always ignored without trusted CA"); // But once you add a trusted CA, you should be able to create the context. server_validation_ctx->mutable_trusted_ca()->set_filename( TestEnvironment::substitute("{{ test_rundir }}/test/common/ssl/test_data/ca_cert.pem")); - EXPECT_NO_THROW(ServerContextConfigImpl server_context_config(tls_context)); + EXPECT_NO_THROW(ServerContextConfigImpl server_context_config(tls_context, secret_manager)); } } // namespace Ssl diff --git a/test/common/ssl/ssl_certs_test.h b/test/common/ssl/ssl_certs_test.h index 4aee4a34986c..2f09e019944a 100644 --- a/test/common/ssl/ssl_certs_test.h +++ b/test/common/ssl/ssl_certs_test.h @@ -1,5 +1,6 @@ #pragma once +#include "test/mocks/secret/mocks.h" #include "test/test_common/environment.h" #include "gtest/gtest.h" @@ -10,5 +11,7 @@ class SslCertsTest : public testing::Test { static void SetUpTestCase() { TestEnvironment::exec({TestEnvironment::runfilesPath("test/common/ssl/gen_unittest_certs.sh")}); } + + Secret::MockSecretManager secret_manager_; }; } // namespace Envoy diff --git a/test/common/ssl/ssl_socket_test.cc b/test/common/ssl/ssl_socket_test.cc index fedab198834f..095600f02cfe 100644 --- a/test/common/ssl/ssl_socket_test.cc +++ b/test/common/ssl/ssl_socket_test.cc @@ -20,6 +20,7 @@ #include "test/mocks/buffer/mocks.h" #include "test/mocks/network/mocks.h" #include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" #include "test/mocks/server/mocks.h" #include "test/mocks/stats/mocks.h" #include "test/test_common/environment.h" @@ -51,9 +52,10 @@ void testUtil(const std::string& client_ctx_json, const std::string& server_ctx_ const Network::Address::IpVersion version) { Stats::IsolatedStoreImpl stats_store; Runtime::MockLoader runtime; + Secret::MockSecretManager secret_manager; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - ServerContextConfigImpl server_ctx_config(*server_ctx_loader); + ServerContextConfigImpl server_ctx_config(*server_ctx_loader, secret_manager); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(server_ctx_config, manager, stats_store, std::vector{}); @@ -66,7 +68,7 @@ void testUtil(const std::string& client_ctx_json, const std::string& server_ctx_ Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false); Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); - ClientContextConfigImpl client_ctx_config(*client_ctx_loader); + ClientContextConfigImpl client_ctx_config(*client_ctx_loader, secret_manager); Ssl::ClientSslSocketFactory client_ssl_socket_factory(client_ctx_config, manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -143,6 +145,7 @@ const std::string testUtilV2(const envoy::api::v2::Listener& server_proto, const Network::Address::IpVersion version) { Stats::IsolatedStoreImpl stats_store; Runtime::MockLoader runtime; + Secret::MockSecretManager secret_manager; ContextManagerImpl manager(runtime); std::string new_session = EMPTY_STRING; @@ -151,7 +154,7 @@ const std::string testUtilV2(const envoy::api::v2::Listener& server_proto, const auto& filter_chain = server_proto.filter_chains(0); std::vector server_names(filter_chain.filter_chain_match().server_names().begin(), filter_chain.filter_chain_match().server_names().end()); - Ssl::ServerContextConfigImpl server_ctx_config(filter_chain.tls_context()); + Ssl::ServerContextConfigImpl server_ctx_config(filter_chain.tls_context(), secret_manager); Ssl::ServerSslSocketFactory server_ssl_socket_factory(server_ctx_config, manager, stats_store, server_names); @@ -162,7 +165,7 @@ const std::string testUtilV2(const envoy::api::v2::Listener& server_proto, Network::MockConnectionHandler connection_handler; Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false); - ClientContextConfigImpl client_ctx_config(client_ctx_proto); + ClientContextConfigImpl client_ctx_config(client_ctx_proto, secret_manager); ClientSslSocketFactory client_ssl_socket_factory(client_ctx_config, manager, stats_store); ClientContextPtr client_ctx(manager.createSslClientContext(stats_store, client_ctx_config)); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( @@ -1513,7 +1516,7 @@ TEST_P(SslSocketTest, FlushCloseDuringHandshake) { )EOF"; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - ServerContextConfigImpl server_ctx_config(*server_ctx_loader); + ServerContextConfigImpl server_ctx_config(*server_ctx_loader, secret_manager_); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(server_ctx_config, manager, stats_store, std::vector{}); @@ -1571,7 +1574,7 @@ TEST_P(SslSocketTest, HalfClose) { )EOF"; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - ServerContextConfigImpl server_ctx_config(*server_ctx_loader); + ServerContextConfigImpl server_ctx_config(*server_ctx_loader, secret_manager_); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(server_ctx_config, manager, stats_store, std::vector{}); @@ -1592,7 +1595,7 @@ TEST_P(SslSocketTest, HalfClose) { )EOF"; Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); - ClientContextConfigImpl client_ctx_config(*client_ctx_loader); + ClientContextConfigImpl client_ctx_config(*client_ctx_loader, secret_manager_); ClientSslSocketFactory client_ssl_socket_factory(client_ctx_config, manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -1644,6 +1647,7 @@ TEST_P(SslSocketTest, HalfClose) { TEST_P(SslSocketTest, ClientAuthMultipleCAs) { Stats::IsolatedStoreImpl stats_store; Runtime::MockLoader runtime; + Secret::MockSecretManager secret_manager; std::string server_ctx_json = R"EOF( { @@ -1654,7 +1658,7 @@ TEST_P(SslSocketTest, ClientAuthMultipleCAs) { )EOF"; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - ServerContextConfigImpl server_ctx_config(*server_ctx_loader); + ServerContextConfigImpl server_ctx_config(*server_ctx_loader, secret_manager); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(server_ctx_config, manager, stats_store, std::vector{}); @@ -1674,7 +1678,7 @@ TEST_P(SslSocketTest, ClientAuthMultipleCAs) { )EOF"; Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); - ClientContextConfigImpl client_ctx_config(*client_ctx_loader); + ClientContextConfigImpl client_ctx_config(*client_ctx_loader, secret_manager); ClientSslSocketFactory ssl_socket_factory(client_ctx_config, manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -1731,12 +1735,13 @@ void testTicketSessionResumption(const std::string& server_ctx_json1, const Network::Address::IpVersion ip_version) { Stats::IsolatedStoreImpl stats_store; Runtime::MockLoader runtime; + Secret::MockSecretManager secret_manager; ContextManagerImpl manager(runtime); Json::ObjectSharedPtr server_ctx_loader1 = TestEnvironment::jsonLoadFromString(server_ctx_json1); Json::ObjectSharedPtr server_ctx_loader2 = TestEnvironment::jsonLoadFromString(server_ctx_json2); - ServerContextConfigImpl server_ctx_config1(*server_ctx_loader1); - ServerContextConfigImpl server_ctx_config2(*server_ctx_loader2); + ServerContextConfigImpl server_ctx_config1(*server_ctx_loader1, secret_manager); + ServerContextConfigImpl server_ctx_config2(*server_ctx_loader2, secret_manager); Ssl::ServerSslSocketFactory server_ssl_socket_factory1(server_ctx_config1, manager, stats_store, server_names1); Ssl::ServerSslSocketFactory server_ssl_socket_factory2(server_ctx_config2, manager, stats_store, @@ -1753,7 +1758,7 @@ void testTicketSessionResumption(const std::string& server_ctx_json1, Network::ListenerPtr listener2 = dispatcher.createListener(socket2, callbacks, true, false); Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); - ClientContextConfigImpl client_ctx_config(*client_ctx_loader); + ClientContextConfigImpl client_ctx_config(*client_ctx_loader, secret_manager); ClientSslSocketFactory ssl_socket_factory(client_ctx_config, manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket1.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -2093,9 +2098,9 @@ TEST_P(SslSocketTest, ClientAuthCrossListenerSessionResumption) { )EOF"; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - ServerContextConfigImpl server_ctx_config(*server_ctx_loader); + ServerContextConfigImpl server_ctx_config(*server_ctx_loader, secret_manager_); Json::ObjectSharedPtr server2_ctx_loader = TestEnvironment::jsonLoadFromString(server2_ctx_json); - ServerContextConfigImpl server2_ctx_config(*server2_ctx_loader); + ServerContextConfigImpl server2_ctx_config(*server2_ctx_loader, secret_manager_); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(server_ctx_config, manager, stats_store, std::vector{}); @@ -2120,7 +2125,7 @@ TEST_P(SslSocketTest, ClientAuthCrossListenerSessionResumption) { )EOF"; Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); - ClientContextConfigImpl client_ctx_config(*client_ctx_loader); + ClientContextConfigImpl client_ctx_config(*client_ctx_loader, secret_manager_); ClientSslSocketFactory ssl_socket_factory(client_ctx_config, manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -2206,7 +2211,7 @@ TEST_P(SslSocketTest, SslError) { )EOF"; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - ServerContextConfigImpl server_ctx_config(*server_ctx_loader); + ServerContextConfigImpl server_ctx_config(*server_ctx_loader, secret_manager_); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(server_ctx_config, manager, stats_store, std::vector{}); @@ -2528,7 +2533,7 @@ class SslReadBufferLimitTest : public SslCertsTest, public: void initialize() { server_ctx_loader_ = TestEnvironment::jsonLoadFromString(server_ctx_json_); - server_ctx_config_.reset(new ServerContextConfigImpl(*server_ctx_loader_)); + server_ctx_config_.reset(new ServerContextConfigImpl(*server_ctx_loader_, secret_manager_)); manager_.reset(new ContextManagerImpl(runtime_)); server_ssl_socket_factory_.reset(new ServerSslSocketFactory( *server_ctx_config_, *manager_, stats_store_, std::vector{})); @@ -2536,7 +2541,7 @@ class SslReadBufferLimitTest : public SslCertsTest, listener_ = dispatcher_->createListener(socket_, listener_callbacks_, true, false); client_ctx_loader_ = TestEnvironment::jsonLoadFromString(client_ctx_json_); - client_ctx_config_.reset(new ClientContextConfigImpl(*client_ctx_loader_)); + client_ctx_config_.reset(new ClientContextConfigImpl(*client_ctx_loader_, secret_manager_)); client_ssl_socket_factory_.reset( new ClientSslSocketFactory(*client_ctx_config_, *manager_, stats_store_)); diff --git a/test/common/upstream/BUILD b/test/common/upstream/BUILD index 90d760ad23bd..6dc40b5cb839 100644 --- a/test/common/upstream/BUILD +++ b/test/common/upstream/BUILD @@ -46,6 +46,7 @@ envoy_cc_test( "//test/mocks/local_info:local_info_mocks", "//test/mocks/network:network_mocks", "//test/mocks/runtime:runtime_mocks", + "//test/mocks/secret:secret_mocks", "//test/mocks/server:server_mocks", "//test/mocks/thread_local:thread_local_mocks", "//test/mocks/upstream:upstream_mocks", diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index 88e5d8753822..28f7094b0ab0 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -20,6 +20,7 @@ #include "test/mocks/local_info/mocks.h" #include "test/mocks/network/mocks.h" #include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" #include "test/mocks/server/mocks.h" #include "test/mocks/thread_local/mocks.h" #include "test/mocks/upstream/mocks.h" @@ -87,6 +88,8 @@ class TestClusterManagerFactory : public ClusterManagerFactory { local_info, log_manager, admin)}; } + Secret::SecretManager& secretManager() override { return secret_manager_; } + MOCK_METHOD8(clusterManagerFromProto_, ClusterManager*(const envoy::config::bootstrap::v2::Bootstrap& bootstrap, Stats::Store& stats, ThreadLocal::Instance& tls, @@ -109,6 +112,7 @@ class TestClusterManagerFactory : public ClusterManagerFactory { Ssl::ContextManagerImpl ssl_context_manager_{runtime_}; NiceMock dispatcher_; LocalInfo::MockLocalInfo local_info_; + Secret::MockSecretManager secret_manager_; }; class ClusterManagerImplTest : public testing::Test { diff --git a/test/config_test/config_test.cc b/test/config_test/config_test.cc index bd3c83b9f848..f29bb540fd19 100644 --- a/test/config_test/config_test.cc +++ b/test/config_test/config_test.cc @@ -43,7 +43,8 @@ class ConfigTest { cluster_manager_factory_.reset(new Upstream::ValidationClusterManagerFactory( server_.runtime(), server_.stats(), server_.threadLocal(), server_.random(), - server_.dnsResolver(), ssl_context_manager_, server_.dispatcher(), server_.localInfo())); + server_.dnsResolver(), ssl_context_manager_, server_.dispatcher(), server_.localInfo(), + server_.secretManager())); ON_CALL(server_, clusterManager()).WillByDefault(Invoke([&]() -> Upstream::ClusterManager& { return *main_config.clusterManager(); diff --git a/test/integration/BUILD b/test/integration/BUILD index 43ca0d78f0ce..2c4b907bdebd 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -34,6 +34,7 @@ envoy_cc_test( "//source/extensions/transport_sockets/ssl:config", "//test/common/grpc:grpc_client_integration_lib", "//test/mocks/runtime:runtime_mocks", + "//test/mocks/secret:secret_mocks", "//test/test_common:network_utility_lib", "//test/test_common:utility_lib", "@envoy_api//envoy/api/v2:cds_cc", @@ -403,6 +404,7 @@ envoy_cc_test( "//source/extensions/filters/listener/tls_inspector:config", "//source/extensions/transport_sockets/ssl:config", "//test/mocks/runtime:runtime_mocks", + "//test/mocks/secret:secret_mocks", "//test/test_common:utility_lib", "@envoy_api//envoy/config/transport_socket/capture/v2alpha:capture_cc", "@envoy_api//envoy/data/tap/v2alpha:capture_cc", @@ -425,6 +427,7 @@ envoy_cc_test( "//source/extensions/access_loggers/file:config", "//source/extensions/filters/network/tcp_proxy:config", "//test/mocks/runtime:runtime_mocks", + "//test/mocks/secret:secret_mocks", "//test/test_common:utility_lib", ], ) @@ -471,6 +474,7 @@ envoy_cc_test( "//source/common/http:header_map_lib", "//source/extensions/filters/listener/tls_inspector:config", "//source/extensions/transport_sockets/ssl:config", + "//test/mocks/secret:secret_mocks", "//test/test_common:utility_lib", ], ) diff --git a/test/integration/ads_integration_test.cc b/test/integration/ads_integration_test.cc index 516309ceceb1..273fa5477978 100644 --- a/test/integration/ads_integration_test.cc +++ b/test/integration/ads_integration_test.cc @@ -19,6 +19,7 @@ #include "test/integration/http_integration.h" #include "test/integration/utility.h" #include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" #include "test/test_common/network_utility.h" #include "test/test_common/utility.h" @@ -81,7 +82,7 @@ class AdsIntegrationTest : public HttpIntegrationTest, public Grpc::GrpcClientIn TestEnvironment::runfilesPath("test/config/integration/certs/upstreamcert.pem")); tls_cert->mutable_private_key()->set_filename( TestEnvironment::runfilesPath("test/config/integration/certs/upstreamkey.pem")); - Ssl::ServerContextConfigImpl cfg(tls_context); + Ssl::ServerContextConfigImpl cfg(tls_context, secret_manager_); static Stats::Scope* upstream_stats_store = new Stats::TestIsolatedStoreImpl(); return std::make_unique( @@ -239,6 +240,7 @@ class AdsIntegrationTest : public HttpIntegrationTest, public Grpc::GrpcClientIn } } + Secret::MockSecretManager secret_manager_; Runtime::MockLoader runtime_; Ssl::ContextManagerImpl context_manager_{runtime_}; FakeHttpConnectionPtr ads_connection_; diff --git a/test/integration/ssl_integration_test.cc b/test/integration/ssl_integration_test.cc index 705bee968cfd..baeab9241f92 100644 --- a/test/integration/ssl_integration_test.cc +++ b/test/integration/ssl_integration_test.cc @@ -35,10 +35,14 @@ void SslIntegrationTest::initialize() { context_manager_.reset(new ContextManagerImpl(*runtime_)); registerTestServerPorts({"http"}); - client_ssl_ctx_plain_ = createClientSslTransportSocketFactory(false, false, *context_manager_); - client_ssl_ctx_alpn_ = createClientSslTransportSocketFactory(true, false, *context_manager_); - client_ssl_ctx_san_ = createClientSslTransportSocketFactory(false, true, *context_manager_); - client_ssl_ctx_alpn_san_ = createClientSslTransportSocketFactory(true, true, *context_manager_); + client_ssl_ctx_plain_ = + createClientSslTransportSocketFactory(false, false, *context_manager_, secret_manager_); + client_ssl_ctx_alpn_ = + createClientSslTransportSocketFactory(true, false, *context_manager_, secret_manager_); + client_ssl_ctx_san_ = + createClientSslTransportSocketFactory(false, true, *context_manager_, secret_manager_); + client_ssl_ctx_alpn_san_ = + createClientSslTransportSocketFactory(true, true, *context_manager_, secret_manager_); } void SslIntegrationTest::TearDown() { diff --git a/test/integration/ssl_integration_test.h b/test/integration/ssl_integration_test.h index 755ef09dddaf..26d21bab7053 100644 --- a/test/integration/ssl_integration_test.h +++ b/test/integration/ssl_integration_test.h @@ -6,6 +6,7 @@ #include "test/integration/http_integration.h" #include "test/integration/server.h" #include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -31,6 +32,7 @@ class SslIntegrationTest : public HttpIntegrationTest, private: std::unique_ptr runtime_; std::unique_ptr context_manager_; + Secret::MockSecretManager secret_manager_; Network::TransportSocketFactoryPtr client_ssl_ctx_plain_; Network::TransportSocketFactoryPtr client_ssl_ctx_alpn_; diff --git a/test/integration/ssl_utility.cc b/test/integration/ssl_utility.cc index 197e39f2781f..9c3d1e773b06 100644 --- a/test/integration/ssl_utility.cc +++ b/test/integration/ssl_utility.cc @@ -14,7 +14,8 @@ namespace Envoy { namespace Ssl { Network::TransportSocketFactoryPtr -createClientSslTransportSocketFactory(bool alpn, bool san, ContextManager& context_manager) { +createClientSslTransportSocketFactory(bool alpn, bool san, ContextManager& context_manager, + Secret::SecretManager& secret_manager) { const std::string json_plain = R"EOF( { "ca_cert_file": "{{ test_rundir }}/test/config/integration/certs/cacert.pem", @@ -58,7 +59,7 @@ createClientSslTransportSocketFactory(bool alpn, bool san, ContextManager& conte target = san ? json_san : json_plain; } Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(target); - ClientContextConfigImpl cfg(*loader); + ClientContextConfigImpl cfg(*loader, secret_manager); static auto* client_stats_store = new Stats::TestIsolatedStoreImpl(); return Network::TransportSocketFactoryPtr{ new Ssl::ClientSslSocketFactory(cfg, context_manager, *client_stats_store)}; diff --git a/test/integration/ssl_utility.h b/test/integration/ssl_utility.h index 1110652a766f..d2ff42561bd4 100644 --- a/test/integration/ssl_utility.h +++ b/test/integration/ssl_utility.h @@ -2,13 +2,15 @@ #include "envoy/network/address.h" #include "envoy/network/transport_socket.h" +#include "envoy/secret/secret_manager.h" #include "envoy/ssl/context_manager.h" namespace Envoy { namespace Ssl { Network::TransportSocketFactoryPtr -createClientSslTransportSocketFactory(bool alpn, bool san, ContextManager& context_manager); +createClientSslTransportSocketFactory(bool alpn, bool san, ContextManager& context_manager, + Secret::SecretManager& secret_manager); Network::Address::InstanceConstSharedPtr getSslAddress(const Network::Address::IpVersion& version, int port); diff --git a/test/integration/tcp_proxy_integration_test.cc b/test/integration/tcp_proxy_integration_test.cc index b8baa806687d..4c48974950ea 100644 --- a/test/integration/tcp_proxy_integration_test.cc +++ b/test/integration/tcp_proxy_integration_test.cc @@ -321,7 +321,8 @@ void TcpProxySslIntegrationTest::setupConnections() { // Set up the SSl client. Network::Address::InstanceConstSharedPtr address = Ssl::getSslAddress(version_, lookupPort("tcp_proxy")); - context_ = Ssl::createClientSslTransportSocketFactory(false, false, *context_manager_); + context_ = + Ssl::createClientSslTransportSocketFactory(false, false, *context_manager_, secret_manager_); ssl_client_ = dispatcher_->createClientConnection(address, Network::Address::InstanceConstSharedPtr(), context_->createTransportSocket(), nullptr); diff --git a/test/integration/tcp_proxy_integration_test.h b/test/integration/tcp_proxy_integration_test.h index 166c0c052942..0532890980ba 100644 --- a/test/integration/tcp_proxy_integration_test.h +++ b/test/integration/tcp_proxy_integration_test.h @@ -5,6 +5,7 @@ #include "test/integration/integration.h" #include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" #include "gtest/gtest.h" @@ -40,6 +41,7 @@ class TcpProxySslIntegrationTest : public TcpProxyIntegrationTest { ConnectionStatusCallbacks connect_callbacks_; MockWatermarkBuffer* client_write_buffer_; std::shared_ptr payload_reader_; + Secret::MockSecretManager secret_manager_; }; } // namespace diff --git a/test/integration/xfcc_integration_test.cc b/test/integration/xfcc_integration_test.cc index 76be3b8d4ea3..8f444b0ae763 100644 --- a/test/integration/xfcc_integration_test.cc +++ b/test/integration/xfcc_integration_test.cc @@ -57,7 +57,7 @@ Network::TransportSocketFactoryPtr XfccIntegrationTest::createClientSslContext(b target = json_tls; } Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(target); - Ssl::ClientContextConfigImpl cfg(*loader); + Ssl::ClientContextConfigImpl cfg(*loader, secret_manager_); static auto* client_stats_store = new Stats::TestIsolatedStoreImpl(); return Network::TransportSocketFactoryPtr{ new Ssl::ClientSslSocketFactory(cfg, *context_manager_, *client_stats_store)}; @@ -72,7 +72,7 @@ Network::TransportSocketFactoryPtr XfccIntegrationTest::createUpstreamSslContext )EOF"; Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - Ssl::ServerContextConfigImpl cfg(*loader); + Ssl::ServerContextConfigImpl cfg(*loader, secret_manager_); static Stats::Scope* upstream_stats_store = new Stats::TestIsolatedStoreImpl(); return std::make_unique( cfg, *context_manager_, *upstream_stats_store, std::vector{}); diff --git a/test/integration/xfcc_integration_test.h b/test/integration/xfcc_integration_test.h index 6a9b300c2639..3432313af715 100644 --- a/test/integration/xfcc_integration_test.h +++ b/test/integration/xfcc_integration_test.h @@ -6,6 +6,7 @@ #include "test/integration/http_integration.h" #include "test/integration/server.h" #include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -55,6 +56,7 @@ class XfccIntegrationTest : public HttpIntegrationTest, Network::TransportSocketFactoryPtr client_tls_ssl_ctx_; Network::TransportSocketFactoryPtr client_mtls_ssl_ctx_; Network::TransportSocketFactoryPtr upstream_ssl_ctx_; + Secret::MockSecretManager secret_manager_; }; } // namespace Xfcc } // namespace Envoy diff --git a/test/mocks/secret/BUILD b/test/mocks/secret/BUILD new file mode 100644 index 000000000000..f3d6223461cd --- /dev/null +++ b/test/mocks/secret/BUILD @@ -0,0 +1,19 @@ +licenses(["notice"]) # Apache 2 + +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_mock", + "envoy_package", +) + +envoy_package() + +envoy_cc_mock( + name = "secret_mocks", + srcs = ["mocks.cc"], + hdrs = ["mocks.h"], + deps = [ + "//include/envoy/secret:secret_manager_interface", + "//include/envoy/ssl:tls_certificate_config_interface", + ], +) diff --git a/test/mocks/secret/mocks.cc b/test/mocks/secret/mocks.cc new file mode 100644 index 000000000000..e11b7de14dde --- /dev/null +++ b/test/mocks/secret/mocks.cc @@ -0,0 +1,11 @@ +#include "test/mocks/secret/mocks.h" + +namespace Envoy { +namespace Secret { + +MockSecretManager::MockSecretManager() {} + +MockSecretManager::~MockSecretManager() {} + +} // namespace Secret +} // namespace Envoy diff --git a/test/mocks/secret/mocks.h b/test/mocks/secret/mocks.h new file mode 100644 index 000000000000..1d111df74993 --- /dev/null +++ b/test/mocks/secret/mocks.h @@ -0,0 +1,22 @@ +#pragma once + +#include "envoy/secret/secret_manager.h" +#include "envoy/ssl/tls_certificate_config.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Secret { + +class MockSecretManager : public SecretManager { +public: + MockSecretManager(); + ~MockSecretManager(); + + MOCK_METHOD1(addOrUpdateSecret, void(const envoy::api::v2::auth::Secret& secret)); + MOCK_CONST_METHOD1(findTlsCertificate, const Ssl::TlsCertificateConfig*(const std::string& name)); +}; + +} // namespace Secret +} // namespace Envoy diff --git a/test/mocks/server/BUILD b/test/mocks/server/BUILD index 1cbf1ef51048..8d203b45580e 100644 --- a/test/mocks/server/BUILD +++ b/test/mocks/server/BUILD @@ -13,6 +13,7 @@ envoy_cc_mock( srcs = ["mocks.cc"], hdrs = ["mocks.h"], deps = [ + "//include/envoy/secret:secret_manager_interface", "//include/envoy/server:admin_interface", "//include/envoy/server:configuration_interface", "//include/envoy/server:drain_manager_interface", @@ -23,6 +24,7 @@ envoy_cc_mock( "//include/envoy/server:options_interface", "//include/envoy/server:worker_interface", "//include/envoy/ssl:context_manager_interface", + "//source/common/secret:secret_manager_impl_lib", "//source/common/singleton:manager_impl_lib", "//source/common/ssl:context_lib", "//source/common/stats:stats_lib", @@ -34,6 +36,7 @@ envoy_cc_mock( "//test/mocks/network:network_mocks", "//test/mocks/router:router_mocks", "//test/mocks/runtime:runtime_mocks", + "//test/mocks/secret:secret_mocks", "//test/mocks/thread_local:thread_local_mocks", "//test/mocks/tracing:tracing_mocks", "//test/mocks/upstream:upstream_mocks", diff --git a/test/mocks/server/mocks.cc b/test/mocks/server/mocks.cc index b33b61bec720..72724db9b04d 100644 --- a/test/mocks/server/mocks.cc +++ b/test/mocks/server/mocks.cc @@ -107,7 +107,8 @@ MockWorker::MockWorker() { MockWorker::~MockWorker() {} MockInstance::MockInstance() - : ssl_context_manager_(runtime_loader_), singleton_manager_(new Singleton::ManagerImpl()) { + : secret_manager_(new Secret::SecretManagerImpl()), ssl_context_manager_(runtime_loader_), + singleton_manager_(new Singleton::ManagerImpl()) { ON_CALL(*this, threadLocal()).WillByDefault(ReturnRef(thread_local_)); ON_CALL(*this, stats()).WillByDefault(ReturnRef(stats_store_)); ON_CALL(*this, httpTracer()).WillByDefault(ReturnRef(http_tracer_)); diff --git a/test/mocks/server/mocks.h b/test/mocks/server/mocks.h index 6899d5467858..ceefff32ae8b 100644 --- a/test/mocks/server/mocks.h +++ b/test/mocks/server/mocks.h @@ -17,6 +17,7 @@ #include "envoy/ssl/context_manager.h" #include "envoy/thread/thread.h" +#include "common/secret/secret_manager_impl.h" #include "common/ssl/context_manager_impl.h" #include "common/stats/stats_impl.h" @@ -29,6 +30,7 @@ #include "test/mocks/network/mocks.h" #include "test/mocks/router/mocks.h" #include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" #include "test/mocks/thread_local/mocks.h" #include "test/mocks/tracing/mocks.h" #include "test/mocks/upstream/mocks.h" @@ -273,6 +275,8 @@ class MockInstance : public Instance { return RateLimit::ClientPtr{rateLimitClient_()}; } + Secret::SecretManager& secretManager() override { return *(secret_manager_.get()); } + MOCK_METHOD0(admin, Admin&()); MOCK_METHOD0(api, Api::Api&()); MOCK_METHOD0(clusterManager, Upstream::ClusterManager&()); @@ -303,6 +307,7 @@ class MockInstance : public Instance { MOCK_METHOD0(localInfo, const LocalInfo::LocalInfo&()); MOCK_CONST_METHOD0(statsFlushInterval, std::chrono::milliseconds()); + std::unique_ptr secret_manager_; testing::NiceMock thread_local_; Stats::IsolatedStoreImpl stats_store_; testing::NiceMock http_tracer_; diff --git a/test/mocks/ssl/BUILD b/test/mocks/ssl/BUILD index fffa33cfe06e..39330f6db353 100644 --- a/test/mocks/ssl/BUILD +++ b/test/mocks/ssl/BUILD @@ -18,5 +18,6 @@ envoy_cc_mock( "//include/envoy/ssl:context_interface", "//include/envoy/ssl:context_manager_interface", "//include/envoy/stats:stats_interface", + "//test/mocks/secret:secret_mocks", ], ) diff --git a/test/mocks/ssl/mocks.h b/test/mocks/ssl/mocks.h index d7b6a8705cff..60691fa39797 100644 --- a/test/mocks/ssl/mocks.h +++ b/test/mocks/ssl/mocks.h @@ -9,6 +9,8 @@ #include "envoy/ssl/context_manager.h" #include "envoy/stats/stats.h" +#include "test/mocks/secret/mocks.h" + #include "gmock/gmock.h" namespace Envoy { diff --git a/test/mocks/upstream/BUILD b/test/mocks/upstream/BUILD index 67d54226e152..753a2727ba90 100644 --- a/test/mocks/upstream/BUILD +++ b/test/mocks/upstream/BUILD @@ -50,6 +50,7 @@ envoy_cc_mock( "//test/mocks/grpc:grpc_mocks", "//test/mocks/http:http_mocks", "//test/mocks/runtime:runtime_mocks", + "//test/mocks/secret:secret_mocks", "//test/mocks/stats:stats_mocks", ], ) diff --git a/test/mocks/upstream/mocks.h b/test/mocks/upstream/mocks.h index 1e9047487d50..109cc31c2c67 100644 --- a/test/mocks/upstream/mocks.h +++ b/test/mocks/upstream/mocks.h @@ -18,6 +18,7 @@ #include "test/mocks/grpc/mocks.h" #include "test/mocks/http/mocks.h" #include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" #include "test/mocks/stats/mocks.h" #include "test/mocks/upstream/cluster_info.h" @@ -134,6 +135,39 @@ class MockThreadLocalCluster : public ThreadLocalCluster { NiceMock lb_; }; +class MockClusterManagerFactory : public ClusterManagerFactory { +public: + MockClusterManagerFactory() {} + ~MockClusterManagerFactory() {} + + Secret::MockSecretManager& secretManager() override { return secret_manager_; }; + + MOCK_METHOD8(clusterManagerFromProto, + ClusterManagerPtr(const envoy::config::bootstrap::v2::Bootstrap& bootstrap, + Stats::Store& stats, ThreadLocal::Instance& tls, + Runtime::Loader& runtime, Runtime::RandomGenerator& random, + const LocalInfo::LocalInfo& local_info, + AccessLog::AccessLogManager& log_manager, Server::Admin& admin)); + + MOCK_METHOD5(allocateConnPool, Http::ConnectionPool::InstancePtr( + Event::Dispatcher& dispatcher, HostConstSharedPtr host, + ResourcePriority priority, Http::Protocol protocol, + const Network::ConnectionSocket::OptionsSharedPtr& options)); + + MOCK_METHOD4(clusterFromProto, + ClusterSharedPtr(const envoy::api::v2::Cluster& cluster, ClusterManager& cm, + Outlier::EventLoggerSharedPtr outlier_event_logger, + bool added_via_api)); + + MOCK_METHOD3(createCds, + CdsApiPtr(const envoy::api::v2::core::ConfigSource& cds_config, + const absl::optional& eds_config, + ClusterManager& cm)); + +private: + Secret::MockSecretManager secret_manager_; +}; + class MockClusterManager : public ClusterManager { public: MockClusterManager(); @@ -145,6 +179,8 @@ class MockClusterManager : public ClusterManager { return {Network::ClientConnectionPtr{data.connection_}, data.host_description_}; } + ClusterManagerFactory& clusterManagerFactory() override { return cluster_manager_factory_; } + // Upstream::ClusterManager MOCK_METHOD2(addOrUpdateCluster, bool(const envoy::api::v2::Cluster& cluster, const std::string& version_info)); @@ -176,6 +212,7 @@ class MockClusterManager : public ClusterManager { NiceMock ads_mux_; NiceMock async_client_manager_; std::string local_cluster_name_; + NiceMock cluster_manager_factory_; }; class MockHealthChecker : public HealthChecker { diff --git a/test/server/BUILD b/test/server/BUILD index 5a7c7d9a26cf..723c30ef32d0 100644 --- a/test/server/BUILD +++ b/test/server/BUILD @@ -25,6 +25,9 @@ envoy_cc_test( envoy_cc_test( name = "configuration_impl_test", srcs = ["configuration_impl_test.cc"], + data = [ + "//test/config/integration/certs", + ], deps = [ "//source/common/event:dispatcher_lib", "//source/common/upstream:cluster_manager_lib", diff --git a/test/server/config_validation/BUILD b/test/server/config_validation/BUILD index 67a377e52dfd..2925a168f5ac 100644 --- a/test/server/config_validation/BUILD +++ b/test/server/config_validation/BUILD @@ -33,6 +33,7 @@ envoy_cc_test( "//test/mocks/local_info:local_info_mocks", "//test/mocks/network:network_mocks", "//test/mocks/runtime:runtime_mocks", + "//test/mocks/secret:secret_mocks", "//test/mocks/server:server_mocks", "//test/mocks/thread_local:thread_local_mocks", "//test/mocks/upstream:upstream_mocks", diff --git a/test/server/config_validation/cluster_manager_test.cc b/test/server/config_validation/cluster_manager_test.cc index 1ccfdb92c7b1..cafd2666a4de 100644 --- a/test/server/config_validation/cluster_manager_test.cc +++ b/test/server/config_validation/cluster_manager_test.cc @@ -12,6 +12,7 @@ #include "test/mocks/local_info/mocks.h" #include "test/mocks/network/mocks.h" #include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" #include "test/mocks/server/mocks.h" #include "test/mocks/thread_local/mocks.h" #include "test/mocks/upstream/mocks.h" @@ -25,6 +26,7 @@ TEST(ValidationClusterManagerTest, MockedMethods) { Stats::IsolatedStoreImpl stats; NiceMock tls; NiceMock random; + Secret::MockSecretManager secret_manager; auto dns_resolver = std::make_shared>(); Ssl::ContextManagerImpl ssl_context_manager{runtime}; NiceMock dispatcher; @@ -32,7 +34,8 @@ TEST(ValidationClusterManagerTest, MockedMethods) { NiceMock admin; ValidationClusterManagerFactory factory(runtime, stats, tls, random, dns_resolver, - ssl_context_manager, dispatcher, local_info); + ssl_context_manager, dispatcher, local_info, + secret_manager); AccessLog::MockAccessLogManager log_manager; const envoy::config::bootstrap::v2::Bootstrap bootstrap; diff --git a/test/server/configuration_impl_test.cc b/test/server/configuration_impl_test.cc index de84f98a5583..bec9bb6d0567 100644 --- a/test/server/configuration_impl_test.cc +++ b/test/server/configuration_impl_test.cc @@ -2,7 +2,9 @@ #include #include +#include "common/config/bootstrap_json.h" #include "common/config/well_known_names.h" +#include "common/json/json_loader.h" #include "common/upstream/cluster_manager_impl.h" #include "server/configuration_impl.h" @@ -53,7 +55,7 @@ class ConfigurationImplTest : public testing::Test { : cluster_manager_factory_(server_.runtime(), server_.stats(), server_.threadLocal(), server_.random(), server_.dnsResolver(), server_.sslContextManager(), server_.dispatcher(), - server_.localInfo()) {} + server_.localInfo(), server_.secretManager()) {} NiceMock server_; Upstream::ProdClusterManagerFactory cluster_manager_factory_;