Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions include/envoy/secret/secret_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ class SecretManager {
virtual TlsCertificateConfigProviderSharedPtr findOrCreateTlsCertificateProvider(
const envoy::api::v2::core::ConfigSource& config_source, const std::string& config_name,
Server::Configuration::TransportSocketFactoryContext& secret_provider_context) PURE;

/**
* Finds and returns a dynamic secret provider associated to SDS config. Create
* a new one if such provider does not exist.
*
* @param config_source a protobuf message object containing a SDS config source.
* @param config_name a name that uniquely refers to the SDS config source.
* @param secret_provider_context context that provides components for creating and initializing
* secret provider.
* @return CertificateValidationContextConfigProviderSharedPtr the dynamic certificate validation
* context secret provider.
*/
virtual CertificateValidationContextConfigProviderSharedPtr
findOrCreateCertificateValidationContextProvider(
const envoy::api::v2::core::ConfigSource& config_source, const std::string& config_name,
Server::Configuration::TransportSocketFactoryContext& secret_provider_context) PURE;
};

} // namespace Secret
Expand Down
1 change: 1 addition & 0 deletions source/common/secret/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ envoy_cc_library(
"//source/common/config:resources_lib",
"//source/common/config:subscription_factory_lib",
"//source/common/protobuf:utility_lib",
"//source/common/ssl:certificate_validation_context_config_impl_lib",
"//source/common/ssl:tls_certificate_config_impl_lib",
],
)
42 changes: 30 additions & 12 deletions source/common/secret/sds_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "common/config/resources.h"
#include "common/config/subscription_factory.h"
#include "common/protobuf/utility.h"
#include "common/ssl/certificate_validation_context_config_impl.h"
#include "common/ssl/tls_certificate_config_impl.h"

namespace Envoy {
Expand All @@ -17,9 +18,9 @@ SdsApi::SdsApi(const LocalInfo::LocalInfo& local_info, Event::Dispatcher& dispat
Upstream::ClusterManager& cluster_manager, Init::Manager& init_manager,
const envoy::api::v2::core::ConfigSource& sds_config, std::string sds_config_name,
std::function<void()> destructor_cb)
: local_info_(local_info), dispatcher_(dispatcher), random_(random), stats_(stats),
cluster_manager_(cluster_manager), sds_config_(sds_config), sds_config_name_(sds_config_name),
secret_hash_(0), clean_up_(destructor_cb) {
: secret_hash_(0), local_info_(local_info), dispatcher_(dispatcher), random_(random),
stats_(stats), cluster_manager_(cluster_manager), sds_config_(sds_config),
sds_config_name_(sds_config_name), clean_up_(destructor_cb) {
// TODO(JimmyCYJ): Implement chained_init_manager, so that multiple init_manager
// can be chained together to behave as one init_manager. In that way, we let
// two listeners which share same SdsApi to register at separate init managers, and
Expand Down Expand Up @@ -59,15 +60,7 @@ void SdsApi::onConfigUpdate(const ResourceVector& resources, const std::string&)
fmt::format("Unexpected SDS secret (expecting {}): {}", sds_config_name_, secret.name()));
}

const uint64_t new_hash = MessageUtil::hash(secret);
if (new_hash != secret_hash_ &&
secret.type_case() == envoy::api::v2::auth::Secret::TypeCase::kTlsCertificate) {
secret_hash_ = new_hash;
tls_certificate_secrets_ =
std::make_unique<Ssl::TlsCertificateConfigImpl>(secret.tls_certificate());

update_callback_manager_.runCallbacks();
}
updateConfigHelper(secret);

runInitializeCallbackIfAny();
}
Expand All @@ -84,5 +77,30 @@ void SdsApi::runInitializeCallbackIfAny() {
}
}

void TlsCertificateSdsApi::updateConfigHelper(const envoy::api::v2::auth::Secret& secret) {
const uint64_t new_hash = MessageUtil::hash(secret);
if (new_hash != secret_hash_ &&
secret.type_case() == envoy::api::v2::auth::Secret::TypeCase::kTlsCertificate) {
secret_hash_ = new_hash;
tls_certificate_secrets_ =
std::make_unique<Ssl::TlsCertificateConfigImpl>(secret.tls_certificate());

update_callback_manager_.runCallbacks();
}
}

