Skip to content

Fetch certificate validation context using SDS service.#4355

Merged
htuch merged 18 commits intoenvoyproxy:masterfrom
istio:refactor_sds_api
Sep 17, 2018
Merged

Fetch certificate validation context using SDS service.#4355
htuch merged 18 commits intoenvoyproxy:masterfrom
istio:refactor_sds_api

Conversation

@JimmyCYJ
Copy link
Member

@JimmyCYJ JimmyCYJ commented Sep 6, 2018

Description: Refactor SdsApi to support dynamic certificate validation context, and support Envoy to fetch certificate validation context from remote server via SDS API.
Risk Level: Low
Testing: Unit tests and integration tests.
Fixes #1194

Signed-off-by: Jimmy Chen jimmychen.0102@gmail.com

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
@JimmyCYJ
Copy link
Member Author

JimmyCYJ commented Sep 6, 2018

I am adding unit tests and integration tests to cover this change.

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
Common::CallbackHandle* tls_certificate_update_callback_handle_;
Secret::CertificateValidationContextConfigProviderSharedPtr
certficate_validation_context_provider_;
Common::CallbackHandle* certificate_validation_context_update_callback_handle_;
Copy link
Contributor

Choose a reason for hiding this comment

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

variable name is too long

…_api

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
}

CertificateValidationContextConfigProviderSharedPtr
SecretManagerImpl::findOrCreateCertificateValidationContextProvider(
Copy link
Contributor

Choose a reason for hiding this comment

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

The code is similar for this function and the other. try to share them by create a

SdsApiSharedPtr innerFindOrCreate(..., create_fn);

Then, each function will provide its creation_function to create proper object,

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

RepeatedPtrUtil::join(config.tls_params().ecdh_curves(), ":"), DEFAULT_ECDH_CURVES)),
tls_certficate_provider_(getTlsCertificateConfigProvider(config, factory_context)),
secret_update_callback_handle_(nullptr),
tls_certificate_update_callback_handle_(nullptr),
Copy link
Contributor

Choose a reason for hiding this comment

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

use {} to initiliaze raw pointer

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

const std::string ecdh_curves_;
Secret::TlsCertificateConfigProviderSharedPtr tls_certficate_provider_;
Common::CallbackHandle* secret_update_callback_handle_;
Common::CallbackHandle* tls_certificate_update_callback_handle_;
Copy link
Contributor

Choose a reason for hiding this comment

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

