From e453404d318982f64b244db8fa487b3deef3887d Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 1 Feb 2017 07:39:08 -0800 Subject: Canonify server URI when setting the channel arg. --- src/core/ext/transport/chttp2/client/secure/secure_channel_create.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c') diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index f979d9bad5..149d5e1863 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -39,6 +39,7 @@ #include #include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/transport/chttp2/client/chttp2_connector.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/security/credentials/credentials.h" @@ -69,8 +70,9 @@ static grpc_channel *client_channel_factory_create_channel( grpc_arg arg; arg.type = GRPC_ARG_STRING; arg.key = GRPC_ARG_SERVER_URI; - arg.value.string = (char *)target; + arg.value.string = grpc_resolver_factory_add_default_prefix_if_needed(target); grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1); + gpr_free(arg.value.string); grpc_channel *channel = grpc_channel_create(exec_ctx, target, new_args, GRPC_CLIENT_CHANNEL, NULL); grpc_channel_args_destroy(exec_ctx, new_args); -- cgit v1.2.3 From 30d3a6892dc4ce2532a820046d3dd8285a20845a Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 1 Feb 2017 09:15:46 -0800 Subject: Check for target being NULL in client channel factory. --- src/core/ext/transport/chttp2/client/insecure/channel_create.c | 4 ++++ src/core/ext/transport/chttp2/client/secure/secure_channel_create.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c') diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c index b987086db6..490a0c560e 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c @@ -64,6 +64,10 @@ static grpc_channel *client_channel_factory_create_channel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, const char *target, grpc_client_channel_type type, const grpc_channel_args *args) { + if (target == NULL) { + gpr_log(GPR_ERROR, "cannot create channel with NULL target name"); + return NULL; + } // Add channel arg containing the server URI. grpc_arg arg; arg.type = GRPC_ARG_STRING; diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index 149d5e1863..f351010d98 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -66,6 +66,10 @@ static grpc_channel *client_channel_factory_create_channel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, const char *target, grpc_client_channel_type type, const grpc_channel_args *args) { + if (target == NULL) { + gpr_log(GPR_ERROR, "cannot create channel with NULL target name"); + return NULL; + } // Add channel arg containing the server URI. grpc_arg arg; arg.type = GRPC_ARG_STRING; -- cgit v1.2.3 From b43c7bfb859ee95c7e2af873135553966fc63e80 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 1 Feb 2017 12:55:20 -0800 Subject: Make sure grpc_secure_channel_create() never returns NULL. --- src/core/ext/transport/chttp2/client/secure/secure_channel_create.c | 5 ++++- test/core/end2end/fuzzers/api_fuzzer.c | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c') diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index f351010d98..cbdd9fbc37 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -144,5 +144,8 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, "secure_client_channel_factory_create_channel"); grpc_channel_args_destroy(&exec_ctx, new_args); grpc_exec_ctx_finish(&exec_ctx); - return channel; /* may be NULL */ + return channel == NULL ? channel + : grpc_lame_client_channel_create( + target, GRPC_STATUS_INTERNAL, + "Failed to create secure client channel"); } diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c index 12bd24de33..2569579739 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.c +++ b/test/core/end2end/fuzzers/api_fuzzer.c @@ -1155,6 +1155,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { grpc_channel_args *args = read_args(&inp); grpc_channel_credentials *creds = read_channel_creds(&inp); g_channel = grpc_secure_channel_create(creds, target_uri, args, NULL); + GPR_ASSERT(g_channel != NULL); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_args_destroy(&exec_ctx, args); -- cgit v1.2.3 From 539a864d913337658fa60b859b2df2fe958755b1 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 2 Feb 2017 07:23:19 -0800 Subject: Fixed dumb reversed conditional. --- src/core/ext/transport/chttp2/client/secure/secure_channel_create.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c') diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index cbdd9fbc37..d3e53984f2 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -144,7 +144,7 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, "secure_client_channel_factory_create_channel"); grpc_channel_args_destroy(&exec_ctx, new_args); grpc_exec_ctx_finish(&exec_ctx); - return channel == NULL ? channel + return channel != NULL ? channel : grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, "Failed to create secure client channel"); -- cgit v1.2.3 From 012915045fca08c365add95a8e29eb40021ecd64 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Tue, 7 Feb 2017 13:26:41 -0800 Subject: Secure naming support for gRPCLB --- BUILD | 62 ++++++-- CMakeLists.txt | 4 + Makefile | 6 + binding.gyp | 2 + build.yaml | 22 ++- config.m4 | 2 + gRPC-Core.podspec | 6 + grpc.gemspec | 4 + package.xml | 4 + src/core/ext/client_channel/subchannel.c | 16 +- src/core/ext/client_channel/subchannel.h | 3 + src/core/ext/lb_policy/grpclb/grpclb.c | 171 +++++++++++++-------- src/core/ext/lb_policy/grpclb/grpclb_channel.c | 77 ++++++++++ src/core/ext/lb_policy/grpclb/grpclb_channel.h | 56 +++++++ .../ext/lb_policy/grpclb/grpclb_channel_secure.c | 107 +++++++++++++ src/core/ext/lb_policy/round_robin/round_robin.c | 7 + .../chttp2/client/secure/secure_channel_create.c | 171 +++++++++++++++------ src/core/lib/iomgr/sockaddr_utils.c | 38 +++-- src/core/lib/iomgr/sockaddr_utils.h | 4 + src/core/lib/security/credentials/credentials.c | 47 ++++++ src/core/lib/security/credentials/credentials.h | 13 ++ .../security/credentials/fake/fake_credentials.c | 8 +- .../security/credentials/fake/fake_credentials.h | 15 ++ .../lib/security/transport/client_auth_filter.c | 2 +- src/core/lib/security/transport/lb_targets_info.c | 70 +++++++++ src/core/lib/security/transport/lb_targets_info.h | 47 ++++++ .../lib/security/transport/security_connector.c | 141 ++++++++++++++--- .../lib/security/transport/security_connector.h | 7 +- .../lib/security/transport/security_handshaker.c | 4 +- src/core/lib/surface/init_secure.c | 2 +- src/python/grpcio/grpc_core_dependencies.py | 2 + test/core/end2end/fake_resolver.c | 29 +++- test/core/surface/secure_channel_create_test.c | 2 +- test/cpp/grpclb/grpclb_test.cc | 89 +++++++---- tools/doxygen/Doxyfile.core.internal | 4 + tools/run_tests/generated/sources_and_headers.json | 37 ++++- vsprojects/vcxproj/grpc/grpc.vcxproj | 6 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 12 ++ .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 3 + .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 + 40 files changed, 1098 insertions(+), 210 deletions(-) create mode 100644 src/core/ext/lb_policy/grpclb/grpclb_channel.c create mode 100644 src/core/ext/lb_policy/grpclb/grpclb_channel.h create mode 100644 src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c create mode 100644 src/core/lib/security/transport/lb_targets_info.c create mode 100644 src/core/lib/security/transport/lb_targets_info.h (limited to 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c') diff --git a/BUILD b/BUILD index 58971ff8e3..c56d9c9746 100644 --- a/BUILD +++ b/BUILD @@ -63,7 +63,7 @@ grpc_cc_library( deps = [ "census", "grpc_base", - "grpc_lb_policy_grpclb", + "grpc_lb_policy_grpclb_secure", "grpc_lb_policy_pick_first", "grpc_lb_policy_round_robin", "grpc_load_reporting", @@ -624,9 +624,9 @@ grpc_cc_library( "src/core/lib/surface/completion_queue.h", "src/core/lib/surface/event_string.h", "src/core/lib/surface/init.h", - "src/core/lib/surface/validate_metadata.h", "src/core/lib/surface/lame_client.h", "src/core/lib/surface/server.h", + "src/core/lib/surface/validate_metadata.h", "src/core/lib/transport/byte_stream.h", "src/core/lib/transport/connectivity_state.h", "src/core/lib/transport/error_utils.h", @@ -665,7 +665,6 @@ grpc_cc_library( grpc_cc_library( name = "grpc_client_channel", - language = "c", srcs = [ "src/core/ext/client_channel/channel_connectivity.c", "src/core/ext/client_channel/client_channel.c", @@ -709,6 +708,7 @@ grpc_cc_library( "src/core/ext/client_channel/subchannel_index.h", "src/core/ext/client_channel/uri_parser.h", ], + language = "c", deps = [ "grpc_base", ], @@ -735,11 +735,37 @@ grpc_cc_library( name = "grpc_lb_policy_grpclb", srcs = [ "src/core/ext/lb_policy/grpclb/grpclb.c", + "src/core/ext/lb_policy/grpclb/grpclb_channel.c", + "src/core/ext/lb_policy/grpclb/load_balancer_api.c", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", + ], + hdrs = [ + "src/core/ext/lb_policy/grpclb/grpclb.h", + "src/core/ext/lb_policy/grpclb/grpclb_channel.h", + "src/core/ext/lb_policy/grpclb/load_balancer_api.h", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", + ], + external_deps = [ + "nanopb", + ], + language = "c", + deps = [ + "grpc_base", + "grpc_client_channel", + ], +) + +grpc_cc_library( + name = "grpc_lb_policy_grpclb_secure", + srcs = [ + "src/core/ext/lb_policy/grpclb/grpclb.c", + "src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", ], hdrs = [ "src/core/ext/lb_policy/grpclb/grpclb.h", + "src/core/ext/lb_policy/grpclb/grpclb_channel.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", ], @@ -750,6 +776,7 @@ grpc_cc_library( deps = [ "grpc_base", "grpc_client_channel", + "grpc_secure", ], ) @@ -837,6 +864,7 @@ grpc_cc_library( "src/core/lib/security/credentials/ssl/ssl_credentials.c", "src/core/lib/security/transport/client_auth_filter.c", "src/core/lib/security/transport/secure_endpoint.c", + "src/core/lib/security/transport/lb_targets_info.c", "src/core/lib/security/transport/security_connector.c", "src/core/lib/security/transport/security_handshaker.c", "src/core/lib/security/transport/server_auth_filter.c", @@ -860,6 +888,7 @@ grpc_cc_library( "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/transport/auth_filters.h", "src/core/lib/security/transport/secure_endpoint.h", + "src/core/lib/security/transport/lb_targets_info.h", "src/core/lib/security/transport/security_connector.h", "src/core/lib/security/transport/security_handshaker.h", "src/core/lib/security/transport/tsi_error.h", @@ -943,22 +972,21 @@ grpc_cc_library( ) grpc_cc_library( - name = "grpc_transport_chttp2_client_connector", - hdrs = [ - "src/core/ext/transport/chttp2/client/chttp2_connector.h", - ], - srcs = [ - "src/core/ext/transport/chttp2/client/chttp2_connector.c", - ], - language = "c", - deps = [ - "grpc_transport_chttp2", - "grpc_base", - "grpc_client_channel", - ], + name = "grpc_transport_chttp2_client_connector", + srcs = [ + "src/core/ext/transport/chttp2/client/chttp2_connector.c", + ], + hdrs = [ + "src/core/ext/transport/chttp2/client/chttp2_connector.h", + ], + language = "c", + deps = [ + "grpc_base", + "grpc_client_channel", + "grpc_transport_chttp2", + ], ) - grpc_cc_library( name = "grpc_transport_chttp2_client_insecure", srcs = [ diff --git a/CMakeLists.txt b/CMakeLists.txt index c6a57e5f82..cf9908b060 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -953,6 +953,7 @@ add_library(grpc src/core/lib/security/credentials/plugin/plugin_credentials.c src/core/lib/security/credentials/ssl/ssl_credentials.c src/core/lib/security/transport/client_auth_filter.c + src/core/lib/security/transport/lb_targets_info.c src/core/lib/security/transport/secure_endpoint.c src/core/lib/security/transport/security_connector.c src/core/lib/security/transport/security_handshaker.c @@ -993,6 +994,7 @@ add_library(grpc src/core/ext/transport/chttp2/client/insecure/channel_create.c src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c src/core/ext/lb_policy/grpclb/grpclb.c + src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c src/core/ext/lb_policy/grpclb/load_balancer_api.c src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c third_party/nanopb/pb_common.c @@ -1272,6 +1274,7 @@ add_library(grpc_cronet src/core/lib/security/credentials/plugin/plugin_credentials.c src/core/lib/security/credentials/ssl/ssl_credentials.c src/core/lib/security/transport/client_auth_filter.c + src/core/lib/security/transport/lb_targets_info.c src/core/lib/security/transport/secure_endpoint.c src/core/lib/security/transport/security_connector.c src/core/lib/security/transport/security_handshaker.c @@ -1773,6 +1776,7 @@ add_library(grpc_unsecure src/core/ext/load_reporting/load_reporting.c src/core/ext/load_reporting/load_reporting_filter.c src/core/ext/lb_policy/grpclb/grpclb.c + src/core/ext/lb_policy/grpclb/grpclb_channel.c src/core/ext/lb_policy/grpclb/load_balancer_api.c src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c third_party/nanopb/pb_common.c diff --git a/Makefile b/Makefile index d6b7a659be..d0602def84 100644 --- a/Makefile +++ b/Makefile @@ -2794,6 +2794,7 @@ LIBGRPC_SRC = \ src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/transport/client_auth_filter.c \ + src/core/lib/security/transport/lb_targets_info.c \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/security_connector.c \ src/core/lib/security/transport/security_handshaker.c \ @@ -2834,6 +2835,7 @@ LIBGRPC_SRC = \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ src/core/ext/lb_policy/grpclb/grpclb.c \ + src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -3127,6 +3129,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/transport/client_auth_filter.c \ + src/core/lib/security/transport/lb_targets_info.c \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/security_connector.c \ src/core/lib/security/transport/security_handshaker.c \ @@ -3644,6 +3647,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/load_reporting/load_reporting.c \ src/core/ext/load_reporting/load_reporting_filter.c \ src/core/ext/lb_policy/grpclb/grpclb.c \ + src/core/ext/lb_policy/grpclb/grpclb_channel.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -17705,6 +17709,7 @@ ifneq ($(OPENSSL_DEP),) # This is to ensure the embedded OpenSSL is built beforehand, properly # installing headers to their final destination on the drive. We need this # otherwise parallel compilation will fail if a source is compiled first. +src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP) src/core/ext/transport/cronet/client/secure/cronet_channel_create.c: $(OPENSSL_DEP) @@ -17726,6 +17731,7 @@ src/core/lib/security/credentials/oauth2/oauth2_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/plugin/plugin_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/ssl/ssl_credentials.c: $(OPENSSL_DEP) src/core/lib/security/transport/client_auth_filter.c: $(OPENSSL_DEP) +src/core/lib/security/transport/lb_targets_info.c: $(OPENSSL_DEP) src/core/lib/security/transport/secure_endpoint.c: $(OPENSSL_DEP) src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP) src/core/lib/security/transport/security_handshaker.c: $(OPENSSL_DEP) diff --git a/binding.gyp b/binding.gyp index 1815a5a476..8ff3d8c1a3 100644 --- a/binding.gyp +++ b/binding.gyp @@ -758,6 +758,7 @@ 'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/transport/client_auth_filter.c', + 'src/core/lib/security/transport/lb_targets_info.c', 'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/security_connector.c', 'src/core/lib/security/transport/security_handshaker.c', @@ -798,6 +799,7 @@ 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', 'src/core/ext/lb_policy/grpclb/grpclb.c', + 'src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/build.yaml b/build.yaml index cacb5c4790..7fec296ad3 100644 --- a/build.yaml +++ b/build.yaml @@ -452,10 +452,28 @@ filegroups: - name: grpc_lb_policy_grpclb headers: - src/core/ext/lb_policy/grpclb/grpclb.h + - src/core/ext/lb_policy/grpclb/grpclb_channel.h - src/core/ext/lb_policy/grpclb/load_balancer_api.h - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h src: - src/core/ext/lb_policy/grpclb/grpclb.c + - src/core/ext/lb_policy/grpclb/grpclb_channel.c + - src/core/ext/lb_policy/grpclb/load_balancer_api.c + - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c + plugin: grpc_lb_policy_grpclb + uses: + - grpc_base + - grpc_client_channel + - nanopb +- name: grpc_lb_policy_grpclb_secure + headers: + - src/core/ext/lb_policy/grpclb/grpclb.h + - src/core/ext/lb_policy/grpclb/grpclb_channel.h + - src/core/ext/lb_policy/grpclb/load_balancer_api.h + - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h + src: + - src/core/ext/lb_policy/grpclb/grpclb.c + - src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c - src/core/ext/lb_policy/grpclb/load_balancer_api.c - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c plugin: grpc_lb_policy_grpclb @@ -518,6 +536,7 @@ filegroups: - src/core/lib/security/credentials/plugin/plugin_credentials.h - src/core/lib/security/credentials/ssl/ssl_credentials.h - src/core/lib/security/transport/auth_filters.h + - src/core/lib/security/transport/lb_targets_info.h - src/core/lib/security/transport/secure_endpoint.h - src/core/lib/security/transport/security_connector.h - src/core/lib/security/transport/security_handshaker.h @@ -541,6 +560,7 @@ filegroups: - src/core/lib/security/credentials/plugin/plugin_credentials.c - src/core/lib/security/credentials/ssl/ssl_credentials.c - src/core/lib/security/transport/client_auth_filter.c + - src/core/lib/security/transport/lb_targets_info.c - src/core/lib/security/transport/secure_endpoint.c - src/core/lib/security/transport/security_connector.c - src/core/lib/security/transport/security_handshaker.c @@ -909,7 +929,7 @@ libs: - grpc_transport_chttp2_client_secure - grpc_transport_chttp2_server_insecure - grpc_transport_chttp2_client_insecure - - grpc_lb_policy_grpclb + - grpc_lb_policy_grpclb_secure - grpc_lb_policy_pick_first - grpc_lb_policy_round_robin - grpc_resolver_dns_native diff --git a/config.m4 b/config.m4 index 2c6c89f3ee..90536e503e 100644 --- a/config.m4 +++ b/config.m4 @@ -237,6 +237,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/transport/client_auth_filter.c \ + src/core/lib/security/transport/lb_targets_info.c \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/security_connector.c \ src/core/lib/security/transport/security_handshaker.c \ @@ -277,6 +278,7 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ src/core/ext/lb_policy/grpclb/grpclb.c \ + src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 7632174f31..77743f69bd 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -388,6 +388,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/transport/auth_filters.h', + 'src/core/lib/security/transport/lb_targets_info.h', 'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/security_connector.h', 'src/core/lib/security/transport/security_handshaker.h', @@ -420,6 +421,7 @@ Pod::Spec.new do |s| 'src/core/ext/client_channel/uri_parser.h', 'src/core/ext/transport/chttp2/client/chttp2_connector.h', 'src/core/ext/lb_policy/grpclb/grpclb.h', + 'src/core/ext/lb_policy/grpclb/grpclb_channel.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', @@ -596,6 +598,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/transport/client_auth_filter.c', + 'src/core/lib/security/transport/lb_targets_info.c', 'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/security_connector.c', 'src/core/lib/security/transport/security_handshaker.c', @@ -636,6 +639,7 @@ Pod::Spec.new do |s| 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', 'src/core/ext/lb_policy/grpclb/grpclb.c', + 'src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', @@ -813,6 +817,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/transport/auth_filters.h', + 'src/core/lib/security/transport/lb_targets_info.h', 'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/security_connector.h', 'src/core/lib/security/transport/security_handshaker.h', @@ -845,6 +850,7 @@ Pod::Spec.new do |s| 'src/core/ext/client_channel/uri_parser.h', 'src/core/ext/transport/chttp2/client/chttp2_connector.h', 'src/core/ext/lb_policy/grpclb/grpclb.h', + 'src/core/ext/lb_policy/grpclb/grpclb_channel.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', diff --git a/grpc.gemspec b/grpc.gemspec index 7b132686c8..6e7e1174da 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -305,6 +305,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h ) s.files += %w( src/core/lib/security/transport/auth_filters.h ) + s.files += %w( src/core/lib/security/transport/lb_targets_info.h ) s.files += %w( src/core/lib/security/transport/secure_endpoint.h ) s.files += %w( src/core/lib/security/transport/security_connector.h ) s.files += %w( src/core/lib/security/transport/security_handshaker.h ) @@ -337,6 +338,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_channel/uri_parser.h ) s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h ) s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.h ) + s.files += %w( src/core/ext/lb_policy/grpclb/grpclb_channel.h ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h ) s.files += %w( third_party/nanopb/pb.h ) @@ -513,6 +515,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.c ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.c ) s.files += %w( src/core/lib/security/transport/client_auth_filter.c ) + s.files += %w( src/core/lib/security/transport/lb_targets_info.c ) s.files += %w( src/core/lib/security/transport/secure_endpoint.c ) s.files += %w( src/core/lib/security/transport/security_connector.c ) s.files += %w( src/core/lib/security/transport/security_handshaker.c ) @@ -553,6 +556,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c ) s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.c ) + s.files += %w( src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c ) s.files += %w( third_party/nanopb/pb_common.c ) diff --git a/package.xml b/package.xml index e4c0e83cc7..7aa894a178 100644 --- a/package.xml +++ b/package.xml @@ -314,6 +314,7 @@ + @@ -346,6 +347,7 @@ + @@ -522,6 +524,7 @@ + @@ -562,6 +565,7 @@ + diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c index f1e4e079e2..abbbfdfd64 100644 --- a/src/core/ext/client_channel/subchannel.c +++ b/src/core/ext/client_channel/subchannel.c @@ -788,7 +788,8 @@ grpc_call_stack *grpc_subchannel_call_get_call_stack( return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); } -static void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr) { +static void grpc_uri_to_sockaddr(const char *uri_str, + grpc_resolved_address *addr) { grpc_uri *uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); GPR_ASSERT(uri != NULL); if (strcmp(uri->scheme, "ipv4") == 0) { @@ -803,14 +804,19 @@ static void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr) { void grpc_get_subchannel_address_arg(const grpc_channel_args *args, grpc_resolved_address *addr) { + const char *addr_uri_str = grpc_get_subchannel_address_uri_arg(args); + memset(addr, 0, sizeof(*addr)); + if (*addr_uri_str != '\0') { + grpc_uri_to_sockaddr(addr_uri_str, addr); + } +} + +const char *grpc_get_subchannel_address_uri_arg(const grpc_channel_args *args) { const grpc_arg *addr_arg = grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); GPR_ASSERT(addr_arg != NULL); // Should have been set by LB policy. GPR_ASSERT(addr_arg->type == GRPC_ARG_STRING); - memset(addr, 0, sizeof(*addr)); - if (*addr_arg->value.string != '\0') { - grpc_uri_to_sockaddr(addr_arg->value.string, addr); - } + return addr_arg->value.string; } grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr) { diff --git a/src/core/ext/client_channel/subchannel.h b/src/core/ext/client_channel/subchannel.h index 9bd35a7704..26ce954487 100644 --- a/src/core/ext/client_channel/subchannel.h +++ b/src/core/ext/client_channel/subchannel.h @@ -178,6 +178,9 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, void grpc_get_subchannel_address_arg(const grpc_channel_args *args, grpc_resolved_address *addr); +/// Returns the URI string for the address to connect to. +const char *grpc_get_subchannel_address_uri_arg(const grpc_channel_args *args); + /// Returns a new channel arg encoding the subchannel address as a string. /// Caller is responsible for freeing the string. grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr); diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c index 308facb7e7..ab62e5ed6a 100644 --- a/src/core/ext/lb_policy/grpclb/grpclb.c +++ b/src/core/ext/lb_policy/grpclb/grpclb.c @@ -112,11 +112,13 @@ #include "src/core/ext/client_channel/lb_policy_registry.h" #include "src/core/ext/client_channel/parse_address.h" #include "src/core/ext/lb_policy/grpclb/grpclb.h" +#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h" #include "src/core/ext/lb_policy/grpclb/load_balancer_api.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/slice/slice_hash_table.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/backoff.h" @@ -751,6 +753,96 @@ static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg, GRPC_ERROR_UNREF(error); } +static void destroy_balancer_name(grpc_exec_ctx *exec_ctx, + void *balancer_name) { + gpr_free(balancer_name); +} + +static void *copy_balancer_name(void *balancer_name) { + return gpr_strdup(balancer_name); +} + +static grpc_slice_hash_table_entry targets_info_entry_create( + const char *address, const char *balancer_name) { + static const grpc_slice_hash_table_vtable vtable = {destroy_balancer_name, + copy_balancer_name}; + grpc_slice_hash_table_entry entry; + entry.key = grpc_slice_from_copied_string(address); + entry.value = (void *)balancer_name; + entry.vtable = &vtable; + return entry; +} + +/* Returns the target URI for the LB service whose addresses are in \a + * addresses. Using this URI, a bidirectional streaming channel will be created + * for the reception of load balancing updates. + * + * The output argument \a targets_info will be updated to contain a mapping of + * "LB server address" to "balancer name", as reported by the naming system. + * This mapping will be propagated via the channel arguments of the + * aforementioned LB streaming channel, to be used by the security connector for + * secure naming checks. The user is responsible for freeing \a targets_info. */ +static char *get_lb_uri_target_addresses(grpc_exec_ctx *exec_ctx, + const grpc_lb_addresses *addresses, + grpc_slice_hash_table **targets_info) { + size_t num_grpclb_addrs = 0; + for (size_t i = 0; i < addresses->num_addresses; ++i) { + if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs; + } + /* All input addresses come from a resolver that claims they are LB services. + * It's the resolver's responsibility to make sure this policy is only + * instantiated and used in that case. Otherwise, something has gone wrong. */ + GPR_ASSERT(num_grpclb_addrs > 0); + + grpc_slice_hash_table_entry *targets_info_entries = + gpr_malloc(sizeof(*targets_info_entries) * num_grpclb_addrs); + + /* construct a target ipvX://ip1:port1,ip2:port2,... from the addresses in \a + * addresses */ + /* TODO(dgq): support mixed ip version */ + char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs); + size_t addr_index = 0; + + for (size_t i = 0; i < addresses->num_addresses; i++) { + if (addresses->addresses[i].user_data != NULL) { + gpr_log(GPR_ERROR, + "This LB policy doesn't support user data. It will be ignored"); + } + if (addresses->addresses[i].is_balancer) { + char *addr_str; + GPR_ASSERT(grpc_sockaddr_to_string( + &addr_str, &addresses->addresses[i].address, true) > 0); + targets_info_entries[addr_index] = targets_info_entry_create( + addr_str, addresses->addresses[i].balancer_name); + addr_strs[addr_index++] = addr_str; + } + } + GPR_ASSERT(addr_index == num_grpclb_addrs); + + size_t uri_path_len; + char *uri_path = gpr_strjoin_sep((const char **)addr_strs, num_grpclb_addrs, + ",", &uri_path_len); + for (size_t i = 0; i < num_grpclb_addrs; i++) gpr_free(addr_strs[i]); + gpr_free(addr_strs); + + char *target_uri_str = NULL; + /* TODO(dgq): Don't assume all addresses will share the scheme of the first + * one */ + gpr_asprintf(&target_uri_str, "%s:%s", + grpc_sockaddr_get_uri_scheme(&addresses->addresses[0].address), + uri_path); + gpr_free(uri_path); + + *targets_info = + grpc_slice_hash_table_create(num_grpclb_addrs, targets_info_entries); + for (size_t i = 0; i < num_grpclb_addrs; i++) { + grpc_slice_unref_internal(exec_ctx, targets_info_entries[i].key); + } + gpr_free(targets_info_entries); + + return target_uri_str; +} + static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { @@ -788,85 +880,30 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, } grpc_uri_destroy(uri); - /* All input addresses in addresses come from a resolver that claims - * they are LB services. It's the resolver's responsibility to make sure - * this policy is only instantiated and used in that case. - * - * Create a client channel over them to communicate with a LB service */ glb_policy->cc_factory = args->client_channel_factory; glb_policy->args = grpc_channel_args_copy(args->args); GPR_ASSERT(glb_policy->cc_factory != NULL); - /* construct a target from the addresses in args, given in the form - * ipvX://ip1:port1,ip2:port2,... - * TODO(dgq): support mixed ip version */ - char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs); - size_t addr_index = 0; - for (size_t i = 0; i < addresses->num_addresses; i++) { - if (addresses->addresses[i].user_data != NULL) { - gpr_log(GPR_ERROR, - "This LB policy doesn't support user data. It will be ignored"); - } - if (addresses->addresses[i].is_balancer) { - if (addr_index == 0) { - addr_strs[addr_index++] = - grpc_sockaddr_to_uri(&addresses->addresses[i].address); - } else { - GPR_ASSERT(grpc_sockaddr_to_string(&addr_strs[addr_index++], - &addresses->addresses[i].address, - true) > 0); - } - } - } - size_t uri_path_len; - char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs, - num_grpclb_addrs, ",", &uri_path_len); - - /* Create a channel to talk to the LBs. - * - * We strip out the channel arg for the LB policy name, since we want - * to use the default (pick_first) in this case. - * - * We also strip out the channel arg for the resolved addresses, since - * that will be generated by the name resolver used in the LB channel. - * Note that the LB channel will use the sockaddr resolver, so this - * won't actually generate a query to DNS (or some other name service). - * However, the addresses returned by the sockaddr resolver will have - * is_balancer=false, whereas our own addresses have is_balancer=true. - * We need the LB channel to return addresses with is_balancer=false - * so that it does not wind up recursively using the grpclb LB policy, - * as per the special case logic in client_channel.c. - * - * Finally, we also strip out the channel arg for the server URI, - * since that will be different for the LB channel than for the parent - * channel. (The client channel factory will re-add this arg with - * the right value.) - */ - static const char *keys_to_remove[] = { - GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI}; - grpc_channel_args *new_args = grpc_channel_args_copy_and_remove( - args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove)); - glb_policy->lb_channel = grpc_client_channel_factory_create_channel( - exec_ctx, glb_policy->cc_factory, target_uri_str, - GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args); - grpc_channel_args_destroy(exec_ctx, new_args); - - gpr_free(target_uri_str); - for (size_t i = 0; i < num_grpclb_addrs; i++) { - gpr_free(addr_strs[i]); - } - gpr_free(addr_strs); - + grpc_slice_hash_table *targets_info = NULL; + /* Create a client channel over them to communicate with a LB service */ + char *lb_service_target_addresses = + get_lb_uri_target_addresses(exec_ctx, addresses, &targets_info); + grpc_channel_args *lb_channel_args = + get_lb_channel_args(exec_ctx, targets_info, args->args); + glb_policy->lb_channel = grpc_lb_policy_grpclb_create_lb_channel( + exec_ctx, lb_service_target_addresses, args->client_channel_factory, + lb_channel_args); + grpc_slice_hash_table_unref(exec_ctx, targets_info); + grpc_channel_args_destroy(exec_ctx, lb_channel_args); + gpr_free(lb_service_target_addresses); if (glb_policy->lb_channel == NULL) { gpr_free(glb_policy); return NULL; } - grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable); gpr_mu_init(&glb_policy->mu); grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE, "grpclb"); - return &glb_policy->base; } diff --git a/src/core/ext/lb_policy/grpclb/grpclb_channel.c b/src/core/ext/lb_policy/grpclb/grpclb_channel.c new file mode 100644 index 0000000000..1b8bbab1b6 --- /dev/null +++ b/src/core/ext/lb_policy/grpclb/grpclb_channel.c @@ -0,0 +1,77 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/support/string.h" + +grpc_channel *grpc_lb_policy_grpclb_create_lb_channel( + grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses, + grpc_client_channel_factory *client_channel_factory, + grpc_channel_args *args) { + grpc_channel *lb_channel = grpc_client_channel_factory_create_channel( + exec_ctx, client_channel_factory, lb_service_target_addresses, + GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, args); + return lb_channel; +} + +grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx, + grpc_slice_hash_table *targets_info, + const grpc_channel_args *args) { + /* We strip out the channel arg for the LB policy name, since we want + * to use the default (pick_first) in this case. + * + * We also strip out the channel arg for the resolved addresses, since + * that will be generated by the name resolver used in the LB channel. + * Note that the LB channel will use the sockaddr resolver, so this + * won't actually generate a query to DNS (or some other name service). + * However, the addresses returned by the sockaddr resolver will have + * is_balancer=false, whereas our own addresses have is_balancer=true. + * We need the LB channel to return addresses with is_balancer=false + * so that it does not wind up recursively using the grpclb LB policy, + * as per the special case logic in client_channel.c. + * + * Lastly, we also strip out the channel arg for the server URI, + * since that will be different for the LB channel than for the parent + * channel (the client channel factory will re-add this arg with + * the right value). */ + static const char *keys_to_remove[] = { + GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI}; + return grpc_channel_args_copy_and_remove(args, keys_to_remove, + GPR_ARRAY_SIZE(keys_to_remove)); +} diff --git a/src/core/ext/lb_policy/grpclb/grpclb_channel.h b/src/core/ext/lb_policy/grpclb/grpclb_channel.h new file mode 100644 index 0000000000..f66082d78e --- /dev/null +++ b/src/core/ext/lb_policy/grpclb/grpclb_channel.h @@ -0,0 +1,56 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H +#define GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H + +#include "src/core/ext/client_channel/lb_policy_factory.h" +#include "src/core/lib/slice/slice_hash_table.h" + +/** Create the channel used for communicating with an LB service. + * Note that an LB *service* may be comprised of several LB *servers*. + * + * \a lb_service_target_addresses is the target URI containing the addresses + * from resolving the LB service's name (eg, ipv4:10.0.0.1:1234,10.2.3.4:9876). + * \a client_channel_factory will be used for the creation of the LB channel, + * alongside the channel args passed in \a args. */ +grpc_channel *grpc_lb_policy_grpclb_create_lb_channel( + grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses, + grpc_client_channel_factory *client_channel_factory, + grpc_channel_args *args); + +grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx, + grpc_slice_hash_table *targets_info, + const grpc_channel_args *args); + +#endif /* GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H */ diff --git a/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c b/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c new file mode 100644 index 0000000000..2fee5f1b8e --- /dev/null +++ b/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c @@ -0,0 +1,107 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/transport/lb_targets_info.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/support/string.h" + +grpc_channel *grpc_lb_policy_grpclb_create_lb_channel( + grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses, + grpc_client_channel_factory *client_channel_factory, + grpc_channel_args *args) { + grpc_channel_args *new_args = args; + grpc_channel_credentials *channel_credentials = + grpc_channel_credentials_find_in_args(args); + if (channel_credentials != NULL) { + /* Substitute the channel credentials with a version without call + * credentials: the load balancer is not necessarily trusted to handle + * bearer token credentials */ + static const char *keys_to_remove[] = {GRPC_ARG_CHANNEL_CREDENTIALS}; + grpc_channel_credentials *creds_sans_call_creds = + grpc_channel_credentials_duplicate_without_call_credentials( + channel_credentials); + GPR_ASSERT(creds_sans_call_creds != NULL); + grpc_arg args_to_add[] = { + grpc_channel_credentials_to_arg(creds_sans_call_creds)}; + /* Create the new set of channel args */ + new_args = grpc_channel_args_copy_and_add_and_remove( + args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add, + GPR_ARRAY_SIZE(args_to_add)); + grpc_channel_credentials_unref(exec_ctx, creds_sans_call_creds); + } + grpc_channel *lb_channel = grpc_client_channel_factory_create_channel( + exec_ctx, client_channel_factory, lb_service_target_addresses, + GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args); + if (channel_credentials != NULL) { + grpc_channel_args_destroy(exec_ctx, new_args); + } + return lb_channel; +} + +grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx, + grpc_slice_hash_table *targets_info, + const grpc_channel_args *args) { + const grpc_arg targets_info_arg = + grpc_lb_targets_info_create_channel_arg(targets_info); + /* We strip out the channel arg for the LB policy name, since we want + * to use the default (pick_first) in this case. + * + * We also strip out the channel arg for the resolved addresses, since + * that will be generated by the name resolver used in the LB channel. + * Note that the LB channel will use the sockaddr resolver, so this + * won't actually generate a query to DNS (or some other name service). + * However, the addresses returned by the sockaddr resolver will have + * is_balancer=false, whereas our own addresses have is_balancer=true. + * We need the LB channel to return addresses with is_balancer=false + * so that it does not wind up recursively using the grpclb LB policy, + * as per the special case logic in client_channel.c. + * + * Lastly, we also strip out the channel arg for the server URI, + * since that will be different for the LB channel than for the parent + * channel (the client channel factory will re-add this arg with + * the right value). */ + static const char *keys_to_remove[] = { + GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI}; + /* Add the targets info table to be used for secure naming */ + return grpc_channel_args_copy_and_add_and_remove( + args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &targets_info_arg, + 1); +} diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c index d17d8fa057..3e060d189a 100644 --- a/src/core/ext/lb_policy/round_robin/round_robin.c +++ b/src/core/ext/lb_policy/round_robin/round_robin.c @@ -739,6 +739,13 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, sc_args.args = new_args; grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); + if (grpc_lb_round_robin_trace) { + char *address_uri = + grpc_sockaddr_to_uri(&addresses->addresses[i].address); + gpr_log(GPR_DEBUG, "Created subchannel %p for address uri %s", + (void *)subchannel, address_uri); + gpr_free(address_uri); + } grpc_channel_args_destroy(exec_ctx, new_args); if (subchannel != NULL) { diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index d3e53984f2..d8c18eb122 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -40,10 +40,15 @@ #include "src/core/ext/client_channel/client_channel.h" #include "src/core/ext/client_channel/resolver_registry.h" +#include "src/core/ext/client_channel/uri_parser.h" #include "src/core/ext/transport/chttp2/client/chttp2_connector.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/transport/lb_targets_info.h" #include "src/core/lib/security/transport/security_connector.h" +#include "src/core/lib/slice/slice_hash_table.h" +#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/channel.h" @@ -53,12 +58,114 @@ static void client_channel_factory_ref( static void client_channel_factory_unref( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {} +static grpc_subchannel_args *get_secure_naming_subchannel_args( + grpc_exec_ctx *exec_ctx, const grpc_subchannel_args *args) { + grpc_channel_credentials *channel_credentials = + grpc_channel_credentials_find_in_args(args->args); + if (channel_credentials == NULL) { + gpr_log(GPR_ERROR, + "Can't create subchannel: channel credentials missing for secure " + "channel."); + return NULL; + } + // Make sure security connector does not already exist in args. + if (grpc_security_connector_find_in_args(args->args) != NULL) { + gpr_log(GPR_ERROR, + "Can't create subchannel: security connector already present in " + "channel args."); + return NULL; + } + // To which address are we connecting? By default, use the server URI. + const grpc_arg *server_uri_arg = + grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI); + GPR_ASSERT(server_uri_arg != NULL); + GPR_ASSERT(server_uri_arg->type == GRPC_ARG_STRING); + const char *server_uri_str = server_uri_arg->value.string; + GPR_ASSERT(server_uri_str != NULL); + grpc_uri *server_uri = + grpc_uri_parse(server_uri_str, true /* supress errors */); + GPR_ASSERT(server_uri != NULL); + const char *server_uri_path; + server_uri_path = + server_uri->path[0] == '/' ? server_uri->path + 1 : server_uri->path; + const grpc_slice_hash_table *targets_info = + grpc_lb_targets_info_find_in_args(args->args); + char *target_name_to_check = NULL; + if (targets_info != NULL) { // LB channel + // Find the balancer name for the target. + const char *target_uri_str = + grpc_get_subchannel_address_uri_arg(args->args); + grpc_uri *target_uri = + grpc_uri_parse(target_uri_str, false /* suppress errors */); + GPR_ASSERT(target_uri != NULL); + if (target_uri->path[0] != '\0') { // "path" may be empty + const grpc_slice key = grpc_slice_from_static_string( + target_uri->path[0] == '/' ? target_uri->path + 1 : target_uri->path); + const char *value = grpc_slice_hash_table_get(targets_info, key); + if (value != NULL) target_name_to_check = gpr_strdup(value); + grpc_slice_unref_internal(exec_ctx, key); + } + if (target_name_to_check == NULL) { + // If the target name to check hasn't already been set, fall back to using + // SERVER_URI + target_name_to_check = gpr_strdup(server_uri_path); + } + grpc_uri_destroy(target_uri); + } else { // regular channel: the secure name is the original server URI. + target_name_to_check = gpr_strdup(server_uri_path); + } + grpc_uri_destroy(server_uri); + GPR_ASSERT(target_name_to_check != NULL); + grpc_channel_security_connector *subchannel_security_connector = NULL; + // Create the security connector using the credentials and target name. + grpc_channel_args *new_args_from_connector = NULL; + const grpc_security_status security_status = + grpc_channel_credentials_create_security_connector( + exec_ctx, channel_credentials, target_name_to_check, args->args, + &subchannel_security_connector, &new_args_from_connector); + if (security_status != GRPC_SECURITY_OK) { + gpr_log(GPR_ERROR, + "Failed to create secure subchannel for secure name '%s'", + target_name_to_check); + gpr_free(target_name_to_check); + return NULL; + } + gpr_free(target_name_to_check); + grpc_arg new_security_connector_arg = + grpc_security_connector_to_arg(&subchannel_security_connector->base); + + grpc_channel_args *new_args = grpc_channel_args_copy_and_add( + new_args_from_connector != NULL ? new_args_from_connector : args->args, + &new_security_connector_arg, 1); + GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, &subchannel_security_connector->base, + "lb_channel_create"); + if (new_args_from_connector != NULL) { + grpc_channel_args_destroy(exec_ctx, new_args_from_connector); + } + grpc_subchannel_args *final_sc_args = gpr_malloc(sizeof(*final_sc_args)); + memcpy(final_sc_args, args, sizeof(*args)); + final_sc_args->args = new_args; + return final_sc_args; +} + static grpc_subchannel *client_channel_factory_create_subchannel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, const grpc_subchannel_args *args) { + grpc_subchannel_args *subchannel_args = + get_secure_naming_subchannel_args(exec_ctx, args); + if (subchannel_args == NULL) { + gpr_log( + GPR_ERROR, + "Failed to create subchannel arguments during subchannel creation."); + return NULL; + } grpc_connector *connector = grpc_chttp2_connector_create(); - grpc_subchannel *s = grpc_subchannel_create(exec_ctx, connector, args); + grpc_subchannel *s = + grpc_subchannel_create(exec_ctx, connector, subchannel_args); grpc_connector_unref(exec_ctx, connector); + grpc_channel_args_destroy(exec_ctx, + (grpc_channel_args *)subchannel_args->args); + gpr_free(subchannel_args); return s; } @@ -91,10 +198,10 @@ static const grpc_client_channel_factory_vtable client_channel_factory_vtable = static grpc_client_channel_factory client_channel_factory = { &client_channel_factory_vtable}; -/* Create a secure client channel: - Asynchronously: - resolve target - - connect to it (trying alternatives as presented) - - perform handshakes */ +// Create a secure client channel: +// Asynchronously: - resolve target +// - connect to it (trying alternatives as presented) +// - perform handshakes grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args, @@ -103,47 +210,25 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, GRPC_API_TRACE( "grpc_secure_channel_create(creds=%p, target=%s, args=%p, " "reserved=%p)", - 4, (creds, target, args, reserved)); + 4, ((void *)creds, target, (void *)args, (void *)reserved)); GPR_ASSERT(reserved == NULL); - // Make sure security connector does not already exist in args. - if (grpc_find_security_connector_in_args(args) != NULL) { - gpr_log(GPR_ERROR, "Cannot set security context in channel args."); + grpc_channel *channel = NULL; + if (creds != NULL) { + // Add channel args containing the client channel factory and channel + // credentials. + grpc_arg args_to_add[] = { + grpc_client_channel_factory_create_channel_arg(&client_channel_factory), + grpc_channel_credentials_to_arg(creds)}; + grpc_channel_args *new_args = grpc_channel_args_copy_and_add( + args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); + // Create channel. + channel = client_channel_factory_create_channel( + &exec_ctx, &client_channel_factory, target, + GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args); + // Clean up. + grpc_channel_args_destroy(&exec_ctx, new_args); grpc_exec_ctx_finish(&exec_ctx); - return grpc_lame_client_channel_create( - target, GRPC_STATUS_INTERNAL, - "Security connector exists in channel args."); - } - // Create security connector and construct new channel args. - grpc_channel_security_connector *security_connector; - grpc_channel_args *new_args_from_connector; - if (grpc_channel_credentials_create_security_connector( - &exec_ctx, creds, target, args, &security_connector, - &new_args_from_connector) != GRPC_SECURITY_OK) { - grpc_exec_ctx_finish(&exec_ctx); - return grpc_lame_client_channel_create( - target, GRPC_STATUS_INTERNAL, "Failed to create security connector."); - } - // Add channel args containing the client channel factory and security - // connector. - grpc_arg args_to_add[2]; - args_to_add[0] = - grpc_client_channel_factory_create_channel_arg(&client_channel_factory); - args_to_add[1] = grpc_security_connector_to_arg(&security_connector->base); - grpc_channel_args *new_args = grpc_channel_args_copy_and_add( - new_args_from_connector != NULL ? new_args_from_connector : args, - args_to_add, GPR_ARRAY_SIZE(args_to_add)); - if (new_args_from_connector != NULL) { - grpc_channel_args_destroy(&exec_ctx, new_args_from_connector); } - // Create channel. - grpc_channel *channel = client_channel_factory_create_channel( - &exec_ctx, &client_channel_factory, target, - GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args); - // Clean up. - GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &security_connector->base, - "secure_client_channel_factory_create_channel"); - grpc_channel_args_destroy(&exec_ctx, new_args); - grpc_exec_ctx_finish(&exec_ctx); return channel != NULL ? channel : grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, diff --git a/src/core/lib/iomgr/sockaddr_utils.c b/src/core/lib/iomgr/sockaddr_utils.c index 44bc2f968b..ffa62cb53c 100644 --- a/src/core/lib/iomgr/sockaddr_utils.c +++ b/src/core/lib/iomgr/sockaddr_utils.c @@ -190,31 +190,37 @@ int grpc_sockaddr_to_string(char **out, } char *grpc_sockaddr_to_uri(const grpc_resolved_address *resolved_addr) { - char *temp; - char *result; grpc_resolved_address addr_normalized; - const struct sockaddr *addr; - if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) { resolved_addr = &addr_normalized; } + const char *scheme = grpc_sockaddr_get_uri_scheme(resolved_addr); + if (scheme == NULL || strcmp("unix", scheme) == 0) { + return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr); + } + char *path = NULL; + char *uri_str = NULL; + if (grpc_sockaddr_to_string(&path, resolved_addr, + false /* suppress errors */) && + scheme != NULL) { + gpr_asprintf(&uri_str, "%s:%s", scheme, path); + } + gpr_free(path); + return uri_str != NULL ? uri_str : NULL; +} - addr = (const struct sockaddr *)resolved_addr->addr; - +const char *grpc_sockaddr_get_uri_scheme( + const grpc_resolved_address *resolved_addr) { + const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr; switch (addr->sa_family) { case AF_INET: - grpc_sockaddr_to_string(&temp, resolved_addr, 0); - gpr_asprintf(&result, "ipv4:%s", temp); - gpr_free(temp); - return result; + return "ipv4"; case AF_INET6: - grpc_sockaddr_to_string(&temp, resolved_addr, 0); - gpr_asprintf(&result, "ipv6:%s", temp); - gpr_free(temp); - return result; - default: - return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr); + return "ipv6"; + case AF_UNIX: + return "unix"; } + return NULL; } int grpc_sockaddr_get_port(const grpc_resolved_address *resolved_addr) { diff --git a/src/core/lib/iomgr/sockaddr_utils.h b/src/core/lib/iomgr/sockaddr_utils.h index 5371e360c5..2b22f11b49 100644 --- a/src/core/lib/iomgr/sockaddr_utils.h +++ b/src/core/lib/iomgr/sockaddr_utils.h @@ -84,6 +84,10 @@ int grpc_sockaddr_set_port(const grpc_resolved_address *addr, int port); int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *addr, int normalize); +/* Returns the URI string corresponding to \a addr */ char *grpc_sockaddr_to_uri(const grpc_resolved_address *addr); +/* Returns the URI scheme corresponding to \a addr */ +const char *grpc_sockaddr_get_uri_scheme(const grpc_resolved_address *addr); + #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */ diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c index 9781a22a86..b24697ce54 100644 --- a/src/core/lib/security/credentials/credentials.c +++ b/src/core/lib/security/credentials/credentials.c @@ -160,6 +160,53 @@ grpc_channel_credentials_duplicate_without_call_credentials( } } +static void credentials_pointer_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) { + grpc_channel_credentials_unref(exec_ctx, p); +} + +static void *credentials_pointer_arg_copy(void *p) { + return grpc_channel_credentials_ref(p); +} + +static int credentials_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); } + +static const grpc_arg_pointer_vtable credentials_pointer_vtable = { + credentials_pointer_arg_copy, credentials_pointer_arg_destroy, + credentials_pointer_cmp}; + +grpc_arg grpc_channel_credentials_to_arg( + grpc_channel_credentials *credentials) { + grpc_arg result; + result.type = GRPC_ARG_POINTER; + result.key = GRPC_ARG_CHANNEL_CREDENTIALS; + result.value.pointer.vtable = &credentials_pointer_vtable; + result.value.pointer.p = credentials; + return result; +} + +grpc_channel_credentials *grpc_channel_credentials_from_arg( + const grpc_arg *arg) { + if (strcmp(arg->key, GRPC_ARG_CHANNEL_CREDENTIALS)) return NULL; + if (arg->type != GRPC_ARG_POINTER) { + gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, + GRPC_ARG_CHANNEL_CREDENTIALS); + return NULL; + } + return arg->value.pointer.p; +} + +grpc_channel_credentials *grpc_channel_credentials_find_in_args( + const grpc_channel_args *args) { + size_t i; + if (args == NULL) return NULL; + for (i = 0; i < args->num_args; i++) { + grpc_channel_credentials *credentials = + grpc_channel_credentials_from_arg(&args->args[i]); + if (credentials != NULL) return credentials; + } + return NULL; +} + grpc_server_credentials *grpc_server_credentials_ref( grpc_server_credentials *creds) { if (creds == NULL) return NULL; diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h index 3011df6b8a..510b79552a 100644 --- a/src/core/lib/security/credentials/credentials.h +++ b/src/core/lib/security/credentials/credentials.h @@ -100,6 +100,8 @@ void grpc_override_well_known_credentials_path_getter( /* --- grpc_channel_credentials. --- */ +#define GRPC_ARG_CHANNEL_CREDENTIALS "grpc.channel_credentials" + typedef struct { void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c); @@ -140,6 +142,17 @@ grpc_channel_credentials * grpc_channel_credentials_duplicate_without_call_credentials( grpc_channel_credentials *creds); +/* Util to encapsulate the channel credentials in a channel arg. */ +grpc_arg grpc_channel_credentials_to_arg(grpc_channel_credentials *credentials); + +/* Util to get the channel credentials from a channel arg. */ +grpc_channel_credentials *grpc_channel_credentials_from_arg( + const grpc_arg *arg); + +/* Util to find the channel credentials from channel args. */ +grpc_channel_credentials *grpc_channel_credentials_find_in_args( + const grpc_channel_args *args); + /* --- grpc_credentials_md. --- */ typedef struct { diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c index a8679d097d..a0629f76ce 100644 --- a/src/core/lib/security/credentials/fake/fake_credentials.c +++ b/src/core/lib/security/credentials/fake/fake_credentials.c @@ -35,13 +35,13 @@ #include -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/executor.h" - #include #include #include +#include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/support/string.h" + /* -- Fake transport security credentials. -- */ static grpc_security_status fake_transport_security_create_security_connector( @@ -49,7 +49,7 @@ static grpc_security_status fake_transport_security_create_security_connector( grpc_call_credentials *call_creds, const char *target, const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args) { - *sc = grpc_fake_channel_security_connector_create(call_creds); + *sc = grpc_fake_channel_security_connector_create(call_creds, target, args); return GRPC_SECURITY_OK; } diff --git a/src/core/lib/security/credentials/fake/fake_credentials.h b/src/core/lib/security/credentials/fake/fake_credentials.h index 9cf38084a3..0fe98417c6 100644 --- a/src/core/lib/security/credentials/fake/fake_credentials.h +++ b/src/core/lib/security/credentials/fake/fake_credentials.h @@ -38,6 +38,21 @@ /* -- Fake transport security credentials. -- */ +/* Used to verify the target names given to the fake transport security + * connector. + * + * Its syntax by example: + * For LB channels: + * "backend_target_1,backend_target_2,...;lb_target_1,lb_target_2,..." + * For regular channels: + * "backend_taget_1,backend_target_2,..." + * + * That is to say, LB channels have a heading list of LB targets separated from + * the list of backend targets by a semicolon. For non-LB channels, only the + * latter is present. */ +#define GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS \ + "grpc.test_only.fake_security.expected_target" + /* Creates a fake transport security credentials object for testing. */ grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void); diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c index cf056e8008..b9bbe1b304 100644 --- a/src/core/lib/security/transport/client_auth_filter.c +++ b/src/core/lib/security/transport/client_auth_filter.c @@ -335,7 +335,7 @@ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { grpc_security_connector *sc = - grpc_find_security_connector_in_args(args->channel_args); + grpc_security_connector_find_in_args(args->channel_args); grpc_auth_context *auth_context = grpc_find_auth_context_in_args(args->channel_args); diff --git a/src/core/lib/security/transport/lb_targets_info.c b/src/core/lib/security/transport/lb_targets_info.c new file mode 100644 index 0000000000..e73483c039 --- /dev/null +++ b/src/core/lib/security/transport/lb_targets_info.c @@ -0,0 +1,70 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/security/transport/lb_targets_info.h" + +/* Channel arg key for the mapping of LB server addresses to their names for + * secure naming purposes. */ +#define GRPC_ARG_LB_SECURE_NAMING_MAP "grpc.lb_secure_naming_map" + +static void *targets_info_copy(void *p) { return grpc_slice_hash_table_ref(p); } +static void targets_info_destroy(grpc_exec_ctx *exec_ctx, void *p) { + grpc_slice_hash_table_unref(exec_ctx, p); +} +static int targets_info_cmp(void *a, void *b) { return GPR_ICMP(a, b); } +static const grpc_arg_pointer_vtable server_to_balancer_names_vtable = { + targets_info_copy, targets_info_destroy, targets_info_cmp}; + +grpc_arg grpc_lb_targets_info_create_channel_arg( + grpc_slice_hash_table *targets_info) { + grpc_arg arg; + arg.type = GRPC_ARG_POINTER; + arg.key = GRPC_ARG_LB_SECURE_NAMING_MAP; + arg.value.pointer.p = targets_info; + arg.value.pointer.vtable = &server_to_balancer_names_vtable; + return arg; +} + +grpc_slice_hash_table *grpc_lb_targets_info_find_in_args( + const grpc_channel_args *args) { + const grpc_arg *targets_info_arg = + grpc_channel_args_find(args, GRPC_ARG_LB_SECURE_NAMING_MAP); + if (targets_info_arg != NULL) { + GPR_ASSERT(targets_info_arg->type == GRPC_ARG_POINTER); + return targets_info_arg->value.pointer.p; + } + return NULL; +} diff --git a/src/core/lib/security/transport/lb_targets_info.h b/src/core/lib/security/transport/lb_targets_info.h new file mode 100644 index 0000000000..5e6cacc197 --- /dev/null +++ b/src/core/lib/security/transport/lb_targets_info.h @@ -0,0 +1,47 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H +#define GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H + +#include "src/core/lib/slice/slice_hash_table.h" + +/** Return a channel argument containing \a targets_info. */ +grpc_arg grpc_lb_targets_info_create_channel_arg( + grpc_slice_hash_table *targets_info); + +/** Return the instance of targets info in \a args or NULL */ +grpc_slice_hash_table *grpc_lb_targets_info_find_in_args( + const grpc_channel_args *args); + +#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H */ diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c index b09127811b..aeb04e33a3 100644 --- a/src/core/lib/security/transport/security_connector.c +++ b/src/core/lib/security/transport/security_connector.c @@ -43,10 +43,13 @@ #include #include "src/core/ext/transport/chttp2/alpn/alpn.h" +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "src/core/lib/security/transport/lb_targets_info.h" #include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/security/transport/security_handshaker.h" #include "src/core/lib/support/env.h" @@ -205,23 +208,23 @@ static const grpc_arg_pointer_vtable connector_pointer_vtable = { grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) { grpc_arg result; result.type = GRPC_ARG_POINTER; - result.key = GRPC_SECURITY_CONNECTOR_ARG; + result.key = GRPC_ARG_SECURITY_CONNECTOR; result.value.pointer.vtable = &connector_pointer_vtable; result.value.pointer.p = sc; return result; } grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg) { - if (strcmp(arg->key, GRPC_SECURITY_CONNECTOR_ARG)) return NULL; + if (strcmp(arg->key, GRPC_ARG_SECURITY_CONNECTOR)) return NULL; if (arg->type != GRPC_ARG_POINTER) { gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, - GRPC_SECURITY_CONNECTOR_ARG); + GRPC_ARG_SECURITY_CONNECTOR); return NULL; } return arg->value.pointer.p; } -grpc_security_connector *grpc_find_security_connector_in_args( +grpc_security_connector *grpc_security_connector_find_in_args( const grpc_channel_args *args) { size_t i; if (args == NULL) return NULL; @@ -235,11 +238,21 @@ grpc_security_connector *grpc_find_security_connector_in_args( /* -- Fake implementation. -- */ +typedef struct { + grpc_channel_security_connector base; + char *target; + char *expected_targets; + bool is_lb_channel; +} grpc_fake_channel_security_connector; + static void fake_channel_destroy(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc) { - grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc; - grpc_call_credentials_unref(exec_ctx, c->request_metadata_creds); - gpr_free(sc); + grpc_fake_channel_security_connector *c = + (grpc_fake_channel_security_connector *)sc; + grpc_call_credentials_unref(exec_ctx, c->base.request_metadata_creds); + gpr_free(c->target); + gpr_free(c->expected_targets); + gpr_free(c); } static void fake_server_destroy(grpc_exec_ctx *exec_ctx, @@ -247,6 +260,68 @@ static void fake_server_destroy(grpc_exec_ctx *exec_ctx, gpr_free(sc); } +static bool fake_check_target(const char *target_type, const char *target, + const char *set_str) { + GPR_ASSERT(target_type != NULL); + GPR_ASSERT(target != NULL); + char **set = NULL; + size_t set_size = 0; + gpr_string_split(set_str, ",", &set, &set_size); + bool found = false; + for (size_t i = 0; i < set_size; ++i) { + if (set[i] != NULL && strcmp(target, set[i]) == 0) found = true; + } + for (size_t i = 0; i < set_size; ++i) { + gpr_free(set[i]); + } + gpr_free(set); + return found; +} + +static void fake_secure_name_check(const char *target, + const char *expected_targets, + bool is_lb_channel) { + if (expected_targets == NULL) return; + char **lbs_and_backends = NULL; + size_t lbs_and_backends_size = 0; + bool success = false; + gpr_string_split(expected_targets, ";", &lbs_and_backends, + &lbs_and_backends_size); + if (lbs_and_backends_size > 2 || lbs_and_backends_size == 0) { + gpr_log(GPR_ERROR, "Invalid expected targets arg value: '%s'", + expected_targets); + goto done; + } + if (is_lb_channel) { + if (lbs_and_backends_size != 2) { + gpr_log(GPR_ERROR, + "Invalid expected targets arg value: '%s'. Expectations for LB " + "channels must be of the form 'be1,be2,be3,...;lb1,lb2,...", + expected_targets); + goto done; + } + if (!fake_check_target("LB", target, lbs_and_backends[1])) { + gpr_log(GPR_ERROR, "LB target '%s' not found in expected set '%s'", + target, lbs_and_backends[1]); + goto done; + } + success = true; + } else { + if (!fake_check_target("Backend", target, lbs_and_backends[0])) { + gpr_log(GPR_ERROR, "Backend target '%s' not found in expected set '%s'", + target, lbs_and_backends[0]); + goto done; + } + success = true; + } +done: + for (size_t i = 0; i < lbs_and_backends_size; ++i) { + gpr_free(lbs_and_backends[i]); + } + gpr_free(lbs_and_backends); + if (!success) abort(); +} + static void fake_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, @@ -277,12 +352,28 @@ static void fake_check_peer(grpc_exec_ctx *exec_ctx, grpc_auth_context_add_cstring_property( *auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, GRPC_FAKE_TRANSPORT_SECURITY_TYPE); - end: grpc_closure_sched(exec_ctx, on_peer_checked, error); tsi_peer_destruct(&peer); } +static void fake_channel_check_peer(grpc_exec_ctx *exec_ctx, + grpc_security_connector *sc, tsi_peer peer, + grpc_auth_context **auth_context, + grpc_closure *on_peer_checked) { + fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked); + grpc_fake_channel_security_connector *c = + (grpc_fake_channel_security_connector *)sc; + fake_secure_name_check(c->target, c->expected_targets, c->is_lb_channel); +} + +static void fake_server_check_peer(grpc_exec_ctx *exec_ctx, + grpc_security_connector *sc, tsi_peer peer, + grpc_auth_context **auth_context, + grpc_closure *on_peer_checked) { + fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked); +} + static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, const char *host, @@ -313,22 +404,32 @@ static void fake_server_add_handshakers(grpc_exec_ctx *exec_ctx, } static grpc_security_connector_vtable fake_channel_vtable = { - fake_channel_destroy, fake_check_peer}; + fake_channel_destroy, fake_channel_check_peer}; -static grpc_security_connector_vtable fake_server_vtable = {fake_server_destroy, - fake_check_peer}; +static grpc_security_connector_vtable fake_server_vtable = { + fake_server_destroy, fake_server_check_peer}; grpc_channel_security_connector *grpc_fake_channel_security_connector_create( - grpc_call_credentials *request_metadata_creds) { - grpc_channel_security_connector *c = gpr_malloc(sizeof(*c)); + grpc_call_credentials *request_metadata_creds, const char *target, + const grpc_channel_args *args) { + grpc_fake_channel_security_connector *c = gpr_malloc(sizeof(*c)); memset(c, 0, sizeof(*c)); - gpr_ref_init(&c->base.refcount, 1); - c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; - c->base.vtable = &fake_channel_vtable; - c->request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds); - c->check_call_host = fake_channel_check_call_host; - c->add_handshakers = fake_channel_add_handshakers; - return c; + gpr_ref_init(&c->base.base.refcount, 1); + c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; + c->base.base.vtable = &fake_channel_vtable; + c->base.request_metadata_creds = + grpc_call_credentials_ref(request_metadata_creds); + c->base.check_call_host = fake_channel_check_call_host; + c->base.add_handshakers = fake_channel_add_handshakers; + c->target = gpr_strdup(target); + const grpc_arg *expected_target_arg = + grpc_channel_args_find(args, GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS); + if (expected_target_arg != NULL) { + GPR_ASSERT(expected_target_arg->type == GRPC_ARG_STRING); + c->expected_targets = gpr_strdup(expected_target_arg->value.string); + } + c->is_lb_channel = (grpc_lb_targets_info_find_in_args(args) != NULL); + return &c->base; } grpc_server_security_connector *grpc_fake_server_security_connector_create( diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h index eba4e6d1d7..3df2fecd39 100644 --- a/src/core/lib/security/transport/security_connector.h +++ b/src/core/lib/security/transport/security_connector.h @@ -57,7 +57,7 @@ typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status; typedef struct grpc_security_connector grpc_security_connector; -#define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector" +#define GRPC_ARG_SECURITY_CONNECTOR "grpc.security_connector" typedef struct { void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc); @@ -115,7 +115,7 @@ grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc); grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg); /* Util to find the connector from channel args. */ -grpc_security_connector *grpc_find_security_connector_in_args( +grpc_security_connector *grpc_security_connector_find_in_args( const grpc_channel_args *args); /* --- channel_security_connector object. --- @@ -175,7 +175,8 @@ void grpc_server_security_connector_add_handshakers( /* For TESTING ONLY! Creates a fake connector that emulates real channel security. */ grpc_channel_security_connector *grpc_fake_channel_security_connector_create( - grpc_call_credentials *request_metadata_creds); + grpc_call_credentials *request_metadata_creds, const char *target, + const grpc_channel_args *args); /* For TESTING ONLY! Creates a fake connector that emulates real server security. */ diff --git a/src/core/lib/security/transport/security_handshaker.c b/src/core/lib/security/transport/security_handshaker.c index bb8a3bf6cd..5d57543ac5 100644 --- a/src/core/lib/security/transport/security_handshaker.c +++ b/src/core/lib/security/transport/security_handshaker.c @@ -451,7 +451,7 @@ static void client_handshaker_factory_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory, const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) { grpc_channel_security_connector *security_connector = - (grpc_channel_security_connector *)grpc_find_security_connector_in_args( + (grpc_channel_security_connector *)grpc_security_connector_find_in_args( args); grpc_channel_security_connector_add_handshakers(exec_ctx, security_connector, handshake_mgr); @@ -461,7 +461,7 @@ static void server_handshaker_factory_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *hf, const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) { grpc_server_security_connector *security_connector = - (grpc_server_security_connector *)grpc_find_security_connector_in_args( + (grpc_server_security_connector *)grpc_security_connector_find_in_args( args); grpc_server_security_connector_add_handshakers(exec_ctx, security_connector, handshake_mgr); diff --git a/src/core/lib/surface/init_secure.c b/src/core/lib/surface/init_secure.c index a44407d3bb..46b9a8f922 100644 --- a/src/core/lib/surface/init_secure.c +++ b/src/core/lib/surface/init_secure.c @@ -56,7 +56,7 @@ static bool maybe_prepend_client_auth_filter( grpc_channel_stack_builder_get_channel_arguments(builder); if (args) { for (size_t i = 0; i < args->num_args; i++) { - if (0 == strcmp(GRPC_SECURITY_CONNECTOR_ARG, args->args[i].key)) { + if (0 == strcmp(GRPC_ARG_SECURITY_CONNECTOR, args->args[i].key)) { return grpc_channel_stack_builder_prepend_filter( builder, &grpc_client_auth_filter, NULL, NULL); } diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 6bca3ed1a5..a9f20e6d2a 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -231,6 +231,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/transport/client_auth_filter.c', + 'src/core/lib/security/transport/lb_targets_info.c', 'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/security_connector.c', 'src/core/lib/security/transport/security_handshaker.c', @@ -271,6 +272,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', 'src/core/ext/lb_policy/grpclb/grpclb.c', + 'src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/test/core/end2end/fake_resolver.c b/test/core/end2end/fake_resolver.c index 8e711c6b41..4f05f69f01 100644 --- a/test/core/end2end/fake_resolver.c +++ b/test/core/end2end/fake_resolver.c @@ -154,12 +154,34 @@ static grpc_resolver* fake_resolver_create(grpc_exec_ctx* exec_ctx, grpc_uri_get_query_arg(args->uri, "lb_enabled"); const bool lb_enabled = lb_enabled_qpart != NULL && strcmp("0", lb_enabled_qpart) != 0; + + // Get the balancer's names. + const char* balancer_names = + grpc_uri_get_query_arg(args->uri, "balancer_names"); + grpc_slice_buffer balancer_names_parts; + grpc_slice_buffer_init(&balancer_names_parts); + if (balancer_names != NULL) { + const grpc_slice balancer_names_slice = + grpc_slice_from_copied_string(balancer_names); + grpc_slice_split(balancer_names_slice, ",", &balancer_names_parts); + grpc_slice_unref(balancer_names_slice); + } + // Construct addresses. grpc_slice path_slice = grpc_slice_new(args->uri->path, strlen(args->uri->path), do_nothing); grpc_slice_buffer path_parts; grpc_slice_buffer_init(&path_parts); grpc_slice_split(path_slice, ",", &path_parts); + if (balancer_names_parts.count > 0 && + path_parts.count != balancer_names_parts.count) { + gpr_log(GPR_ERROR, + "Balancer names present but mismatched with number of addresses: " + "%lu balancer names != %lu addresses", + (unsigned long)balancer_names_parts.count, + (unsigned long)path_parts.count); + return NULL; + } grpc_lb_addresses* addresses = grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */); bool errors_found = false; @@ -171,10 +193,15 @@ static grpc_resolver* fake_resolver_create(grpc_exec_ctx* exec_ctx, errors_found = true; } gpr_free(part_str); - addresses->addresses[i].is_balancer = lb_enabled; if (errors_found) break; + addresses->addresses[i].is_balancer = lb_enabled; + addresses->addresses[i].balancer_name = + balancer_names_parts.count > 0 + ? grpc_dump_slice(balancer_names_parts.slices[i], GPR_DUMP_ASCII) + : NULL; } grpc_slice_buffer_destroy_internal(exec_ctx, &path_parts); + grpc_slice_buffer_destroy_internal(exec_ctx, &balancer_names_parts); grpc_slice_unref(path_slice); if (errors_found) { grpc_lb_addresses_destroy(exec_ctx, addresses); diff --git a/test/core/surface/secure_channel_create_test.c b/test/core/surface/secure_channel_create_test.c index 280806707e..567f8ae16e 100644 --- a/test/core/surface/secure_channel_create_test.c +++ b/test/core/surface/secure_channel_create_test.c @@ -62,7 +62,7 @@ void test_security_connector_already_in_arg(void) { grpc_arg arg; arg.type = GRPC_ARG_POINTER; arg.value.pointer.p = NULL; - arg.key = GRPC_SECURITY_CONNECTOR_ARG; + arg.key = GRPC_ARG_SECURITY_CONNECTOR; grpc_channel_args args; args.num_args = 1; args.args = &arg; diff --git a/test/cpp/grpclb/grpclb_test.cc b/test/cpp/grpclb/grpclb_test.cc index 4b8a434c78..89ed9249ad 100644 --- a/test/cpp/grpclb/grpclb_test.cc +++ b/test/cpp/grpclb/grpclb_test.cc @@ -52,8 +52,10 @@ #include extern "C" { #include "src/core/ext/client_channel/client_channel.h" +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/support/string.h" #include "src/core/lib/support/tmpfile.h" #include "src/core/lib/surface/channel.h" @@ -110,6 +112,7 @@ typedef struct server_fixture { grpc_call *server_call; grpc_completion_queue *cq; char *servers_hostport; + const char *balancer_name; int port; const char *lb_token_prefix; gpr_thd_id tid; @@ -201,10 +204,12 @@ static void start_lb_server(server_fixture *sf, int *ports, size_t nports, &request_metadata_recv, sf->cq, sf->cq, tag(200)); GPR_ASSERT(GRPC_CALL_OK == error); - gpr_log(GPR_INFO, "LB Server[%s] up", sf->servers_hostport); + gpr_log(GPR_INFO, "LB Server[%s](%s) up", sf->servers_hostport, + sf->balancer_name); CQ_EXPECT_COMPLETION(cqv, tag(200), 1); cq_verify(cqv); - gpr_log(GPR_INFO, "LB Server[%s] after tag 200", sf->servers_hostport); + gpr_log(GPR_INFO, "LB Server[%s](%s) after tag 200", sf->servers_hostport, + sf->balancer_name); // make sure we've received the initial metadata from the grpclb request. GPR_ASSERT(request_metadata_recv.count > 0); @@ -221,7 +226,8 @@ static void start_lb_server(server_fixture *sf, int *ports, size_t nports, GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(202), 1); cq_verify(cqv); - gpr_log(GPR_INFO, "LB Server[%s] after RECV_MSG", sf->servers_hostport); + gpr_log(GPR_INFO, "LB Server[%s](%s) after RECV_MSG", sf->servers_hostport, + sf->balancer_name); // validate initial request. grpc_byte_buffer_reader bbr; @@ -250,7 +256,8 @@ static void start_lb_server(server_fixture *sf, int *ports, size_t nports, op++; error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(201), NULL); GPR_ASSERT(GRPC_CALL_OK == error); - gpr_log(GPR_INFO, "LB Server[%s] after tag 201", sf->servers_hostport); + gpr_log(GPR_INFO, "LB Server[%s](%s) after tag 201", sf->servers_hostport, + sf->balancer_name); for (int i = 0; i < 2; i++) { if (i == 0) { @@ -276,13 +283,14 @@ static void start_lb_server(server_fixture *sf, int *ports, size_t nports, GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(203), 1); cq_verify(cqv); - gpr_log(GPR_INFO, "LB Server[%s] after SEND_MESSAGE, iter %d", - sf->servers_hostport, i); + gpr_log(GPR_INFO, "LB Server[%s](%s) after SEND_MESSAGE, iter %d", + sf->servers_hostport, sf->balancer_name, i); grpc_byte_buffer_destroy(response_payload); grpc_slice_unref(response_payload_slice); } - gpr_log(GPR_INFO, "LB Server[%s] shutting down", sf->servers_hostport); + gpr_log(GPR_INFO, "LB Server[%s](%s) shutting down", sf->servers_hostport, + sf->balancer_name); op = ops; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; @@ -299,8 +307,8 @@ static void start_lb_server(server_fixture *sf, int *ports, size_t nports, CQ_EXPECT_COMPLETION(cqv, tag(201), 1); CQ_EXPECT_COMPLETION(cqv, tag(204), 1); cq_verify(cqv); - gpr_log(GPR_INFO, "LB Server[%s] after tag 204. All done. LB server out", - sf->servers_hostport); + gpr_log(GPR_INFO, "LB Server[%s](%s) after tag 204. All done. LB server out", + sf->servers_hostport, sf->balancer_name); grpc_call_destroy(s); @@ -561,10 +569,38 @@ static void perform_request(client_fixture *cf) { gpr_free(peer); } -static void setup_client(const char *server_hostport, client_fixture *cf) { +#define BALANCERS_NAME "lb.name" +static void setup_client(const server_fixture *lb_server, + const server_fixture *backends, client_fixture *cf) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + char *lb_uri; + // The grpclb LB policy will be automatically selected by virtue of + // the fact that the returned addresses are balancer addresses. + gpr_asprintf(&lb_uri, "test:///%s?lb_enabled=1&balancer_names=%s", + lb_server->servers_hostport, lb_server->balancer_name); + + grpc_arg expected_target_arg; + expected_target_arg.type = GRPC_ARG_STRING; + expected_target_arg.key = + const_cast(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS); + + char *expected_target_names = NULL; + const char *backends_name = lb_server->servers_hostport; + gpr_asprintf(&expected_target_names, "%s;%s", backends_name, BALANCERS_NAME); + + expected_target_arg.value.string = const_cast(expected_target_names); + grpc_channel_args *args = + grpc_channel_args_copy_and_add(NULL, &expected_target_arg, 1); + gpr_free(expected_target_names); + cf->cq = grpc_completion_queue_create(NULL); - cf->server_uri = gpr_strdup(server_hostport); - cf->client = grpc_insecure_channel_create(cf->server_uri, NULL, NULL); + cf->server_uri = lb_uri; + grpc_channel_credentials *fake_creds = + grpc_fake_transport_security_credentials_create(); + cf->client = + grpc_secure_channel_create(fake_creds, cf->server_uri, args, NULL); + grpc_channel_credentials_unref(&exec_ctx, fake_creds); + grpc_channel_args_destroy(&exec_ctx, args); } static void teardown_client(client_fixture *cf) { @@ -591,10 +627,14 @@ static void setup_server(const char *host, server_fixture *sf) { gpr_join_host_port(&sf->servers_hostport, host, sf->port); } + grpc_server_credentials *server_creds = + grpc_fake_transport_security_server_credentials_create(); + sf->server = grpc_server_create(NULL, NULL); grpc_server_register_completion_queue(sf->server, sf->cq, NULL); - GPR_ASSERT((assigned_port = grpc_server_add_insecure_http2_port( - sf->server, sf->servers_hostport)) > 0); + GPR_ASSERT((assigned_port = grpc_server_add_secure_http2_port( + sf->server, sf->servers_hostport, server_creds)) > 0); + grpc_server_credentials_release(server_creds); GPR_ASSERT(sf->port == assigned_port); grpc_server_start(sf->server); } @@ -656,17 +696,10 @@ static test_fixture setup_test_fixture(int lb_server_update_delay_ms) { } tf.lb_server.lb_token_prefix = LB_TOKEN_PREFIX; + tf.lb_server.balancer_name = BALANCERS_NAME; setup_server("127.0.0.1", &tf.lb_server); gpr_thd_new(&tf.lb_server.tid, fork_lb_server, &tf.lb_server, &options); - - char *server_uri; - // The grpclb LB policy will be automatically selected by virtue of - // the fact that the returned addresses are balancer addresses. - gpr_asprintf(&server_uri, "test:///%s?lb_enabled=1", - tf.lb_server.servers_hostport); - setup_client(server_uri, &tf.client); - gpr_free(server_uri); - + setup_client(&tf.lb_server, tf.lb_backends, &tf.client); return tf; } @@ -711,8 +744,9 @@ TEST(GrpclbTest, Updates) { // batch 1. All subsequent picks will come from the second half of the // backends, those coming in the LB update. tf_result = grpc::test_update(800); - GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced == 1); - GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 0); + GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced + + tf_result.lb_backends[1].num_calls_serviced == + 1); GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced + tf_result.lb_backends[3].num_calls_serviced > 0); @@ -728,8 +762,9 @@ TEST(GrpclbTest, Updates) { // update. In any case, the total number of serviced calls must again be equal // to four across all the backends. tf_result = grpc::test_update(2500); - GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced >= 1); - GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 1); + GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced + + tf_result.lb_backends[1].num_calls_serviced >= + 2); GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced + tf_result.lb_backends[3].num_calls_serviced > 0); diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 285b7dd321..499390eb5b 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -927,6 +927,8 @@ src/core/ext/client_channel/uri_parser.c \ src/core/ext/client_channel/uri_parser.h \ src/core/ext/lb_policy/grpclb/grpclb.c \ src/core/ext/lb_policy/grpclb/grpclb.h \ +src/core/ext/lb_policy/grpclb/grpclb_channel.h \ +src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.h \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ @@ -1191,6 +1193,8 @@ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.h \ src/core/lib/security/transport/auth_filters.h \ src/core/lib/security/transport/client_auth_filter.c \ +src/core/lib/security/transport/lb_targets_info.c \ +src/core/lib/security/transport/lb_targets_info.h \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/secure_endpoint.h \ src/core/lib/security/transport/security_connector.c \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index def360afc8..6a8c29169b 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -5197,7 +5197,7 @@ "census", "gpr", "grpc_base", - "grpc_lb_policy_grpclb", + "grpc_lb_policy_grpclb_secure", "grpc_lb_policy_pick_first", "grpc_lb_policy_round_robin", "grpc_load_reporting", @@ -7514,6 +7514,7 @@ ], "headers": [ "src/core/ext/lb_policy/grpclb/grpclb.h", + "src/core/ext/lb_policy/grpclb/grpclb_channel.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" ], @@ -7523,6 +7524,37 @@ "src": [ "src/core/ext/lb_policy/grpclb/grpclb.c", "src/core/ext/lb_policy/grpclb/grpclb.h", + "src/core/ext/lb_policy/grpclb/grpclb_channel.c", + "src/core/ext/lb_policy/grpclb/grpclb_channel.h", + "src/core/ext/lb_policy/grpclb/load_balancer_api.c", + "src/core/ext/lb_policy/grpclb/load_balancer_api.h", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" + ], + "third_party": false, + "type": "filegroup" + }, + { + "deps": [ + "gpr", + "grpc_base", + "grpc_client_channel", + "nanopb" + ], + "headers": [ + "src/core/ext/lb_policy/grpclb/grpclb.h", + "src/core/ext/lb_policy/grpclb/grpclb_channel.h", + "src/core/ext/lb_policy/grpclb/load_balancer_api.h", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" + ], + "is_filegroup": true, + "language": "c", + "name": "grpc_lb_policy_grpclb_secure", + "src": [ + "src/core/ext/lb_policy/grpclb/grpclb.c", + "src/core/ext/lb_policy/grpclb/grpclb.h", + "src/core/ext/lb_policy/grpclb/grpclb_channel.h", + "src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", @@ -7638,6 +7670,7 @@ "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/transport/auth_filters.h", + "src/core/lib/security/transport/lb_targets_info.h", "src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/security_connector.h", "src/core/lib/security/transport/security_handshaker.h", @@ -7679,6 +7712,8 @@ "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/transport/auth_filters.h", "src/core/lib/security/transport/client_auth_filter.c", + "src/core/lib/security/transport/lb_targets_info.c", + "src/core/lib/security/transport/lb_targets_info.h", "src/core/lib/security/transport/secure_endpoint.c", "src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/security_connector.c", diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index c7aa771e5f..4d010ac607 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -437,6 +437,7 @@ + @@ -469,6 +470,7 @@ + @@ -804,6 +806,8 @@ + + @@ -884,6 +888,8 @@ + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 00aa8b2781..191fc18f86 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -472,6 +472,9 @@ src\core\lib\security\transport + + src\core\lib\security\transport + src\core\lib\security\transport @@ -592,6 +595,9 @@ src\core\ext\lb_policy\grpclb + + src\core\ext\lb_policy\grpclb + src\core\ext\lb_policy\grpclb @@ -1178,6 +1184,9 @@ src\core\lib\security\transport + + src\core\lib\security\transport + src\core\lib\security\transport @@ -1274,6 +1283,9 @@ src\core\ext\lb_policy\grpclb + + src\core\ext\lb_policy\grpclb + src\core\ext\lb_policy\grpclb diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index f2c9d1ae03..6d120cc0fa 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -437,6 +437,7 @@ + @@ -802,6 +803,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index d3117bd272..c06af3fd86 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -520,6 +520,9 @@ src\core\ext\lb_policy\grpclb + + src\core\ext\lb_policy\grpclb + src\core\ext\lb_policy\grpclb @@ -1121,6 +1124,9 @@ src\core\ext\lb_policy\grpclb + + src\core\ext\lb_policy\grpclb + src\core\ext\lb_policy\grpclb -- cgit v1.2.3