Add SPIFFE security stack to gRPC core

pull/18115/head
Yihua Zhang 6 years ago
parent bd68cbcd24
commit b017c801b6
  1. 4
      BUILD
  2. 40
      CMakeLists.txt
  3. 40
      Makefile
  4. 4
      build.yaml
  5. 3
      config.m4
  6. 3
      config.w32
  7. 2
      gRPC-C++.podspec
  8. 6
      gRPC-Core.podspec
  9. 4
      grpc.gemspec
  10. 2
      grpc.gyp
  11. 51
      include/grpc/grpc_security.h
  12. 4
      package.xml
  13. 9
      src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
  14. 129
      src/core/lib/security/credentials/tls/spiffe_credentials.cc
  15. 62
      src/core/lib/security/credentials/tls/spiffe_credentials.h
  16. 237
      src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
  17. 134
      src/core/lib/security/security_connector/ssl_utils.cc
  18. 32
      src/core/lib/security/security_connector/ssl_utils.h
  19. 426
      src/core/lib/security/security_connector/tls/spiffe_security_connector.cc
  20. 122
      src/core/lib/security/security_connector/tls/spiffe_security_connector.h
  21. 22
      src/core/tsi/ssl_transport_security.cc
  22. 2
      src/python/grpcio/grpc_core_dependencies.py
  23. 290
      test/core/end2end/fixtures/h2_spiffe.cc
  24. 1
      test/core/end2end/gen_build_yaml.py
  25. 1
      test/core/end2end/generate_tests.bzl
  26. 4
      tools/doxygen/Doxyfile.core.internal
  27. 23
      tools/run_tests/generated/sources_and_headers.json
  28. 1775
      tools/run_tests/generated/tests.json

@ -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",

@ -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 $<$<COMPILE_LANGUAGE:CXX>:${_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
)

@ -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)

@ -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

@ -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)

@ -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");

@ -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',

@ -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',

@ -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 )

@ -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',

@ -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

@ -228,6 +228,7 @@
<file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/spiffe_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/alts/alts_security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/fake/fake_security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/load_system_roots.h" role="src" />
@ -236,6 +237,7 @@
<file baseinstalldir="/" name="src/core/lib/security/security_connector/security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/ssl/ssl_security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/ssl_utils.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/tls/spiffe_security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/auth_filters.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.h" role="src" />
@ -667,6 +669,7 @@
<file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/spiffe_credentials.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/alts/alts_security_connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/fake/fake_security_connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/load_system_roots_fallback.cc" role="src" />
@ -675,6 +678,7 @@
<file baseinstalldir="/" name="src/core/lib/security/security_connector/security_connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/ssl/ssl_security_connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/ssl_utils.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/tls/spiffe_security_connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/client_auth_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.cc" role="src" />

@ -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(

@ -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 <grpc/support/port_platform.h>
#include "src/core/lib/security/credentials/tls/spiffe_credentials.h"
#include <cstring>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#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<grpc_tls_credentials_options> options)
: grpc_channel_credentials(GRPC_CREDENTIALS_TYPE_SPIFFE),
options_(std::move(options)) {}
SpiffeCredentials::~SpiffeCredentials() {}
grpc_core::RefCountedPtr<grpc_channel_security_connector>
SpiffeCredentials::create_security_connector(
grpc_core::RefCountedPtr<grpc_call_credentials> 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<tsi_ssl_session_cache*>(arg->value.pointer.p);
}
}
grpc_core::RefCountedPtr<grpc_channel_security_connector> 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<grpc_tls_credentials_options> options)
: grpc_server_credentials(GRPC_CREDENTIALS_TYPE_SPIFFE),
options_(std::move(options)) {}
SpiffeServerCredentials::~SpiffeServerCredentials() {}
grpc_core::RefCountedPtr<grpc_server_security_connector>
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<SpiffeCredentials>(
grpc_core::RefCountedPtr<grpc_tls_credentials_options>(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<SpiffeServerCredentials>(
grpc_core::RefCountedPtr<grpc_tls_credentials_options>(options));
}

@ -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 <grpc/support/port_platform.h>
#include <grpc/grpc_security.h>
#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<grpc_tls_credentials_options> options);
~SpiffeCredentials() override;
grpc_core::RefCountedPtr<grpc_channel_security_connector>
create_security_connector(
grpc_core::RefCountedPtr<grpc_call_credentials> 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<grpc_tls_credentials_options> options_;
};
class SpiffeServerCredentials final : public grpc_server_credentials {
public:
explicit SpiffeServerCredentials(
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options);
~SpiffeServerCredentials() override;
grpc_core::RefCountedPtr<grpc_server_security_connector>
create_security_connector() override;
const grpc_tls_credentials_options& options() const { return *options_; }
private:
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options_;
};
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_SPIFFE_CREDENTIALS_H */

@ -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<grpc_auth_context>* 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<char*>(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<char*>(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<const grpc_ssl_channel_security_connector*>(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<const grpc_ssl_server_credentials*>(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<uint16_t>(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<grpc_auth_context>* 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<grpc_ssl_server_credentials*>(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<const grpc_ssl_server_credentials*>(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<uint16_t>(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<grpc_ssl_channel_security_connector> c =
grpc_core::MakeRefCounted<grpc_ssl_channel_security_connector>(
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;
}

@ -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_auth_context> 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<uint16_t>(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) {

@ -27,7 +27,10 @@
#include <grpc/slice_buffer.h>
#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_auth_context> grpc_ssl_peer_to_auth_context(
const tsi_peer* peer);

@ -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 <grpc/support/port_platform.h>
#include "src/core/lib/security/security_connector/tls/spiffe_security_connector.h"
#include <stdbool.h>
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#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<tsi_ssl_pem_key_cert_pair*>(
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<grpc_tls_key_materials_config>
PopulateSpiffeCredentials(const grpc_tls_credentials_options& options) {
GPR_ASSERT(options.credential_reload_config() != nullptr ||
options.key_materials_config() != nullptr);
grpc_core::RefCountedPtr<grpc_tls_key_materials_config> 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<grpc_tls_credential_reload_arg>();
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<grpc_channel_credentials> channel_creds,
grpc_core::RefCountedPtr<grpc_call_credentials> 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<grpc_auth_context>* 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<const SpiffeCredentials*>(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<char*>(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<const SpiffeChannelSecurityConnector*>(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<grpc_channel_security_connector>
SpiffeChannelSecurityConnector::CreateSpiffeChannelSecurityConnector(
grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,
grpc_core::RefCountedPtr<grpc_call_credentials> 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<SpiffeChannelSecurityConnector> c =
grpc_core::MakeRefCounted<SpiffeChannelSecurityConnector>(
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<const SpiffeCredentials*>(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<SpiffeChannelSecurityConnector*>(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<grpc_tls_server_authorization_check_arg>();
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<grpc_server_credentials> 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<grpc_auth_context>* 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<const grpc_server_security_connector*>(other));
}
grpc_core::RefCountedPtr<grpc_server_security_connector>
SpiffeServerSecurityConnector::CreateSpiffeServerSecurityConnector(
grpc_core::RefCountedPtr<grpc_server_credentials> server_creds) {
if (server_creds == nullptr) {
gpr_log(GPR_ERROR,
"server_creds is nullptr in "
"SpiffeServerSecurityConnectorCreate()");
return nullptr;
}
grpc_core::RefCountedPtr<SpiffeServerSecurityConnector> c =
grpc_core::MakeRefCounted<SpiffeServerSecurityConnector>(
std::move(server_creds));
if (c->RefreshServerHandshakerFactory() != GRPC_SECURITY_OK) {
return nullptr;
}
return c;
}
grpc_security_status
SpiffeServerSecurityConnector::RefreshServerHandshakerFactory() {
const SpiffeServerCredentials* creds =
static_cast<const SpiffeServerCredentials*>(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;
}

@ -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 <grpc/support/port_platform.h>
#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<grpc_channel_security_connector>
CreateSpiffeChannelSecurityConnector(
grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,
grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,
const char* target_name, const char* overridden_target_name,
tsi_ssl_session_cache* ssl_session_cache);
SpiffeChannelSecurityConnector(
grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,
grpc_core::RefCountedPtr<grpc_call_credentials> 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<grpc_auth_context>* 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<grpc_server_security_connector>
CreateSpiffeServerSecurityConnector(
grpc_core::RefCountedPtr<grpc_server_credentials> server_creds);
explicit SpiffeServerSecurityConnector(
grpc_core::RefCountedPtr<grpc_server_credentials> 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<grpc_auth_context>* 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 \
*/

@ -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<const tsi_ssl_handshaker_result*>(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<unsigned char*>(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;
}

@ -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',

@ -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 <stdio.h>
#include <string.h>
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#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<grpc_core::Thread, 1> 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<fullstack_secure_fixture_data>();
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<fullstack_secure_fixture_data*>(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<fullstack_secure_fixture_data*>(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<fullstack_secure_fixture_data*>(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<grpc_tls_server_authorization_check_arg*>(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<fullstack_secure_fixture_data*>(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<grpc_ssl_pem_key_cert_pair**>(
gpr_zalloc(sizeof(grpc_ssl_pem_key_cert_pair*)));
key_cert_pair[0] = static_cast<grpc_ssl_pem_key_cert_pair*>(
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<grpc_ssl_pem_key_cert_pair**>(
gpr_zalloc(sizeof(grpc_ssl_pem_key_cert_pair*)));
key_cert_pair[0] = static_cast<grpc_ssl_pem_key_cert_pair*>(
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<fullstack_secure_fixture_data*>(f->fixture_data));
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
{const_cast<char*>("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;
}

@ -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,

@ -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"]),

@ -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 \

@ -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",

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save