Skip to content

Commit

Permalink
Implement certificate_provider_instances in bootstrap (#19308)
Browse files Browse the repository at this point in the history
Introduce a CertificateProviderManager to parse the certificate_provider_instances
config and instantiate certificate providers.

Signed-off-by: Luyao Zhong <[email protected]>
  • Loading branch information
Luyao Zhong committed Feb 15, 2022
1 parent e727e1f commit d4eb3cb
Show file tree
Hide file tree
Showing 28 changed files with 463 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
/*/extensions/access_loggers/filters/cel @dio @douglas-reid
/*/extensions/access_loggers/open_telemetry @itamarkam @yanavlasov
/*/extensions/access_loggers/stream @mattklein123 @davinci26
# certificate providers extensions
/*/extensions/certificate_providers/default_cert_provider @LuyaoZhong @lizan
# compression extensions
/*/extensions/compression/common/compressor @rojkov @junr03
/*/extensions/compression/gzip/compressor @rojkov @junr03
Expand Down
1 change: 0 additions & 1 deletion api/envoy/config/bootstrap/v3/bootstrap.proto
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,6 @@ message Bootstrap {
// :ref:`CommonTlsContext.CertificateProviderInstance.instance_name
// <envoy_v3_api_field_extensions.transport_sockets.tls.v3.CommonTlsContext.CertificateProviderInstance.instance_name>`
// field.
// [#not-implemented-hide:]
map<string, core.v3.TypedExtensionConfig> certificate_provider_instances = 25;

// Specifies a set of headers that need to be registered as inline header. This configuration
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = [
"//envoy/config/core/v3:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
syntax = "proto3";

package envoy.extensions.certificate_providers.default_cert_provider.v3;

import "envoy/config/core/v3/base.proto";

import "udpa/annotations/status.proto";

option java_package = "io.envoyproxy.envoy.extensions.certificate_providers.default_cert_provider.v3";
option java_outer_classname = "ConfigProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/certificate_providers/default_cert_provider/v3;default_cert_providerv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Default Certificate Provider]
// [#extension: envoy.cert_providers.default_cert_provider]

// A DefaultCertProvider provides static TLS identity certificate
// [#extension-category: envoy.cert_providers]

message DefaultCertProviderConfig {
config.core.v3.DataSource certificate = 1;

config.core.v3.DataSource private_key = 2;
}
1 change: 1 addition & 0 deletions api/versioning/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ proto_library(
"//envoy/extensions/access_loggers/stream/v3:pkg",
"//envoy/extensions/access_loggers/wasm/v3:pkg",
"//envoy/extensions/cache/simple_http_cache/v3:pkg",
"//envoy/extensions/certificate_providers/default_cert_provider/v3:pkg",
"//envoy/extensions/clusters/aggregate/v3:pkg",
"//envoy/extensions/clusters/dynamic_forward_proxy/v3:pkg",
"//envoy/extensions/clusters/redis/v3:pkg",
Expand Down
18 changes: 18 additions & 0 deletions envoy/certificate_provider/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_package",
)

licenses(["notice"]) # Apache 2

envoy_package()

envoy_cc_library(
name = "certificate_provider_manager_interface",
hdrs = ["certificate_provider_manager.h"],
deps = [
"//source/extensions/certificate_providers:certificate_provider_lib",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
],
)
31 changes: 31 additions & 0 deletions envoy/certificate_provider/certificate_provider_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <string>

#include "envoy/common/pure.h"
#include "envoy/config/core/v3/extension.pb.h"

#include "source/extensions/certificate_providers/certificate_provider.h"

namespace Envoy {
namespace CertificateProvider {

/**
* A manager for certificate provider instances.
*/
class CertificateProviderManager {
public:
virtual ~CertificateProviderManager() = default;

virtual void
addCertificateProvider(std::string name,
const envoy::config::core::v3::TypedExtensionConfig& config) PURE;

virtual Envoy::Extensions::CertificateProviders::CertificateProviderSharedPtr
getCertificateProvider(std::string name) PURE;
};

using CertificateProviderManagerPtr = std::unique_ptr<CertificateProviderManager>;

} // namespace CertificateProvider
} // namespace Envoy
1 change: 1 addition & 0 deletions envoy/server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ envoy_cc_library(
":options_interface",
"//envoy/access_log:access_log_interface",
"//envoy/api:api_interface",
"//envoy/certificate_provider:certificate_provider_manager_interface",
"//envoy/common:mutex_tracer",
"//envoy/event:timer_interface",
"//envoy/http:context_interface",
Expand Down
6 changes: 6 additions & 0 deletions envoy/server/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "envoy/access_log/access_log.h"
#include "envoy/api/api.h"
#include "envoy/certificate_provider/certificate_provider_manager.h"
#include "envoy/common/mutex_tracer.h"
#include "envoy/common/random_generator.h"
#include "envoy/config/trace/v3/http_tracer.pb.h"
Expand Down Expand Up @@ -137,6 +138,11 @@ class Instance {
*/
virtual Secret::SecretManager& secretManager() PURE;

/**
* @return the certificate provider manager
*/
virtual CertificateProvider::CertificateProviderManager& certificateProviderManager() PURE;

/**
* @return the server's CLI options.
*/
Expand Down
22 changes: 22 additions & 0 deletions source/common/certificate_provider/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_package",
)

licenses(["notice"]) # Apache 2

envoy_package()

envoy_cc_library(
name = "certificate_provider_manager_impl_lib",
srcs = ["certificate_provider_manager_impl.cc"],
hdrs = ["certificate_provider_manager_impl.h"],
deps = [
"//envoy/api:api_interface",
"//envoy/certificate_provider:certificate_provider_manager_interface",
"//source/common/config:utility_lib",
"@com_google_absl//absl/container:flat_hash_map",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "source/common/certificate_provider/certificate_provider_manager_impl.h"

#include <string>

#include "envoy/common/exception.h"

#include "source/common/config/utility.h"
#include "source/extensions/certificate_providers/factory.h"

namespace Envoy {
namespace CertificateProvider {

CertificateProviderManagerImpl::CertificateProviderManagerImpl(Api::Api& api) : api_(api) {}

void CertificateProviderManagerImpl::addCertificateProvider(
std::string name, const envoy::config::core::v3::TypedExtensionConfig& config) {
auto& cert_provider_factory = Envoy::Config::Utility::getAndCheckFactory<
Extensions::CertificateProviders::CertificateProviderFactory>(config);

auto cert_provider_instance =
cert_provider_factory.createCertificateProviderInstance(config, api_);
certificate_provider_instances_.emplace(name, cert_provider_instance);
}

Envoy::Extensions::CertificateProviders::CertificateProviderSharedPtr
CertificateProviderManagerImpl::getCertificateProvider(std::string name) {
auto it = certificate_provider_instances_.find(name);
if (it != certificate_provider_instances_.end()) {
return it->second;
} else {
return nullptr;
}
}

} // namespace CertificateProvider
} // namespace Envoy
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include <string>

#include "envoy/api/api.h"
#include "envoy/certificate_provider/certificate_provider_manager.h"
#include "envoy/config/core/v3/extension.pb.h"

#include "absl/container/flat_hash_map.h"

namespace Envoy {
namespace CertificateProvider {

/**
* A manager for certificate provider instances.
*/
class CertificateProviderManagerImpl : public CertificateProviderManager {
public:
CertificateProviderManagerImpl(Api::Api& api);

void addCertificateProvider(std::string name,
const envoy::config::core::v3::TypedExtensionConfig& config) override;

Envoy::Extensions::CertificateProviders::CertificateProviderSharedPtr
getCertificateProvider(std::string name) override;

private:
absl::flat_hash_map<std::string,
Envoy::Extensions::CertificateProviders::CertificateProviderSharedPtr>
certificate_provider_instances_;
Api::Api& api_;
};

using CertificateProviderManagerPtr = std::unique_ptr<CertificateProviderManager>;

} // namespace CertificateProvider
} // namespace Envoy
29 changes: 29 additions & 0 deletions source/extensions/certificate_providers/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_extension_package",
)

licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_library(
name = "certificate_provider_lib",
srcs = [
"factory.cc",
],
hdrs = [
"certificate_provider.h",
"factory.h",
],
external_deps = [
"ssl",
],
visibility = ["//visibility:public"],
deps = [
"//envoy/registry",
"@com_google_absl//absl/strings",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
],
)
59 changes: 59 additions & 0 deletions source/extensions/certificate_providers/certificate_provider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#pragma once

#include <list>

#include "envoy/common/pure.h"

#include "absl/strings/string_view.h"
#include "openssl/ssl.h"
#include "openssl/x509v3.h"

namespace Envoy {
namespace Extensions {
namespace CertificateProviders {

struct Certpair {
const std::string& certificate_;
const std::string& private_key_;
};

struct Capabilites {
/* whether or not a provider provides a ca cert directly */
bool provide_ca_cert = false;

/* Whether or not a provider provides identity certs directly */
bool provide_identity_certs = false;

/* whether or not a provider supports generating identity certs during handshake,
* which requires the capability provide_ca_cert to sign the certificates
*/
bool generate_identity_certs = false;
};

class CertificateProvider {
public:
virtual ~CertificateProvider() = default;

virtual Capabilites capabilities() const PURE;

/**
* @return CA certificate from provider
*/
virtual const std::string& getCACertificate() const PURE;

/*
* Get TLS identity certificates directly from provider
*/
virtual std::list<Certpair> getTlsCertificates() PURE;

/*
* Generate TLS identity certificate dynamically during TLS handshake
*/
virtual Certpair* generateTlsCertificate(absl::string_view server_name) PURE;
};

using CertificateProviderSharedPtr = std::shared_ptr<CertificateProvider>;

} // namespace CertificateProviders
} // namespace Extensions
} // namespace Envoy
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_extension",
"envoy_extension_package",
)

licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_extension(
name = "config",
srcs = ["config.cc"],
hdrs = ["config.h"],
deps = [
"//source/common/config:datasource_lib",
"//source/common/config:utility_lib",
"//source/extensions/certificate_providers:certificate_provider_lib",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
"@envoy_api//envoy/extensions/certificate_providers/default_cert_provider/v3:pkg_cc_proto",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "source/extensions/certificate_providers/default_cert_provider/config.h"

#include "envoy/extensions/certificate_providers/default_cert_provider/v3/config.pb.h"

#include "source/common/config/datasource.h"
#include "source/common/config/utility.h"
#include "source/common/protobuf/message_validator_impl.h"

namespace Envoy {
namespace Extensions {
namespace CertificateProviders {

using DefaultCertProviderConfig =
envoy::extensions::certificate_providers::default_cert_provider::v3::DefaultCertProviderConfig;

DefaultCertificateProvider::DefaultCertificateProvider(
const envoy::config::core::v3::TypedExtensionConfig& config, Api::Api& api) {

DefaultCertProviderConfig message;
Config::Utility::translateOpaqueConfig(config.typed_config(),
ProtobufMessage::getStrictValidationVisitor(), message);

capabilities_.provide_ca_cert = false;
capabilities_.provide_identity_certs = true;
capabilities_.generate_identity_certs = false;

const std::string& cert = Config::DataSource::read(message.certificate(), true, api);
const std::string& key = Config::DataSource::read(message.private_key(), true, api);
Certpair certpair = {cert, key};
tls_certificates_.emplace_back(certpair);
}

} // namespace CertificateProviders
} // namespace Extensions
} // namespace Envoy
Loading

0 comments on commit d4eb3cb

Please sign in to comment.