diff --git a/BUILD b/BUILD
index f733d81368e..94185cbc575 100644
--- a/BUILD
+++ b/BUILD
@@ -1695,6 +1695,7 @@ grpc_cc_library(
grpc_cc_library(
name = "grpc_secure",
srcs = [
+ "src/core/ext/xds/certificate_provider_registry.cc",
"src/core/lib/http/httpcli_security_connector.cc",
"src/core/lib/security/context/security_context.cc",
"src/core/lib/security/credentials/alts/alts_credentials.cc",
diff --git a/BUILD.gn b/BUILD.gn
index 4530191a01c..5f1ffba0879 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -543,6 +543,7 @@ config("grpc_config") {
"src/core/ext/upb-generated/validate/validate.upb.c",
"src/core/ext/upb-generated/validate/validate.upb.h",
"src/core/ext/xds/certificate_provider_factory.h",
+ "src/core/ext/xds/certificate_provider_registry.cc",
"src/core/ext/xds/certificate_provider_registry.h",
"src/core/ext/xds/certificate_provider_store.h",
"src/core/ext/xds/xds_api.cc",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fc87324ec4a..8a46e3cc71a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -785,6 +785,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx byte_buffer_test)
add_dependencies(buildtests_cxx byte_stream_test)
add_dependencies(buildtests_cxx cancel_ares_query_test)
+ add_dependencies(buildtests_cxx certificate_provider_registry_test)
add_dependencies(buildtests_cxx cfstream_test)
add_dependencies(buildtests_cxx channel_arguments_test)
add_dependencies(buildtests_cxx channel_filter_test)
@@ -1596,6 +1597,7 @@ add_library(grpc
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
src/core/ext/upb-generated/validate/validate.upb.c
+ src/core/ext/xds/certificate_provider_registry.cc
src/core/ext/xds/xds_api.cc
src/core/ext/xds/xds_bootstrap.cc
src/core/ext/xds/xds_client.cc
@@ -9637,6 +9639,45 @@ target_link_libraries(cancel_ares_query_test
)
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(certificate_provider_registry_test
+ test/core/client_channel/certificate_provider_registry_test.cc
+ third_party/googletest/googletest/src/gtest-all.cc
+ third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(certificate_provider_registry_test
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+ ${_gRPC_RE2_INCLUDE_DIR}
+ ${_gRPC_SSL_INCLUDE_DIR}
+ ${_gRPC_UPB_GENERATED_DIR}
+ ${_gRPC_UPB_GRPC_GENERATED_DIR}
+ ${_gRPC_UPB_INCLUDE_DIR}
+ ${_gRPC_ZLIB_INCLUDE_DIR}
+ third_party/googletest/googletest/include
+ third_party/googletest/googletest
+ third_party/googletest/googlemock/include
+ third_party/googletest/googlemock
+ ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(certificate_provider_registry_test
+ ${_gRPC_PROTOBUF_LIBRARIES}
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc_test_util
+ grpc
+ gpr
+ address_sorting
+ upb
+ ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+
endif()
if(gRPC_BUILD_TESTS)
diff --git a/Makefile b/Makefile
index 82323ebf0b2..17691de5dc5 100644
--- a/Makefile
+++ b/Makefile
@@ -2002,6 +2002,7 @@ LIBGRPC_SRC = \
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
src/core/ext/upb-generated/validate/validate.upb.c \
+ src/core/ext/xds/certificate_provider_registry.cc \
src/core/ext/xds/xds_api.cc \
src/core/ext/xds/xds_bootstrap.cc \
src/core/ext/xds/xds_client.cc \
@@ -4587,6 +4588,7 @@ src/core/ext/upb-generated/udpa/annotations/migrate.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/udpa/annotations/status.upb.c: $(OPENSSL_DEP)
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c: $(OPENSSL_DEP)
+src/core/ext/xds/certificate_provider_registry.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_api.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_bootstrap.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_client.cc: $(OPENSSL_DEP)
diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml
index ac9ccc4ad9f..be2a660d6d4 100644
--- a/build_autogenerated.yaml
+++ b/build_autogenerated.yaml
@@ -943,6 +943,7 @@ libs:
- src/core/ext/upb-generated/udpa/annotations/versioning.upb.c
- src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
- src/core/ext/upb-generated/validate/validate.upb.c
+ - src/core/ext/xds/certificate_provider_registry.cc
- src/core/ext/xds/xds_api.cc
- src/core/ext/xds/xds_bootstrap.cc
- src/core/ext/xds/xds_client.cc
@@ -5252,6 +5253,19 @@ targets:
- gpr
- address_sorting
- upb
+- name: certificate_provider_registry_test
+ gtest: true
+ build: test
+ language: c++
+ headers: []
+ src:
+ - test/core/client_channel/certificate_provider_registry_test.cc
+ deps:
+ - grpc_test_util
+ - grpc
+ - gpr
+ - address_sorting
+ - upb
- name: cfstream_test
gtest: true
build: test
diff --git a/config.m4 b/config.m4
index 3be0b51ae05..8381cfb0702 100644
--- a/config.m4
+++ b/config.m4
@@ -223,6 +223,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/upb-generated/udpa/annotations/versioning.upb.c \
src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
src/core/ext/upb-generated/validate/validate.upb.c \
+ src/core/ext/xds/certificate_provider_registry.cc \
src/core/ext/xds/xds_api.cc \
src/core/ext/xds/xds_bootstrap.cc \
src/core/ext/xds/xds_client.cc \
diff --git a/config.w32 b/config.w32
index e04d0b378d5..419bc4759d5 100644
--- a/config.w32
+++ b/config.w32
@@ -190,6 +190,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\upb-generated\\udpa\\annotations\\versioning.upb.c " +
"src\\core\\ext\\upb-generated\\udpa\\data\\orca\\v1\\orca_load_report.upb.c " +
"src\\core\\ext\\upb-generated\\validate\\validate.upb.c " +
+ "src\\core\\ext\\xds\\certificate_provider_registry.cc " +
"src\\core\\ext\\xds\\xds_api.cc " +
"src\\core\\ext\\xds\\xds_bootstrap.cc " +
"src\\core\\ext\\xds\\xds_client.cc " +
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 6c7df953c18..6930419233f 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -529,6 +529,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/validate/validate.upb.c',
'src/core/ext/upb-generated/validate/validate.upb.h',
'src/core/ext/xds/certificate_provider_factory.h',
+ 'src/core/ext/xds/certificate_provider_registry.cc',
'src/core/ext/xds/certificate_provider_registry.h',
'src/core/ext/xds/certificate_provider_store.h',
'src/core/ext/xds/xds_api.cc',
diff --git a/grpc.gemspec b/grpc.gemspec
index df0b3269ca1..bae5c641695 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -447,6 +447,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/upb-generated/validate/validate.upb.c )
s.files += %w( src/core/ext/upb-generated/validate/validate.upb.h )
s.files += %w( src/core/ext/xds/certificate_provider_factory.h )
+ s.files += %w( src/core/ext/xds/certificate_provider_registry.cc )
s.files += %w( src/core/ext/xds/certificate_provider_registry.h )
s.files += %w( src/core/ext/xds/certificate_provider_store.h )
s.files += %w( src/core/ext/xds/xds_api.cc )
diff --git a/grpc.gyp b/grpc.gyp
index 080cd6aa05e..454df875cc7 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -628,6 +628,7 @@
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
'src/core/ext/upb-generated/validate/validate.upb.c',
+ 'src/core/ext/xds/certificate_provider_registry.cc',
'src/core/ext/xds/xds_api.cc',
'src/core/ext/xds/xds_bootstrap.cc',
'src/core/ext/xds/xds_client.cc',
diff --git a/package.xml b/package.xml
index d498c782ca1..bfcaa220401 100644
--- a/package.xml
+++ b/package.xml
@@ -427,6 +427,7 @@
+
diff --git a/src/core/ext/xds/certificate_provider_registry.cc b/src/core/ext/xds/certificate_provider_registry.cc
new file mode 100644
index 00000000000..0d7950d5686
--- /dev/null
+++ b/src/core/ext/xds/certificate_provider_registry.cc
@@ -0,0 +1,103 @@
+//
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+#include
+
+#include "absl/container/inlined_vector.h"
+
+#include "src/core/ext/xds/certificate_provider_registry.h"
+
+namespace grpc_core {
+
+namespace {
+
+class RegistryState {
+ public:
+ void RegisterCertificateProviderFactory(
+ std::unique_ptr factory) {
+ gpr_log(GPR_DEBUG, "registering certificate provider factory for \"%s\"",
+ factory->name());
+ for (size_t i = 0; i < factories_.size(); ++i) {
+ GPR_ASSERT(strcmp(factories_[i]->name(), factory->name()) != 0);
+ }
+ factories_.push_back(std::move(factory));
+ }
+
+ CertificateProviderFactory* LookupCertificateProviderFactory(
+ absl::string_view name) const {
+ for (size_t i = 0; i < factories_.size(); ++i) {
+ if (name == factories_[i]->name()) {
+ return factories_[i].get();
+ }
+ }
+ return nullptr;
+ }
+
+ private:
+ // We currently support 3 factories without doing additional
+ // allocation. This number could be raised if there is a case where
+ // more factories are needed and the additional allocations are
+ // hurting performance (which is unlikely, since these allocations
+ // only occur at gRPC initialization time).
+ absl::InlinedVector, 3>
+ factories_;
+};
+
+static RegistryState* g_state = nullptr;
+
+} // namespace
+
+//
+// CertificateProviderRegistry
+//
+
+CertificateProviderFactory*
+CertificateProviderRegistry::LookupCertificateProviderFactory(
+ absl::string_view name) {
+ GPR_ASSERT(g_state != nullptr);
+ return g_state->LookupCertificateProviderFactory(name);
+}
+
+void CertificateProviderRegistry::InitRegistry() {
+ if (g_state == nullptr) g_state = new RegistryState();
+}
+
+void CertificateProviderRegistry::ShutdownRegistry() {
+ delete g_state;
+ g_state = nullptr;
+}
+
+void CertificateProviderRegistry::RegisterCertificateProviderFactory(
+ std::unique_ptr factory) {
+ InitRegistry();
+ g_state->RegisterCertificateProviderFactory(std::move(factory));
+}
+
+} // namespace grpc_core
+
+//
+// Plugin registration
+//
+
+void grpc_certificate_provider_registry_init() {
+ grpc_core::CertificateProviderRegistry::InitRegistry();
+}
+
+void grpc_certificate_provider_registry_shutdown() {
+ grpc_core::CertificateProviderRegistry::ShutdownRegistry();
+}
diff --git a/src/core/ext/xds/certificate_provider_registry.h b/src/core/ext/xds/certificate_provider_registry.h
index 06c5e6665d8..38979765a1c 100644
--- a/src/core/ext/xds/certificate_provider_registry.h
+++ b/src/core/ext/xds/certificate_provider_registry.h
@@ -32,7 +32,7 @@ class CertificateProviderRegistry {
public:
// Returns the factory for the plugin keyed by name.
static CertificateProviderFactory* LookupCertificateProviderFactory(
- const std::string& name);
+ absl::string_view name);
// The following methods are used to create and populate the
// CertificateProviderRegistry. NOT THREAD SAFE -- to be used only during
diff --git a/src/core/plugin_registry/grpc_plugin_registry.cc b/src/core/plugin_registry/grpc_plugin_registry.cc
index 90da88c34ff..134263c19af 100644
--- a/src/core/plugin_registry/grpc_plugin_registry.cc
+++ b/src/core/plugin_registry/grpc_plugin_registry.cc
@@ -62,6 +62,8 @@ void grpc_workaround_cronet_compression_filter_init(void);
void grpc_workaround_cronet_compression_filter_shutdown(void);
#ifndef GRPC_NO_XDS
+void grpc_certificate_provider_registry_init(void);
+void grpc_certificate_provider_registry_shutdown(void);
void grpc_lb_policy_cds_init(void);
void grpc_lb_policy_cds_shutdown(void);
void grpc_lb_policy_eds_init(void);
@@ -116,6 +118,8 @@ void grpc_register_built_in_plugins(void) {
grpc_register_plugin(grpc_workaround_cronet_compression_filter_init,
grpc_workaround_cronet_compression_filter_shutdown);
#ifndef GRPC_NO_XDS
+ grpc_register_plugin(grpc_certificate_provider_registry_init,
+ grpc_certificate_provider_registry_shutdown);
grpc_register_plugin(grpc_lb_policy_cds_init,
grpc_lb_policy_cds_shutdown);
grpc_register_plugin(grpc_lb_policy_eds_init,
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index c5c04bc288e..8ecaf65da44 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -199,6 +199,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/upb-generated/udpa/annotations/versioning.upb.c',
'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
'src/core/ext/upb-generated/validate/validate.upb.c',
+ 'src/core/ext/xds/certificate_provider_registry.cc',
'src/core/ext/xds/xds_api.cc',
'src/core/ext/xds/xds_bootstrap.cc',
'src/core/ext/xds/xds_client.cc',
diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD
index a08275749f1..a81930c06b1 100644
--- a/test/core/client_channel/BUILD
+++ b/test/core/client_channel/BUILD
@@ -18,6 +18,18 @@ grpc_package(name = "test/core/client_channel")
licenses(["notice"])
+grpc_cc_test(
+ name = "certificate_provider_registry_test",
+ srcs = ["certificate_provider_registry_test.cc"],
+ external_deps = ["gtest"],
+ language = "C++",
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//test/core/util:grpc_test_util",
+ ],
+)
+
grpc_cc_test(
name = "retry_throttle_test",
srcs = ["retry_throttle_test.cc"],
diff --git a/test/core/client_channel/certificate_provider_registry_test.cc b/test/core/client_channel/certificate_provider_registry_test.cc
new file mode 100644
index 00000000000..1443856c7a5
--- /dev/null
+++ b/test/core/client_channel/certificate_provider_registry_test.cc
@@ -0,0 +1,90 @@
+//
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+#include
+
+#include
+
+#include "src/core/ext/xds/certificate_provider_registry.h"
+
+#include "test/core/util/test_config.h"
+
+namespace grpc_core {
+namespace testing {
+namespace {
+
+class FakeCertificateProviderFactory1 : public CertificateProviderFactory {
+ public:
+ const char* name() const override { return "fake1"; }
+
+ std::unique_ptr CreateCertificateProviderConfig(
+ const Json& config_json, grpc_error** error) override {
+ return nullptr;
+ }
+
+ RefCountedPtr CreateCertificateProvider(
+ std::unique_ptr config) override {
+ return nullptr;
+ }
+};
+
+class FakeCertificateProviderFactory2 : public CertificateProviderFactory {
+ public:
+ const char* name() const override { return "fake2"; }
+
+ std::unique_ptr CreateCertificateProviderConfig(
+ const Json& config_json, grpc_error** error) override {
+ return nullptr;
+ }
+
+ RefCountedPtr CreateCertificateProvider(
+ std::unique_ptr config) override {
+ return nullptr;
+ }
+};
+
+TEST(CertificateProviderRegistryTest, Basic) {
+ CertificateProviderRegistry::InitRegistry();
+ auto* fake_factory_1 = new FakeCertificateProviderFactory1;
+ auto* fake_factory_2 = new FakeCertificateProviderFactory2;
+ CertificateProviderRegistry::RegisterCertificateProviderFactory(
+ std::unique_ptr(fake_factory_1));
+ CertificateProviderRegistry::RegisterCertificateProviderFactory(
+ std::unique_ptr(fake_factory_2));
+ EXPECT_EQ(
+ CertificateProviderRegistry::LookupCertificateProviderFactory("fake1"),
+ fake_factory_1);
+ EXPECT_EQ(
+ CertificateProviderRegistry::LookupCertificateProviderFactory("fake2"),
+ fake_factory_2);
+ EXPECT_EQ(
+ CertificateProviderRegistry::LookupCertificateProviderFactory("fake3"),
+ nullptr);
+ CertificateProviderRegistry::ShutdownRegistry();
+}
+
+} // namespace
+} // namespace testing
+} // namespace grpc_core
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ grpc::testing::TestEnvironment env(argc, argv);
+ auto result = RUN_ALL_TESTS();
+ return result;
+}
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 72be2bf76eb..342cafcc2f0 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -1394,6 +1394,7 @@ src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \
src/core/ext/upb-generated/validate/validate.upb.c \
src/core/ext/upb-generated/validate/validate.upb.h \
src/core/ext/xds/certificate_provider_factory.h \
+src/core/ext/xds/certificate_provider_registry.cc \
src/core/ext/xds/certificate_provider_registry.h \
src/core/ext/xds/certificate_provider_store.h \
src/core/ext/xds/xds_api.cc \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index b8b02e21401..03d1cced318 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1218,6 +1218,7 @@ src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h \
src/core/ext/upb-generated/validate/validate.upb.c \
src/core/ext/upb-generated/validate/validate.upb.h \
src/core/ext/xds/certificate_provider_factory.h \
+src/core/ext/xds/certificate_provider_registry.cc \
src/core/ext/xds/certificate_provider_registry.h \
src/core/ext/xds/certificate_provider_store.h \
src/core/ext/xds/xds_api.cc \
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 7008a729211..67d7e8aca6c 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -3881,6 +3881,30 @@
],
"uses_polling": false
},
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "gtest": true,
+ "language": "c++",
+ "name": "certificate_provider_registry_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "uses_polling": true
+ },
{
"args": [],
"benchmark": false,