just add {} next to the raw pointer to initailize it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
TlsCertificateConfigProviderSharedPtr SecretManagerImpl::findOrCreateTlsCertificateProvider(
const envoy::api::v2::core::ConfigSource& sds_config_source, const std::string& config_name,
Server::Configuration::TransportSocketFactoryContext& secret_provider_context) {
std::function<SdsApiSharedPtr(std::function<void()> unregister_secret_provider)> create_fn =
Copy link
Contributor

Choose a reason for hiding this comment

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

just use auto as
auto create_fn = [&]

in the capture, not need to list all used variable, just one & to tell compiler that all used variables are using reference.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

std::function<SdsApiSharedPtr(std::function<void()> unregister_secret_provider)> create_fn =
[&sds_config_source, &config_name, &secret_provider_context](
std::function<void()> unregister_secret_provider) -> SdsApiSharedPtr {
return std::make_shared<TlsCertificateSdsApi>(
Copy link
Contributor

Choose a reason for hiding this comment

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

How about move this make_shared code to a static create() function in the

TlsCertificateSdsApi class

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

secret.type_case() == envoy::api::v2::auth::Secret::TypeCase::kValidationContext) {
secret_hash_ = new_hash;
secrets_ =
certificate_validation_context_secrets_ =
Copy link
Contributor

Choose a reason for hiding this comment

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

these two updateConfigHelper are almost the same. can we move them to the sds_api base class

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
Stats::Store& stats, Upstream::ClusterManager& cluster_manager,
Init::Manager& init_manager,
const envoy::api::v2::core::ConfigSource& sds_config,
const std::string& sds_config_name,
Copy link
Contributor

Choose a reason for hiding this comment

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

can we use provider_context in create() function so less number of argument to pass?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

auto sds_api = std::static_pointer_cast<CertificateValidationContextSdsApi>(
CertificateValidationContextSdsApi::create(
server.localInfo(), server.dispatcher(), server.random(), server.stats(),
server.clusterManager(), init_manager, config_source, "abc.com", []() {}));
Copy link
Contributor

Choose a reason for hiding this comment

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

you don't need to change this. It can still use constructor

Copy link
Member Author

Choose a reason for hiding this comment

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

Reverted.

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
: SdsApi(local_info, dispatcher, random, stats, cluster_manager, init_manager, sds_config,
sds_config_name, destructor_cb,
[this](const uint64_t new_hash, const envoy::api::v2::auth::Secret& secret) {
if (new_hash != secret_hash_ &&
Copy link
Contributor

Choose a reason for hiding this comment

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

This create_secret_fn is doing more than creating secret. It is confusing.

My idea: derived class overload two virtual functions:
secret_type() and set_secret(). That is it. Most of updateConfig() logic are in the sds_api class

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
@qiwzhang
Copy link
Contributor

qiwzhang commented Sep 7, 2018

LGTM

@JimmyCYJ JimmyCYJ changed the title [WIP] Support Envoy to fetch certificate validation context using SDS service. Support Envoy to fetch certificate validation context using SDS service. Sep 7, 2018
@JimmyCYJ
Copy link
Member Author

JimmyCYJ commented Sep 7, 2018

cc @lizan @htuch

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
@htuch htuch self-assigned this Sep 12, 2018
Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
…_api

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
@JimmyCYJ JimmyCYJ changed the title Support Envoy to fetch certificate validation context using SDS service. Fetch certificate validation context using SDS service. Sep 13, 2018
Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

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

Looks good, should be shippable after this round of feedback.

}
protected:
// Creates new secrets.
virtual void set_secret(const envoy::api::v2::auth::Secret&) PURE;
Copy link
Member

Choose a reason for hiding this comment

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

Nit: setSecret

Copy link
Member Author

Choose a reason for hiding this comment

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

Done. Thanks!

// Creates new secrets.
virtual void set_secret(const envoy::api::v2::auth::Secret&) PURE;
Common::CallbackManager<> update_callback_manager_;
uint64_t secret_hash_;
Copy link
Member

Choose a reason for hiding this comment

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

Why is secret_hash_ no longer private?

Copy link
Member Author

Choose a reason for hiding this comment

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

It should be private, thanks for catching this.
It was changed to be protected because it was assigned to a new hash in derived class. But then we simplified that part of code and moved hash calculation back to base class.

* CertificateValidationContextSdsApi implementation maintains and updates dynamic certificate
* validation context secrets.
*/
class CertificateValidationContextSdsApi : public SdsApi,
Copy link
Member

Choose a reason for hiding this comment

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

At first I thought templates might be a nice thing here to avoid the boiler plate, but then we have another problem, namely how to marry templates and virtual inheritance. Worth thinking about if you have any way to reduce this repetition.

Copy link
Member Author

Choose a reason for hiding this comment

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

We tried using templates at first (cd35a2c), and then we found that causes many duplicated methods. We have to add more methods into secret manager to create each type of provider, and the provider creation methods have duplicated code. We also need two maps for each type of providers in secret manager. Besides, each type of provider also overrides some methods of provider interface, and those methods have duplicated code, too. Then we decide to switch to this way and simplify the code a lot. We don't find a better way for now.

// Removes dynamic secret provider which has been deleted.
void removeDynamicSecretProvider(const std::string& map_key);
// Finds or creates SdsApi object.
SdsApiSharedPtr innerFindOrCreate(
Copy link
Member

Choose a reason for hiding this comment

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

Can we rename innerFindOrCreate to something else? Even findOrCreate would be fine, I just find "inner" leads to more questions (e.g. "is this an inner class?", "inner of what?"), so this isn't as clear as it could be.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point. Changed to findOrCreate. Thanks.


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

Choose a reason for hiding this comment

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

Is this definitely TLS? It seems the general SdsApi type of dynamic_secret_providers_ might suggest otherwise?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this message is not correct. Changed to secret provider.

TlsCertificateConfigProviderSharedPtr SecretManagerImpl::findOrCreateTlsCertificateProvider(
const envoy::api::v2::core::ConfigSource& sds_config_source, const std::string& config_name,
Server::Configuration::TransportSocketFactoryContext& secret_provider_context) {
auto create_fn = [&](std::function<void()> unregister_secret_provider) -> SdsApiSharedPtr {
Copy link
Member

Choose a reason for hiding this comment

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

Prefer to use explicit capture rather than & for lambdas (I think this is a style guide recommendation).

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, done.

if (secret_update_callback_handle_) {
secret_update_callback_handle_->remove();
if (tc_update_callback_handle_) {
tc_update_callback_handle_->remove();
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed in context_impl_test.cc. Thanks.

}
if (certficate_validation_context_provider_) {
if (cvc_update_callback_handle_) {
cvc_update_callback_handle_->remove();
Copy link
Member

Choose a reason for hiding this comment

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

Ditto

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed in context_impl_test.cc. Thanks.

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
…_api

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

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

Rad, thanks!

};
SdsApiSharedPtr secret_provider = findOrCreate(sds_config_source, config_name, create_fn);

return std::dynamic_pointer_cast<CertificateValidationContextConfigProvider>(secret_provider);
Copy link
Member

Choose a reason for hiding this comment

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

Can we templatize findOrCreate and remove avoid std::dynamic_pointer_cast here?

Copy link
Member Author

Choose a reason for hiding this comment

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

We are building sidecar with SDS feature from istio:collab-gcp-identity branch, and @quanjielin is working on merging istio:collab-gcp-identity branch into istio:master. This PR blocks the merge.
Maybe let's make this change in a follow up PR. I would like to get this in soon.

@htuch htuch merged commit 15cfc5a into envoyproxy:master Sep 17, 2018
@JimmyCYJ JimmyCYJ deleted the refactor_sds_api branch September 17, 2018 23:19
htuch pushed a commit that referenced this pull request Sep 18, 2018
According to comment in PR #4355, we want to avoid std::dynamic_pointer_cast in SecretManagerImpl. This PR creates a template class and moves findOrCreate method into the template class.

Risk Level: Low
Testing: Existing unit tests and integration tests.

Signed-off-by: JimmyCYJ <jimmychen.0102@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants