From 618771dc6aa33c38fe4499fee2c3acebef96b04d Mon Sep 17 00:00:00 2001 From: Zhen Lian Date: Fri, 20 Dec 2019 10:02:34 -0800 Subject: [PATCH] [Exposing ALTS Context 2/2] Utility Wrapper Class This PR contains: 1. An ALTS context exposed for users to use, and a GetAltsContextFromAuthContext() function to get ALTS context from an AuthContext. Functionality-wise this part is similar with a previous PR https://github.com/grpc/grpc/pull/21536, but in this PR, we adjusted the code structure and made some minor changes to better suit function clientAuthzCheck() 2. A clientAuthzCheck() function for users to check if the server is authorized --- BUILD | 19 +++ CMakeLists.txt | 103 +++++++++++++ Makefile | 142 ++++++++++++++++- build.yaml | 26 ++++ grpc.gyp | 11 ++ include/grpc/grpc_security_constants.h | 9 ++ include/grpcpp/security/alts_context.h | 67 ++++++++ include/grpcpp/security/alts_util.h | 50 ++++++ src/cpp/common/alts_context.cc | 108 +++++++++++++ src/cpp/common/alts_util.cc | 79 ++++++++++ test/cpp/common/BUILD | 13 ++ test/cpp/common/alts_util_test.cc | 203 +++++++++++++++++++++++++ tools/run_tests/generated/tests.json | 24 +++ 13 files changed, 852 insertions(+), 2 deletions(-) create mode 100644 include/grpcpp/security/alts_context.h create mode 100644 include/grpcpp/security/alts_util.h create mode 100644 src/cpp/common/alts_context.cc create mode 100644 src/cpp/common/alts_util.cc create mode 100644 test/cpp/common/alts_util_test.cc diff --git a/BUILD b/BUILD index 4b1361d2d45..27dbd4e514e 100644 --- a/BUILD +++ b/BUILD @@ -428,6 +428,25 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "grpc++_alts", + srcs = [ + "src/cpp/common/alts_context.cc", + "src/cpp/common/alts_util.cc", + ], + hdrs = [ + "include/grpcpp/security/alts_context.h", + "include/grpcpp/security/alts_util.h", + ], + language = "c++", + standalone = True, + deps = [ + "alts_upb", + "alts_util", + "grpc++", + ], +) + grpc_cc_library( name = "grpc_csharp_ext", srcs = [ diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e3fa30e445..cf6258b464c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -646,6 +646,7 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx alts_security_connector_test) add_dependencies(buildtests_cxx alts_tsi_handshaker_test) add_dependencies(buildtests_cxx alts_tsi_utils_test) + add_dependencies(buildtests_cxx alts_util_test) add_dependencies(buildtests_cxx alts_zero_copy_grpc_protector_test) add_dependencies(buildtests_cxx async_end2end_test) add_dependencies(buildtests_cxx auth_property_iterator_test) @@ -3827,6 +3828,68 @@ if(gRPC_INSTALL) ) endif() + +add_library(grpc++_alts + src/cpp/common/alts_context.cc + src/cpp/common/alts_util.cc +) + +set_target_properties(grpc++_alts PROPERTIES + VERSION ${gRPC_CPP_VERSION} + SOVERSION ${gRPC_CPP_SOVERSION} +) + +if(WIN32 AND MSVC) + set_target_properties(grpc++_alts PROPERTIES COMPILE_PDB_NAME "grpc++_alts" + COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" + ) + if(gRPC_INSTALL) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_alts.pdb + DESTINATION ${gRPC_INSTALL_LIBDIR} OPTIONAL + ) + endif() +endif() + +target_include_directories(grpc++_alts + PUBLIC $ $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + ${_gRPC_PROTO_GENS_DIR} +) +target_link_libraries(grpc++_alts + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++ +) + +foreach(_hdr + include/grpcpp/impl/codegen/security/auth_context.h + include/grpcpp/security/alts_context.h + include/grpcpp/security/alts_util.h +) + string(REPLACE "include/" "" _path ${_hdr}) + get_filename_component(_path ${_path} PATH) + install(FILES ${_hdr} + DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}" + ) +endforeach() + + +if(gRPC_INSTALL) + install(TARGETS grpc++_alts EXPORT gRPCTargets + RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR} + LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR} + ) +endif() + if(gRPC_BUILD_TESTS) if(gRPC_BUILD_CODEGEN) @@ -10245,6 +10308,46 @@ target_link_libraries(alts_tsi_utils_test ) +endif() +if(gRPC_BUILD_TESTS) + +add_executable(alts_util_test + test/cpp/common/alts_util_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(alts_util_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(alts_util_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test_util + grpc_test_util + grpc++_alts + grpc++ + grpc + gpr + grpc++_test_config + ${_gRPC_GFLAGS_LIBRARIES} +) + + endif() if(gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index 369a7acdfe2..7ef9c09b9e1 100644 --- a/Makefile +++ b/Makefile @@ -1162,6 +1162,7 @@ alts_iovec_record_protocol_test: $(BINDIR)/$(CONFIG)/alts_iovec_record_protocol_ alts_security_connector_test: $(BINDIR)/$(CONFIG)/alts_security_connector_test alts_tsi_handshaker_test: $(BINDIR)/$(CONFIG)/alts_tsi_handshaker_test alts_tsi_utils_test: $(BINDIR)/$(CONFIG)/alts_tsi_utils_test +alts_util_test: $(BINDIR)/$(CONFIG)/alts_util_test alts_zero_copy_grpc_protector_test: $(BINDIR)/$(CONFIG)/alts_zero_copy_grpc_protector_test async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test @@ -1411,14 +1412,14 @@ static: static_c static_cxx static_c: pc_c pc_c_unsecure cache.mk $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libupb.a -static_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpcpp_channelz.a +static_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_alts.a $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpcpp_channelz.a static_csharp: static_c $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a shared: shared_c shared_cxx shared_c: pc_c pc_c_unsecure cache.mk $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -shared_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpcpp_channelz$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) +shared_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpcpp_channelz$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) shared_csharp: shared_c $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) grpc_csharp_ext: shared_csharp @@ -1641,6 +1642,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/alts_security_connector_test \ $(BINDIR)/$(CONFIG)/alts_tsi_handshaker_test \ $(BINDIR)/$(CONFIG)/alts_tsi_utils_test \ + $(BINDIR)/$(CONFIG)/alts_util_test \ $(BINDIR)/$(CONFIG)/alts_zero_copy_grpc_protector_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \ @@ -1815,6 +1817,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/alts_security_connector_test \ $(BINDIR)/$(CONFIG)/alts_tsi_handshaker_test \ $(BINDIR)/$(CONFIG)/alts_tsi_utils_test \ + $(BINDIR)/$(CONFIG)/alts_util_test \ $(BINDIR)/$(CONFIG)/alts_zero_copy_grpc_protector_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \ @@ -2262,6 +2265,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/alts_tsi_handshaker_test || ( echo test alts_tsi_handshaker_test failed ; exit 1 ) $(E) "[RUN] Testing alts_tsi_utils_test" $(Q) $(BINDIR)/$(CONFIG)/alts_tsi_utils_test || ( echo test alts_tsi_utils_test failed ; exit 1 ) + $(E) "[RUN] Testing alts_util_test" + $(Q) $(BINDIR)/$(CONFIG)/alts_util_test || ( echo test alts_util_test failed ; exit 1 ) $(E) "[RUN] Testing alts_zero_copy_grpc_protector_test" $(Q) $(BINDIR)/$(CONFIG)/alts_zero_copy_grpc_protector_test || ( echo test alts_zero_copy_grpc_protector_test failed ; exit 1 ) $(E) "[RUN] Testing async_end2end_test" @@ -2590,6 +2595,8 @@ strip-static_cxx: static_cxx ifeq ($(CONFIG),opt) $(E) "[STRIP] Stripping libgrpc++.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++.a + $(E) "[STRIP] Stripping libgrpc++_alts.a" + $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++_alts.a $(E) "[STRIP] Stripping libgrpc++_error_details.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(E) "[STRIP] Stripping libgrpc++_reflection.a" @@ -2620,6 +2627,8 @@ strip-shared_cxx: shared_cxx ifeq ($(CONFIG),opt) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) + $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" + $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" @@ -3195,6 +3204,9 @@ install-static_cxx: static_cxx strip-static_cxx install-pkg-config_cxx $(E) "[INSTALL] Installing libgrpc++.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(prefix)/lib/libgrpc++.a + $(E) "[INSTALL] Installing libgrpc++_alts.a" + $(Q) $(INSTALL) -d $(prefix)/lib + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_alts.a $(prefix)/lib/libgrpc++_alts.a $(E) "[INSTALL] Installing libgrpc++_error_details.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(prefix)/lib/libgrpc++_error_details.a @@ -3281,6 +3293,15 @@ ifeq ($(SYSTEM),MINGW32) else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so +endif + $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" + $(Q) $(INSTALL) -d $(prefix)/lib + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) +ifeq ($(SYSTEM),MINGW32) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_alts$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_alts.a +else ifneq ($(SYSTEM),Darwin) + $(Q) ln -sf $(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_alts.so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_alts.so endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib @@ -6219,6 +6240,78 @@ endif endif +LIBGRPC++_ALTS_SRC = \ + src/cpp/common/alts_context.cc \ + src/cpp/common/alts_util.cc \ + +PUBLIC_HEADERS_CXX += \ + include/grpcpp/impl/codegen/security/auth_context.h \ + include/grpcpp/security/alts_context.h \ + include/grpcpp/security/alts_util.h \ + +LIBGRPC++_ALTS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_ALTS_SRC)))) + + +ifeq ($(NO_SECURE),true) + +# You can't build secure libraries if you don't have OpenSSL. + +$(LIBDIR)/$(CONFIG)/libgrpc++_alts.a: openssl_dep_error + +$(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): openssl_dep_error + +else + +ifeq ($(NO_PROTOBUF),true) + +# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. + +$(LIBDIR)/$(CONFIG)/libgrpc++_alts.a: protobuf_dep_error + +$(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): protobuf_dep_error + +else + +$(LIBDIR)/$(CONFIG)/libgrpc++_alts.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(UPB_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_ALTS_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(ADDRESS_SORTING_MERGE_OBJS) $(UPB_MERGE_OBJS) + $(E) "[AR] Creating $@" + $(Q) mkdir -p `dirname $@` + $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_alts.a + $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_alts.a $(LIBGRPC++_ALTS_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(ADDRESS_SORTING_MERGE_OBJS) $(UPB_MERGE_OBJS) +ifeq ($(SYSTEM),Darwin) + $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_alts.a +endif + + + +ifeq ($(SYSTEM),MINGW32) +$(LIBDIR)/$(CONFIG)/grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_ALTS_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(UPB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(OPENSSL_DEP) + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_alts$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_alts$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_ALTS_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++$(SHARED_VERSION_CPP)-dll +else +$(LIBDIR)/$(CONFIG)/libgrpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_ALTS_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(UPB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP) + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` +ifeq ($(SYSTEM),Darwin) + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_ALTS_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++ +else + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_alts.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_ALTS_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++ + $(Q) ln -sf $(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_alts$(SHARED_VERSION_CPP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc++_alts$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_alts$(SHARED_VERSION_CPP).so +endif +endif + +endif + +endif + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(LIBGRPC++_ALTS_OBJS:.o=.dep) +endif +endif + + LIBGRPC++_CORE_STATS_SRC = \ $(GENDIR)/src/proto/grpc/core/stats.pb.cc $(GENDIR)/src/proto/grpc/core/stats.grpc.pb.cc \ src/cpp/util/core_stats.cc \ @@ -14189,6 +14282,49 @@ endif endif +ALTS_UTIL_TEST_SRC = \ + test/cpp/common/alts_util_test.cc \ + +ALTS_UTIL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALTS_UTIL_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/alts_util_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/alts_util_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/alts_util_test: $(PROTOBUF_DEP) $(ALTS_UTIL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_alts.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(ALTS_UTIL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_alts.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/alts_util_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/common/alts_util_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_alts.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a + +deps_alts_util_test: $(ALTS_UTIL_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(ALTS_UTIL_TEST_OBJS:.o=.dep) +endif +endif + + ALTS_ZERO_COPY_GRPC_PROTECTOR_TEST_SRC = \ test/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector_test.cc \ @@ -23216,6 +23352,8 @@ src/core/tsi/ssl_transport_security.cc: $(OPENSSL_DEP) src/core/tsi/transport_security.cc: $(OPENSSL_DEP) src/core/tsi/transport_security_grpc.cc: $(OPENSSL_DEP) src/cpp/client/secure_credentials.cc: $(OPENSSL_DEP) +src/cpp/common/alts_context.cc: $(OPENSSL_DEP) +src/cpp/common/alts_util.cc: $(OPENSSL_DEP) src/cpp/common/auth_property_iterator.cc: $(OPENSSL_DEP) src/cpp/common/secure_auth_context.cc: $(OPENSSL_DEP) src/cpp/common/secure_channel_arguments.cc: $(OPENSSL_DEP) diff --git a/build.yaml b/build.yaml index c1777aec2ab..accfad1ee20 100644 --- a/build.yaml +++ b/build.yaml @@ -1879,6 +1879,19 @@ libs: - grpc++_codegen_proto - grpc++_codegen_base_src secure: check +- name: grpc++_alts + build: all + language: c++ + public_headers: + - include/grpcpp/impl/codegen/security/auth_context.h + - include/grpcpp/security/alts_context.h + - include/grpcpp/security/alts_util.h + src: + - src/cpp/common/alts_context.cc + - src/cpp/common/alts_util.cc + deps: + - grpc++ + baselib: true - name: grpc++_core_stats build: private language: c++ @@ -4006,6 +4019,19 @@ targets: - alts_test_util - gpr - grpc +- name: alts_util_test + build: test + language: c++ + src: + - test/cpp/common/alts_util_test.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++_alts + - grpc++ + - grpc + - gpr + - grpc++_test_config - name: alts_zero_copy_grpc_protector_test build: test language: c++ diff --git a/grpc.gyp b/grpc.gyp index 0092e4501d4..5caad279cec 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -1749,6 +1749,17 @@ 'src/cpp/codegen/codegen_init.cc', ], }, + { + 'target_name': 'grpc++_alts', + 'type': 'static_library', + 'dependencies': [ + 'grpc++', + ], + 'sources': [ + 'src/cpp/common/alts_context.cc', + 'src/cpp/common/alts_util.cc', + ], + }, { 'target_name': 'grpc++_core_stats', 'type': 'static_library', diff --git a/include/grpc/grpc_security_constants.h b/include/grpc/grpc_security_constants.h index 1be524a78f8..13d6e9ff8e0 100644 --- a/include/grpc/grpc_security_constants.h +++ b/include/grpc/grpc_security_constants.h @@ -105,6 +105,15 @@ typedef enum { GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY } grpc_ssl_client_certificate_request_type; +/* Security levels of grpc transport security */ +typedef enum { + GRPC_SECURITY_MIN, + GRPC_SECURITY_NONE = GRPC_SECURITY_MIN, + GRPC_INTEGRITY_ONLY, + GRPC_PRIVACY_AND_INTEGRITY, + GRPC_SECURITY_MAX = GRPC_PRIVACY_AND_INTEGRITY, +} grpc_security_level; + /** * Type of local connections for which local channel/server credentials will be * applied. It supports UDS and local TCP connections. diff --git a/include/grpcpp/security/alts_context.h b/include/grpcpp/security/alts_context.h new file mode 100644 index 00000000000..9208730dbc1 --- /dev/null +++ b/include/grpcpp/security/alts_context.h @@ -0,0 +1,67 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SECURITY_ALTS_CONTEXT_H +#define GRPCPP_SECURITY_ALTS_CONTEXT_H + +#include +#include + +#include + +struct grpc_gcp_AltsContext; + +namespace grpc { +namespace experimental { + +// AltsContext is a wrapper class for grpc_gcp_AltsContext. +class AltsContext { + public: + struct RpcProtocolVersions { + struct Version { + int major_version; + int minor_version; + }; + Version max_rpc_version; + Version min_rpc_version; + }; + explicit AltsContext(const grpc_gcp_AltsContext* ctx); + AltsContext& operator=(const AltsContext&) = default; + AltsContext(const AltsContext&) = default; + + grpc::string application_protocol() const; + grpc::string record_protocol() const; + grpc::string peer_service_account() const; + grpc::string local_service_account() const; + grpc_security_level security_level() const; + RpcProtocolVersions peer_rpc_versions() const; + + private: + // TODO(ZhenLian): Also plumb field peer_attributes when it is in use + grpc::string application_protocol_; + grpc::string record_protocol_; + grpc::string peer_service_account_; + grpc::string local_service_account_; + grpc_security_level security_level_ = GRPC_SECURITY_NONE; + RpcProtocolVersions peer_rpc_versions_ = {{0, 0}, {0, 0}}; +}; + +} // namespace experimental +} // namespace grpc + +#endif // GRPCPP_SECURITY_ALTS_CONTEXT_H diff --git a/include/grpcpp/security/alts_util.h b/include/grpcpp/security/alts_util.h new file mode 100644 index 00000000000..2b2b07e4bd1 --- /dev/null +++ b/include/grpcpp/security/alts_util.h @@ -0,0 +1,50 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SECURITY_ALTS_UTIL_H +#define GRPCPP_SECURITY_ALTS_UTIL_H + +#include +#include +#include +#include + +#include + +struct grpc_gcp_AltsContext; + +namespace grpc { +namespace experimental { + +// GetAltsContextFromAuthContext helps to get the AltsContext from AuthContext. +// If ALTS is not the transport security protocol used to establish the +// connection, this function will return nullptr. +std::unique_ptr GetAltsContextFromAuthContext( + const std::shared_ptr& auth_context); + +// This utility function performs ALTS client authorization check on server +// side, i.e., checks if the client identity matches one of the expected service +// accounts. It returns OK if client is authorized and an error otherwise. +grpc::Status AltsClientAuthzCheck( + const std::shared_ptr& auth_context, + const std::vector& expected_service_accounts); + +} // namespace experimental +} // namespace grpc + +#endif // GRPCPP_SECURITY_ALTS_UTIL_H diff --git a/src/cpp/common/alts_context.cc b/src/cpp/common/alts_context.cc new file mode 100644 index 00000000000..f58d9f5f047 --- /dev/null +++ b/src/cpp/common/alts_context.cc @@ -0,0 +1,108 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" +#include "src/proto/grpc/gcp/altscontext.upb.h" + +namespace grpc { +namespace experimental { + +// A upb-generated grpc_gcp_AltsContext is passed in to construct an +// AltsContext. Normal users should use GetAltsContextFromAuthContext to get +// AltsContext, instead of constructing their own. +AltsContext::AltsContext(const grpc_gcp_AltsContext* ctx) { + upb_strview application_protocol = + grpc_gcp_AltsContext_application_protocol(ctx); + if (application_protocol.data != nullptr && application_protocol.size > 0) { + application_protocol_ = + grpc::string(application_protocol.data, application_protocol.size); + } + upb_strview record_protocol = grpc_gcp_AltsContext_record_protocol(ctx); + if (record_protocol.data != nullptr && record_protocol.size > 0) { + record_protocol_ = grpc::string(record_protocol.data, record_protocol.size); + } + upb_strview peer_service_account = + grpc_gcp_AltsContext_peer_service_account(ctx); + if (peer_service_account.data != nullptr && peer_service_account.size > 0) { + peer_service_account_ = + grpc::string(peer_service_account.data, peer_service_account.size); + } + upb_strview local_service_account = + grpc_gcp_AltsContext_local_service_account(ctx); + if (local_service_account.data != nullptr && local_service_account.size > 0) { + local_service_account_ = + grpc::string(local_service_account.data, local_service_account.size); + } + const grpc_gcp_RpcProtocolVersions* versions = + grpc_gcp_AltsContext_peer_rpc_versions(ctx); + if (versions != nullptr) { + const grpc_gcp_RpcProtocolVersions_Version* max_version = + grpc_gcp_RpcProtocolVersions_max_rpc_version(versions); + if (max_version != nullptr) { + int max_version_major = + grpc_gcp_RpcProtocolVersions_Version_major(max_version); + int max_version_minor = + grpc_gcp_RpcProtocolVersions_Version_minor(max_version); + peer_rpc_versions_.max_rpc_version.major_version = max_version_major; + peer_rpc_versions_.max_rpc_version.minor_version = max_version_minor; + } + const grpc_gcp_RpcProtocolVersions_Version* min_version = + grpc_gcp_RpcProtocolVersions_min_rpc_version(versions); + if (min_version != nullptr) { + int min_version_major = + grpc_gcp_RpcProtocolVersions_Version_major(min_version); + int min_version_minor = + grpc_gcp_RpcProtocolVersions_Version_minor(min_version); + peer_rpc_versions_.min_rpc_version.major_version = min_version_major; + peer_rpc_versions_.min_rpc_version.minor_version = min_version_minor; + } + } + if (grpc_gcp_AltsContext_security_level(ctx) >= GRPC_SECURITY_MIN || + grpc_gcp_AltsContext_security_level(ctx) <= GRPC_SECURITY_MAX) { + security_level_ = static_cast( + grpc_gcp_AltsContext_security_level(ctx)); + } +} + +grpc::string AltsContext::application_protocol() const { + return application_protocol_; +} + +grpc::string AltsContext::record_protocol() const { return record_protocol_; } + +grpc::string AltsContext::peer_service_account() const { + return peer_service_account_; +} + +grpc::string AltsContext::local_service_account() const { + return local_service_account_; +} + +grpc_security_level AltsContext::security_level() const { + return security_level_; +} + +AltsContext::RpcProtocolVersions AltsContext::peer_rpc_versions() const { + return peer_rpc_versions_; +} + +} // namespace experimental +} // namespace grpc diff --git a/src/cpp/common/alts_util.cc b/src/cpp/common/alts_util.cc new file mode 100644 index 00000000000..7ac299816b9 --- /dev/null +++ b/src/cpp/common/alts_util.cc @@ -0,0 +1,79 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "src/core/lib/gprpp/memory.h" +#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" +#include "src/cpp/common/secure_auth_context.h" +#include "src/proto/grpc/gcp/altscontext.upb.h" + +namespace grpc { +namespace experimental { + +std::unique_ptr GetAltsContextFromAuthContext( + const std::shared_ptr& auth_context) { + if (auth_context == nullptr) { + gpr_log(GPR_ERROR, "auth_context is nullptr."); + return nullptr; + } + std::vector ctx_vector = + auth_context->FindPropertyValues(TSI_ALTS_CONTEXT); + if (ctx_vector.size() != 1) { + gpr_log(GPR_ERROR, "contains zero or more than one ALTS context."); + return nullptr; + } + upb::Arena context_arena; + grpc_gcp_AltsContext* ctx = grpc_gcp_AltsContext_parse( + ctx_vector[0].data(), ctx_vector[0].size(), context_arena.ptr()); + if (ctx == nullptr) { + gpr_log(GPR_ERROR, "fails to parse ALTS context."); + return nullptr; + } + if (grpc_gcp_AltsContext_security_level(ctx) < GRPC_SECURITY_MIN || + grpc_gcp_AltsContext_security_level(ctx) > GRPC_SECURITY_MAX) { + gpr_log(GPR_ERROR, "security_level is invalid."); + return nullptr; + } + return grpc_core::MakeUnique(AltsContext(ctx)); +} + +grpc::Status AltsClientAuthzCheck( + const std::shared_ptr& auth_context, + const std::vector& expected_service_accounts) { + std::unique_ptr alts_ctx = + GetAltsContextFromAuthContext(auth_context); + if (alts_ctx == nullptr) { + return grpc::Status(grpc::StatusCode::PERMISSION_DENIED, + "fails to parse ALTS context."); + } + if (std::find(expected_service_accounts.begin(), + expected_service_accounts.end(), + alts_ctx->peer_service_account()) != + expected_service_accounts.end()) { + return grpc::Status::OK; + } + return grpc::Status( + grpc::StatusCode::PERMISSION_DENIED, + "client " + alts_ctx->peer_service_account() + " is not authorized."); +} + +} // namespace experimental +} // namespace grpc diff --git a/test/cpp/common/BUILD b/test/cpp/common/BUILD index 05e7bda330a..3a579273162 100644 --- a/test/cpp/common/BUILD +++ b/test/cpp/common/BUILD @@ -108,3 +108,16 @@ grpc_cc_test( "//test/cpp/util:test_util", ], ) + +grpc_cc_test( + name = "alts_util_test", + srcs = ["alts_util_test.cc"], + external_deps = [ + "gtest", + ], + deps = [ + "//:grpc++_alts", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) diff --git a/test/cpp/common/alts_util_test.cc b/test/cpp/common/alts_util_test.cc new file mode 100644 index 00000000000..88c4543fe1e --- /dev/null +++ b/test/cpp/common/alts_util_test.cc @@ -0,0 +1,203 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" +#include "src/cpp/common/secure_auth_context.h" +#include "src/proto/grpc/gcp/altscontext.upb.h" +#include "test/cpp/util/string_ref_helper.h" + +namespace grpc { +namespace { + +TEST(AltsUtilTest, NullAuthContext) { + std::unique_ptr alts_context = + experimental::GetAltsContextFromAuthContext(nullptr); + EXPECT_EQ(alts_context, nullptr); +} + +TEST(AltsUtilTest, EmptyAuthContext) { + grpc_core::RefCountedPtr ctx = + grpc_core::MakeRefCounted(nullptr); + const std::shared_ptr auth_context( + new SecureAuthContext(ctx.get())); + std::unique_ptr alts_context = + experimental::GetAltsContextFromAuthContext(auth_context); + EXPECT_EQ(alts_context, nullptr); +} + +TEST(AltsUtilTest, AuthContextWithMoreThanOneAltsContext) { + grpc_core::RefCountedPtr ctx = + grpc_core::MakeRefCounted(nullptr); + const std::shared_ptr auth_context( + new SecureAuthContext(ctx.get())); + ctx.reset(); + auth_context->AddProperty(TSI_ALTS_CONTEXT, "context1"); + auth_context->AddProperty(TSI_ALTS_CONTEXT, "context2"); + std::unique_ptr alts_context = + experimental::GetAltsContextFromAuthContext(auth_context); + EXPECT_EQ(alts_context, nullptr); +} + +TEST(AltsUtilTest, AuthContextWithBadAltsContext) { + grpc_core::RefCountedPtr ctx = + grpc_core::MakeRefCounted(nullptr); + const std::shared_ptr auth_context( + new SecureAuthContext(ctx.get())); + ctx.reset(); + auth_context->AddProperty(TSI_ALTS_CONTEXT, + "bad context string serialization"); + std::unique_ptr alts_context = + experimental::GetAltsContextFromAuthContext(auth_context); + EXPECT_EQ(alts_context, nullptr); +} + +TEST(AltsUtilTest, AuthContextWithGoodAltsContextWithoutRpcVersions) { + grpc_core::RefCountedPtr ctx = + grpc_core::MakeRefCounted(nullptr); + const std::shared_ptr auth_context( + new SecureAuthContext(ctx.get())); + ctx.reset(); + grpc::string expected_ap("application protocol"); + grpc::string expected_rp("record protocol"); + grpc::string expected_peer("peer"); + grpc::string expected_local("local"); + grpc_security_level expected_sl = GRPC_INTEGRITY_ONLY; + upb::Arena context_arena; + grpc_gcp_AltsContext* context = grpc_gcp_AltsContext_new(context_arena.ptr()); + grpc_gcp_AltsContext_set_application_protocol( + context, upb_strview_make(expected_ap.data(), expected_ap.length())); + grpc_gcp_AltsContext_set_record_protocol( + context, upb_strview_make(expected_rp.data(), expected_rp.length())); + grpc_gcp_AltsContext_set_security_level(context, expected_sl); + grpc_gcp_AltsContext_set_peer_service_account( + context, upb_strview_make(expected_peer.data(), expected_peer.length())); + grpc_gcp_AltsContext_set_local_service_account( + context, + upb_strview_make(expected_local.data(), expected_local.length())); + size_t serialized_ctx_length; + char* serialized_ctx = grpc_gcp_AltsContext_serialize( + context, context_arena.ptr(), &serialized_ctx_length); + EXPECT_NE(serialized_ctx, nullptr); + auth_context->AddProperty(TSI_ALTS_CONTEXT, + string(serialized_ctx, serialized_ctx_length)); + std::unique_ptr alts_context = + experimental::GetAltsContextFromAuthContext(auth_context); + EXPECT_NE(alts_context, nullptr); + EXPECT_EQ(expected_ap, alts_context->application_protocol()); + EXPECT_EQ(expected_rp, alts_context->record_protocol()); + EXPECT_EQ(expected_peer, alts_context->peer_service_account()); + EXPECT_EQ(expected_local, alts_context->local_service_account()); + EXPECT_EQ(expected_sl, alts_context->security_level()); + // all rpc versions should be 0 if not set + experimental::AltsContext::RpcProtocolVersions rpc_protocol_versions = + alts_context->peer_rpc_versions(); + EXPECT_EQ(0, rpc_protocol_versions.max_rpc_version.major_version); + EXPECT_EQ(0, rpc_protocol_versions.max_rpc_version.minor_version); + EXPECT_EQ(0, rpc_protocol_versions.min_rpc_version.major_version); + EXPECT_EQ(0, rpc_protocol_versions.min_rpc_version.minor_version); +} + +TEST(AltsUtilTest, AuthContextWithGoodAltsContext) { + grpc_core::RefCountedPtr ctx = + grpc_core::MakeRefCounted(nullptr); + const std::shared_ptr auth_context( + new SecureAuthContext(ctx.get())); + ctx.reset(); + upb::Arena context_arena; + grpc_gcp_AltsContext* context = grpc_gcp_AltsContext_new(context_arena.ptr()); + upb::Arena versions_arena; + grpc_gcp_RpcProtocolVersions* versions = + grpc_gcp_RpcProtocolVersions_new(versions_arena.ptr()); + upb::Arena max_major_version_arena; + grpc_gcp_RpcProtocolVersions_Version* version = + grpc_gcp_RpcProtocolVersions_Version_new(max_major_version_arena.ptr()); + grpc_gcp_RpcProtocolVersions_Version_set_major(version, 10); + grpc_gcp_RpcProtocolVersions_set_max_rpc_version(versions, version); + grpc_gcp_AltsContext_set_peer_rpc_versions(context, versions); + size_t serialized_ctx_length; + char* serialized_ctx = grpc_gcp_AltsContext_serialize( + context, context_arena.ptr(), &serialized_ctx_length); + EXPECT_NE(serialized_ctx, nullptr); + auth_context->AddProperty(TSI_ALTS_CONTEXT, + string(serialized_ctx, serialized_ctx_length)); + std::unique_ptr alts_context = + experimental::GetAltsContextFromAuthContext(auth_context); + EXPECT_NE(alts_context, nullptr); + EXPECT_EQ("", alts_context->application_protocol()); + EXPECT_EQ("", alts_context->record_protocol()); + EXPECT_EQ("", alts_context->peer_service_account()); + EXPECT_EQ("", alts_context->local_service_account()); + EXPECT_EQ(GRPC_SECURITY_NONE, alts_context->security_level()); + experimental::AltsContext::RpcProtocolVersions rpc_protocol_versions = + alts_context->peer_rpc_versions(); + EXPECT_EQ(10, rpc_protocol_versions.max_rpc_version.major_version); + EXPECT_EQ(0, rpc_protocol_versions.max_rpc_version.minor_version); + EXPECT_EQ(0, rpc_protocol_versions.min_rpc_version.major_version); + EXPECT_EQ(0, rpc_protocol_versions.min_rpc_version.minor_version); +} + +TEST(AltsUtilTest, AltsClientAuthzCheck) { + // AltsClientAuthzCheck function should return a permission denied error on + // the bad_auth_context, whose internal ALTS context does not exist + const std::shared_ptr bad_auth_context( + new SecureAuthContext(nullptr)); + std::vector service_accounts{"client"}; + grpc::Status status = + experimental::AltsClientAuthzCheck(bad_auth_context, service_accounts); + EXPECT_EQ(grpc::StatusCode::PERMISSION_DENIED, status.error_code()); + // AltsClientAuthzCheck function should function normally when the peer name + // in ALTS context is listed in service_accounts + grpc_core::RefCountedPtr ctx = + grpc_core::MakeRefCounted(nullptr); + const std::shared_ptr auth_context( + new SecureAuthContext(ctx.get())); + ctx.reset(); + grpc::string peer("good_client"); + std::vector good_service_accounts{"good_client", + "good_client_1"}; + std::vector bad_service_accounts{"bad_client", "bad_client_1"}; + upb::Arena context_arena; + grpc_gcp_AltsContext* context = grpc_gcp_AltsContext_new(context_arena.ptr()); + grpc_gcp_AltsContext_set_peer_service_account( + context, upb_strview_make(peer.data(), peer.length())); + size_t serialized_ctx_length; + char* serialized_ctx = grpc_gcp_AltsContext_serialize( + context, context_arena.ptr(), &serialized_ctx_length); + EXPECT_NE(serialized_ctx, nullptr); + auth_context->AddProperty(TSI_ALTS_CONTEXT, + string(serialized_ctx, serialized_ctx_length)); + grpc::Status good_status = + experimental::AltsClientAuthzCheck(auth_context, good_service_accounts); + EXPECT_TRUE(good_status.ok()); + grpc::Status bad_status = + experimental::AltsClientAuthzCheck(auth_context, bad_service_accounts); + EXPECT_EQ(grpc::StatusCode::PERMISSION_DENIED, bad_status.error_code()); +} + +} // namespace +} // namespace grpc + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 9197a29d163..a3a658f3e36 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -3247,6 +3247,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c++", + "name": "alts_util_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false,