commit
c6da80bcce
114 changed files with 3767 additions and 481 deletions
@ -0,0 +1,12 @@ |
||||
prefix=@CMAKE_INSTALL_PREFIX@ |
||||
exec_prefix=${prefix} |
||||
includedir=${prefix}/include |
||||
libdir=${exec_prefix}/lib |
||||
|
||||
Name: @PC_NAME@ |
||||
Description: @PC_DESCRIPTION@ |
||||
Version: @PC_VERSION@ |
||||
Cflags: -I${includedir} |
||||
Requires: @PC_REQUIRES@ |
||||
Libs: -L${libdir} @PC_LIB@ |
||||
Libs.private: @PC_LIBS_PRIVATE@ |
@ -0,0 +1,330 @@ |
||||
/*
|
||||
* |
||||
* 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_TLS_CREDENTIALS_OPTIONS_H |
||||
#define GRPCPP_SECURITY_TLS_CREDENTIALS_OPTIONS_H |
||||
|
||||
#include <memory> |
||||
#include <vector> |
||||
|
||||
#include <grpc/grpc_security_constants.h> |
||||
#include <grpc/status.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpcpp/support/config.h> |
||||
|
||||
typedef struct grpc_tls_credential_reload_arg grpc_tls_credential_reload_arg; |
||||
typedef struct grpc_tls_credential_reload_config |
||||
grpc_tls_credential_reload_config; |
||||
typedef struct grpc_tls_server_authorization_check_arg |
||||
grpc_tls_server_authorization_check_arg; |
||||
typedef struct grpc_tls_server_authorization_check_config |
||||
grpc_tls_server_authorization_check_config; |
||||
typedef struct grpc_tls_credentials_options grpc_tls_credentials_options; |
||||
|
||||
namespace grpc_impl { |
||||
namespace experimental { |
||||
|
||||
/** TLS key materials config, wrapper for grpc_tls_key_materials_config. It is
|
||||
* used for experimental purposes for now and subject to change. **/ |
||||
class TlsKeyMaterialsConfig { |
||||
public: |
||||
struct PemKeyCertPair { |
||||
grpc::string private_key; |
||||
grpc::string cert_chain; |
||||
}; |
||||
|
||||
/** Getters for member fields. **/ |
||||
const grpc::string pem_root_certs() const { return pem_root_certs_; } |
||||
const std::vector<PemKeyCertPair>& pem_key_cert_pair_list() const { |
||||
return pem_key_cert_pair_list_; |
||||
} |
||||
int version() const { return version_; } |
||||
|
||||
/** Setter for key materials that will be called by the user. The setter
|
||||
* transfers ownership of the arguments to the config. **/ |
||||
void set_pem_root_certs(grpc::string pem_root_certs); |
||||
void add_pem_key_cert_pair(const PemKeyCertPair& pem_key_cert_pair); |
||||
void set_key_materials(grpc::string pem_root_certs, |
||||
std::vector<PemKeyCertPair> pem_key_cert_pair_list); |
||||
void set_version(int version) { version_ = version; }; |
||||
|
||||
private: |
||||
int version_ = 0; |
||||
std::vector<PemKeyCertPair> pem_key_cert_pair_list_; |
||||
grpc::string pem_root_certs_; |
||||
}; |
||||
|
||||
/** TLS credential reload arguments, wraps grpc_tls_credential_reload_arg. It is
|
||||
* used for experimental purposes for now and it is subject to change. |
||||
* |
||||
* The credential reload arg contains all the info necessary to schedule/cancel |
||||
* a credential reload request. The callback function must be called after |
||||
* finishing the schedule operation. See the description of the |
||||
* grpc_tls_credential_reload_arg struct in grpc_security.h for more details. |
||||
* **/ |
||||
class TlsCredentialReloadArg { |
||||
public: |
||||
/** TlsCredentialReloadArg does not take ownership of the C arg that is passed
|
||||
* to the constructor. One must remember to free any memory allocated to the C |
||||
* arg after using the setter functions below. **/ |
||||
TlsCredentialReloadArg(grpc_tls_credential_reload_arg* arg); |
||||
~TlsCredentialReloadArg(); |
||||
|
||||
/** Getters for member fields. The callback function is not exposed.
|
||||
* They return the corresponding fields of the underlying C arg. In the case |
||||
* of the key materials config, it creates a new instance of the C++ key |
||||
* materials config from the underlying C grpc_tls_key_materials_config. **/ |
||||
void* cb_user_data() const; |
||||
bool is_pem_key_cert_pair_list_empty() const; |
||||
grpc_ssl_certificate_config_reload_status status() const; |
||||
grpc::string error_details() const; |
||||
|
||||
/** Setters for member fields. They modify the fields of the underlying C arg.
|
||||
* The setters for the key_materials_config and the error_details allocate |
||||
* memory when modifying c_arg_, so one must remember to free c_arg_'s |
||||
* original key_materials_config or error_details after using the appropriate |
||||
* setter function. |
||||
* **/ |
||||
void set_cb_user_data(void* cb_user_data); |
||||
void set_pem_root_certs(const grpc::string& pem_root_certs); |
||||
void add_pem_key_cert_pair( |
||||
TlsKeyMaterialsConfig::PemKeyCertPair pem_key_cert_pair); |
||||
void set_key_materials_config( |
||||
const std::shared_ptr<TlsKeyMaterialsConfig>& key_materials_config); |
||||
void set_status(grpc_ssl_certificate_config_reload_status status); |
||||
void set_error_details(const grpc::string& error_details); |
||||
|
||||
/** Calls the C arg's callback function. **/ |
||||
void OnCredentialReloadDoneCallback(); |
||||
|
||||
private: |
||||
grpc_tls_credential_reload_arg* c_arg_; |
||||
}; |
||||
|
||||
/** An interface that the application derives and uses to instantiate a
|
||||
* TlsCredentialReloadConfig instance. Refer to the definition of the |
||||
* grpc_tls_credential_reload_config in grpc_tls_credentials_options.h for more |
||||
* details on the expectations of the member functions of the interface. **/ |
||||
struct TlsCredentialReloadInterface { |
||||
virtual ~TlsCredentialReloadInterface() = default; |
||||
/** A callback that invokes the credential reload. **/ |
||||
virtual int Schedule(TlsCredentialReloadArg* arg) = 0; |
||||
/** A callback that cancels a credential reload request. **/ |
||||
virtual void Cancel(TlsCredentialReloadArg* arg) {} |
||||
}; |
||||
|
||||
/** TLS credential reloag config, wraps grpc_tls_credential_reload_config. It is
|
||||
* used for experimental purposes for now and it is subject to change. **/ |
||||
class TlsCredentialReloadConfig { |
||||
public: |
||||
TlsCredentialReloadConfig(std::shared_ptr<TlsCredentialReloadInterface> |
||||
credential_reload_interface); |
||||
~TlsCredentialReloadConfig(); |
||||
|
||||
int Schedule(TlsCredentialReloadArg* arg) const { |
||||
if (credential_reload_interface_ == nullptr) { |
||||
gpr_log(GPR_ERROR, "credential reload interface is nullptr"); |
||||
if (arg != nullptr) { |
||||
arg->set_status(GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL); |
||||
arg->set_error_details( |
||||
"the interface of the credential reload config is nullptr"); |
||||
} |
||||
return 1; |
||||
} |
||||
return credential_reload_interface_->Schedule(arg); |
||||
} |
||||
|
||||
void Cancel(TlsCredentialReloadArg* arg) const { |
||||
if (credential_reload_interface_ == nullptr) { |
||||
gpr_log(GPR_ERROR, "credential reload interface is nullptr"); |
||||
if (arg != nullptr) { |
||||
arg->set_status(GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL); |
||||
arg->set_error_details( |
||||
"the interface of the credential reload config is nullptr"); |
||||
} |
||||
return; |
||||
} |
||||
credential_reload_interface_->Cancel(arg); |
||||
} |
||||
|
||||
/** Returns a C struct for the credential reload config. **/ |
||||
grpc_tls_credential_reload_config* c_config() const { return c_config_; } |
||||
|
||||
private: |
||||
grpc_tls_credential_reload_config* c_config_; |
||||
std::shared_ptr<TlsCredentialReloadInterface> credential_reload_interface_; |
||||
}; |
||||
|
||||
/** TLS server authorization check arguments, wraps
|
||||
* grpc_tls_server_authorization_check_arg. It is used for experimental |
||||
* purposes for now and it is subject to change. |
||||
* |
||||
* The server authorization check arg contains all the info necessary to |
||||
* schedule/cancel a server authorization check request. The callback function |
||||
* must be called after finishing the schedule operation. See the description |
||||
* of the grpc_tls_server_authorization_check_arg struct in grpc_security.h for |
||||
* more details. **/ |
||||
class TlsServerAuthorizationCheckArg { |
||||
public: |
||||
/** TlsServerAuthorizationCheckArg does not take ownership of the C arg passed
|
||||
* to the constructor. One must remember to free any memory allocated to the |
||||
* C arg after using the setter functions below. **/ |
||||
TlsServerAuthorizationCheckArg(grpc_tls_server_authorization_check_arg* arg); |
||||
~TlsServerAuthorizationCheckArg(); |
||||
|
||||
/** Getters for member fields. They return the corresponding fields of the
|
||||
* underlying C arg.**/ |
||||
void* cb_user_data() const; |
||||
int success() const; |
||||
grpc::string target_name() const; |
||||
grpc::string peer_cert() const; |
||||
grpc_status_code status() const; |
||||
grpc::string error_details() const; |
||||
|
||||
/** Setters for member fields. They modify the fields of the underlying C arg.
|
||||
* The setters for target_name, peer_cert, and error_details allocate memory |
||||
* when modifying c_arg_, so one must remember to free c_arg_'s original |
||||
* target_name, peer_cert, or error_details after using the appropriate setter |
||||
* function. |
||||
* **/ |
||||
void set_cb_user_data(void* cb_user_data); |
||||
void set_success(int success); |
||||
void set_target_name(const grpc::string& target_name); |
||||
void set_peer_cert(const grpc::string& peer_cert); |
||||
void set_status(grpc_status_code status); |
||||
void set_error_details(const grpc::string& error_details); |
||||
|
||||
/** Calls the C arg's callback function. **/ |
||||
void OnServerAuthorizationCheckDoneCallback(); |
||||
|
||||
private: |
||||
grpc_tls_server_authorization_check_arg* c_arg_; |
||||
}; |
||||
|
||||
/** An interface that the application derives and uses to instantiate a
|
||||
* TlsServerAuthorizationCheckConfig instance. Refer to the definition of the |
||||
* grpc_tls_server_authorization_check_config in grpc_tls_credentials_options.h |
||||
* for more details on the expectations of the member functions of the |
||||
* interface. |
||||
* **/ |
||||
struct TlsServerAuthorizationCheckInterface { |
||||
virtual ~TlsServerAuthorizationCheckInterface() = default; |
||||
/** A callback that invokes the server authorization check. **/ |
||||
virtual int Schedule(TlsServerAuthorizationCheckArg* arg) = 0; |
||||
/** A callback that cancels a server authorization check request. **/ |
||||
virtual void Cancel(TlsServerAuthorizationCheckArg* arg) {} |
||||
}; |
||||
|
||||
/** TLS server authorization check config, wraps
|
||||
* grps_tls_server_authorization_check_config. It is used for experimental |
||||
* purposes for now and it is subject to change. **/ |
||||
class TlsServerAuthorizationCheckConfig { |
||||
public: |
||||
TlsServerAuthorizationCheckConfig( |
||||
std::shared_ptr<TlsServerAuthorizationCheckInterface> |
||||
server_authorization_check_interface); |
||||
~TlsServerAuthorizationCheckConfig(); |
||||
|
||||
int Schedule(TlsServerAuthorizationCheckArg* arg) const { |
||||
if (server_authorization_check_interface_ == nullptr) { |
||||
gpr_log(GPR_ERROR, "server authorization check interface is nullptr"); |
||||
if (arg != nullptr) { |
||||
arg->set_status(GRPC_STATUS_NOT_FOUND); |
||||
arg->set_error_details( |
||||
"the interface of the server authorization check config is " |
||||
"nullptr"); |
||||
} |
||||
return 1; |
||||
} |
||||
return server_authorization_check_interface_->Schedule(arg); |
||||
} |
||||
|
||||
void Cancel(TlsServerAuthorizationCheckArg* arg) const { |
||||
if (server_authorization_check_interface_ == nullptr) { |
||||
gpr_log(GPR_ERROR, "server authorization check interface is nullptr"); |
||||
if (arg != nullptr) { |
||||
arg->set_status(GRPC_STATUS_NOT_FOUND); |
||||
arg->set_error_details( |
||||
"the interface of the server authorization check config is " |
||||
"nullptr"); |
||||
} |
||||
return; |
||||
} |
||||
server_authorization_check_interface_->Cancel(arg); |
||||
} |
||||
|
||||
/** Returns C struct for the server authorization check config. **/ |
||||
grpc_tls_server_authorization_check_config* c_config() const { |
||||
return c_config_; |
||||
} |
||||
|
||||
private: |
||||
grpc_tls_server_authorization_check_config* c_config_; |
||||
std::shared_ptr<TlsServerAuthorizationCheckInterface> |
||||
server_authorization_check_interface_; |
||||
}; |
||||
|
||||
/** TLS credentials options, wrapper for grpc_tls_credentials_options. It is
|
||||
* used for experimental purposes for now and it is subject to change. See the |
||||
* description of the grpc_tls_credentials_options struct in grpc_security.h for |
||||
* more details. **/ |
||||
class TlsCredentialsOptions { |
||||
public: |
||||
TlsCredentialsOptions( |
||||
grpc_ssl_client_certificate_request_type cert_request_type, |
||||
std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config, |
||||
std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config, |
||||
std::shared_ptr<TlsServerAuthorizationCheckConfig> |
||||
server_authorization_check_config); |
||||
~TlsCredentialsOptions(); |
||||
|
||||
/** Getters for member fields. **/ |
||||
grpc_ssl_client_certificate_request_type cert_request_type() const { |
||||
return cert_request_type_; |
||||
} |
||||
std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config() const { |
||||
return key_materials_config_; |
||||
} |
||||
std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config() const { |
||||
return credential_reload_config_; |
||||
} |
||||
std::shared_ptr<TlsServerAuthorizationCheckConfig> |
||||
server_authorization_check_config() const { |
||||
return server_authorization_check_config_; |
||||
} |
||||
grpc_tls_credentials_options* c_credentials_options() const { |
||||
return c_credentials_options_; |
||||
} |
||||
|
||||
private: |
||||
/** The cert_request_type_ flag is only relevant when the
|
||||
* TlsCredentialsOptions are used to instantiate server credentials; the flag |
||||
* goes unused when creating channel credentials, and the user can set it to |
||||
* GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE. **/ |
||||
grpc_ssl_client_certificate_request_type cert_request_type_; |
||||
std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config_; |
||||
std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config_; |
||||
std::shared_ptr<TlsServerAuthorizationCheckConfig> |
||||
server_authorization_check_config_; |
||||
grpc_tls_credentials_options* c_credentials_options_; |
||||
}; |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_impl
|
||||
|
||||
#endif // GRPCPP_SECURITY_TLS_CREDENTIALS_OPTIONS_H
|
@ -0,0 +1,452 @@ |
||||
//
|
||||
// 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h" |
||||
|
||||
#include <errno.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/lib/gpr/env.h" |
||||
#include "src/core/lib/iomgr/load_file.h" |
||||
#include "src/core/lib/slice/slice_internal.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
UniquePtr<XdsBootstrap> XdsBootstrap::ReadFromFile(grpc_error** error) { |
||||
UniquePtr<char> path(gpr_getenv("GRPC_XDS_BOOTSTRAP")); |
||||
if (path == nullptr) { |
||||
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"GRPC_XDS_BOOTSTRAP env var not set"); |
||||
return nullptr; |
||||
} |
||||
grpc_slice contents; |
||||
*error = grpc_load_file(path.get(), /*add_null_terminator=*/true, &contents); |
||||
if (*error != GRPC_ERROR_NONE) return nullptr; |
||||
return MakeUnique<XdsBootstrap>(contents, error); |
||||
} |
||||
|
||||
XdsBootstrap::XdsBootstrap(grpc_slice contents, grpc_error** error) |
||||
: contents_(contents) { |
||||
tree_ = grpc_json_parse_string_with_len( |
||||
reinterpret_cast<char*>(GPR_SLICE_START_PTR(contents_)), |
||||
GPR_SLICE_LENGTH(contents_)); |
||||
if (tree_ == nullptr) { |
||||
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"failed to parse bootstrap file JSON"); |
||||
return; |
||||
} |
||||
if (tree_->type != GRPC_JSON_OBJECT || tree_->key != nullptr) { |
||||
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"malformed JSON in bootstrap file"); |
||||
return; |
||||
} |
||||
InlinedVector<grpc_error*, 1> error_list; |
||||
bool seen_xds_server = false; |
||||
bool seen_node = false; |
||||
for (grpc_json* child = tree_->child; child != nullptr; child = child->next) { |
||||
if (child->key == nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null")); |
||||
} else if (strcmp(child->key, "xds_server") == 0) { |
||||
if (child->type != GRPC_JSON_OBJECT) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"xds_server\" field is not an object")); |
||||
} |
||||
if (seen_xds_server) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"duplicate \"xds_server\" field")); |
||||
} |
||||
seen_xds_server = true; |
||||
grpc_error* parse_error = ParseXdsServer(child); |
||||
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); |
||||
} else if (strcmp(child->key, "node") == 0) { |
||||
if (child->type != GRPC_JSON_OBJECT) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"node\" field is not an object")); |
||||
} |
||||
if (seen_node) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"node\" field")); |
||||
} |
||||
seen_node = true; |
||||
grpc_error* parse_error = ParseNode(child); |
||||
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); |
||||
} |
||||
} |
||||
if (!seen_xds_server) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"xds_server\" field not present")); |
||||
} |
||||
*error = GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing xds bootstrap file", |
||||
&error_list); |
||||
} |
||||
|
||||
XdsBootstrap::~XdsBootstrap() { |
||||
grpc_json_destroy(tree_); |
||||
grpc_slice_unref_internal(contents_); |
||||
} |
||||
|
||||
grpc_error* XdsBootstrap::ParseXdsServer(grpc_json* json) { |
||||
InlinedVector<grpc_error*, 1> error_list; |
||||
server_uri_ = nullptr; |
||||
bool seen_channel_creds = false; |
||||
for (grpc_json* child = json->child; child != nullptr; child = child->next) { |
||||
if (child->key == nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null")); |
||||
} else if (strcmp(child->key, "server_uri") == 0) { |
||||
if (child->type != GRPC_JSON_STRING) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"server_uri\" field is not a string")); |
||||
} |
||||
if (server_uri_ != nullptr) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"duplicate \"server_uri\" field")); |
||||
} |
||||
server_uri_ = child->value; |
||||
} else if (strcmp(child->key, "channel_creds") == 0) { |
||||
if (child->type != GRPC_JSON_ARRAY) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"channel_creds\" field is not a array")); |
||||
} |
||||
if (seen_channel_creds) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"duplicate \"channel_creds\" field")); |
||||
} |
||||
seen_channel_creds = true; |
||||
grpc_error* parse_error = ParseChannelCredsArray(child); |
||||
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); |
||||
} |
||||
} |
||||
if (server_uri_ == nullptr) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"server_uri\" field not present")); |
||||
} |
||||
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"xds_server\" object", |
||||
&error_list); |
||||
} |
||||
|
||||
grpc_error* XdsBootstrap::ParseChannelCredsArray(grpc_json* json) { |
||||
InlinedVector<grpc_error*, 1> error_list; |
||||
size_t idx = 0; |
||||
for (grpc_json *child = json->child; child != nullptr; |
||||
child = child->next, ++idx) { |
||||
if (child->key != nullptr) { |
||||
char* msg; |
||||
gpr_asprintf(&msg, "array element %" PRIuPTR " key is not null", idx); |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg)); |
||||
} |
||||
if (child->type != GRPC_JSON_OBJECT) { |
||||
char* msg; |
||||
gpr_asprintf(&msg, "array element %" PRIuPTR " is not an object", idx); |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg)); |
||||
} else { |
||||
grpc_error* parse_error = ParseChannelCreds(child, idx); |
||||
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); |
||||
} |
||||
} |
||||
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"channel_creds\" array", |
||||
&error_list); |
||||
} |
||||
|
||||
grpc_error* XdsBootstrap::ParseChannelCreds(grpc_json* json, size_t idx) { |
||||
InlinedVector<grpc_error*, 1> error_list; |
||||
ChannelCreds channel_creds; |
||||
for (grpc_json* child = json->child; child != nullptr; child = child->next) { |
||||
if (child->key == nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null")); |
||||
} else if (strcmp(child->key, "type") == 0) { |
||||
if (child->type != GRPC_JSON_STRING) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"type\" field is not a string")); |
||||
} |
||||
if (channel_creds.type != nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"type\" field")); |
||||
} |
||||
channel_creds.type = child->value; |
||||
} else if (strcmp(child->key, "config") == 0) { |
||||
if (child->type != GRPC_JSON_OBJECT) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"config\" field is not an object")); |
||||
} |
||||
if (channel_creds.config != nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"config\" field")); |
||||
} |
||||
channel_creds.config = child; |
||||
} |
||||
} |
||||
if (channel_creds.type != nullptr) channel_creds_.push_back(channel_creds); |
||||
// Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
|
||||
// string is not static in this case.
|
||||
if (error_list.empty()) return GRPC_ERROR_NONE; |
||||
char* msg; |
||||
gpr_asprintf(&msg, "errors parsing index %" PRIuPTR, idx); |
||||
grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); |
||||
gpr_free(msg); |
||||
for (size_t i = 0; i < error_list.size(); ++i) { |
||||
error = grpc_error_add_child(error, error_list[i]); |
||||
GRPC_ERROR_UNREF(error_list[i]); |
||||
} |
||||
return error; |
||||
} |
||||
|
||||
grpc_error* XdsBootstrap::ParseNode(grpc_json* json) { |
||||
InlinedVector<grpc_error*, 1> error_list; |
||||
node_ = MakeUnique<Node>(); |
||||
bool seen_metadata = false; |
||||
bool seen_locality = false; |
||||
for (grpc_json* child = json->child; child != nullptr; child = child->next) { |
||||
if (child->key == nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null")); |
||||
} else if (strcmp(child->key, "id") == 0) { |
||||
if (child->type != GRPC_JSON_STRING) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"id\" field is not a string")); |
||||
} |
||||
if (node_->id != nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"id\" field")); |
||||
} |
||||
node_->id = child->value; |
||||
} else if (strcmp(child->key, "cluster") == 0) { |
||||
if (child->type != GRPC_JSON_STRING) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"cluster\" field is not a string")); |
||||
} |
||||
if (node_->cluster != nullptr) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"duplicate \"cluster\" field")); |
||||
} |
||||
node_->cluster = child->value; |
||||
} else if (strcmp(child->key, "locality") == 0) { |
||||
if (child->type != GRPC_JSON_OBJECT) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"locality\" field is not an object")); |
||||
} |
||||
if (seen_locality) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"duplicate \"locality\" field")); |
||||
} |
||||
seen_locality = true; |
||||
grpc_error* parse_error = ParseLocality(child); |
||||
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); |
||||
} else if (strcmp(child->key, "metadata") == 0) { |
||||
if (child->type != GRPC_JSON_OBJECT) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"metadata\" field is not an object")); |
||||
} |
||||
if (seen_metadata) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"duplicate \"metadata\" field")); |
||||
} |
||||
seen_metadata = true; |
||||
InlinedVector<grpc_error*, 1> parse_errors = |
||||
ParseMetadataStruct(child, &node_->metadata); |
||||
if (!parse_errors.empty()) { |
||||
grpc_error* parse_error = GRPC_ERROR_CREATE_FROM_VECTOR( |
||||
"errors parsing \"metadata\" object", &parse_errors); |
||||
error_list.push_back(parse_error); |
||||
} |
||||
} |
||||
} |
||||
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"node\" object", |
||||
&error_list); |
||||
} |
||||
|
||||
grpc_error* XdsBootstrap::ParseLocality(grpc_json* json) { |
||||
InlinedVector<grpc_error*, 1> error_list; |
||||
node_->locality_region = nullptr; |
||||
node_->locality_zone = nullptr; |
||||
node_->locality_subzone = nullptr; |
||||
for (grpc_json* child = json->child; child != nullptr; child = child->next) { |
||||
if (child->key == nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null")); |
||||
} else if (strcmp(child->key, "region") == 0) { |
||||
if (child->type != GRPC_JSON_STRING) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"region\" field is not a string")); |
||||
} |
||||
if (node_->locality_region != nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"region\" field")); |
||||
} |
||||
node_->locality_region = child->value; |
||||
} else if (strcmp(child->key, "zone") == 0) { |
||||
if (child->type != GRPC_JSON_STRING) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"zone\" field is not a string")); |
||||
} |
||||
if (node_->locality_zone != nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"zone\" field")); |
||||
} |
||||
node_->locality_zone = child->value; |
||||
} else if (strcmp(child->key, "subzone") == 0) { |
||||
if (child->type != GRPC_JSON_STRING) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"\"subzone\" field is not a string")); |
||||
} |
||||
if (node_->locality_subzone != nullptr) { |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||
"duplicate \"subzone\" field")); |
||||
} |
||||
node_->locality_subzone = child->value; |
||||
} |
||||
} |
||||
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"locality\" object", |
||||
&error_list); |
||||
} |
||||
|
||||
InlinedVector<grpc_error*, 1> XdsBootstrap::ParseMetadataStruct( |
||||
grpc_json* json, |
||||
Map<const char*, XdsBootstrap::MetadataValue, StringLess>* result) { |
||||
InlinedVector<grpc_error*, 1> error_list; |
||||
for (grpc_json* child = json->child; child != nullptr; child = child->next) { |
||||
if (child->key == nullptr) { |
||||
error_list.push_back( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null")); |
||||
continue; |
||||
} |
||||
if (result->find(child->key) != result->end()) { |
||||
char* msg; |
||||
gpr_asprintf(&msg, "duplicate metadata key \"%s\"", child->key); |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg)); |
||||
gpr_free(msg); |
||||
} |
||||
MetadataValue& value = (*result)[child->key]; |
||||
grpc_error* parse_error = ParseMetadataValue(child, 0, &value); |
||||
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); |
||||
} |
||||
return error_list; |
||||
} |
||||
|
||||
InlinedVector<grpc_error*, 1> XdsBootstrap::ParseMetadataList( |
||||
grpc_json* json, std::vector<MetadataValue>* result) { |
||||
InlinedVector<grpc_error*, 1> error_list; |
||||
size_t idx = 0; |
||||
for (grpc_json *child = json->child; child != nullptr; |
||||
child = child->next, ++idx) { |
||||
if (child->key != nullptr) { |
||||
char* msg; |
||||
gpr_asprintf(&msg, "JSON key is non-null for index %" PRIuPTR, idx); |
||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg)); |
||||
gpr_free(msg); |
||||
} |
||||
result->emplace_back(); |
||||
grpc_error* parse_error = ParseMetadataValue(child, idx, &result->back()); |
||||
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); |
||||
} |
||||
return error_list; |
||||
} |
||||
|
||||
grpc_error* XdsBootstrap::ParseMetadataValue(grpc_json* json, size_t idx, |
||||
MetadataValue* result) { |
||||
grpc_error* error = GRPC_ERROR_NONE; |
||||
auto context_func = [json, idx]() { |
||||
char* context; |
||||
if (json->key != nullptr) { |
||||
gpr_asprintf(&context, "key \"%s\"", json->key); |
||||
} else { |
||||
gpr_asprintf(&context, "index %" PRIuPTR, idx); |
||||
} |
||||
return context; |
||||
}; |
||||
switch (json->type) { |
||||
case GRPC_JSON_STRING: |
||||
result->type = MetadataValue::Type::STRING; |
||||
result->string_value = json->value; |
||||
break; |
||||
case GRPC_JSON_NUMBER: |
||||
result->type = MetadataValue::Type::DOUBLE; |
||||
errno = 0; // To distinguish error.
|
||||
result->double_value = strtod(json->value, nullptr); |
||||
if (errno != 0) { |
||||
char* context = context_func(); |
||||
char* msg; |
||||
gpr_asprintf(&msg, "error parsing numeric value for %s: \"%s\"", |
||||
context, json->value); |
||||
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); |
||||
gpr_free(context); |
||||
gpr_free(msg); |
||||
} |
||||
break; |
||||
case GRPC_JSON_TRUE: |
||||
result->type = MetadataValue::Type::BOOL; |
||||
result->bool_value = true; |
||||
break; |
||||
case GRPC_JSON_FALSE: |
||||
result->type = MetadataValue::Type::BOOL; |
||||
result->bool_value = false; |
||||
break; |
||||
case GRPC_JSON_NULL: |
||||
result->type = MetadataValue::Type::MD_NULL; |
||||
break; |
||||
case GRPC_JSON_ARRAY: { |
||||
result->type = MetadataValue::Type::LIST; |
||||
InlinedVector<grpc_error*, 1> error_list = |
||||
ParseMetadataList(json, &result->list_value); |
||||
if (!error_list.empty()) { |
||||
// Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
|
||||
// string is not static in this case.
|
||||
char* context = context_func(); |
||||
char* msg; |
||||
gpr_asprintf(&msg, "errors parsing struct for %s", context); |
||||
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); |
||||
gpr_free(context); |
||||
gpr_free(msg); |
||||
for (size_t i = 0; i < error_list.size(); ++i) { |
||||
error = grpc_error_add_child(error, error_list[i]); |
||||
GRPC_ERROR_UNREF(error_list[i]); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
case GRPC_JSON_OBJECT: { |
||||
result->type = MetadataValue::Type::STRUCT; |
||||
InlinedVector<grpc_error*, 1> error_list = |
||||
ParseMetadataStruct(json, &result->struct_value); |
||||
if (!error_list.empty()) { |
||||
// Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
|
||||
// string is not static in this case.
|
||||
char* context = context_func(); |
||||
char* msg; |
||||
gpr_asprintf(&msg, "errors parsing struct for %s", context); |
||||
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); |
||||
gpr_free(context); |
||||
gpr_free(msg); |
||||
for (size_t i = 0; i < error_list.size(); ++i) { |
||||
error = grpc_error_add_child(error, error_list[i]); |
||||
GRPC_ERROR_UNREF(error_list[i]); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
default: |
||||
break; |
||||
} |
||||
return error; |
||||
} |
||||
|
||||
} // namespace grpc_core
|
@ -0,0 +1,99 @@ |
||||
//
|
||||
// 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 GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_XDS_XDS_BOOTSTRAP_H |
||||
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_XDS_XDS_BOOTSTRAP_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <vector> |
||||
|
||||
#include <grpc/impl/codegen/slice.h> |
||||
|
||||
#include "src/core/lib/gprpp/inlined_vector.h" |
||||
#include "src/core/lib/gprpp/map.h" |
||||
#include "src/core/lib/gprpp/memory.h" |
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/json/json.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
class XdsBootstrap { |
||||
public: |
||||
struct MetadataValue { |
||||
enum class Type { MD_NULL, DOUBLE, STRING, BOOL, STRUCT, LIST }; |
||||
Type type = Type::MD_NULL; |
||||
// TODO(roth): Once we can use C++17, these can be in a std::variant.
|
||||
double double_value; |
||||
const char* string_value; |
||||
bool bool_value; |
||||
Map<const char*, MetadataValue, StringLess> struct_value; |
||||
std::vector<MetadataValue> list_value; |
||||
}; |
||||
|
||||
struct Node { |
||||
const char* id = nullptr; |
||||
const char* cluster = nullptr; |
||||
const char* locality_region = nullptr; |
||||
const char* locality_zone = nullptr; |
||||
const char* locality_subzone = nullptr; |
||||
Map<const char*, MetadataValue, StringLess> metadata; |
||||
}; |
||||
|
||||
struct ChannelCreds { |
||||
const char* type = nullptr; |
||||
grpc_json* config = nullptr; |
||||
}; |
||||
|
||||
// If *error is not GRPC_ERROR_NONE after returning, then there was an
|
||||
// error reading the file.
|
||||
static UniquePtr<XdsBootstrap> ReadFromFile(grpc_error** error); |
||||
|
||||
// Do not instantiate directly -- use ReadFromFile() above instead.
|
||||
XdsBootstrap(grpc_slice contents, grpc_error** error); |
||||
~XdsBootstrap(); |
||||
|
||||
const char* server_uri() const { return server_uri_; } |
||||
const InlinedVector<ChannelCreds, 1>& channel_creds() const { |
||||
return channel_creds_; |
||||
} |
||||
const Node* node() const { return node_.get(); } |
||||
|
||||
private: |
||||
grpc_error* ParseXdsServer(grpc_json* json); |
||||
grpc_error* ParseChannelCredsArray(grpc_json* json); |
||||
grpc_error* ParseChannelCreds(grpc_json* json, size_t idx); |
||||
grpc_error* ParseNode(grpc_json* json); |
||||
grpc_error* ParseLocality(grpc_json* json); |
||||
|
||||
InlinedVector<grpc_error*, 1> ParseMetadataStruct( |
||||
grpc_json* json, Map<const char*, MetadataValue, StringLess>* result); |
||||
InlinedVector<grpc_error*, 1> ParseMetadataList( |
||||
grpc_json* json, std::vector<MetadataValue>* result); |
||||
grpc_error* ParseMetadataValue(grpc_json* json, size_t idx, |
||||
MetadataValue* result); |
||||
|
||||
grpc_slice contents_; |
||||
grpc_json* tree_ = nullptr; |
||||
|
||||
const char* server_uri_ = nullptr; |
||||
InlinedVector<ChannelCreds, 1> channel_creds_; |
||||
UniquePtr<Node> node_; |
||||
}; |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_XDS_XDS_BOOTSTRAP_H */ |
@ -0,0 +1,282 @@ |
||||
/*
|
||||
* |
||||
* 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 <grpcpp/security/tls_credentials_options.h> |
||||
#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
|
||||
#include "src/cpp/common/tls_credentials_options_util.h" |
||||
|
||||
namespace grpc_impl { |
||||
namespace experimental { |
||||
|
||||
/** TLS key materials config API implementation **/ |
||||
void TlsKeyMaterialsConfig::set_pem_root_certs(grpc::string pem_root_certs) { |
||||
pem_root_certs_ = std::move(pem_root_certs); |
||||
} |
||||
|
||||
void TlsKeyMaterialsConfig::add_pem_key_cert_pair( |
||||
const PemKeyCertPair& pem_key_cert_pair) { |
||||
pem_key_cert_pair_list_.push_back(pem_key_cert_pair); |
||||
} |
||||
|
||||
void TlsKeyMaterialsConfig::set_key_materials( |
||||
grpc::string pem_root_certs, |
||||
std::vector<PemKeyCertPair> pem_key_cert_pair_list) { |
||||
pem_key_cert_pair_list_ = std::move(pem_key_cert_pair_list); |
||||
pem_root_certs_ = std::move(pem_root_certs); |
||||
} |
||||
|
||||
/** TLS credential reload arg API implementation **/ |
||||
TlsCredentialReloadArg::TlsCredentialReloadArg( |
||||
grpc_tls_credential_reload_arg* arg) |
||||
: c_arg_(arg) { |
||||
if (c_arg_ != nullptr && c_arg_->context != nullptr) { |
||||
gpr_log(GPR_ERROR, "c_arg context has already been set"); |
||||
} |
||||
c_arg_->context = static_cast<void*>(this); |
||||
c_arg_->destroy_context = &TlsCredentialReloadArgDestroyContext; |
||||
} |
||||
|
||||
TlsCredentialReloadArg::~TlsCredentialReloadArg() {} |
||||
|
||||
void* TlsCredentialReloadArg::cb_user_data() const { |
||||
return c_arg_->cb_user_data; |
||||
} |
||||
|
||||
bool TlsCredentialReloadArg::is_pem_key_cert_pair_list_empty() const { |
||||
return c_arg_->key_materials_config->pem_key_cert_pair_list().empty(); |
||||
} |
||||
|
||||
grpc_ssl_certificate_config_reload_status TlsCredentialReloadArg::status() |
||||
const { |
||||
return c_arg_->status; |
||||
} |
||||
|
||||
grpc::string TlsCredentialReloadArg::error_details() const { |
||||
grpc::string cpp_error_details(c_arg_->error_details); |
||||
return cpp_error_details; |
||||
} |
||||
|
||||
void TlsCredentialReloadArg::set_cb_user_data(void* cb_user_data) { |
||||
c_arg_->cb_user_data = cb_user_data; |
||||
} |
||||
|
||||
void TlsCredentialReloadArg::set_pem_root_certs( |
||||
const grpc::string& pem_root_certs) { |
||||
::grpc_core::UniquePtr<char> c_pem_root_certs( |
||||
gpr_strdup(pem_root_certs.c_str())); |
||||
c_arg_->key_materials_config->set_pem_root_certs(std::move(c_pem_root_certs)); |
||||
} |
||||
|
||||
void TlsCredentialReloadArg::add_pem_key_cert_pair( |
||||
TlsKeyMaterialsConfig::PemKeyCertPair pem_key_cert_pair) { |
||||
grpc_ssl_pem_key_cert_pair* ssl_pair = |
||||
(grpc_ssl_pem_key_cert_pair*)gpr_malloc( |
||||
sizeof(grpc_ssl_pem_key_cert_pair)); |
||||
ssl_pair->private_key = gpr_strdup(pem_key_cert_pair.private_key.c_str()); |
||||
ssl_pair->cert_chain = gpr_strdup(pem_key_cert_pair.cert_chain.c_str()); |
||||
::grpc_core::PemKeyCertPair c_pem_key_cert_pair = |
||||
::grpc_core::PemKeyCertPair(ssl_pair); |
||||
c_arg_->key_materials_config->add_pem_key_cert_pair( |
||||
std::move(c_pem_key_cert_pair)); |
||||
} |
||||
|
||||
void TlsCredentialReloadArg::set_key_materials_config( |
||||
const std::shared_ptr<TlsKeyMaterialsConfig>& key_materials_config) { |
||||
if (key_materials_config == nullptr) { |
||||
c_arg_->key_materials_config = nullptr; |
||||
return; |
||||
} |
||||
::grpc_core::InlinedVector<::grpc_core::PemKeyCertPair, 1> |
||||
c_pem_key_cert_pair_list; |
||||
for (auto key_cert_pair = |
||||
key_materials_config->pem_key_cert_pair_list().begin(); |
||||
key_cert_pair != key_materials_config->pem_key_cert_pair_list().end(); |
||||
key_cert_pair++) { |
||||
grpc_ssl_pem_key_cert_pair* ssl_pair = |
||||
(grpc_ssl_pem_key_cert_pair*)gpr_malloc( |
||||
sizeof(grpc_ssl_pem_key_cert_pair)); |
||||
ssl_pair->private_key = gpr_strdup(key_cert_pair->private_key.c_str()); |
||||
ssl_pair->cert_chain = gpr_strdup(key_cert_pair->cert_chain.c_str()); |
||||
::grpc_core::PemKeyCertPair c_pem_key_cert_pair = |
||||
::grpc_core::PemKeyCertPair(ssl_pair); |
||||
c_pem_key_cert_pair_list.emplace_back(std::move(c_pem_key_cert_pair)); |
||||
} |
||||
::grpc_core::UniquePtr<char> c_pem_root_certs( |
||||
gpr_strdup(key_materials_config->pem_root_certs().c_str())); |
||||
if (c_arg_->key_materials_config == nullptr) { |
||||
c_arg_->key_materials_config = grpc_tls_key_materials_config_create(); |
||||
} |
||||
c_arg_->key_materials_config->set_key_materials( |
||||
std::move(c_pem_root_certs), std::move(c_pem_key_cert_pair_list)); |
||||
c_arg_->key_materials_config->set_version(key_materials_config->version()); |
||||
} |
||||
|
||||
void TlsCredentialReloadArg::set_status( |
||||
grpc_ssl_certificate_config_reload_status status) { |
||||
c_arg_->status = status; |
||||
} |
||||
|
||||
void TlsCredentialReloadArg::set_error_details( |
||||
const grpc::string& error_details) { |
||||
c_arg_->error_details = gpr_strdup(error_details.c_str()); |
||||
} |
||||
|
||||
void TlsCredentialReloadArg::OnCredentialReloadDoneCallback() { |
||||
if (c_arg_->cb == nullptr) { |
||||
gpr_log(GPR_ERROR, "credential reload arg callback API is nullptr"); |
||||
return; |
||||
} |
||||
c_arg_->cb(c_arg_); |
||||
} |
||||
|
||||
/** gRPC TLS credential reload config API implementation **/ |
||||
TlsCredentialReloadConfig::TlsCredentialReloadConfig( |
||||
std::shared_ptr<TlsCredentialReloadInterface> credential_reload_interface) |
||||
: credential_reload_interface_(std::move(credential_reload_interface)) { |
||||
c_config_ = grpc_tls_credential_reload_config_create( |
||||
nullptr, &TlsCredentialReloadConfigCSchedule, |
||||
&TlsCredentialReloadConfigCCancel, nullptr); |
||||
c_config_->set_context(static_cast<void*>(this)); |
||||
} |
||||
|
||||
TlsCredentialReloadConfig::~TlsCredentialReloadConfig() {} |
||||
|
||||
/** gRPC TLS server authorization check arg API implementation **/ |
||||
TlsServerAuthorizationCheckArg::TlsServerAuthorizationCheckArg( |
||||
grpc_tls_server_authorization_check_arg* arg) |
||||
: c_arg_(arg) { |
||||
if (c_arg_ != nullptr && c_arg_->context != nullptr) { |
||||
gpr_log(GPR_ERROR, "c_arg context has already been set"); |
||||
} |
||||
c_arg_->context = static_cast<void*>(this); |
||||
c_arg_->destroy_context = &TlsServerAuthorizationCheckArgDestroyContext; |
||||
} |
||||
|
||||
TlsServerAuthorizationCheckArg::~TlsServerAuthorizationCheckArg() {} |
||||
|
||||
void* TlsServerAuthorizationCheckArg::cb_user_data() const { |
||||
return c_arg_->cb_user_data; |
||||
} |
||||
|
||||
int TlsServerAuthorizationCheckArg::success() const { return c_arg_->success; } |
||||
|
||||
grpc::string TlsServerAuthorizationCheckArg::target_name() const { |
||||
grpc::string cpp_target_name(c_arg_->target_name); |
||||
return cpp_target_name; |
||||
} |
||||
|
||||
grpc::string TlsServerAuthorizationCheckArg::peer_cert() const { |
||||
grpc::string cpp_peer_cert(c_arg_->peer_cert); |
||||
return cpp_peer_cert; |
||||
} |
||||
|
||||
grpc_status_code TlsServerAuthorizationCheckArg::status() const { |
||||
return c_arg_->status; |
||||
} |
||||
|
||||
grpc::string TlsServerAuthorizationCheckArg::error_details() const { |
||||
grpc::string cpp_error_details(c_arg_->error_details); |
||||
return cpp_error_details; |
||||
} |
||||
|
||||
void TlsServerAuthorizationCheckArg::set_cb_user_data(void* cb_user_data) { |
||||
c_arg_->cb_user_data = cb_user_data; |
||||
} |
||||
|
||||
void TlsServerAuthorizationCheckArg::set_success(int success) { |
||||
c_arg_->success = success; |
||||
} |
||||
|
||||
void TlsServerAuthorizationCheckArg::set_target_name( |
||||
const grpc::string& target_name) { |
||||
c_arg_->target_name = gpr_strdup(target_name.c_str()); |
||||
} |
||||
|
||||
void TlsServerAuthorizationCheckArg::set_peer_cert( |
||||
const grpc::string& peer_cert) { |
||||
c_arg_->peer_cert = gpr_strdup(peer_cert.c_str()); |
||||
} |
||||
|
||||
void TlsServerAuthorizationCheckArg::set_status(grpc_status_code status) { |
||||
c_arg_->status = status; |
||||
} |
||||
|
||||
void TlsServerAuthorizationCheckArg::set_error_details( |
||||
const grpc::string& error_details) { |
||||
c_arg_->error_details = gpr_strdup(error_details.c_str()); |
||||
} |
||||
|
||||
void TlsServerAuthorizationCheckArg::OnServerAuthorizationCheckDoneCallback() { |
||||
if (c_arg_->cb == nullptr) { |
||||
gpr_log(GPR_ERROR, "server authorizaton check arg callback API is nullptr"); |
||||
return; |
||||
} |
||||
c_arg_->cb(c_arg_); |
||||
} |
||||
|
||||
/** gRPC TLS server authorization check config API implementation. **/ |
||||
TlsServerAuthorizationCheckConfig::TlsServerAuthorizationCheckConfig( |
||||
std::shared_ptr<TlsServerAuthorizationCheckInterface> |
||||
server_authorization_check_interface) |
||||
: server_authorization_check_interface_( |
||||
std::move(server_authorization_check_interface)) { |
||||
c_config_ = grpc_tls_server_authorization_check_config_create( |
||||
nullptr, &TlsServerAuthorizationCheckConfigCSchedule, |
||||
&TlsServerAuthorizationCheckConfigCCancel, nullptr); |
||||
c_config_->set_context(static_cast<void*>(this)); |
||||
} |
||||
|
||||
TlsServerAuthorizationCheckConfig::~TlsServerAuthorizationCheckConfig() {} |
||||
|
||||
/** gRPC TLS credential options API implementation **/ |
||||
TlsCredentialsOptions::TlsCredentialsOptions( |
||||
grpc_ssl_client_certificate_request_type cert_request_type, |
||||
std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config, |
||||
std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config, |
||||
std::shared_ptr<TlsServerAuthorizationCheckConfig> |
||||
server_authorization_check_config) |
||||
: cert_request_type_(cert_request_type), |
||||
key_materials_config_(std::move(key_materials_config)), |
||||
credential_reload_config_(std::move(credential_reload_config)), |
||||
server_authorization_check_config_( |
||||
std::move(server_authorization_check_config)) { |
||||
c_credentials_options_ = grpc_tls_credentials_options_create(); |
||||
grpc_tls_credentials_options_set_cert_request_type(c_credentials_options_, |
||||
cert_request_type_); |
||||
if (key_materials_config_ != nullptr) { |
||||
grpc_tls_credentials_options_set_key_materials_config( |
||||
c_credentials_options_, |
||||
ConvertToCKeyMaterialsConfig(key_materials_config_)); |
||||
} |
||||
if (credential_reload_config_ != nullptr) { |
||||
grpc_tls_credentials_options_set_credential_reload_config( |
||||
c_credentials_options_, credential_reload_config_->c_config()); |
||||
} |
||||
if (server_authorization_check_config_ != nullptr) { |
||||
grpc_tls_credentials_options_set_server_authorization_check_config( |
||||
c_credentials_options_, server_authorization_check_config_->c_config()); |
||||
} |
||||
} |
||||
|
||||
TlsCredentialsOptions::~TlsCredentialsOptions() {} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_impl
|
@ -0,0 +1,150 @@ |
||||
/*
|
||||
* |
||||
* 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 "src/cpp/common/tls_credentials_options_util.h" |
||||
#include <grpcpp/security/tls_credentials_options.h> |
||||
|
||||
namespace grpc_impl { |
||||
namespace experimental { |
||||
|
||||
/** Converts the Cpp key materials to C key materials; this allocates memory for
|
||||
* the C key materials. Note that the user must free |
||||
* the underlying pointer to private key and cert chain duplicates; they are not |
||||
* freed when the UniquePtr<char> member variables of PemKeyCertPair are unused. |
||||
* Similarly, the user must free the underlying pointer to c_pem_root_certs. **/ |
||||
grpc_tls_key_materials_config* ConvertToCKeyMaterialsConfig( |
||||
const std::shared_ptr<TlsKeyMaterialsConfig>& config) { |
||||
if (config == nullptr) { |
||||
return nullptr; |
||||
} |
||||
grpc_tls_key_materials_config* c_config = |
||||
grpc_tls_key_materials_config_create(); |
||||
::grpc_core::InlinedVector<::grpc_core::PemKeyCertPair, 1> |
||||
c_pem_key_cert_pair_list; |
||||
for (auto key_cert_pair = config->pem_key_cert_pair_list().begin(); |
||||
key_cert_pair != config->pem_key_cert_pair_list().end(); |
||||
key_cert_pair++) { |
||||
grpc_ssl_pem_key_cert_pair* ssl_pair = |
||||
(grpc_ssl_pem_key_cert_pair*)gpr_malloc( |
||||
sizeof(grpc_ssl_pem_key_cert_pair)); |
||||
ssl_pair->private_key = gpr_strdup(key_cert_pair->private_key.c_str()); |
||||
ssl_pair->cert_chain = gpr_strdup(key_cert_pair->cert_chain.c_str()); |
||||
::grpc_core::PemKeyCertPair c_pem_key_cert_pair = |
||||
::grpc_core::PemKeyCertPair(ssl_pair); |
||||
c_pem_key_cert_pair_list.push_back(::std::move(c_pem_key_cert_pair)); |
||||
} |
||||
::grpc_core::UniquePtr<char> c_pem_root_certs( |
||||
gpr_strdup(config->pem_root_certs().c_str())); |
||||
c_config->set_key_materials(std::move(c_pem_root_certs), |
||||
std::move(c_pem_key_cert_pair_list)); |
||||
c_config->set_version(config->version()); |
||||
return c_config; |
||||
} |
||||
|
||||
/** The C schedule and cancel functions for the credential reload config.
|
||||
* They populate a C credential reload arg with the result of a C++ credential |
||||
* reload schedule/cancel API. **/ |
||||
int TlsCredentialReloadConfigCSchedule(void* config_user_data, |
||||
grpc_tls_credential_reload_arg* arg) { |
||||
if (arg == nullptr || arg->config == nullptr || |
||||
arg->config->context() == nullptr) { |
||||
gpr_log(GPR_ERROR, "credential reload arg was not properly initialized"); |
||||
return 1; |
||||
} |
||||
TlsCredentialReloadConfig* cpp_config = |
||||
static_cast<TlsCredentialReloadConfig*>(arg->config->context()); |
||||
TlsCredentialReloadArg* cpp_arg = new TlsCredentialReloadArg(arg); |
||||
int schedule_result = cpp_config->Schedule(cpp_arg); |
||||
return schedule_result; |
||||
} |
||||
|
||||
void TlsCredentialReloadConfigCCancel(void* config_user_data, |
||||
grpc_tls_credential_reload_arg* arg) { |
||||
if (arg == nullptr || arg->config == nullptr || |
||||
arg->config->context() == nullptr) { |
||||
gpr_log(GPR_ERROR, "credential reload arg was not properly initialized"); |
||||
return; |
||||
} |
||||
if (arg->context == nullptr) { |
||||
gpr_log(GPR_ERROR, "credential reload arg schedule has already completed"); |
||||
return; |
||||
} |
||||
TlsCredentialReloadConfig* cpp_config = |
||||
static_cast<TlsCredentialReloadConfig*>(arg->config->context()); |
||||
TlsCredentialReloadArg* cpp_arg = |
||||
static_cast<TlsCredentialReloadArg*>(arg->context); |
||||
cpp_config->Cancel(cpp_arg); |
||||
} |
||||
|
||||
void TlsCredentialReloadArgDestroyContext(void* context) { |
||||
if (context != nullptr) { |
||||
TlsCredentialReloadArg* cpp_arg = |
||||
static_cast<TlsCredentialReloadArg*>(context); |
||||
delete cpp_arg; |
||||
} |
||||
} |
||||
|
||||
/** The C schedule and cancel functions for the server authorization check
|
||||
* config. They populate a C server authorization check arg with the result |
||||
* of a C++ server authorization check schedule/cancel API. **/ |
||||
int TlsServerAuthorizationCheckConfigCSchedule( |
||||
void* config_user_data, grpc_tls_server_authorization_check_arg* arg) { |
||||
if (arg == nullptr || arg->config == nullptr || |
||||
arg->config->context() == nullptr) { |
||||
gpr_log(GPR_ERROR, |
||||
"server authorization check arg was not properly initialized"); |
||||
return 1; |
||||
} |
||||
TlsServerAuthorizationCheckConfig* cpp_config = |
||||
static_cast<TlsServerAuthorizationCheckConfig*>(arg->config->context()); |
||||
TlsServerAuthorizationCheckArg* cpp_arg = |
||||
new TlsServerAuthorizationCheckArg(arg); |
||||
int schedule_result = cpp_config->Schedule(cpp_arg); |
||||
return schedule_result; |
||||
} |
||||
|
||||
void TlsServerAuthorizationCheckConfigCCancel( |
||||
void* config_user_data, grpc_tls_server_authorization_check_arg* arg) { |
||||
if (arg == nullptr || arg->config == nullptr || |
||||
arg->config->context() == nullptr) { |
||||
gpr_log(GPR_ERROR, |
||||
"server authorization check arg was not properly initialized"); |
||||
return; |
||||
} |
||||
if (arg->context == nullptr) { |
||||
gpr_log(GPR_ERROR, |
||||
"server authorization check arg schedule has already completed"); |
||||
return; |
||||
} |
||||
TlsServerAuthorizationCheckConfig* cpp_config = |
||||
static_cast<TlsServerAuthorizationCheckConfig*>(arg->config->context()); |
||||
TlsServerAuthorizationCheckArg* cpp_arg = |
||||
static_cast<TlsServerAuthorizationCheckArg*>(arg->context); |
||||
cpp_config->Cancel(cpp_arg); |
||||
} |
||||
|
||||
void TlsServerAuthorizationCheckArgDestroyContext(void* context) { |
||||
if (context != nullptr) { |
||||
TlsServerAuthorizationCheckArg* cpp_arg = |
||||
static_cast<TlsServerAuthorizationCheckArg*>(context); |
||||
delete cpp_arg; |
||||
} |
||||
} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_impl
|
@ -0,0 +1,58 @@ |
||||
/*
|
||||
* |
||||
* 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 GRPC_INTERNAL_CPP_COMMON_TLS_CREDENTIALS_OPTIONS_UTIL_H |
||||
#define GRPC_INTERNAL_CPP_COMMON_TLS_CREDENTIALS_OPTIONS_UTIL_H |
||||
|
||||
#include <grpc/grpc_security.h> |
||||
#include <grpcpp/security/tls_credentials_options.h> |
||||
|
||||
#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" |
||||
|
||||
namespace grpc_impl { |
||||
namespace experimental { |
||||
|
||||
/** The following function is exposed for testing purposes. **/ |
||||
grpc_tls_key_materials_config* ConvertToCKeyMaterialsConfig( |
||||
const std::shared_ptr<TlsKeyMaterialsConfig>& config); |
||||
|
||||
/** The following 4 functions convert the user-provided schedule or cancel
|
||||
* functions into C style schedule or cancel functions. These are internal |
||||
* functions, not meant to be accessed by the user. **/ |
||||
int TlsCredentialReloadConfigCSchedule(void* config_user_data, |
||||
grpc_tls_credential_reload_arg* arg); |
||||
|
||||
void TlsCredentialReloadConfigCCancel(void* config_user_data, |
||||
grpc_tls_credential_reload_arg* arg); |
||||
|
||||
int TlsServerAuthorizationCheckConfigCSchedule( |
||||
void* config_user_data, grpc_tls_server_authorization_check_arg* arg); |
||||
|
||||
void TlsServerAuthorizationCheckConfigCCancel( |
||||
void* config_user_data, grpc_tls_server_authorization_check_arg* arg); |
||||
|
||||
/** The following 2 functions cleanup data created in the above C schedule
|
||||
* functions. **/ |
||||
void TlsCredentialReloadArgDestroyContext(void* context); |
||||
|
||||
void TlsServerAuthorizationCheckArgDestroyContext(void* context); |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_impl
|
||||
|
||||
#endif // GRPC_INTERNAL_CPP_COMMON_TLS_CREDENTIALS_OPTIONS_UTIL_H
|
@ -0,0 +1,27 @@ |
||||
# 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. |
||||
"""Exceptions for the aio version of the RPC calls.""" |
||||
|
||||
|
||||
cdef class _AioRpcError(Exception): |
||||
cdef readonly: |
||||
tuple _initial_metadata |
||||
int _code |
||||
str _details |
||||
tuple _trailing_metadata |
||||
|
||||
cpdef tuple initial_metadata(self) |
||||
cpdef int code(self) |
||||
cpdef str details(self) |
||||
cpdef tuple trailing_metadata(self) |
@ -0,0 +1,35 @@ |
||||
# 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. |
||||
"""Exceptions for the aio version of the RPC calls.""" |
||||
|
||||
|
||||
cdef class _AioRpcError(Exception): |
||||
|
||||
def __cinit__(self, tuple initial_metadata, int code, str details, tuple trailing_metadata): |
||||
self._initial_metadata = initial_metadata |
||||
self._code = code |
||||
self._details = details |
||||
self._trailing_metadata = trailing_metadata |
||||
|
||||
cpdef tuple initial_metadata(self): |
||||
return self._initial_metadata |
||||
|
||||
cpdef int code(self): |
||||
return self._code |
||||
|
||||
cpdef str details(self): |
||||
return self._details |
||||
|
||||
cpdef tuple trailing_metadata(self): |
||||
return self._trailing_metadata |
@ -1,5 +1,6 @@ |
||||
[ |
||||
"_sanity._sanity_test.AioSanityTest", |
||||
"unit.channel_test.TestChannel", |
||||
"unit.init_test.TestAioRpcError", |
||||
"unit.init_test.TestInsecureChannel" |
||||
] |
||||
|
@ -0,0 +1,338 @@ |
||||
//
|
||||
// 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 <regex> |
||||
|
||||
#include <gmock/gmock.h> |
||||
#include <gtest/gtest.h> |
||||
|
||||
#include <grpc/grpc.h> |
||||
#include <grpc/slice.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h" |
||||
#include "test/core/util/test_config.h" |
||||
|
||||
namespace grpc_core { |
||||
namespace testing { |
||||
|
||||
void VerifyRegexMatch(grpc_error* error, const std::regex& e) { |
||||
std::smatch match; |
||||
std::string s(grpc_error_string(error)); |
||||
EXPECT_TRUE(std::regex_search(s, match, e)); |
||||
GRPC_ERROR_UNREF(error); |
||||
} |
||||
|
||||
TEST(XdsBootstrapTest, Basic) { |
||||
const char* json = |
||||
"{" |
||||
" \"xds_server\": {" |
||||
" \"server_uri\": \"fake:///lb\"," |
||||
" \"channel_creds\": [" |
||||
" {" |
||||
" \"type\": \"fake\"," |
||||
" \"ignore\": 0" |
||||
" }" |
||||
" ]," |
||||
" \"ignore\": 0" |
||||
" }," |
||||
" \"node\": {" |
||||
" \"id\": \"foo\"," |
||||
" \"cluster\": \"bar\"," |
||||
" \"locality\": {" |
||||
" \"region\": \"milky_way\"," |
||||
" \"zone\": \"sol_system\"," |
||||
" \"subzone\": \"earth\"," |
||||
" \"ignore\": {}" |
||||
" }," |
||||
" \"metadata\": {" |
||||
" \"null\": null," |
||||
" \"string\": \"quux\"," |
||||
" \"double\": 123.4," |
||||
" \"bool\": true," |
||||
" \"struct\": {" |
||||
" \"whee\": 0" |
||||
" }," |
||||
" \"list\": [1, 2, 3]" |
||||
" }," |
||||
" \"ignore\": \"whee\"" |
||||
" }," |
||||
" \"ignore\": {}" |
||||
"}"; |
||||
grpc_slice slice = grpc_slice_from_copied_string(json); |
||||
grpc_error* error = GRPC_ERROR_NONE; |
||||
grpc_core::XdsBootstrap bootstrap(slice, &error); |
||||
EXPECT_EQ(error, GRPC_ERROR_NONE); |
||||
EXPECT_STREQ(bootstrap.server_uri(), "fake:///lb"); |
||||
ASSERT_EQ(bootstrap.channel_creds().size(), 1); |
||||
EXPECT_STREQ(bootstrap.channel_creds()[0].type, "fake"); |
||||
EXPECT_EQ(bootstrap.channel_creds()[0].config, nullptr); |
||||
ASSERT_NE(bootstrap.node(), nullptr); |
||||
EXPECT_STREQ(bootstrap.node()->id, "foo"); |
||||
EXPECT_STREQ(bootstrap.node()->cluster, "bar"); |
||||
EXPECT_STREQ(bootstrap.node()->locality_region, "milky_way"); |
||||
EXPECT_STREQ(bootstrap.node()->locality_zone, "sol_system"); |
||||
EXPECT_STREQ(bootstrap.node()->locality_subzone, "earth"); |
||||
EXPECT_THAT( |
||||
bootstrap.node()->metadata, |
||||
::testing::ElementsAre( |
||||
::testing::Pair(::testing::StrEq("null"), |
||||
::testing::AllOf(::testing::Field( |
||||
&XdsBootstrap::MetadataValue::type, |
||||
XdsBootstrap::MetadataValue::Type::MD_NULL))), |
||||
::testing::Pair( |
||||
::testing::StrEq("string"), |
||||
::testing::AllOf( |
||||
::testing::Field(&XdsBootstrap::MetadataValue::type, |
||||
XdsBootstrap::MetadataValue::Type::STRING), |
||||
::testing::Field(&XdsBootstrap::MetadataValue::string_value, |
||||
::testing::StrEq("quux")))), |
||||
::testing::Pair( |
||||
::testing::StrEq("double"), |
||||
::testing::AllOf( |
||||
::testing::Field(&XdsBootstrap::MetadataValue::type, |
||||
XdsBootstrap::MetadataValue::Type::DOUBLE), |
||||
::testing::Field(&XdsBootstrap::MetadataValue::double_value, |
||||
123.4))), |
||||
::testing::Pair( |
||||
::testing::StrEq("bool"), |
||||
::testing::AllOf( |
||||
::testing::Field(&XdsBootstrap::MetadataValue::type, |
||||
XdsBootstrap::MetadataValue::Type::BOOL), |
||||
::testing::Field(&XdsBootstrap::MetadataValue::bool_value, |
||||
true))), |
||||
::testing::Pair( |
||||
::testing::StrEq("struct"), |
||||
::testing::AllOf( |
||||
::testing::Field(&XdsBootstrap::MetadataValue::type, |
||||
XdsBootstrap::MetadataValue::Type::STRUCT), |
||||
::testing::Field( |
||||
&XdsBootstrap::MetadataValue::struct_value, |
||||
::testing::ElementsAre(::testing::Pair( |
||||
::testing::StrEq("whee"), |
||||
::testing::AllOf( |
||||
::testing::Field( |
||||
&XdsBootstrap::MetadataValue::type, |
||||
XdsBootstrap::MetadataValue::Type::DOUBLE), |
||||
::testing::Field( |
||||
&XdsBootstrap::MetadataValue::double_value, |
||||
0))))))), |
||||
::testing::Pair( |
||||
::testing::StrEq("list"), |
||||
::testing::Field(&XdsBootstrap::MetadataValue::type, |
||||
XdsBootstrap::MetadataValue::Type::LIST)))); |
||||
// TODO(roth): Once our InlinedVector<> implementation supports
|
||||
// iteration, replace this by using ElementsAre() in the statement above.
|
||||
auto it = bootstrap.node()->metadata.find("list"); |
||||
ASSERT_TRUE(it != bootstrap.node()->metadata.end()); |
||||
ASSERT_EQ(it->second.list_value.size(), 3); |
||||
EXPECT_EQ(it->second.list_value[0].type, |
||||
XdsBootstrap::MetadataValue::Type::DOUBLE); |
||||
EXPECT_EQ(it->second.list_value[0].double_value, 1); |
||||
EXPECT_EQ(it->second.list_value[1].type, |
||||
XdsBootstrap::MetadataValue::Type::DOUBLE); |
||||
EXPECT_EQ(it->second.list_value[1].double_value, 2); |
||||
EXPECT_EQ(it->second.list_value[2].type, |
||||
XdsBootstrap::MetadataValue::Type::DOUBLE); |
||||
EXPECT_EQ(it->second.list_value[2].double_value, 3); |
||||
} |
||||
|
||||
TEST(XdsBootstrapTest, ValidWithoutChannelCredsAndNode) { |
||||
const char* json = |
||||
"{" |
||||
" \"xds_server\": {" |
||||
" \"server_uri\": \"fake:///lb\"" |
||||
" }" |
||||
"}"; |
||||
grpc_slice slice = grpc_slice_from_copied_string(json); |
||||
grpc_error* error = GRPC_ERROR_NONE; |
||||
grpc_core::XdsBootstrap bootstrap(slice, &error); |
||||
EXPECT_EQ(error, GRPC_ERROR_NONE); |
||||
EXPECT_STREQ(bootstrap.server_uri(), "fake:///lb"); |
||||
EXPECT_EQ(bootstrap.channel_creds().size(), 0); |
||||
EXPECT_EQ(bootstrap.node(), nullptr); |
||||
} |
||||
|
||||
TEST(XdsBootstrapTest, InvalidJson) { |
||||
grpc_slice slice = grpc_slice_from_copied_string(""); |
||||
grpc_error* error = GRPC_ERROR_NONE; |
||||
grpc_core::XdsBootstrap bootstrap(slice, &error); |
||||
gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); |
||||
ASSERT_TRUE(error != GRPC_ERROR_NONE); |
||||
std::regex e(std::string("failed to parse bootstrap file JSON")); |
||||
VerifyRegexMatch(error, e); |
||||
} |
||||
|
||||
TEST(XdsBootstrapTest, MalformedJson) { |
||||
grpc_slice slice = grpc_slice_from_copied_string("\"foo\""); |
||||
grpc_error* error = GRPC_ERROR_NONE; |
||||
grpc_core::XdsBootstrap bootstrap(slice, &error); |
||||
gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); |
||||
ASSERT_TRUE(error != GRPC_ERROR_NONE); |
||||
std::regex e(std::string("malformed JSON in bootstrap file")); |
||||
VerifyRegexMatch(error, e); |
||||
} |
||||
|
||||
TEST(XdsBootstrapTest, MissingXdsServer) { |
||||
grpc_slice slice = grpc_slice_from_copied_string("{}"); |
||||
grpc_error* error = GRPC_ERROR_NONE; |
||||
grpc_core::XdsBootstrap bootstrap(slice, &error); |
||||
gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); |
||||
ASSERT_TRUE(error != GRPC_ERROR_NONE); |
||||
std::regex e(std::string("\"xds_server\" field not present")); |
||||
VerifyRegexMatch(error, e); |
||||
} |
||||
|
||||
TEST(XdsBootstrapTest, BadXdsServer) { |
||||
grpc_slice slice = grpc_slice_from_copied_string( |
||||
"{" |
||||
" \"xds_server\":1," |
||||
" \"xds_server\":{}" |
||||
"}"); |
||||
grpc_error* error = GRPC_ERROR_NONE; |
||||
grpc_core::XdsBootstrap bootstrap(slice, &error); |
||||
gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); |
||||
ASSERT_TRUE(error != GRPC_ERROR_NONE); |
||||
std::regex e( |
||||
std::string("\"xds_server\" field is not an object(.*)" |
||||
"duplicate \"xds_server\" field(.*)" |
||||
"errors parsing \"xds_server\" object(.*)" |
||||
"\"server_uri\" field not present")); |
||||
VerifyRegexMatch(error, e); |
||||
} |
||||
|
||||
TEST(XdsBootstrapTest, BadXdsServerContents) { |
||||
grpc_slice slice = grpc_slice_from_copied_string( |
||||
"{" |
||||
" \"xds_server\":{" |
||||
" \"server_uri\":1," |
||||
" \"server_uri\":\"foo\"," |
||||
" \"channel_creds\":1," |
||||
" \"channel_creds\":{}" |
||||
" }" |
||||
"}"); |
||||
grpc_error* error = GRPC_ERROR_NONE; |
||||
grpc_core::XdsBootstrap bootstrap(slice, &error); |
||||
gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); |
||||
ASSERT_TRUE(error != GRPC_ERROR_NONE); |
||||
std::regex e( |
||||
std::string("errors parsing \"xds_server\" object(.*)" |
||||
"\"server_uri\" field is not a string(.*)" |
||||
"duplicate \"server_uri\" field(.*)" |
||||
"\"channel_creds\" field is not an array(.*)" |
||||
"duplicate \"channel_creds\" field(.*)" |
||||
"\"channel_creds\" field is not an array")); |
||||
VerifyRegexMatch(error, e); |
||||
} |
||||
|
||||
TEST(XdsBootstrapTest, BadChannelCredsContents) { |
||||
grpc_slice slice = grpc_slice_from_copied_string( |
||||
"{" |
||||
" \"xds_server\":{" |
||||
" \"server_uri\":\"foo\"," |
||||
" \"channel_creds\":[" |
||||
" {" |
||||
" \"type\":0," |
||||
" \"type\":\"fake\"," |
||||
" \"config\":1," |
||||
" \"config\":{}" |
||||
" }" |
||||
" ]" |
||||
" }" |
||||
"}"); |
||||
grpc_error* error = GRPC_ERROR_NONE; |
||||
grpc_core::XdsBootstrap bootstrap(slice, &error); |
||||
gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); |
||||
ASSERT_TRUE(error != GRPC_ERROR_NONE); |
||||
std::regex e( |
||||
std::string("errors parsing \"xds_server\" object(.*)" |
||||
"errors parsing \"channel_creds\" object(.*)" |
||||
"\"type\" field is not a string(.*)" |
||||
"duplicate \"type\" field(.*)" |
||||
"\"config\" field is not an object(.*)" |
||||
"duplicate \"config\" field")); |
||||
VerifyRegexMatch(error, e); |
||||
} |
||||
|
||||
TEST(XdsBootstrapTest, BadNode) { |
||||
grpc_slice slice = grpc_slice_from_copied_string( |
||||
"{" |
||||
" \"node\":1," |
||||
" \"node\":{" |
||||
" \"id\":0," |
||||
" \"id\":\"foo\"," |
||||
" \"cluster\":0," |
||||
" \"cluster\":\"foo\"," |
||||
" \"locality\":0," |
||||
" \"locality\":{" |
||||
" \"region\":0," |
||||
" \"region\":\"foo\"," |
||||
" \"zone\":0," |
||||
" \"zone\":\"foo\"," |
||||
" \"subzone\":0," |
||||
" \"subzone\":\"foo\"" |
||||
" }," |
||||
" \"metadata\":0," |
||||
" \"metadata\":{" |
||||
" \"foo\":0," |
||||
" \"foo\":\"whee\"," |
||||
" \"foo\":\"whee2\"" |
||||
" }" |
||||
" }" |
||||
"}"); |
||||
grpc_error* error = GRPC_ERROR_NONE; |
||||
grpc_core::XdsBootstrap bootstrap(slice, &error); |
||||
gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); |
||||
ASSERT_TRUE(error != GRPC_ERROR_NONE); |
||||
std::regex e( |
||||
std::string("\"node\" field is not an object(.*)" |
||||
"duplicate \"node\" field(.*)" |
||||
"errors parsing \"node\" object(.*)" |
||||
"\"id\" field is not a string(.*)" |
||||
"duplicate \"id\" field(.*)" |
||||
"\"cluster\" field is not a string(.*)" |
||||
"duplicate \"cluster\" field(.*)" |
||||
"\"locality\" field is not an object(.*)" |
||||
"duplicate \"locality\" field(.*)" |
||||
"errors parsing \"locality\" object(.*)" |
||||
"\"region\" field is not a string(.*)" |
||||
"duplicate \"region\" field(.*)" |
||||
"\"zone\" field is not a string(.*)" |
||||
"duplicate \"zone\" field(.*)" |
||||
"\"subzone\" field is not a string(.*)" |
||||
"duplicate \"subzone\" field(.*)" |
||||
"\"metadata\" field is not an object(.*)" |
||||
"duplicate \"metadata\" field(.*)" |
||||
"errors parsing \"metadata\" object(.*)" |
||||
"duplicate metadata key \"foo\"")); |
||||
VerifyRegexMatch(error, e); |
||||
} |
||||
|
||||
} // namespace testing
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) { |
||||
// Regexes don't work in gcc4.8 and below, so just skip testing in those cases
|
||||
#if defined(__GNUC__) && \ |
||||
((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__) <= 8)) |
||||
return 0; |
||||
#endif |
||||
grpc::testing::TestEnvironment env(argc, argv); |
||||
grpc_init(); |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
int ret = RUN_ALL_TESTS(); |
||||
grpc_shutdown(); |
||||
return ret; |
||||
} |
@ -0,0 +1,22 @@ |
||||
{ |
||||
"xds_server": { |
||||
"server_uri": "fake:///lb", |
||||
"channel_creds": [ |
||||
{ |
||||
"type": "fake" |
||||
} |
||||
] |
||||
}, |
||||
"node": { |
||||
"id": "xds_end2end_test", |
||||
"cluster": "test", |
||||
"metadata": { |
||||
"foo": "bar" |
||||
}, |
||||
"locality": { |
||||
"region": "corp", |
||||
"zone": "svl", |
||||
"subzone": "mp3" |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
{ |
||||
"xds_server": { |
||||
"server_uri": "fake:///wrong_lb", |
||||
"channel_creds": [ |
||||
{ |
||||
"type": "fake" |
||||
} |
||||
] |
||||
}, |
||||
"node": { |
||||
} |
||||
} |
@ -0,0 +1,66 @@ |
||||
#!/bin/bash |
||||
# Copyright 2017 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. |
||||
|
||||
set -ex |
||||
|
||||
cd "$(dirname "$0")/../../.." |
||||
|
||||
echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list |
||||
echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf |
||||
sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list |
||||
apt-get update |
||||
apt-get install -t jessie-backports -y libssl-dev pkg-config |
||||
|
||||
# Install c-ares |
||||
cd third_party/cares/cares |
||||
git fetch origin |
||||
git checkout cares-1_15_0 |
||||
mkdir -p cmake/build |
||||
cd cmake/build |
||||
cmake -DCMAKE_BUILD_TYPE=Release ../.. |
||||
make -j4 install |
||||
cd ../../../../.. |
||||
rm -rf third_party/cares/cares # wipe out to prevent influencing the grpc build |
||||
|
||||
# Install zlib |
||||
cd third_party/zlib |
||||
mkdir -p cmake/build |
||||
cd cmake/build |
||||
cmake -DCMAKE_BUILD_TYPE=Release ../.. |
||||
make -j4 install |
||||
cd ../../../.. |
||||
rm -rf third_party/zlib # wipe out to prevent influencing the grpc build |
||||
|
||||
# Install protobuf |
||||
cd third_party/protobuf |
||||
mkdir -p cmake/build |
||||
cd cmake/build |
||||
cmake -Dprotobuf_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release .. |
||||
make -j4 install |
||||
cd ../../../.. |
||||
rm -rf third_party/protobuf # wipe out to prevent influencing the grpc build |
||||
|
||||
# Install gRPC |
||||
mkdir -p cmake/build |
||||
cd cmake/build |
||||
cmake -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DgRPC_PROTOBUF_PROVIDER=package -DgRPC_ZLIB_PROVIDER=package -DgRPC_CARES_PROVIDER=package -DgRPC_SSL_PROVIDER=package -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local/grpc ../.. |
||||
make -j4 install |
||||
cd ../.. |
||||
|
||||
# Build helloworld example using Makefiles and pkg-config |
||||
cd examples/cpp/helloworld |
||||
export PKG_CONFIG_PATH=/usr/local/grpc/lib/pkgconfig |
||||
export PATH=$PATH:/usr/local/grpc/bin |
||||
make |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue