Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 7 additions & 0 deletions include/envoy/secret/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ load(

envoy_package()

envoy_cc_library(
name = "secret_callbacks_interface",
hdrs = ["secret_callbacks.h"],
)

envoy_cc_library(
name = "secret_manager_interface",
hdrs = ["secret_manager.h"],
deps = [
":secret_callbacks_interface",
"//include/envoy/ssl:tls_certificate_config_interface",
"@envoy_api//envoy/api/v2/auth:cert_cc",
"@envoy_api//envoy/api/v2/core:config_source_cc",
],
)
22 changes: 22 additions & 0 deletions include/envoy/secret/secret_callbacks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include <memory>
#include <string>

#include "envoy/common/pure.h"

namespace Envoy {
namespace Secret {

/**
* Callbacks invoked by a secret manager.
*/
class SecretCallbacks {
public:
virtual ~SecretCallbacks() {}

virtual void onAddOrUpdateSecret() PURE;
};

} // namespace Secret
} // namespace Envoy
46 changes: 41 additions & 5 deletions include/envoy/secret/secret_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,67 @@
#include <string>

#include "envoy/api/v2/auth/cert.pb.h"
#include "envoy/secret/secret_callbacks.h"
#include "envoy/ssl/tls_certificate_config.h"

namespace Envoy {
namespace Secret {

/**
* A manager for static secrets.
*
* TODO(jaebong) Support dynamic secrets.
* A manager for static and dynamic secrets.
*/
class SecretManager {
public:
virtual ~SecretManager() {}

/**
* @param config_source_hash a hash string of normalized config source. If it is empty string,
* find secret from the static secrets.
* @param secret a protobuf message of envoy::api::v2::auth::Secret.
* @throw an EnvoyException if the secret is invalid or not supported.
*/
virtual void addOrUpdateSecret(const envoy::api::v2::auth::Secret& secret) PURE;
virtual void addOrUpdateSecret(const std::string& config_source_hash,
const envoy::api::v2::auth::Secret& secret) PURE;

/**
* @param sds_config_source_hash hash string of normalized config source.
* @param name a name of the Ssl::TlsCertificateConfig.
* @return the TlsCertificate secret. Returns nullptr if the secret is not found.
*/
virtual const Ssl::TlsCertificateConfig* findTlsCertificate(const std::string& name) const PURE;
virtual const Ssl::TlsCertificateConfig* findTlsCertificate(const std::string& config_source_hash,
const std::string& name) const PURE;

/**
* Add or update SDS config source. SecretManager starts downloading secrets from registered
* config source.
*
* @param sdsConfigSource a protobuf message object contains SDS config source.
* @param config_name a name that uniquely refers to the SDS config source.
* @return a hash string of normalized config source.
*/
virtual std::string addOrUpdateSdsService(const envoy::api::v2::core::ConfigSource& config_source,
std::string config_name) PURE;

/**
* Register callback function which is to be invoked on secret update.
*
* @param config_source_hash Hash code of ConfigSource.
* @param secret_name name of the secret.
* @param callback SecretCallbacks class.
*/
virtual void registerTlsCertificateConfigCallbacks(const std::string& config_source_hash,
const std::string& secret_name,
SecretCallbacks* callback) PURE;

/**
* Unregister callback function.
* @param config_source_hash Hash code of ConfigSource.
* @param secret_name name of the secret.
* @param callback SecretCallbacks class.
*/
virtual void unRegisterTlsCertificateConfigCallbacks(const std::string& config_source_hash,
const std::string& secret_name,
SecretCallbacks& callback) PURE;
};

} // namespace Secret
Expand Down
4 changes: 4 additions & 0 deletions include/envoy/ssl/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@ class Context {
virtual std::string getCertChainInformation() const PURE;
};

typedef std::shared_ptr<Context> ContextSharedPtr;

class ClientContext : public virtual Context {};
typedef std::unique_ptr<ClientContext> ClientContextPtr;
typedef std::shared_ptr<ClientContext> ClientContextSharedPtr;

class ServerContext : public virtual Context {};
typedef std::unique_ptr<ServerContext> ServerContextPtr;
typedef std::shared_ptr<ServerContext> ServerContextSharedPtr;

} // namespace Ssl
} // namespace Envoy
21 changes: 21 additions & 0 deletions include/envoy/ssl/context_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,23 @@ class ContextConfig {
* @return The maximum TLS protocol version to negotiate.
*/
virtual unsigned maxProtocolVersion() const PURE;

/**
* @return The hash code of SdsSecretConfig in std::string. If the SdsSecretConfig is empty, then
* returns empty string.
*/
virtual const std::string& sdsConfigSourceHash() const PURE;

/**
* @return The secret name in SdsSecretConfig. If SdsSecretConfig is empty, returns empty string.
*/
virtual const std::string& sdsSecretName() const PURE;

/**
* @return true if dynamic secret is required per config, and is not
* downloaded from SDS server yet; and false otherwise.
*/
virtual bool waitForSdsSecret() const PURE;
};

class ClientContextConfig : public virtual ContextConfig {
Expand All @@ -127,6 +144,8 @@ class ClientContextConfig : public virtual ContextConfig {
virtual bool allowRenegotiation() const PURE;
};

typedef std::unique_ptr<ClientContextConfig> ClientContextConfigPtr;

class ServerContextConfig : public virtual ContextConfig {
public:
struct SessionTicketKey {
Expand All @@ -148,5 +167,7 @@ class ServerContextConfig : public virtual ContextConfig {
virtual const std::vector<SessionTicketKey>& sessionTicketKeys() const PURE;
};

typedef std::unique_ptr<ServerContextConfig> ServerContextConfigPtr;

} // namespace Ssl
} // namespace Envoy
43 changes: 40 additions & 3 deletions include/envoy/ssl/context_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <functional>

#include "envoy/secret/secret_manager.h"
#include "envoy/ssl/context.h"
#include "envoy/ssl/context_config.h"
#include "envoy/stats/stats.h"
Expand All @@ -19,16 +20,42 @@ class ContextManager {
/**
* Builds a ClientContext from a ClientContextConfig.
*/
virtual ClientContextPtr createSslClientContext(Stats::Scope& scope,
const ClientContextConfig& config) PURE;
virtual ClientContextSharedPtr createSslClientContext(Stats::Scope& scope,
const ClientContextConfig& config) PURE;

/**
* Updates ClientContext and returns updated ClientContext.
*
* @param context ClientContext to be updated.
* @param scope stats scope.
* @param config supplies the configuration for ClientContext.
* @return an updated ClientContext.
*/
virtual ClientContextSharedPtr updateSslClientContext(const ClientContextSharedPtr context,
Stats::Scope& scope,
const ClientContextConfig& config) PURE;

/**
* Builds a ServerContext from a ServerContextConfig.
*/
virtual ServerContextPtr
virtual ServerContextSharedPtr
createSslServerContext(Stats::Scope& scope, const ServerContextConfig& config,
const std::vector<std::string>& server_names) PURE;

/**
* Updates ServerContext and returns updated ServerContext.
*
* @param context ServerContext to be updated.
* @param scope stats scope
* @param config supplies the configuration for ServerContext.
* @param server_names server names.
* @return an updated ServerContext.
*/
virtual ServerContextSharedPtr
updateSslServerContext(const ServerContextSharedPtr context, Stats::Scope& scope,
const ServerContextConfig& config,
const std::vector<std::string>& server_names) PURE;

/**
* @return the number of days until the next certificate being managed will expire.
*/
Expand All @@ -38,6 +65,16 @@ class ContextManager {
* Iterate through all currently allocated contexts.
*/
virtual void iterateContexts(std::function<void(const Context&)> callback) PURE;

/**
* release context from this manager.
*/
virtual void releaseContext(Context* context) PURE;

/**
* @return a SecretManager.
*/
virtual Secret::SecretManager& secretManager() PURE;
};

} // namespace Ssl
Expand Down
8 changes: 7 additions & 1 deletion include/envoy/ssl/tls_certificate_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ class TlsCertificateConfig {
* @return a string of private key
*/
virtual const std::string& privateKey() const PURE;

/**
* @return true if secret contains same certificate chain and private key.
* Otherwise returns false.
*/
virtual bool equalTo(const TlsCertificateConfig& secret) const PURE;
};

typedef std::unique_ptr<TlsCertificateConfig> TlsCertificateConfigPtr;
typedef std::unique_ptr<const TlsCertificateConfig> TlsCertificateConfigPtr;

} // namespace Ssl
} // namespace Envoy
1 change: 1 addition & 0 deletions source/common/config/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,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,12 +1,14 @@
#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 {

// Hack to force linking of the service: https://github.com/google/protobuf/issues/4221.
// This file should be included ONLY if this hack is required.
const envoy::service::discovery::v2::AdsDummy _ads_dummy;
const envoy::service::discovery::v2::SdsDummy _sds_dummy;
const envoy::service::ratelimit::v2::RateLimitRequest _rls_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
25 changes: 25 additions & 0 deletions source/common/secret/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,34 @@ envoy_cc_library(
srcs = ["secret_manager_impl.cc"],
hdrs = ["secret_manager_impl.h"],
deps = [
":sds_api_lib",
":secret_manager_util",
"//include/envoy/secret:secret_manager_interface",
"//include/envoy/server:instance_interface",
"//source/common/common:minimal_logger_lib",
"//source/common/ssl:tls_certificate_config_impl_lib",
"@envoy_api//envoy/api/v2/auth:cert_cc",
],
)

envoy_cc_library(
name = "secret_manager_util",
hdrs = ["secret_manager_util.h"],
deps = [
"//source/common/json:json_loader_lib",
"@envoy_api//envoy/api/v2/core:config_source_cc",
],
)

envoy_cc_library(
name = "sds_api_lib",
srcs = ["sds_api.cc"],
hdrs = ["sds_api.h"],
deps = [
":secret_manager_util",
"//include/envoy/config:subscription_interface",
"//include/envoy/server:instance_interface",
"//source/common/config:resources_lib",
"//source/common/config:subscription_factory_lib",
],
)
62 changes: 62 additions & 0 deletions source/common/secret/sds_api.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#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_hash, std::string sds_config_name)
: server_(server), sds_config_(sds_config), sds_config_source_hash_(sds_config_hash),
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",
"envoy.service.discovery.v2.SecretDiscoveryService.StreamSecrets");

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
Loading