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,