Add spiffe client-side credential reload

pull/19346/head
Yihua Zhang 5 years ago
parent 5bf40ae30e
commit ae863630d5
  1. 44
      CMakeLists.txt
  2. 48
      Makefile
  3. 14
      build.yaml
  4. 2
      grpc.def
  5. 24
      include/grpc/grpc_security.h
  6. 23
      src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc
  7. 3
      src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
  8. 6
      src/core/lib/security/credentials/tls/spiffe_credentials.cc
  9. 12
      src/core/lib/security/security_connector/ssl_utils.h
  10. 210
      src/core/lib/security/security_connector/tls/spiffe_security_connector.cc
  11. 35
      src/core/lib/security/security_connector/tls/spiffe_security_connector.h
  12. 4
      src/ruby/ext/grpc/rb_grpc_imports.generated.c
  13. 6
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  14. 8
      test/core/end2end/fixtures/h2_spiffe.cc
  15. 16
      test/core/security/BUILD
  16. 282
      test/core/security/spiffe_security_connector_test.cc
  17. 2
      test/core/surface/public_headers_must_be_c89.c
  18. 19
      tools/run_tests/generated/sources_and_headers.json
  19. 24
      tools/run_tests/generated/tests.json

@ -641,6 +641,7 @@ add_dependencies(buildtests_cxx grpc_cli)
add_dependencies(buildtests_cxx grpc_core_map_test)
add_dependencies(buildtests_cxx grpc_fetch_oauth2)
add_dependencies(buildtests_cxx grpc_linux_system_roots_test)
add_dependencies(buildtests_cxx grpc_spiffe_security_connector_test)
add_dependencies(buildtests_cxx grpc_tool_test)
add_dependencies(buildtests_cxx grpclb_api_test)
add_dependencies(buildtests_cxx grpclb_end2end_test)
@ -14722,6 +14723,49 @@ endif()
endif (gRPC_BUILD_CODEGEN)
if (gRPC_BUILD_TESTS)
add_executable(grpc_spiffe_security_connector_test
test/core/security/spiffe_security_connector_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(grpc_spiffe_security_connector_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_UPB_GENERATED_DIR}
PRIVATE ${_gRPC_UPB_GRPC_GENERATED_DIR}
PRIVATE ${_gRPC_UPB_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(grpc_spiffe_security_connector_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc++_test_util
grpc++
grpc
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(grpc_tool_test
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc

@ -1222,6 +1222,7 @@ grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin
grpc_php_plugin: $(BINDIR)/$(CONFIG)/grpc_php_plugin
grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin
grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
grpc_spiffe_security_connector_test: $(BINDIR)/$(CONFIG)/grpc_spiffe_security_connector_test
grpc_tool_test: $(BINDIR)/$(CONFIG)/grpc_tool_test
grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test
grpclb_end2end_test: $(BINDIR)/$(CONFIG)/grpclb_end2end_test
@ -1695,6 +1696,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/grpc_core_map_test \
$(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 \
$(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test \
$(BINDIR)/$(CONFIG)/grpc_spiffe_security_connector_test \
$(BINDIR)/$(CONFIG)/grpc_tool_test \
$(BINDIR)/$(CONFIG)/grpclb_api_test \
$(BINDIR)/$(CONFIG)/grpclb_end2end_test \
@ -1862,6 +1864,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/grpc_core_map_test \
$(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 \
$(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test \
$(BINDIR)/$(CONFIG)/grpc_spiffe_security_connector_test \
$(BINDIR)/$(CONFIG)/grpc_tool_test \
$(BINDIR)/$(CONFIG)/grpclb_api_test \
$(BINDIR)/$(CONFIG)/grpclb_end2end_test \
@ -2370,6 +2373,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/grpc_core_map_test || ( echo test grpc_core_map_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_linux_system_roots_test"
$(Q) $(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test || ( echo test grpc_linux_system_roots_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_spiffe_security_connector_test"
$(Q) $(BINDIR)/$(CONFIG)/grpc_spiffe_security_connector_test || ( echo test grpc_spiffe_security_connector_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_tool_test"
$(Q) $(BINDIR)/$(CONFIG)/grpc_tool_test || ( echo test grpc_tool_test failed ; exit 1 )
$(E) "[RUN] Testing grpclb_api_test"
@ -16944,6 +16949,49 @@ ifneq ($(NO_DEPS),true)
endif
GRPC_SPIFFE_SECURITY_CONNECTOR_TEST_SRC = \
test/core/security/spiffe_security_connector_test.cc \
GRPC_SPIFFE_SECURITY_CONNECTOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_SPIFFE_SECURITY_CONNECTOR_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_spiffe_security_connector_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)/grpc_spiffe_security_connector_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/grpc_spiffe_security_connector_test: $(PROTOBUF_DEP) $(GRPC_SPIFFE_SECURITY_CONNECTOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(GRPC_SPIFFE_SECURITY_CONNECTOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpc_spiffe_security_connector_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/core/security/spiffe_security_connector_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_grpc_spiffe_security_connector_test: $(GRPC_SPIFFE_SECURITY_CONNECTOR_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(GRPC_SPIFFE_SECURITY_CONNECTOR_TEST_OBJS:.o=.dep)
endif
endif
GRPC_TOOL_TEST_SRC = \
$(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc \

@ -5112,6 +5112,20 @@ targets:
deps:
- grpc_plugin_support
secure: false
- name: grpc_spiffe_security_connector_test
gtest: true
build: test
language: c++
src:
- test/core/security/spiffe_security_connector_test.cc
deps:
- grpc_test_util
- grpc++_test_util
- grpc++
- grpc
- gpr
uses:
- grpc++_test
- name: grpc_tool_test
gtest: true
build: test

@ -141,6 +141,8 @@ EXPORTS
grpc_tls_credentials_options_set_server_authorization_check_config
grpc_tls_key_materials_config_create
grpc_tls_key_materials_config_set_key_materials
grpc_tls_key_materials_config_set_version
grpc_tls_key_materials_config_get_version
grpc_tls_credential_reload_config_create
grpc_tls_server_authorization_check_config_create
grpc_raw_byte_buffer_create

@ -778,6 +778,21 @@ GRPCAPI int grpc_tls_key_materials_config_set_key_materials(
const grpc_ssl_pem_key_cert_pair** pem_key_cert_pairs,
size_t num_key_cert_pairs);
/** Set grpc_tls_key_materials_config instance with a provided version number,
which is used to keep track of the version of key materials.
It returns 1 on success and 0 on failure. It is used for
experimental purpose for now and subject to change.
*/
GRPCAPI int grpc_tls_key_materials_config_set_version(
grpc_tls_key_materials_config* config, int version);
/** Get the version number of a grpc_tls_key_materials_config instance.
It returns the version number on success and -1 on failure.
It is used for experimental purpose for now and subject to change.
*/
GRPCAPI int grpc_tls_key_materials_config_get_version(
grpc_tls_key_materials_config* config);
/** --- TLS credential reload config. ---
It is used for experimental purpose for now and subject to change.*/
@ -793,10 +808,11 @@ typedef void (*grpc_tls_on_credential_reload_done_cb)(
/** A struct containing all information necessary to schedule/cancel
a credential reload request. cb and cb_user_data represent a gRPC-provided
callback and an argument passed to it. key_materials is an in/output
parameter containing currently used/newly reloaded credentials. status and
error_details are used to hold information about errors occurred when a
credential reload request is scheduled/cancelled. It is used for
experimental purpose for now and subject to change. */
parameter containing currently used/newly reloaded credentials. If
credential reload does not result in a new credential, key_materials should
not be modified. status and error_details are used to hold information about
errors occurred when a credential reload request is scheduled/cancelled. It
is used for experimental purpose for now and subject to change. */
struct grpc_tls_credential_reload_arg {
grpc_tls_on_credential_reload_done_cb cb;
void* cb_user_data;

@ -157,6 +157,29 @@ int grpc_tls_key_materials_config_set_key_materials(
return 1;
}
int grpc_tls_key_materials_config_set_version(
grpc_tls_key_materials_config* config, int version) {
if (config == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_tls_key_materials_config_set_version()");
return 0;
}
config->set_version(version);
return 1;
}
int grpc_tls_key_materials_config_get_version(
grpc_tls_key_materials_config* config) {
if (config == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_tls_key_materials_config_get_version()");
return -1;
}
return config->version();
}
grpc_tls_credential_reload_config* grpc_tls_credential_reload_config_create(
const void* config_user_data,
int (*schedule)(void* config_user_data,

@ -39,12 +39,15 @@ struct grpc_tls_key_materials_config
const PemKeyCertPairList& pem_key_cert_pair_list() const {
return pem_key_cert_pair_list_;
}
int version() const { return version_; }
/** Setters for member fields. **/
void set_key_materials(grpc_core::UniquePtr<char> pem_root_certs,
PemKeyCertPairList pem_key_cert_pair_list);
void set_version(int version) { version_ = version; }
private:
int version_ = 0;
PemKeyCertPairList pem_key_cert_pair_list_;
grpc_core::UniquePtr<char> pem_root_certs_;
};

@ -84,7 +84,7 @@ SpiffeCredentials::create_security_connector(
static_cast<tsi_ssl_session_cache*>(arg->value.pointer.p);
}
}
grpc_core::RefCountedPtr<grpc_channel_security_connector> sc =
grpc_core::RefCountedPtr<grpc_channel_security_connector> sc = grpc_core::
SpiffeChannelSecurityConnector::CreateSpiffeChannelSecurityConnector(
this->Ref(), std::move(call_creds), target_name,
overridden_target_name, ssl_session_cache);
@ -106,8 +106,8 @@ SpiffeServerCredentials::~SpiffeServerCredentials() {}
grpc_core::RefCountedPtr<grpc_server_security_connector>
SpiffeServerCredentials::create_security_connector() {
return SpiffeServerSecurityConnector::CreateSpiffeServerSecurityConnector(
this->Ref());
return grpc_core::SpiffeServerSecurityConnector::
CreateSpiffeServerSecurityConnector(this->Ref());
}
grpc_channel_credentials* grpc_tls_spiffe_credentials_create(

@ -149,9 +149,15 @@ class PemKeyCertPair {
return *this;
}
// Not copyable.
PemKeyCertPair(const PemKeyCertPair&) = delete;
PemKeyCertPair& operator=(const PemKeyCertPair&) = delete;
// Copyable.
PemKeyCertPair(const PemKeyCertPair& other)
: private_key_(gpr_strdup(other.private_key())),
cert_chain_(gpr_strdup(other.cert_chain())) {}
PemKeyCertPair& operator=(const PemKeyCertPair& other) {
private_key_ = grpc_core::UniquePtr<char>(gpr_strdup(other.private_key()));
cert_chain_ = grpc_core::UniquePtr<char>(gpr_strdup(other.cert_chain()));
return *this;
}
char* private_key() const { return private_key_.get(); }
char* cert_chain() const { return cert_chain_.get(); }

@ -38,6 +38,8 @@
#include "src/core/tsi/ssl_transport_security.h"
#include "src/core/tsi/transport_security.h"
namespace grpc_core {
namespace {
tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair(
@ -58,42 +60,55 @@ tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair(
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;
} // namespace
/** -- Util function to fetch SPIFFE server/channel credentials. -- */
grpc_status_code TlsFetchKeyMaterials(
const grpc_core::RefCountedPtr<grpc_tls_key_materials_config>&
key_materials_config,
const grpc_tls_credentials_options& options,
grpc_ssl_certificate_config_reload_status* reload_status) {
GPR_ASSERT(key_materials_config != nullptr);
bool is_key_materials_empty =
key_materials_config->pem_key_cert_pair_list().empty();
if (options.credential_reload_config() == nullptr && is_key_materials_empty) {
gpr_log(GPR_ERROR,
"Either credential reload config or key materials should be "
"provisioned.");
return GRPC_STATUS_FAILED_PRECONDITION;
}
grpc_status_code status = GRPC_STATUS_OK;
/* 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.");
status =
is_key_materials_empty ? GRPC_STATUS_UNIMPLEMENTED : GRPC_STATUS_OK;
} else {
grpc_ssl_certificate_config_reload_status status = arg->status;
if (status == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED) {
GPR_ASSERT(reload_status != nullptr);
*reload_status = arg->status;
if (arg->status == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED) {
/* Key materials is not empty. */
gpr_log(GPR_DEBUG, "Credential does not change after reload.");
} else if (status == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL) {
gpr_log(GPR_ERROR, "Credential reload failed with an error: %s",
arg->error_details);
} else if (arg->status == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL) {
gpr_log(GPR_ERROR, "Credential reload failed with an error:");
if (arg->error_details != nullptr) {
gpr_log(GPR_ERROR, "%s", arg->error_details);
}
status = is_key_materials_empty ? GRPC_STATUS_INTERNAL : GRPC_STATUS_OK;
}
}
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;
return status;
}
} // namespace
SpiffeChannelSecurityConnector::SpiffeChannelSecurityConnector(
grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,
grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,
@ -104,6 +119,7 @@ SpiffeChannelSecurityConnector::SpiffeChannelSecurityConnector(
overridden_target_name_(overridden_target_name == nullptr
? nullptr
: gpr_strdup(overridden_target_name)) {
key_materials_config_ = grpc_tls_key_materials_config_create()->Ref();
check_arg_ = ServerAuthorizationCheckArgCreate(this);
grpc_core::StringView host;
grpc_core::StringView port;
@ -115,12 +131,19 @@ SpiffeChannelSecurityConnector::~SpiffeChannelSecurityConnector() {
if (client_handshaker_factory_ != nullptr) {
tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
}
if (key_materials_config_.get() != nullptr) {
key_materials_config_.get()->Unref();
}
ServerAuthorizationCheckArgDestroy(check_arg_);
}
void SpiffeChannelSecurityConnector::add_handshakers(
grpc_pollset_set* interested_parties,
grpc_core::HandshakeManager* handshake_mgr) {
if (RefreshHandshakerFactory() != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR, "Handshaker factory refresh failed.");
return;
}
// Instantiate TSI handshaker.
tsi_handshaker* tsi_hs = nullptr;
tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
@ -239,32 +262,75 @@ SpiffeChannelSecurityConnector::CreateSpiffeChannelSecurityConnector(
std::move(channel_creds), std::move(request_metadata_creds),
target_name, overridden_target_name);
if (c->InitializeHandshakerFactory(ssl_session_cache) != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR, "Could not initialize client handshaker factory.");
return nullptr;
}
return c;
}
grpc_security_status
SpiffeChannelSecurityConnector::InitializeHandshakerFactory(
grpc_security_status SpiffeChannelSecurityConnector::ReplaceHandshakerFactory(
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->pem_key_cert_pair_list().empty()) {
key_materials_config->Unref();
return GRPC_SECURITY_ERROR;
/* Free the client handshaker factory if exists. */
if (client_handshaker_factory_) {
tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
}
GPR_ASSERT(!key_materials_config_->pem_key_cert_pair_list().empty());
tsi_ssl_pem_key_cert_pair* pem_key_cert_pair = ConvertToTsiPemKeyCertPair(
key_materials_config->pem_key_cert_pair_list());
key_materials_config_->pem_key_cert_pair_list());
grpc_security_status status = grpc_ssl_tsi_client_handshaker_factory_init(
pem_key_cert_pair, key_materials_config->pem_root_certs(),
pem_key_cert_pair, key_materials_config_->pem_root_certs(),
ssl_session_cache, &client_handshaker_factory_);
// Free memory.
key_materials_config->Unref();
/* Free memory. */
grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1);
return status;
}
grpc_security_status
SpiffeChannelSecurityConnector::InitializeHandshakerFactory(
tsi_ssl_session_cache* ssl_session_cache) {
grpc_core::MutexLock lock(&mu_);
const SpiffeCredentials* creds =
static_cast<const SpiffeCredentials*>(channel_creds());
grpc_tls_key_materials_config* key_materials_config =
creds->options().key_materials_config();
/* Copy key materials config from credential options. */
if (key_materials_config != nullptr) {
grpc_tls_key_materials_config::PemKeyCertPairList cert_pair_list =
key_materials_config->pem_key_cert_pair_list();
auto pem_root_certs = grpc_core::UniquePtr<char>(
gpr_strdup(key_materials_config->pem_root_certs()));
key_materials_config_->set_key_materials(std::move(pem_root_certs),
std::move(cert_pair_list));
}
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(),
&reload_status) != GRPC_STATUS_OK) {
/* Raise an error if key materials are not populated. */
return GRPC_SECURITY_ERROR;
}
return ReplaceHandshakerFactory(ssl_session_cache);
}
grpc_security_status
SpiffeChannelSecurityConnector::RefreshHandshakerFactory() {
grpc_core::MutexLock lock(&mu_);
const SpiffeCredentials* creds =
static_cast<const SpiffeCredentials*>(channel_creds());
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(),
&reload_status) != GRPC_STATUS_OK) {
return GRPC_SECURITY_ERROR;
}
if (reload_status != GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW) {
// Re-use existing handshaker factory.
return GRPC_SECURITY_OK;
} else {
return ReplaceHandshakerFactory(nullptr);
}
}
void SpiffeChannelSecurityConnector::ServerAuthorizationCheckDone(
grpc_tls_server_authorization_check_arg* arg) {
GPR_ASSERT(arg != nullptr);
@ -332,19 +398,28 @@ void SpiffeChannelSecurityConnector::ServerAuthorizationCheckArgDestroy(
SpiffeServerSecurityConnector::SpiffeServerSecurityConnector(
grpc_core::RefCountedPtr<grpc_server_credentials> server_creds)
: grpc_server_security_connector(GRPC_SSL_URL_SCHEME,
std::move(server_creds)) {}
std::move(server_creds)) {
key_materials_config_ = grpc_tls_key_materials_config_create()->Ref();
}
SpiffeServerSecurityConnector::~SpiffeServerSecurityConnector() {
if (server_handshaker_factory_ != nullptr) {
tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
}
if (key_materials_config_.get() != nullptr) {
key_materials_config_.get()->Unref();
}
}
void SpiffeServerSecurityConnector::add_handshakers(
grpc_pollset_set* interested_parties,
grpc_core::HandshakeManager* handshake_mgr) {
/* Refresh handshaker factory if needed. */
if (RefreshHandshakerFactory() != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR, "Handshaker factory refresh failed.");
return;
}
/* Create a TLS 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);
@ -384,39 +459,76 @@ SpiffeServerSecurityConnector::CreateSpiffeServerSecurityConnector(
grpc_core::RefCountedPtr<SpiffeServerSecurityConnector> c =
grpc_core::MakeRefCounted<SpiffeServerSecurityConnector>(
std::move(server_creds));
if (c->RefreshServerHandshakerFactory() != GRPC_SECURITY_OK) {
if (c->InitializeHandshakerFactory() != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR, "Could not initialize server handshaker factory.");
return nullptr;
}
return c;
}
grpc_security_status
SpiffeServerSecurityConnector::RefreshServerHandshakerFactory() {
grpc_security_status SpiffeServerSecurityConnector::ReplaceHandshakerFactory() {
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->pem_key_cert_pair_list().empty()) {
key_materials_config->Unref();
return GRPC_SECURITY_ERROR;
}
/* Credential reload takes effect and we need to free the existing
* handshaker library. */
/* Free the server handshaker factory if exists. */
if (server_handshaker_factory_) {
tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
}
GPR_ASSERT(!key_materials_config_->pem_key_cert_pair_list().empty());
tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = ConvertToTsiPemKeyCertPair(
key_materials_config->pem_key_cert_pair_list());
key_materials_config_->pem_key_cert_pair_list());
size_t num_key_cert_pairs =
key_materials_config->pem_key_cert_pair_list().size();
key_materials_config_->pem_key_cert_pair_list().size();
grpc_security_status status = grpc_ssl_tsi_server_handshaker_factory_init(
pem_key_cert_pairs, num_key_cert_pairs,
key_materials_config->pem_root_certs(),
key_materials_config_->pem_root_certs(),
creds->options().cert_request_type(), &server_handshaker_factory_);
// Free memory.
key_materials_config->Unref();
/* Free memory. */
grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pairs,
num_key_cert_pairs);
return status;
}
grpc_security_status
SpiffeServerSecurityConnector::InitializeHandshakerFactory() {
grpc_core::MutexLock lock(&mu_);
const SpiffeServerCredentials* creds =
static_cast<const SpiffeServerCredentials*>(server_creds());
grpc_tls_key_materials_config* key_materials_config =
creds->options().key_materials_config();
if (key_materials_config != nullptr) {
grpc_tls_key_materials_config::PemKeyCertPairList cert_pair_list =
key_materials_config->pem_key_cert_pair_list();
auto pem_root_certs = grpc_core::UniquePtr<char>(
gpr_strdup(key_materials_config->pem_root_certs()));
key_materials_config_->set_key_materials(std::move(pem_root_certs),
std::move(cert_pair_list));
}
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(),
&reload_status) != GRPC_STATUS_OK) {
/* Raise an error if key materials are not populated. */
return GRPC_SECURITY_ERROR;
}
return ReplaceHandshakerFactory();
}
grpc_security_status SpiffeServerSecurityConnector::RefreshHandshakerFactory() {
grpc_core::MutexLock lock(&mu_);
const SpiffeServerCredentials* creds =
static_cast<const SpiffeServerCredentials*>(server_creds());
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(),
&reload_status) != GRPC_STATUS_OK) {
return GRPC_SECURITY_ERROR;
}
if (reload_status != GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW) {
/* At this point, we should have key materials populated. */
return GRPC_SECURITY_OK;
} else {
return ReplaceHandshakerFactory();
}
}
} // namespace grpc_core

@ -21,11 +21,14 @@
#include <grpc/support/port_platform.h>
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h"
#define GRPC_TLS_SPIFFE_TRANSPORT_SECURITY_TYPE "spiffe"
namespace grpc_core {
// Spiffe channel security connector.
class SpiffeChannelSecurityConnector final
: public grpc_channel_security_connector {
@ -66,6 +69,11 @@ class SpiffeChannelSecurityConnector final
grpc_security_status InitializeHandshakerFactory(
tsi_ssl_session_cache* ssl_session_cache);
// A util function to create a new client handshaker factory to replace
// the existing one if exists.
grpc_security_status ReplaceHandshakerFactory(
tsi_ssl_session_cache* ssl_session_cache);
// gRPC-provided callback executed by application, which servers to bring the
// control back to gRPC core.
static void ServerAuthorizationCheckDone(
@ -83,11 +91,17 @@ class SpiffeChannelSecurityConnector final
static void ServerAuthorizationCheckArgDestroy(
grpc_tls_server_authorization_check_arg* arg);
// A util function to refresh SSL TSI client handshaker factory with a valid
// credential.
grpc_security_status RefreshHandshakerFactory();
grpc_core::Mutex mu_;
grpc_closure* on_peer_checked_;
grpc_core::UniquePtr<char> target_name_;
grpc_core::UniquePtr<char> overridden_target_name_;
tsi_ssl_client_handshaker_factory* client_handshaker_factory_ = nullptr;
grpc_tls_server_authorization_check_arg* check_arg_;
grpc_core::RefCountedPtr<grpc_tls_key_materials_config> key_materials_config_;
};
// Spiffe server security connector.
@ -113,11 +127,30 @@ class SpiffeServerSecurityConnector final
int cmp(const grpc_security_connector* other) const override;
private:
// Initialize SSL TSI server handshaker factory.
grpc_security_status InitializeHandshakerFactory();
// A util function to create a new server handshaker factory to replace the
// existing once if exists.
grpc_security_status ReplaceHandshakerFactory();
// A util function to refresh SSL TSI server handshaker factory with a valid
// credential.
grpc_security_status RefreshServerHandshakerFactory();
grpc_security_status RefreshHandshakerFactory();
grpc_core::Mutex mu_;
tsi_ssl_server_handshaker_factory* server_handshaker_factory_ = nullptr;
grpc_core::RefCountedPtr<grpc_tls_key_materials_config> key_materials_config_;
};
// Exposed for testing only.
grpc_status_code TlsFetchKeyMaterials(
const grpc_core::RefCountedPtr<grpc_tls_key_materials_config>&
key_materials_config,
const grpc_tls_credentials_options& options,
grpc_ssl_certificate_config_reload_status* status);
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_TLS_SPIFFE_SECURITY_CONNECTOR_H \
*/

@ -164,6 +164,8 @@ grpc_tls_credentials_options_set_credential_reload_config_type grpc_tls_credenti
grpc_tls_credentials_options_set_server_authorization_check_config_type grpc_tls_credentials_options_set_server_authorization_check_config_import;
grpc_tls_key_materials_config_create_type grpc_tls_key_materials_config_create_import;
grpc_tls_key_materials_config_set_key_materials_type grpc_tls_key_materials_config_set_key_materials_import;
grpc_tls_key_materials_config_set_version_type grpc_tls_key_materials_config_set_version_import;
grpc_tls_key_materials_config_get_version_type grpc_tls_key_materials_config_get_version_import;
grpc_tls_credential_reload_config_create_type grpc_tls_credential_reload_config_create_import;
grpc_tls_server_authorization_check_config_create_type grpc_tls_server_authorization_check_config_create_import;
grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import;
@ -435,6 +437,8 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_tls_credentials_options_set_server_authorization_check_config_import = (grpc_tls_credentials_options_set_server_authorization_check_config_type) GetProcAddress(library, "grpc_tls_credentials_options_set_server_authorization_check_config");
grpc_tls_key_materials_config_create_import = (grpc_tls_key_materials_config_create_type) GetProcAddress(library, "grpc_tls_key_materials_config_create");
grpc_tls_key_materials_config_set_key_materials_import = (grpc_tls_key_materials_config_set_key_materials_type) GetProcAddress(library, "grpc_tls_key_materials_config_set_key_materials");
grpc_tls_key_materials_config_set_version_import = (grpc_tls_key_materials_config_set_version_type) GetProcAddress(library, "grpc_tls_key_materials_config_set_version");
grpc_tls_key_materials_config_get_version_import = (grpc_tls_key_materials_config_get_version_type) GetProcAddress(library, "grpc_tls_key_materials_config_get_version");
grpc_tls_credential_reload_config_create_import = (grpc_tls_credential_reload_config_create_type) GetProcAddress(library, "grpc_tls_credential_reload_config_create");
grpc_tls_server_authorization_check_config_create_import = (grpc_tls_server_authorization_check_config_create_type) GetProcAddress(library, "grpc_tls_server_authorization_check_config_create");
grpc_raw_byte_buffer_create_import = (grpc_raw_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_byte_buffer_create");

@ -467,6 +467,12 @@ extern grpc_tls_key_materials_config_create_type grpc_tls_key_materials_config_c
typedef int(*grpc_tls_key_materials_config_set_key_materials_type)(grpc_tls_key_materials_config* config, const char* pem_root_certs, const grpc_ssl_pem_key_cert_pair** pem_key_cert_pairs, size_t num_key_cert_pairs);
extern grpc_tls_key_materials_config_set_key_materials_type grpc_tls_key_materials_config_set_key_materials_import;
#define grpc_tls_key_materials_config_set_key_materials grpc_tls_key_materials_config_set_key_materials_import
typedef int(*grpc_tls_key_materials_config_set_version_type)(grpc_tls_key_materials_config* config, int version);
extern grpc_tls_key_materials_config_set_version_type grpc_tls_key_materials_config_set_version_import;
#define grpc_tls_key_materials_config_set_version grpc_tls_key_materials_config_set_version_import
typedef int(*grpc_tls_key_materials_config_get_version_type)(grpc_tls_key_materials_config* config);
extern grpc_tls_key_materials_config_get_version_type grpc_tls_key_materials_config_get_version_import;
#define grpc_tls_key_materials_config_get_version grpc_tls_key_materials_config_get_version_import
typedef grpc_tls_credential_reload_config*(*grpc_tls_credential_reload_config_create_type)(const void* config_user_data, int (*schedule)(void* config_user_data, grpc_tls_credential_reload_arg* arg), void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), void (*destruct)(void* config_user_data));
extern grpc_tls_credential_reload_config_create_type grpc_tls_credential_reload_config_create_import;
#define grpc_tls_credential_reload_config_create grpc_tls_credential_reload_config_create_import

@ -138,6 +138,10 @@ static int server_authz_check_async(
// grpc_tls_credentials_options instance.
static int client_cred_reload_sync(void* config_user_data,
grpc_tls_credential_reload_arg* arg) {
if (!arg->key_materials_config->pem_key_cert_pair_list().empty()) {
arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
return 0;
}
grpc_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*)));
@ -160,6 +164,10 @@ static int client_cred_reload_sync(void* config_user_data,
// grpc_tls_credentials_options instance.
static int server_cred_reload_sync(void* config_user_data,
grpc_tls_credential_reload_arg* arg) {
if (!arg->key_materials_config->pem_key_cert_pair_list().empty()) {
arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
return 0;
}
grpc_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*)));

@ -252,3 +252,19 @@ grpc_cc_test(
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test(
name = "spiffe_security_connector_test",
srcs = ["spiffe_security_connector_test.cc"],
language = "C++",
external_deps = [
"gtest",
],
deps = [
"//:gpr",
"//:grpc",
"//:grpc_secure",
"//test/core/util:grpc_test_util",
"//test/core/end2end:ssl_test_data",
],
)

@ -0,0 +1,282 @@
/*
*
* 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 <stdlib.h>
#include <string.h>
#include <gmock/gmock.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <gtest/gtest.h>
#include "src/core/lib/security/security_connector/tls/spiffe_security_connector.h"
#include "test/core/end2end/data/ssl_test_data.h"
#include "test/core/util/test_config.h"
namespace {
enum CredReloadResult { FAIL, SUCCESS, UNCHANGED, ASYNC };
void SetKeyMaterials(grpc_tls_key_materials_config* config) {
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);
grpc_tls_key_materials_config_set_key_materials(
config, gpr_strdup(test_root_cert),
(const grpc_ssl_pem_key_cert_pair**)key_cert_pair, 1);
}
int CredReloadSuccess(void* config_user_data,
grpc_tls_credential_reload_arg* arg) {
SetKeyMaterials(arg->key_materials_config);
arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW;
return 0;
}
int CredReloadFail(void* config_user_data,
grpc_tls_credential_reload_arg* arg) {
arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL;
return 0;
}
int CredReloadUnchanged(void* config_user_data,
grpc_tls_credential_reload_arg* arg) {
arg->status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
return 0;
}
int CredReloadAsync(void* config_user_data,
grpc_tls_credential_reload_arg* arg) {
return 1;
}
} // namespace
namespace grpc {
namespace testing {
class SpiffeSecurityConnectorTest : public ::testing::Test {
protected:
SpiffeSecurityConnectorTest() {}
void SetUp() override {
options_ = grpc_tls_credentials_options_create()->Ref();
config_ = grpc_tls_key_materials_config_create()->Ref();
}
void TearDown() override { config_->Unref(); }
// Set credential reload config in options.
void SetOptions(CredReloadResult type) {
grpc_tls_credential_reload_config* reload_config = nullptr;
switch (type) {
case SUCCESS:
reload_config = grpc_tls_credential_reload_config_create(
nullptr, CredReloadSuccess, nullptr, nullptr);
break;
case FAIL:
reload_config = grpc_tls_credential_reload_config_create(
nullptr, CredReloadFail, nullptr, nullptr);
break;
case UNCHANGED:
reload_config = grpc_tls_credential_reload_config_create(
nullptr, CredReloadUnchanged, nullptr, nullptr);
break;
case ASYNC:
reload_config = grpc_tls_credential_reload_config_create(
nullptr, CredReloadAsync, nullptr, nullptr);
break;
default:
break;
}
grpc_tls_credentials_options_set_credential_reload_config(options_.get(),
reload_config);
}
// Set key materials config.
void SetKeyMaterialsConfig() { SetKeyMaterials(config_.get()); }
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options_;
grpc_core::RefCountedPtr<grpc_tls_key_materials_config> config_;
};
TEST_F(SpiffeSecurityConnectorTest, NoKeysAndConfig) {
grpc_ssl_certificate_config_reload_status reload_status;
grpc_status_code status =
TlsFetchKeyMaterials(config_, *options_, &reload_status);
EXPECT_EQ(status, GRPC_STATUS_FAILED_PRECONDITION);
options_->Unref();
}
TEST_F(SpiffeSecurityConnectorTest, NoKeySuccessReload) {
grpc_ssl_certificate_config_reload_status reload_status;
SetOptions(SUCCESS);
grpc_status_code status =
TlsFetchKeyMaterials(config_, *options_, &reload_status);
EXPECT_EQ(status, GRPC_STATUS_OK);
EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW);
options_->Unref();
}
TEST_F(SpiffeSecurityConnectorTest, NoKeyFailReload) {
grpc_ssl_certificate_config_reload_status reload_status;
SetOptions(FAIL);
grpc_status_code status =
TlsFetchKeyMaterials(config_, *options_, &reload_status);
EXPECT_EQ(status, GRPC_STATUS_INTERNAL);
EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL);
options_->Unref();
}
TEST_F(SpiffeSecurityConnectorTest, NoKeyAsyncReload) {
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
SetOptions(ASYNC);
grpc_status_code status =
TlsFetchKeyMaterials(config_, *options_, &reload_status);
EXPECT_EQ(status, GRPC_STATUS_UNIMPLEMENTED);
EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED);
options_->Unref();
}
TEST_F(SpiffeSecurityConnectorTest, NoKeyUnchangedReload) {
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
SetOptions(UNCHANGED);
grpc_status_code status =
TlsFetchKeyMaterials(config_, *options_, &reload_status);
EXPECT_EQ(status, GRPC_STATUS_OK);
EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED);
options_->Unref();
}
TEST_F(SpiffeSecurityConnectorTest, WithKeyNoReload) {
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
SetKeyMaterialsConfig();
grpc_status_code status =
TlsFetchKeyMaterials(config_, *options_, &reload_status);
EXPECT_EQ(status, GRPC_STATUS_OK);
options_->Unref();
}
TEST_F(SpiffeSecurityConnectorTest, WithKeySuccessReload) {
grpc_ssl_certificate_config_reload_status reload_status;
SetOptions(SUCCESS);
SetKeyMaterialsConfig();
grpc_status_code status =
TlsFetchKeyMaterials(config_, *options_, &reload_status);
EXPECT_EQ(status, GRPC_STATUS_OK);
EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW);
options_->Unref();
}
TEST_F(SpiffeSecurityConnectorTest, WithKeyFailReload) {
grpc_ssl_certificate_config_reload_status reload_status;
SetOptions(FAIL);
SetKeyMaterialsConfig();
grpc_status_code status =
TlsFetchKeyMaterials(config_, *options_, &reload_status);
EXPECT_EQ(status, GRPC_STATUS_OK);
EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL);
options_->Unref();
}
TEST_F(SpiffeSecurityConnectorTest, WithKeyAsyncReload) {
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
SetOptions(ASYNC);
SetKeyMaterialsConfig();
grpc_status_code status =
TlsFetchKeyMaterials(config_, *options_, &reload_status);
EXPECT_EQ(status, GRPC_STATUS_OK);
EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED);
options_->Unref();
}
TEST_F(SpiffeSecurityConnectorTest, WithKeyUnchangedReload) {
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
SetOptions(UNCHANGED);
SetKeyMaterialsConfig();
grpc_status_code status =
TlsFetchKeyMaterials(config_, *options_, &reload_status);
EXPECT_EQ(status, GRPC_STATUS_OK);
EXPECT_EQ(reload_status, GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED);
options_->Unref();
}
TEST_F(SpiffeSecurityConnectorTest, CreateChannelSecurityConnectorSuccess) {
SetOptions(SUCCESS);
auto cred = grpc_core::UniquePtr<grpc_channel_credentials>(
grpc_tls_spiffe_credentials_create(options_.get()));
const char* target_name = "some_target";
grpc_channel_args* new_args = nullptr;
auto connector =
cred->create_security_connector(nullptr, target_name, nullptr, &new_args);
EXPECT_NE(connector, nullptr);
grpc_channel_args_destroy(new_args);
}
TEST_F(SpiffeSecurityConnectorTest,
CreateChannelSecurityConnectorFailNoTargetName) {
SetOptions(SUCCESS);
auto cred = grpc_core::UniquePtr<grpc_channel_credentials>(
grpc_tls_spiffe_credentials_create(options_.get()));
grpc_channel_args* new_args = nullptr;
auto connector =
cred->create_security_connector(nullptr, nullptr, nullptr, &new_args);
EXPECT_EQ(connector, nullptr);
}
TEST_F(SpiffeSecurityConnectorTest, CreateChannelSecurityConnectorFailInit) {
SetOptions(FAIL);
auto cred = grpc_core::UniquePtr<grpc_channel_credentials>(
grpc_tls_spiffe_credentials_create(options_.get()));
grpc_channel_args* new_args = nullptr;
auto connector =
cred->create_security_connector(nullptr, nullptr, nullptr, &new_args);
EXPECT_EQ(connector, nullptr);
}
TEST_F(SpiffeSecurityConnectorTest, CreateServerSecurityConnectorSuccess) {
SetOptions(SUCCESS);
auto cred = grpc_core::UniquePtr<grpc_server_credentials>(
grpc_tls_spiffe_server_credentials_create(options_.get()));
auto connector = cred->create_security_connector();
EXPECT_NE(connector, nullptr);
}
TEST_F(SpiffeSecurityConnectorTest, CreateServerSecurityConnectorFailInit) {
SetOptions(FAIL);
auto cred = grpc_core::UniquePtr<grpc_server_credentials>(
grpc_tls_spiffe_server_credentials_create(options_.get()));
auto connector = cred->create_security_connector();
EXPECT_EQ(connector, nullptr);
}
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
grpc_init();
::testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}

@ -201,6 +201,8 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_tls_credentials_options_set_server_authorization_check_config);
printf("%lx", (unsigned long) grpc_tls_key_materials_config_create);
printf("%lx", (unsigned long) grpc_tls_key_materials_config_set_key_materials);
printf("%lx", (unsigned long) grpc_tls_key_materials_config_set_version);
printf("%lx", (unsigned long) grpc_tls_key_materials_config_get_version);
printf("%lx", (unsigned long) grpc_tls_credential_reload_config_create);
printf("%lx", (unsigned long) grpc_tls_server_authorization_check_config_create);
printf("%lx", (unsigned long) grpc_raw_byte_buffer_create);

@ -4020,6 +4020,25 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"grpc",
"grpc++",
"grpc++_test",
"grpc++_test_util",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c++",
"name": "grpc_spiffe_security_connector_test",
"src": [
"test/core/security/spiffe_security_connector_test.cc"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",

@ -4811,6 +4811,30 @@
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "grpc_spiffe_security_connector_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save