void CertificateValidationContextSdsApi::updateConfigHelper(
const envoy::api::v2::auth::Secret& secret) {
const uint64_t new_hash = MessageUtil::hash(secret);
if (new_hash != secret_hash_ &&
secret.type_case() == envoy::api::v2::auth::Secret::TypeCase::kValidationContext) {
secret_hash_ = new_hash;
certificate_validation_context_secrets_ =
std::make_unique<Ssl::CertificateValidationContextConfigImpl>(secret.validation_context());

update_callback_manager_.runCallbacks();
}
}

} // namespace Secret
} // namespace Envoy
77 changes: 66 additions & 11 deletions source/common/secret/sds_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ namespace Secret {
* SDS API implementation that fetches secrets from SDS server via Subscription.
*/
class SdsApi : public Init::Target,
public TlsCertificateConfigProvider,
public Config::SubscriptionCallbacks<envoy::api::v2::auth::Secret> {
public:
SdsApi(const LocalInfo::LocalInfo& local_info, Event::Dispatcher& dispatcher,
Expand All @@ -43,14 +42,10 @@ class SdsApi : public Init::Target,
return MessageUtil::anyConvert<envoy::api::v2::auth::Secret>(resource).name();
}

// SecretProvider
const Ssl::TlsCertificateConfig* secret() const override {
return tls_certificate_secrets_.get();
}

Common::CallbackHandle* addUpdateCallback(std::function<void()> callback) override {
return update_callback_manager_.add(callback);
}
protected:
// Updates local storage of dynamic secrets and invokes callbacks.
virtual void updateConfigHelper(const envoy::api::v2::auth::Secret&) {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be PURE, no?

uint64_t secret_hash_;

private:
void runInitializeCallbackIfAny();
Expand All @@ -66,13 +61,73 @@ class SdsApi : public Init::Target,
std::function<void()> initialize_callback_;
const std::string sds_config_name_;

uint64_t secret_hash_;
Cleanup clean_up_;
};

/**
* TlsCertificateSdsApi implementation maintains and updates dynamic TLS certificate secrets.
*/
class TlsCertificateSdsApi : public SdsApi, public TlsCertificateConfigProvider {
public:
TlsCertificateSdsApi(const LocalInfo::LocalInfo& local_info, Event::Dispatcher& dispatcher,
Runtime::RandomGenerator& random, Stats::Store& stats,
Upstream::ClusterManager& cluster_manager, Init::Manager& init_manager,
const envoy::api::v2::core::ConfigSource& sds_config,
std::string sds_config_name, std::function<void()> destructor_cb)
: SdsApi(local_info, dispatcher, random, stats, cluster_manager, init_manager, sds_config,
sds_config_name, destructor_cb) {}

// SecretProvider
const Ssl::TlsCertificateConfig* secret() const override {
return tls_certificate_secrets_.get();
}

Common::CallbackHandle* addUpdateCallback(std::function<void()> callback) override {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this and update_callback_manager to parent class?

return update_callback_manager_.add(callback);
}

private:
// SdsApi
void updateConfigHelper(const envoy::api::v2::auth::Secret& secret) override;

Ssl::TlsCertificateConfigPtr tls_certificate_secrets_;
Common::CallbackManager<> update_callback_manager_;
};

typedef std::unique_ptr<SdsApi> SdsApiPtr;
/**
* CertificateValidationContextSdsApi implementation maintains and updates dynamic certificate
* validation context secrets.
*/
class CertificateValidationContextSdsApi : public SdsApi,
public CertificateValidationContextConfigProvider {
public:
CertificateValidationContextSdsApi(const LocalInfo::LocalInfo& local_info,
Event::Dispatcher& dispatcher,
Runtime::RandomGenerator& random, Stats::Store& stats,
Upstream::ClusterManager& cluster_manager,
Init::Manager& init_manager,
const envoy::api::v2::core::ConfigSource& sds_config,
std::string sds_config_name,
std::function<void()> destructor_cb)
: SdsApi(local_info, dispatcher, random, stats, cluster_manager, init_manager, sds_config,
sds_config_name, destructor_cb) {}

// SecretProvider
const Ssl::CertificateValidationContextConfig* secret() const override {
return certificate_validation_context_secrets_.get();
}

Common::CallbackHandle* addUpdateCallback(std::function<void()> callback) override {
return update_callback_manager_.add(callback);
}

private:
// SdsApi
void updateConfigHelper(const envoy::api::v2::auth::Secret& secret) override;

Ssl::CertificateValidationContextConfigPtr certificate_validation_context_secrets_;
Common::CallbackManager<> update_callback_manager_;
};

} // namespace Secret
} // namespace Envoy
51 changes: 44 additions & 7 deletions source/common/secret/secret_manager_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ SecretManagerImpl::createInlineCertificateValidationContextProvider(
certificate_validation_context);
}

