diff --git a/include/envoy/secret/BUILD b/include/envoy/secret/BUILD index c4dcf8404fd6f..6124d51a32100 100644 --- a/include/envoy/secret/BUILD +++ b/include/envoy/secret/BUILD @@ -8,11 +8,19 @@ load( envoy_package() +envoy_cc_library( + name = "secret_provider_interface", + hdrs = ["secret_provider.h"], + deps = [ + "//include/envoy/ssl:tls_certificate_config_interface", + ], +) + envoy_cc_library( name = "secret_manager_interface", hdrs = ["secret_manager.h"], deps = [ - "//include/envoy/ssl:tls_certificate_config_interface", + ":secret_provider_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 index d7f9788741213..85f5e7228f723 100644 --- a/include/envoy/secret/secret_manager.h +++ b/include/envoy/secret/secret_manager.h @@ -3,7 +3,7 @@ #include #include "envoy/api/v2/auth/cert.pb.h" -#include "envoy/ssl/tls_certificate_config.h" +#include "envoy/secret/secret_provider.h" namespace Envoy { namespace Secret { @@ -18,16 +18,25 @@ class SecretManager { virtual ~SecretManager() {} /** - * @param secret a protobuf message of envoy::api::v2::auth::Secret. - * @throw an EnvoyException if the secret is invalid or not supported. + * @param add a static secret from envoy::api::v2::auth::Secret. + * @throw an EnvoyException if the secret is invalid or not supported, or there is duplicate. */ - virtual void addOrUpdateSecret(const envoy::api::v2::auth::Secret& secret) PURE; + virtual void addStaticSecret(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. + * @param name a name of the static TlsCertificateConfigProvider. + * @return the TlsCertificateConfigProviderSharedPtr. Returns nullptr if the static secret is not + * found. */ - virtual const Ssl::TlsCertificateConfig* findTlsCertificate(const std::string& name) const PURE; + virtual TlsCertificateConfigProviderSharedPtr + findStaticTlsCertificateProvider(const std::string& name) const PURE; + + /** + * @param tls_certificate the protobuf config of the TLS certificate. + * @return a TlsCertificateConfigProviderSharedPtr created from tls_certificate. + */ + virtual TlsCertificateConfigProviderSharedPtr createInlineTlsCertificateProvider( + const envoy::api::v2::auth::TlsCertificate& tls_certificate) PURE; }; } // namespace Secret diff --git a/include/envoy/secret/secret_provider.h b/include/envoy/secret/secret_provider.h new file mode 100644 index 0000000000000..b6f9f26ca76ce --- /dev/null +++ b/include/envoy/secret/secret_provider.h @@ -0,0 +1,28 @@ +#pragma once + +#include "envoy/common/pure.h" +#include "envoy/ssl/tls_certificate_config.h" + +namespace Envoy { +namespace Secret { + +/** + * A secret provider for each kind of secret. + */ +template class SecretProvider { +public: + virtual ~SecretProvider() {} + + /** + * @return the secret. Returns nullptr if the secret is not ready. + */ + virtual const SecretType* secret() const PURE; + + // TODO(lizan): Add more methods for dynamic secret provider. +}; + +typedef SecretProvider TlsCertificateConfigProvider; +typedef std::shared_ptr TlsCertificateConfigProviderSharedPtr; + +} // namespace Secret +} // namespace Envoy diff --git a/include/envoy/ssl/context_config.h b/include/envoy/ssl/context_config.h index 6e2236dfcaaa7..20f76b5c38c29 100644 --- a/include/envoy/ssl/context_config.h +++ b/include/envoy/ssl/context_config.h @@ -60,6 +60,7 @@ class ContextConfig { */ virtual const std::string& certificateRevocationListPath() const PURE; + // TODO(lizan): consider refactor 4 methods below to Ssl::TlsCertificateConfig /** * @return The certificate chain used to identify the local side. */ diff --git a/include/envoy/ssl/tls_certificate_config.h b/include/envoy/ssl/tls_certificate_config.h index 6a5c8c842a060..945111f6835e4 100644 --- a/include/envoy/ssl/tls_certificate_config.h +++ b/include/envoy/ssl/tls_certificate_config.h @@ -17,10 +17,22 @@ class TlsCertificateConfig { */ virtual const std::string& certificateChain() const PURE; + /** + * @return Path of the certificate chain used to identify the local side or "" + * if the certificate chain was inlined. + */ + virtual const std::string& certificateChainPath() const PURE; + /** * @return a string of private key */ virtual const std::string& privateKey() const PURE; + + /** + * @return Path of the private key used to identify the local side or "" + * if the private key was inlined. + */ + virtual const std::string& privateKeyPath() const PURE; }; typedef std::unique_ptr TlsCertificateConfigPtr; diff --git a/source/common/config/datasource.cc b/source/common/config/datasource.cc index 7d8d58375733b..d1754f6697f0c 100644 --- a/source/common/config/datasource.cc +++ b/source/common/config/datasource.cc @@ -25,9 +25,10 @@ std::string read(const envoy::api::v2::core::DataSource& source, bool allow_empt } } -std::string getPath(const envoy::api::v2::core::DataSource& source) { - return source.specifier_case() == envoy::api::v2::core::DataSource::kFilename ? source.filename() - : ""; +absl::optional getPath(const envoy::api::v2::core::DataSource& source) { + return source.specifier_case() == envoy::api::v2::core::DataSource::kFilename + ? absl::make_optional(source.filename()) + : absl::nullopt; } } // namespace DataSource diff --git a/source/common/config/datasource.h b/source/common/config/datasource.h index e5c74063155b9..16ff658dcbca6 100644 --- a/source/common/config/datasource.h +++ b/source/common/config/datasource.h @@ -2,6 +2,8 @@ #include "envoy/api/v2/core/base.pb.h" +#include "absl/types/optional.h" + namespace Envoy { namespace Config { namespace DataSource { @@ -17,9 +19,9 @@ std::string read(const envoy::api::v2::core::DataSource& source, bool allow_empt /** * @param source data source. - * @return std::string path to DataSource if a filename, otherwise an empty string. + * @return absl::optional path to DataSource if a filename, otherwise absl::nullopt. */ -std::string getPath(const envoy::api::v2::core::DataSource& source); +absl::optional getPath(const envoy::api::v2::core::DataSource& source); } // namespace DataSource } // namespace Config diff --git a/source/common/secret/BUILD b/source/common/secret/BUILD index 4f1eff746d6d9..598d8249fa5ea 100644 --- a/source/common/secret/BUILD +++ b/source/common/secret/BUILD @@ -13,8 +13,19 @@ envoy_cc_library( srcs = ["secret_manager_impl.cc"], hdrs = ["secret_manager_impl.h"], deps = [ + ":secret_provider_impl_lib", "//include/envoy/secret:secret_manager_interface", "//source/common/common:minimal_logger_lib", + "@envoy_api//envoy/api/v2/auth:cert_cc", + ], +) + +envoy_cc_library( + name = "secret_provider_impl_lib", + srcs = ["secret_provider_impl.cc"], + hdrs = ["secret_provider_impl.h"], + deps = [ + "//include/envoy/secret:secret_provider_interface", "//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 index 3e6689a369da4..f3f2c9549ea8f 100644 --- a/source/common/secret/secret_manager_impl.cc +++ b/source/common/secret/secret_manager_impl.cc @@ -2,26 +2,39 @@ #include "envoy/common/exception.h" +#include "common/common/assert.h" +#include "common/secret/secret_provider_impl.h" #include "common/ssl/tls_certificate_config_impl.h" namespace Envoy { namespace Secret { -void SecretManagerImpl::addOrUpdateSecret(const envoy::api::v2::auth::Secret& secret) { +void SecretManagerImpl::addStaticSecret(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()); + case envoy::api::v2::auth::Secret::TypeCase::kTlsCertificate: { + auto secret_provider = + std::make_shared(secret.tls_certificate()); + if (!static_tls_certificate_providers_.insert(std::make_pair(secret.name(), secret_provider)) + .second) { + throw EnvoyException( + fmt::format("Duplicate static TlsCertificate secret name {}", secret.name())); + } 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; +TlsCertificateConfigProviderSharedPtr +SecretManagerImpl::findStaticTlsCertificateProvider(const std::string& name) const { + auto secret = static_tls_certificate_providers_.find(name); + return (secret != static_tls_certificate_providers_.end()) ? secret->second : nullptr; +} + +TlsCertificateConfigProviderSharedPtr SecretManagerImpl::createInlineTlsCertificateProvider( + const envoy::api::v2::auth::TlsCertificate& tls_certificate) { + return std::make_shared(tls_certificate); } } // namespace Secret diff --git a/source/common/secret/secret_manager_impl.h b/source/common/secret/secret_manager_impl.h index b9406754a8c45..6af790f50c422 100644 --- a/source/common/secret/secret_manager_impl.h +++ b/source/common/secret/secret_manager_impl.h @@ -3,6 +3,7 @@ #include #include "envoy/secret/secret_manager.h" +#include "envoy/secret/secret_provider.h" #include "envoy/ssl/tls_certificate_config.h" #include "common/common/logger.h" @@ -12,11 +13,15 @@ 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; + void addStaticSecret(const envoy::api::v2::auth::Secret& secret) override; + TlsCertificateConfigProviderSharedPtr + findStaticTlsCertificateProvider(const std::string& name) const override; + TlsCertificateConfigProviderSharedPtr createInlineTlsCertificateProvider( + const envoy::api::v2::auth::TlsCertificate& tls_certificate) override; private: - std::unordered_map tls_certificate_secrets_; + std::unordered_map + static_tls_certificate_providers_; }; } // namespace Secret diff --git a/source/common/secret/secret_provider_impl.cc b/source/common/secret/secret_provider_impl.cc new file mode 100644 index 0000000000000..961924bef5a81 --- /dev/null +++ b/source/common/secret/secret_provider_impl.cc @@ -0,0 +1,14 @@ +#include "common/secret/secret_provider_impl.h" + +#include "common/common/assert.h" +#include "common/ssl/tls_certificate_config_impl.h" + +namespace Envoy { +namespace Secret { + +TlsCertificateConfigProviderImpl::TlsCertificateConfigProviderImpl( + const envoy::api::v2::auth::TlsCertificate& tls_certificate) + : tls_certificate_(std::make_unique(tls_certificate)) {} + +} // namespace Secret +} // namespace Envoy diff --git a/source/common/secret/secret_provider_impl.h b/source/common/secret/secret_provider_impl.h new file mode 100644 index 0000000000000..9ac79c66009c7 --- /dev/null +++ b/source/common/secret/secret_provider_impl.h @@ -0,0 +1,21 @@ +#pragma once + +#include "envoy/api/v2/auth/cert.pb.h" +#include "envoy/secret/secret_provider.h" +#include "envoy/ssl/tls_certificate_config.h" + +namespace Envoy { +namespace Secret { + +class TlsCertificateConfigProviderImpl : public TlsCertificateConfigProvider { +public: + TlsCertificateConfigProviderImpl(const envoy::api::v2::auth::TlsCertificate& tls_certificate); + + const Ssl::TlsCertificateConfig* secret() const override { return tls_certificate_.get(); } + +private: + Ssl::TlsCertificateConfigPtr tls_certificate_; +}; + +} // namespace Secret +} // namespace Envoy diff --git a/source/common/ssl/BUILD b/source/common/ssl/BUILD index dfeda75e6708a..abc98f802ff0b 100644 --- a/source/common/ssl/BUILD +++ b/source/common/ssl/BUILD @@ -35,6 +35,7 @@ envoy_cc_library( ], deps = [ "//include/envoy/secret:secret_manager_interface", + "//include/envoy/secret:secret_provider_interface", "//include/envoy/ssl:context_config_interface", "//source/common/common:assert_lib", "//source/common/common:empty_string", @@ -78,6 +79,7 @@ envoy_cc_library( hdrs = ["tls_certificate_config_impl.h"], deps = [ "//include/envoy/ssl:tls_certificate_config_interface", + "//source/common/common:empty_string", "//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 1b2fee09b383d..fd9f49ed210ce 100644 --- a/source/common/ssl/context_config_impl.cc +++ b/source/common/ssl/context_config_impl.cc @@ -16,23 +16,28 @@ 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) { +Secret::TlsCertificateConfigProviderSharedPtr +getTlsCertificateConfigProvider(const envoy::api::v2::auth::CommonTlsContext& config, + Secret::SecretManager& secret_manager) { 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)); + const auto& tls_certificate = config.tls_certificates(0); + if (!tls_certificate.has_certificate_chain() && !tls_certificate.has_private_key()) { + return nullptr; } - return read_secret(*secret); - } else { - return EMPTY_STRING; + return secret_manager.createInlineTlsCertificateProvider(config.tls_certificates(0)); } + if (!config.tls_certificate_sds_secret_configs().empty()) { + const auto& sds_secret_config = config.tls_certificate_sds_secret_configs(0); + + auto secret_provider = + secret_manager.findStaticTlsCertificateProvider(sds_secret_config.name()); + if (!secret_provider) { + throw EnvoyException( + fmt::format("Static secret is not defined: {}", sds_secret_config.name())); + } + return secret_provider; + } + return nullptr; } } // namespace @@ -62,35 +67,13 @@ ContextConfigImpl::ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContex ecdh_curves_(StringUtil::nonEmptyStringOrDefault( RepeatedPtrUtil::join(config.tls_params().ecdh_curves(), ":"), DEFAULT_ECDH_CURVES)), ca_cert_(Config::DataSource::read(config.validation_context().trusted_ca(), true)), - ca_cert_path_(Config::DataSource::getPath(config.validation_context().trusted_ca())), + ca_cert_path_(Config::DataSource::getPath(config.validation_context().trusted_ca()) + .value_or(EMPTY_STRING)), certificate_revocation_list_( Config::DataSource::read(config.validation_context().crl(), true)), certificate_revocation_list_path_( - Config::DataSource::getPath(config.validation_context().crl())), - 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_(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() - ? "" - : Config::DataSource::getPath(config.tls_certificates()[0].private_key())), + Config::DataSource::getPath(config.validation_context().crl()).value_or(EMPTY_STRING)), + tls_certficate_provider_(getTlsCertificateConfigProvider(config, secret_manager)), verify_subject_alt_name_list_(config.validation_context().verify_subject_alt_name().begin(), config.validation_context().verify_subject_alt_name().end()), verify_certificate_hash_list_(config.validation_context().verify_certificate_hash().begin(), diff --git a/source/common/ssl/context_config_impl.h b/source/common/ssl/context_config_impl.h index 2628f39b2e00c..f16d2dcb082c8 100644 --- a/source/common/ssl/context_config_impl.h +++ b/source/common/ssl/context_config_impl.h @@ -5,8 +5,10 @@ #include "envoy/api/v2/auth/cert.pb.h" #include "envoy/secret/secret_manager.h" +#include "envoy/secret/secret_provider.h" #include "envoy/ssl/context_config.h" +#include "common/common/empty_string.h" #include "common/json/json_loader.h" namespace Envoy { @@ -33,13 +35,24 @@ class ContextConfigImpl : public virtual Ssl::ContextConfig { ? INLINE_STRING : certificate_revocation_list_path_; } - const std::string& certChain() const override { return cert_chain_; } + const std::string& certChain() const override { + return tls_certficate_provider_ == nullptr + ? EMPTY_STRING + : tls_certficate_provider_->secret()->certificateChain(); + } const std::string& certChainPath() const override { - return (cert_chain_path_.empty() && !cert_chain_.empty()) ? INLINE_STRING : cert_chain_path_; + return tls_certficate_provider_ == nullptr + ? EMPTY_STRING + : tls_certficate_provider_->secret()->certificateChainPath(); + } + const std::string& privateKey() const override { + return tls_certficate_provider_ == nullptr ? EMPTY_STRING + : tls_certficate_provider_->secret()->privateKey(); } - const std::string& privateKey() const override { return private_key_; } const std::string& privateKeyPath() const override { - return (private_key_path_.empty() && !private_key_.empty()) ? INLINE_STRING : private_key_path_; + return tls_certficate_provider_ == nullptr + ? EMPTY_STRING + : tls_certficate_provider_->secret()->privateKeyPath(); } const std::vector& verifySubjectAltNameList() const override { return verify_subject_alt_name_list_; @@ -74,10 +87,7 @@ class ContextConfigImpl : public virtual Ssl::ContextConfig { const std::string ca_cert_path_; const std::string certificate_revocation_list_; const std::string certificate_revocation_list_path_; - const std::string cert_chain_; - const std::string cert_chain_path_; - const std::string private_key_; - const std::string private_key_path_; + Secret::TlsCertificateConfigProviderSharedPtr tls_certficate_provider_; const std::vector verify_subject_alt_name_list_; const std::vector verify_certificate_hash_list_; const std::vector verify_certificate_spki_list_; diff --git a/source/common/ssl/context_impl.cc b/source/common/ssl/context_impl.cc index 7cc77a65599ed..7628af976f03a 100644 --- a/source/common/ssl/context_impl.cc +++ b/source/common/ssl/context_impl.cc @@ -168,10 +168,8 @@ ContextImpl::ContextImpl(Stats::Scope& scope, const ContextConfig& config) SSL_CTX_set_cert_verify_callback(ctx_.get(), ContextImpl::verifyCallback, this); } - if (config.certChain().empty() != config.privateKey().empty()) { - throw EnvoyException(fmt::format("Failed to load incomplete certificate from {}, {}", - config.certChainPath(), config.privateKeyPath())); - } + // Validation happened in TlsCertificateConfigImpl + ASSERT(config.certChain().empty() == config.privateKey().empty()); if (!config.certChain().empty()) { // Load certificate chain. diff --git a/source/common/ssl/tls_certificate_config_impl.cc b/source/common/ssl/tls_certificate_config_impl.cc index 4f0afeb49733f..3d9be01363838 100644 --- a/source/common/ssl/tls_certificate_config_impl.cc +++ b/source/common/ssl/tls_certificate_config_impl.cc @@ -2,15 +2,30 @@ #include "envoy/common/exception.h" +#include "common/common/empty_string.h" +#include "common/common/fmt.h" #include "common/config/datasource.h" namespace Envoy { namespace Ssl { +static const std::string INLINE_STRING = ""; + 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)) {} + certificate_chain_path_( + Config::DataSource::getPath(config.certificate_chain()) + .value_or(certificate_chain_.empty() ? EMPTY_STRING : INLINE_STRING)), + private_key_(Config::DataSource::read(config.private_key(), true)), + private_key_path_(Config::DataSource::getPath(config.private_key()) + .value_or(private_key_.empty() ? EMPTY_STRING : INLINE_STRING)) { + + if (certificate_chain_.empty() || private_key_.empty()) { + throw EnvoyException(fmt::format("Failed to load incomplete certificate from {}, {}", + certificate_chain_path_, private_key_path_)); + } +} } // namespace Ssl } // namespace Envoy diff --git a/source/common/ssl/tls_certificate_config_impl.h b/source/common/ssl/tls_certificate_config_impl.h index b8875ffd6998e..a8ab270f914e6 100644 --- a/source/common/ssl/tls_certificate_config_impl.h +++ b/source/common/ssl/tls_certificate_config_impl.h @@ -13,11 +13,15 @@ class TlsCertificateConfigImpl : public TlsCertificateConfig { TlsCertificateConfigImpl(const envoy::api::v2::auth::TlsCertificate& config); const std::string& certificateChain() const override { return certificate_chain_; } + const std::string& certificateChainPath() const override { return certificate_chain_path_; } const std::string& privateKey() const override { return private_key_; } + const std::string& privateKeyPath() const override { return private_key_path_; } private: const std::string certificate_chain_; + const std::string certificate_chain_path_; const std::string private_key_; + const std::string private_key_path_; }; } // namespace Ssl diff --git a/source/server/configuration_impl.cc b/source/server/configuration_impl.cc index 0746d48d9d6d0..57ff50ec322a5 100644 --- a/source/server/configuration_impl.cc +++ b/source/server/configuration_impl.cc @@ -50,7 +50,7 @@ void MainImpl::initialize(const envoy::config::bootstrap::v2::Bootstrap& bootstr 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]); + server.secretManager().addStaticSecret(secrets[i]); } cluster_manager_ = cluster_manager_factory.clusterManagerFromProto( diff --git a/test/common/grpc/grpc_client_integration_test_harness.h b/test/common/grpc/grpc_client_integration_test_harness.h index 27b7baf5b8fc0..9211c5411421d 100644 --- a/test/common/grpc/grpc_client_integration_test_harness.h +++ b/test/common/grpc/grpc_client_integration_test_harness.h @@ -499,7 +499,7 @@ class GrpcSslClientIntegrationTest : public GrpcClientIntegrationTest { } bool use_client_cert_{}; - Secret::MockSecretManager secret_manager_; + NiceMock secret_manager_; }; } // namespace diff --git a/test/common/secret/secret_manager_impl_test.cc b/test/common/secret/secret_manager_impl_test.cc index a692976c4c6e4..bf27f559fd4ff 100644 --- a/test/common/secret/secret_manager_impl_test.cc +++ b/test/common/secret/secret_manager_impl_test.cc @@ -34,19 +34,20 @@ name: "abc.com" std::unique_ptr secret_manager(new SecretManagerImpl()); - secret_manager->addOrUpdateSecret(secret_config); + secret_manager->addStaticSecret(secret_config); - ASSERT_EQ(secret_manager->findTlsCertificate("undefined"), nullptr); + ASSERT_EQ(secret_manager->findStaticTlsCertificateProvider("undefined"), nullptr); - ASSERT_NE(secret_manager->findTlsCertificate("abc.com"), nullptr); + ASSERT_NE(secret_manager->findStaticTlsCertificateProvider("abc.com"), nullptr); const std::string cert_pem = "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_cert.pem"; - EXPECT_EQ(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(cert_pem)), - secret_manager->findTlsCertificate("abc.com")->certificateChain()); + EXPECT_EQ( + TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(cert_pem)), + secret_manager->findStaticTlsCertificateProvider("abc.com")->secret()->certificateChain()); const std::string key_pem = "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_key.pem"; EXPECT_EQ(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(key_pem)), - secret_manager->findTlsCertificate("abc.com")->privateKey()); + secret_manager->findStaticTlsCertificateProvider("abc.com")->secret()->privateKey()); } TEST_F(SecretManagerImplTest, NotImplementedException) { @@ -64,7 +65,7 @@ name: "abc.com" std::unique_ptr secret_manager(new SecretManagerImpl()); - EXPECT_THROW_WITH_MESSAGE(secret_manager->addOrUpdateSecret(secret_config), EnvoyException, + EXPECT_THROW_WITH_MESSAGE(secret_manager->addStaticSecret(secret_config), EnvoyException, "Secret type not implemented"); } diff --git a/test/common/ssl/context_impl_test.cc b/test/common/ssl/context_impl_test.cc index 31ac97c0d3d17..b6db285500254 100644 --- a/test/common/ssl/context_impl_test.cc +++ b/test/common/ssl/context_impl_test.cc @@ -15,6 +15,8 @@ #include "gtest/gtest.h" +using testing::NiceMock; + namespace Envoy { namespace Ssl { @@ -178,7 +180,7 @@ class SslServerContextImplTicketTest : public SslContextImplTest { public: static void loadConfig(ServerContextConfigImpl& cfg) { Runtime::MockLoader runtime; - Secret::MockSecretManager secret_manager; + NiceMock secret_manager; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; ServerContextSharedPtr server_ctx( @@ -194,14 +196,14 @@ class SslServerContextImplTicketTest : public SslContextImplTest { server_cert->mutable_private_key()->set_filename( TestEnvironment::substitute("{{ test_tmpdir }}/unittestkey.pem")); - Secret::MockSecretManager secret_manager; + NiceMock 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); - Secret::MockSecretManager secret_manager; + NiceMock secret_manager; ServerContextConfigImpl cfg(*loader, secret_manager); loadConfig(cfg); } @@ -359,7 +361,7 @@ 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; + NiceMock secret_manager; tls_context.set_sni(std::string("\000", 1)); EXPECT_THROW_WITH_MESSAGE( @@ -374,7 +376,7 @@ TEST(ClientContextConfigImplTest, EmptyServerNameIndication) { // 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; + NiceMock 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). @@ -391,7 +393,7 @@ 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; + NiceMock secret_manager; tls_context.mutable_common_tls_context() ->mutable_validation_context() // Not a base64-encoded string. @@ -408,7 +410,7 @@ TEST(ClientContextConfigImplTest, InvalidCertificateSpki) { // TODO(PiotrSikora): Support multiple TLS certificates. TEST(ClientContextConfigImplTest, MultipleTlsCertificates) { envoy::api::v2::auth::UpstreamTlsContext tls_context; - Secret::MockSecretManager secret_manager; + NiceMock secret_manager; tls_context.mutable_common_tls_context()->add_tls_certificates(); tls_context.mutable_common_tls_context()->add_tls_certificates(); EXPECT_THROW_WITH_MESSAGE( @@ -431,7 +433,7 @@ name: "abc.com" MessageUtil::loadFromYaml(TestEnvironment::substitute(yaml), secret_config); std::unique_ptr secret_manager(new Secret::SecretManagerImpl()); - secret_manager->addOrUpdateSecret(secret_config); + secret_manager->addStaticSecret(secret_config); envoy::api::v2::auth::UpstreamTlsContext tls_context; tls_context.mutable_common_tls_context() @@ -465,7 +467,7 @@ name: "abc.com" std::unique_ptr secret_manager(new Secret::SecretManagerImpl()); - secret_manager->addOrUpdateSecret(secret_config); + secret_manager->addStaticSecret(secret_config); envoy::api::v2::auth::UpstreamTlsContext tls_context; tls_context.mutable_common_tls_context() @@ -483,7 +485,7 @@ name: "abc.com" // TODO(PiotrSikora): Support multiple TLS certificates. TEST(ServerContextConfigImplTest, MultipleTlsCertificates) { envoy::api::v2::auth::DownstreamTlsContext tls_context; - Secret::MockSecretManager secret_manager; + NiceMock secret_manager; EXPECT_THROW_WITH_MESSAGE( ServerContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, "A single TLS certificate is required for server contexts"); @@ -497,7 +499,7 @@ TEST(ServerContextConfigImplTest, MultipleTlsCertificates) { // TlsCertificate messages must have a cert for servers. TEST(ServerContextImplTest, TlsCertificateNonEmpty) { envoy::api::v2::auth::DownstreamTlsContext tls_context; - Secret::MockSecretManager secret_manager; + NiceMock secret_manager; tls_context.mutable_common_tls_context()->add_tls_certificates(); ServerContextConfigImpl client_context_config(tls_context, secret_manager); Runtime::MockLoader runtime; @@ -512,7 +514,7 @@ 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; + NiceMock secret_manager; envoy::api::v2::auth::CertificateValidationContext* server_validation_ctx = tls_context.mutable_common_tls_context()->mutable_validation_context(); diff --git a/test/common/ssl/ssl_certs_test.h b/test/common/ssl/ssl_certs_test.h index 2f09e019944a4..37b85cad3f458 100644 --- a/test/common/ssl/ssl_certs_test.h +++ b/test/common/ssl/ssl_certs_test.h @@ -12,6 +12,6 @@ class SslCertsTest : public testing::Test { TestEnvironment::exec({TestEnvironment::runfilesPath("test/common/ssl/gen_unittest_certs.sh")}); } - Secret::MockSecretManager secret_manager_; + testing::NiceMock secret_manager_; }; } // namespace Envoy diff --git a/test/common/ssl/ssl_socket_test.cc b/test/common/ssl/ssl_socket_test.cc index c27c9aa951b4d..219de0e829551 100644 --- a/test/common/ssl/ssl_socket_test.cc +++ b/test/common/ssl/ssl_socket_test.cc @@ -51,7 +51,7 @@ void testUtil(const std::string& client_ctx_json, const std::string& server_ctx_ bool expect_success, const Network::Address::IpVersion version) { Stats::IsolatedStoreImpl stats_store; Runtime::MockLoader runtime; - Secret::MockSecretManager secret_manager; + NiceMock secret_manager; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); auto server_cfg = std::make_unique(*server_ctx_loader, secret_manager); @@ -148,7 +148,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; + NiceMock secret_manager; ContextManagerImpl manager(runtime); std::string new_session = EMPTY_STRING; @@ -1667,7 +1667,7 @@ TEST_P(SslSocketTest, HalfClose) { TEST_P(SslSocketTest, ClientAuthMultipleCAs) { Stats::IsolatedStoreImpl stats_store; Runtime::MockLoader runtime; - Secret::MockSecretManager secret_manager; + NiceMock secret_manager; std::string server_ctx_json = R"EOF( { @@ -1755,7 +1755,7 @@ 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; + NiceMock secret_manager; ContextManagerImpl manager(runtime); Json::ObjectSharedPtr server_ctx_loader1 = TestEnvironment::jsonLoadFromString(server_ctx_json1); diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index ac2f4fccfa358..510e74e423d58 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -121,7 +121,7 @@ class TestClusterManagerFactory : public ClusterManagerFactory { Ssl::ContextManagerImpl ssl_context_manager_{runtime_}; NiceMock dispatcher_; NiceMock local_info_; - Secret::MockSecretManager secret_manager_; + NiceMock secret_manager_; }; // Helper to intercept calls to postThreadLocalClusterUpdate. diff --git a/test/integration/ads_integration_test.cc b/test/integration/ads_integration_test.cc index 84ad8b57b0a89..e2a96d260fe33 100644 --- a/test/integration/ads_integration_test.cc +++ b/test/integration/ads_integration_test.cc @@ -295,7 +295,7 @@ class AdsIntegrationTest : public AdsIntegrationBaseTest, return dynamic_cast(*message_ptr); } - Secret::MockSecretManager secret_manager_; + testing::NiceMock secret_manager_; Runtime::MockLoader runtime_; Ssl::ContextManagerImpl context_manager_{runtime_}; FakeStreamPtr ads_stream_; diff --git a/test/integration/sds_static_integration_test.cc b/test/integration/sds_static_integration_test.cc index bc7e285436afa..e3a24c3c42989 100644 --- a/test/integration/sds_static_integration_test.cc +++ b/test/integration/sds_static_integration_test.cc @@ -88,7 +88,7 @@ class SdsStaticDownstreamIntegrationTest private: Runtime::MockLoader runtime_; Ssl::ContextManagerImpl context_manager_{runtime_}; - Secret::MockSecretManager secret_manager_; + NiceMock secret_manager_; Network::TransportSocketFactoryPtr client_ssl_ctx_; }; @@ -178,7 +178,7 @@ class SdsStaticUpstreamIntegrationTest private: Runtime::MockLoader runtime_; Ssl::ContextManagerImpl context_manager_{runtime_}; - Secret::MockSecretManager secret_manager_; + NiceMock secret_manager_; }; INSTANTIATE_TEST_CASE_P(IpVersions, SdsStaticUpstreamIntegrationTest, diff --git a/test/integration/ssl_integration_test.h b/test/integration/ssl_integration_test.h index 26d21bab70533..73f96c514a201 100644 --- a/test/integration/ssl_integration_test.h +++ b/test/integration/ssl_integration_test.h @@ -32,7 +32,7 @@ class SslIntegrationTest : public HttpIntegrationTest, private: std::unique_ptr runtime_; std::unique_ptr context_manager_; - Secret::MockSecretManager secret_manager_; + NiceMock secret_manager_; Network::TransportSocketFactoryPtr client_ssl_ctx_plain_; Network::TransportSocketFactoryPtr client_ssl_ctx_alpn_; diff --git a/test/integration/tcp_proxy_integration_test.h b/test/integration/tcp_proxy_integration_test.h index 0532890980ba4..9c75ee45fd924 100644 --- a/test/integration/tcp_proxy_integration_test.h +++ b/test/integration/tcp_proxy_integration_test.h @@ -41,7 +41,7 @@ class TcpProxySslIntegrationTest : public TcpProxyIntegrationTest { ConnectionStatusCallbacks connect_callbacks_; MockWatermarkBuffer* client_write_buffer_; std::shared_ptr payload_reader_; - Secret::MockSecretManager secret_manager_; + testing::NiceMock secret_manager_; }; } // namespace diff --git a/test/integration/xfcc_integration_test.h b/test/integration/xfcc_integration_test.h index 3432313af7153..e762b1720f416 100644 --- a/test/integration/xfcc_integration_test.h +++ b/test/integration/xfcc_integration_test.h @@ -56,7 +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_; + testing::NiceMock secret_manager_; }; } // namespace Xfcc } // namespace Envoy diff --git a/test/mocks/secret/BUILD b/test/mocks/secret/BUILD index f3d6223461cd8..e01f07aaae592 100644 --- a/test/mocks/secret/BUILD +++ b/test/mocks/secret/BUILD @@ -15,5 +15,6 @@ envoy_cc_mock( deps = [ "//include/envoy/secret:secret_manager_interface", "//include/envoy/ssl:tls_certificate_config_interface", + "//source/common/secret:secret_provider_impl_lib", ], ) diff --git a/test/mocks/secret/mocks.cc b/test/mocks/secret/mocks.cc index e11b7de14dde7..48b788874a666 100644 --- a/test/mocks/secret/mocks.cc +++ b/test/mocks/secret/mocks.cc @@ -1,9 +1,19 @@ #include "test/mocks/secret/mocks.h" +#include "common/secret/secret_provider_impl.h" + +using testing::Invoke; +using testing::_; + namespace Envoy { namespace Secret { -MockSecretManager::MockSecretManager() {} +MockSecretManager::MockSecretManager() { + ON_CALL(*this, createInlineTlsCertificateProvider(_)) + .WillByDefault(Invoke([](const envoy::api::v2::auth::TlsCertificate& tls_certificate) { + return std::make_shared(tls_certificate); + })); +} MockSecretManager::~MockSecretManager() {} diff --git a/test/mocks/secret/mocks.h b/test/mocks/secret/mocks.h index 1d111df74993c..212cc8985cbba 100644 --- a/test/mocks/secret/mocks.h +++ b/test/mocks/secret/mocks.h @@ -14,8 +14,12 @@ class MockSecretManager : public SecretManager { MockSecretManager(); ~MockSecretManager(); - MOCK_METHOD1(addOrUpdateSecret, void(const envoy::api::v2::auth::Secret& secret)); - MOCK_CONST_METHOD1(findTlsCertificate, const Ssl::TlsCertificateConfig*(const std::string& name)); + MOCK_METHOD1(addStaticSecret, void(const envoy::api::v2::auth::Secret& secret)); + MOCK_CONST_METHOD1(findStaticTlsCertificateProvider, + TlsCertificateConfigProviderSharedPtr(const std::string& name)); + MOCK_METHOD1(createInlineTlsCertificateProvider, + TlsCertificateConfigProviderSharedPtr( + const envoy::api::v2::auth::TlsCertificate& tls_certificate)); }; } // namespace Secret diff --git a/test/mocks/upstream/mocks.h b/test/mocks/upstream/mocks.h index 08e5cd394fb30..5ad05945a5826 100644 --- a/test/mocks/upstream/mocks.h +++ b/test/mocks/upstream/mocks.h @@ -173,7 +173,7 @@ class MockClusterManagerFactory : public ClusterManagerFactory { ClusterManager& cm)); private: - Secret::MockSecretManager secret_manager_; + NiceMock secret_manager_; }; class MockClusterManager : public ClusterManager { diff --git a/test/server/config_validation/cluster_manager_test.cc b/test/server/config_validation/cluster_manager_test.cc index 54a612cee5061..e28e1313a8c2f 100644 --- a/test/server/config_validation/cluster_manager_test.cc +++ b/test/server/config_validation/cluster_manager_test.cc @@ -25,7 +25,7 @@ TEST(ValidationClusterManagerTest, MockedMethods) { Stats::IsolatedStoreImpl stats; NiceMock tls; NiceMock random; - Secret::MockSecretManager secret_manager; + testing::NiceMock secret_manager; auto dns_resolver = std::make_shared>(); Ssl::ContextManagerImpl ssl_context_manager{runtime}; NiceMock dispatcher;