diff --git a/BUILD b/BUILD index a63b888b6d5..03cf5c350a6 100644 --- a/BUILD +++ b/BUILD @@ -252,6 +252,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/tls_certificate_provider.h", "include/grpcpp/security/tls_credentials_options.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", @@ -355,6 +356,7 @@ grpc_cc_library( "src/cpp/common/secure_auth_context.cc", "src/cpp/common/secure_channel_arguments.cc", "src/cpp/common/secure_create_auth_context.cc", + "src/cpp/common/tls_certificate_provider.cc", "src/cpp/common/tls_credentials_options.cc", "src/cpp/common/tls_credentials_options_util.cc", "src/cpp/server/insecure_server_credentials.cc", @@ -1796,6 +1798,7 @@ grpc_cc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.cc", "src/core/lib/security/credentials/ssl/ssl_credentials.cc", "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc", + "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc", "src/core/lib/security/credentials/tls/tls_credentials.cc", "src/core/lib/security/security_connector/alts/alts_security_connector.cc", @@ -1820,7 +1823,6 @@ grpc_cc_library( hdrs = [ "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", "src/core/ext/xds/xds_channel_args.h", - "src/core/lib/security/certificate_provider.h", "src/core/lib/security/context/security_context.h", "src/core/lib/security/credentials/alts/alts_credentials.h", "src/core/lib/security/credentials/composite/composite_credentials.h", @@ -1838,6 +1840,7 @@ grpc_cc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h", + "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h", "src/core/lib/security/credentials/tls/tls_credentials.h", "src/core/lib/security/security_connector/alts/alts_security_connector.h", diff --git a/BUILD.gn b/BUILD.gn index d0a6428ed81..3d3cebf9261 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -976,7 +976,6 @@ config("grpc_config") { "src/core/lib/security/authorization/evaluate_args.h", "src/core/lib/security/authorization/mock_cel/activation.h", "src/core/lib/security/authorization/mock_cel/cel_value.h", - "src/core/lib/security/certificate_provider.h", "src/core/lib/security/context/security_context.cc", "src/core/lib/security/context/security_context.h", "src/core/lib/security/credentials/alts/alts_credentials.cc", @@ -1023,6 +1022,8 @@ config("grpc_config") { "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc", "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h", + "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc", + "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h", "src/core/lib/security/credentials/tls/tls_credentials.cc", @@ -1376,6 +1377,7 @@ config("grpc_config") { "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/tls_certificate_provider.h", "include/grpcpp/security/tls_credentials_options.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", @@ -1430,6 +1432,7 @@ config("grpc_config") { "src/cpp/common/secure_auth_context.h", "src/cpp/common/secure_channel_arguments.cc", "src/cpp/common/secure_create_auth_context.cc", + "src/cpp/common/tls_certificate_provider.cc", "src/cpp/common/tls_credentials_options.cc", "src/cpp/common/tls_credentials_options_util.cc", "src/cpp/common/tls_credentials_options_util.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a684bf94f0..43f1899f93d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -908,6 +908,7 @@ if(gRPC_BUILD_TESTS) endif() add_dependencies(buildtests_cxx string_ref_test) add_dependencies(buildtests_cxx test_cpp_client_credentials_test) + add_dependencies(buildtests_cxx test_cpp_server_credentials_test) add_dependencies(buildtests_cxx test_cpp_util_slice_test) add_dependencies(buildtests_cxx test_cpp_util_time_test) add_dependencies(buildtests_cxx thread_manager_test) @@ -1852,6 +1853,7 @@ add_library(grpc src/core/lib/security/credentials/plugin/plugin_credentials.cc src/core/lib/security/credentials/ssl/ssl_credentials.cc src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc + src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc src/core/lib/security/credentials/tls/tls_credentials.cc src/core/lib/security/credentials/xds/xds_credentials.cc @@ -2671,6 +2673,7 @@ add_library(grpc++ src/cpp/common/secure_auth_context.cc src/cpp/common/secure_channel_arguments.cc src/cpp/common/secure_create_auth_context.cc + src/cpp/common/tls_certificate_provider.cc src/cpp/common/tls_credentials_options.cc src/cpp/common/tls_credentials_options_util.cc src/cpp/common/validate_service_config.cc @@ -2893,6 +2896,7 @@ foreach(_hdr include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/tls_certificate_provider.h include/grpcpp/security/tls_credentials_options.h include/grpcpp/server.h include/grpcpp/server_builder.h @@ -3562,6 +3566,7 @@ foreach(_hdr include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/tls_certificate_provider.h include/grpcpp/security/tls_credentials_options.h include/grpcpp/server.h include/grpcpp/server_builder.h @@ -14572,6 +14577,46 @@ target_link_libraries(test_cpp_client_credentials_test ) +endif() +if(gRPC_BUILD_TESTS) + +add_executable(test_cpp_server_credentials_test + test/cpp/server/credentials_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(test_cpp_server_credentials_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(test_cpp_server_credentials_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc++ + grpc + gpr + address_sorting + upb + ${_gRPC_GFLAGS_LIBRARIES} +) + + endif() if(gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index a117b94125b..48122070494 100644 --- a/Makefile +++ b/Makefile @@ -2265,6 +2265,7 @@ LIBGRPC_SRC = \ src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \ + src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/credentials/tls/tls_credentials.cc \ src/core/lib/security/credentials/xds/xds_credentials.cc \ @@ -2844,6 +2845,7 @@ LIBGRPC++_SRC = \ src/cpp/common/secure_auth_context.cc \ src/cpp/common/secure_channel_arguments.cc \ src/cpp/common/secure_create_auth_context.cc \ + src/cpp/common/tls_certificate_provider.cc \ src/cpp/common/tls_credentials_options.cc \ src/cpp/common/tls_credentials_options_util.cc \ src/cpp/common/validate_service_config.cc \ @@ -3026,6 +3028,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/tls_certificate_provider.h \ include/grpcpp/security/tls_credentials_options.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ @@ -3540,6 +3543,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/tls_certificate_provider.h \ include/grpcpp/security/tls_credentials_options.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ @@ -4801,6 +4805,7 @@ src/core/lib/security/credentials/oauth2/oauth2_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/plugin/plugin_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/ssl/ssl_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc: $(OPENSSL_DEP) +src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/tls/tls_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/xds/xds_credentials.cc: $(OPENSSL_DEP) @@ -4858,6 +4863,7 @@ src/cpp/common/auth_property_iterator.cc: $(OPENSSL_DEP) src/cpp/common/secure_auth_context.cc: $(OPENSSL_DEP) src/cpp/common/secure_channel_arguments.cc: $(OPENSSL_DEP) src/cpp/common/secure_create_auth_context.cc: $(OPENSSL_DEP) +src/cpp/common/tls_certificate_provider.cc: $(OPENSSL_DEP) src/cpp/common/tls_credentials_options.cc: $(OPENSSL_DEP) src/cpp/common/tls_credentials_options_util.cc: $(OPENSSL_DEP) src/cpp/ext/proto_server_reflection.cc: $(OPENSSL_DEP) diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index 6ed671d6316..624bbeeefe2 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -748,7 +748,6 @@ libs: - src/core/lib/security/authorization/evaluate_args.h - src/core/lib/security/authorization/mock_cel/activation.h - src/core/lib/security/authorization/mock_cel/cel_value.h - - src/core/lib/security/certificate_provider.h - src/core/lib/security/context/security_context.h - src/core/lib/security/credentials/alts/alts_credentials.h - src/core/lib/security/credentials/alts/check_gcp_environment.h @@ -768,6 +767,7 @@ libs: - src/core/lib/security/credentials/plugin/plugin_credentials.h - src/core/lib/security/credentials/ssl/ssl_credentials.h - src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h + - src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h - src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h - src/core/lib/security/credentials/tls/tls_credentials.h - src/core/lib/security/credentials/xds/xds_credentials.h @@ -1280,6 +1280,7 @@ libs: - src/core/lib/security/credentials/plugin/plugin_credentials.cc - src/core/lib/security/credentials/ssl/ssl_credentials.cc - src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc + - src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc - src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc - src/core/lib/security/credentials/tls/tls_credentials.cc - src/core/lib/security/credentials/xds/xds_credentials.cc @@ -2249,6 +2250,7 @@ libs: - include/grpcpp/security/auth_metadata_processor.h - include/grpcpp/security/credentials.h - include/grpcpp/security/server_credentials.h + - include/grpcpp/security/tls_certificate_provider.h - include/grpcpp/security/tls_credentials_options.h - include/grpcpp/server.h - include/grpcpp/server_builder.h @@ -2312,6 +2314,7 @@ libs: - src/cpp/common/secure_auth_context.cc - src/cpp/common/secure_channel_arguments.cc - src/cpp/common/secure_create_auth_context.cc + - src/cpp/common/tls_certificate_provider.cc - src/cpp/common/tls_credentials_options.cc - src/cpp/common/tls_credentials_options_util.cc - src/cpp/common/validate_service_config.cc @@ -2611,6 +2614,7 @@ libs: - include/grpcpp/security/auth_metadata_processor.h - include/grpcpp/security/credentials.h - include/grpcpp/security/server_credentials.h + - include/grpcpp/security/tls_certificate_provider.h - include/grpcpp/security/tls_credentials_options.h - include/grpcpp/server.h - include/grpcpp/server_builder.h @@ -7449,6 +7453,20 @@ targets: - gpr - address_sorting - upb +- name: test_cpp_server_credentials_test + gtest: true + build: test + language: c++ + headers: [] + src: + - test/cpp/server/credentials_test.cc + deps: + - grpc_test_util + - grpc++ + - grpc + - gpr + - address_sorting + - upb - name: test_cpp_util_slice_test gtest: true build: test diff --git a/config.m4 b/config.m4 index 26b7b31fd2d..28b6d84670a 100644 --- a/config.m4 +++ b/config.m4 @@ -512,6 +512,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \ + src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/credentials/tls/tls_credentials.cc \ src/core/lib/security/credentials/xds/xds_credentials.cc \ diff --git a/config.w32 b/config.w32 index a01156c0b45..dbf46fe7ec8 100644 --- a/config.w32 +++ b/config.w32 @@ -479,6 +479,7 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\security\\credentials\\plugin\\plugin_credentials.cc " + "src\\core\\lib\\security\\credentials\\ssl\\ssl_credentials.cc " + "src\\core\\lib\\security\\credentials\\tls\\grpc_tls_certificate_distributor.cc " + + "src\\core\\lib\\security\\credentials\\tls\\grpc_tls_certificate_provider.cc " + "src\\core\\lib\\security\\credentials\\tls\\grpc_tls_credentials_options.cc " + "src\\core\\lib\\security\\credentials\\tls\\tls_credentials.cc " + "src\\core\\lib\\security\\credentials\\xds\\xds_credentials.cc " + diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 7f5136f6114..741708fb157 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -150,6 +150,7 @@ Pod::Spec.new do |s| 'include/grpcpp/security/auth_metadata_processor.h', 'include/grpcpp/security/credentials.h', 'include/grpcpp/security/server_credentials.h', + 'include/grpcpp/security/tls_certificate_provider.h', 'include/grpcpp/security/tls_credentials_options.h', 'include/grpcpp/server.h', 'include/grpcpp/server_builder.h', @@ -596,7 +597,6 @@ Pod::Spec.new do |s| 'src/core/lib/security/authorization/evaluate_args.h', 'src/core/lib/security/authorization/mock_cel/activation.h', 'src/core/lib/security/authorization/mock_cel/cel_value.h', - 'src/core/lib/security/certificate_provider.h', 'src/core/lib/security/context/security_context.h', 'src/core/lib/security/credentials/alts/alts_credentials.h', 'src/core/lib/security/credentials/alts/check_gcp_environment.h', @@ -616,6 +616,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/credentials/tls/tls_credentials.h', 'src/core/lib/security/credentials/xds/xds_credentials.h', @@ -723,6 +724,7 @@ Pod::Spec.new do |s| 'src/cpp/common/secure_auth_context.h', 'src/cpp/common/secure_channel_arguments.cc', 'src/cpp/common/secure_create_auth_context.cc', + 'src/cpp/common/tls_certificate_provider.cc', 'src/cpp/common/tls_credentials_options.cc', 'src/cpp/common/tls_credentials_options_util.cc', 'src/cpp/common/tls_credentials_options_util.h', @@ -1195,7 +1197,6 @@ Pod::Spec.new do |s| 'src/core/lib/security/authorization/evaluate_args.h', 'src/core/lib/security/authorization/mock_cel/activation.h', 'src/core/lib/security/authorization/mock_cel/cel_value.h', - 'src/core/lib/security/certificate_provider.h', 'src/core/lib/security/context/security_context.h', 'src/core/lib/security/credentials/alts/alts_credentials.h', 'src/core/lib/security/credentials/alts/check_gcp_environment.h', @@ -1215,6 +1216,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/credentials/tls/tls_credentials.h', 'src/core/lib/security/credentials/xds/xds_credentials.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index fdcf4d06db7..244562bd9be 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -1033,7 +1033,6 @@ Pod::Spec.new do |s| 'src/core/lib/security/authorization/evaluate_args.h', 'src/core/lib/security/authorization/mock_cel/activation.h', 'src/core/lib/security/authorization/mock_cel/cel_value.h', - 'src/core/lib/security/certificate_provider.h', 'src/core/lib/security/context/security_context.cc', 'src/core/lib/security/context/security_context.h', 'src/core/lib/security/credentials/alts/alts_credentials.cc', @@ -1080,6 +1079,8 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc', 'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/credentials/tls/tls_credentials.cc', @@ -1720,7 +1721,6 @@ Pod::Spec.new do |s| 'src/core/lib/security/authorization/evaluate_args.h', 'src/core/lib/security/authorization/mock_cel/activation.h', 'src/core/lib/security/authorization/mock_cel/cel_value.h', - 'src/core/lib/security/certificate_provider.h', 'src/core/lib/security/context/security_context.h', 'src/core/lib/security/credentials/alts/alts_credentials.h', 'src/core/lib/security/credentials/alts/check_gcp_environment.h', @@ -1740,6 +1740,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/credentials/tls/tls_credentials.h', 'src/core/lib/security/credentials/xds/xds_credentials.h', diff --git a/grpc.def b/grpc.def index ed319097ec0..aecf99a9bfe 100644 --- a/grpc.def +++ b/grpc.def @@ -135,18 +135,22 @@ EXPORTS grpc_alts_server_credentials_create grpc_local_credentials_create grpc_local_server_credentials_create + grpc_tls_identity_pairs_create + grpc_tls_identity_pairs_add_pair + grpc_tls_identity_pairs_destroy + grpc_tls_certificate_provider_static_data_create + grpc_tls_certificate_provider_release grpc_tls_credentials_options_create grpc_tls_credentials_options_set_cert_request_type grpc_tls_credentials_options_set_server_verification_option - grpc_tls_credentials_options_set_key_materials_config - grpc_tls_credentials_options_set_credential_reload_config + grpc_tls_credentials_options_set_certificate_provider + grpc_tls_credentials_options_watch_root_certs + grpc_tls_credentials_options_set_root_cert_name + grpc_tls_credentials_options_watch_identity_key_cert_pairs + grpc_tls_credentials_options_set_identity_cert_name grpc_tls_credentials_options_set_server_authorization_check_config - grpc_tls_key_materials_config_create - grpc_tls_key_materials_config_set_key_materials - grpc_tls_key_materials_config_set_version - grpc_tls_key_materials_config_get_version - grpc_tls_credential_reload_config_create grpc_tls_server_authorization_check_config_create + grpc_tls_server_authorization_check_config_release grpc_xds_credentials_create grpc_raw_byte_buffer_create grpc_raw_compressed_byte_buffer_create diff --git a/grpc.gemspec b/grpc.gemspec index 34e0d226957..ec28ecb6edf 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -951,7 +951,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/authorization/evaluate_args.h ) s.files += %w( src/core/lib/security/authorization/mock_cel/activation.h ) s.files += %w( src/core/lib/security/authorization/mock_cel/cel_value.h ) - s.files += %w( src/core/lib/security/certificate_provider.h ) s.files += %w( src/core/lib/security/context/security_context.cc ) s.files += %w( src/core/lib/security/context/security_context.h ) s.files += %w( src/core/lib/security/credentials/alts/alts_credentials.cc ) @@ -998,6 +997,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h ) s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc ) s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h ) + s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc ) + s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h ) s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc ) s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h ) s.files += %w( src/core/lib/security/credentials/tls/tls_credentials.cc ) diff --git a/grpc.gyp b/grpc.gyp index 2e12326f7a9..5661e1cd8c7 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -875,6 +875,7 @@ 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', 'src/core/lib/security/credentials/tls/tls_credentials.cc', 'src/core/lib/security/credentials/xds/xds_credentials.cc', @@ -1403,6 +1404,7 @@ 'src/cpp/common/secure_auth_context.cc', 'src/cpp/common/secure_channel_arguments.cc', 'src/cpp/common/secure_create_auth_context.cc', + 'src/cpp/common/tls_certificate_provider.cc', 'src/cpp/common/tls_credentials_options.cc', 'src/cpp/common/tls_credentials_options_util.cc', 'src/cpp/common/validate_service_config.cc', diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index d8f4d4552a3..12f39ec2c69 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -743,183 +743,156 @@ GRPCAPI grpc_server_credentials* grpc_local_server_credentials_create( * experimental purpose for now and subject to change. */ typedef struct grpc_tls_error_details grpc_tls_error_details; -/** Config for TLS key materials. It is used for - * experimental purpose for now and subject to change. */ -typedef struct grpc_tls_key_materials_config grpc_tls_key_materials_config; - -/** Config for TLS credential reload. It is used for - * experimental purpose for now and subject to change. */ -typedef struct grpc_tls_credential_reload_config - grpc_tls_credential_reload_config; - /** Config for TLS server authorization check. It is used for * experimental purpose for now and subject to change. */ typedef struct grpc_tls_server_authorization_check_config grpc_tls_server_authorization_check_config; -/** TLS credentials options. It is used for - * experimental purpose for now and subject to change. */ +/** + * A struct that can be specified by callers to configure underlying TLS + * behaviors. It is used for experimental purpose for now and subject to change. + */ typedef struct grpc_tls_credentials_options grpc_tls_credentials_options; -/** Create an empty TLS credentials options. It is used for - * experimental purpose for now and subject to change. */ +/** + * A struct provides ways to gain credential data that will be used in the TLS + * handshake. It is used for experimental purpose for now and subject to change. + */ +typedef struct grpc_tls_certificate_provider grpc_tls_certificate_provider; + +/** + * A struct that stores the credential data presented to the peer in handshake + * to show local identity. It is used for experimental purpose for now and + * subject to change. + */ +typedef struct grpc_tls_identity_pairs grpc_tls_identity_pairs; + +/** + * Creates a grpc_tls_identity_pairs that stores a list of identity credential + * data, including identity private key and identity certificate chain. It is + * used for experimental purpose for now and subject to change. + */ +GRPCAPI grpc_tls_identity_pairs* grpc_tls_identity_pairs_create(); + +/** + * Adds a identity private key and a identity certificate chain to + * grpc_tls_identity_pairs. This function will make an internal copy of + * |private_key| and |cert_chain|. It is used for experimental purpose for now + * and subject to change. + */ +GRPCAPI void grpc_tls_identity_pairs_add_pair(grpc_tls_identity_pairs* pairs, + const char* private_key, + const char* cert_chain); + +/** + * Destroys a grpc_tls_identity_pairs object. If this object is passed to a + * provider initiation function, the ownership is transferred so this function + * doesn't need to be called. Otherwise the creator of the + * grpc_tls_identity_pairs object is responsible for its destruction. It is + * used for experimental purpose for now and subject to change. + */ +GRPCAPI void grpc_tls_identity_pairs_destroy(grpc_tls_identity_pairs* pairs); + +/** + * Creates a grpc_tls_certificate_provider that will load credential data from + * static string during initialization. This provider will always return the + * same cert data for all cert names. + * root_certificate and pem_key_cert_pairs can be nullptr, indicating the + * corresponding credential data is not needed. + * This function will make a copy of |root_certificate|. + * The ownership of |pem_key_cert_pairs| is transferred. + * It is used for experimental purpose for now and subject to change. + */ +GRPCAPI grpc_tls_certificate_provider* +grpc_tls_certificate_provider_static_data_create( + const char* root_certificate, grpc_tls_identity_pairs* pem_key_cert_pairs); + +/** + * Releases a grpc_tls_certificate_provider object. The creator of the + * grpc_tls_certificate_provider object is responsible for its release. It is + * used for experimental purpose for now and subject to change. + */ +GRPCAPI void grpc_tls_certificate_provider_release( + grpc_tls_certificate_provider* provider); + +/** + * Creates an grpc_tls_credentials_options. + * It is used for experimental purpose for now and subject to change. + */ GRPCAPI grpc_tls_credentials_options* grpc_tls_credentials_options_create(void); -/** Set grpc_ssl_client_certificate_request_type field in credentials options - with the provided type. options should not be NULL. - It returns 1 on success and 0 on failure. It is used for - experimental purpose for now and subject to change. */ -GRPCAPI int grpc_tls_credentials_options_set_cert_request_type( +/** + * Sets the options of whether to request and verify client certs. This should + * be called only on the server side. It returns 1 on success and 0 on failure. + * It is used for experimental purpose for now and subject to change. + */ +GRPCAPI void grpc_tls_credentials_options_set_cert_request_type( grpc_tls_credentials_options* options, grpc_ssl_client_certificate_request_type type); -/** Set grpc_tls_server_verification_option field in credentials options - with the provided server_verification_option. options should not be NULL. - This should be called only on the client side. - If grpc_tls_server_verification_option is not - GRPC_TLS_SERVER_VERIFICATION, use of a customer server - authorization check (grpc_tls_server_authorization_check_config) - will be mandatory. - It returns 1 on success and 0 on failure. It is used for - experimental purpose for now and subject to change. */ -GRPCAPI int grpc_tls_credentials_options_set_server_verification_option( +/** + * Sets the options of whether to choose certain checks, e.g. certificate check, + * hostname check, etc. This should be called only on the client side. If + * |server_verification_option| is not GRPC_TLS_SERVER_VERIFICATION, use of a + * custom authorization check (grpc_tls_server_authorization_check_config) is + * mandatory. It returns 1 on success and 0 on failure. It is used for + * experimental purpose for now and subject to change. + */ +GRPCAPI void grpc_tls_credentials_options_set_server_verification_option( grpc_tls_credentials_options* options, grpc_tls_server_verification_option server_verification_option); -/** Set grpc_tls_key_materials_config field in credentials options - with the provided config struct whose ownership is transferred. - Both parameters should not be NULL. - It returns 1 on success and 0 on failure. It is used for - experimental purpose for now and subject to change. */ -GRPCAPI int grpc_tls_credentials_options_set_key_materials_config( - grpc_tls_credentials_options* options, - grpc_tls_key_materials_config* config); - -/** Set grpc_tls_credential_reload_config field in credentials options - with the provided config struct whose ownership is transferred. - Both parameters should not be NULL. - It returns 1 on success and 0 on failure. It is used for - experimental purpose for now and subject to change. */ -GRPCAPI int grpc_tls_credentials_options_set_credential_reload_config( - grpc_tls_credentials_options* options, - grpc_tls_credential_reload_config* config); - -/** Set grpc_tls_server_authorization_check_config field in credentials options - with the provided config struct whose ownership is transferred. - Both parameters should not be NULL. - It returns 1 on success and 0 on failure. It is used for - experimental purpose for now and subject to change. */ -GRPCAPI int grpc_tls_credentials_options_set_server_authorization_check_config( +/** + * Sets the credential provider in the options. + * The |options| will implicitly take a new ref to the |provider|. + * It returns 1 on success and 0 on failure. + * It is used for experimental purpose for now and subject to change. + */ +GRPCAPI void grpc_tls_credentials_options_set_certificate_provider( grpc_tls_credentials_options* options, - grpc_tls_server_authorization_check_config* config); + grpc_tls_certificate_provider* provider); -/** --- TLS key materials config. --- - It is used for experimental purpose for now and subject to change. */ +/** + * If set, gRPC stack will keep watching the root certificates with + * name |root_cert_name|. It returns 1 on success and 0 on failure. It is used + * for experimental purpose for now and subject to change. + */ +GRPCAPI void grpc_tls_credentials_options_watch_root_certs( + grpc_tls_credentials_options* options); -/** Create an empty grpc_tls_key_materials_config instance. - * It is used for experimental purpose for now and subject to change. */ -GRPCAPI grpc_tls_key_materials_config* grpc_tls_key_materials_config_create( - void); - -/** Set grpc_tls_key_materials_config instance with provided a TLS certificate. - It's valid for the caller to provide nullptr pem_root_certs, in which case - the gRPC-provided root cert will be used. pem_key_cert_pairs should not be - NULL. - The ownerships of |pem_root_certs| and |pem_key_cert_pairs| remain with the - caller. - It returns 1 on success and 0 on failure. It is used for experimental - purpose for now and subject to change. +/** + * Sets the name of the root certificates being watched. + * If not set, We will use a default empty string as the root certificate name. + * It is used for experimental purpose for now and subject to change. */ -GRPCAPI int grpc_tls_key_materials_config_set_key_materials( - grpc_tls_key_materials_config* config, const char* pem_root_certs, - const grpc_ssl_pem_key_cert_pair** pem_key_cert_pairs, - size_t num_key_cert_pairs); +GRPCAPI void grpc_tls_credentials_options_set_root_cert_name( + grpc_tls_credentials_options* options, const char* root_cert_name); -/** Set grpc_tls_key_materials_config instance with a provided version number, - which is used to keep track of the version of key materials. - It returns 1 on success and 0 on failure. It is used for - experimental purpose for now and subject to change. +/** + * If set, gRPC stack will keep watching the identity key-cert pairs + * with name |identity_cert_name|. It returns 1 on success and 0 on failure. It + * is used for experimental purpose for now and subject to change. */ -GRPCAPI int grpc_tls_key_materials_config_set_version( - grpc_tls_key_materials_config* config, int version); +GRPCAPI void grpc_tls_credentials_options_watch_identity_key_cert_pairs( + grpc_tls_credentials_options* options); -/** Get the version number of a grpc_tls_key_materials_config instance. - It returns the version number on success and -1 on failure. - It is used for experimental purpose for now and subject to change. +/** + * Sets the name of the identity certificates being watched. + * If not set, We will use a default empty string as the identity certificate + * name. It is used for experimental purpose for now and subject to change. */ -GRPCAPI int grpc_tls_key_materials_config_get_version( - grpc_tls_key_materials_config* config); - -/** --- TLS credential reload config. --- - It is used for experimental purpose for now and subject to change.*/ - -typedef struct grpc_tls_credential_reload_arg grpc_tls_credential_reload_arg; - -/** A callback function provided by gRPC to handle the result of credential - reload. It is used when schedule API is implemented asynchronously and - serves to bring the control back to grpc C core. It is used for - experimental purpose for now and subject to change. */ -typedef void (*grpc_tls_on_credential_reload_done_cb)( - grpc_tls_credential_reload_arg* arg); - -/** A struct containing all information necessary to schedule/cancel a - credential reload request. - - cb and cb_user_data represent a gRPC-provided - callback and an argument passed to it. - - key_materials_config is an in/output parameter containing currently - used/newly reloaded credentials. If credential reload does not result in - a new credential, key_materials_config should not be modified. The same - key_materials_config object can be updated if new key materials is - available. - - status and error_details are used to hold information about - errors occurred when a credential reload request is scheduled/cancelled. - - config is a pointer to the unique grpc_tls_credential_reload_config - instance that this argument corresponds to. - - context is a pointer to a wrapped language implementation of this - grpc_tls_credential_reload_arg instance. - - destroy_context is a pointer to a caller-provided method that cleans - up any data associated with the context pointer. - It is used for experimental purposes for now and subject to change. -*/ -struct grpc_tls_credential_reload_arg { - grpc_tls_on_credential_reload_done_cb cb; - void* cb_user_data; - grpc_tls_key_materials_config* key_materials_config; - grpc_ssl_certificate_config_reload_status status; - grpc_tls_error_details* error_details; - grpc_tls_credential_reload_config* config; - void* context; - void (*destroy_context)(void* ctx); -}; +GRPCAPI void grpc_tls_credentials_options_set_identity_cert_name( + grpc_tls_credentials_options* options, const char* identity_cert_name); -/** Create a grpc_tls_credential_reload_config instance. - - config_user_data is config-specific, read-only user data - that works for all channels created with a credential using the config. - - schedule is a pointer to an application-provided callback used to invoke - credential reload API. The implementation of this method has to be - non-blocking, but can be performed synchronously or asynchronously. - 1) If processing occurs synchronously, it populates - arg->key_materials_config, arg->status, and arg->error_details - and returns zero. - 2) If processing occurs asynchronously, it returns a non-zero value. - The application then invokes arg->cb when processing is completed. Note - that arg->cb cannot be invoked before schedule API returns. - - cancel is a pointer to an application-provided callback used to cancel - a credential reload request scheduled via an asynchronous schedule API. - arg is used to pinpoint an exact reloading request to be cancelled. - The operation may not have any effect if the request has already been - processed. - - destruct is a pointer to an application-provided callback used to clean up - any data associated with the config. - It is used for experimental purpose for now and subject to change. -*/ -GRPCAPI grpc_tls_credential_reload_config* -grpc_tls_credential_reload_config_create( - const void* config_user_data, - int (*schedule)(void* config_user_data, - grpc_tls_credential_reload_arg* arg), - void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), - void (*destruct)(void* config_user_data)); +/** + * Sets the configuration for a custom authorization check performed at the end + * of the handshake. The |options| will implicitly take a new ref to the + * |config|. It returns 1 on success and 0 on failure. It is used for + * experimental purpose for now and subject to change. + */ +GRPCAPI void grpc_tls_credentials_options_set_server_authorization_check_config( + grpc_tls_credentials_options* options, + grpc_tls_server_authorization_check_config* config); /** --- TLS server authorization check config. --- * It is used for experimental purpose for now and subject to change. */ @@ -1000,31 +973,28 @@ grpc_tls_server_authorization_check_config_create( void (*destruct)(void* config_user_data)); /** - * This method creates a TLS channel credential object. - * It takes ownership of the options parameter. The security level - * of the resulting connection is GRPC_PRIVACY_AND_INTEGRITY. - * - * - options: grpc TLS credentials options instance. - * - * It returns the created credential object. - * - * It is used for experimental purpose for now and subject - * to change. + * Releases a grpc_tls_server_authorization_check_config object. The creator of + * the grpc_tls_server_authorization_check_config object is responsible for its + * release. It is used for experimental purpose for now and subject to change. */ +GRPCAPI void grpc_tls_server_authorization_check_config_release( + grpc_tls_server_authorization_check_config* config); +/** + * Creates a TLS channel credential object based on the + * grpc_tls_credentials_options specified by callers. The + * grpc_channel_credentials will take the ownership of the |options|. The + * security level of the resulting connection is GRPC_PRIVACY_AND_INTEGRITY. It + * is used for experimental purpose for now and subject to change. + */ grpc_channel_credentials* grpc_tls_credentials_create( grpc_tls_credentials_options* options); /** - * This method creates a TLS server credential object. - * It takes ownership of the options parameter. - * - * - options: grpc TLS credentials options instance. - * - * It returns the created credential object. - * - * It is used for experimental purpose for now and subject - * to change. + * Creates a TLS server credential object based on the + * grpc_tls_credentials_options specified by callers. The + * grpc_server_credentials will take the ownership of the |options|. It + * is used for experimental purpose for now and subject to change. */ grpc_server_credentials* grpc_tls_server_credentials_create( grpc_tls_credentials_options* options); diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h index 1cbf6ebdc16..2c915c8dc7c 100644 --- a/include/grpcpp/security/credentials.h +++ b/include/grpcpp/security/credentials.h @@ -329,7 +329,7 @@ std::shared_ptr LocalCredentials( /// Builds TLS Credentials given TLS options. std::shared_ptr TlsCredentials( - const TlsCredentialsOptions& options); + const TlsChannelCredentialsOptions& options); } // namespace experimental } // namespace grpc diff --git a/include/grpcpp/security/server_credentials.h b/include/grpcpp/security/server_credentials.h index a86d0e35f07..b5f0b262963 100644 --- a/include/grpcpp/security/server_credentials.h +++ b/include/grpcpp/security/server_credentials.h @@ -105,7 +105,7 @@ std::shared_ptr LocalServerCredentials( /// Builds TLS ServerCredentials given TLS options. std::shared_ptr TlsServerCredentials( - const experimental::TlsCredentialsOptions& options); + const experimental::TlsServerCredentialsOptions& options); } // namespace experimental } // namespace grpc diff --git a/include/grpcpp/security/tls_certificate_provider.h b/include/grpcpp/security/tls_certificate_provider.h new file mode 100644 index 00000000000..797687c66c2 --- /dev/null +++ b/include/grpcpp/security/tls_certificate_provider.h @@ -0,0 +1,80 @@ +// +// 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. +// + +#ifndef GRPCPP_SECURITY_TLS_CERTIFICATE_PROVIDER_H +#define GRPCPP_SECURITY_TLS_CERTIFICATE_PROVIDER_H + +#include +#include +#include +#include +#include + +#include +#include + +// TODO(yihuazhang): remove the forward declaration here and include +// directly once the insecure builds are cleaned up. +typedef struct grpc_tls_certificate_provider grpc_tls_certificate_provider; + +namespace grpc { +namespace experimental { + +// Interface for a class that handles the process to fetch credential data. +// Implementations should be a wrapper class of an internal provider +// implementation. +class CertificateProviderInterface { + public: + virtual ~CertificateProviderInterface() = default; + virtual grpc_tls_certificate_provider* c_provider() = 0; +}; + +// A struct that stores the credential data presented to the peer in handshake +// to show local identity. The private_key and certificate_chain should always +// match. +struct IdentityKeyCertPair { + std::string private_key; + std::string certificate_chain; +}; + +// A basic CertificateProviderInterface implementation that will load credential +// data from static string during initialization. This provider will always +// return the same cert data for all cert names, and reloading is not supported. +class StaticDataCertificateProvider : public CertificateProviderInterface { + public: + StaticDataCertificateProvider( + const std::string& root_certificate, + const std::vector& identity_key_cert_pairs); + + StaticDataCertificateProvider(const std::string& root_certificate) + : StaticDataCertificateProvider(root_certificate, {}) {} + + StaticDataCertificateProvider( + const std::vector& identity_key_cert_pairs) + : StaticDataCertificateProvider("", identity_key_cert_pairs) {} + + ~StaticDataCertificateProvider(); + + grpc_tls_certificate_provider* c_provider() override { return c_provider_; } + + private: + grpc_tls_certificate_provider* c_provider_ = nullptr; +}; + +} // namespace experimental +} // namespace grpc + +#endif // GRPCPP_SECURITY_TLS_CERTIFICATE_PROVIDER_H diff --git a/include/grpcpp/security/tls_credentials_options.h b/include/grpcpp/security/tls_credentials_options.h index 9613e2f69ba..aaa1a90ca43 100644 --- a/include/grpcpp/security/tls_credentials_options.h +++ b/include/grpcpp/security/tls_credentials_options.h @@ -22,151 +22,24 @@ #include #include #include +#include #include #include #include -typedef struct grpc_tls_credential_reload_arg grpc_tls_credential_reload_arg; -typedef struct grpc_tls_credential_reload_config - grpc_tls_credential_reload_config; +// TODO(yihuazhang): remove the forward declaration here and include +// directly once the insecure builds are cleaned up. typedef struct grpc_tls_server_authorization_check_arg grpc_tls_server_authorization_check_arg; typedef struct grpc_tls_server_authorization_check_config grpc_tls_server_authorization_check_config; typedef struct grpc_tls_credentials_options grpc_tls_credentials_options; +typedef struct grpc_tls_certificate_provider grpc_tls_certificate_provider; namespace grpc { namespace experimental { -/** TLS key materials config, wrapper for grpc_tls_key_materials_config. It is - * used for experimental purposes for now and subject to change. **/ -class TlsKeyMaterialsConfig { - public: - struct PemKeyCertPair { - std::string private_key; - std::string cert_chain; - }; - - /** Getters for member fields. **/ - const std::string pem_root_certs() const { return pem_root_certs_; } - const std::vector& pem_key_cert_pair_list() const { - return pem_key_cert_pair_list_; - } - int version() const { return version_; } - - /** Setter for key materials that will be called by the user. Ownership of the - * arguments will not be transferred. **/ - void set_pem_root_certs(const std::string& pem_root_certs); - void add_pem_key_cert_pair(const PemKeyCertPair& pem_key_cert_pair); - void set_key_materials( - const std::string& pem_root_certs, - const std::vector& pem_key_cert_pair_list); - void set_version(int version) { version_ = version; }; - - private: - int version_ = 0; - std::vector pem_key_cert_pair_list_; - std::string pem_root_certs_; -}; - -/** TLS credential reload arguments, wraps grpc_tls_credential_reload_arg. It is - * used for experimental purposes for now and it is subject to change. - * - * The credential reload arg contains all the info necessary to schedule/cancel - * a credential reload request. The callback function must be called after - * finishing the schedule operation. See the description of the - * grpc_tls_credential_reload_arg struct in grpc_security.h for more details. - * **/ -class TlsCredentialReloadArg { - public: - /** TlsCredentialReloadArg does not take ownership of the C arg that is passed - * to the constructor. One must remember to free any memory allocated to the - * C arg after using the setter functions below. **/ - TlsCredentialReloadArg(grpc_tls_credential_reload_arg* arg); - ~TlsCredentialReloadArg(); - - /** Getters for member fields. **/ - void* cb_user_data() const; - bool is_pem_key_cert_pair_list_empty() const; - grpc_ssl_certificate_config_reload_status status() const; - std::string error_details() const; - - /** Setters for member fields. Ownership of the arguments will not be - * transferred. **/ - void set_cb_user_data(void* cb_user_data); - void set_pem_root_certs(const std::string& pem_root_certs); - void add_pem_key_cert_pair( - const TlsKeyMaterialsConfig::PemKeyCertPair& pem_key_cert_pair); - void set_key_materials(const std::string& pem_root_certs, - std::vector - pem_key_cert_pair_list); - void set_key_materials_config( - const std::shared_ptr& key_materials_config); - void set_status(grpc_ssl_certificate_config_reload_status status); - void set_error_details(const std::string& error_details); - - /** Calls the C arg's callback function. **/ - void OnCredentialReloadDoneCallback(); - - private: - grpc_tls_credential_reload_arg* c_arg_; -}; - -/** An interface that the application derives and uses to instantiate a - * TlsCredentialReloadConfig instance. Refer to the definition of the - * grpc_tls_credential_reload_config in grpc_tls_credentials_options.h for more - * details on the expectations of the member functions of the interface. **/ -struct TlsCredentialReloadInterface { - virtual ~TlsCredentialReloadInterface() = default; - /** A callback that invokes the credential reload. **/ - virtual int Schedule(TlsCredentialReloadArg* arg) = 0; - /** A callback that cancels a credential reload request. **/ - virtual void Cancel(TlsCredentialReloadArg* /* arg */) {} -}; - -/** TLS credential reloag config, wraps grpc_tls_credential_reload_config. It is - * used for experimental purposes for now and it is subject to change. **/ -class TlsCredentialReloadConfig { - public: - TlsCredentialReloadConfig(std::shared_ptr - credential_reload_interface); - ~TlsCredentialReloadConfig(); - - int Schedule(TlsCredentialReloadArg* arg) const { - if (credential_reload_interface_ == nullptr) { - gpr_log(GPR_ERROR, "credential reload interface is nullptr"); - if (arg != nullptr) { - arg->set_status(GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL); - arg->set_error_details( - "the interface of the credential reload config is nullptr"); - } - return 1; - } - return credential_reload_interface_->Schedule(arg); - } - - void Cancel(TlsCredentialReloadArg* arg) const { - if (credential_reload_interface_ == nullptr) { - gpr_log(GPR_ERROR, "credential reload interface is nullptr"); - if (arg != nullptr) { - arg->set_status(GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL); - arg->set_error_details( - "the interface of the credential reload config is nullptr"); - } - return; - } - credential_reload_interface_->Cancel(arg); - } - - /** Returns a C struct for the credential reload config. **/ - grpc_tls_credential_reload_config* c_config() const { return c_config_; } - - private: - grpc_tls_credential_reload_config* c_config_; - std::shared_ptr credential_reload_interface_; -}; - /** TLS server authorization check arguments, wraps * grpc_tls_server_authorization_check_arg. It is used for experimental * purposes for now and it is subject to change. @@ -272,71 +145,85 @@ class TlsServerAuthorizationCheckConfig { server_authorization_check_interface_; }; -/** TLS credentials options, wrapper for grpc_tls_credentials_options. It is - * used for experimental purposes for now and it is subject to change. See the - * description of the grpc_tls_credentials_options struct in grpc_security.h for - * more details. **/ +// Base class of configurable options specified by users to configure their +// certain security features supported in TLS. It is used for experimental +// purposes for now and it is subject to change. class TlsCredentialsOptions { public: - // Constructor for client. + // Constructor for base class TlsCredentialsOptions. + // + // @param certificate_provider the provider which fetches TLS credentials that + // will be used in the TLS handshake explicit TlsCredentialsOptions( - grpc_tls_server_verification_option server_verification_option, - std::shared_ptr key_materials_config, - std::shared_ptr credential_reload_config, - std::shared_ptr - server_authorization_check_config); + std::shared_ptr certificate_provider); + // ---- Setters for member fields ---- + // Watches the updates of root certificates with name |root_cert_name|. + // If used in TLS credentials, it should always be set unless the root + // certificates are not needed(e.g. in the one-side TLS scenario, the server + // is not required to verify the client). + void watch_root_certs(); + // Sets the name of root certificates being watched, if |watch_root_certs| is + // called. If not set, an empty string will be used as the name. + // + // @param root_cert_name the name of root certs being set. + void set_root_cert_name(const std::string& root_cert_name); + // Watches the updates of identity key-cert pairs with name + // |identity_cert_name|. If used in TLS credentials, it should always be set + // unless the identity certificates are not needed(e.g. in the one-side TLS + // scenario, the client is not required to provide certs). + void watch_identity_key_cert_pairs(); + // Sets the name of identity key-cert pairs being watched, if + // |watch_identity_key_cert_pairs| is called. If not set, an empty string will + // be used as the name. + // + // @param identity_cert_name the name of identity key-cert pairs being set. + void set_identity_cert_name(const std::string& identity_cert_name); + + // ----- Getters for member fields ---- + // Get the internal c options. This function shall be used only internally. + grpc_tls_credentials_options* c_credentials_options() const { + return c_credentials_options_; + } - // Constructor for server. - explicit TlsCredentialsOptions( - grpc_ssl_client_certificate_request_type cert_request_type, - std::shared_ptr key_materials_config, - std::shared_ptr credential_reload_config); + private: + std::shared_ptr certificate_provider_; + grpc_tls_credentials_options* c_credentials_options_ = nullptr; +}; - // This constructor will be deprecated. - TlsCredentialsOptions( - grpc_ssl_client_certificate_request_type cert_request_type, - grpc_tls_server_verification_option server_verification_option, - std::shared_ptr key_materials_config, - std::shared_ptr credential_reload_config, +// Contains configurable options on the client side. +// It is used for experimental purposes for now and it is subject to change. +class TlsChannelCredentialsOptions final : public TlsCredentialsOptions { + public: + explicit TlsChannelCredentialsOptions( + std::shared_ptr certificate_provider) + : TlsCredentialsOptions(std::move(certificate_provider)) {} + + // Sets the option to verify the server. + // The default is GRPC_TLS_SERVER_VERIFICATION. + void set_server_verification_option( + grpc_tls_server_verification_option server_verification_option); + // Sets the custom authorization config. + void set_server_authorization_check_config( std::shared_ptr - server_authorization_check_config); - ~TlsCredentialsOptions(); + authorization_check_config); - /** Getters for member fields. **/ - grpc_ssl_client_certificate_request_type cert_request_type() const { - return cert_request_type_; - } - grpc_tls_server_verification_option server_verification_option() const { - return server_verification_option_; - } - std::shared_ptr key_materials_config() const { - return key_materials_config_; - } - std::shared_ptr credential_reload_config() const { - return credential_reload_config_; - } - std::shared_ptr - server_authorization_check_config() const { - return server_authorization_check_config_; - } - grpc_tls_credentials_options* c_credentials_options() const { - return c_credentials_options_; - } + private: +}; + +// Contains configurable options on the server side. +// It is used for experimental purposes for now and it is subject to change. +class TlsServerCredentialsOptions final : public TlsCredentialsOptions { + public: + explicit TlsServerCredentialsOptions( + std::shared_ptr certificate_provider) + : TlsCredentialsOptions(std::move(certificate_provider)) {} + + // Sets option to request the certificates from the client. + // The default is GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE. + void set_cert_request_type( + grpc_ssl_client_certificate_request_type cert_request_type); private: - /** The cert_request_type_ flag is only relevant when the - * TlsCredentialsOptions are used to instantiate server credentials; the flag - * goes unused when creating channel credentials, and the user can set it to - * GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE. **/ - grpc_ssl_client_certificate_request_type cert_request_type_; - /** The server_verification_option_ flag is only relevant when the - * TlsCredentialsOptions are used to instantiate client credentials; **/ - grpc_tls_server_verification_option server_verification_option_; - std::shared_ptr key_materials_config_; - std::shared_ptr credential_reload_config_; - std::shared_ptr - server_authorization_check_config_; - grpc_tls_credentials_options* c_credentials_options_; }; } // namespace experimental diff --git a/package.xml b/package.xml index 8e6199006fb..1b5500c6bef 100644 --- a/package.xml +++ b/package.xml @@ -931,7 +931,6 @@ - @@ -978,6 +977,8 @@ + + diff --git a/src/core/ext/xds/certificate_provider_factory.h b/src/core/ext/xds/certificate_provider_factory.h index 1a4345644d4..068bddd4ad6 100644 --- a/src/core/ext/xds/certificate_provider_factory.h +++ b/src/core/ext/xds/certificate_provider_factory.h @@ -23,7 +23,7 @@ #include "src/core/lib/iomgr/error.h" #include "src/core/lib/json/json.h" -#include "src/core/lib/security/certificate_provider.h" +#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" namespace grpc_core { diff --git a/src/core/ext/xds/certificate_provider_store.h b/src/core/ext/xds/certificate_provider_store.h index cc5391f67c7..ef22d365c61 100644 --- a/src/core/ext/xds/certificate_provider_store.h +++ b/src/core/ext/xds/certificate_provider_store.h @@ -28,7 +28,7 @@ #include "src/core/ext/xds/certificate_provider_factory.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/sync.h" -#include "src/core/lib/security/certificate_provider.h" +#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" namespace grpc_core { diff --git a/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc b/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc index 2189865bba2..fb6d2e967ea 100644 --- a/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc +++ b/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc @@ -26,7 +26,7 @@ void grpc_tls_certificate_distributor::SetKeyMaterials( const std::string& cert_name, absl::optional pem_root_certs, - absl::optional pem_key_cert_pairs) { + absl::optional pem_key_cert_pairs) { GPR_ASSERT(pem_root_certs.has_value() || pem_key_cert_pairs.has_value()); grpc_core::MutexLock lock(&mu_); auto& cert_info = certificate_info_map_[cert_name]; @@ -38,7 +38,8 @@ void grpc_tls_certificate_distributor::SetKeyMaterials( const auto watcher_it = watchers_.find(watcher_ptr); GPR_ASSERT(watcher_it != watchers_.end()); GPR_ASSERT(watcher_it->second.root_cert_name.has_value()); - absl::optional pem_key_cert_pairs_to_report; + absl::optional + pem_key_cert_pairs_to_report; if (pem_key_cert_pairs.has_value() && watcher_it->second.identity_cert_name == cert_name) { pem_key_cert_pairs_to_report = pem_key_cert_pairs; @@ -188,7 +189,7 @@ void grpc_tls_certificate_distributor::WatchTlsCertificates( watchers_[watcher_ptr] = {std::move(watcher), root_cert_name, identity_cert_name}; absl::optional updated_root_certs; - absl::optional updated_identity_pairs; + absl::optional updated_identity_pairs; grpc_error* root_error = GRPC_ERROR_NONE; grpc_error* identity_error = GRPC_ERROR_NONE; if (root_cert_name.has_value()) { @@ -319,3 +320,28 @@ void grpc_tls_certificate_distributor::CancelTlsCertificatesWatch( } } }; + +/** -- Wrapper APIs declared in grpc_security.h -- **/ + +grpc_tls_identity_pairs* grpc_tls_identity_pairs_create() { + return new grpc_tls_identity_pairs(); +} + +void grpc_tls_identity_pairs_add_pair(grpc_tls_identity_pairs* pairs, + const char* private_key, + const char* cert_chain) { + GPR_ASSERT(pairs != nullptr); + GPR_ASSERT(private_key != nullptr); + GPR_ASSERT(cert_chain != nullptr); + grpc_ssl_pem_key_cert_pair* ssl_pair = + static_cast( + gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair))); + ssl_pair->private_key = gpr_strdup(private_key); + ssl_pair->cert_chain = gpr_strdup(cert_chain); + pairs->pem_key_cert_pairs.emplace_back(ssl_pair); +} + +void grpc_tls_identity_pairs_destroy(grpc_tls_identity_pairs* pairs) { + GPR_ASSERT(pairs != nullptr); + delete pairs; +} diff --git a/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h b/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h index ee89fb4e85f..35451e77d5c 100644 --- a/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h +++ b/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h @@ -28,12 +28,14 @@ #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/security/security_connector/ssl_utils.h" +struct grpc_tls_identity_pairs { + grpc_core::PemKeyCertPairList pem_key_cert_pairs; +}; + // TLS certificate distributor. struct grpc_tls_certificate_distributor : public grpc_core::RefCounted { public: - typedef absl::InlinedVector PemKeyCertPairList; - // Interface for watching TLS certificates update. class TlsCertificatesWatcherInterface { public: @@ -50,7 +52,7 @@ struct grpc_tls_certificate_distributor // pairs. virtual void OnCertificatesChanged( absl::optional root_certs, - absl::optional key_cert_pairs) = 0; + absl::optional key_cert_pairs) = 0; // Handles an error that occurs while attempting to fetch certificate data. // Note that if a watcher sees an error, it simply means the Provider is @@ -80,9 +82,9 @@ struct grpc_tls_certificate_distributor // @param cert_name The name of the certificates being updated. // @param pem_root_certs The content of root certificates. // @param pem_key_cert_pairs The content of identity key-cert pairs. - void SetKeyMaterials(const std::string& cert_name, - absl::optional pem_root_certs, - absl::optional pem_key_cert_pairs); + void SetKeyMaterials( + const std::string& cert_name, absl::optional pem_root_certs, + absl::optional pem_key_cert_pairs); bool HasRootCerts(const std::string& root_cert_name); @@ -170,7 +172,7 @@ struct grpc_tls_certificate_distributor // The contents of the root certificates. std::string pem_root_certs; // The contents of the identity key-certificate pairs. - PemKeyCertPairList pem_key_cert_pairs; + grpc_core::PemKeyCertPairList pem_key_cert_pairs; // The root cert reloading error propagated by the caller. grpc_error* root_cert_error = GRPC_ERROR_NONE; // The identity cert reloading error propagated by the caller. diff --git a/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc b/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc new file mode 100644 index 00000000000..80ea4eaee3b --- /dev/null +++ b/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc @@ -0,0 +1,78 @@ +// +// 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 "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" + +#include +#include +#include + +#include "src/core/lib/surface/api_trace.h" + +namespace grpc_core { + +StaticDataCertificateProvider::StaticDataCertificateProvider( + std::string root_certificate, + grpc_core::PemKeyCertPairList pem_key_cert_pairs) + : distributor_(MakeRefCounted()), + root_certificate_(std::move(root_certificate)), + pem_key_cert_pairs_(std::move(pem_key_cert_pairs)) { + distributor_->SetWatchStatusCallback([this](std::string cert_name, + bool root_being_watched, + bool identity_being_watched) { + if (!root_being_watched && !identity_being_watched) return; + absl::optional root_certificate; + absl::optional pem_key_cert_pairs; + if (root_being_watched) { + root_certificate = root_certificate_; + } + if (identity_being_watched) { + pem_key_cert_pairs = pem_key_cert_pairs_; + } + distributor_->SetKeyMaterials(cert_name, std::move(root_certificate), + std::move(pem_key_cert_pairs)); + }); +} + +} // namespace grpc_core + +/** -- Wrapper APIs declared in grpc_security.h -- **/ + +grpc_tls_certificate_provider* grpc_tls_certificate_provider_static_data_create( + const char* root_certificate, grpc_tls_identity_pairs* pem_key_cert_pairs) { + GPR_ASSERT(root_certificate != nullptr || pem_key_cert_pairs != nullptr); + grpc_core::PemKeyCertPairList identity_pairs_core; + if (pem_key_cert_pairs != nullptr) { + identity_pairs_core = std::move(pem_key_cert_pairs->pem_key_cert_pairs); + delete pem_key_cert_pairs; + } + std::string root_cert_core; + if (root_certificate != nullptr) { + root_cert_core = root_certificate; + } + return new grpc_core::StaticDataCertificateProvider( + std::move(root_cert_core), std::move(identity_pairs_core)); +} + +void grpc_tls_certificate_provider_release( + grpc_tls_certificate_provider* provider) { + GRPC_API_TRACE("grpc_tls_certificate_provider_release(provider=%p)", 1, + (provider)); + grpc_core::ExecCtx exec_ctx; + if (provider != nullptr) provider->Unref(); +} diff --git a/src/core/lib/security/certificate_provider.h b/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h similarity index 62% rename from src/core/lib/security/certificate_provider.h rename to src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h index 03f77c96fef..dae6fd21586 100644 --- a/src/core/lib/security/certificate_provider.h +++ b/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h @@ -1,5 +1,4 @@ // -// // Copyright 2020 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,17 +13,22 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// -#ifndef GRPC_CORE_LIB_SECURITY_CERTIFICATE_PROVIDER_H -#define GRPC_CORE_LIB_SECURITY_CERTIFICATE_PROVIDER_H +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_PROVIDER_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_PROVIDER_H #include +#include +#include + +#include "absl/container/inlined_vector.h" + #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h" +#include "src/core/lib/security/security_connector/ssl_utils.h" // Interface for a grpc_tls_certificate_provider that handles the process to // fetch credentials and validation contexts. Implementations are free to rely @@ -44,4 +48,27 @@ struct grpc_tls_certificate_provider distributor() const = 0; }; -#endif // GRPC_CORE_LIB_SECURITY_CERTIFICATE_PROVIDER_H +namespace grpc_core { + +// A basic provider class that will get credentials from string during +// initialization. +class StaticDataCertificateProvider final + : public grpc_tls_certificate_provider { + public: + StaticDataCertificateProvider( + std::string root_certificate, + grpc_core::PemKeyCertPairList pem_key_cert_pairs); + + RefCountedPtr distributor() const override { + return distributor_; + } + + private: + RefCountedPtr distributor_; + std::string root_certificate_; + grpc_core::PemKeyCertPairList pem_key_cert_pairs_; +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_PROVIDER_H diff --git a/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc index 906a2f02099..12e462bb9dd 100644 --- a/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +++ b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc @@ -27,49 +27,7 @@ #include #include -/** -- gRPC TLS key materials config API implementation. -- **/ -void grpc_tls_key_materials_config::set_key_materials( - const char* pem_root_certs, - const grpc_ssl_pem_key_cert_pair** pem_key_cert_pairs, - size_t num_key_cert_pairs) { - this->set_pem_root_certs(pem_root_certs); - grpc_tls_key_materials_config::PemKeyCertPairList cert_pair_list; - for (size_t i = 0; i < num_key_cert_pairs; i++) { - auto current_pair = static_cast( - gpr_zalloc(sizeof(grpc_ssl_pem_key_cert_pair))); - current_pair->cert_chain = gpr_strdup(pem_key_cert_pairs[i]->cert_chain); - current_pair->private_key = gpr_strdup(pem_key_cert_pairs[i]->private_key); - cert_pair_list.emplace_back(grpc_core::PemKeyCertPair(current_pair)); - } - pem_key_cert_pair_list_ = std::move(cert_pair_list); -} - -void grpc_tls_key_materials_config::set_key_materials( - const char* pem_root_certs, - const PemKeyCertPairList& pem_key_cert_pair_list) { - this->set_pem_root_certs(pem_root_certs); - grpc_tls_key_materials_config::PemKeyCertPairList dup_list( - pem_key_cert_pair_list); - pem_key_cert_pair_list_ = std::move(dup_list); -} - -/** -- gRPC TLS credential reload config API implementation. -- **/ -grpc_tls_credential_reload_config::grpc_tls_credential_reload_config( - const void* config_user_data, - int (*schedule)(void* config_user_data, - grpc_tls_credential_reload_arg* arg), - void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), - void (*destruct)(void* config_user_data)) - : config_user_data_(const_cast(config_user_data)), - schedule_(schedule), - cancel_(cancel), - destruct_(destruct) {} - -grpc_tls_credential_reload_config::~grpc_tls_credential_reload_config() { - if (destruct_ != nullptr) { - destruct_((void*)config_user_data_); - } -} +#include "src/core/lib/surface/api_trace.h" /** -- gRPC TLS server authorization check API implementation. -- **/ grpc_tls_server_authorization_check_config:: @@ -92,138 +50,99 @@ grpc_tls_server_authorization_check_config:: } } +int grpc_tls_server_authorization_check_config::Schedule( + grpc_tls_server_authorization_check_arg* arg) const { + if (schedule_ == nullptr) { + gpr_log(GPR_ERROR, "schedule API is nullptr"); + if (arg != nullptr) { + arg->status = GRPC_STATUS_NOT_FOUND; + arg->error_details->set_error_details( + "schedule API in server authorization check config is nullptr"); + } + return 1; + } + if (arg != nullptr && context_ != nullptr) { + arg->config = const_cast(this); + } + return schedule_(config_user_data_, arg); +} + +void grpc_tls_server_authorization_check_config::Cancel( + grpc_tls_server_authorization_check_arg* arg) const { + if (cancel_ == nullptr) { + gpr_log(GPR_ERROR, "cancel API is nullptr."); + if (arg != nullptr) { + arg->status = GRPC_STATUS_NOT_FOUND; + arg->error_details->set_error_details( + "schedule API in server authorization check config is nullptr"); + } + return; + } + if (arg != nullptr) { + arg->config = const_cast(this); + } + cancel_(config_user_data_, arg); +} + /** -- Wrapper APIs declared in grpc_security.h -- **/ + grpc_tls_credentials_options* grpc_tls_credentials_options_create() { return new grpc_tls_credentials_options(); } -int grpc_tls_credentials_options_set_cert_request_type( +void grpc_tls_credentials_options_set_cert_request_type( grpc_tls_credentials_options* options, grpc_ssl_client_certificate_request_type type) { - if (options == nullptr) { - gpr_log(GPR_ERROR, - "Invalid nullptr arguments to " - "grpc_tls_credentials_options_set_cert_request_type()"); - return 0; - } + GPR_ASSERT(options != nullptr); options->set_cert_request_type(type); - return 1; } -int grpc_tls_credentials_options_set_server_verification_option( +void grpc_tls_credentials_options_set_server_verification_option( grpc_tls_credentials_options* options, grpc_tls_server_verification_option server_verification_option) { - if (options == nullptr) { - gpr_log(GPR_ERROR, - "Invalid nullptr arguments to " - "grpc_tls_credentials_options_set_server_verification_option()"); - return 0; - } - if (server_verification_option != GRPC_TLS_SERVER_VERIFICATION && - options->server_authorization_check_config() == nullptr) { - gpr_log(GPR_ERROR, - "server_authorization_check_config needs to be specified when" - "server_verification_option is not GRPC_TLS_SERVER_VERIFICATION"); - return 0; - } + GPR_ASSERT(options != nullptr); options->set_server_verification_option(server_verification_option); - return 1; -} - -int grpc_tls_credentials_options_set_key_materials_config( - grpc_tls_credentials_options* options, - grpc_tls_key_materials_config* config) { - if (options == nullptr || config == nullptr) { - gpr_log(GPR_ERROR, - "Invalid nullptr arguments to " - "grpc_tls_credentials_options_set_key_materials_config()"); - return 0; - } - options->set_key_materials_config(config->Ref()); - return 1; } -int grpc_tls_credentials_options_set_credential_reload_config( +void grpc_tls_credentials_options_set_certificate_provider( grpc_tls_credentials_options* options, - grpc_tls_credential_reload_config* config) { - if (options == nullptr || config == nullptr) { - gpr_log(GPR_ERROR, - "Invalid nullptr arguments to " - "grpc_tls_credentials_options_set_credential_reload_config()"); - return 0; - } - options->set_credential_reload_config(config->Ref()); - return 1; + grpc_tls_certificate_provider* provider) { + GPR_ASSERT(options != nullptr); + GPR_ASSERT(provider != nullptr); + options->set_certificate_provider( + provider->Ref(DEBUG_LOCATION, "set_certificate_provider")); } -int grpc_tls_credentials_options_set_server_authorization_check_config( - grpc_tls_credentials_options* options, - grpc_tls_server_authorization_check_config* config) { - if (options == nullptr || config == nullptr) { - gpr_log( - GPR_ERROR, - "Invalid nullptr arguments to " - "grpc_tls_credentials_options_set_server_authorization_check_config()"); - return 0; - } - options->set_server_authorization_check_config(config->Ref()); - return 1; +void grpc_tls_credentials_options_watch_root_certs( + grpc_tls_credentials_options* options) { + GPR_ASSERT(options != nullptr); + options->set_watch_root_cert(true); } -grpc_tls_key_materials_config* grpc_tls_key_materials_config_create() { - return new grpc_tls_key_materials_config(); +void grpc_tls_credentials_options_set_root_cert_name( + grpc_tls_credentials_options* options, const char* root_cert_name) { + GPR_ASSERT(options != nullptr); + options->set_root_cert_name(root_cert_name); } -int grpc_tls_key_materials_config_set_key_materials( - grpc_tls_key_materials_config* config, const char* root_certs, - const grpc_ssl_pem_key_cert_pair** key_cert_pairs, size_t num) { - if (config == nullptr || key_cert_pairs == nullptr || num == 0) { - gpr_log(GPR_ERROR, - "Invalid arguments to " - "grpc_tls_key_materials_config_set_key_materials()"); - return 0; - } - config->set_key_materials(root_certs, key_cert_pairs, num); - return 1; -} - -int grpc_tls_key_materials_config_set_version( - grpc_tls_key_materials_config* config, int version) { - if (config == nullptr) { - gpr_log(GPR_ERROR, - "Invalid arguments to " - "grpc_tls_key_materials_config_set_version()"); - return 0; - } - config->set_version(version); - return 1; +void grpc_tls_credentials_options_watch_identity_key_cert_pairs( + grpc_tls_credentials_options* options) { + GPR_ASSERT(options != nullptr); + options->set_watch_identity_pair(true); } -int grpc_tls_key_materials_config_get_version( - grpc_tls_key_materials_config* config) { - if (config == nullptr) { - gpr_log(GPR_ERROR, - "Invalid arguments to " - "grpc_tls_key_materials_config_get_version()"); - return -1; - } - return config->version(); +void grpc_tls_credentials_options_set_identity_cert_name( + grpc_tls_credentials_options* options, const char* identity_cert_name) { + GPR_ASSERT(options != nullptr); + options->set_identity_cert_name(identity_cert_name); } -grpc_tls_credential_reload_config* grpc_tls_credential_reload_config_create( - const void* config_user_data, - int (*schedule)(void* config_user_data, - grpc_tls_credential_reload_arg* arg), - void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), - void (*destruct)(void* config_user_data)) { - if (schedule == nullptr) { - gpr_log( - GPR_ERROR, - "Schedule API is nullptr in creating TLS credential reload config."); - return nullptr; - } - return new grpc_tls_credential_reload_config(config_user_data, schedule, - cancel, destruct); +void grpc_tls_credentials_options_set_server_authorization_check_config( + grpc_tls_credentials_options* options, + grpc_tls_server_authorization_check_config* config) { + GPR_ASSERT(options != nullptr); + GPR_ASSERT(config != nullptr); + options->set_server_authorization_check_config(config->Ref()); } grpc_tls_server_authorization_check_config* @@ -243,3 +162,12 @@ grpc_tls_server_authorization_check_config_create( return new grpc_tls_server_authorization_check_config( config_user_data, schedule, cancel, destruct); } + +void grpc_tls_server_authorization_check_config_release( + grpc_tls_server_authorization_check_config* config) { + GRPC_API_TRACE( + "grpc_tls_server_authorization_check_config_release(config=%p)", 1, + (config)); + grpc_core::ExecCtx exec_ctx; + if (config != nullptr) config->Unref(); +} diff --git a/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h index 28faf263512..30a6c9a446a 100644 --- a/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +++ b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h @@ -26,6 +26,8 @@ #include "absl/container/inlined_vector.h" #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h" +#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" #include "src/core/lib/security/security_connector/ssl_utils.h" struct grpc_tls_error_details @@ -41,126 +43,6 @@ struct grpc_tls_error_details std::string error_details_; }; -/** TLS key materials config. **/ -struct grpc_tls_key_materials_config - : public grpc_core::RefCounted { - public: - typedef absl::InlinedVector PemKeyCertPairList; - - /** Getters for member fields. **/ - const char* pem_root_certs() const { return pem_root_certs_.get(); } - const PemKeyCertPairList& pem_key_cert_pair_list() const { - return pem_key_cert_pair_list_; - } - int version() const { return version_; } - - /** Setters for member fields. **/ - // TODO(ZhenLian): Remove this function - void set_pem_root_certs(grpc_core::UniquePtr pem_root_certs) { - pem_root_certs_ = std::move(pem_root_certs); - } - // The ownerships of |pem_root_certs| remain with the caller. - void set_pem_root_certs(const char* pem_root_certs) { - // make a copy of pem_root_certs. - grpc_core::UniquePtr pem_root_ptr(gpr_strdup(pem_root_certs)); - pem_root_certs_ = std::move(pem_root_ptr); - } - void add_pem_key_cert_pair(grpc_core::PemKeyCertPair pem_key_cert_pair) { - pem_key_cert_pair_list_.push_back(std::move(pem_key_cert_pair)); - } - // The ownerships of |pem_root_certs| and |pem_key_cert_pairs| remain with the - // caller. - void set_key_materials(const char* pem_root_certs, - const grpc_ssl_pem_key_cert_pair** pem_key_cert_pairs, - size_t num_key_cert_pairs); - // The ownerships of |pem_root_certs| and |pem_key_cert_pair_list| remain with - // the caller. - void set_key_materials(const char* pem_root_certs, - const PemKeyCertPairList& pem_key_cert_pair_list); - void set_version(int version) { version_ = version; } - - private: - int version_ = 0; - PemKeyCertPairList pem_key_cert_pair_list_; - grpc_core::UniquePtr pem_root_certs_; -}; - -/** TLS credential reload config. **/ -struct grpc_tls_credential_reload_config - : public grpc_core::RefCounted { - public: - grpc_tls_credential_reload_config( - const void* config_user_data, - int (*schedule)(void* config_user_data, - grpc_tls_credential_reload_arg* arg), - void (*cancel)(void* config_user_data, - grpc_tls_credential_reload_arg* arg), - void (*destruct)(void* config_user_data)); - ~grpc_tls_credential_reload_config() override; - - void* context() const { return context_; } - void set_context(void* context) { context_ = context; } - - int Schedule(grpc_tls_credential_reload_arg* arg) const { - if (schedule_ == nullptr) { - gpr_log(GPR_ERROR, "schedule API is nullptr"); - if (arg != nullptr) { - arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL; - arg->error_details->set_error_details( - "schedule API in credential reload config is nullptr"); - } - return 1; - } - if (arg != nullptr) { - arg->config = const_cast(this); - } - return schedule_(config_user_data_, arg); - } - void Cancel(grpc_tls_credential_reload_arg* arg) const { - if (cancel_ == nullptr) { - gpr_log(GPR_ERROR, "cancel API is nullptr."); - if (arg != nullptr) { - arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL; - arg->error_details->set_error_details( - "cancel API in credential reload config is nullptr"); - } - return; - } - if (arg != nullptr) { - arg->config = const_cast(this); - } - cancel_(config_user_data_, arg); - } - - private: - /** This is a pointer to the wrapped language implementation of - * grpc_tls_credential_reload_config. It is necessary to implement the C - * schedule and cancel functions, given the schedule or cancel function in a - * wrapped language. **/ - void* context_ = nullptr; - /** config-specific, read-only user data that works for all channels created - with a credential using the config. */ - void* config_user_data_; - /** callback function for invoking credential reload API. The implementation - of this method has to be non-blocking, but can be performed synchronously - or asynchronously. - If processing occurs synchronously, it populates \a arg->key_materials, \a - arg->status, and \a arg->error_details and returns zero. - If processing occurs asynchronously, it returns a non-zero value. - Application then invokes \a arg->cb when processing is completed. Note that - \a arg->cb cannot be invoked before \a schedule returns. - */ - int (*schedule_)(void* config_user_data, grpc_tls_credential_reload_arg* arg); - /** callback function for cancelling a credential reload request scheduled via - an asynchronous \a schedule. \a arg is used to pinpoint an exact reloading - request to be cancelled, and the operation may not have any effect if the - request has already been processed. */ - void (*cancel_)(void* config_user_data, grpc_tls_credential_reload_arg* arg); - /** callback function for cleaning up any data associated with credential - reload config. */ - void (*destruct_)(void* config_user_data); -}; - /** TLS server authorization check config. **/ struct grpc_tls_server_authorization_check_config : public grpc_core::RefCounted { @@ -175,40 +57,12 @@ struct grpc_tls_server_authorization_check_config ~grpc_tls_server_authorization_check_config() override; void* context() const { return context_; } + void set_context(void* context) { context_ = context; } - int Schedule(grpc_tls_server_authorization_check_arg* arg) const { - if (schedule_ == nullptr) { - gpr_log(GPR_ERROR, "schedule API is nullptr"); - if (arg != nullptr) { - arg->status = GRPC_STATUS_NOT_FOUND; - arg->error_details->set_error_details( - "schedule API in server authorization check config is nullptr"); - } - return 1; - } - if (arg != nullptr && context_ != nullptr) { - arg->config = - const_cast(this); - } - return schedule_(config_user_data_, arg); - } - void Cancel(grpc_tls_server_authorization_check_arg* arg) const { - if (cancel_ == nullptr) { - gpr_log(GPR_ERROR, "cancel API is nullptr."); - if (arg != nullptr) { - arg->status = GRPC_STATUS_NOT_FOUND; - arg->error_details->set_error_details( - "schedule API in server authorization check config is nullptr"); - } - return; - } - if (arg != nullptr) { - arg->config = - const_cast(this); - } - cancel_(config_user_data_, arg); - } + int Schedule(grpc_tls_server_authorization_check_arg* arg) const; + + void Cancel(grpc_tls_server_authorization_check_arg* arg) const; private: /** This is a pointer to the wrapped language implementation of @@ -241,23 +95,15 @@ struct grpc_tls_server_authorization_check_config void (*destruct_)(void* config_user_data); }; -/* TLS credentials options. */ +// Contains configurable options specified by callers to configure their certain +// security features supported in TLS. +// TODO(ZhenLian): consider making this not ref-counted. struct grpc_tls_credentials_options : public grpc_core::RefCounted { public: - ~grpc_tls_credentials_options() override { - if (key_materials_config_.get() != nullptr) { - key_materials_config_->Unref(); - } - if (credential_reload_config_.get() != nullptr) { - credential_reload_config_->Unref(); - } - if (server_authorization_check_config_.get() != nullptr) { - server_authorization_check_config_->Unref(); - } - } + ~grpc_tls_credentials_options() override = default; - /* Getters for member fields. */ + // Getters for member fields. grpc_ssl_client_certificate_request_type cert_request_type() const { return cert_request_type_; } @@ -266,18 +112,26 @@ struct grpc_tls_credentials_options } grpc_tls_version min_tls_version() const { return min_tls_version_; } grpc_tls_version max_tls_version() const { return max_tls_version_; } - grpc_tls_key_materials_config* key_materials_config() const { - return key_materials_config_.get(); - } - grpc_tls_credential_reload_config* credential_reload_config() const { - return credential_reload_config_.get(); - } grpc_tls_server_authorization_check_config* server_authorization_check_config() const { return server_authorization_check_config_.get(); } - - /* Setters for member fields. */ + // This will be used by the security connector to get the correct distributor. + // It can be applied to both the Tls*Creds and the Xds*Creds cases. + // For Tls*Creds case, we will get the distributor from the provider; + // For Xds*Creds case, there will be a level of indirection between the + // provider and the distributor, so we will get the distributor directly. + grpc_tls_certificate_distributor* certificate_distributor() { + if (provider_ != nullptr) return provider_->distributor().get(); + if (distributor_ != nullptr) return distributor_.get(); + return nullptr; + } + bool watch_root_cert() { return watch_root_cert_; } + const std::string& root_cert_name() { return root_cert_name_; } + bool watch_identity_pair() { return watch_identity_pair_; } + const std::string& identity_cert_name() { return identity_cert_name_; } + + // Setters for member fields. void set_cert_request_type( const grpc_ssl_client_certificate_request_type type) { cert_request_type_ = type; @@ -292,32 +146,61 @@ struct grpc_tls_credentials_options void set_max_tls_version(grpc_tls_version max_tls_version) { max_tls_version_ = max_tls_version; } - void set_key_materials_config( - grpc_core::RefCountedPtr config) { - key_materials_config_ = std::move(config); - } - void set_credential_reload_config( - grpc_core::RefCountedPtr config) { - credential_reload_config_ = std::move(config); - } void set_server_authorization_check_config( grpc_core::RefCountedPtr config) { server_authorization_check_config_ = std::move(config); } + // Sets the provider in the options. + // This should only be used by C-core API for Tls*Creds case. + void set_certificate_provider( + grpc_core::RefCountedPtr provider) { + provider_ = std::move(provider); + } + // Sets the distributor in the options. + // This should only be used by the xDS code for Xds*Creds case. + void set_certificate_distributor( + grpc_core::RefCountedPtr distributor) { + distributor_ = std::move(distributor); + } + // If need to watch the updates of root certificates with name + // |root_cert_name|. The default value is false. If used in tls_credentials, + // it should always be set to true unless the root certificates are not + // needed. + void set_watch_root_cert(bool watch) { watch_root_cert_ = watch; } + // Sets the name of root certificates being watched, if |set_watch_root_cert| + // is called. If not set, an empty string will be used as the name. + void set_root_cert_name(std::string root_cert_name) { + root_cert_name_ = std::move(root_cert_name); + } + // If need to watch the updates of identity certificates with name + // |identity_cert_name|. + // The default value is false. + // If used in tls_credentials, it should always be set to true + // unless the identity key-cert pairs are not needed. + void set_watch_identity_pair(bool watch) { watch_identity_pair_ = watch; } + // Sets the name of identity key-cert pairs being watched, if + // |set_watch_identity_pair| is called. If not set, an empty string will + // be used as the name. + void set_identity_cert_name(std::string identity_cert_name) { + identity_cert_name_ = std::move(identity_cert_name); + } private: - grpc_ssl_client_certificate_request_type cert_request_type_; + grpc_ssl_client_certificate_request_type cert_request_type_ = + GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE; grpc_tls_server_verification_option server_verification_option_ = GRPC_TLS_SERVER_VERIFICATION; grpc_tls_version min_tls_version_ = grpc_tls_version::TLS1_2; grpc_tls_version max_tls_version_ = grpc_tls_version::TLS1_3; - grpc_core::RefCountedPtr key_materials_config_; - grpc_core::RefCountedPtr - credential_reload_config_; grpc_core::RefCountedPtr server_authorization_check_config_; + grpc_core::RefCountedPtr provider_; + grpc_core::RefCountedPtr distributor_; + bool watch_root_cert_ = false; + std::string root_cert_name_; + bool watch_identity_pair_ = false; + std::string identity_cert_name_; }; -#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H \ - */ +#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H diff --git a/src/core/lib/security/credentials/tls/tls_credentials.cc b/src/core/lib/security/credentials/tls/tls_credentials.cc index 701fd3b1502..f2c4b3b807d 100644 --- a/src/core/lib/security/credentials/tls/tls_credentials.cc +++ b/src/core/lib/security/credentials/tls/tls_credentials.cc @@ -40,18 +40,18 @@ bool CredentialOptionSanityCheck(const grpc_tls_credentials_options* options, gpr_log(GPR_ERROR, "TLS credentials options is nullptr."); return false; } - if (options->key_materials_config() == nullptr && - options->credential_reload_config() == nullptr) { - gpr_log(GPR_ERROR, - "TLS credentials options must specify either key materials or " - "credential reload config."); - return false; - } + // TODO(ZhenLian): remove this when it is also supported on server side. if (!is_client && options->server_authorization_check_config() != nullptr) { gpr_log(GPR_INFO, "Server's credentials options should not contain server " "authorization check config."); } + if (options->server_verification_option() != GRPC_TLS_SERVER_VERIFICATION && + options->server_authorization_check_config() == nullptr) { + gpr_log(GPR_ERROR, + "Should provider custom verifications if bypassing default ones."); + return false; + } return true; } @@ -85,14 +85,16 @@ TlsCredentials::create_security_connector( } grpc_core::RefCountedPtr sc = grpc_core::TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector( - this->Ref(), std::move(call_creds), target_name, + this->Ref(), options_, std::move(call_creds), target_name, overridden_target_name, ssl_session_cache); if (sc == nullptr) { return nullptr; } - grpc_arg new_arg = grpc_channel_arg_string_create( - (char*)GRPC_ARG_HTTP2_SCHEME, (char*)"https"); - *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1); + if (args != nullptr) { + grpc_arg new_arg = grpc_channel_arg_string_create( + (char*)GRPC_ARG_HTTP2_SCHEME, (char*)"https"); + *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1); + } return sc; } @@ -106,9 +108,11 @@ TlsServerCredentials::~TlsServerCredentials() {} grpc_core::RefCountedPtr TlsServerCredentials::create_security_connector() { return grpc_core::TlsServerSecurityConnector:: - CreateTlsServerSecurityConnector(this->Ref()); + CreateTlsServerSecurityConnector(this->Ref(), options_); } +/** -- Wrapper APIs declared in grpc_security.h -- **/ + grpc_channel_credentials* grpc_tls_credentials_create( grpc_tls_credentials_options* options) { if (!CredentialOptionSanityCheck(options, true /* is_client */)) { diff --git a/src/core/lib/security/credentials/tls/tls_credentials.h b/src/core/lib/security/credentials/tls/tls_credentials.h index 388c71f6b73..214bc904062 100644 --- a/src/core/lib/security/credentials/tls/tls_credentials.h +++ b/src/core/lib/security/credentials/tls/tls_credentials.h @@ -38,7 +38,7 @@ class TlsCredentials final : public grpc_channel_credentials { const char* target_name, const grpc_channel_args* args, grpc_channel_args** new_args) override; - const grpc_tls_credentials_options& options() const { return *options_; } + grpc_tls_credentials_options* options() const { return options_.get(); } private: grpc_core::RefCountedPtr options_; @@ -53,7 +53,7 @@ class TlsServerCredentials final : public grpc_server_credentials { grpc_core::RefCountedPtr create_security_connector() override; - const grpc_tls_credentials_options& options() const { return *options_; } + grpc_tls_credentials_options* options() const { return options_.get(); } private: grpc_core::RefCountedPtr options_; diff --git a/src/core/lib/security/security_connector/ssl_utils.h b/src/core/lib/security/security_connector/ssl_utils.h index 3c3e9fc98cf..d54cdeeda03 100644 --- a/src/core/lib/security/security_connector/ssl_utils.h +++ b/src/core/lib/security/security_connector/ssl_utils.h @@ -187,6 +187,8 @@ class PemKeyCertPair { grpc_core::UniquePtr cert_chain_; }; +typedef absl::InlinedVector PemKeyCertPairList; + } // namespace grpc_core #endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_UTILS_H \ diff --git a/src/core/lib/security/security_connector/tls/tls_security_connector.cc b/src/core/lib/security/security_connector/tls/tls_security_connector.cc index 8088cf831fa..05f50b48d70 100644 --- a/src/core/lib/security/security_connector/tls/tls_security_connector.cc +++ b/src/core/lib/security/security_connector/tls/tls_security_connector.cc @@ -46,7 +46,7 @@ namespace grpc_core { namespace { tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair( - const grpc_tls_key_materials_config::PemKeyCertPairList& cert_pair_list) { + const grpc_core::PemKeyCertPairList& cert_pair_list) { tsi_ssl_pem_key_cert_pair* tsi_pairs = nullptr; size_t num_key_cert_pairs = cert_pair_list.size(); if (num_key_cert_pairs > 0) { @@ -65,127 +65,120 @@ tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair( } // namespace -grpc_status_code TlsFetchKeyMaterials( - const grpc_core::RefCountedPtr& - key_materials_config, - const grpc_tls_credentials_options& options, bool is_server, - grpc_ssl_certificate_config_reload_status* status) { - GPR_ASSERT(key_materials_config != nullptr); - GPR_ASSERT(status != nullptr); - bool is_key_materials_empty = - key_materials_config->pem_key_cert_pair_list().empty(); - grpc_tls_credential_reload_config* credential_reload_config = - options.credential_reload_config(); - /** If there are no key materials and no credential reload config and the - * caller is a server, then return an error. We do not require that a client - * always provision certificates. **/ - if (credential_reload_config == nullptr && is_key_materials_empty && - is_server) { +// -------------------channel security connector------------------- +grpc_core::RefCountedPtr +TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector( + grpc_core::RefCountedPtr ch_creds, + grpc_core::RefCountedPtr options, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name, const char* overridden_target_name, + tsi_ssl_session_cache* ssl_session_cache) { + if (ch_creds == nullptr) { gpr_log(GPR_ERROR, - "Either credential reload config or key materials should be " - "provisioned."); - return GRPC_STATUS_FAILED_PRECONDITION; - } - grpc_status_code reload_status = GRPC_STATUS_OK; - /** Use |credential_reload_config| to update |key_materials_config|. **/ - if (credential_reload_config != nullptr) { - grpc_tls_credential_reload_arg* arg = new grpc_tls_credential_reload_arg(); - arg->key_materials_config = key_materials_config.get(); - arg->error_details = new grpc_tls_error_details(); - int result = credential_reload_config->Schedule(arg); - if (result) { - /** Credential reloading is performed async. This is not yet supported. - * **/ - gpr_log(GPR_ERROR, "Async credential reload is unsupported now."); - *status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - reload_status = - is_key_materials_empty ? GRPC_STATUS_UNIMPLEMENTED : GRPC_STATUS_OK; - } else { - /** Credential reloading is performed sync. **/ - *status = arg->status; - if (arg->status == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED) { - /* Key materials is not empty. */ - gpr_log(GPR_DEBUG, "Credential does not change after reload."); - } else if (arg->status == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL) { - gpr_log(GPR_ERROR, "Credential reload failed with an error:"); - if (arg->error_details != nullptr) { - gpr_log(GPR_ERROR, "%s", arg->error_details->error_details().c_str()); - } - reload_status = - is_key_materials_empty ? GRPC_STATUS_INTERNAL : GRPC_STATUS_OK; - } - } - delete arg->error_details; - /** If the credential reload config was constructed via a wrapped language, - * then |arg->context| and |arg->destroy_context| will not be nullptr. In - * this case, we must destroy |arg->context|, which stores the wrapped - * language-version of the credential reload arg. **/ - if (arg->destroy_context != nullptr) { - arg->destroy_context(arg->context); - } - delete arg; + "channel_creds is nullptr in " + "TlsChannelSecurityConnectorCreate()"); + return nullptr; } - return reload_status; -} - -grpc_error* TlsCheckHostName(const char* peer_name, const tsi_peer* peer) { - /* Check the peer name if specified. */ - if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) { - return GRPC_ERROR_CREATE_FROM_COPIED_STRING( - absl::StrCat("Peer name ", peer_name, " is not in peer certificate") - .c_str()); + if (options == nullptr) { + gpr_log(GPR_ERROR, + "options is nullptr in " + "TlsChannelSecurityConnectorCreate()"); + return nullptr; } - return GRPC_ERROR_NONE; + if (target_name == nullptr) { + gpr_log(GPR_ERROR, + "target_name is nullptr in " + "TlsChannelSecurityConnectorCreate()"); + return nullptr; + } + grpc_core::RefCountedPtr c = + grpc_core::MakeRefCounted( + std::move(ch_creds), std::move(options), + std::move(request_metadata_creds), target_name, + overridden_target_name, ssl_session_cache); + return c; } TlsChannelSecurityConnector::TlsChannelSecurityConnector( - grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr ch_creds, + grpc_core::RefCountedPtr options, grpc_core::RefCountedPtr request_metadata_creds, - const char* target_name, const char* overridden_target_name) - : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME, - std::move(channel_creds), + const char* target_name, const char* overridden_target_name, + tsi_ssl_session_cache* ssl_session_cache) + : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME, std::move(ch_creds), std::move(request_metadata_creds)), + options_(std::move(options)), overridden_target_name_( - overridden_target_name == nullptr ? "" : overridden_target_name) { - key_materials_config_ = grpc_tls_key_materials_config_create()->Ref(); + overridden_target_name == nullptr ? "" : overridden_target_name), + ssl_session_cache_(ssl_session_cache) { + if (ssl_session_cache_ != nullptr) { + tsi_ssl_session_cache_ref(ssl_session_cache_); + } check_arg_ = ServerAuthorizationCheckArgCreate(this); absl::string_view host; absl::string_view port; grpc_core::SplitHostPort(target_name, &host, &port); target_name_ = std::string(host); + // Create a watcher. + auto watcher_ptr = absl::make_unique(this); + certificate_watcher_ = watcher_ptr.get(); + // Register the watcher with the distributor. + grpc_tls_certificate_distributor* distributor = + options_->certificate_distributor(); + absl::optional watched_root_cert_name; + if (options_->watch_root_cert()) { + watched_root_cert_name = options_->root_cert_name(); + } + absl::optional watched_identity_cert_name; + if (options_->watch_identity_pair()) { + watched_identity_cert_name = options_->identity_cert_name(); + } + distributor->WatchTlsCertificates(std::move(watcher_ptr), + watched_root_cert_name, + watched_identity_cert_name); } TlsChannelSecurityConnector::~TlsChannelSecurityConnector() { + if (ssl_session_cache_ != nullptr) { + tsi_ssl_session_cache_unref(ssl_session_cache_); + } + // Cancel all the watchers. + grpc_tls_certificate_distributor* distributor = + options_->certificate_distributor(); + distributor->CancelTlsCertificatesWatch(certificate_watcher_); if (client_handshaker_factory_ != nullptr) { tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_); } - if (key_materials_config_.get() != nullptr) { - key_materials_config_->Unref(); + if (check_arg_ != nullptr) { + ServerAuthorizationCheckArgDestroy(check_arg_); } - ServerAuthorizationCheckArgDestroy(check_arg_); } void TlsChannelSecurityConnector::add_handshakers( const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/, grpc_core::HandshakeManager* handshake_mgr) { - if (RefreshHandshakerFactory() != GRPC_SECURITY_OK) { - gpr_log(GPR_ERROR, "Handshaker factory refresh failed."); - return; - } - // Instantiate TSI handshaker. - tsi_handshaker* tsi_hs = nullptr; - tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( - client_handshaker_factory_, - overridden_target_name_.empty() ? target_name_.c_str() - : overridden_target_name_.c_str(), - &tsi_hs); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", - tsi_result_to_string(result)); + grpc_core::MutexLock lock(&mu_); + if (client_handshaker_factory_ != nullptr) { + // Instantiate TSI handshaker. + tsi_handshaker* tsi_hs = nullptr; + tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( + client_handshaker_factory_, + overridden_target_name_.empty() ? target_name_.c_str() + : overridden_target_name_.c_str(), + &tsi_hs); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", + tsi_result_to_string(result)); + return; + } + // Create handshakers. + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args)); return; } - // Create handshakers. - handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args)); + // TODO(ZhenLian): Implement the logic(delegation to + // BlockOnInitialCredentialHandshaker) when certificates are not ready. + gpr_log(GPR_ERROR, "%s not supported yet.", + "Client BlockOnInitialCredentialHandshaker"); } void TlsChannelSecurityConnector::check_peer( @@ -203,12 +196,9 @@ void TlsChannelSecurityConnector::check_peer( } *auth_context = grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE); - const TlsCredentials* creds = - static_cast(channel_creds()); - if (creds->options().server_verification_option() == - GRPC_TLS_SERVER_VERIFICATION) { + if (options_->server_verification_option() == GRPC_TLS_SERVER_VERIFICATION) { /* Do the default host name check if specifying the target name. */ - error = TlsCheckHostName(target_name, &peer); + error = internal::TlsCheckHostName(target_name, &peer); if (error != GRPC_ERROR_NONE) { grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error); tsi_peer_destruct(&peer); @@ -217,7 +207,7 @@ void TlsChannelSecurityConnector::check_peer( } /* Do the custom server authorization check, if specified by the user. */ const grpc_tls_server_authorization_check_config* config = - creds->options().server_authorization_check_config(); + options_->server_authorization_check_config(); /* If server authorization config is not null, use it to perform * server authorization check. */ if (config != nullptr) { @@ -289,105 +279,86 @@ void TlsChannelSecurityConnector::cancel_check_call_host( GRPC_ERROR_UNREF(error); } -grpc_core::RefCountedPtr -TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector( - grpc_core::RefCountedPtr channel_creds, - grpc_core::RefCountedPtr request_metadata_creds, - const char* target_name, const char* overridden_target_name, - tsi_ssl_session_cache* ssl_session_cache) { - if (channel_creds == nullptr) { - gpr_log(GPR_ERROR, - "channel_creds is nullptr in " - "TlsChannelSecurityConnectorCreate()"); - return nullptr; +void TlsChannelSecurityConnector::TlsChannelCertificateWatcher:: + OnCertificatesChanged( + absl::optional root_certs, + absl::optional key_cert_pairs) { + GPR_ASSERT(security_connector_ != nullptr); + grpc_core::MutexLock lock(&security_connector_->mu_); + if (root_certs.has_value()) { + security_connector_->pem_root_certs_ = root_certs; + } + if (key_cert_pairs.has_value()) { + security_connector_->pem_key_cert_pair_list_ = std::move(key_cert_pairs); + } + bool root_being_watched = security_connector_->options_->watch_root_cert(); + bool root_has_value = security_connector_->pem_root_certs_.has_value(); + bool identity_being_watched = + security_connector_->options_->watch_identity_pair(); + bool identity_has_value = + security_connector_->pem_key_cert_pair_list_.has_value(); + if ((root_being_watched && root_has_value && identity_being_watched && + identity_has_value) || + (root_being_watched && root_has_value && !identity_being_watched) || + (!root_being_watched && identity_being_watched && identity_has_value)) { + if (security_connector_->UpdateHandshakerFactoryLocked() != + GRPC_SECURITY_OK) { + gpr_log(GPR_ERROR, "Update handshaker factory failed."); + } } - if (target_name == nullptr) { +} + +// TODO(ZhenLian): implement the logic to signal waiting handshakers once +// BlockOnInitialCredentialHandshaker is implemented. +void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::OnError( + grpc_error* root_cert_error, grpc_error* identity_cert_error) { + if (root_cert_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, - "target_name is nullptr in " - "TlsChannelSecurityConnectorCreate()"); - return nullptr; + "TlsChannelCertificateWatcher getting root_cert_error: %s", + grpc_error_string(root_cert_error)); } - grpc_core::RefCountedPtr c = - grpc_core::MakeRefCounted( - std::move(channel_creds), std::move(request_metadata_creds), - target_name, overridden_target_name); - if (c->InitializeHandshakerFactory(ssl_session_cache) != GRPC_SECURITY_OK) { - gpr_log(GPR_ERROR, "Could not initialize client handshaker factory."); - return nullptr; + if (identity_cert_error != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, + "TlsChannelCertificateWatcher getting identity_cert_error: %s", + grpc_error_string(identity_cert_error)); } - return c; + GRPC_ERROR_UNREF(root_cert_error); + GRPC_ERROR_UNREF(identity_cert_error); } -grpc_security_status TlsChannelSecurityConnector::ReplaceHandshakerFactory( - tsi_ssl_session_cache* ssl_session_cache) { - const TlsCredentials* creds = - static_cast(channel_creds()); +// TODO(ZhenLian): implement the logic to signal waiting handshakers once +// BlockOnInitialCredentialHandshaker is implemented. +grpc_security_status +TlsChannelSecurityConnector::UpdateHandshakerFactoryLocked() { bool skip_server_certificate_verification = - creds->options().server_verification_option() == + options_->server_verification_option() == GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION; /* Free the client handshaker factory if exists. */ - if (client_handshaker_factory_) { + if (client_handshaker_factory_ != nullptr) { tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_); } - tsi_ssl_pem_key_cert_pair* pem_key_cert_pair = ConvertToTsiPemKeyCertPair( - key_materials_config_->pem_key_cert_pair_list()); + std::string pem_root_certs; + if (pem_root_certs_.has_value()) { + // TODO(ZhenLian): update the underlying TSI layer to use C++ types like + // std::string and absl::string_view to avoid making another copy here. + pem_root_certs = std::string(*pem_root_certs_); + } + tsi_ssl_pem_key_cert_pair* pem_key_cert_pair = nullptr; + if (pem_key_cert_pair_list_.has_value()) { + pem_key_cert_pair = ConvertToTsiPemKeyCertPair(*pem_key_cert_pair_list_); + } grpc_security_status status = grpc_ssl_tsi_client_handshaker_factory_init( - pem_key_cert_pair, key_materials_config_->pem_root_certs(), + pem_key_cert_pair, + pem_root_certs.empty() ? nullptr : pem_root_certs.c_str(), skip_server_certificate_verification, - grpc_get_tsi_tls_version(creds->options().min_tls_version()), - grpc_get_tsi_tls_version(creds->options().max_tls_version()), - ssl_session_cache, &client_handshaker_factory_); + grpc_get_tsi_tls_version(options_->min_tls_version()), + grpc_get_tsi_tls_version(options_->max_tls_version()), ssl_session_cache_, + &client_handshaker_factory_); /* Free memory. */ - grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1); - return status; -} - -grpc_security_status TlsChannelSecurityConnector::InitializeHandshakerFactory( - tsi_ssl_session_cache* ssl_session_cache) { - grpc_core::MutexLock lock(&mu_); - const TlsCredentials* creds = - static_cast(channel_creds()); - grpc_tls_key_materials_config* key_materials_config = - creds->options().key_materials_config(); - // key_materials_config_->set_key_materials will handle the copying of the key - // materials users provided - if (key_materials_config != nullptr) { - key_materials_config_->set_key_materials( - key_materials_config->pem_root_certs(), - key_materials_config->pem_key_cert_pair_list()); - } - grpc_ssl_certificate_config_reload_status reload_status = - GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - /** If |creds->options()| has a credential reload config, then the call to - * |TlsFetchKeyMaterials| will use it to update the root cert and - * pem-key-cert-pair list stored in |key_materials_config_|. **/ - if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), false, - &reload_status) != GRPC_STATUS_OK) { - /* Raise an error if key materials are not populated. */ - return GRPC_SECURITY_ERROR; - } - return ReplaceHandshakerFactory(ssl_session_cache); -} - -grpc_security_status TlsChannelSecurityConnector::RefreshHandshakerFactory() { - grpc_core::MutexLock lock(&mu_); - const TlsCredentials* creds = - static_cast(channel_creds()); - grpc_ssl_certificate_config_reload_status reload_status = - GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - /** If |creds->options()| has a credential reload config, then the call to - * |TlsFetchKeyMaterials| will use it to update the root cert and - * pem-key-cert-pair list stored in |key_materials_config_|. **/ - if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), false, - &reload_status) != GRPC_STATUS_OK) { - return GRPC_SECURITY_ERROR; - } - if (reload_status != GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW) { - // Re-use existing handshaker factory. - return GRPC_SECURITY_OK; - } else { - return ReplaceHandshakerFactory(nullptr); + if (pem_key_cert_pair != nullptr) { + grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1); } + return status; } void TlsChannelSecurityConnector::ServerAuthorizationCheckDone( @@ -457,40 +428,86 @@ void TlsChannelSecurityConnector::ServerAuthorizationCheckArgDestroy( delete arg; } +// -------------------server security connector------------------- +grpc_core::RefCountedPtr +TlsServerSecurityConnector::CreateTlsServerSecurityConnector( + grpc_core::RefCountedPtr server_creds, + grpc_core::RefCountedPtr options) { + if (server_creds == nullptr) { + gpr_log(GPR_ERROR, + "server_creds is nullptr in " + "TlsServerSecurityConnectorCreate()"); + return nullptr; + } + if (options == nullptr) { + gpr_log(GPR_ERROR, + "options is nullptr in " + "TlsServerSecurityConnectorCreate()"); + return nullptr; + } + grpc_core::RefCountedPtr c = + grpc_core::MakeRefCounted( + std::move(server_creds), std::move(options)); + return c; +} + TlsServerSecurityConnector::TlsServerSecurityConnector( - grpc_core::RefCountedPtr server_creds) + grpc_core::RefCountedPtr server_creds, + grpc_core::RefCountedPtr options) : grpc_server_security_connector(GRPC_SSL_URL_SCHEME, - std::move(server_creds)) { - key_materials_config_ = grpc_tls_key_materials_config_create()->Ref(); + std::move(server_creds)), + options_(std::move(options)) { + // Create a watcher. + auto watcher_ptr = absl::make_unique(this); + certificate_watcher_ = watcher_ptr.get(); + // Register the watcher with the distributor. + grpc_tls_certificate_distributor* distributor = + options_->certificate_distributor(); + absl::optional watched_root_cert_name; + if (options_->watch_root_cert()) { + watched_root_cert_name = options_->root_cert_name(); + } + absl::optional watched_identity_cert_name; + if (options_->watch_identity_pair()) { + watched_identity_cert_name = options_->identity_cert_name(); + } + distributor->WatchTlsCertificates(std::move(watcher_ptr), + watched_root_cert_name, + watched_identity_cert_name); } TlsServerSecurityConnector::~TlsServerSecurityConnector() { + // Cancel all the watchers. + grpc_tls_certificate_distributor* distributor = + options_->certificate_distributor(); + distributor->CancelTlsCertificatesWatch(certificate_watcher_); if (server_handshaker_factory_ != nullptr) { tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_); } - if (key_materials_config_.get() != nullptr) { - key_materials_config_->Unref(); - } } void TlsServerSecurityConnector::add_handshakers( const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/, grpc_core::HandshakeManager* handshake_mgr) { - /* Refresh handshaker factory if needed. */ - if (RefreshHandshakerFactory() != GRPC_SECURITY_OK) { - gpr_log(GPR_ERROR, "Handshaker factory refresh failed."); - return; - } - /* Create a TLS TSI handshaker for server. */ - tsi_handshaker* tsi_hs = nullptr; - tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker( - server_handshaker_factory_, &tsi_hs); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", - tsi_result_to_string(result)); + grpc_core::MutexLock lock(&mu_); + if (server_handshaker_factory_ != nullptr) { + // Instantiate TSI handshaker. + tsi_handshaker* tsi_hs = nullptr; + tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker( + server_handshaker_factory_, &tsi_hs); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", + tsi_result_to_string(result)); + return; + } + // Create handshakers. + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args)); return; } - handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args)); + // TODO(ZhenLian): Implement the logic(delegation to + // BlockOnInitialCredentialHandshaker) when certificates are not ready. + gpr_log(GPR_ERROR, "%s not supported yet.", + "Server BlockOnInitialCredentialHandshaker"); } void TlsServerSecurityConnector::check_peer( @@ -510,43 +527,79 @@ int TlsServerSecurityConnector::cmp( static_cast(other)); } -grpc_core::RefCountedPtr -TlsServerSecurityConnector::CreateTlsServerSecurityConnector( - grpc_core::RefCountedPtr server_creds) { - if (server_creds == nullptr) { +void TlsServerSecurityConnector::TlsServerCertificateWatcher:: + OnCertificatesChanged( + absl::optional root_certs, + absl::optional key_cert_pairs) { + GPR_ASSERT(security_connector_ != nullptr); + grpc_core::MutexLock lock(&security_connector_->mu_); + if (root_certs.has_value()) { + security_connector_->pem_root_certs_ = root_certs; + } + if (key_cert_pairs.has_value()) { + security_connector_->pem_key_cert_pair_list_ = std::move(key_cert_pairs); + } + bool root_being_watched = security_connector_->options_->watch_root_cert(); + bool root_has_value = security_connector_->pem_root_certs_.has_value(); + bool identity_being_watched = + security_connector_->options_->watch_identity_pair(); + bool identity_has_value = + security_connector_->pem_key_cert_pair_list_.has_value(); + if ((root_being_watched && root_has_value && identity_being_watched && + identity_has_value) || + (root_being_watched && root_has_value && !identity_being_watched) || + (!root_being_watched && identity_being_watched && identity_has_value)) { + if (security_connector_->UpdateHandshakerFactoryLocked() != + GRPC_SECURITY_OK) { + gpr_log(GPR_ERROR, "Update handshaker factory failed."); + } + } +} + +// TODO(ZhenLian): implement the logic to signal waiting handshakers once +// BlockOnInitialCredentialHandshaker is implemented. +void TlsServerSecurityConnector::TlsServerCertificateWatcher::OnError( + grpc_error* root_cert_error, grpc_error* identity_cert_error) { + if (root_cert_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, - "server_creds is nullptr in " - "TlsServerSecurityConnectorCreate()"); - return nullptr; + "TlsServerCertificateWatcher getting root_cert_error: %s", + grpc_error_string(root_cert_error)); } - grpc_core::RefCountedPtr c = - grpc_core::MakeRefCounted( - std::move(server_creds)); - if (c->InitializeHandshakerFactory() != GRPC_SECURITY_OK) { - gpr_log(GPR_ERROR, "Could not initialize server handshaker factory."); - return nullptr; + if (identity_cert_error != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, + "TlsServerCertificateWatcher getting identity_cert_error: %s", + grpc_error_string(identity_cert_error)); } - return c; + GRPC_ERROR_UNREF(root_cert_error); + GRPC_ERROR_UNREF(identity_cert_error); } -grpc_security_status TlsServerSecurityConnector::ReplaceHandshakerFactory() { - const TlsServerCredentials* creds = - static_cast(server_creds()); +// TODO(ZhenLian): implement the logic to signal waiting handshakers once +// BlockOnInitialCredentialHandshaker is implemented. +grpc_security_status +TlsServerSecurityConnector::UpdateHandshakerFactoryLocked() { /* Free the server handshaker factory if exists. */ - if (server_handshaker_factory_) { + if (server_handshaker_factory_ != nullptr) { tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_); } - GPR_ASSERT(!key_materials_config_->pem_key_cert_pair_list().empty()); - tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = ConvertToTsiPemKeyCertPair( - key_materials_config_->pem_key_cert_pair_list()); - size_t num_key_cert_pairs = - key_materials_config_->pem_key_cert_pair_list().size(); + // The identity certs on the server side shouldn't be empty. + GPR_ASSERT(pem_key_cert_pair_list_.has_value()); + GPR_ASSERT(!(*pem_key_cert_pair_list_).empty()); + std::string pem_root_certs; + if (pem_root_certs_.has_value()) { + // TODO(ZhenLian): update the underlying TSI layer to use C++ types like + // std::string and absl::string_view to avoid making another copy here. + pem_root_certs = std::string(*pem_root_certs_); + } + tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = nullptr; + pem_key_cert_pairs = ConvertToTsiPemKeyCertPair(*pem_key_cert_pair_list_); + size_t num_key_cert_pairs = (*pem_key_cert_pair_list_).size(); grpc_security_status status = grpc_ssl_tsi_server_handshaker_factory_init( pem_key_cert_pairs, num_key_cert_pairs, - key_materials_config_->pem_root_certs(), - creds->options().cert_request_type(), - grpc_get_tsi_tls_version(creds->options().min_tls_version()), - grpc_get_tsi_tls_version(creds->options().max_tls_version()), + pem_root_certs.empty() ? nullptr : pem_root_certs.c_str(), + options_->cert_request_type(), + grpc_get_tsi_tls_version(options_->min_tls_version()), + grpc_get_tsi_tls_version(options_->max_tls_version()), &server_handshaker_factory_); /* Free memory. */ grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pairs, @@ -554,53 +607,18 @@ grpc_security_status TlsServerSecurityConnector::ReplaceHandshakerFactory() { return status; } -grpc_security_status TlsServerSecurityConnector::InitializeHandshakerFactory() { - grpc_core::MutexLock lock(&mu_); - const TlsServerCredentials* creds = - static_cast(server_creds()); - grpc_tls_key_materials_config* key_materials_config = - creds->options().key_materials_config(); - if (key_materials_config != nullptr) { - key_materials_config_->set_key_materials( - key_materials_config->pem_root_certs(), - key_materials_config->pem_key_cert_pair_list()); - } - grpc_ssl_certificate_config_reload_status reload_status = - GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - /** If |creds->options()| has a credential reload config, then the call to - * |TlsFetchKeyMaterials| will use it to update the root cert and - * pem-key-cert-pair list stored in |key_materials_config_|. Otherwise, it - * will return |GRPC_STATUS_OK| if |key_materials_config_| already has - * credentials, and an error code if not. **/ - if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), true, - &reload_status) != GRPC_STATUS_OK) { - /* Raise an error if key materials are not populated. */ - return GRPC_SECURITY_ERROR; - } - return ReplaceHandshakerFactory(); -} +namespace internal { -grpc_security_status TlsServerSecurityConnector::RefreshHandshakerFactory() { - grpc_core::MutexLock lock(&mu_); - const TlsServerCredentials* creds = - static_cast(server_creds()); - grpc_ssl_certificate_config_reload_status reload_status = - GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - /** If |creds->options()| has a credential reload config, then the call to - * |TlsFetchKeyMaterials| will use it to update the root cert and - * pem-key-cert-pair list stored in |key_materials_config_|. Otherwise, it - * will return |GRPC_STATUS_OK| if |key_materials_config_| already has - * credentials, and an error code if not. **/ - if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), true, - &reload_status) != GRPC_STATUS_OK) { - return GRPC_SECURITY_ERROR; - } - if (reload_status != GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW) { - /* At this point, we should have key materials populated. */ - return GRPC_SECURITY_OK; - } else { - return ReplaceHandshakerFactory(); +grpc_error* TlsCheckHostName(const char* peer_name, const tsi_peer* peer) { + /* Check the peer name if specified. */ + if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) { + return GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("Peer name ", peer_name, " is not in peer certificate") + .c_str()); } + return GRPC_ERROR_NONE; } +} // namespace internal + } // namespace grpc_core diff --git a/src/core/lib/security/security_connector/tls/tls_security_connector.h b/src/core/lib/security/security_connector/tls/tls_security_connector.h index db5c87bdaef..d9159598819 100644 --- a/src/core/lib/security/security_connector/tls/tls_security_connector.h +++ b/src/core/lib/security/security_connector/tls/tls_security_connector.h @@ -23,13 +23,14 @@ #include "src/core/lib/gprpp/sync.h" #include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" #include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" #define GRPC_TLS_TRANSPORT_SECURITY_TYPE "tls" namespace grpc_core { -// TLS channel security connector. +// Channel security connector using TLS as transport security protocol. class TlsChannelSecurityConnector final : public grpc_channel_security_connector { public: @@ -37,14 +38,18 @@ class TlsChannelSecurityConnector final static grpc_core::RefCountedPtr CreateTlsChannelSecurityConnector( grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr options, grpc_core::RefCountedPtr request_metadata_creds, const char* target_name, const char* overridden_target_name, tsi_ssl_session_cache* ssl_session_cache); TlsChannelSecurityConnector( grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr options, grpc_core::RefCountedPtr request_metadata_creds, - const char* target_name, const char* overridden_target_name); + const char* target_name, const char* overridden_target_name, + tsi_ssl_session_cache* ssl_session_cache); + ~TlsChannelSecurityConnector() override; void add_handshakers(const grpc_channel_args* args, @@ -64,15 +69,45 @@ class TlsChannelSecurityConnector final void cancel_check_call_host(grpc_closure* on_call_host_checked, grpc_error* error) override; - private: - // Initialize SSL TSI client handshaker factory. - grpc_security_status InitializeHandshakerFactory( - tsi_ssl_session_cache* ssl_session_cache); + tsi_ssl_client_handshaker_factory* ClientHandshakerFactoryForTesting() { + grpc_core::MutexLock lock(&mu_); + return client_handshaker_factory_; + }; - // A util function to create a new client handshaker factory to replace - // the existing one if exists. - grpc_security_status ReplaceHandshakerFactory( - tsi_ssl_session_cache* ssl_session_cache); + const absl::optional& RootCertsForTesting() { + grpc_core::MutexLock lock(&mu_); + return pem_root_certs_; + } + + const absl::optional& + KeyCertPairListForTesting() { + grpc_core::MutexLock lock(&mu_); + return pem_key_cert_pair_list_; + } + + private: + // A watcher that watches certificate updates from + // grpc_tls_certificate_distributor. It will never outlive + // |security_connector_|. + class TlsChannelCertificateWatcher : public grpc_tls_certificate_distributor:: + TlsCertificatesWatcherInterface { + public: + explicit TlsChannelCertificateWatcher( + TlsChannelSecurityConnector* security_connector) + : security_connector_(security_connector) {} + void OnCertificatesChanged( + absl::optional root_certs, + absl::optional key_cert_pairs) override; + void OnError(grpc_error* root_cert_error, + grpc_error* identity_cert_error) override; + + private: + TlsChannelSecurityConnector* security_connector_ = nullptr; + }; + + // Updates |client_handshaker_factory_| when the certificates that + // |certificate_watcher_| is watching get updated. + grpc_security_status UpdateHandshakerFactoryLocked(); // gRPC-provided callback executed by application, which servers to bring the // control back to gRPC core. @@ -91,29 +126,32 @@ class TlsChannelSecurityConnector final static void ServerAuthorizationCheckArgDestroy( grpc_tls_server_authorization_check_arg* arg); - // A util function to refresh SSL TSI client handshaker factory with a valid - // credential. - grpc_security_status RefreshHandshakerFactory(); - grpc_core::Mutex mu_; - grpc_closure* on_peer_checked_; + grpc_core::RefCountedPtr options_; + grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface* + certificate_watcher_ = nullptr; + grpc_closure* on_peer_checked_ = nullptr; std::string target_name_; std::string overridden_target_name_; tsi_ssl_client_handshaker_factory* client_handshaker_factory_ = nullptr; - grpc_tls_server_authorization_check_arg* check_arg_; - grpc_core::RefCountedPtr key_materials_config_; + grpc_tls_server_authorization_check_arg* check_arg_ = nullptr; + tsi_ssl_session_cache* ssl_session_cache_ = nullptr; + absl::optional pem_root_certs_; + absl::optional pem_key_cert_pair_list_; }; -// TLS server security connector. +// Server security connector using TLS as transport security protocol. class TlsServerSecurityConnector final : public grpc_server_security_connector { public: // static factory method to create a TLS server security connector. static grpc_core::RefCountedPtr CreateTlsServerSecurityConnector( - grpc_core::RefCountedPtr server_creds); + grpc_core::RefCountedPtr server_creds, + grpc_core::RefCountedPtr options); - explicit TlsServerSecurityConnector( - grpc_core::RefCountedPtr server_creds); + TlsServerSecurityConnector( + grpc_core::RefCountedPtr server_creds, + grpc_core::RefCountedPtr options); ~TlsServerSecurityConnector() override; void add_handshakers(const grpc_channel_args* args, @@ -126,58 +164,65 @@ class TlsServerSecurityConnector final : public grpc_server_security_connector { int cmp(const grpc_security_connector* other) const override; - private: - // Initialize SSL TSI server handshaker factory. - grpc_security_status InitializeHandshakerFactory(); + tsi_ssl_server_handshaker_factory* ServerHandshakerFactoryForTesting() { + grpc_core::MutexLock lock(&mu_); + return server_handshaker_factory_; + }; - // A util function to create a new server handshaker factory to replace the - // existing once if exists. - grpc_security_status ReplaceHandshakerFactory(); + const absl::optional& RootCertsForTesting() { + grpc_core::MutexLock lock(&mu_); + return pem_root_certs_; + } - // A util function to refresh SSL TSI server handshaker factory with a valid - // credential. - grpc_security_status RefreshHandshakerFactory(); + const absl::optional& + KeyCertPairListForTesting() { + grpc_core::MutexLock lock(&mu_); + return pem_key_cert_pair_list_; + } + + private: + // A watcher that watches certificate updates from + // grpc_tls_certificate_distributor. It will never outlive + // |security_connector_|. + class TlsServerCertificateWatcher : public grpc_tls_certificate_distributor:: + TlsCertificatesWatcherInterface { + public: + explicit TlsServerCertificateWatcher( + TlsServerSecurityConnector* security_connector) + : security_connector_(security_connector) {} + void OnCertificatesChanged( + absl::optional root_certs, + absl::optional key_cert_pairs) override; + void OnError(grpc_error* root_cert_error, + grpc_error* identity_cert_error) override; + + private: + TlsServerSecurityConnector* security_connector_ = nullptr; + }; + + // Updates |server_handshaker_factory_| when the certificates that + // |certificate_watcher_| is watching get updated. + grpc_security_status UpdateHandshakerFactoryLocked(); grpc_core::Mutex mu_; + grpc_core::RefCountedPtr options_; + grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface* + certificate_watcher_ = nullptr; + tsi_ssl_server_handshaker_factory* server_handshaker_factory_ = nullptr; - grpc_core::RefCountedPtr key_materials_config_; + absl::optional pem_root_certs_; + absl::optional pem_key_cert_pair_list_; }; // ---- Functions below are exposed for testing only ----------------------- - -/** The |TlsFetchKeyMaterials| API ensures that |key_materials_config| has a - * non-empty pem-key-cert pair list. This is done as follows: - * - if |options| is equipped with a credential reload config, then this - * methods uses credential reloading to populate |key_materials_config|, and - * afterwards it populates |reload_status| with the status of this operation. - * In particular, any data stored in |key_materials_config| is overwritten. - * - if |options| has no credential reload config, then: - * - if |key_materials_config| already has a non-empty pem-key-cert pair - * list or is called by a client, then the method returns |GRPC_STATUS_OK|. - * - if |key_materials_config| has an empty pem-key-cert pair list and is - * called by a server, then the method return an error code. - * - * The arguments are detailed below: - * - key_materials_config: a key materials config that will be populated by the - * method on success; the caller should not pass in nullptr. Any data held by - * the config will be overwritten. - * - options: the TLS credentials options whose credential reloading config - * will be used to populate |key_materials_config|. - * - is_server: true denotes that this method is called by a server, and - * false denotes that this method is called by a client. - * - status: the status of the credential reloading after the method - * returns; the caller should not pass in nullptr. **/ -grpc_status_code TlsFetchKeyMaterials( - const grpc_core::RefCountedPtr& - key_materials_config, - const grpc_tls_credentials_options& options, bool is_server, - grpc_ssl_certificate_config_reload_status* status); +namespace internal { // TlsCheckHostName checks if |peer_name| matches the identity information // contained in |peer|. This is AKA hostname check. grpc_error* TlsCheckHostName(const char* peer_name, const tsi_peer* peer); +} // namespace internal + } // namespace grpc_core -#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_TLS_TLS_SECURITY_CONNECTOR_H \ - */ +#endif // GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_TLS_TLS_SECURITY_CONNECTOR_H diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc index 28ced459f20..af2841c8f43 100644 --- a/src/cpp/client/secure_credentials.cc +++ b/src/cpp/client/secure_credentials.cc @@ -295,7 +295,7 @@ std::shared_ptr LocalCredentials( // Builds TLS Credentials given TLS options. std::shared_ptr TlsCredentials( - const TlsCredentialsOptions& options) { + const TlsChannelCredentialsOptions& options) { return internal::WrapChannelCredentials( grpc_tls_credentials_create(options.c_credentials_options())); } diff --git a/src/cpp/common/tls_certificate_provider.cc b/src/cpp/common/tls_certificate_provider.cc new file mode 100644 index 00000000000..3550e28608e --- /dev/null +++ b/src/cpp/common/tls_certificate_provider.cc @@ -0,0 +1,45 @@ +// +// 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 + +#include "absl/container/inlined_vector.h" + +namespace grpc { +namespace experimental { + +StaticDataCertificateProvider::StaticDataCertificateProvider( + const std::string& root_certificate, + const std::vector& identity_key_cert_pairs) { + GPR_ASSERT(!root_certificate.empty() || !identity_key_cert_pairs.empty()); + grpc_tls_identity_pairs* pairs_core = grpc_tls_identity_pairs_create(); + for (const IdentityKeyCertPair& pair : identity_key_cert_pairs) { + grpc_tls_identity_pairs_add_pair(pairs_core, pair.private_key.c_str(), + pair.certificate_chain.c_str()); + } + c_provider_ = grpc_tls_certificate_provider_static_data_create( + root_certificate.c_str(), pairs_core); + GPR_ASSERT(c_provider_ != nullptr); +}; + +StaticDataCertificateProvider::~StaticDataCertificateProvider() { + grpc_tls_certificate_provider_release(c_provider_); +}; + +} // namespace experimental +} // namespace grpc diff --git a/src/cpp/common/tls_credentials_options.cc b/src/cpp/common/tls_credentials_options.cc index 011cf4b3e5d..02bc6d918b1 100644 --- a/src/cpp/common/tls_credentials_options.cc +++ b/src/cpp/common/tls_credentials_options.cc @@ -16,178 +16,22 @@ * */ +#include #include #include #include "absl/container/inlined_vector.h" -#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" #include "src/cpp/common/tls_credentials_options_util.h" namespace grpc { namespace experimental { -/** TLS key materials config API implementation **/ -void TlsKeyMaterialsConfig::set_pem_root_certs( - const std::string& pem_root_certs) { - pem_root_certs_ = pem_root_certs; -} - -void TlsKeyMaterialsConfig::add_pem_key_cert_pair( - const PemKeyCertPair& pem_key_cert_pair) { - pem_key_cert_pair_list_.push_back(pem_key_cert_pair); -} - -void TlsKeyMaterialsConfig::set_key_materials( - const std::string& pem_root_certs, - const std::vector& pem_key_cert_pair_list) { - pem_key_cert_pair_list_ = pem_key_cert_pair_list; - pem_root_certs_ = pem_root_certs; -} - -/** TLS credential reload arg API implementation **/ -TlsCredentialReloadArg::TlsCredentialReloadArg( - grpc_tls_credential_reload_arg* arg) - : c_arg_(arg) { - if (c_arg_ != nullptr && c_arg_->context != nullptr) { - gpr_log(GPR_ERROR, "c_arg context has already been set"); - } - c_arg_->context = static_cast(this); - c_arg_->destroy_context = &TlsCredentialReloadArgDestroyContext; -} - -TlsCredentialReloadArg::~TlsCredentialReloadArg() {} - -void* TlsCredentialReloadArg::cb_user_data() const { - return c_arg_->cb_user_data; -} -bool TlsCredentialReloadArg::is_pem_key_cert_pair_list_empty() const { - return c_arg_->key_materials_config->pem_key_cert_pair_list().empty(); -} - -grpc_ssl_certificate_config_reload_status TlsCredentialReloadArg::status() - const { - return c_arg_->status; -} - -std::string TlsCredentialReloadArg::error_details() const { - return c_arg_->error_details->error_details(); -} - -void TlsCredentialReloadArg::set_cb_user_data(void* cb_user_data) { - c_arg_->cb_user_data = cb_user_data; -} - -void TlsCredentialReloadArg::set_pem_root_certs( - const std::string& pem_root_certs) { - ::grpc_core::UniquePtr c_pem_root_certs( - gpr_strdup(pem_root_certs.c_str())); - c_arg_->key_materials_config->set_pem_root_certs(std::move(c_pem_root_certs)); -} - -namespace { - -::grpc_core::PemKeyCertPair ConvertToCorePemKeyCertPair( - const TlsKeyMaterialsConfig::PemKeyCertPair& pem_key_cert_pair) { - grpc_ssl_pem_key_cert_pair* ssl_pair = - (grpc_ssl_pem_key_cert_pair*)gpr_malloc( - sizeof(grpc_ssl_pem_key_cert_pair)); - ssl_pair->private_key = gpr_strdup(pem_key_cert_pair.private_key.c_str()); - ssl_pair->cert_chain = gpr_strdup(pem_key_cert_pair.cert_chain.c_str()); - return ::grpc_core::PemKeyCertPair(ssl_pair); -} - -} // namespace - -void TlsCredentialReloadArg::add_pem_key_cert_pair( - const TlsKeyMaterialsConfig::PemKeyCertPair& pem_key_cert_pair) { - c_arg_->key_materials_config->add_pem_key_cert_pair( - ConvertToCorePemKeyCertPair(pem_key_cert_pair)); -} - -void TlsCredentialReloadArg::set_key_materials( - const std::string& pem_root_certs, - std::vector pem_key_cert_pair_list) { - /** Initialize the |key_materials_config| field of |c_arg_|, if it has not - * already been done. **/ - if (c_arg_->key_materials_config == nullptr) { - c_arg_->key_materials_config = grpc_tls_key_materials_config_create(); - } - /** Convert |pem_key_cert_pair_list| to an inlined vector of ssl pairs. **/ - ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1> - c_pem_key_cert_pair_list; - for (const auto& key_cert_pair : pem_key_cert_pair_list) { - c_pem_key_cert_pair_list.emplace_back( - ConvertToCorePemKeyCertPair(key_cert_pair)); - } - /** Populate the key materials config field of |c_arg_|. **/ - c_arg_->key_materials_config->set_key_materials(pem_root_certs.c_str(), - c_pem_key_cert_pair_list); -} - -void TlsCredentialReloadArg::set_key_materials_config( - const std::shared_ptr& key_materials_config) { - if (key_materials_config == nullptr) { - c_arg_->key_materials_config = nullptr; - return; - } - ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1> - c_pem_key_cert_pair_list; - for (const auto& key_cert_pair : - key_materials_config->pem_key_cert_pair_list()) { - grpc_ssl_pem_key_cert_pair* ssl_pair = - (grpc_ssl_pem_key_cert_pair*)gpr_malloc( - sizeof(grpc_ssl_pem_key_cert_pair)); - ssl_pair->private_key = gpr_strdup(key_cert_pair.private_key.c_str()); - ssl_pair->cert_chain = gpr_strdup(key_cert_pair.cert_chain.c_str()); - ::grpc_core::PemKeyCertPair c_pem_key_cert_pair = - ::grpc_core::PemKeyCertPair(ssl_pair); - c_pem_key_cert_pair_list.emplace_back(std::move(c_pem_key_cert_pair)); - } - ::grpc_core::UniquePtr c_pem_root_certs( - gpr_strdup(key_materials_config->pem_root_certs().c_str())); - if (c_arg_->key_materials_config == nullptr) { - c_arg_->key_materials_config = grpc_tls_key_materials_config_create(); - } - c_arg_->key_materials_config->set_key_materials( - key_materials_config->pem_root_certs().c_str(), c_pem_key_cert_pair_list); - c_arg_->key_materials_config->set_version(key_materials_config->version()); -} - -void TlsCredentialReloadArg::set_status( - grpc_ssl_certificate_config_reload_status status) { - c_arg_->status = status; -} - -void TlsCredentialReloadArg::set_error_details( - const std::string& error_details) { - c_arg_->error_details->set_error_details(error_details.c_str()); -} - -void TlsCredentialReloadArg::OnCredentialReloadDoneCallback() { - if (c_arg_->cb == nullptr) { - gpr_log(GPR_ERROR, "credential reload arg callback API is nullptr"); - return; - } - c_arg_->cb(c_arg_); -} - -/** gRPC TLS credential reload config API implementation **/ -TlsCredentialReloadConfig::TlsCredentialReloadConfig( - std::shared_ptr credential_reload_interface) - : credential_reload_interface_(std::move(credential_reload_interface)) { - c_config_ = grpc_tls_credential_reload_config_create( - nullptr, &TlsCredentialReloadConfigCSchedule, - &TlsCredentialReloadConfigCCancel, nullptr); - c_config_->set_context(static_cast(this)); -} - -TlsCredentialReloadConfig::~TlsCredentialReloadConfig() {} - /** gRPC TLS server authorization check arg API implementation **/ TlsServerAuthorizationCheckArg::TlsServerAuthorizationCheckArg( grpc_tls_server_authorization_check_arg* arg) : c_arg_(arg) { - if (c_arg_ != nullptr && c_arg_->context != nullptr) { + GPR_ASSERT(c_arg_ != nullptr); + if (c_arg_->context != nullptr) { gpr_log(GPR_ERROR, "c_arg context has already been set"); } c_arg_->context = static_cast(this); @@ -265,7 +109,6 @@ void TlsServerAuthorizationCheckArg::OnServerAuthorizationCheckDoneCallback() { c_arg_->cb(c_arg_); } -/** gRPC TLS server authorization check config API implementation. **/ TlsServerAuthorizationCheckConfig::TlsServerAuthorizationCheckConfig( std::shared_ptr server_authorization_check_interface) @@ -277,67 +120,66 @@ TlsServerAuthorizationCheckConfig::TlsServerAuthorizationCheckConfig( c_config_->set_context(static_cast(this)); } -TlsServerAuthorizationCheckConfig::~TlsServerAuthorizationCheckConfig() {} - -/** gRPC TLS credential options API implementation **/ -TlsCredentialsOptions::TlsCredentialsOptions( - grpc_tls_server_verification_option server_verification_option, - std::shared_ptr key_materials_config, - std::shared_ptr credential_reload_config, - std::shared_ptr - server_authorization_check_config) - : TlsCredentialsOptions( - GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, server_verification_option, - std::move(key_materials_config), std::move(credential_reload_config), - std::move(server_authorization_check_config)) {} - -TlsCredentialsOptions::TlsCredentialsOptions( - grpc_ssl_client_certificate_request_type cert_request_type, - std::shared_ptr key_materials_config, - std::shared_ptr credential_reload_config) - : TlsCredentialsOptions(cert_request_type, GRPC_TLS_SERVER_VERIFICATION, - std::move(key_materials_config), - std::move(credential_reload_config), nullptr) {} +TlsServerAuthorizationCheckConfig::~TlsServerAuthorizationCheckConfig() { + grpc_tls_server_authorization_check_config_release(c_config_); +} TlsCredentialsOptions::TlsCredentialsOptions( - grpc_ssl_client_certificate_request_type cert_request_type, - grpc_tls_server_verification_option server_verification_option, - std::shared_ptr key_materials_config, - std::shared_ptr credential_reload_config, - std::shared_ptr - server_authorization_check_config) - : cert_request_type_(cert_request_type), - server_verification_option_(server_verification_option), - key_materials_config_(std::move(key_materials_config)), - credential_reload_config_(std::move(credential_reload_config)), - server_authorization_check_config_( - std::move(server_authorization_check_config)) { + std::shared_ptr certificate_provider) + : certificate_provider_(std::move(certificate_provider)) { c_credentials_options_ = grpc_tls_credentials_options_create(); - grpc_tls_credentials_options_set_cert_request_type(c_credentials_options_, - cert_request_type_); - if (key_materials_config_ != nullptr) { - grpc_tls_credentials_options_set_key_materials_config( - c_credentials_options_, - ConvertToCKeyMaterialsConfig(key_materials_config_)); - } - if (credential_reload_config_ != nullptr) { - grpc_tls_credentials_options_set_credential_reload_config( - c_credentials_options_, credential_reload_config_->c_config()); + if (certificate_provider_ != nullptr) { + grpc_tls_credentials_options_set_certificate_provider( + c_credentials_options_, certificate_provider_->c_provider()); } - if (server_authorization_check_config_ != nullptr) { +} + +void TlsCredentialsOptions::watch_root_certs() { + grpc_tls_credentials_options_watch_root_certs(c_credentials_options_); +} + +void TlsCredentialsOptions::set_root_cert_name( + const std::string& root_cert_name) { + grpc_tls_credentials_options_set_root_cert_name(c_credentials_options_, + root_cert_name.c_str()); +} + +void TlsCredentialsOptions::watch_identity_key_cert_pairs() { + grpc_tls_credentials_options_watch_identity_key_cert_pairs( + c_credentials_options_); +} + +void TlsCredentialsOptions::set_identity_cert_name( + const std::string& identity_cert_name) { + grpc_tls_credentials_options_set_identity_cert_name( + c_credentials_options_, identity_cert_name.c_str()); +} + +void TlsChannelCredentialsOptions::set_server_verification_option( + grpc_tls_server_verification_option server_verification_option) { + grpc_tls_credentials_options* options = c_credentials_options(); + GPR_ASSERT(options != nullptr); + grpc_tls_credentials_options_set_server_verification_option( + options, server_verification_option); +} + +void TlsChannelCredentialsOptions::set_server_authorization_check_config( + std::shared_ptr config) { + grpc_tls_credentials_options* options = c_credentials_options(); + GPR_ASSERT(options != nullptr); + if (config != nullptr) { grpc_tls_credentials_options_set_server_authorization_check_config( - c_credentials_options_, server_authorization_check_config_->c_config()); + options, config->c_config()); } - grpc_tls_credentials_options_set_server_verification_option( - c_credentials_options_, server_verification_option); } -/** Whenever a TlsCredentialsOptions instance is created, the caller takes - * ownership of the c_credentials_options_ pointer (see e.g. the implementation - * of the TlsCredentials API in secure_credentials.cc). For this reason, the - * TlsCredentialsOptions destructor is not responsible for freeing - * c_credentials_options_. **/ -TlsCredentialsOptions::~TlsCredentialsOptions() {} +void TlsServerCredentialsOptions::set_cert_request_type( + grpc_ssl_client_certificate_request_type cert_request_type) { + grpc_tls_credentials_options* options = c_credentials_options(); + GPR_ASSERT(options != nullptr); + grpc_tls_credentials_options_set_cert_request_type(options, + cert_request_type); +} } // namespace experimental } // namespace grpc diff --git a/src/cpp/common/tls_credentials_options_util.cc b/src/cpp/common/tls_credentials_options_util.cc index 51cc4e2aefa..1cea450b0ab 100644 --- a/src/cpp/common/tls_credentials_options_util.cc +++ b/src/cpp/common/tls_credentials_options_util.cc @@ -19,85 +19,12 @@ #include "absl/container/inlined_vector.h" #include + #include "src/cpp/common/tls_credentials_options_util.h" namespace grpc { namespace experimental { -/** Converts the Cpp key materials to C key materials; this allocates memory for - * the C key materials. Note that the user must free - * the underlying pointer to private key and cert chain duplicates; they are not - * freed when the grpc_core::UniquePtr member variables of PemKeyCertPair - * are unused. Similarly, the user must free the underlying pointer to - * c_pem_root_certs. **/ -grpc_tls_key_materials_config* ConvertToCKeyMaterialsConfig( - const std::shared_ptr& config) { - if (config == nullptr) { - return nullptr; - } - grpc_tls_key_materials_config* c_config = - grpc_tls_key_materials_config_create(); - ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1> - c_pem_key_cert_pair_list; - for (const auto& key_cert_pair : config->pem_key_cert_pair_list()) { - grpc_ssl_pem_key_cert_pair* ssl_pair = - (grpc_ssl_pem_key_cert_pair*)gpr_malloc( - sizeof(grpc_ssl_pem_key_cert_pair)); - ssl_pair->private_key = gpr_strdup(key_cert_pair.private_key.c_str()); - ssl_pair->cert_chain = gpr_strdup(key_cert_pair.cert_chain.c_str()); - ::grpc_core::PemKeyCertPair c_pem_key_cert_pair = - ::grpc_core::PemKeyCertPair(ssl_pair); - c_pem_key_cert_pair_list.push_back(::std::move(c_pem_key_cert_pair)); - } - c_config->set_key_materials(config->pem_root_certs().c_str(), - c_pem_key_cert_pair_list); - c_config->set_version(config->version()); - return c_config; -} - -/** The C schedule and cancel functions for the credential reload config. - * They populate a C credential reload arg with the result of a C++ credential - * reload schedule/cancel API. **/ -int TlsCredentialReloadConfigCSchedule(void* /*config_user_data*/, - grpc_tls_credential_reload_arg* arg) { - if (arg == nullptr || arg->config == nullptr || - arg->config->context() == nullptr) { - gpr_log(GPR_ERROR, "credential reload arg was not properly initialized"); - return 1; - } - TlsCredentialReloadConfig* cpp_config = - static_cast(arg->config->context()); - TlsCredentialReloadArg* cpp_arg = new TlsCredentialReloadArg(arg); - int schedule_result = cpp_config->Schedule(cpp_arg); - return schedule_result; -} - -void TlsCredentialReloadConfigCCancel(void* /*config_user_data*/, - grpc_tls_credential_reload_arg* arg) { - if (arg == nullptr || arg->config == nullptr || - arg->config->context() == nullptr) { - gpr_log(GPR_ERROR, "credential reload arg was not properly initialized"); - return; - } - if (arg->context == nullptr) { - gpr_log(GPR_ERROR, "credential reload arg schedule has already completed"); - return; - } - TlsCredentialReloadConfig* cpp_config = - static_cast(arg->config->context()); - TlsCredentialReloadArg* cpp_arg = - static_cast(arg->context); - cpp_config->Cancel(cpp_arg); -} - -void TlsCredentialReloadArgDestroyContext(void* context) { - if (context != nullptr) { - TlsCredentialReloadArg* cpp_arg = - static_cast(context); - delete cpp_arg; - } -} - /** The C schedule and cancel functions for the server authorization check * config. They populate a C server authorization check arg with the result * of a C++ server authorization check schedule/cancel API. **/ diff --git a/src/cpp/common/tls_credentials_options_util.h b/src/cpp/common/tls_credentials_options_util.h index 4ee04d15d7f..d6247219fb7 100644 --- a/src/cpp/common/tls_credentials_options_util.h +++ b/src/cpp/common/tls_credentials_options_util.h @@ -27,29 +27,15 @@ namespace grpc { namespace experimental { -/** The following function is exposed for testing purposes. **/ -grpc_tls_key_materials_config* ConvertToCKeyMaterialsConfig( - const std::shared_ptr& config); - -/** The following 4 functions convert the user-provided schedule or cancel +/** The following 2 functions convert the user-provided schedule or cancel * functions into C style schedule or cancel functions. These are internal * functions, not meant to be accessed by the user. **/ -int TlsCredentialReloadConfigCSchedule(void* config_user_data, - grpc_tls_credential_reload_arg* arg); - -void TlsCredentialReloadConfigCCancel(void* config_user_data, - grpc_tls_credential_reload_arg* arg); - int TlsServerAuthorizationCheckConfigCSchedule( void* config_user_data, grpc_tls_server_authorization_check_arg* arg); void TlsServerAuthorizationCheckConfigCCancel( void* config_user_data, grpc_tls_server_authorization_check_arg* arg); -/** The following 2 functions cleanup data created in the above C schedule - * functions. **/ -void TlsCredentialReloadArgDestroyContext(void* context); - void TlsServerAuthorizationCheckArgDestroyContext(void* context); } // namespace experimental diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index 89b3c685b29..25a46ede88f 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -145,8 +145,7 @@ std::shared_ptr LocalServerCredentials( } std::shared_ptr TlsServerCredentials( - const grpc::experimental::TlsCredentialsOptions& options) { - grpc::GrpcLibraryCodegen init; + const grpc::experimental::TlsServerCredentialsOptions& options) { return std::shared_ptr(new SecureServerCredentials( grpc_tls_server_credentials_create(options.c_credentials_options()))); } diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 3d20756ad55..5ede540727a 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -488,6 +488,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', 'src/core/lib/security/credentials/tls/tls_credentials.cc', 'src/core/lib/security/credentials/xds/xds_credentials.cc', diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 78d57404480..9024a8e581b 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -158,18 +158,22 @@ grpc_alts_credentials_create_type grpc_alts_credentials_create_import; grpc_alts_server_credentials_create_type grpc_alts_server_credentials_create_import; grpc_local_credentials_create_type grpc_local_credentials_create_import; grpc_local_server_credentials_create_type grpc_local_server_credentials_create_import; +grpc_tls_identity_pairs_create_type grpc_tls_identity_pairs_create_import; +grpc_tls_identity_pairs_add_pair_type grpc_tls_identity_pairs_add_pair_import; +grpc_tls_identity_pairs_destroy_type grpc_tls_identity_pairs_destroy_import; +grpc_tls_certificate_provider_static_data_create_type grpc_tls_certificate_provider_static_data_create_import; +grpc_tls_certificate_provider_release_type grpc_tls_certificate_provider_release_import; grpc_tls_credentials_options_create_type grpc_tls_credentials_options_create_import; grpc_tls_credentials_options_set_cert_request_type_type grpc_tls_credentials_options_set_cert_request_type_import; grpc_tls_credentials_options_set_server_verification_option_type grpc_tls_credentials_options_set_server_verification_option_import; -grpc_tls_credentials_options_set_key_materials_config_type grpc_tls_credentials_options_set_key_materials_config_import; -grpc_tls_credentials_options_set_credential_reload_config_type grpc_tls_credentials_options_set_credential_reload_config_import; +grpc_tls_credentials_options_set_certificate_provider_type grpc_tls_credentials_options_set_certificate_provider_import; +grpc_tls_credentials_options_watch_root_certs_type grpc_tls_credentials_options_watch_root_certs_import; +grpc_tls_credentials_options_set_root_cert_name_type grpc_tls_credentials_options_set_root_cert_name_import; +grpc_tls_credentials_options_watch_identity_key_cert_pairs_type grpc_tls_credentials_options_watch_identity_key_cert_pairs_import; +grpc_tls_credentials_options_set_identity_cert_name_type grpc_tls_credentials_options_set_identity_cert_name_import; grpc_tls_credentials_options_set_server_authorization_check_config_type grpc_tls_credentials_options_set_server_authorization_check_config_import; -grpc_tls_key_materials_config_create_type grpc_tls_key_materials_config_create_import; -grpc_tls_key_materials_config_set_key_materials_type grpc_tls_key_materials_config_set_key_materials_import; -grpc_tls_key_materials_config_set_version_type grpc_tls_key_materials_config_set_version_import; -grpc_tls_key_materials_config_get_version_type grpc_tls_key_materials_config_get_version_import; -grpc_tls_credential_reload_config_create_type grpc_tls_credential_reload_config_create_import; grpc_tls_server_authorization_check_config_create_type grpc_tls_server_authorization_check_config_create_import; +grpc_tls_server_authorization_check_config_release_type grpc_tls_server_authorization_check_config_release_import; grpc_xds_credentials_create_type grpc_xds_credentials_create_import; grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import; grpc_raw_compressed_byte_buffer_create_type grpc_raw_compressed_byte_buffer_create_import; @@ -432,18 +436,22 @@ void grpc_rb_load_imports(HMODULE library) { grpc_alts_server_credentials_create_import = (grpc_alts_server_credentials_create_type) GetProcAddress(library, "grpc_alts_server_credentials_create"); grpc_local_credentials_create_import = (grpc_local_credentials_create_type) GetProcAddress(library, "grpc_local_credentials_create"); grpc_local_server_credentials_create_import = (grpc_local_server_credentials_create_type) GetProcAddress(library, "grpc_local_server_credentials_create"); + grpc_tls_identity_pairs_create_import = (grpc_tls_identity_pairs_create_type) GetProcAddress(library, "grpc_tls_identity_pairs_create"); + grpc_tls_identity_pairs_add_pair_import = (grpc_tls_identity_pairs_add_pair_type) GetProcAddress(library, "grpc_tls_identity_pairs_add_pair"); + grpc_tls_identity_pairs_destroy_import = (grpc_tls_identity_pairs_destroy_type) GetProcAddress(library, "grpc_tls_identity_pairs_destroy"); + grpc_tls_certificate_provider_static_data_create_import = (grpc_tls_certificate_provider_static_data_create_type) GetProcAddress(library, "grpc_tls_certificate_provider_static_data_create"); + grpc_tls_certificate_provider_release_import = (grpc_tls_certificate_provider_release_type) GetProcAddress(library, "grpc_tls_certificate_provider_release"); grpc_tls_credentials_options_create_import = (grpc_tls_credentials_options_create_type) GetProcAddress(library, "grpc_tls_credentials_options_create"); grpc_tls_credentials_options_set_cert_request_type_import = (grpc_tls_credentials_options_set_cert_request_type_type) GetProcAddress(library, "grpc_tls_credentials_options_set_cert_request_type"); grpc_tls_credentials_options_set_server_verification_option_import = (grpc_tls_credentials_options_set_server_verification_option_type) GetProcAddress(library, "grpc_tls_credentials_options_set_server_verification_option"); - grpc_tls_credentials_options_set_key_materials_config_import = (grpc_tls_credentials_options_set_key_materials_config_type) GetProcAddress(library, "grpc_tls_credentials_options_set_key_materials_config"); - grpc_tls_credentials_options_set_credential_reload_config_import = (grpc_tls_credentials_options_set_credential_reload_config_type) GetProcAddress(library, "grpc_tls_credentials_options_set_credential_reload_config"); + grpc_tls_credentials_options_set_certificate_provider_import = (grpc_tls_credentials_options_set_certificate_provider_type) GetProcAddress(library, "grpc_tls_credentials_options_set_certificate_provider"); + grpc_tls_credentials_options_watch_root_certs_import = (grpc_tls_credentials_options_watch_root_certs_type) GetProcAddress(library, "grpc_tls_credentials_options_watch_root_certs"); + grpc_tls_credentials_options_set_root_cert_name_import = (grpc_tls_credentials_options_set_root_cert_name_type) GetProcAddress(library, "grpc_tls_credentials_options_set_root_cert_name"); + grpc_tls_credentials_options_watch_identity_key_cert_pairs_import = (grpc_tls_credentials_options_watch_identity_key_cert_pairs_type) GetProcAddress(library, "grpc_tls_credentials_options_watch_identity_key_cert_pairs"); + grpc_tls_credentials_options_set_identity_cert_name_import = (grpc_tls_credentials_options_set_identity_cert_name_type) GetProcAddress(library, "grpc_tls_credentials_options_set_identity_cert_name"); grpc_tls_credentials_options_set_server_authorization_check_config_import = (grpc_tls_credentials_options_set_server_authorization_check_config_type) GetProcAddress(library, "grpc_tls_credentials_options_set_server_authorization_check_config"); - grpc_tls_key_materials_config_create_import = (grpc_tls_key_materials_config_create_type) GetProcAddress(library, "grpc_tls_key_materials_config_create"); - grpc_tls_key_materials_config_set_key_materials_import = (grpc_tls_key_materials_config_set_key_materials_type) GetProcAddress(library, "grpc_tls_key_materials_config_set_key_materials"); - grpc_tls_key_materials_config_set_version_import = (grpc_tls_key_materials_config_set_version_type) GetProcAddress(library, "grpc_tls_key_materials_config_set_version"); - grpc_tls_key_materials_config_get_version_import = (grpc_tls_key_materials_config_get_version_type) GetProcAddress(library, "grpc_tls_key_materials_config_get_version"); - grpc_tls_credential_reload_config_create_import = (grpc_tls_credential_reload_config_create_type) GetProcAddress(library, "grpc_tls_credential_reload_config_create"); grpc_tls_server_authorization_check_config_create_import = (grpc_tls_server_authorization_check_config_create_type) GetProcAddress(library, "grpc_tls_server_authorization_check_config_create"); + grpc_tls_server_authorization_check_config_release_import = (grpc_tls_server_authorization_check_config_release_type) GetProcAddress(library, "grpc_tls_server_authorization_check_config_release"); grpc_xds_credentials_create_import = (grpc_xds_credentials_create_type) GetProcAddress(library, "grpc_xds_credentials_create"); grpc_raw_byte_buffer_create_import = (grpc_raw_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_byte_buffer_create"); grpc_raw_compressed_byte_buffer_create_import = (grpc_raw_compressed_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_compressed_byte_buffer_create"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 91f060657fa..1079e4253ee 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -449,42 +449,54 @@ extern grpc_local_credentials_create_type grpc_local_credentials_create_import; typedef grpc_server_credentials*(*grpc_local_server_credentials_create_type)(grpc_local_connect_type type); extern grpc_local_server_credentials_create_type grpc_local_server_credentials_create_import; #define grpc_local_server_credentials_create grpc_local_server_credentials_create_import +typedef grpc_tls_identity_pairs*(*grpc_tls_identity_pairs_create_type)(); +extern grpc_tls_identity_pairs_create_type grpc_tls_identity_pairs_create_import; +#define grpc_tls_identity_pairs_create grpc_tls_identity_pairs_create_import +typedef void(*grpc_tls_identity_pairs_add_pair_type)(grpc_tls_identity_pairs* pairs, const char* private_key, const char* cert_chain); +extern grpc_tls_identity_pairs_add_pair_type grpc_tls_identity_pairs_add_pair_import; +#define grpc_tls_identity_pairs_add_pair grpc_tls_identity_pairs_add_pair_import +typedef void(*grpc_tls_identity_pairs_destroy_type)(grpc_tls_identity_pairs* pairs); +extern grpc_tls_identity_pairs_destroy_type grpc_tls_identity_pairs_destroy_import; +#define grpc_tls_identity_pairs_destroy grpc_tls_identity_pairs_destroy_import +typedef grpc_tls_certificate_provider*(*grpc_tls_certificate_provider_static_data_create_type)(const char* root_certificate, grpc_tls_identity_pairs* pem_key_cert_pairs); +extern grpc_tls_certificate_provider_static_data_create_type grpc_tls_certificate_provider_static_data_create_import; +#define grpc_tls_certificate_provider_static_data_create grpc_tls_certificate_provider_static_data_create_import +typedef void(*grpc_tls_certificate_provider_release_type)(grpc_tls_certificate_provider* provider); +extern grpc_tls_certificate_provider_release_type grpc_tls_certificate_provider_release_import; +#define grpc_tls_certificate_provider_release grpc_tls_certificate_provider_release_import typedef grpc_tls_credentials_options*(*grpc_tls_credentials_options_create_type)(void); extern grpc_tls_credentials_options_create_type grpc_tls_credentials_options_create_import; #define grpc_tls_credentials_options_create grpc_tls_credentials_options_create_import -typedef int(*grpc_tls_credentials_options_set_cert_request_type_type)(grpc_tls_credentials_options* options, grpc_ssl_client_certificate_request_type type); +typedef void(*grpc_tls_credentials_options_set_cert_request_type_type)(grpc_tls_credentials_options* options, grpc_ssl_client_certificate_request_type type); extern grpc_tls_credentials_options_set_cert_request_type_type grpc_tls_credentials_options_set_cert_request_type_import; #define grpc_tls_credentials_options_set_cert_request_type grpc_tls_credentials_options_set_cert_request_type_import -typedef int(*grpc_tls_credentials_options_set_server_verification_option_type)(grpc_tls_credentials_options* options, grpc_tls_server_verification_option server_verification_option); +typedef void(*grpc_tls_credentials_options_set_server_verification_option_type)(grpc_tls_credentials_options* options, grpc_tls_server_verification_option server_verification_option); extern grpc_tls_credentials_options_set_server_verification_option_type grpc_tls_credentials_options_set_server_verification_option_import; #define grpc_tls_credentials_options_set_server_verification_option grpc_tls_credentials_options_set_server_verification_option_import -typedef int(*grpc_tls_credentials_options_set_key_materials_config_type)(grpc_tls_credentials_options* options, grpc_tls_key_materials_config* config); -extern grpc_tls_credentials_options_set_key_materials_config_type grpc_tls_credentials_options_set_key_materials_config_import; -#define grpc_tls_credentials_options_set_key_materials_config grpc_tls_credentials_options_set_key_materials_config_import -typedef int(*grpc_tls_credentials_options_set_credential_reload_config_type)(grpc_tls_credentials_options* options, grpc_tls_credential_reload_config* config); -extern grpc_tls_credentials_options_set_credential_reload_config_type grpc_tls_credentials_options_set_credential_reload_config_import; -#define grpc_tls_credentials_options_set_credential_reload_config grpc_tls_credentials_options_set_credential_reload_config_import -typedef int(*grpc_tls_credentials_options_set_server_authorization_check_config_type)(grpc_tls_credentials_options* options, grpc_tls_server_authorization_check_config* config); +typedef void(*grpc_tls_credentials_options_set_certificate_provider_type)(grpc_tls_credentials_options* options, grpc_tls_certificate_provider* provider); +extern grpc_tls_credentials_options_set_certificate_provider_type grpc_tls_credentials_options_set_certificate_provider_import; +#define grpc_tls_credentials_options_set_certificate_provider grpc_tls_credentials_options_set_certificate_provider_import +typedef void(*grpc_tls_credentials_options_watch_root_certs_type)(grpc_tls_credentials_options* options); +extern grpc_tls_credentials_options_watch_root_certs_type grpc_tls_credentials_options_watch_root_certs_import; +#define grpc_tls_credentials_options_watch_root_certs grpc_tls_credentials_options_watch_root_certs_import +typedef void(*grpc_tls_credentials_options_set_root_cert_name_type)(grpc_tls_credentials_options* options, const char* root_cert_name); +extern grpc_tls_credentials_options_set_root_cert_name_type grpc_tls_credentials_options_set_root_cert_name_import; +#define grpc_tls_credentials_options_set_root_cert_name grpc_tls_credentials_options_set_root_cert_name_import +typedef void(*grpc_tls_credentials_options_watch_identity_key_cert_pairs_type)(grpc_tls_credentials_options* options); +extern grpc_tls_credentials_options_watch_identity_key_cert_pairs_type grpc_tls_credentials_options_watch_identity_key_cert_pairs_import; +#define grpc_tls_credentials_options_watch_identity_key_cert_pairs grpc_tls_credentials_options_watch_identity_key_cert_pairs_import +typedef void(*grpc_tls_credentials_options_set_identity_cert_name_type)(grpc_tls_credentials_options* options, const char* identity_cert_name); +extern grpc_tls_credentials_options_set_identity_cert_name_type grpc_tls_credentials_options_set_identity_cert_name_import; +#define grpc_tls_credentials_options_set_identity_cert_name grpc_tls_credentials_options_set_identity_cert_name_import +typedef void(*grpc_tls_credentials_options_set_server_authorization_check_config_type)(grpc_tls_credentials_options* options, grpc_tls_server_authorization_check_config* config); extern grpc_tls_credentials_options_set_server_authorization_check_config_type grpc_tls_credentials_options_set_server_authorization_check_config_import; #define grpc_tls_credentials_options_set_server_authorization_check_config grpc_tls_credentials_options_set_server_authorization_check_config_import -typedef grpc_tls_key_materials_config*(*grpc_tls_key_materials_config_create_type)(void); -extern grpc_tls_key_materials_config_create_type grpc_tls_key_materials_config_create_import; -#define grpc_tls_key_materials_config_create grpc_tls_key_materials_config_create_import -typedef int(*grpc_tls_key_materials_config_set_key_materials_type)(grpc_tls_key_materials_config* config, const char* pem_root_certs, const grpc_ssl_pem_key_cert_pair** pem_key_cert_pairs, size_t num_key_cert_pairs); -extern grpc_tls_key_materials_config_set_key_materials_type grpc_tls_key_materials_config_set_key_materials_import; -#define grpc_tls_key_materials_config_set_key_materials grpc_tls_key_materials_config_set_key_materials_import -typedef int(*grpc_tls_key_materials_config_set_version_type)(grpc_tls_key_materials_config* config, int version); -extern grpc_tls_key_materials_config_set_version_type grpc_tls_key_materials_config_set_version_import; -#define grpc_tls_key_materials_config_set_version grpc_tls_key_materials_config_set_version_import -typedef int(*grpc_tls_key_materials_config_get_version_type)(grpc_tls_key_materials_config* config); -extern grpc_tls_key_materials_config_get_version_type grpc_tls_key_materials_config_get_version_import; -#define grpc_tls_key_materials_config_get_version grpc_tls_key_materials_config_get_version_import -typedef grpc_tls_credential_reload_config*(*grpc_tls_credential_reload_config_create_type)(const void* config_user_data, int (*schedule)(void* config_user_data, grpc_tls_credential_reload_arg* arg), void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), void (*destruct)(void* config_user_data)); -extern grpc_tls_credential_reload_config_create_type grpc_tls_credential_reload_config_create_import; -#define grpc_tls_credential_reload_config_create grpc_tls_credential_reload_config_create_import typedef grpc_tls_server_authorization_check_config*(*grpc_tls_server_authorization_check_config_create_type)(const void* config_user_data, int (*schedule)(void* config_user_data, grpc_tls_server_authorization_check_arg* arg), void (*cancel)(void* config_user_data, grpc_tls_server_authorization_check_arg* arg), void (*destruct)(void* config_user_data)); extern grpc_tls_server_authorization_check_config_create_type grpc_tls_server_authorization_check_config_create_import; #define grpc_tls_server_authorization_check_config_create grpc_tls_server_authorization_check_config_create_import +typedef void(*grpc_tls_server_authorization_check_config_release_type)(grpc_tls_server_authorization_check_config* config); +extern grpc_tls_server_authorization_check_config_release_type grpc_tls_server_authorization_check_config_release_import; +#define grpc_tls_server_authorization_check_config_release grpc_tls_server_authorization_check_config_release_import typedef grpc_channel_credentials*(*grpc_xds_credentials_create_type)(grpc_channel_credentials* fallback_credentials); extern grpc_xds_credentials_create_type grpc_xds_credentials_create_import; #define grpc_xds_credentials_create grpc_xds_credentials_create_import diff --git a/test/core/end2end/fixtures/h2_tls.cc b/test/core/end2end/fixtures/h2_tls.cc index 8c719996474..4689cee5c91 100644 --- a/test/core/end2end/fixtures/h2_tls.cc +++ b/test/core/end2end/fixtures/h2_tls.cc @@ -50,10 +50,14 @@ struct fullstack_secure_fixture_data { for (size_t ind = 0; ind < thd_list.size(); ind++) { thd_list[ind].Join(); } + grpc_tls_certificate_provider_release(client_provider); + grpc_tls_certificate_provider_release(server_provider); } std::string localaddr; grpc_tls_version tls_version; ThreadList thd_list; + grpc_tls_certificate_provider* client_provider = nullptr; + grpc_tls_certificate_provider* server_provider = nullptr; }; static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( @@ -65,9 +69,35 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( memset(&f, 0, sizeof(f)); ffd->localaddr = grpc_core::JoinHostPort("localhost", port); ffd->tls_version = tls_version; + grpc_slice root_slice, cert_slice, key_slice; + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(CA_CERT_PATH, 1, &root_slice))); + std::string root_cert = + std::string(grpc_core::StringViewFromSlice(root_slice)); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice))); + std::string identity_cert = + std::string(grpc_core::StringViewFromSlice(cert_slice)); + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SERVER_KEY_PATH, 1, &key_slice))); + std::string private_key = + std::string(grpc_core::StringViewFromSlice(key_slice)); + grpc_tls_identity_pairs* client_pairs = grpc_tls_identity_pairs_create(); + grpc_tls_identity_pairs_add_pair(client_pairs, private_key.c_str(), + identity_cert.c_str()); + ffd->client_provider = grpc_tls_certificate_provider_static_data_create( + root_cert.c_str(), client_pairs); + grpc_tls_identity_pairs* server_pairs = grpc_tls_identity_pairs_create(); + grpc_tls_identity_pairs_add_pair(server_pairs, private_key.c_str(), + identity_cert.c_str()); + ffd->server_provider = grpc_tls_certificate_provider_static_data_create( + root_cert.c_str(), server_pairs); f.fixture_data = ffd; f.cq = grpc_completion_queue_create_for_next(nullptr); f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr); + grpc_slice_unref(root_slice); + grpc_slice_unref(cert_slice); + grpc_slice_unref(key_slice); return f; } @@ -151,82 +181,6 @@ static int server_authz_check_async( return 1; } -// Synchronous implementation of schedule field in -// grpc_tls_credential_reload_config instance that is a part of client-side -// grpc_tls_credentials_options instance. -static int client_cred_reload_sync(void* /*config_user_data*/, - grpc_tls_credential_reload_arg* arg) { - if (!arg->key_materials_config->pem_key_cert_pair_list().empty()) { - arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - return 0; - } - grpc_slice ca_slice, cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(CA_CERT_PATH, 1, &ca_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SERVER_KEY_PATH, 1, &key_slice))); - const char* ca_cert = - reinterpret_cast GRPC_SLICE_START_PTR(ca_slice); - const char* server_cert = - reinterpret_cast GRPC_SLICE_START_PTR(cert_slice); - const char* server_key = - reinterpret_cast GRPC_SLICE_START_PTR(key_slice); - grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert}; - if (arg->key_materials_config->pem_key_cert_pair_list().empty()) { - const auto* pem_key_cert_pair_ptr = &pem_key_cert_pair; - grpc_tls_key_materials_config_set_key_materials( - arg->key_materials_config, ca_cert, &pem_key_cert_pair_ptr, 1); - } - // new credential has been reloaded. - arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW; - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - grpc_slice_unref(ca_slice); - return 0; -} - -// Synchronous implementation of schedule field in -// grpc_tls_credential_reload_config instance that is a part of server-side -// grpc_tls_credentials_options instance. -static int server_cred_reload_sync(void* /*config_user_data*/, - grpc_tls_credential_reload_arg* arg) { - if (!arg->key_materials_config->pem_key_cert_pair_list().empty()) { - arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - return 0; - } - grpc_slice ca_slice, cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(CA_CERT_PATH, 1, &ca_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SERVER_KEY_PATH, 1, &key_slice))); - const char* ca_cert = - reinterpret_cast GRPC_SLICE_START_PTR(ca_slice); - const char* server_cert = - reinterpret_cast GRPC_SLICE_START_PTR(cert_slice); - const char* server_key = - reinterpret_cast GRPC_SLICE_START_PTR(key_slice); - grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert}; - GPR_ASSERT(arg != nullptr); - GPR_ASSERT(arg->key_materials_config != nullptr); - GPR_ASSERT(arg->key_materials_config->pem_key_cert_pair_list().data() != - nullptr); - if (arg->key_materials_config->pem_key_cert_pair_list().empty()) { - const auto* pem_key_cert_pair_ptr = &pem_key_cert_pair; - grpc_tls_key_materials_config_set_key_materials( - arg->key_materials_config, ca_cert, &pem_key_cert_pair_ptr, 1); - } - // new credential has been reloaded. - arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW; - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - grpc_slice_unref(ca_slice); - return 0; -} - // Create a TLS channel credential. static grpc_channel_credentials* create_tls_channel_credentials( fullstack_secure_fixture_data* ffd) { @@ -234,12 +188,11 @@ static grpc_channel_credentials* create_tls_channel_credentials( options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION); options->set_min_tls_version(ffd->tls_version); options->set_max_tls_version(ffd->tls_version); - /* Set credential reload config. */ - grpc_tls_credential_reload_config* reload_config = - grpc_tls_credential_reload_config_create(nullptr, client_cred_reload_sync, - nullptr, nullptr); - grpc_tls_credentials_options_set_credential_reload_config(options, - reload_config); + // Set credential provider. + grpc_tls_credentials_options_set_certificate_provider(options, + ffd->client_provider); + grpc_tls_credentials_options_watch_root_certs(options); + grpc_tls_credentials_options_watch_identity_key_cert_pairs(options); /* Set server authorization check config. */ grpc_tls_server_authorization_check_config* check_config = grpc_tls_server_authorization_check_config_create( @@ -248,6 +201,7 @@ static grpc_channel_credentials* create_tls_channel_credentials( options, check_config); /* Create TLS channel credentials. */ grpc_channel_credentials* creds = grpc_tls_credentials_create(options); + grpc_tls_server_authorization_check_config_release(check_config); return creds; } @@ -257,12 +211,11 @@ static grpc_server_credentials* create_tls_server_credentials( grpc_tls_credentials_options* options = grpc_tls_credentials_options_create(); options->set_min_tls_version(ffd->tls_version); options->set_max_tls_version(ffd->tls_version); - /* Set credential reload config. */ - grpc_tls_credential_reload_config* reload_config = - grpc_tls_credential_reload_config_create(nullptr, server_cred_reload_sync, - nullptr, nullptr); - grpc_tls_credentials_options_set_credential_reload_config(options, - reload_config); + // Set credential provider. + grpc_tls_credentials_options_set_certificate_provider(options, + ffd->server_provider); + grpc_tls_credentials_options_watch_root_certs(options); + grpc_tls_credentials_options_watch_identity_key_cert_pairs(options); /* Set client certificate request type. */ grpc_tls_credentials_options_set_cert_request_type( options, GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY); diff --git a/test/core/security/BUILD b/test/core/security/BUILD index 17653e6e4c0..39b095f62a3 100644 --- a/test/core/security/BUILD +++ b/test/core/security/BUILD @@ -279,6 +279,10 @@ grpc_cc_test( srcs = ["tls_security_connector_test.cc"], data = [ "//src/core/tsi/test_creds:ca.pem", + "//src/core/tsi/test_creds:multi-domain.key", + "//src/core/tsi/test_creds:multi-domain.pem", + "//src/core/tsi/test_creds:server0.key", + "//src/core/tsi/test_creds:server0.pem", "//src/core/tsi/test_creds:server1.key", "//src/core/tsi/test_creds:server1.pem", ], diff --git a/test/core/security/grpc_tls_certificate_distributor_test.cc b/test/core/security/grpc_tls_certificate_distributor_test.cc index 6c67770bffe..61be71c8ac0 100644 --- a/test/core/security/grpc_tls_certificate_distributor_test.cc +++ b/test/core/security/grpc_tls_certificate_distributor_test.cc @@ -53,8 +53,8 @@ class GrpcTlsCertificateDistributorTest : public ::testing::Test { // Forward declaration. class TlsCertificatesTestWatcher; - static grpc_tls_certificate_distributor::PemKeyCertPairList MakeCertKeyPairs( - const char* private_key, const char* certs) { + static grpc_core::PemKeyCertPairList MakeCertKeyPairs(const char* private_key, + const char* certs) { if (strcmp(private_key, "") == 0 && strcmp(certs, "") == 0) { return {}; } @@ -63,7 +63,7 @@ class GrpcTlsCertificateDistributorTest : public ::testing::Test { gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair))); ssl_pair->private_key = gpr_strdup(private_key); ssl_pair->cert_chain = gpr_strdup(certs); - grpc_tls_certificate_distributor::PemKeyCertPairList pem_key_cert_pairs; + grpc_core::PemKeyCertPairList pem_key_cert_pairs; pem_key_cert_pairs.emplace_back(ssl_pair); return pem_key_cert_pairs; } @@ -74,10 +74,8 @@ class GrpcTlsCertificateDistributorTest : public ::testing::Test { // if the status updates are correct. struct CredentialInfo { std::string root_certs; - grpc_tls_certificate_distributor::PemKeyCertPairList key_cert_pairs; - CredentialInfo( - std::string root, - grpc_tls_certificate_distributor::PemKeyCertPairList key_cert) + grpc_core::PemKeyCertPairList key_cert_pairs; + CredentialInfo(std::string root, grpc_core::PemKeyCertPairList key_cert) : root_certs(std::move(root)), key_cert_pairs(std::move(key_cert)) {} bool operator==(const CredentialInfo& other) const { return root_certs == other.root_certs && @@ -130,13 +128,12 @@ class GrpcTlsCertificateDistributorTest : public ::testing::Test { void OnCertificatesChanged( absl::optional root_certs, - absl::optional - key_cert_pairs) override { + absl::optional key_cert_pairs) override { std::string updated_root; if (root_certs.has_value()) { updated_root = std::string(*root_certs); } - grpc_tls_certificate_distributor::PemKeyCertPairList updated_identity; + grpc_core::PemKeyCertPairList updated_identity; if (key_cert_pairs.has_value()) { updated_identity = std::move(*key_cert_pairs); } diff --git a/test/core/security/grpc_tls_credentials_options_test.cc b/test/core/security/grpc_tls_credentials_options_test.cc index 630add320bb..dee1d47a92b 100644 --- a/test/core/security/grpc_tls_credentials_options_test.cc +++ b/test/core/security/grpc_tls_credentials_options_test.cc @@ -33,56 +33,6 @@ namespace testing { -static void SetKeyMaterials(grpc_tls_key_materials_config* config) { - grpc_slice ca_slice, cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(CA_CERT_PATH, 1, &ca_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SERVER_KEY_PATH, 1, &key_slice))); - const char* ca_cert = - reinterpret_cast GRPC_SLICE_START_PTR(ca_slice); - const char* server_cert = - reinterpret_cast GRPC_SLICE_START_PTR(cert_slice); - const char* server_key = - reinterpret_cast GRPC_SLICE_START_PTR(key_slice); - grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert}; - const auto* pem_key_cert_pair_ptr = &pem_key_cert_pair; - grpc_tls_key_materials_config_set_key_materials(config, ca_cert, - &pem_key_cert_pair_ptr, 1); - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - grpc_slice_unref(ca_slice); -} - -TEST(GrpcTlsCredentialsOptionsTest, SetKeyMaterials) { - grpc_tls_key_materials_config* config = - grpc_tls_key_materials_config_create(); - SetKeyMaterials(config); - grpc_slice ca_slice, cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(CA_CERT_PATH, 1, &ca_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SERVER_KEY_PATH, 1, &key_slice))); - const char* ca_cert = - reinterpret_cast GRPC_SLICE_START_PTR(ca_slice); - const char* server_cert = - reinterpret_cast GRPC_SLICE_START_PTR(cert_slice); - const char* server_key = - reinterpret_cast GRPC_SLICE_START_PTR(key_slice); - EXPECT_STREQ(config->pem_root_certs(), ca_cert); - EXPECT_EQ(config->pem_key_cert_pair_list().size(), 1); - EXPECT_STREQ(config->pem_key_cert_pair_list()[0].private_key(), server_key); - EXPECT_STREQ(config->pem_key_cert_pair_list()[0].cert_chain(), server_cert); - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - grpc_slice_unref(ca_slice); - delete config; -} - TEST(GrpcTlsCredentialsOptionsTest, ErrorDetails) { grpc_tls_error_details error_details; EXPECT_STREQ(error_details.error_details().c_str(), ""); diff --git a/test/core/security/tls_security_connector_test.cc b/test/core/security/tls_security_connector_test.cc index 694b6b66b1e..63ec2a4ec3a 100644 --- a/test/core/security/tls_security_connector_test.cc +++ b/test/core/security/tls_security_connector_test.cc @@ -27,253 +27,282 @@ #include #include "src/core/lib/iomgr/load_file.h" +#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" +#include "src/core/lib/security/credentials/tls/tls_credentials.h" #include "src/core/tsi/transport_security.h" #include "test/core/util/test_config.h" #define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem" -#define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem" -#define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key" - -namespace { - -enum CredReloadResult { FAIL, SUCCESS, UNCHANGED, ASYNC }; - -void SetKeyMaterials(grpc_tls_key_materials_config* config) { - grpc_slice ca_slice, cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(CA_CERT_PATH, 1, &ca_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SERVER_KEY_PATH, 1, &key_slice))); - const char* ca_cert = - reinterpret_cast GRPC_SLICE_START_PTR(ca_slice); - const char* server_cert = - reinterpret_cast GRPC_SLICE_START_PTR(cert_slice); - const char* server_key = - reinterpret_cast GRPC_SLICE_START_PTR(key_slice); - grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert}; - const auto* pem_key_cert_pair_ptr = &pem_key_cert_pair; - grpc_tls_key_materials_config_set_key_materials(config, ca_cert, - &pem_key_cert_pair_ptr, 1); - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - grpc_slice_unref(ca_slice); -} - -int CredReloadSuccess(void* /*config_user_data*/, - grpc_tls_credential_reload_arg* arg) { - SetKeyMaterials(arg->key_materials_config); - arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW; - return 0; -} - -int CredReloadFail(void* /*config_user_data*/, - grpc_tls_credential_reload_arg* arg) { - arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL; - return 0; -} - -int CredReloadUnchanged(void* /*config_user_data*/, - grpc_tls_credential_reload_arg* arg) { - arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - return 0; -} - -int CredReloadAsync(void* /*config_user_data*/, - grpc_tls_credential_reload_arg* /*arg*/) { - return 1; -} - -} // namespace +#define CLIENT_CERT_PATH "src/core/tsi/test_creds/multi-domain.pem" +#define SERVER_CERT_PATH_0 "src/core/tsi/test_creds/server0.pem" +#define SERVER_KEY_PATH_0 "src/core/tsi/test_creds/server0.key" +#define SERVER_CERT_PATH_1 "src/core/tsi/test_creds/server1.pem" +#define SERVER_KEY_PATH_1 "src/core/tsi/test_creds/server1.key" namespace grpc { namespace testing { +constexpr const char* kRootCertName = "root_cert_name"; +constexpr const char* kIdentityCertName = "identity_cert_name"; +constexpr const char* kErrorMessage = "error_message"; +constexpr const char* kTargetName = "some_target"; + class TlsSecurityConnectorTest : public ::testing::Test { protected: TlsSecurityConnectorTest() {} void SetUp() override { - options_ = grpc_tls_credentials_options_create()->Ref(); - config_ = grpc_tls_key_materials_config_create()->Ref(); - } - void TearDown() override { config_->Unref(); } - // Set credential reload config in options. - void SetOptions(CredReloadResult type) { - grpc_tls_credential_reload_config* reload_config = nullptr; - switch (type) { - case SUCCESS: - reload_config = grpc_tls_credential_reload_config_create( - nullptr, CredReloadSuccess, nullptr, nullptr); - break; - case FAIL: - reload_config = grpc_tls_credential_reload_config_create( - nullptr, CredReloadFail, nullptr, nullptr); - break; - case UNCHANGED: - reload_config = grpc_tls_credential_reload_config_create( - nullptr, CredReloadUnchanged, nullptr, nullptr); - break; - case ASYNC: - reload_config = grpc_tls_credential_reload_config_create( - nullptr, CredReloadAsync, nullptr, nullptr); - break; - default: - break; - } - grpc_tls_credentials_options_set_credential_reload_config(options_.get(), - reload_config); + grpc_slice ca_slice_1, ca_slice_0, cert_slice_1, key_slice_1, cert_slice_0, + key_slice_0; + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(CA_CERT_PATH, 1, &ca_slice_1))); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(CLIENT_CERT_PATH, 1, &ca_slice_0))); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(SERVER_CERT_PATH_1, 1, &cert_slice_1))); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(SERVER_KEY_PATH_1, 1, &key_slice_1))); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(SERVER_CERT_PATH_0, 1, &cert_slice_0))); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(SERVER_KEY_PATH_0, 1, &key_slice_0))); + root_cert_1_ = std::string(grpc_core::StringViewFromSlice(ca_slice_1)); + root_cert_0_ = std::string(grpc_core::StringViewFromSlice(ca_slice_0)); + std::string identity_key_1 = + std::string(grpc_core::StringViewFromSlice(key_slice_1)); + std::string identity_key_0 = + std::string(grpc_core::StringViewFromSlice(key_slice_0)); + std::string identity_cert_1 = + std::string(grpc_core::StringViewFromSlice(cert_slice_1)); + std::string identity_cert_0 = + std::string(grpc_core::StringViewFromSlice(cert_slice_0)); + grpc_ssl_pem_key_cert_pair* ssl_pair_1 = + static_cast( + gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair))); + ssl_pair_1->private_key = gpr_strdup(identity_key_1.c_str()); + ssl_pair_1->cert_chain = gpr_strdup(identity_cert_1.c_str()); + identity_pairs_1_.emplace_back(ssl_pair_1); + grpc_ssl_pem_key_cert_pair* ssl_pair_0 = + static_cast( + gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair))); + ssl_pair_0->private_key = gpr_strdup(identity_key_0.c_str()); + ssl_pair_0->cert_chain = gpr_strdup(identity_cert_0.c_str()); + identity_pairs_0_.emplace_back(ssl_pair_0); + grpc_slice_unref(ca_slice_1); + grpc_slice_unref(ca_slice_0); + grpc_slice_unref(cert_slice_1); + grpc_slice_unref(key_slice_1); + grpc_slice_unref(cert_slice_0); + grpc_slice_unref(key_slice_0); } - // Set key materials config. - void SetKeyMaterialsConfig() { SetKeyMaterials(config_.get()); } - grpc_core::RefCountedPtr options_; - grpc_core::RefCountedPtr config_; -}; -TEST_F(TlsSecurityConnectorTest, NoKeysAndConfig) { - grpc_ssl_certificate_config_reload_status reload_status; - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, true, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_FAILED_PRECONDITION); - options_->Unref(); -} + void TearDown() override {} -TEST_F(TlsSecurityConnectorTest, NoKeysAndConfigAsAClient) { - grpc_ssl_certificate_config_reload_status reload_status; - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, false, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_OK); - options_->Unref(); -} - -TEST_F(TlsSecurityConnectorTest, NoKeySuccessReload) { - grpc_ssl_certificate_config_reload_status reload_status; - SetOptions(SUCCESS); - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, true, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_OK); - EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW); - options_->Unref(); -} - -TEST_F(TlsSecurityConnectorTest, NoKeyFailReload) { - grpc_ssl_certificate_config_reload_status reload_status; - SetOptions(FAIL); - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, true, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_INTERNAL); - EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL); - options_->Unref(); -} - -TEST_F(TlsSecurityConnectorTest, NoKeyAsyncReload) { - grpc_ssl_certificate_config_reload_status reload_status = - GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - SetOptions(ASYNC); - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, true, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_UNIMPLEMENTED); - EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED); - options_->Unref(); -} - -TEST_F(TlsSecurityConnectorTest, NoKeyUnchangedReload) { - grpc_ssl_certificate_config_reload_status reload_status = - GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - SetOptions(UNCHANGED); - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, true, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_OK); - EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED); - options_->Unref(); -} + std::string root_cert_1_; + std::string root_cert_0_; + grpc_core::PemKeyCertPairList identity_pairs_1_; + grpc_core::PemKeyCertPairList identity_pairs_0_; +}; -TEST_F(TlsSecurityConnectorTest, WithKeyNoReload) { - grpc_ssl_certificate_config_reload_status reload_status = - GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - SetKeyMaterialsConfig(); - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, true, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_OK); - options_->Unref(); -} +class TlsTestCertificateProvider : public ::grpc_tls_certificate_provider { + public: + explicit TlsTestCertificateProvider( + grpc_core::RefCountedPtr distributor) + : distributor_(std::move(distributor)) {} + ~TlsTestCertificateProvider() override {} + grpc_core::RefCountedPtr distributor() + const override { + return distributor_; + } -TEST_F(TlsSecurityConnectorTest, WithKeySuccessReload) { - grpc_ssl_certificate_config_reload_status reload_status; - SetOptions(SUCCESS); - SetKeyMaterialsConfig(); - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, true, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_OK); - EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW); - options_->Unref(); -} + private: + grpc_core::RefCountedPtr distributor_; +}; -TEST_F(TlsSecurityConnectorTest, WithKeyFailReload) { - grpc_ssl_certificate_config_reload_status reload_status; - SetOptions(FAIL); - SetKeyMaterialsConfig(); - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, true, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_OK); - EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL); - options_->Unref(); +// Tests for ChannelSecurityConnector. +TEST_F(TlsSecurityConnectorTest, + RootAndIdentityCertsObtainedWhenCreateChannelSecurityConnector) { + grpc_core::RefCountedPtr distributor = + grpc_core::MakeRefCounted(); + distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt); + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_0_); + grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider = + grpc_core::MakeRefCounted(distributor); + grpc_core::RefCountedPtr options = + grpc_core::MakeRefCounted(); + options->set_certificate_provider(provider); + options->set_watch_root_cert(true); + options->set_watch_identity_pair(true); + options->set_root_cert_name(kRootCertName); + options->set_identity_cert_name(kIdentityCertName); + grpc_core::RefCountedPtr credential = + grpc_core::MakeRefCounted(options); + grpc_channel_args* new_args = nullptr; + grpc_core::RefCountedPtr connector = + credential->create_security_connector(nullptr, kTargetName, nullptr, + &new_args); + EXPECT_NE(connector, nullptr); + grpc_core::TlsChannelSecurityConnector* tls_connector = + static_cast(connector.get()); + EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_0_); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_0_); + distributor->SetKeyMaterials(kRootCertName, root_cert_1_, absl::nullopt); + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_1_); + EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_1_); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_1_); + grpc_channel_args_destroy(new_args); } -TEST_F(TlsSecurityConnectorTest, WithKeyAsyncReload) { - grpc_ssl_certificate_config_reload_status reload_status = - GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - SetOptions(ASYNC); - SetKeyMaterialsConfig(); - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, true, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_OK); - EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED); - options_->Unref(); +// Note that on client side, we don't have tests watching identity certs only, +// because in TLS, the trust certs should always be presented. If we don't +// provide, it will try to load certs from some default system locations, and +// will hence fail on some systems. +TEST_F(TlsSecurityConnectorTest, + RootCertsObtainedWhenCreateChannelSecurityConnector) { + grpc_core::RefCountedPtr distributor = + grpc_core::MakeRefCounted(); + distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt); + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_0_); + grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider = + grpc_core::MakeRefCounted(distributor); + // Create options only watching for root certificates. + grpc_core::RefCountedPtr root_options = + grpc_core::MakeRefCounted(); + root_options->set_certificate_provider(provider); + root_options->set_watch_root_cert(true); + root_options->set_root_cert_name(kRootCertName); + grpc_core::RefCountedPtr root_credential = + grpc_core::MakeRefCounted(root_options); + grpc_channel_args* root_new_args = nullptr; + grpc_core::RefCountedPtr root_connector = + root_credential->create_security_connector(nullptr, "some_target", + nullptr, &root_new_args); + EXPECT_NE(root_connector, nullptr); + grpc_core::TlsChannelSecurityConnector* tls_root_connector = + static_cast( + root_connector.get()); + EXPECT_NE(tls_root_connector->ClientHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_root_connector->RootCertsForTesting(), root_cert_0_); + distributor->SetKeyMaterials(kRootCertName, root_cert_1_, absl::nullopt); + EXPECT_NE(tls_root_connector->ClientHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_root_connector->RootCertsForTesting(), root_cert_1_); + grpc_channel_args_destroy(root_new_args); } -TEST_F(TlsSecurityConnectorTest, WithKeyUnchangedReload) { - grpc_ssl_certificate_config_reload_status reload_status = - GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - SetOptions(UNCHANGED); - SetKeyMaterialsConfig(); - grpc_status_code status = - TlsFetchKeyMaterials(config_, *options_, true, &reload_status); - EXPECT_EQ(status, GRPC_STATUS_OK); - EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED); - options_->Unref(); +TEST_F(TlsSecurityConnectorTest, + CertPartiallyObtainedWhenCreateChannelSecurityConnector) { + grpc_core::RefCountedPtr distributor = + grpc_core::MakeRefCounted(); + distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt); + grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider = + grpc_core::MakeRefCounted(distributor); + // Registered the options watching both certs, but only root certs are + // available at distributor right now. + grpc_core::RefCountedPtr options = + grpc_core::MakeRefCounted(); + options->set_certificate_provider(provider); + options->set_watch_root_cert(true); + options->set_watch_identity_pair(true); + options->set_root_cert_name(kRootCertName); + options->set_identity_cert_name(kIdentityCertName); + grpc_core::RefCountedPtr credential = + grpc_core::MakeRefCounted(options); + grpc_channel_args* new_args = nullptr; + grpc_core::RefCountedPtr connector = + credential->create_security_connector(nullptr, kTargetName, nullptr, + &new_args); + EXPECT_NE(connector, nullptr); + grpc_core::TlsChannelSecurityConnector* tls_connector = + static_cast(connector.get()); + // The client_handshaker_factory_ shouldn't be updated. + EXPECT_EQ(tls_connector->ClientHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_0_); + // After updating the root certs, the client_handshaker_factory_ should be + // updated. + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_0_); + EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_0_); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_0_); + grpc_channel_args_destroy(new_args); } -TEST_F(TlsSecurityConnectorTest, CreateChannelSecurityConnectorSuccess) { - SetOptions(SUCCESS); - auto cred = std::unique_ptr( - grpc_tls_credentials_create(options_.get())); - const char* target_name = "some_target"; +TEST_F(TlsSecurityConnectorTest, + DistributorHasErrorForChannelSecurityConnector) { + grpc_core::RefCountedPtr distributor = + grpc_core::MakeRefCounted(); + distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt); + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_0_); + grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider = + grpc_core::MakeRefCounted(distributor); + grpc_core::RefCountedPtr options = + grpc_core::MakeRefCounted(); + options->set_certificate_provider(provider); + options->set_watch_root_cert(true); + options->set_watch_identity_pair(true); + options->set_root_cert_name(kRootCertName); + options->set_identity_cert_name(kIdentityCertName); + grpc_core::RefCountedPtr credential = + grpc_core::MakeRefCounted(options); grpc_channel_args* new_args = nullptr; - auto connector = - cred->create_security_connector(nullptr, target_name, nullptr, &new_args); + grpc_core::RefCountedPtr connector = + credential->create_security_connector(nullptr, kTargetName, nullptr, + &new_args); EXPECT_NE(connector, nullptr); + grpc_core::TlsChannelSecurityConnector* tls_connector = + static_cast(connector.get()); + EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_0_); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_0_); + // Calling SetErrorForCert on distributor shouldn't invalidate the previous + // valid credentials. + distributor->SetErrorForCert( + kRootCertName, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kErrorMessage), + absl::nullopt); + distributor->SetErrorForCert( + kIdentityCertName, absl::nullopt, + GRPC_ERROR_CREATE_FROM_STATIC_STRING(kErrorMessage)); + EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_0_); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_0_); grpc_channel_args_destroy(new_args); } TEST_F(TlsSecurityConnectorTest, CreateChannelSecurityConnectorFailNoTargetName) { - SetOptions(SUCCESS); - auto cred = std::unique_ptr( - grpc_tls_credentials_create(options_.get())); + grpc_core::RefCountedPtr options = + grpc_core::MakeRefCounted(); + grpc_core::RefCountedPtr credential = + grpc_core::MakeRefCounted(options); grpc_channel_args* new_args = nullptr; + grpc_core::RefCountedPtr connector = + credential->create_security_connector(nullptr, nullptr, nullptr, + &new_args); + EXPECT_EQ(connector, nullptr); +} + +TEST_F(TlsSecurityConnectorTest, + CreateChannelSecurityConnectorFailNoCredentials) { auto connector = - cred->create_security_connector(nullptr, nullptr, nullptr, &new_args); + grpc_core::TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector( + nullptr, grpc_core::MakeRefCounted(), + nullptr, kTargetName, nullptr, nullptr); EXPECT_EQ(connector, nullptr); } -TEST_F(TlsSecurityConnectorTest, CreateChannelSecurityConnectorFailInit) { - SetOptions(FAIL); - auto cred = std::unique_ptr( - grpc_tls_credentials_create(options_.get())); - grpc_channel_args* new_args = nullptr; +TEST_F(TlsSecurityConnectorTest, CreateChannelSecurityConnectorFailNoOptions) { + grpc_core::RefCountedPtr options = + grpc_core::MakeRefCounted(); + grpc_core::RefCountedPtr credential = + grpc_core::MakeRefCounted(options); auto connector = - cred->create_security_connector(nullptr, nullptr, nullptr, &new_args); + grpc_core::TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector( + credential, nullptr, nullptr, kTargetName, nullptr, nullptr); EXPECT_EQ(connector, nullptr); } @@ -284,11 +313,10 @@ TEST_F(TlsSecurityConnectorTest, TlsCheckHostNameSuccess) { GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, target_name, &peer.properties[0]) == TSI_OK); - grpc_error* error = grpc_core::TlsCheckHostName(target_name, &peer); + grpc_error* error = grpc_core::internal::TlsCheckHostName(target_name, &peer); tsi_peer_destruct(&peer); EXPECT_EQ(error, GRPC_ERROR_NONE); GRPC_ERROR_UNREF(error); - options_->Unref(); } TEST_F(TlsSecurityConnectorTest, TlsCheckHostNameFail) { @@ -299,26 +327,176 @@ TEST_F(TlsSecurityConnectorTest, TlsCheckHostNameFail) { GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, another_name, &peer.properties[0]) == TSI_OK); - grpc_error* error = grpc_core::TlsCheckHostName(target_name, &peer); + grpc_error* error = grpc_core::internal::TlsCheckHostName(target_name, &peer); tsi_peer_destruct(&peer); EXPECT_NE(error, GRPC_ERROR_NONE); GRPC_ERROR_UNREF(error); - options_->Unref(); } -TEST_F(TlsSecurityConnectorTest, CreateServerSecurityConnectorSuccess) { - SetOptions(SUCCESS); - auto cred = std::unique_ptr( - grpc_tls_server_credentials_create(options_.get())); - auto connector = cred->create_security_connector(); +// Tests for ServerSecurityConnector. +TEST_F(TlsSecurityConnectorTest, + RootAndIdentityCertsObtainedWhenCreateServerSecurityConnector) { + grpc_core::RefCountedPtr distributor = + grpc_core::MakeRefCounted(); + distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt); + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_0_); + grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider = + grpc_core::MakeRefCounted(distributor); + grpc_core::RefCountedPtr options = + grpc_core::MakeRefCounted(); + options->set_certificate_provider(provider); + options->set_watch_root_cert(true); + options->set_watch_identity_pair(true); + options->set_root_cert_name(kRootCertName); + options->set_identity_cert_name(kIdentityCertName); + grpc_core::RefCountedPtr credential = + grpc_core::MakeRefCounted(options); + grpc_core::RefCountedPtr connector = + credential->create_security_connector(); + EXPECT_NE(connector, nullptr); + grpc_core::TlsServerSecurityConnector* tls_connector = + static_cast(connector.get()); + EXPECT_NE(tls_connector->ServerHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_0_); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_0_); + distributor->SetKeyMaterials(kRootCertName, root_cert_1_, absl::nullopt); + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_1_); + EXPECT_NE(tls_connector->ServerHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_1_); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_1_); +} + +// Note that on server side, we don't have tests watching root certs only, +// because in TLS, the identity certs should always be presented. If we don't +// provide, it will try to load certs from some default system locations, and +// will hence fail on some systems. +TEST_F(TlsSecurityConnectorTest, + IdentityCertsObtainedWhenCreateServerSecurityConnector) { + grpc_core::RefCountedPtr distributor = + grpc_core::MakeRefCounted(); + distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt); + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_0_); + grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider = + grpc_core::MakeRefCounted(distributor); + // Create options only watching for identity certificates. + grpc_core::RefCountedPtr identity_options = + grpc_core::MakeRefCounted(); + identity_options->set_certificate_provider(provider); + identity_options->set_watch_identity_pair(true); + identity_options->set_identity_cert_name(kIdentityCertName); + grpc_core::RefCountedPtr identity_credential = + grpc_core::MakeRefCounted(identity_options); + grpc_core::RefCountedPtr identity_connector = + identity_credential->create_security_connector(); + EXPECT_NE(identity_connector, nullptr); + grpc_core::TlsServerSecurityConnector* tls_identity_connector = + static_cast( + identity_connector.get()); + EXPECT_NE(tls_identity_connector->ServerHandshakerFactoryForTesting(), + nullptr); + EXPECT_EQ(tls_identity_connector->KeyCertPairListForTesting(), + identity_pairs_0_); + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_1_); + EXPECT_NE(tls_identity_connector->ServerHandshakerFactoryForTesting(), + nullptr); + EXPECT_EQ(tls_identity_connector->KeyCertPairListForTesting(), + identity_pairs_1_); +} + +TEST_F(TlsSecurityConnectorTest, + CertPartiallyObtainedWhenCreateServerSecurityConnector) { + grpc_core::RefCountedPtr distributor = + grpc_core::MakeRefCounted(); + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_0_); + grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider = + grpc_core::MakeRefCounted(distributor); + // Registered the options watching both certs, but only root certs are + // available at distributor right now. + grpc_core::RefCountedPtr options = + grpc_core::MakeRefCounted(); + options->set_certificate_provider(provider); + options->set_watch_root_cert(true); + options->set_watch_identity_pair(true); + options->set_root_cert_name(kRootCertName); + options->set_identity_cert_name(kIdentityCertName); + grpc_core::RefCountedPtr credential = + grpc_core::MakeRefCounted(options); + grpc_core::RefCountedPtr connector = + credential->create_security_connector(); + EXPECT_NE(connector, nullptr); + grpc_core::TlsServerSecurityConnector* tls_connector = + static_cast(connector.get()); + // The server_handshaker_factory_ shouldn't be updated. + EXPECT_EQ(tls_connector->ServerHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_0_); + // After updating the root certs, the server_handshaker_factory_ should be + // updated. + distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt); + EXPECT_NE(tls_connector->ServerHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_0_); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_0_); +} + +TEST_F(TlsSecurityConnectorTest, + DistributorHasErrorForServerSecurityConnector) { + grpc_core::RefCountedPtr distributor = + grpc_core::MakeRefCounted(); + distributor->SetKeyMaterials(kRootCertName, root_cert_0_, absl::nullopt); + distributor->SetKeyMaterials(kIdentityCertName, absl::nullopt, + identity_pairs_0_); + grpc_core::RefCountedPtr<::grpc_tls_certificate_provider> provider = + grpc_core::MakeRefCounted(distributor); + grpc_core::RefCountedPtr options = + grpc_core::MakeRefCounted(); + options->set_certificate_provider(provider); + options->set_watch_root_cert(true); + options->set_watch_identity_pair(true); + options->set_root_cert_name(kRootCertName); + options->set_identity_cert_name(kIdentityCertName); + grpc_core::RefCountedPtr credential = + grpc_core::MakeRefCounted(options); + grpc_core::RefCountedPtr connector = + credential->create_security_connector(); EXPECT_NE(connector, nullptr); + grpc_core::TlsServerSecurityConnector* tls_connector = + static_cast(connector.get()); + EXPECT_NE(tls_connector->ServerHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_0_); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_0_); + // Calling SetErrorForCert on distributor shouldn't invalidate the previous + // valid credentials. + distributor->SetErrorForCert( + kRootCertName, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kErrorMessage), + absl::nullopt); + distributor->SetErrorForCert( + kIdentityCertName, absl::nullopt, + GRPC_ERROR_CREATE_FROM_STATIC_STRING(kErrorMessage)); + EXPECT_NE(tls_connector->ServerHandshakerFactoryForTesting(), nullptr); + EXPECT_EQ(tls_connector->RootCertsForTesting(), root_cert_0_); + EXPECT_EQ(tls_connector->KeyCertPairListForTesting(), identity_pairs_0_); +} + +TEST_F(TlsSecurityConnectorTest, + CreateServerSecurityConnectorFailNoCredentials) { + auto connector = + grpc_core::TlsServerSecurityConnector::CreateTlsServerSecurityConnector( + nullptr, grpc_core::MakeRefCounted()); + EXPECT_EQ(connector, nullptr); } -TEST_F(TlsSecurityConnectorTest, CreateServerSecurityConnectorFailInit) { - SetOptions(FAIL); - auto cred = std::unique_ptr( - grpc_tls_server_credentials_create(options_.get())); - auto connector = cred->create_security_connector(); +TEST_F(TlsSecurityConnectorTest, CreateServerSecurityConnectorFailNoOptions) { + grpc_core::RefCountedPtr options = + grpc_core::MakeRefCounted(); + grpc_core::RefCountedPtr credential = + grpc_core::MakeRefCounted(options); + auto connector = + grpc_core::TlsServerSecurityConnector::CreateTlsServerSecurityConnector( + credential, nullptr); EXPECT_EQ(connector, nullptr); } diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 11d3fdce2af..4b821bebec1 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -202,18 +202,22 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_alts_server_credentials_create); printf("%lx", (unsigned long) grpc_local_credentials_create); printf("%lx", (unsigned long) grpc_local_server_credentials_create); + printf("%lx", (unsigned long) grpc_tls_identity_pairs_create); + printf("%lx", (unsigned long) grpc_tls_identity_pairs_add_pair); + printf("%lx", (unsigned long) grpc_tls_identity_pairs_destroy); + printf("%lx", (unsigned long) grpc_tls_certificate_provider_static_data_create); + printf("%lx", (unsigned long) grpc_tls_certificate_provider_release); printf("%lx", (unsigned long) grpc_tls_credentials_options_create); printf("%lx", (unsigned long) grpc_tls_credentials_options_set_cert_request_type); printf("%lx", (unsigned long) grpc_tls_credentials_options_set_server_verification_option); - printf("%lx", (unsigned long) grpc_tls_credentials_options_set_key_materials_config); - printf("%lx", (unsigned long) grpc_tls_credentials_options_set_credential_reload_config); + printf("%lx", (unsigned long) grpc_tls_credentials_options_set_certificate_provider); + printf("%lx", (unsigned long) grpc_tls_credentials_options_watch_root_certs); + printf("%lx", (unsigned long) grpc_tls_credentials_options_set_root_cert_name); + printf("%lx", (unsigned long) grpc_tls_credentials_options_watch_identity_key_cert_pairs); + printf("%lx", (unsigned long) grpc_tls_credentials_options_set_identity_cert_name); printf("%lx", (unsigned long) grpc_tls_credentials_options_set_server_authorization_check_config); - printf("%lx", (unsigned long) grpc_tls_key_materials_config_create); - printf("%lx", (unsigned long) grpc_tls_key_materials_config_set_key_materials); - printf("%lx", (unsigned long) grpc_tls_key_materials_config_set_version); - printf("%lx", (unsigned long) grpc_tls_key_materials_config_get_version); - printf("%lx", (unsigned long) grpc_tls_credential_reload_config_create); printf("%lx", (unsigned long) grpc_tls_server_authorization_check_config_create); + printf("%lx", (unsigned long) grpc_tls_server_authorization_check_config_release); printf("%lx", (unsigned long) grpc_xds_credentials_create); printf("%lx", (unsigned long) grpc_raw_byte_buffer_create); printf("%lx", (unsigned long) grpc_raw_compressed_byte_buffer_create); diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc index 9d6d25b21e5..0d9eaf01e5c 100644 --- a/test/cpp/client/credentials_test.cc +++ b/test/cpp/client/credentials_test.cc @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -28,45 +29,21 @@ #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/tmpfile.h" -#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" #include "src/cpp/client/secure_credentials.h" #include "src/cpp/common/tls_credentials_options_util.h" namespace { -typedef class ::grpc::experimental::TlsKeyMaterialsConfig TlsKeyMaterialsConfig; -typedef class ::grpc::experimental::TlsCredentialReloadArg - TlsCredentialReloadArg; -typedef struct ::grpc::experimental::TlsCredentialReloadInterface - TlsCredentialReloadInterface; -typedef class ::grpc::experimental::TlsServerAuthorizationCheckArg - TlsServerAuthorizationCheckArg; -typedef struct ::grpc::experimental::TlsServerAuthorizationCheckInterface - TlsServerAuthorizationCheckInterface; - -static void tls_credential_reload_callback( - grpc_tls_credential_reload_arg* arg) { - GPR_ASSERT(arg != nullptr); - arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; -} +constexpr const char* kRootCertName = "root_cert_name"; +constexpr const char* kRootCertContents = "root_cert_contents"; +constexpr const char* kIdentityCertName = "identity_cert_name"; +constexpr const char* kIdentityCertPrivateKey = "identity_private_key"; +constexpr const char* kIdentityCertContents = "identity_cert_contents"; -class TestTlsCredentialReload : public TlsCredentialReloadInterface { - int Schedule(TlsCredentialReloadArg* arg) override { - GPR_ASSERT(arg != nullptr); - TlsKeyMaterialsConfig::PemKeyCertPair pair = {"private_key3", - "cert_chain3"}; - arg->set_pem_root_certs("new_pem_root_certs"); - arg->add_pem_key_cert_pair(pair); - arg->set_status(GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW); - return 0; - } - - void Cancel(TlsCredentialReloadArg* arg) override { - GPR_ASSERT(arg != nullptr); - arg->set_status(GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL); - arg->set_error_details("cancelled"); - } -}; +using ::grpc::experimental::StaticDataCertificateProvider; +using ::grpc::experimental::TlsServerAuthorizationCheckArg; +using ::grpc::experimental::TlsServerAuthorizationCheckConfig; +using ::grpc::experimental::TlsServerAuthorizationCheckInterface; static void tls_server_authorization_check_callback( grpc_tls_server_authorization_check_arg* arg) { @@ -104,21 +81,18 @@ class TestTlsServerAuthorizationCheck namespace grpc { namespace testing { +namespace { -class CredentialsTest : public ::testing::Test { - protected: -}; - -TEST_F(CredentialsTest, InvalidGoogleRefreshToken) { +TEST(CredentialsTest, InvalidGoogleRefreshToken) { std::shared_ptr bad1 = GoogleRefreshTokenCredentials(""); EXPECT_EQ(static_cast(nullptr), bad1.get()); } -TEST_F(CredentialsTest, DefaultCredentials) { +TEST(CredentialsTest, DefaultCredentials) { auto creds = GoogleDefaultCredentials(); } -TEST_F(CredentialsTest, StsCredentialsOptionsCppToCore) { +TEST(CredentialsTest, StsCredentialsOptionsCppToCore) { grpc::experimental::StsCredentialsOptions options; options.token_exchange_service_uri = "https://foo.com/exchange"; options.resource = "resource"; @@ -143,7 +117,7 @@ TEST_F(CredentialsTest, StsCredentialsOptionsCppToCore) { EXPECT_EQ(options.actor_token_type, core_opts.actor_token_type); } -TEST_F(CredentialsTest, StsCredentialsOptionsJson) { +TEST(CredentialsTest, StsCredentialsOptionsJson) { const char valid_json[] = R"( { "token_exchange_service_uri": "https://foo/exchange", @@ -231,7 +205,7 @@ TEST_F(CredentialsTest, StsCredentialsOptionsJson) { ::testing::HasSubstr("token_exchange_service_uri")); } -TEST_F(CredentialsTest, StsCredentialsOptionsFromEnv) { +TEST(CredentialsTest, StsCredentialsOptionsFromEnv) { // Unset env and check expected failure. gpr_unsetenv("STS_CREDENTIALS"); grpc::experimental::StsCredentialsOptions options; @@ -270,173 +244,7 @@ TEST_F(CredentialsTest, StsCredentialsOptionsFromEnv) { gpr_unsetenv("STS_CREDENTIALS"); } -typedef class ::grpc::experimental::TlsKeyMaterialsConfig TlsKeyMaterialsConfig; - -TEST_F(CredentialsTest, TlsKeyMaterialsConfigCppToC) { - std::shared_ptr config(new TlsKeyMaterialsConfig()); - struct TlsKeyMaterialsConfig::PemKeyCertPair pair = {"private_key", - "cert_chain"}; - std::vector pair_list = {pair}; - config->set_key_materials("pem_root_certs", pair_list); - grpc_tls_key_materials_config* c_config = - ConvertToCKeyMaterialsConfig(config); - EXPECT_STREQ("pem_root_certs", c_config->pem_root_certs()); - EXPECT_EQ(1, static_cast(c_config->pem_key_cert_pair_list().size())); - EXPECT_STREQ(pair.private_key.c_str(), - c_config->pem_key_cert_pair_list()[0].private_key()); - EXPECT_STREQ(pair.cert_chain.c_str(), - c_config->pem_key_cert_pair_list()[0].cert_chain()); - delete c_config; -} - -TEST_F(CredentialsTest, TlsKeyMaterialsModifiers) { - std::shared_ptr config(new TlsKeyMaterialsConfig()); - TlsKeyMaterialsConfig::PemKeyCertPair pair = {"private_key", "cert_chain"}; - config->add_pem_key_cert_pair(pair); - config->set_pem_root_certs("pem_root_certs"); - EXPECT_STREQ(config->pem_root_certs().c_str(), "pem_root_certs"); - std::vector list = - config->pem_key_cert_pair_list(); - EXPECT_EQ(static_cast(list.size()), 1); - EXPECT_STREQ(list[0].private_key.c_str(), "private_key"); - EXPECT_STREQ(list[0].cert_chain.c_str(), "cert_chain"); -} - -typedef class ::grpc::experimental::TlsCredentialReloadArg - TlsCredentialReloadArg; -typedef class ::grpc::experimental::TlsCredentialReloadConfig - TlsCredentialReloadConfig; - -TEST_F(CredentialsTest, TlsCredentialReloadArgCallback) { - grpc_tls_credential_reload_arg* c_arg = new grpc_tls_credential_reload_arg; - c_arg->key_materials_config = grpc_tls_key_materials_config_create(); - c_arg->cb = tls_credential_reload_callback; - c_arg->context = nullptr; - TlsCredentialReloadArg* arg = new TlsCredentialReloadArg(c_arg); - arg->set_pem_root_certs("pem_root_certs"); - TlsKeyMaterialsConfig::PemKeyCertPair pair = {"private_key", "cert_chain"}; - arg->add_pem_key_cert_pair(pair); - arg->set_status(GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW); - arg->OnCredentialReloadDoneCallback(); - EXPECT_EQ(arg->status(), GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED); - EXPECT_STREQ(c_arg->key_materials_config->pem_root_certs(), "pem_root_certs"); - EXPECT_EQ(c_arg->key_materials_config->pem_key_cert_pair_list().size(), 1); - EXPECT_STREQ( - c_arg->key_materials_config->pem_key_cert_pair_list()[0].private_key(), - "private_key"); - EXPECT_STREQ( - c_arg->key_materials_config->pem_key_cert_pair_list()[0].cert_chain(), - "cert_chain"); - - // Cleanup. - delete arg; - delete c_arg->key_materials_config; - delete c_arg; -} - -TEST_F(CredentialsTest, TlsCredentialReloadConfigSchedule) { - std::shared_ptr test_credential_reload( - new TestTlsCredentialReload()); - std::shared_ptr config( - new TlsCredentialReloadConfig(test_credential_reload)); - grpc_tls_credential_reload_arg* c_arg = new grpc_tls_credential_reload_arg(); - c_arg->error_details = new grpc_tls_error_details(); - c_arg->context = nullptr; - TlsCredentialReloadArg* arg = new TlsCredentialReloadArg(c_arg); - struct TlsKeyMaterialsConfig::PemKeyCertPair pair1 = {"private_key1", - "cert_chain1"}; - struct TlsKeyMaterialsConfig::PemKeyCertPair pair2 = {"private_key2", - "cert_chain2"}; - std::vector pair_list = {pair1, pair2}; - arg->set_key_materials("pem_root_certs", pair_list); - arg->set_status(GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW); - arg->set_error_details("error_details"); - - int schedule_output = config->Schedule(arg); - EXPECT_EQ(schedule_output, 0); - EXPECT_STREQ(c_arg->key_materials_config->pem_root_certs(), - "new_pem_root_certs"); - grpc_tls_key_materials_config::PemKeyCertPairList c_pair_list = - c_arg->key_materials_config->pem_key_cert_pair_list(); - EXPECT_TRUE(!arg->is_pem_key_cert_pair_list_empty()); - EXPECT_EQ(static_cast(c_pair_list.size()), 3); - EXPECT_STREQ(c_pair_list[0].private_key(), "private_key1"); - EXPECT_STREQ(c_pair_list[0].cert_chain(), "cert_chain1"); - EXPECT_STREQ(c_pair_list[1].private_key(), "private_key2"); - EXPECT_STREQ(c_pair_list[1].cert_chain(), "cert_chain2"); - EXPECT_STREQ(c_pair_list[2].private_key(), "private_key3"); - EXPECT_STREQ(c_pair_list[2].cert_chain(), "cert_chain3"); - EXPECT_EQ(arg->status(), GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW); - EXPECT_STREQ(arg->error_details().c_str(), "error_details"); - - // Cleanup. - delete c_arg->key_materials_config; - if (c_arg->destroy_context != nullptr) { - c_arg->destroy_context(c_arg->context); - } - delete c_arg->error_details; - delete c_arg; - delete config->c_config(); -} - -TEST_F(CredentialsTest, TlsCredentialReloadConfigCppToC) { - std::shared_ptr test_credential_reload( - new TestTlsCredentialReload()); - TlsCredentialReloadConfig config(test_credential_reload); - grpc_tls_credential_reload_arg c_arg; - c_arg.error_details = new grpc_tls_error_details(); - c_arg.context = nullptr; - c_arg.cb_user_data = static_cast(nullptr); - grpc_tls_key_materials_config c_key_materials; - std::string test_private_key = "private_key"; - std::string test_cert_chain = "cert_chain"; - grpc_ssl_pem_key_cert_pair* ssl_pair = - (grpc_ssl_pem_key_cert_pair*)gpr_malloc( - sizeof(grpc_ssl_pem_key_cert_pair)); - ssl_pair->private_key = gpr_strdup(test_private_key.c_str()); - ssl_pair->cert_chain = gpr_strdup(test_cert_chain.c_str()); - ::grpc_core::PemKeyCertPair pem_key_cert_pair = - ::grpc_core::PemKeyCertPair(ssl_pair); - ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1> pem_key_cert_pair_list; - pem_key_cert_pair_list.push_back(pem_key_cert_pair); - std::string test_pem_root_certs = "pem_root_certs"; - c_key_materials.set_key_materials(test_pem_root_certs.c_str(), - pem_key_cert_pair_list); - c_arg.key_materials_config = &c_key_materials; - c_arg.status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - std::string test_error_details = "error_details"; - c_arg.error_details->set_error_details(test_error_details.c_str()); - - grpc_tls_credential_reload_config* c_config = config.c_config(); - c_arg.config = c_config; - int c_schedule_output = c_config->Schedule(&c_arg); - EXPECT_EQ(c_schedule_output, 0); - EXPECT_EQ(c_arg.cb_user_data, nullptr); - EXPECT_STREQ(c_arg.key_materials_config->pem_root_certs(), - "new_pem_root_certs"); - ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1> pair_list = - c_arg.key_materials_config->pem_key_cert_pair_list(); - EXPECT_EQ(static_cast(pair_list.size()), 2); - EXPECT_STREQ(pair_list[0].private_key(), "private_key"); - EXPECT_STREQ(pair_list[0].cert_chain(), "cert_chain"); - EXPECT_STREQ(pair_list[1].private_key(), "private_key3"); - EXPECT_STREQ(pair_list[1].cert_chain(), "cert_chain3"); - EXPECT_EQ(c_arg.status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW); - EXPECT_STREQ(c_arg.error_details->error_details().c_str(), - test_error_details.c_str()); - - // Cleanup. - c_arg.destroy_context(c_arg.context); - delete c_arg.error_details; - delete config.c_config(); -} - -typedef class ::grpc::experimental::TlsServerAuthorizationCheckArg - TlsServerAuthorizationCheckArg; -typedef class ::grpc::experimental::TlsServerAuthorizationCheckConfig - TlsServerAuthorizationCheckConfig; - -TEST_F(CredentialsTest, TlsServerAuthorizationCheckArgCallback) { +TEST(CredentialsTest, TlsServerAuthorizationCheckArgCallback) { grpc_tls_server_authorization_check_arg* c_arg = new grpc_tls_server_authorization_check_arg; c_arg->cb = tls_server_authorization_check_callback; @@ -472,7 +280,7 @@ TEST_F(CredentialsTest, TlsServerAuthorizationCheckArgCallback) { delete c_arg; } -TEST_F(CredentialsTest, TlsServerAuthorizationCheckConfigSchedule) { +TEST(CredentialsTest, TlsServerAuthorizationCheckConfigSchedule) { std::shared_ptr test_server_authorization_check(new TestTlsServerAuthorizationCheck()); TlsServerAuthorizationCheckConfig config(test_server_authorization_check); @@ -511,10 +319,9 @@ TEST_F(CredentialsTest, TlsServerAuthorizationCheckConfigSchedule) { c_arg->destroy_context(c_arg->context); } delete c_arg; - delete config.c_config(); } -TEST_F(CredentialsTest, TlsServerAuthorizationCheckConfigCppToC) { +TEST(CredentialsTest, TlsServerAuthorizationCheckConfigCppToC) { std::shared_ptr test_server_authorization_check(new TestTlsServerAuthorizationCheck()); TlsServerAuthorizationCheckConfig config(test_server_authorization_check); @@ -545,174 +352,62 @@ TEST_F(CredentialsTest, TlsServerAuthorizationCheckConfigCppToC) { delete c_arg.error_details; gpr_free(const_cast(c_arg.target_name)); gpr_free(const_cast(c_arg.peer_cert)); - delete config.c_config(); -} - -typedef class ::grpc::experimental::TlsCredentialsOptions TlsCredentialsOptions; - -TEST_F(CredentialsTest, TlsCredentialsOptionsCppToC) { - std::shared_ptr key_materials_config( - new TlsKeyMaterialsConfig()); - struct TlsKeyMaterialsConfig::PemKeyCertPair pair = {"private_key", - "cert_chain"}; - std::vector pair_list = {pair}; - key_materials_config->set_key_materials("pem_root_certs", pair_list); - - std::shared_ptr test_credential_reload( - new TestTlsCredentialReload()); - std::shared_ptr credential_reload_config( - new TlsCredentialReloadConfig(test_credential_reload)); - - std::shared_ptr - test_server_authorization_check(new TestTlsServerAuthorizationCheck()); - std::shared_ptr - server_authorization_check_config(new TlsServerAuthorizationCheckConfig( - test_server_authorization_check)); - - TlsCredentialsOptions options = TlsCredentialsOptions( - GRPC_TLS_SERVER_VERIFICATION, key_materials_config, - credential_reload_config, server_authorization_check_config); - grpc_tls_credentials_options* c_options = options.c_credentials_options(); - EXPECT_EQ(c_options->cert_request_type(), - GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE); - EXPECT_EQ(c_options->server_verification_option(), - GRPC_TLS_SERVER_VERIFICATION); - grpc_tls_key_materials_config* c_key_materials_config = - c_options->key_materials_config(); - grpc_tls_credential_reload_config* c_credential_reload_config = - c_options->credential_reload_config(); - grpc_tls_credential_reload_arg c_credential_reload_arg; - c_credential_reload_arg.cb_user_data = nullptr; - c_credential_reload_arg.key_materials_config = - c_options->key_materials_config(); - c_credential_reload_arg.status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED; - std::string test_error_details = "error_details"; - c_credential_reload_arg.error_details = new grpc_tls_error_details(); - c_credential_reload_arg.error_details->set_error_details( - test_error_details.c_str()); - c_credential_reload_arg.context = nullptr; - grpc_tls_server_authorization_check_config* - c_server_authorization_check_config = - c_options->server_authorization_check_config(); - grpc_tls_server_authorization_check_arg c_server_authorization_check_arg; - c_server_authorization_check_arg.cb = tls_server_authorization_check_callback; - c_server_authorization_check_arg.cb_user_data = nullptr; - c_server_authorization_check_arg.success = 0; - c_server_authorization_check_arg.target_name = "target_name"; - c_server_authorization_check_arg.peer_cert = "peer_cert"; - c_server_authorization_check_arg.status = GRPC_STATUS_UNAUTHENTICATED; - c_server_authorization_check_arg.error_details = new grpc_tls_error_details(); - c_server_authorization_check_arg.error_details->set_error_details( - "error_details"); - c_server_authorization_check_arg.context = nullptr; - EXPECT_STREQ(c_key_materials_config->pem_root_certs(), "pem_root_certs"); - EXPECT_EQ( - static_cast(c_key_materials_config->pem_key_cert_pair_list().size()), - 1); - EXPECT_STREQ( - c_key_materials_config->pem_key_cert_pair_list()[0].private_key(), - "private_key"); - EXPECT_STREQ(c_key_materials_config->pem_key_cert_pair_list()[0].cert_chain(), - "cert_chain"); - - GPR_ASSERT(c_credential_reload_config != nullptr); - int c_credential_reload_schedule_output = - c_credential_reload_config->Schedule(&c_credential_reload_arg); - EXPECT_EQ(c_credential_reload_schedule_output, 0); - EXPECT_EQ(c_credential_reload_arg.cb_user_data, nullptr); - EXPECT_STREQ(c_credential_reload_arg.key_materials_config->pem_root_certs(), - "new_pem_root_certs"); - ::absl::InlinedVector<::grpc_core::PemKeyCertPair, 1> c_pair_list = - c_credential_reload_arg.key_materials_config->pem_key_cert_pair_list(); - EXPECT_EQ(static_cast(c_pair_list.size()), 2); - EXPECT_STREQ(c_pair_list[0].private_key(), "private_key"); - EXPECT_STREQ(c_pair_list[0].cert_chain(), "cert_chain"); - EXPECT_STREQ(c_pair_list[1].private_key(), "private_key3"); - EXPECT_STREQ(c_pair_list[1].cert_chain(), "cert_chain3"); - EXPECT_EQ(c_credential_reload_arg.status, - GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW); - EXPECT_STREQ(c_credential_reload_arg.error_details->error_details().c_str(), - test_error_details.c_str()); - - int c_server_authorization_check_schedule_output = - c_server_authorization_check_config->Schedule( - &c_server_authorization_check_arg); - EXPECT_EQ(c_server_authorization_check_schedule_output, 1); - EXPECT_STREQ( - static_cast(c_server_authorization_check_arg.cb_user_data), - "cb_user_data"); - EXPECT_EQ(c_server_authorization_check_arg.success, 1); - EXPECT_STREQ(c_server_authorization_check_arg.target_name, - "sync_target_name"); - EXPECT_STREQ(c_server_authorization_check_arg.peer_cert, "sync_peer_cert"); - EXPECT_EQ(c_server_authorization_check_arg.status, GRPC_STATUS_OK); - EXPECT_STREQ( - c_server_authorization_check_arg.error_details->error_details().c_str(), - "sync_error_details"); - - // Cleanup. - c_credential_reload_arg.destroy_context(c_credential_reload_arg.context); - delete c_credential_reload_arg.error_details; - c_server_authorization_check_arg.destroy_context( - c_server_authorization_check_arg.context); - gpr_free(c_server_authorization_check_arg.cb_user_data); - gpr_free(const_cast(c_server_authorization_check_arg.target_name)); - gpr_free(const_cast(c_server_authorization_check_arg.peer_cert)); - delete c_server_authorization_check_arg.error_details; - delete c_options; } -// This test demonstrates how the TLS credentials will be used. -TEST_F(CredentialsTest, LoadTlsChannelCredentials) { - std::shared_ptr test_credential_reload( - new TestTlsCredentialReload()); - std::shared_ptr credential_reload_config( - new TlsCredentialReloadConfig(test_credential_reload)); - - std::shared_ptr - test_server_authorization_check(new TestTlsServerAuthorizationCheck()); - std::shared_ptr - server_authorization_check_config(new TlsServerAuthorizationCheckConfig( - test_server_authorization_check)); - - TlsCredentialsOptions options = TlsCredentialsOptions( - GRPC_TLS_SERVER_VERIFICATION, nullptr, credential_reload_config, +TEST( + CredentialsTest, + TlsChannelCredentialsWithStaticDataCertificateProviderLoadingRootAndIdentity) { + experimental::IdentityKeyCertPair key_cert_pair; + key_cert_pair.private_key = kIdentityCertPrivateKey; + key_cert_pair.certificate_chain = kIdentityCertContents; + std::vector identity_key_cert_pairs; + identity_key_cert_pairs.emplace_back(key_cert_pair); + auto certificate_provider = std::make_shared( + kRootCertContents, identity_key_cert_pairs); + auto test_server_authorization_check = + std::make_shared(); + auto server_authorization_check_config = + std::make_shared( + test_server_authorization_check); + grpc::experimental::TlsChannelCredentialsOptions options( + certificate_provider); + options.watch_root_certs(); + options.set_root_cert_name(kRootCertName); + options.watch_identity_key_cert_pairs(); + options.set_identity_cert_name(kIdentityCertName); + options.set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION); + options.set_server_authorization_check_config( server_authorization_check_config); - std::shared_ptr channel_credentials = - grpc::experimental::TlsCredentials(options); + auto channel_credentials = grpc::experimental::TlsCredentials(options); GPR_ASSERT(channel_credentials.get() != nullptr); } -TEST_F(CredentialsTest, TlsCredentialReloadConfigErrorMessages) { - std::shared_ptr config( - new TlsCredentialReloadConfig(nullptr)); - grpc_tls_credential_reload_arg* c_arg = new grpc_tls_credential_reload_arg; - c_arg->error_details = new grpc_tls_error_details(); - c_arg->context = nullptr; - TlsCredentialReloadArg* arg = new TlsCredentialReloadArg(c_arg); - int schedule_output = config->Schedule(arg); - - EXPECT_EQ(schedule_output, 1); - EXPECT_EQ(arg->status(), GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL); - EXPECT_STREQ(arg->error_details().c_str(), - "the interface of the credential reload config is nullptr"); - - arg->set_status(GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED); - config->Cancel(arg); - EXPECT_EQ(arg->status(), GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL); - EXPECT_STREQ(arg->error_details().c_str(), - "the interface of the credential reload config is nullptr"); - - // Cleanup. - if (c_arg->destroy_context != nullptr) { - c_arg->destroy_context(c_arg->context); - } - delete c_arg->error_details; - delete c_arg; - delete config->c_config(); +// ChannelCredentials should always have root credential presented. +// Otherwise the system root certificates will be loaded, which will cause +// failure in some tests under MacOS/Windows. +TEST(CredentialsTest, + TlsChannelCredentialsWithStaticDataCertificateProviderLoadingRootOnly) { + auto certificate_provider = + std::make_shared(kRootCertContents); + auto test_server_authorization_check = + std::make_shared(); + auto server_authorization_check_config = + std::make_shared( + test_server_authorization_check); + GPR_ASSERT(certificate_provider != nullptr); + GPR_ASSERT(certificate_provider->c_provider() != nullptr); + grpc::experimental::TlsChannelCredentialsOptions options( + certificate_provider); + options.watch_root_certs(); + options.set_root_cert_name(kRootCertName); + options.set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION); + options.set_server_authorization_check_config( + server_authorization_check_config); + auto channel_credentials = grpc::experimental::TlsCredentials(options); + GPR_ASSERT(channel_credentials.get() != nullptr); } -TEST_F(CredentialsTest, TlsServerAuthorizationCheckConfigErrorMessages) { +TEST(CredentialsTest, TlsServerAuthorizationCheckConfigErrorMessages) { std::shared_ptr config( new TlsServerAuthorizationCheckConfig(nullptr)); grpc_tls_server_authorization_check_arg* c_arg = @@ -742,9 +437,9 @@ TEST_F(CredentialsTest, TlsServerAuthorizationCheckConfigErrorMessages) { c_arg->destroy_context(c_arg->context); } delete c_arg; - delete config->c_config(); } +} // namespace } // namespace testing } // namespace grpc diff --git a/test/cpp/server/BUILD b/test/cpp/server/BUILD index 5c9d99d3deb..c2ccd8a4cf1 100644 --- a/test/cpp/server/BUILD +++ b/test/cpp/server/BUILD @@ -59,3 +59,17 @@ grpc_cc_test( "//test/core/util:grpc_test_util_unsecure", ], ) + +grpc_cc_test( + name = "credentials_test", + srcs = ["credentials_test.cc"], + external_deps = [ + "gtest", + ], + deps = [ + "//:gpr", + "//:grpc", + "//:grpc++", + "//test/core/util:grpc_test_util", + ], +) diff --git a/test/cpp/server/credentials_test.cc b/test/cpp/server/credentials_test.cc new file mode 100644 index 00000000000..8e7fc1719a9 --- /dev/null +++ b/test/cpp/server/credentials_test.cc @@ -0,0 +1,98 @@ +// +// 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 +#include +#include +#include + +#include + +#include "src/cpp/client/secure_credentials.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +namespace { + +constexpr const char* kRootCertName = "root_cert_name"; +constexpr const char* kRootCertContents = "root_cert_contents"; +constexpr const char* kIdentityCertName = "identity_cert_name"; +constexpr const char* kIdentityCertPrivateKey = "identity_private_key"; +constexpr const char* kIdentityCertContents = "identity_cert_contents"; + +using ::grpc::experimental::StaticDataCertificateProvider; + +} // namespace + +namespace grpc { +namespace testing { +namespace { + +TEST( + CredentialsTest, + TlsServerCredentialsWithStaticDataCertificateProviderLoadingRootAndIdentity) { + experimental::IdentityKeyCertPair key_cert_pair; + key_cert_pair.private_key = kIdentityCertPrivateKey; + key_cert_pair.certificate_chain = kIdentityCertContents; + std::vector identity_key_cert_pairs; + identity_key_cert_pairs.emplace_back(key_cert_pair); + auto certificate_provider = std::make_shared( + kRootCertContents, identity_key_cert_pairs); + grpc::experimental::TlsServerCredentialsOptions options(certificate_provider); + options.watch_root_certs(); + options.set_root_cert_name(kRootCertName); + options.watch_identity_key_cert_pairs(); + options.set_identity_cert_name(kIdentityCertName); + options.set_cert_request_type( + GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY); + auto server_credentials = grpc::experimental::TlsServerCredentials(options); + GPR_ASSERT(server_credentials.get() != nullptr); +} + +// ServerCredentials should always have identity credential presented. +// Otherwise gRPC stack will fail. +TEST(CredentialsTest, + TlsServerCredentialsWithStaticDataCertificateProviderLoadingIdentityOnly) { + experimental::IdentityKeyCertPair key_cert_pair; + key_cert_pair.private_key = kIdentityCertPrivateKey; + key_cert_pair.certificate_chain = kIdentityCertContents; + std::vector identity_key_cert_pairs; + // Adding two key_cert_pair(s) should still work. + identity_key_cert_pairs.emplace_back(key_cert_pair); + identity_key_cert_pairs.emplace_back(key_cert_pair); + auto certificate_provider = + std::make_shared(identity_key_cert_pairs); + grpc::experimental::TlsServerCredentialsOptions options(certificate_provider); + options.watch_identity_key_cert_pairs(); + options.set_identity_cert_name(kIdentityCertName); + options.set_cert_request_type( + GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY); + auto server_credentials = grpc::experimental::TlsServerCredentials(options); + GPR_ASSERT(server_credentials.get() != nullptr); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + grpc::testing::TestEnvironment env(argc, argv); + int ret = RUN_ALL_TESTS(); + return ret; +} diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 334dab91ba7..9d481b72758 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -1010,6 +1010,7 @@ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ +include/grpcpp/security/tls_certificate_provider.h \ include/grpcpp/security/tls_credentials_options.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 9389f376385..58bd30d6e97 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1010,6 +1010,7 @@ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ +include/grpcpp/security/tls_certificate_provider.h \ include/grpcpp/security/tls_credentials_options.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ @@ -1882,7 +1883,6 @@ src/core/lib/security/authorization/evaluate_args.cc \ src/core/lib/security/authorization/evaluate_args.h \ src/core/lib/security/authorization/mock_cel/activation.h \ src/core/lib/security/authorization/mock_cel/cel_value.h \ -src/core/lib/security/certificate_provider.h \ src/core/lib/security/context/security_context.cc \ src/core/lib/security/context/security_context.h \ src/core/lib/security/credentials/alts/alts_credentials.cc \ @@ -1929,6 +1929,8 @@ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.h \ src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \ src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h \ +src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc \ +src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h \ src/core/lib/security/credentials/tls/tls_credentials.cc \ @@ -2126,6 +2128,7 @@ src/cpp/common/secure_auth_context.cc \ src/cpp/common/secure_auth_context.h \ src/cpp/common/secure_channel_arguments.cc \ src/cpp/common/secure_create_auth_context.cc \ +src/cpp/common/tls_certificate_provider.cc \ src/cpp/common/tls_credentials_options.cc \ src/cpp/common/tls_credentials_options_util.cc \ src/cpp/common/tls_credentials_options_util.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1ce7249950e..a0bc5bf529c 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1725,7 +1725,6 @@ src/core/lib/security/authorization/evaluate_args.cc \ src/core/lib/security/authorization/evaluate_args.h \ src/core/lib/security/authorization/mock_cel/activation.h \ src/core/lib/security/authorization/mock_cel/cel_value.h \ -src/core/lib/security/certificate_provider.h \ src/core/lib/security/context/security_context.cc \ src/core/lib/security/context/security_context.h \ src/core/lib/security/credentials/alts/alts_credentials.cc \ @@ -1772,6 +1771,8 @@ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.h \ src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \ src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h \ +src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc \ +src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h \ src/core/lib/security/credentials/tls/tls_credentials.cc \ diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 17663a5ecd9..2c49f8bdfb6 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -5833,6 +5833,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "test_cpp_server_credentials_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false,