diff --git a/BUILD b/BUILD index 0b6fff354f4..afeacf0239a 100644 --- a/BUILD +++ b/BUILD @@ -1618,6 +1618,7 @@ grpc_cc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.cc", "src/core/lib/security/credentials/ssl/ssl_credentials.cc", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc", + "src/core/lib/security/credentials/tls/spiffe_credentials.cc", "src/core/lib/security/security_connector/alts/alts_security_connector.cc", "src/core/lib/security/security_connector/fake/fake_security_connector.cc", "src/core/lib/security/security_connector/load_system_roots_fallback.cc", @@ -1626,6 +1627,7 @@ grpc_cc_library( "src/core/lib/security/security_connector/security_connector.cc", "src/core/lib/security/security_connector/ssl/ssl_security_connector.cc", "src/core/lib/security/security_connector/ssl_utils.cc", + "src/core/lib/security/security_connector/tls/spiffe_security_connector.cc", "src/core/lib/security/transport/client_auth_filter.cc", "src/core/lib/security/transport/secure_endpoint.cc", "src/core/lib/security/transport/security_handshaker.cc", @@ -1653,6 +1655,7 @@ grpc_cc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h", + "src/core/lib/security/credentials/tls/spiffe_credentials.h", "src/core/lib/security/security_connector/alts/alts_security_connector.h", "src/core/lib/security/security_connector/fake/fake_security_connector.h", "src/core/lib/security/security_connector/load_system_roots.h", @@ -1661,6 +1664,7 @@ grpc_cc_library( "src/core/lib/security/security_connector/security_connector.h", "src/core/lib/security/security_connector/ssl/ssl_security_connector.h", "src/core/lib/security/security_connector/ssl_utils.h", + "src/core/lib/security/security_connector/tls/spiffe_security_connector.h", "src/core/lib/security/transport/auth_filters.h", "src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/security_handshaker.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 0030c9eb9af..2308582c2f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -482,6 +482,7 @@ add_dependencies(buildtests_c h2_proxy_test) add_dependencies(buildtests_c h2_sockpair_test) add_dependencies(buildtests_c h2_sockpair+trace_test) add_dependencies(buildtests_c h2_sockpair_1byte_test) +add_dependencies(buildtests_c h2_spiffe_test) add_dependencies(buildtests_c h2_ssl_test) add_dependencies(buildtests_c h2_ssl_proxy_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -1164,6 +1165,7 @@ add_library(grpc src/core/lib/security/credentials/plugin/plugin_credentials.cc src/core/lib/security/credentials/ssl/ssl_credentials.cc src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc + src/core/lib/security/credentials/tls/spiffe_credentials.cc src/core/lib/security/security_connector/alts/alts_security_connector.cc src/core/lib/security/security_connector/fake/fake_security_connector.cc src/core/lib/security/security_connector/load_system_roots_fallback.cc @@ -1172,6 +1174,7 @@ add_library(grpc src/core/lib/security/security_connector/security_connector.cc src/core/lib/security/security_connector/ssl/ssl_security_connector.cc src/core/lib/security/security_connector/ssl_utils.cc + src/core/lib/security/security_connector/tls/spiffe_security_connector.cc src/core/lib/security/transport/client_auth_filter.cc src/core/lib/security/transport/secure_endpoint.cc src/core/lib/security/transport/security_handshaker.cc @@ -1621,6 +1624,7 @@ add_library(grpc_cronet src/core/lib/security/credentials/plugin/plugin_credentials.cc src/core/lib/security/credentials/ssl/ssl_credentials.cc src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc + src/core/lib/security/credentials/tls/spiffe_credentials.cc src/core/lib/security/security_connector/alts/alts_security_connector.cc src/core/lib/security/security_connector/fake/fake_security_connector.cc src/core/lib/security/security_connector/load_system_roots_fallback.cc @@ -1629,6 +1633,7 @@ add_library(grpc_cronet src/core/lib/security/security_connector/security_connector.cc src/core/lib/security/security_connector/ssl/ssl_security_connector.cc src/core/lib/security/security_connector/ssl_utils.cc + src/core/lib/security/security_connector/tls/spiffe_security_connector.cc src/core/lib/security/transport/client_auth_filter.cc src/core/lib/security/transport/secure_endpoint.cc src/core/lib/security/transport/security_handshaker.cc @@ -17469,6 +17474,41 @@ target_link_libraries(h2_sockpair_1byte_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(h2_spiffe_test + test/core/end2end/fixtures/h2_spiffe.cc +) + + +target_include_directories(h2_spiffe_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} +) + +target_link_libraries(h2_spiffe_test + ${_gRPC_ALLTARGETS_LIBRARIES} + end2end_tests + grpc_test_util + grpc + gpr +) + + # avoid dependency on libstdc++ + if (_gRPC_CORE_NOSTDCXX_FLAGS) + set_target_properties(h2_spiffe_test PROPERTIES LINKER_LANGUAGE C) + target_compile_options(h2_spiffe_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) + endif() + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(h2_ssl_test test/core/end2end/fixtures/h2_ssl.cc ) diff --git a/Makefile b/Makefile index 5a31d648b32..69a2abbc8ca 100644 --- a/Makefile +++ b/Makefile @@ -1361,6 +1361,7 @@ h2_proxy_test: $(BINDIR)/$(CONFIG)/h2_proxy_test h2_sockpair_test: $(BINDIR)/$(CONFIG)/h2_sockpair_test h2_sockpair+trace_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test h2_sockpair_1byte_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test +h2_spiffe_test: $(BINDIR)/$(CONFIG)/h2_spiffe_test h2_ssl_test: $(BINDIR)/$(CONFIG)/h2_ssl_test h2_ssl_proxy_test: $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test h2_uds_test: $(BINDIR)/$(CONFIG)/h2_uds_test @@ -1623,6 +1624,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/h2_sockpair_test \ $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test \ $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test \ + $(BINDIR)/$(CONFIG)/h2_spiffe_test \ $(BINDIR)/$(CONFIG)/h2_ssl_test \ $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test \ $(BINDIR)/$(CONFIG)/h2_uds_test \ @@ -3708,6 +3710,7 @@ LIBGRPC_SRC = \ src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ + src/core/lib/security/credentials/tls/spiffe_credentials.cc \ src/core/lib/security/security_connector/alts/alts_security_connector.cc \ src/core/lib/security/security_connector/fake/fake_security_connector.cc \ src/core/lib/security/security_connector/load_system_roots_fallback.cc \ @@ -3716,6 +3719,7 @@ LIBGRPC_SRC = \ src/core/lib/security/security_connector/security_connector.cc \ src/core/lib/security/security_connector/ssl/ssl_security_connector.cc \ src/core/lib/security/security_connector/ssl_utils.cc \ + src/core/lib/security/security_connector/tls/spiffe_security_connector.cc \ src/core/lib/security/transport/client_auth_filter.cc \ src/core/lib/security/transport/secure_endpoint.cc \ src/core/lib/security/transport/security_handshaker.cc \ @@ -4159,6 +4163,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ + src/core/lib/security/credentials/tls/spiffe_credentials.cc \ src/core/lib/security/security_connector/alts/alts_security_connector.cc \ src/core/lib/security/security_connector/fake/fake_security_connector.cc \ src/core/lib/security/security_connector/load_system_roots_fallback.cc \ @@ -4167,6 +4172,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/security/security_connector/security_connector.cc \ src/core/lib/security/security_connector/ssl/ssl_security_connector.cc \ src/core/lib/security/security_connector/ssl_utils.cc \ + src/core/lib/security/security_connector/tls/spiffe_security_connector.cc \ src/core/lib/security/transport/client_auth_filter.cc \ src/core/lib/security/transport/secure_endpoint.cc \ src/core/lib/security/transport/security_handshaker.cc \ @@ -24353,6 +24359,38 @@ endif endif +H2_SPIFFE_TEST_SRC = \ + test/core/end2end/fixtures/h2_spiffe.cc \ + +H2_SPIFFE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SPIFFE_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/h2_spiffe_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/h2_spiffe_test: $(H2_SPIFFE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(H2_SPIFFE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_spiffe_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_spiffe.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_h2_spiffe_test: $(H2_SPIFFE_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(H2_SPIFFE_TEST_OBJS:.o=.dep) +endif +endif + + H2_SSL_TEST_SRC = \ test/core/end2end/fixtures/h2_ssl.cc \ @@ -25572,6 +25610,7 @@ src/core/lib/security/credentials/oauth2/oauth2_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/plugin/plugin_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/ssl/ssl_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc: $(OPENSSL_DEP) +src/core/lib/security/credentials/tls/spiffe_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/alts/alts_security_connector.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/fake/fake_security_connector.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/load_system_roots_fallback.cc: $(OPENSSL_DEP) @@ -25580,6 +25619,7 @@ src/core/lib/security/security_connector/local/local_security_connector.cc: $(OP src/core/lib/security/security_connector/security_connector.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/ssl/ssl_security_connector.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/ssl_utils.cc: $(OPENSSL_DEP) +src/core/lib/security/security_connector/tls/spiffe_security_connector.cc: $(OPENSSL_DEP) src/core/lib/security/transport/client_auth_filter.cc: $(OPENSSL_DEP) src/core/lib/security/transport/secure_endpoint.cc: $(OPENSSL_DEP) src/core/lib/security/transport/security_handshaker.cc: $(OPENSSL_DEP) diff --git a/build.yaml b/build.yaml index d8322b176b7..34b271f58de 100644 --- a/build.yaml +++ b/build.yaml @@ -833,6 +833,7 @@ filegroups: - src/core/lib/security/credentials/plugin/plugin_credentials.h - src/core/lib/security/credentials/ssl/ssl_credentials.h - src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h + - src/core/lib/security/credentials/tls/spiffe_credentials.h - src/core/lib/security/security_connector/alts/alts_security_connector.h - src/core/lib/security/security_connector/fake/fake_security_connector.h - src/core/lib/security/security_connector/load_system_roots.h @@ -841,6 +842,7 @@ filegroups: - src/core/lib/security/security_connector/security_connector.h - src/core/lib/security/security_connector/ssl/ssl_security_connector.h - src/core/lib/security/security_connector/ssl_utils.h + - src/core/lib/security/security_connector/tls/spiffe_security_connector.h - src/core/lib/security/transport/auth_filters.h - src/core/lib/security/transport/secure_endpoint.h - src/core/lib/security/transport/security_handshaker.h @@ -866,6 +868,7 @@ filegroups: - src/core/lib/security/credentials/plugin/plugin_credentials.cc - src/core/lib/security/credentials/ssl/ssl_credentials.cc - src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc + - src/core/lib/security/credentials/tls/spiffe_credentials.cc - src/core/lib/security/security_connector/alts/alts_security_connector.cc - src/core/lib/security/security_connector/fake/fake_security_connector.cc - src/core/lib/security/security_connector/load_system_roots_fallback.cc @@ -874,6 +877,7 @@ filegroups: - src/core/lib/security/security_connector/security_connector.cc - src/core/lib/security/security_connector/ssl/ssl_security_connector.cc - src/core/lib/security/security_connector/ssl_utils.cc + - src/core/lib/security/security_connector/tls/spiffe_security_connector.cc - src/core/lib/security/transport/client_auth_filter.cc - src/core/lib/security/transport/secure_endpoint.cc - src/core/lib/security/transport/security_handshaker.cc diff --git a/config.m4 b/config.m4 index bb23c2ed956..b920799f49b 100644 --- a/config.m4 +++ b/config.m4 @@ -282,6 +282,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ + src/core/lib/security/credentials/tls/spiffe_credentials.cc \ src/core/lib/security/security_connector/alts/alts_security_connector.cc \ src/core/lib/security/security_connector/fake/fake_security_connector.cc \ src/core/lib/security/security_connector/load_system_roots_fallback.cc \ @@ -290,6 +291,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/security/security_connector/security_connector.cc \ src/core/lib/security/security_connector/ssl/ssl_security_connector.cc \ src/core/lib/security/security_connector/ssl_utils.cc \ + src/core/lib/security/security_connector/tls/spiffe_security_connector.cc \ src/core/lib/security/transport/client_auth_filter.cc \ src/core/lib/security/transport/secure_endpoint.cc \ src/core/lib/security/transport/security_handshaker.cc \ @@ -733,6 +735,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/security_connector/fake) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/security_connector/local) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/security_connector/ssl) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/security_connector/tls) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/transport) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/util) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/slice) diff --git a/config.w32 b/config.w32 index 35e52e15bd0..49eab2dc109 100644 --- a/config.w32 +++ b/config.w32 @@ -257,6 +257,7 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\security\\credentials\\plugin\\plugin_credentials.cc " + "src\\core\\lib\\security\\credentials\\ssl\\ssl_credentials.cc " + "src\\core\\lib\\security\\credentials\\tls\\grpc_tls_credentials_options.cc " + + "src\\core\\lib\\security\\credentials\\tls\\spiffe_credentials.cc " + "src\\core\\lib\\security\\security_connector\\alts\\alts_security_connector.cc " + "src\\core\\lib\\security\\security_connector\\fake\\fake_security_connector.cc " + "src\\core\\lib\\security\\security_connector\\load_system_roots_fallback.cc " + @@ -265,6 +266,7 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\security\\security_connector\\security_connector.cc " + "src\\core\\lib\\security\\security_connector\\ssl\\ssl_security_connector.cc " + "src\\core\\lib\\security\\security_connector\\ssl_utils.cc " + + "src\\core\\lib\\security\\security_connector\\tls\\spiffe_security_connector.cc " + "src\\core\\lib\\security\\transport\\client_auth_filter.cc " + "src\\core\\lib\\security\\transport\\secure_endpoint.cc " + "src\\core\\lib\\security\\transport\\security_handshaker.cc " + @@ -748,6 +750,7 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\security_connector\\fake"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\security_connector\\local"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\security_connector\\ssl"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\security_connector\\tls"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\transport"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\util"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\slice"); diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index e755b7aa602..5a850bc8438 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -299,6 +299,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', + 'src/core/lib/security/credentials/tls/spiffe_credentials.h', 'src/core/lib/security/security_connector/alts/alts_security_connector.h', 'src/core/lib/security/security_connector/fake/fake_security_connector.h', 'src/core/lib/security/security_connector/load_system_roots.h', @@ -307,6 +308,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/security_connector/security_connector.h', 'src/core/lib/security/security_connector/ssl/ssl_security_connector.h', 'src/core/lib/security/security_connector/ssl_utils.h', + 'src/core/lib/security/security_connector/tls/spiffe_security_connector.h', 'src/core/lib/security/transport/auth_filters.h', 'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/security_handshaker.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 7068f039870..42633186ac3 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -293,6 +293,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', + 'src/core/lib/security/credentials/tls/spiffe_credentials.h', 'src/core/lib/security/security_connector/alts/alts_security_connector.h', 'src/core/lib/security/security_connector/fake/fake_security_connector.h', 'src/core/lib/security/security_connector/load_system_roots.h', @@ -301,6 +302,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/security_connector/security_connector.h', 'src/core/lib/security/security_connector/ssl/ssl_security_connector.h', 'src/core/lib/security/security_connector/ssl_utils.h', + 'src/core/lib/security/security_connector/tls/spiffe_security_connector.h', 'src/core/lib/security/transport/auth_filters.h', 'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/security_handshaker.h', @@ -728,6 +730,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', + 'src/core/lib/security/credentials/tls/spiffe_credentials.cc', 'src/core/lib/security/security_connector/alts/alts_security_connector.cc', 'src/core/lib/security/security_connector/fake/fake_security_connector.cc', 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', @@ -736,6 +739,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/security_connector/security_connector.cc', 'src/core/lib/security/security_connector/ssl/ssl_security_connector.cc', 'src/core/lib/security/security_connector/ssl_utils.cc', + 'src/core/lib/security/security_connector/tls/spiffe_security_connector.cc', 'src/core/lib/security/transport/client_auth_filter.cc', 'src/core/lib/security/transport/secure_endpoint.cc', 'src/core/lib/security/transport/security_handshaker.cc', @@ -919,6 +923,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', + 'src/core/lib/security/credentials/tls/spiffe_credentials.h', 'src/core/lib/security/security_connector/alts/alts_security_connector.h', 'src/core/lib/security/security_connector/fake/fake_security_connector.h', 'src/core/lib/security/security_connector/load_system_roots.h', @@ -927,6 +932,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/security_connector/security_connector.h', 'src/core/lib/security/security_connector/ssl/ssl_security_connector.h', 'src/core/lib/security/security_connector/ssl_utils.h', + 'src/core/lib/security/security_connector/tls/spiffe_security_connector.h', 'src/core/lib/security/transport/auth_filters.h', 'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/security_handshaker.h', diff --git a/grpc.gemspec b/grpc.gemspec index 5c749dd285d..d9fc6ef0ebc 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -223,6 +223,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/credentials/tls/grpc_tls_credentials_options.h ) + s.files += %w( src/core/lib/security/credentials/tls/spiffe_credentials.h ) s.files += %w( src/core/lib/security/security_connector/alts/alts_security_connector.h ) s.files += %w( src/core/lib/security/security_connector/fake/fake_security_connector.h ) s.files += %w( src/core/lib/security/security_connector/load_system_roots.h ) @@ -231,6 +232,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/security_connector/security_connector.h ) s.files += %w( src/core/lib/security/security_connector/ssl/ssl_security_connector.h ) s.files += %w( src/core/lib/security/security_connector/ssl_utils.h ) + s.files += %w( src/core/lib/security/security_connector/tls/spiffe_security_connector.h ) s.files += %w( src/core/lib/security/transport/auth_filters.h ) s.files += %w( src/core/lib/security/transport/secure_endpoint.h ) s.files += %w( src/core/lib/security/transport/security_handshaker.h ) @@ -662,6 +664,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.cc ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.cc ) s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc ) + s.files += %w( src/core/lib/security/credentials/tls/spiffe_credentials.cc ) s.files += %w( src/core/lib/security/security_connector/alts/alts_security_connector.cc ) s.files += %w( src/core/lib/security/security_connector/fake/fake_security_connector.cc ) s.files += %w( src/core/lib/security/security_connector/load_system_roots_fallback.cc ) @@ -670,6 +673,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/security_connector/security_connector.cc ) s.files += %w( src/core/lib/security/security_connector/ssl/ssl_security_connector.cc ) s.files += %w( src/core/lib/security/security_connector/ssl_utils.cc ) + s.files += %w( src/core/lib/security/security_connector/tls/spiffe_security_connector.cc ) s.files += %w( src/core/lib/security/transport/client_auth_filter.cc ) s.files += %w( src/core/lib/security/transport/secure_endpoint.cc ) s.files += %w( src/core/lib/security/transport/security_handshaker.cc ) diff --git a/grpc.gyp b/grpc.gyp index cce9f738fbd..b3795cbfd06 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -464,6 +464,7 @@ 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', + 'src/core/lib/security/credentials/tls/spiffe_credentials.cc', 'src/core/lib/security/security_connector/alts/alts_security_connector.cc', 'src/core/lib/security/security_connector/fake/fake_security_connector.cc', 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', @@ -472,6 +473,7 @@ 'src/core/lib/security/security_connector/security_connector.cc', 'src/core/lib/security/security_connector/ssl/ssl_security_connector.cc', 'src/core/lib/security/security_connector/ssl_utils.cc', + 'src/core/lib/security/security_connector/tls/spiffe_security_connector.cc', 'src/core/lib/security/transport/client_auth_filter.cc', 'src/core/lib/security/transport/secure_endpoint.cc', 'src/core/lib/security/transport/security_handshaker.cc', diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index 9b7822627e0..f1185d2b2a6 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -720,7 +720,7 @@ struct grpc_tls_credential_reload_arg { grpc_tls_on_credential_reload_done_cb cb; void* cb_user_data; grpc_tls_key_materials_config* key_materials_config; - grpc_status_code status; + grpc_ssl_certificate_config_reload_status status; const char* error_details; }; @@ -767,17 +767,19 @@ typedef void (*grpc_tls_on_server_authorization_check_done_cb)( /** A struct containing all information necessary to schedule/cancel a server authorization check request. cb and cb_user_data represent a gRPC-provided - callback and an argument passed to it. result will store the result of - server authorization check. target_name is the name of an endpoint the - channel is connecting to and certificate represents a complete certificate - chain including both signing and leaf certificates. status and error_details - contain information about errors occurred when a server authorization check - request is scheduled/cancelled. It is used for experimental purpose for now - and subject to change.*/ + callback and an argument passed to it. success will store the result of + server authorization check. That is, if success returns a non-zero value, it + means the authorization check passes and if returning zero, it means the + check fails. target_name is the name of an endpoint the channel is connecting + to and certificate represents a complete certificate chain including both + signing and leaf certificates. status and error_details contain information + about errors occurred when a server authorization check request is + scheduled/cancelled. It is used for experimental purpose for now and subject + to change.*/ struct grpc_tls_server_authorization_check_arg { grpc_tls_on_server_authorization_check_done_cb cb; void* cb_user_data; - int result; + int success; const char* target_name; const char* peer_cert; grpc_status_code status; @@ -813,6 +815,37 @@ grpc_tls_server_authorization_check_config_create( grpc_tls_server_authorization_check_arg* arg), void (*destruct)(void* config_user_data)); +/** --- SPIFFE channel/server credentials --- **/ + +/** + * This method creates a TLS SPIFFE channel credential object. + * It takes ownership of the options parameter. + * + * - options: grpc TLS credentials options instance. + * + * It returns the created credential object. + * + * It is used for experimental purpose for now and subject + * to change. + */ + +grpc_channel_credentials* grpc_tls_spiffe_credentials_create( + grpc_tls_credentials_options* options); + +/** + * This method creates a TLS server credential object. + * It takes ownership of the options parameter. + * + * - options: grpc TLS credentials options instance. + * + * It returns the created credential object. + * + * It is used for experimental purpose for now and subject + * to change. + */ +grpc_server_credentials* grpc_tls_spiffe_server_credentials_create( + grpc_tls_credentials_options* options); + #ifdef __cplusplus } #endif diff --git a/package.xml b/package.xml index be7e258b98a..48ccdeff73b 100644 --- a/package.xml +++ b/package.xml @@ -228,6 +228,7 @@ + @@ -236,6 +237,7 @@ + @@ -667,6 +669,7 @@ + @@ -675,6 +678,7 @@ + diff --git a/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h index 71410d20a8f..aee9292acb8 100644 --- a/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +++ b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h @@ -167,19 +167,16 @@ struct grpc_tls_credentials_options grpc_ssl_client_certificate_request_type cert_request_type() const { return cert_request_type_; } - const grpc_tls_key_materials_config* key_materials_config() const { + grpc_tls_key_materials_config* key_materials_config() const { return key_materials_config_.get(); } - const grpc_tls_credential_reload_config* credential_reload_config() const { + grpc_tls_credential_reload_config* credential_reload_config() const { return credential_reload_config_.get(); } - const grpc_tls_server_authorization_check_config* + grpc_tls_server_authorization_check_config* server_authorization_check_config() const { return server_authorization_check_config_.get(); } - grpc_tls_key_materials_config* mutable_key_materials_config() { - return key_materials_config_.get(); - } /* Setters for member fields. */ void set_cert_request_type( diff --git a/src/core/lib/security/credentials/tls/spiffe_credentials.cc b/src/core/lib/security/credentials/tls/spiffe_credentials.cc new file mode 100644 index 00000000000..da764936c76 --- /dev/null +++ b/src/core/lib/security/credentials/tls/spiffe_credentials.cc @@ -0,0 +1,129 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/credentials/tls/spiffe_credentials.h" + +#include + +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/security/security_connector/tls/spiffe_security_connector.h" + +#define GRPC_CREDENTIALS_TYPE_SPIFFE "Spiffe" + +namespace { + +bool CredentialOptionSanityCheck(const grpc_tls_credentials_options* options, + bool is_client) { + if (options == nullptr) { + gpr_log(GPR_ERROR, "SPIFFE TLS credentials options is nullptr."); + return false; + } + if (options->key_materials_config() == nullptr && + options->credential_reload_config() == nullptr) { + gpr_log( + GPR_ERROR, + "SPIFFE TLS credentials options must specify either key materials or " + "credential reload config."); + return false; + } + if (!is_client && options->server_authorization_check_config() != nullptr) { + gpr_log(GPR_INFO, + "Server's credentials options should not contain server " + "authorization check config."); + } + return true; +} + +} // namespace + +SpiffeCredentials::SpiffeCredentials( + grpc_core::RefCountedPtr options) + : grpc_channel_credentials(GRPC_CREDENTIALS_TYPE_SPIFFE), + options_(std::move(options)) {} + +SpiffeCredentials::~SpiffeCredentials() {} + +grpc_core::RefCountedPtr +SpiffeCredentials::create_security_connector( + grpc_core::RefCountedPtr call_creds, + const char* target_name, const grpc_channel_args* args, + grpc_channel_args** new_args) { + const char* overridden_target_name = nullptr; + tsi_ssl_session_cache* ssl_session_cache = nullptr; + for (size_t i = 0; args != nullptr && i < args->num_args; i++) { + grpc_arg* arg = &args->args[i]; + if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 && + arg->type == GRPC_ARG_STRING) { + overridden_target_name = arg->value.string; + } + if (strcmp(arg->key, GRPC_SSL_SESSION_CACHE_ARG) == 0 && + arg->type == GRPC_ARG_POINTER) { + ssl_session_cache = + static_cast(arg->value.pointer.p); + } + } + grpc_core::RefCountedPtr sc = + SpiffeChannelSecurityConnector::CreateSpiffeChannelSecurityConnector( + this->Ref(), std::move(call_creds), target_name, + overridden_target_name, ssl_session_cache); + if (sc == nullptr) { + return nullptr; + } + grpc_arg new_arg = grpc_channel_arg_string_create( + (char*)GRPC_ARG_HTTP2_SCHEME, (char*)"https"); + *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1); + return sc; +} + +SpiffeServerCredentials::SpiffeServerCredentials( + grpc_core::RefCountedPtr options) + : grpc_server_credentials(GRPC_CREDENTIALS_TYPE_SPIFFE), + options_(std::move(options)) {} + +SpiffeServerCredentials::~SpiffeServerCredentials() {} + +grpc_core::RefCountedPtr +SpiffeServerCredentials::create_security_connector() { + return SpiffeServerSecurityConnector::CreateSpiffeServerSecurityConnector( + this->Ref()); +} + +grpc_channel_credentials* grpc_tls_spiffe_credentials_create( + grpc_tls_credentials_options* options) { + if (!CredentialOptionSanityCheck(options, true /* is_client */)) { + return nullptr; + } + return grpc_core::New( + grpc_core::RefCountedPtr(options)); +} + +grpc_server_credentials* grpc_tls_spiffe_server_credentials_create( + grpc_tls_credentials_options* options) { + if (!CredentialOptionSanityCheck(options, false /* is_client */)) { + return nullptr; + } + return grpc_core::New( + grpc_core::RefCountedPtr(options)); +} diff --git a/src/core/lib/security/credentials/tls/spiffe_credentials.h b/src/core/lib/security/credentials/tls/spiffe_credentials.h new file mode 100644 index 00000000000..4985fda4a7e --- /dev/null +++ b/src/core/lib/security/credentials/tls/spiffe_credentials.h @@ -0,0 +1,62 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_SPIFFE_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_SPIFFE_CREDENTIALS_H + +#include + +#include + +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" + +class SpiffeCredentials final : public grpc_channel_credentials { + public: + explicit SpiffeCredentials( + grpc_core::RefCountedPtr options); + ~SpiffeCredentials() override; + + grpc_core::RefCountedPtr + create_security_connector( + grpc_core::RefCountedPtr call_creds, + const char* target_name, const grpc_channel_args* args, + grpc_channel_args** new_args) override; + + const grpc_tls_credentials_options& options() const { return *options_; } + + private: + grpc_core::RefCountedPtr options_; +}; + +class SpiffeServerCredentials final : public grpc_server_credentials { + public: + explicit SpiffeServerCredentials( + grpc_core::RefCountedPtr options); + ~SpiffeServerCredentials() override; + + grpc_core::RefCountedPtr + create_security_connector() override; + + const grpc_tls_credentials_options& options() const { return *options_; } + + private: + grpc_core::RefCountedPtr options_; +}; + +#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_SPIFFE_CREDENTIALS_H */ diff --git a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc index 8a00bbb82ed..39c5434208b 100644 --- a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +++ b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc @@ -41,33 +41,6 @@ #include "src/core/tsi/transport_security.h" namespace { -grpc_error* ssl_check_peer( - const char* peer_name, const tsi_peer* peer, - grpc_core::RefCountedPtr* auth_context) { -#if TSI_OPENSSL_ALPN_SUPPORT - /* Check the ALPN if ALPN is supported. */ - const tsi_peer_property* p = - tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); - if (p == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Cannot check peer: missing selected ALPN property."); - } - if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Cannot check peer: invalid ALPN value."); - } -#endif /* TSI_OPENSSL_ALPN_SUPPORT */ - /* Check the peer name if specified. */ - if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) { - char* msg; - gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name); - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); - gpr_free(msg); - return error; - } - *auth_context = grpc_ssl_peer_to_auth_context(peer); - return GRPC_ERROR_NONE; -} class grpc_ssl_channel_security_connector final : public grpc_channel_security_connector { @@ -96,34 +69,10 @@ class grpc_ssl_channel_security_connector final } grpc_security_status InitializeHandshakerFactory( - const grpc_ssl_config* config, const char* pem_root_certs, - const tsi_ssl_root_certs_store* root_store, - tsi_ssl_session_cache* ssl_session_cache) { - bool has_key_cert_pair = - config->pem_key_cert_pair != nullptr && - config->pem_key_cert_pair->private_key != nullptr && - config->pem_key_cert_pair->cert_chain != nullptr; - tsi_ssl_client_handshaker_options options; - GPR_DEBUG_ASSERT(pem_root_certs != nullptr); - options.pem_root_certs = pem_root_certs; - options.root_store = root_store; - options.alpn_protocols = - grpc_fill_alpn_protocol_strings(&options.num_alpn_protocols); - if (has_key_cert_pair) { - options.pem_key_cert_pair = config->pem_key_cert_pair; - } - options.cipher_suites = grpc_get_ssl_cipher_suites(); - options.session_cache = ssl_session_cache; - const tsi_result result = - tsi_create_ssl_client_handshaker_factory_with_options( - &options, &client_handshaker_factory_); - gpr_free((void*)options.alpn_protocols); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", - tsi_result_to_string(result)); - return GRPC_SECURITY_ERROR; - } - return GRPC_SECURITY_OK; + const grpc_ssl_config* config, tsi_ssl_session_cache* ssl_session_cache) { + return grpc_ssl_tsi_client_handshaker_factory_init( + config->pem_key_cert_pair, config->pem_root_certs, ssl_session_cache, + &client_handshaker_factory_); } void add_handshakers(grpc_pollset_set* interested_parties, @@ -150,29 +99,35 @@ class grpc_ssl_channel_security_connector final const char* target_name = overridden_target_name_ != nullptr ? overridden_target_name_ : target_name_; - grpc_error* error = ssl_check_peer(target_name, &peer, auth_context); - if (error == GRPC_ERROR_NONE && - verify_options_->verify_peer_callback != nullptr) { - const tsi_peer_property* p = - tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY); - if (p == nullptr) { - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Cannot check peer: missing pem cert property."); - } else { - char* peer_pem = static_cast(gpr_malloc(p->value.length + 1)); - memcpy(peer_pem, p->value.data, p->value.length); - peer_pem[p->value.length] = '\0'; - int callback_status = verify_options_->verify_peer_callback( - target_name, peer_pem, - verify_options_->verify_peer_callback_userdata); - gpr_free(peer_pem); - if (callback_status) { - char* msg; - gpr_asprintf(&msg, "Verify peer callback returned a failure (%d)", - callback_status); - error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); - gpr_free(msg); + grpc_error* error = grpc_ssl_check_alpn(&peer); + if (error == GRPC_ERROR_NONE) { + error = grpc_ssl_check_peer_name(target_name, &peer); + if (error == GRPC_ERROR_NONE) { + if (verify_options_->verify_peer_callback != nullptr) { + const tsi_peer_property* p = + tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY); + if (p == nullptr) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Cannot check peer: missing pem cert property."); + } else { + char* peer_pem = + static_cast(gpr_malloc(p->value.length + 1)); + memcpy(peer_pem, p->value.data, p->value.length); + peer_pem[p->value.length] = '\0'; + int callback_status = verify_options_->verify_peer_callback( + target_name, peer_pem, + verify_options_->verify_peer_callback_userdata); + gpr_free(peer_pem); + if (callback_status) { + char* msg; + gpr_asprintf(&msg, "Verify peer callback returned a failure (%d)", + callback_status); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + gpr_free(msg); + } + } } + *auth_context = grpc_ssl_peer_to_auth_context(&peer); } } GRPC_CLOSURE_SCHED(on_peer_checked, error); @@ -184,34 +139,16 @@ class grpc_ssl_channel_security_connector final reinterpret_cast(other_sc); int c = channel_security_connector_cmp(other); if (c != 0) return c; - c = strcmp(target_name_, other->target_name_); - if (c != 0) return c; - return (overridden_target_name_ == nullptr || - other->overridden_target_name_ == nullptr) - ? GPR_ICMP(overridden_target_name_, - other->overridden_target_name_) - : strcmp(overridden_target_name_, - other->overridden_target_name_); + return grpc_ssl_cmp_target_name(target_name_, other->target_name_, + overridden_target_name_, + other->overridden_target_name_); } bool check_call_host(const char* host, grpc_auth_context* auth_context, grpc_closure* on_call_host_checked, grpc_error** error) override { - grpc_security_status status = GRPC_SECURITY_ERROR; - tsi_peer peer = grpc_shallow_peer_from_ssl_auth_context(auth_context); - if (grpc_ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK; - /* If the target name was overridden, then the original target_name was - 'checked' transitively during the previous peer check at the end of the - handshake. */ - if (overridden_target_name_ != nullptr && strcmp(host, target_name_) == 0) { - status = GRPC_SECURITY_OK; - } - if (status != GRPC_SECURITY_OK) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "call host does not match SSL server name"); - } - grpc_shallow_peer_destruct(&peer); - return true; + return grpc_ssl_check_call_host(host, target_name_, overridden_target_name_, + auth_context, on_call_host_checked, error); } void cancel_check_call_host(grpc_closure* on_call_host_checked, @@ -248,43 +185,25 @@ class grpc_ssl_server_security_connector } grpc_security_status InitializeHandshakerFactory() { + grpc_security_status retval = GRPC_SECURITY_OK; if (has_cert_config_fetcher()) { // Load initial credentials from certificate_config_fetcher: if (!try_fetch_ssl_server_credentials()) { gpr_log(GPR_ERROR, "Failed loading SSL server credentials from fetcher."); - return GRPC_SECURITY_ERROR; + retval = GRPC_SECURITY_ERROR; } } else { auto* server_credentials = static_cast(server_creds()); - size_t num_alpn_protocols = 0; - const char** alpn_protocol_strings = - grpc_fill_alpn_protocol_strings(&num_alpn_protocols); - tsi_ssl_server_handshaker_options options; - options.pem_key_cert_pairs = - server_credentials->config().pem_key_cert_pairs; - options.num_key_cert_pairs = - server_credentials->config().num_key_cert_pairs; - options.pem_client_root_certs = - server_credentials->config().pem_root_certs; - options.client_certificate_request = - grpc_get_tsi_client_certificate_request_type( - server_credentials->config().client_certificate_request); - options.cipher_suites = grpc_get_ssl_cipher_suites(); - options.alpn_protocols = alpn_protocol_strings; - options.num_alpn_protocols = static_cast(num_alpn_protocols); - const tsi_result result = - tsi_create_ssl_server_handshaker_factory_with_options( - &options, &server_handshaker_factory_); - gpr_free((void*)alpn_protocol_strings); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", - tsi_result_to_string(result)); - return GRPC_SECURITY_ERROR; - } + retval = grpc_ssl_tsi_server_handshaker_factory_init( + server_credentials->config().pem_key_cert_pairs, + server_credentials->config().num_key_cert_pairs, + server_credentials->config().pem_root_certs, + server_credentials->config().client_certificate_request, + &server_handshaker_factory_); } - return GRPC_SECURITY_OK; + return retval; } void add_handshakers(grpc_pollset_set* interested_parties, @@ -306,7 +225,8 @@ class grpc_ssl_server_security_connector void check_peer(tsi_peer peer, grpc_endpoint* ep, grpc_core::RefCountedPtr* auth_context, grpc_closure* on_peer_checked) override { - grpc_error* error = ssl_check_peer(nullptr, &peer, auth_context); + grpc_error* error = grpc_ssl_check_alpn(&peer); + *auth_context = grpc_ssl_peer_to_auth_context(&peer); tsi_peer_destruct(&peer); GRPC_CLOSURE_SCHED(on_peer_checked, error); } @@ -323,9 +243,7 @@ class grpc_ssl_server_security_connector bool try_fetch_ssl_server_credentials() { grpc_ssl_server_certificate_config* certificate_config = nullptr; bool status; - if (!has_cert_config_fetcher()) return false; - grpc_ssl_server_credentials* server_creds = static_cast(this->mutable_server_creds()); grpc_ssl_certificate_config_reload_status cb_result = @@ -342,7 +260,6 @@ class grpc_ssl_server_security_connector "use previously-loaded credentials."); status = false; } - if (certificate_config != nullptr) { grpc_ssl_server_certificate_config_destroy(certificate_config); } @@ -361,34 +278,18 @@ class grpc_ssl_server_security_connector "config."); return false; } - gpr_log(GPR_DEBUG, "Using new server certificate config (%p).", config); - - size_t num_alpn_protocols = 0; - const char** alpn_protocol_strings = - grpc_fill_alpn_protocol_strings(&num_alpn_protocols); - tsi_ssl_server_handshaker_factory* new_handshaker_factory = nullptr; - const grpc_ssl_server_credentials* server_creds = + tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = + grpc_convert_grpc_to_tsi_cert_pairs(config->pem_key_cert_pairs, + config->num_key_cert_pairs); + const grpc_ssl_server_credentials* server_credentials = static_cast(this->server_creds()); - GPR_DEBUG_ASSERT(config->pem_root_certs != nullptr); - tsi_ssl_server_handshaker_options options; - options.pem_key_cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs( - config->pem_key_cert_pairs, config->num_key_cert_pairs); - options.num_key_cert_pairs = config->num_key_cert_pairs; - options.pem_client_root_certs = config->pem_root_certs; - options.client_certificate_request = - grpc_get_tsi_client_certificate_request_type( - server_creds->config().client_certificate_request); - options.cipher_suites = grpc_get_ssl_cipher_suites(); - options.alpn_protocols = alpn_protocol_strings; - options.num_alpn_protocols = static_cast(num_alpn_protocols); - tsi_result result = tsi_create_ssl_server_handshaker_factory_with_options( - &options, &new_handshaker_factory); - gpr_free((void*)options.pem_key_cert_pairs); - gpr_free((void*)alpn_protocol_strings); - - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", - tsi_result_to_string(result)); + tsi_ssl_server_handshaker_factory* new_handshaker_factory = nullptr; + grpc_security_status retval = grpc_ssl_tsi_server_handshaker_factory_init( + pem_key_cert_pairs, config->num_key_cert_pairs, config->pem_root_certs, + server_credentials->config().client_certificate_request, + &new_handshaker_factory); + gpr_free(pem_key_cert_pairs); + if (retval != GRPC_SECURITY_OK) { return false; } set_server_handshaker_factory(new_handshaker_factory); @@ -418,28 +319,12 @@ grpc_ssl_channel_security_connector_create( gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name."); return nullptr; } - - const char* pem_root_certs; - const tsi_ssl_root_certs_store* root_store; - if (config->pem_root_certs == nullptr) { - // Use default root certificates. - pem_root_certs = grpc_core::DefaultSslRootStore::GetPemRootCerts(); - if (pem_root_certs == nullptr) { - gpr_log(GPR_ERROR, "Could not get default pem root certs."); - return nullptr; - } - root_store = grpc_core::DefaultSslRootStore::GetRootStore(); - } else { - pem_root_certs = config->pem_root_certs; - root_store = nullptr; - } - grpc_core::RefCountedPtr c = grpc_core::MakeRefCounted( std::move(channel_creds), std::move(request_metadata_creds), config, target_name, overridden_target_name); - const grpc_security_status result = c->InitializeHandshakerFactory( - config, pem_root_certs, root_store, ssl_session_cache); + const grpc_security_status result = + c->InitializeHandshakerFactory(config, ssl_session_cache); if (result != GRPC_SECURITY_OK) { return nullptr; } diff --git a/src/core/lib/security/security_connector/ssl_utils.cc b/src/core/lib/security/security_connector/ssl_utils.cc index 29030f07ad6..c9af5ca6ad0 100644 --- a/src/core/lib/security/security_connector/ssl_utils.cc +++ b/src/core/lib/security/security_connector/ssl_utils.cc @@ -112,6 +112,55 @@ grpc_get_tsi_client_certificate_request_type( } } +grpc_error* grpc_ssl_check_alpn(const tsi_peer* peer) { +#if TSI_OPENSSL_ALPN_SUPPORT + /* Check the ALPN if ALPN is supported. */ + const tsi_peer_property* p = + tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); + if (p == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Cannot check peer: missing selected ALPN property."); + } + if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Cannot check peer: invalid ALPN value."); + } +#endif /* TSI_OPENSSL_ALPN_SUPPORT */ + return GRPC_ERROR_NONE; +} + +grpc_error* grpc_ssl_check_peer_name(const char* peer_name, + const tsi_peer* peer) { + /* Check the peer name if specified. */ + if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) { + char* msg; + gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name); + grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + gpr_free(msg); + return error; + } + return GRPC_ERROR_NONE; +} + +bool grpc_ssl_check_call_host(const char* host, const char* target_name, + const char* overridden_target_name, + grpc_auth_context* auth_context, + grpc_closure* on_call_host_checked, + grpc_error** error) { + grpc_security_status status = GRPC_SECURITY_ERROR; + tsi_peer peer = grpc_shallow_peer_from_ssl_auth_context(auth_context); + if (grpc_ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK; + if (overridden_target_name != nullptr && strcmp(host, target_name) == 0) { + status = GRPC_SECURITY_OK; + } + if (status != GRPC_SECURITY_OK) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "call host does not match SSL server name"); + } + grpc_shallow_peer_destruct(&peer); + return true; +} + const char** grpc_fill_alpn_protocol_strings(size_t* num_alpn_protocols) { GPR_ASSERT(num_alpn_protocols != nullptr); *num_alpn_protocols = grpc_chttp2_num_alpn_versions(); @@ -142,6 +191,18 @@ int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name) { return r; } +bool grpc_ssl_cmp_target_name(const char* target_name, + const char* other_target_name, + const char* overridden_target_name, + const char* other_overridden_target_name) { + int c = strcmp(target_name, other_target_name); + if (c != 0) return c; + return (overridden_target_name == nullptr || + other_overridden_target_name == nullptr) + ? GPR_ICMP(overridden_target_name, other_overridden_target_name) + : strcmp(overridden_target_name, other_overridden_target_name); +} + grpc_core::RefCountedPtr grpc_ssl_peer_to_auth_context( const tsi_peer* peer) { size_t i; @@ -230,6 +291,79 @@ void grpc_shallow_peer_destruct(tsi_peer* peer) { if (peer->properties != nullptr) gpr_free(peer->properties); } +grpc_security_status grpc_ssl_tsi_client_handshaker_factory_init( + tsi_ssl_pem_key_cert_pair* pem_key_cert_pair, const char* pem_root_certs, + tsi_ssl_session_cache* ssl_session_cache, + tsi_ssl_client_handshaker_factory** handshaker_factory) { + const char* root_certs; + const tsi_ssl_root_certs_store* root_store; + if (pem_root_certs == nullptr) { + // Use default root certificates. + root_certs = grpc_core::DefaultSslRootStore::GetPemRootCerts(); + if (root_certs == nullptr) { + gpr_log(GPR_ERROR, "Could not get default pem root certs."); + return GRPC_SECURITY_ERROR; + } + root_store = grpc_core::DefaultSslRootStore::GetRootStore(); + } else { + root_certs = pem_root_certs; + root_store = nullptr; + } + bool has_key_cert_pair = pem_key_cert_pair != nullptr && + pem_key_cert_pair->private_key != nullptr && + pem_key_cert_pair->cert_chain != nullptr; + tsi_ssl_client_handshaker_options options; + GPR_DEBUG_ASSERT(root_certs != nullptr); + options.pem_root_certs = root_certs; + options.root_store = root_store; + options.alpn_protocols = + grpc_fill_alpn_protocol_strings(&options.num_alpn_protocols); + if (has_key_cert_pair) { + options.pem_key_cert_pair = pem_key_cert_pair; + } + options.cipher_suites = grpc_get_ssl_cipher_suites(); + options.session_cache = ssl_session_cache; + const tsi_result result = + tsi_create_ssl_client_handshaker_factory_with_options(&options, + handshaker_factory); + gpr_free((void*)options.alpn_protocols); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", + tsi_result_to_string(result)); + return GRPC_SECURITY_ERROR; + } + return GRPC_SECURITY_OK; +} + +grpc_security_status grpc_ssl_tsi_server_handshaker_factory_init( + tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs, size_t num_key_cert_pairs, + const char* pem_root_certs, + grpc_ssl_client_certificate_request_type client_certificate_request, + tsi_ssl_server_handshaker_factory** handshaker_factory) { + size_t num_alpn_protocols = 0; + const char** alpn_protocol_strings = + grpc_fill_alpn_protocol_strings(&num_alpn_protocols); + tsi_ssl_server_handshaker_options options; + options.pem_key_cert_pairs = pem_key_cert_pairs; + options.num_key_cert_pairs = num_key_cert_pairs; + options.pem_client_root_certs = pem_root_certs; + options.client_certificate_request = + grpc_get_tsi_client_certificate_request_type(client_certificate_request); + options.cipher_suites = grpc_get_ssl_cipher_suites(); + options.alpn_protocols = alpn_protocol_strings; + options.num_alpn_protocols = static_cast(num_alpn_protocols); + const tsi_result result = + tsi_create_ssl_server_handshaker_factory_with_options(&options, + handshaker_factory); + gpr_free((void*)alpn_protocol_strings); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", + tsi_result_to_string(result)); + return GRPC_SECURITY_ERROR; + } + return GRPC_SECURITY_OK; +} + /* --- Ssl cache implementation. --- */ grpc_ssl_session_cache* grpc_ssl_session_cache_create_lru(size_t capacity) { diff --git a/src/core/lib/security/security_connector/ssl_utils.h b/src/core/lib/security/security_connector/ssl_utils.h index 972ca439dea..080e277f944 100644 --- a/src/core/lib/security/security_connector/ssl_utils.h +++ b/src/core/lib/security/security_connector/ssl_utils.h @@ -27,7 +27,10 @@ #include #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/security/security_connector/security_connector.h" #include "src/core/tsi/ssl_transport_security.h" +#include "src/core/tsi/transport_security.h" #include "src/core/tsi/transport_security_interface.h" /* --- Util. --- */ @@ -35,6 +38,23 @@ /* --- URL schemes. --- */ #define GRPC_SSL_URL_SCHEME "https" +/* Check ALPN information returned from SSL handshakes. */ +grpc_error* grpc_ssl_check_alpn(const tsi_peer* peer); + +/* Check peer name information returned from SSL handshakes. */ +grpc_error* grpc_ssl_check_peer_name(const char* peer_name, + const tsi_peer* peer); +/* Compare targer_name information extracted from SSL security connectors. */ +bool grpc_ssl_cmp_target_name(const char* target_name, + const char* other_target_name, + const char* overridden_target_name, + const char* other_overridden_target_name); +/* Check the host that will be set for a call is acceptable.*/ +bool grpc_ssl_check_call_host(const char* host, const char* target_name, + const char* overridden_target_name, + grpc_auth_context* auth_context, + grpc_closure* on_call_host_checked, + grpc_error** error); /* Return HTTP2-compliant cipher suites that gRPC accepts by default. */ const char* grpc_get_ssl_cipher_suites(void); @@ -47,6 +67,18 @@ grpc_get_tsi_client_certificate_request_type( /* Return an array of strings containing alpn protocols. */ const char** grpc_fill_alpn_protocol_strings(size_t* num_alpn_protocols); +/* Initialize TSI SSL server/client handshaker factory. */ +grpc_security_status grpc_ssl_tsi_client_handshaker_factory_init( + tsi_ssl_pem_key_cert_pair* key_cert_pair, const char* pem_root_certs, + tsi_ssl_session_cache* ssl_session_cache, + tsi_ssl_client_handshaker_factory** handshaker_factory); + +grpc_security_status grpc_ssl_tsi_server_handshaker_factory_init( + tsi_ssl_pem_key_cert_pair* key_cert_pairs, size_t num_key_cert_pairs, + const char* pem_root_certs, + grpc_ssl_client_certificate_request_type client_certificate_request, + tsi_ssl_server_handshaker_factory** handshaker_factory); + /* Exposed for testing only. */ grpc_core::RefCountedPtr grpc_ssl_peer_to_auth_context( const tsi_peer* peer); diff --git a/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc b/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc new file mode 100644 index 00000000000..075b1c9d53c --- /dev/null +++ b/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc @@ -0,0 +1,426 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/security_connector/tls/spiffe_security_connector.h" + +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/security/credentials/ssl/ssl_credentials.h" +#include "src/core/lib/security/credentials/tls/spiffe_credentials.h" +#include "src/core/lib/security/security_connector/ssl_utils.h" +#include "src/core/lib/security/transport/security_handshaker.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/transport.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "src/core/tsi/transport_security.h" + +namespace { + +tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair( + const grpc_tls_key_materials_config::PemKeyCertPairList& cert_pair_list) { + tsi_ssl_pem_key_cert_pair* tsi_pairs = nullptr; + size_t num_key_cert_pairs = cert_pair_list.size(); + if (num_key_cert_pairs > 0) { + GPR_ASSERT(cert_pair_list.data() != nullptr); + tsi_pairs = static_cast( + gpr_zalloc(num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair))); + } + for (size_t i = 0; i < num_key_cert_pairs; i++) { + GPR_ASSERT(cert_pair_list[i].private_key() != nullptr); + GPR_ASSERT(cert_pair_list[i].cert_chain() != nullptr); + tsi_pairs[i].cert_chain = gpr_strdup(cert_pair_list[i].cert_chain()); + tsi_pairs[i].private_key = gpr_strdup(cert_pair_list[i].private_key()); + } + return tsi_pairs; +} + +/** -- Util function to populate SPIFFE server/channel credentials. -- */ +grpc_core::RefCountedPtr +PopulateSpiffeCredentials(const grpc_tls_credentials_options& options) { + GPR_ASSERT(options.credential_reload_config() != nullptr || + options.key_materials_config() != nullptr); + grpc_core::RefCountedPtr key_materials_config; + /* Use credential reload config to fetch credentials. */ + if (options.credential_reload_config() != nullptr) { + grpc_tls_credential_reload_arg* arg = + grpc_core::New(); + key_materials_config = grpc_tls_key_materials_config_create()->Ref(); + arg->key_materials_config = key_materials_config.get(); + int result = options.credential_reload_config()->Schedule(arg); + if (result) { + /* Do not support async credential reload. */ + gpr_log(GPR_ERROR, "Async credential reload is unsupported now."); + } else { + grpc_ssl_certificate_config_reload_status status = arg->status; + if (status == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED) { + gpr_log(GPR_DEBUG, "Credential does not change after reload."); + } else if (status == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL) { + gpr_log(GPR_ERROR, "Credential reload failed with an error: %s", + arg->error_details); + } + } + gpr_free((void*)arg->error_details); + grpc_core::Delete(arg); + /* Use existing key materials config. */ + } else { + key_materials_config = options.key_materials_config()->Ref(); + } + return key_materials_config; +} + +} // namespace + +SpiffeChannelSecurityConnector::SpiffeChannelSecurityConnector( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name, const char* overridden_target_name) + : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME, + std::move(channel_creds), + std::move(request_metadata_creds)), + overridden_target_name_(overridden_target_name == nullptr + ? nullptr + : gpr_strdup(overridden_target_name)) { + check_arg_ = ServerAuthorizationCheckArgCreate(this); + char* port; + gpr_split_host_port(target_name, &target_name_, &port); + gpr_free(port); +} + +SpiffeChannelSecurityConnector::~SpiffeChannelSecurityConnector() { + if (target_name_ != nullptr) { + gpr_free(target_name_); + } + if (overridden_target_name_ != nullptr) { + gpr_free(overridden_target_name_); + } + if (client_handshaker_factory_ != nullptr) { + tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_); + } + ServerAuthorizationCheckArgDestroy(check_arg_); +} + +void SpiffeChannelSecurityConnector::add_handshakers( + grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) { + // Instantiate TSI handshaker. + tsi_handshaker* tsi_hs = nullptr; + tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( + client_handshaker_factory_, + overridden_target_name_ != nullptr ? overridden_target_name_ + : target_name_, + &tsi_hs); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", + tsi_result_to_string(result)); + return; + } + // Create handshakers. + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this)); +} + +void SpiffeChannelSecurityConnector::check_peer( + tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) { + const char* target_name = overridden_target_name_ != nullptr + ? overridden_target_name_ + : target_name_; + grpc_error* error = grpc_ssl_check_alpn(&peer); + if (error != GRPC_ERROR_NONE) { + GRPC_CLOSURE_SCHED(on_peer_checked, error); + tsi_peer_destruct(&peer); + return; + } + *auth_context = grpc_ssl_peer_to_auth_context(&peer); + const SpiffeCredentials* creds = + static_cast(channel_creds()); + const grpc_tls_server_authorization_check_config* config = + creds->options().server_authorization_check_config(); + /* If server authorization config is not null, use it to perform + * server authorizaiton check. */ + if (config != nullptr) { + const tsi_peer_property* p = + tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY); + if (p == nullptr) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Cannot check peer: missing pem cert property."); + } else { + char* peer_pem = static_cast(gpr_malloc(p->value.length + 1)); + memcpy(peer_pem, p->value.data, p->value.length); + peer_pem[p->value.length] = '\0'; + GPR_ASSERT(check_arg_ != nullptr); + check_arg_->peer_cert = check_arg_->peer_cert == nullptr + ? gpr_strdup(peer_pem) + : check_arg_->peer_cert; + check_arg_->target_name = check_arg_->target_name == nullptr + ? gpr_strdup(target_name) + : check_arg_->target_name; + on_peer_checked_ = on_peer_checked; + gpr_free(peer_pem); + int callback_status = config->Schedule(check_arg_); + /* Server authorization check is handled asynchronously. */ + if (callback_status) { + tsi_peer_destruct(&peer); + return; + } + /* Server authorization check is handled synchronously. */ + error = ProcessServerAuthorizationCheckResult(check_arg_); + } + } + GRPC_CLOSURE_SCHED(on_peer_checked, error); + tsi_peer_destruct(&peer); +} + +int SpiffeChannelSecurityConnector::cmp( + const grpc_security_connector* other_sc) const { + auto* other = + reinterpret_cast(other_sc); + int c = channel_security_connector_cmp(other); + if (c != 0) { + return c; + } + return grpc_ssl_cmp_target_name(target_name_, other->target_name_, + overridden_target_name_, + other->overridden_target_name_); +} + +bool SpiffeChannelSecurityConnector::check_call_host( + const char* host, grpc_auth_context* auth_context, + grpc_closure* on_call_host_checked, grpc_error** error) { + return grpc_ssl_check_call_host(host, target_name_, overridden_target_name_, + auth_context, on_call_host_checked, error); +} + +void SpiffeChannelSecurityConnector::cancel_check_call_host( + grpc_closure* on_call_host_checked, grpc_error* error) { + GRPC_ERROR_UNREF(error); +} + +grpc_core::RefCountedPtr +SpiffeChannelSecurityConnector::CreateSpiffeChannelSecurityConnector( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name, const char* overridden_target_name, + tsi_ssl_session_cache* ssl_session_cache) { + if (channel_creds == nullptr) { + gpr_log(GPR_ERROR, + "channel_creds is nullptr in " + "SpiffeChannelSecurityConnectorCreate()"); + return nullptr; + } + if (target_name == nullptr) { + gpr_log(GPR_ERROR, + "target_name is nullptr in " + "SpiffeChannelSecurityConnectorCreate()"); + return nullptr; + } + grpc_core::RefCountedPtr c = + grpc_core::MakeRefCounted( + std::move(channel_creds), std::move(request_metadata_creds), + target_name, overridden_target_name); + if (c->InitializeHandshakerFactory(ssl_session_cache) != GRPC_SECURITY_OK) { + return nullptr; + } + return c; +} + +grpc_security_status +SpiffeChannelSecurityConnector::InitializeHandshakerFactory( + tsi_ssl_session_cache* ssl_session_cache) { + const SpiffeCredentials* creds = + static_cast(channel_creds()); + auto key_materials_config = PopulateSpiffeCredentials(creds->options()); + if (!key_materials_config.get()->pem_key_cert_pair_list().size()) { + key_materials_config.get()->Unref(); + return GRPC_SECURITY_ERROR; + } + tsi_ssl_pem_key_cert_pair* pem_key_cert_pair = ConvertToTsiPemKeyCertPair( + key_materials_config.get()->pem_key_cert_pair_list()); + grpc_security_status status = grpc_ssl_tsi_client_handshaker_factory_init( + pem_key_cert_pair, key_materials_config.get()->pem_root_certs(), + ssl_session_cache, &client_handshaker_factory_); + // Free memory. + key_materials_config.get()->Unref(); + grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1); + return status; +} + +void SpiffeChannelSecurityConnector::ServerAuthorizationCheckDone( + grpc_tls_server_authorization_check_arg* arg) { + GPR_ASSERT(arg != nullptr); + grpc_core::ExecCtx exec_ctx; + grpc_error* error = ProcessServerAuthorizationCheckResult(arg); + SpiffeChannelSecurityConnector* connector = + static_cast(arg->cb_user_data); + GRPC_CLOSURE_SCHED(connector->on_peer_checked_, error); +} + +grpc_error* +SpiffeChannelSecurityConnector::ProcessServerAuthorizationCheckResult( + grpc_tls_server_authorization_check_arg* arg) { + grpc_error* error = GRPC_ERROR_NONE; + char* msg = nullptr; + /* Server authorization check is cancelled by caller. */ + if (arg->status == GRPC_STATUS_CANCELLED) { + gpr_asprintf(&msg, + "Server authorization check is cancelled by the caller with " + "error: %s", + arg->error_details); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + } else if (arg->status == GRPC_STATUS_OK) { + /* Server authorization check completed successfully but returned check + * failure. */ + if (!arg->success) { + gpr_asprintf(&msg, "Server authorization check failed with error: %s", + arg->error_details); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + } + /* Server authorization check did not complete correctly. */ + } else { + gpr_asprintf( + &msg, + "Server authorization check did not finish correctly with error: %s", + arg->error_details); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + } + gpr_free(msg); + return error; +} + +grpc_tls_server_authorization_check_arg* +SpiffeChannelSecurityConnector::ServerAuthorizationCheckArgCreate( + void* user_data) { + grpc_tls_server_authorization_check_arg* arg = + grpc_core::New(); + arg->cb = ServerAuthorizationCheckDone; + arg->cb_user_data = user_data; + arg->status = GRPC_STATUS_OK; + return arg; +} + +void SpiffeChannelSecurityConnector::ServerAuthorizationCheckArgDestroy( + grpc_tls_server_authorization_check_arg* arg) { + if (arg == nullptr) { + return; + } + gpr_free((void*)arg->target_name); + gpr_free((void*)arg->peer_cert); + gpr_free((void*)arg->error_details); + grpc_core::Delete(arg); +} + +SpiffeServerSecurityConnector::SpiffeServerSecurityConnector( + grpc_core::RefCountedPtr server_creds) + : grpc_server_security_connector(GRPC_SSL_URL_SCHEME, + std::move(server_creds)) {} + +SpiffeServerSecurityConnector::~SpiffeServerSecurityConnector() { + if (server_handshaker_factory_ != nullptr) { + tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_); + } +} + +void SpiffeServerSecurityConnector::add_handshakers( + grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) { + /* Create a TLS SPIFFE TSI handshaker for server. */ + RefreshServerHandshakerFactory(); + tsi_handshaker* tsi_hs = nullptr; + tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker( + server_handshaker_factory_, &tsi_hs); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", + tsi_result_to_string(result)); + return; + } + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this)); +} + +void SpiffeServerSecurityConnector::check_peer( + tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) { + grpc_error* error = grpc_ssl_check_alpn(&peer); + *auth_context = grpc_ssl_peer_to_auth_context(&peer); + tsi_peer_destruct(&peer); + GRPC_CLOSURE_SCHED(on_peer_checked, error); +} + +int SpiffeServerSecurityConnector::cmp( + const grpc_security_connector* other) const { + return server_security_connector_cmp( + static_cast(other)); +} + +grpc_core::RefCountedPtr +SpiffeServerSecurityConnector::CreateSpiffeServerSecurityConnector( + grpc_core::RefCountedPtr server_creds) { + if (server_creds == nullptr) { + gpr_log(GPR_ERROR, + "server_creds is nullptr in " + "SpiffeServerSecurityConnectorCreate()"); + return nullptr; + } + grpc_core::RefCountedPtr c = + grpc_core::MakeRefCounted( + std::move(server_creds)); + if (c->RefreshServerHandshakerFactory() != GRPC_SECURITY_OK) { + return nullptr; + } + return c; +} + +grpc_security_status +SpiffeServerSecurityConnector::RefreshServerHandshakerFactory() { + const SpiffeServerCredentials* creds = + static_cast(server_creds()); + auto key_materials_config = PopulateSpiffeCredentials(creds->options()); + /* Credential reload does NOT take effect and we need to keep using + * the existing handshaker factory. */ + if (key_materials_config.get()->pem_key_cert_pair_list().empty()) { + key_materials_config.get()->Unref(); + return GRPC_SECURITY_ERROR; + } + /* Credential reload takes effect and we need to free the existing + * handshaker library. */ + if (server_handshaker_factory_) { + tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_); + } + tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = ConvertToTsiPemKeyCertPair( + key_materials_config.get()->pem_key_cert_pair_list()); + size_t num_key_cert_pairs = + key_materials_config.get()->pem_key_cert_pair_list().size(); + grpc_security_status status = grpc_ssl_tsi_server_handshaker_factory_init( + pem_key_cert_pairs, num_key_cert_pairs, + key_materials_config.get()->pem_root_certs(), + creds->options().cert_request_type(), &server_handshaker_factory_); + // Free memory. + key_materials_config.get()->Unref(); + grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pairs, + num_key_cert_pairs); + return status; +} diff --git a/src/core/lib/security/security_connector/tls/spiffe_security_connector.h b/src/core/lib/security/security_connector/tls/spiffe_security_connector.h new file mode 100644 index 00000000000..56972153e07 --- /dev/null +++ b/src/core/lib/security/security_connector/tls/spiffe_security_connector.h @@ -0,0 +1,122 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_TLS_SPIFFE_SECURITY_CONNECTOR_H +#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_TLS_SPIFFE_SECURITY_CONNECTOR_H + +#include + +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" + +#define GRPC_TLS_SPIFFE_TRANSPORT_SECURITY_TYPE "spiffe" + +// Spiffe channel security connector. +class SpiffeChannelSecurityConnector final + : public grpc_channel_security_connector { + public: + // static factory method to create a SPIFFE channel security connector. + static grpc_core::RefCountedPtr + CreateSpiffeChannelSecurityConnector( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name, const char* overridden_target_name, + tsi_ssl_session_cache* ssl_session_cache); + + SpiffeChannelSecurityConnector( + grpc_core::RefCountedPtr channel_creds, + grpc_core::RefCountedPtr request_metadata_creds, + const char* target_name, const char* overridden_target_name); + ~SpiffeChannelSecurityConnector() override; + + void add_handshakers(grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) override; + + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) override; + + int cmp(const grpc_security_connector* other_sc) const override; + + bool check_call_host(const char* host, grpc_auth_context* auth_context, + grpc_closure* on_call_host_checked, + grpc_error** error) override; + + void cancel_check_call_host(grpc_closure* on_call_host_checked, + grpc_error* error) override; + + private: + // Initialize SSL TSI client handshaker factory. + grpc_security_status InitializeHandshakerFactory( + tsi_ssl_session_cache* ssl_session_cache); + + // gRPC-provided callback executed by application, which servers to bring the + // control back to gRPC core. + static void ServerAuthorizationCheckDone( + grpc_tls_server_authorization_check_arg* arg); + + // A util function to process server authorization check result. + static grpc_error* ProcessServerAuthorizationCheckResult( + grpc_tls_server_authorization_check_arg* arg); + + // A util function to create a server authorization check arg instance. + static grpc_tls_server_authorization_check_arg* + ServerAuthorizationCheckArgCreate(void* user_data); + + // A util function to destroy a server authorization check arg instance. + static void ServerAuthorizationCheckArgDestroy( + grpc_tls_server_authorization_check_arg* arg); + + grpc_closure* on_peer_checked_; + char* target_name_; + char* overridden_target_name_; + tsi_ssl_client_handshaker_factory* client_handshaker_factory_ = nullptr; + grpc_tls_server_authorization_check_arg* check_arg_; +}; + +// Spiffe server security connector. +class SpiffeServerSecurityConnector final + : public grpc_server_security_connector { + public: + // static factory method to create a SPIFFE server security connector. + static grpc_core::RefCountedPtr + CreateSpiffeServerSecurityConnector( + grpc_core::RefCountedPtr server_creds); + + explicit SpiffeServerSecurityConnector( + grpc_core::RefCountedPtr server_creds); + ~SpiffeServerSecurityConnector() override; + + void add_handshakers(grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_mgr) override; + + void check_peer(tsi_peer peer, grpc_endpoint* ep, + grpc_core::RefCountedPtr* auth_context, + grpc_closure* on_peer_checked) override; + + int cmp(const grpc_security_connector* other) const override; + + private: + // A util function to refresh SSL TSI server handshaker factory with a valid + // credential. + grpc_security_status RefreshServerHandshakerFactory(); + tsi_ssl_server_handshaker_factory* server_handshaker_factory_ = nullptr; +}; + +#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_TLS_SPIFFE_SECURITY_CONNECTOR_H \ + */ diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc index 2107bcaa748..9ab76d99c02 100644 --- a/src/core/tsi/ssl_transport_security.cc +++ b/src/core/tsi/ssl_transport_security.cc @@ -344,18 +344,24 @@ static tsi_result add_subject_alt_names_properties_to_peer( size_t subject_alt_name_count) { size_t i; tsi_result result = TSI_OK; - /* Reset for DNS entries filtering. */ peer->property_count -= subject_alt_name_count; - for (i = 0; i < subject_alt_name_count; i++) { GENERAL_NAME* subject_alt_name = sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i)); - /* Filter out the non-dns entries names. */ - if (subject_alt_name->type == GEN_DNS) { + if (subject_alt_name->type == GEN_DNS || + subject_alt_name->type == GEN_EMAIL || + subject_alt_name->type == GEN_URI) { unsigned char* name = nullptr; int name_size; - name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.dNSName); + if (subject_alt_name->type == GEN_DNS) { + name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.dNSName); + } else if (subject_alt_name->type == GEN_EMAIL) { + name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.rfc822Name); + } else { + name_size = ASN1_STRING_to_UTF8( + &name, subject_alt_name->d.uniformResourceIdentifier); + } if (name_size < 0) { gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string."); result = TSI_INTERNAL_ERROR; @@ -369,7 +375,6 @@ static tsi_result add_subject_alt_names_properties_to_peer( } else if (subject_alt_name->type == GEN_IPADD) { char ntop_buf[INET6_ADDRSTRLEN]; int af; - if (subject_alt_name->d.iPAddress->length == 4) { af = AF_INET; } else if (subject_alt_name->d.iPAddress->length == 16) { @@ -386,7 +391,6 @@ static tsi_result add_subject_alt_names_properties_to_peer( result = TSI_INTERNAL_ERROR; break; } - result = tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, name, &peer->properties[peer->property_count++]); @@ -1017,7 +1021,6 @@ static void tsi_ssl_handshaker_factory_init( } /* --- tsi_handshaker_result methods implementation. ---*/ - static tsi_result ssl_handshaker_result_extract_peer( const tsi_handshaker_result* self, tsi_peer* peer) { tsi_result result = TSI_OK; @@ -1025,6 +1028,7 @@ static tsi_result ssl_handshaker_result_extract_peer( unsigned int alpn_selected_len; const tsi_ssl_handshaker_result* impl = reinterpret_cast(self); + // TODO(yihuazhang): Return a full certificate chain as a peer property. X509* peer_cert = SSL_get_peer_certificate(impl->ssl); if (peer_cert != nullptr) { result = peer_from_x509(peer_cert, 1, peer); @@ -1066,7 +1070,6 @@ static tsi_result ssl_handshaker_result_extract_peer( &peer->properties[peer->property_count]); if (result != TSI_OK) return result; peer->property_count++; - return result; } @@ -1400,7 +1403,6 @@ static tsi_result create_tsi_ssl_handshaker(SSL_CTX* ctx, int is_client, static_cast(gpr_zalloc(impl->outgoing_bytes_buffer_size)); impl->base.vtable = &handshaker_vtable; impl->factory_ref = tsi_ssl_handshaker_factory_ref(factory); - *handshaker = &impl->base; return TSI_OK; } diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 8f7da3a5b04..814f920eaf7 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -256,6 +256,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', + 'src/core/lib/security/credentials/tls/spiffe_credentials.cc', 'src/core/lib/security/security_connector/alts/alts_security_connector.cc', 'src/core/lib/security/security_connector/fake/fake_security_connector.cc', 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', @@ -264,6 +265,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/security/security_connector/security_connector.cc', 'src/core/lib/security/security_connector/ssl/ssl_security_connector.cc', 'src/core/lib/security/security_connector/ssl_utils.cc', + 'src/core/lib/security/security_connector/tls/spiffe_security_connector.cc', 'src/core/lib/security/transport/client_auth_filter.cc', 'src/core/lib/security/transport/secure_endpoint.cc', 'src/core/lib/security/transport/security_handshaker.cc', diff --git a/test/core/end2end/fixtures/h2_spiffe.cc b/test/core/end2end/fixtures/h2_spiffe.cc new file mode 100644 index 00000000000..3cd7c362212 --- /dev/null +++ b/test/core/end2end/fixtures/h2_spiffe.cc @@ -0,0 +1,290 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include + +#include +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gpr/tmpfile.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/thd.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef grpc_core::InlinedVector ThreadList; + +typedef struct fullstack_secure_fixture_data { + char* localaddr; + ThreadList thd_list; +} fullstack_secure_fixture_data; + +static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( + grpc_channel_args* client_args, grpc_channel_args* server_args) { + grpc_end2end_test_fixture f; + int port = grpc_pick_unused_port_or_die(); + fullstack_secure_fixture_data* ffd = + grpc_core::New(); + memset(&f, 0, sizeof(f)); + gpr_join_host_port(&ffd->localaddr, "localhost", port); + f.fixture_data = ffd; + f.cq = grpc_completion_queue_create_for_next(nullptr); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr); + return f; +} + +static void process_auth_failure(void* state, grpc_auth_context* ctx, + const grpc_metadata* md, size_t md_count, + grpc_process_auth_metadata_done_cb cb, + void* user_data) { + GPR_ASSERT(state == nullptr); + cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_UNAUTHENTICATED, nullptr); +} + +static void chttp2_init_client_secure_fullstack( + grpc_end2end_test_fixture* f, grpc_channel_args* client_args, + grpc_channel_credentials* creds) { + fullstack_secure_fixture_data* ffd = + static_cast(f->fixture_data); + f->client = + grpc_secure_channel_create(creds, ffd->localaddr, client_args, nullptr); + GPR_ASSERT(f->client != nullptr); + grpc_channel_credentials_release(creds); +} + +static void chttp2_init_server_secure_fullstack( + grpc_end2end_test_fixture* f, grpc_channel_args* server_args, + grpc_server_credentials* server_creds) { + fullstack_secure_fixture_data* ffd = + static_cast(f->fixture_data); + if (f->server) { + grpc_server_destroy(f->server); + } + f->server = grpc_server_create(server_args, nullptr); + grpc_server_register_completion_queue(f->server, f->cq, nullptr); + GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr, + server_creds)); + grpc_server_credentials_release(server_creds); + grpc_server_start(f->server); +} + +void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture* f) { + fullstack_secure_fixture_data* ffd = + static_cast(f->fixture_data); + for (size_t ind = 0; ind < ffd->thd_list.size(); ind++) { + ffd->thd_list[ind].Join(); + } + gpr_free(ffd->localaddr); + grpc_core::Delete(ffd); +} + +// Application-provided callback for server authorization check. +static void server_authz_check_cb(void* user_data) { + grpc_tls_server_authorization_check_arg* check_arg = + static_cast(user_data); + GPR_ASSERT(check_arg != nullptr); + // result = 1 indicates the server authorization check passes. + // Normally, the applicaiton code should resort to mapping information + // between server identity and target name to derive the result. + // For this test, we directly return 1 for simplicity. + check_arg->success = 1; + check_arg->status = GRPC_STATUS_OK; + check_arg->cb(check_arg); +} + +// Asynchronous implementation of schedule field in +// grpc_server_authorization_check_config. +static int server_authz_check_async( + void* config_user_data, grpc_tls_server_authorization_check_arg* arg) { + fullstack_secure_fixture_data* ffd = + static_cast(config_user_data); + ffd->thd_list.push_back( + grpc_core::Thread("h2_spiffe_test", &server_authz_check_cb, arg)); + ffd->thd_list[ffd->thd_list.size() - 1].Start(); + return 1; +} + +// Synchronous implementation of schedule field in +// grpc_tls_credential_reload_config instance that is a part of client-side +// grpc_tls_credentials_options instance. +static int client_cred_reload_sync(void* config_user_data, + grpc_tls_credential_reload_arg* arg) { + grpc_ssl_pem_key_cert_pair** key_cert_pair = + static_cast( + gpr_zalloc(sizeof(grpc_ssl_pem_key_cert_pair*))); + key_cert_pair[0] = static_cast( + gpr_zalloc(sizeof(grpc_ssl_pem_key_cert_pair))); + key_cert_pair[0]->private_key = gpr_strdup(test_server1_key); + key_cert_pair[0]->cert_chain = gpr_strdup(test_server1_cert); + if (!arg->key_materials_config->pem_key_cert_pair_list().size()) { + grpc_tls_key_materials_config_set_key_materials( + arg->key_materials_config, gpr_strdup(test_root_cert), + (const grpc_ssl_pem_key_cert_pair**)key_cert_pair, 1); + } + // new credential has been reloaded. + arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW; + return 0; +} + +// Synchronous implementation of schedule field in +// grpc_tls_credential_reload_config instance that is a part of server-side +// grpc_tls_credentials_options instance. +static int server_cred_reload_sync(void* config_user_data, + grpc_tls_credential_reload_arg* arg) { + grpc_ssl_pem_key_cert_pair** key_cert_pair = + static_cast( + gpr_zalloc(sizeof(grpc_ssl_pem_key_cert_pair*))); + key_cert_pair[0] = static_cast( + gpr_zalloc(sizeof(grpc_ssl_pem_key_cert_pair))); + key_cert_pair[0]->private_key = gpr_strdup(test_server1_key); + key_cert_pair[0]->cert_chain = gpr_strdup(test_server1_cert); + GPR_ASSERT(arg != nullptr); + GPR_ASSERT(arg->key_materials_config != nullptr); + GPR_ASSERT(arg->key_materials_config->pem_key_cert_pair_list().data() != + nullptr); + if (!arg->key_materials_config->pem_key_cert_pair_list().size()) { + grpc_tls_key_materials_config_set_key_materials( + arg->key_materials_config, gpr_strdup(test_root_cert), + (const grpc_ssl_pem_key_cert_pair**)key_cert_pair, 1); + } + // new credential has been reloaded. + arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW; + return 0; +} + +// Create a SPIFFE channel credential. +static grpc_channel_credentials* create_spiffe_channel_credentials( + fullstack_secure_fixture_data* ffd) { + grpc_tls_credentials_options* options = grpc_tls_credentials_options_create(); + /* Set credential reload config. */ + grpc_tls_credential_reload_config* reload_config = + grpc_tls_credential_reload_config_create(nullptr, client_cred_reload_sync, + nullptr, nullptr); + grpc_tls_credentials_options_set_credential_reload_config(options, + reload_config); + /* Set server authorization check config. */ + grpc_tls_server_authorization_check_config* check_config = + grpc_tls_server_authorization_check_config_create( + ffd, server_authz_check_async, nullptr, nullptr); + grpc_tls_credentials_options_set_server_authorization_check_config( + options, check_config); + /* Create SPIFFE channel credentials. */ + grpc_channel_credentials* creds = grpc_tls_spiffe_credentials_create(options); + return creds; +} + +// Create a SPIFFE server credential. +static grpc_server_credentials* create_spiffe_server_credentials() { + grpc_tls_credentials_options* options = grpc_tls_credentials_options_create(); + /* Set credential reload config. */ + grpc_tls_credential_reload_config* reload_config = + grpc_tls_credential_reload_config_create(nullptr, server_cred_reload_sync, + nullptr, nullptr); + grpc_tls_credentials_options_set_credential_reload_config(options, + reload_config); + /* Set client certificate request type. */ + grpc_tls_credentials_options_set_cert_request_type( + options, GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY); + grpc_server_credentials* creds = + grpc_tls_spiffe_server_credentials_create(options); + return creds; +} + +static void chttp2_init_client(grpc_end2end_test_fixture* f, + grpc_channel_args* client_args) { + grpc_channel_credentials* ssl_creds = create_spiffe_channel_credentials( + static_cast(f->fixture_data)); + grpc_arg ssl_name_override = { + GRPC_ARG_STRING, + const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), + {const_cast("foo.test.google.fr")}}; + grpc_channel_args* new_client_args = + grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); + chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds); + grpc_channel_args_destroy(new_client_args); +} + +static int fail_server_auth_check(grpc_channel_args* server_args) { + size_t i; + if (server_args == nullptr) return 0; + for (i = 0; i < server_args->num_args; i++) { + if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == + 0) { + return 1; + } + } + return 0; +} + +static void chttp2_init_server(grpc_end2end_test_fixture* f, + grpc_channel_args* server_args) { + grpc_server_credentials* ssl_creds = create_spiffe_server_credentials(); + if (fail_server_auth_check(server_args)) { + grpc_auth_metadata_processor processor = {process_auth_failure, nullptr, + nullptr}; + grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); + } + chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); +} + +static grpc_end2end_test_config configs[] = { + /* client sync reload async authz + server sync reload. */ + {"chttp2/simple_ssl_fullstack", + FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + "foo.test.google.fr", chttp2_create_fixture_secure_fullstack, + chttp2_init_client, chttp2_init_server, chttp2_tear_down_secure_fullstack}, +}; + +int main(int argc, char** argv) { + FILE* roots_file; + size_t roots_size = strlen(test_root_cert); + char* roots_filename; + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + /* Set the SSL roots env var. */ + roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename); + GPR_ASSERT(roots_filename != nullptr); + GPR_ASSERT(roots_file != nullptr); + GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size); + fclose(roots_file); + gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename); + grpc_init(); + for (size_t ind = 0; ind < sizeof(configs) / sizeof(*configs); ind++) { + grpc_end2end_tests(argc, argv, configs[ind]); + } + grpc_shutdown(); + /* Cleanup. */ + remove(roots_filename); + gpr_free(roots_filename); + return 0; +} diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index f8ac7036530..231d2262a9d 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -74,6 +74,7 @@ END2END_FIXTURES = { 'h2_sockpair+trace': socketpair_unsecure_fixture_options._replace( ci_mac=False, tracing=True, large_writes=False, exclude_iomgrs=['uv']), 'h2_ssl': default_secure_fixture_options, + 'h2_spiffe': default_secure_fixture_options, 'h2_local_uds': local_fixture_options, 'h2_local_ipv4': local_fixture_options, 'h2_local_ipv6': local_fixture_options, diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index a5fe091c2fc..d1ce92ebfba 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -87,6 +87,7 @@ END2END_FIXTURES = { client_channel = False, ), "h2_ssl": _fixture_options(secure = True), + "h2_spiffe": _fixture_options(secure = True), "h2_local_uds": _fixture_options(secure = True, dns_resolver = False, _platforms = ["linux", "mac", "posix"]), "h2_local_ipv4": _fixture_options(secure = True, dns_resolver = False, _platforms = ["linux", "mac", "posix"]), "h2_local_ipv6": _fixture_options(secure = True, dns_resolver = False, _platforms = ["linux", "mac", "posix"]), diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 6e4a57ba00f..5ce5d5d3ce3 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1381,6 +1381,8 @@ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.h \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h \ +src/core/lib/security/credentials/tls/spiffe_credentials.cc \ +src/core/lib/security/credentials/tls/spiffe_credentials.h \ src/core/lib/security/security_connector/alts/alts_security_connector.cc \ src/core/lib/security/security_connector/alts/alts_security_connector.h \ src/core/lib/security/security_connector/fake/fake_security_connector.cc \ @@ -1397,6 +1399,8 @@ src/core/lib/security/security_connector/ssl/ssl_security_connector.cc \ src/core/lib/security/security_connector/ssl/ssl_security_connector.h \ src/core/lib/security/security_connector/ssl_utils.cc \ src/core/lib/security/security_connector/ssl_utils.h \ +src/core/lib/security/security_connector/tls/spiffe_security_connector.cc \ +src/core/lib/security/security_connector/tls/spiffe_security_connector.h \ src/core/lib/security/transport/auth_filters.h \ src/core/lib/security/transport/client_auth_filter.cc \ src/core/lib/security/transport/secure_endpoint.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8adde9ec602..2d427804d07 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -6285,6 +6285,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "end2end_tests", + "gpr", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "h2_spiffe_test", + "src": [ + "test/core/end2end/fixtures/h2_spiffe.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "end2end_tests", @@ -10458,6 +10475,7 @@ "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h", + "src/core/lib/security/credentials/tls/spiffe_credentials.h", "src/core/lib/security/security_connector/alts/alts_security_connector.h", "src/core/lib/security/security_connector/fake/fake_security_connector.h", "src/core/lib/security/security_connector/load_system_roots.h", @@ -10466,6 +10484,7 @@ "src/core/lib/security/security_connector/security_connector.h", "src/core/lib/security/security_connector/ssl/ssl_security_connector.h", "src/core/lib/security/security_connector/ssl_utils.h", + "src/core/lib/security/security_connector/tls/spiffe_security_connector.h", "src/core/lib/security/transport/auth_filters.h", "src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/security_handshaker.h", @@ -10513,6 +10532,8 @@ "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc", "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h", + "src/core/lib/security/credentials/tls/spiffe_credentials.cc", + "src/core/lib/security/credentials/tls/spiffe_credentials.h", "src/core/lib/security/security_connector/alts/alts_security_connector.cc", "src/core/lib/security/security_connector/alts/alts_security_connector.h", "src/core/lib/security/security_connector/fake/fake_security_connector.cc", @@ -10529,6 +10550,8 @@ "src/core/lib/security/security_connector/ssl/ssl_security_connector.h", "src/core/lib/security/security_connector/ssl_utils.cc", "src/core/lib/security/security_connector/ssl_utils.h", + "src/core/lib/security/security_connector/tls/spiffe_security_connector.cc", + "src/core/lib/security/security_connector/tls/spiffe_security_connector.h", "src/core/lib/security/transport/auth_filters.h", "src/core/lib/security/transport/client_auth_filter.cc", "src/core/lib/security/transport/secure_endpoint.cc", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 7c9fb8d6804..cffc8b98764 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -34543,6 +34543,1781 @@ "posix" ] }, + { + "args": [ + "authority_not_supported" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "bad_hostname" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "bad_ping" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "binary_metadata" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "call_creds" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "call_host_override" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_after_accept" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_after_client_done" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_after_invoke" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_after_round_trip" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_before_invoke" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_in_a_vacuum" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_with_status" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "channelz" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "compressed_payload" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "connectivity" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "default_host" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "disappearing_server" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": true, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "empty_batch" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "filter_call_init_fails" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "filter_causes_close" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "filter_context" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "filter_latency" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "filter_status_code" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "graceful_server_shutdown" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "high_initial_seqno" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "hpack_size" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "idempotent_request" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "invoke_large_request" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "large_metadata" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "max_concurrent_streams" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "max_connection_age" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "max_connection_idle" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "max_message_length" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "negative_deadline" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "no_error_on_hotpath" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "no_logging" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "no_op" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "payload" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "ping" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "ping_pong_streaming" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "registered_call" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "request_with_flags" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "request_with_payload" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "resource_quota_server" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_cancellation" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_disabled" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_exceeds_buffer_size_in_initial_batch" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_exceeds_buffer_size_in_subsequent_batch" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_non_retriable_status" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_non_retriable_status_before_recv_trailing_metadata_started" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_recv_initial_metadata" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_recv_message" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_server_pushback_delay" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_server_pushback_disabled" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_streaming" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_streaming_after_commit" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_streaming_succeeds_before_replay_finished" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_throttled" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "retry_too_many_attempts" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "server_finishes_request" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "shutdown_finishes_calls" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "shutdown_finishes_tags" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "simple_cacheable_request" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "simple_delayed_request" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "simple_metadata" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "simple_request" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "stream_compression_compressed_payload" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "stream_compression_payload" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "stream_compression_ping_pong_streaming" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "streaming_error_response" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "trailing_metadata" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_spiffe_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported"