-
Notifications
You must be signed in to change notification settings - Fork 63
Sds api #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sds api #1
Changes from 8 commits
a9ec642
6a270c4
3d330c5
79defaf
df3e59c
b32cb31
8d0a41f
0dd3cc8
7927531
2f56357
051d7b3
0554e71
fa631a1
d6f4d28
2fe5a73
7c44cc3
de31e41
8398425
6db4351
cc22768
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| #include "common/secret/sds_api.h" | ||
|
|
||
| #include <unordered_map> | ||
|
|
||
| #include "common/config/resources.h" | ||
| #include "common/config/subscription_factory.h" | ||
| #include "common/secret/secret_manager_util.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Secret { | ||
|
|
||
| SdsApi::SdsApi(Server::Instance& server, const envoy::api::v2::core::ConfigSource& sds_config, | ||
| std::string sds_config_name) | ||
| : server_(server), sds_config_(sds_config), | ||
| sds_config_source_hash_(SecretManagerUtil::configSourceHash(sds_config)), | ||
| sds_config_name_(sds_config_name) { | ||
| server_.initManager().registerTarget(*this); | ||
| } | ||
|
|
||
| void SdsApi::initialize(std::function<void()> callback) { | ||
| initialize_callback_ = callback; | ||
| subscription_ = Envoy::Config::SubscriptionFactory::subscriptionFromConfigSource< | ||
| envoy::api::v2::auth::Secret>( | ||
| sds_config_, server_.localInfo().node(), server_.dispatcher(), server_.clusterManager(), | ||
| server_.random(), server_.stats(), /* rest_legacy_constructor */ nullptr, | ||
| "envoy.service.discovery.v2.SecretDiscoveryService.FetchSecrets", | ||
| // TODO(jaebong): replace next line with | ||
| // "envoy.service.discovery.v2.SecretDiscoveryService.StreamSecrets" to support streaming | ||
| // service | ||
| "envoy.service.discovery.v2.SecretDiscoveryService.FetchSecrets"); | ||
|
|
||
| Config::Utility::checkLocalInfo("sds", server_.localInfo()); | ||
|
|
||
| subscription_->start({sds_config_name_}, *this); | ||
| } | ||
|
|
||
| void SdsApi::onConfigUpdate(const ResourceVector& resources, const std::string&) { | ||
| for (const auto& resource : resources) { | ||
| switch (resource.type_case()) { | ||
| case envoy::api::v2::auth::Secret::kTlsCertificate: | ||
| server_.secretManager().addOrUpdateSecret(sds_config_source_hash_, resource); | ||
| break; | ||
| case envoy::api::v2::auth::Secret::kSessionTicketKeys: | ||
| NOT_IMPLEMENTED; | ||
| default: | ||
| throw EnvoyException("sds: invalid configuration"); | ||
| } | ||
| } | ||
|
|
||
| runInitializeCallbackIfAny(); | ||
| } | ||
|
|
||
| void SdsApi::onConfigUpdateFailed(const EnvoyException*) { | ||
| // We need to allow server startup to continue, even if we have a bad config. | ||
| runInitializeCallbackIfAny(); | ||
| } | ||
|
|
||
| void SdsApi::runInitializeCallbackIfAny() { | ||
| if (initialize_callback_) { | ||
| initialize_callback_(); | ||
| initialize_callback_ = nullptr; | ||
| } | ||
| } | ||
|
|
||
| } // namespace Secret | ||
| } // namespace Envoy | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| #pragma once | ||
|
|
||
| #include <functional> | ||
|
|
||
| #include "envoy/api/v2/auth/cert.pb.h" | ||
| #include "envoy/api/v2/core/config_source.pb.h" | ||
| #include "envoy/config/subscription.h" | ||
| #include "envoy/server/instance.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Secret { | ||
|
|
||
| /** | ||
| * SDS API implementation that fetches secrets from SDS server via Subscription. | ||
| */ | ||
| class SdsApi : public Init::Target, Config::SubscriptionCallbacks<envoy::api::v2::auth::Secret> { | ||
| public: | ||
| SdsApi(Server::Instance& server, const envoy::api::v2::core::ConfigSource& sds_config, | ||
| std::string sds_config_name); | ||
|
|
||
| // Init::Target | ||
| void initialize(std::function<void()> callback) override; | ||
|
|
||
| // Config::SubscriptionCallbacks | ||
| void onConfigUpdate(const ResourceVector& resources, const std::string& version_info) override; | ||
| void onConfigUpdateFailed(const EnvoyException* e) override; | ||
| std::string resourceName(const ProtobufWkt::Any& resource) override { | ||
| return MessageUtil::anyConvert<envoy::api::v2::auth::Secret>(resource).name(); | ||
| } | ||
|
|
||
| private: | ||
| void runInitializeCallbackIfAny(); | ||
|
|
||
| Server::Instance& server_; | ||
| const envoy::api::v2::core::ConfigSource sds_config_; | ||
| const std::string sds_config_source_hash_; | ||
| std::unique_ptr<Config::Subscription<envoy::api::v2::auth::Secret>> subscription_; | ||
| std::function<void()> initialize_callback_; | ||
| std::string sds_config_name_; | ||
| }; | ||
|
|
||
| } // namespace Secret | ||
| } // namespace Envoy |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,26 +2,51 @@ | |
|
|
||
| #include "envoy/common/exception.h" | ||
|
|
||
| #include "common/secret/secret_manager_util.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::addOrUpdateSecret(const std::string& config_source_hash, | ||
| const envoy::api::v2::auth::Secret& secret) { | ||
| switch (secret.type_case()) { | ||
| case envoy::api::v2::auth::Secret::TypeCase::kTlsCertificate: | ||
| tls_certificate_secrets_[secret.name()] = | ||
| case envoy::api::v2::auth::Secret::TypeCase::kTlsCertificate: { | ||
| std::unique_lock<std::shared_timed_mutex> lhs(tls_certificate_secrets_mutex_); | ||
| tls_certificate_secrets_[config_source_hash][secret.name()] = | ||
| std::make_unique<Ssl::TlsCertificateConfigImpl>(secret.tls_certificate()); | ||
| break; | ||
| } 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; | ||
| SecretManagerImpl::findTlsCertificate(const std::string& config_source_hash, | ||
| const std::string& name) const { | ||
| std::shared_lock<std::shared_timed_mutex> lhs(tls_certificate_secrets_mutex_); | ||
|
|
||
| auto config_source_it = tls_certificate_secrets_.find(config_source_hash); | ||
| if (config_source_it == tls_certificate_secrets_.end()) { | ||
| return nullptr; | ||
| } | ||
|
|
||
| auto secret = config_source_it->second.find(name); | ||
| return (secret != config_source_it->second.end()) ? secret->second.get() : nullptr; | ||
| } | ||
|
|
||
| std::string SecretManagerImpl::addOrUpdateSdsService( | ||
| const envoy::api::v2::core::ConfigSource& sds_config_source, std::string config_name) { | ||
| std::unique_lock<std::shared_timed_mutex> lhs(sds_api_mutex_); | ||
|
|
||
| auto hash = SecretManagerUtil::configSourceHash(sds_config_source); | ||
| if (sds_apis_.find(hash) != sds_apis_.end()) { | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need to support multiple config_name with the same config_source ? If we do, the sds_apis map key may need |
||
| return hash; | ||
| } | ||
|
|
||
| sds_apis_[hash] = std::move(std::make_unique<SdsApi>(server_, sds_config_source, config_name)); | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pass in hash to SdsApi so it doesn't need to re-calculate it |
||
|
|
||
| return hash; | ||
| } | ||
|
|
||
| } // namespace Secret | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,40 @@ | ||
| #pragma once | ||
|
|
||
| #include <shared_mutex> | ||
| #include <unordered_map> | ||
|
|
||
| #include "envoy/secret/secret_manager.h" | ||
| #include "envoy/server/instance.h" | ||
| #include "envoy/ssl/tls_certificate_config.h" | ||
|
|
||
| #include "common/common/logger.h" | ||
| #include "common/secret/sds_api.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Secret { | ||
|
|
||
| class SecretManagerImpl : public SecretManager, Logger::Loggable<Logger::Id::upstream> { | ||
| public: | ||
| void addOrUpdateSecret(const envoy::api::v2::auth::Secret& secret) override; | ||
| const Ssl::TlsCertificateConfig* findTlsCertificate(const std::string& name) const override; | ||
| SecretManagerImpl(Server::Instance& server) : server_(server) {} | ||
|
|
||
| void addOrUpdateSecret(const std::string& config_source_hash, | ||
| const envoy::api::v2::auth::Secret& secret) override; | ||
| const Ssl::TlsCertificateConfig* findTlsCertificate(const std::string& config_source_hash, | ||
| const std::string& name) const override; | ||
| std::string addOrUpdateSdsService(const envoy::api::v2::core::ConfigSource& config_source, | ||
| std::string config_name) override; | ||
|
|
||
| private: | ||
| std::unordered_map<std::string, Ssl::TlsCertificateConfigPtr> tls_certificate_secrets_; | ||
| Server::Instance& server_; | ||
| // map hash code of SDS config source and SdsApi object | ||
| std::unordered_map<std::string, std::unique_ptr<SdsApi>> sds_apis_; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typedef |
||
| mutable std::shared_timed_mutex sds_api_mutex_; | ||
|
|
||
| // Manages pairs of name and Ssl::TlsCertificateConfig grouped by SDS config source hash. | ||
| // If SDS config source hash is empty, it is a static secret. | ||
| std::unordered_map<std::string, std::unordered_map<std::string, Ssl::TlsCertificateConfigPtr>> | ||
| tls_certificate_secrets_; | ||
| mutable std::shared_timed_mutex tls_certificate_secrets_mutex_; | ||
| }; | ||
|
|
||
| } // namespace Secret | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| #pragma once | ||
|
|
||
| #include "envoy/api/v2/core/config_source.pb.h" | ||
|
|
||
| #include "common/common/fmt.h" | ||
| #include "common/json/json_loader.h" | ||
| #include "common/protobuf/protobuf.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Secret { | ||
|
|
||
| class SecretManagerUtil { | ||
| public: | ||
| virtual ~SecretManagerUtil() {} | ||
|
|
||
| /** | ||
| * Calculate hash code of ConfigSource. To identify the same ConfigSource, calculate the hash | ||
| * code from the ConfigSource | ||
| * | ||
| * @param config_source envoy::api::v2::core::ConfigSource | ||
| * @return hash code | ||
| */ | ||
| static std::string configSourceHash(const envoy::api::v2::core::ConfigSource& config_source) { | ||
| std::string jsonstr; | ||
| if (Protobuf::util::MessageToJsonString(config_source, &jsonstr).ok()) { | ||
| auto obj = Json::Factory::loadFromString(jsonstr); | ||
| if (obj.get() != nullptr) { | ||
| return std::to_string(obj->hash()); | ||
| } | ||
| } | ||
| throw EnvoyException( | ||
| fmt::format("Invalid ConfigSource message: {}", config_source.DebugString())); | ||
| } | ||
| }; | ||
|
|
||
| } // namespace Secret | ||
| } // namespace Envoy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pass in this hash_? not to calculate it