mirror of https://github.com/grpc/grpc.git
Merge pull request #18115 from yihuazhang/SPIFFE_SECURITY_CONNECTOR
Add SPIFFE security stack to gRPCpull/18399/head
commit
a3cc5361e6
28 changed files with 3231 additions and 201 deletions
@ -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 */ |
@ -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 \ |
||||
*/ |
@ -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; |
||||
} |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue