Skip to content

Commit

Permalink
Support Envoy to fetch secrets using SDS service. (#4256)
Browse files Browse the repository at this point in the history
Description: Use SDS api that fetches secrets from remote SDS server. Secrets are stored in Secret Provider. Listeners and Clusters are updated when secrets are received.
Risk Level: Low
Testing: Unit tests and integration tests
Fixes #1194

Signed-off-by: Jimmy Chen jimmychen.0102@gmail.com
  • Loading branch information
JimmyCYJ authored and lizan committed Aug 31, 2018
1 parent a857219 commit 9c492a0
Show file tree
Hide file tree
Showing 55 changed files with 1,055 additions and 208 deletions.
1 change: 1 addition & 0 deletions include/envoy/secret/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ envoy_cc_library(
deps = [
":secret_provider_interface",
"@envoy_api//envoy/api/v2/auth:cert_cc",
"@envoy_api//envoy/api/v2/core:config_source_cc",
],
)
1 change: 1 addition & 0 deletions include/envoy/secret/secret_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Secret {
class SecretCallbacks {
public:
virtual ~SecretCallbacks() {}

virtual void onAddOrUpdateSecret() PURE;
};

Expand Down
28 changes: 24 additions & 4 deletions include/envoy/secret/secret_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
#include "envoy/secret/secret_provider.h"

namespace Envoy {

namespace Server {
namespace Configuration {
class TransportSocketFactoryContext;
} // namespace Configuration
} // namespace Server

namespace Secret {

/**
* A manager for static secrets.
*
* TODO(jaebong) Support dynamic secrets.
* A manager for static and dynamic secrets.
*/
class SecretManager {
public:
Expand Down Expand Up @@ -47,14 +52,29 @@ class SecretManager {
const envoy::api::v2::auth::TlsCertificate& tls_certificate) PURE;

/**
* @param tls_certificate the protobuf config of the certificate validation context.
* @param certificate_validation_context the protobuf config of the certificate validation
* context.
* @return a CertificateValidationContextConfigProviderSharedPtr created from
* certificate_validation_context.
*/
virtual CertificateValidationContextConfigProviderSharedPtr
createInlineCertificateValidationContextProvider(
const envoy::api::v2::auth::CertificateValidationContext& certificate_validation_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 TlsCertificateConfigProviderSharedPtr the dynamic TLS secret provider.
*/
virtual TlsCertificateConfigProviderSharedPtr findOrCreateTlsCertificateProvider(
const envoy::api::v2::core::ConfigSource& config_source, const std::string& config_name,
Server::Configuration::TransportSocketFactoryContext& secret_provider_context) PURE;
};

} // namespace Secret
Expand Down
2 changes: 1 addition & 1 deletion include/envoy/secret/secret_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ template <class SecretType> class SecretProvider {

/**
* Add secret update callback into secret provider.
* It is safe to call this method by main thread and is safe to be invoked
* It is safe to call this method by main thread and callback is safe to be invoked
* on main thread.
* @param callback callback that is executed by secret provider.
* @return CallbackHandle the handle which can remove that update callback.
Expand Down
1 change: 1 addition & 0 deletions include/envoy/server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ envoy_cc_library(
hdrs = ["transport_socket_config.h"],
deps = [
"//include/envoy/event:dispatcher_interface",
"//include/envoy/init:init_interface",
"//include/envoy/local_info:local_info_interface",
"//include/envoy/network:transport_socket_interface",
"//include/envoy/runtime:runtime_interface",
Expand Down
13 changes: 13 additions & 0 deletions include/envoy/server/transport_socket_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <string>

#include "envoy/event/dispatcher.h"
#include "envoy/init/init.h"
#include "envoy/local_info/local_info.h"
#include "envoy/network/transport_socket.h"
#include "envoy/runtime/runtime.h"
Expand Down Expand Up @@ -63,6 +64,18 @@ class TransportSocketFactoryContext {
* @return the server-wide stats store.
*/
virtual Stats::Store& stats() PURE;

/**
* Pass an init manager to register dynamic secret provider.
* @param init_manager instance of init manager.
*/
virtual void setInitManager(Init::Manager& init_manager) PURE;

/**
* @return a pointer pointing to the instance of an init manager, or nullptr
* if not set.
*/
virtual Init::Manager* initManager() PURE;
};

class TransportSocketConfigFactory {
Expand Down
13 changes: 13 additions & 0 deletions include/envoy/ssl/context_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@ class ContextConfig {
* @return The maximum TLS protocol version to negotiate.
*/
virtual unsigned maxProtocolVersion() const PURE;

/**
* @return true if the ContextConfig is able to provide secrets to create SSL context,
* and false if dynamic secrets are expected but are not downloaded from SDS server yet.
*/
virtual bool isReady() const PURE;

/**
* Add secret callback into context config. When dynamic secrets are in use and new secrets
* are downloaded from SDS server, this callback is invoked to update SSL context.
* @param callback callback that is executed by context config.
*/
virtual void setSecretUpdateCallback(std::function<void()> callback) PURE;
};

class ClientContextConfig : public virtual ContextConfig {
Expand Down
1 change: 1 addition & 0 deletions source/common/config/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ envoy_cc_library(
hdrs = ["protobuf_link_hacks.h"],
deps = [
"@envoy_api//envoy/service/discovery/v2:ads_cc",
"@envoy_api//envoy/service/discovery/v2:sds_cc",
"@envoy_api//envoy/service/ratelimit/v2:rls_cc",
],
)
Expand Down
2 changes: 2 additions & 0 deletions source/common/config/protobuf_link_hacks.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "envoy/service/discovery/v2/ads.pb.h"
#include "envoy/service/discovery/v2/sds.pb.h"
#include "envoy/service/ratelimit/v2/rls.pb.h"

namespace Envoy {
Expand All @@ -9,4 +10,5 @@ namespace Envoy {
// This file should be included ONLY if this hack is required.
const envoy::service::discovery::v2::AdsDummy _ads_dummy;
const envoy::service::ratelimit::v2::RateLimitRequest _rls_dummy;
const envoy::service::discovery::v2::SdsDummy _sds_dummy;
} // namespace Envoy
1 change: 1 addition & 0 deletions source/common/config/resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class TypeUrlValues {
const std::string Listener{"type.googleapis.com/envoy.api.v2.Listener"};
const std::string Cluster{"type.googleapis.com/envoy.api.v2.Cluster"};
const std::string ClusterLoadAssignment{"type.googleapis.com/envoy.api.v2.ClusterLoadAssignment"};
const std::string Secret{"type.googleapis.com/envoy.api.v2.auth.Secret"};
const std::string RouteConfiguration{"type.googleapis.com/envoy.api.v2.RouteConfiguration"};
};

Expand Down
3 changes: 3 additions & 0 deletions source/common/secret/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ envoy_cc_library(
srcs = ["secret_manager_impl.cc"],
hdrs = ["secret_manager_impl.h"],
deps = [
":sds_api_lib",
":secret_provider_impl_lib",
"//include/envoy/secret:secret_manager_interface",
"//include/envoy/server:transport_socket_config_interface",
"//source/common/common:assert_lib",
"//source/common/common:minimal_logger_lib",
"@envoy_api//envoy/api/v2/auth:cert_cc",
],
Expand Down
34 changes: 34 additions & 0 deletions source/common/secret/secret_manager_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "envoy/common/exception.h"

#include "common/common/assert.h"
#include "common/secret/sds_api.h"
#include "common/secret/secret_provider_impl.h"
#include "common/ssl/certificate_validation_context_config_impl.h"
#include "common/ssl/tls_certificate_config_impl.h"
Expand Down Expand Up @@ -63,5 +64,38 @@ SecretManagerImpl::createInlineCertificateValidationContextProvider(
certificate_validation_context);
}

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

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

TlsCertificateConfigProviderSharedPtr SecretManagerImpl::findOrCreateTlsCertificateProvider(
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;

TlsCertificateConfigProviderSharedPtr secret_provider = dynamic_secret_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);
};

secret_provider = std::make_shared<SdsApi>(
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;
}

return secret_provider;
}

} // namespace Secret
} // namespace Envoy
12 changes: 12 additions & 0 deletions source/common/secret/secret_manager_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "envoy/secret/secret_manager.h"
#include "envoy/secret/secret_provider.h"
#include "envoy/server/transport_socket_config.h"
#include "envoy/ssl/certificate_validation_context_config.h"
#include "envoy/ssl/tls_certificate_config.h"

Expand All @@ -30,14 +31,25 @@ class SecretManagerImpl : public SecretManager, Logger::Loggable<Logger::Id::sec
const envoy::api::v2::auth::CertificateValidationContext& certificate_validation_context)
override;

TlsCertificateConfigProviderSharedPtr findOrCreateTlsCertificateProvider(
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);

// Manages pairs of secret name and TlsCertificateConfigProviderSharedPtr.
std::unordered_map<std::string, TlsCertificateConfigProviderSharedPtr>
static_tls_certificate_providers_;

// Manages pairs of secret name and CertificateValidationContextConfigProviderSharedPtr.
std::unordered_map<std::string, CertificateValidationContextConfigProviderSharedPtr>
static_certificate_validation_context_providers_;

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

} // namespace Secret
Expand Down
4 changes: 3 additions & 1 deletion source/common/ssl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ envoy_cc_library(
":utility_lib",
"//include/envoy/network:connection_interface",
"//include/envoy/network:transport_socket_interface",
"//include/envoy/stats:stats_macros",
"//source/common/common:assert_lib",
"//source/common/common:empty_string",
"//source/common/common:minimal_logger_lib",
Expand All @@ -34,8 +35,9 @@ envoy_cc_library(
"ssl",
],
deps = [
"//include/envoy/secret:secret_manager_interface",
"//include/envoy/secret:secret_callbacks_interface",
"//include/envoy/secret:secret_provider_interface",
"//include/envoy/server:transport_socket_config_interface",
"//include/envoy/ssl:context_config_interface",
"//source/common/common:assert_lib",
"//source/common/common:empty_string",
Expand Down
Loading

0 comments on commit 9c492a0

Please sign in to comment.