void SecretManagerImpl::removeDynamicSecretProvider(const std::string& map_key) {
ENVOY_LOG(debug, "Unregister secret provider. hash key: {}", map_key);
void SecretManagerImpl::removeDynamicTlsCertificateProvider(const std::string& map_key) {
ENVOY_LOG(debug, "Unregister tls certificate provider. hash key: {}", map_key);

auto num_deleted = dynamic_secret_providers_.erase(map_key);
auto num_deleted = dynamic_tls_certificate_providers_.erase(map_key);
ASSERT(num_deleted == 1, "");
}

Expand All @@ -76,22 +76,59 @@ TlsCertificateConfigProviderSharedPtr SecretManagerImpl::findOrCreateTlsCertific
Server::Configuration::TransportSocketFactoryContext& secret_provider_context) {
const std::string map_key = sds_config_source.SerializeAsString() + config_name;

TlsCertificateConfigProviderSharedPtr secret_provider = dynamic_secret_providers_[map_key].lock();
TlsCertificateConfigProviderSharedPtr secret_provider =
dynamic_tls_certificate_providers_[map_key].lock();
if (!secret_provider) {
ASSERT(secret_provider_context.initManager() != nullptr);

// SdsApi is owned by ListenerImpl and ClusterInfo which are destroyed before
// SecretManagerImpl. It is safe to invoke this callback at the destructor of SdsApi.
std::function<void()> unregister_secret_provider = [map_key, this]() {
removeDynamicSecretProvider(map_key);
removeDynamicTlsCertificateProvider(map_key);
};

secret_provider = std::make_shared<SdsApi>(
secret_provider = std::make_shared<TlsCertificateSdsApi>(
secret_provider_context.localInfo(), secret_provider_context.dispatcher(),
secret_provider_context.random(), secret_provider_context.stats(),
secret_provider_context.clusterManager(), *secret_provider_context.initManager(),
sds_config_source, config_name, unregister_secret_provider);
dynamic_secret_providers_[map_key] = secret_provider;
dynamic_tls_certificate_providers_[map_key] = secret_provider;
}

return secret_provider;
}

void SecretManagerImpl::removeDynamicCertificateValidationContextProvider(
const std::string& map_key) {
ENVOY_LOG(debug, "Unregister certificate validation context provider. hash key: {}", map_key);

auto num_deleted = dynamic_certificate_validation_context_providers_.erase(map_key);
ASSERT(num_deleted == 1, "");
}

CertificateValidationContextConfigProviderSharedPtr

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the fact that many of code are duplicated. But I don't have good solution either.

SecretManagerImpl::findOrCreateCertificateValidationContextProvider(
const envoy::api::v2::core::ConfigSource& sds_config_source, const std::string& config_name,
Server::Configuration::TransportSocketFactoryContext& secret_provider_context) {
const std::string map_key = sds_config_source.SerializeAsString() + config_name;

CertificateValidationContextConfigProviderSharedPtr secret_provider =
dynamic_certificate_validation_context_providers_[map_key].lock();
if (!secret_provider) {
ASSERT(secret_provider_context.initManager() != nullptr);

// SdsApi is owned by ListenerImpl and ClusterInfo which are destroyed before
// SecretManagerImpl. It is safe to invoke this callback at the destructor of SdsApi.
std::function<void()> unregister_secret_provider = [map_key, this]() {
removeDynamicCertificateValidationContextProvider(map_key);
};

secret_provider = std::make_shared<CertificateValidationContextSdsApi>(
secret_provider_context.localInfo(), secret_provider_context.dispatcher(),
secret_provider_context.random(), secret_provider_context.stats(),
secret_provider_context.clusterManager(), *secret_provider_context.initManager(),
sds_config_source, config_name, unregister_secret_provider);
dynamic_certificate_validation_context_providers_[map_key] = secret_provider;
}

return secret_provider;
Expand Down
19 changes: 15 additions & 4 deletions source/common/secret/secret_manager_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,16 @@ class SecretManagerImpl : public SecretManager, Logger::Loggable<Logger::Id::sec
const envoy::api::v2::core::ConfigSource& config_source, const std::string& config_name,
Server::Configuration::TransportSocketFactoryContext& secret_provider_context) override;

CertificateValidationContextConfigProviderSharedPtr
findOrCreateCertificateValidationContextProvider(
const envoy::api::v2::core::ConfigSource& config_source, const std::string& config_name,
Server::Configuration::TransportSocketFactoryContext& secret_provider_context) override;

private:
// Remove dynamic secret provider which has been deleted.
void removeDynamicSecretProvider(const std::string& map_key);
// Remove dynamic tls certificate provider which has been deleted.
void removeDynamicTlsCertificateProvider(const std::string& map_key);
// Remove dynamic certificate validation context provider which has been deleted.
void removeDynamicCertificateValidationContextProvider(const std::string& map_key);

// Manages pairs of secret name and TlsCertificateConfigProviderSharedPtr.
std::unordered_map<std::string, TlsCertificateConfigProviderSharedPtr>
Expand All @@ -47,9 +54,13 @@ class SecretManagerImpl : public SecretManager, Logger::Loggable<Logger::Id::sec
std::unordered_map<std::string, CertificateValidationContextConfigProviderSharedPtr>
static_certificate_validation_context_providers_;

// map hash code of SDS config source and SdsApi object.
// map hash code of SDS config source and TlsCertificateSdsApi object.
std::unordered_map<std::string, std::weak_ptr<TlsCertificateConfigProvider>>
dynamic_secret_providers_;
dynamic_tls_certificate_providers_;

// map hash code of SDS config source and CertificateValidationContextSdsApi object.
std::unordered_map<std::string, std::weak_ptr<CertificateValidationContextConfigProvider>>
dynamic_certificate_validation_context_providers_;
};

} // namespace Secret
Expand Down