|
|
|
@ -20,8 +20,8 @@ |
|
|
|
|
|
|
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
|
|
#include <algorithm> |
|
|
|
|
#include <map> |
|
|
|
|
#include <memory> |
|
|
|
|
#include <utility> |
|
|
|
|
|
|
|
|
|
#include "absl/status/status.h" |
|
|
|
@ -30,6 +30,7 @@ |
|
|
|
|
#include "absl/types/optional.h" |
|
|
|
|
|
|
|
|
|
#include <grpc/event_engine/event_engine.h> |
|
|
|
|
#include <grpc/grpc.h> |
|
|
|
|
#include <grpc/grpc_security_constants.h> |
|
|
|
|
#include <grpc/slice.h> |
|
|
|
|
#include <grpc/support/json.h> |
|
|
|
@ -47,73 +48,44 @@ |
|
|
|
|
#include "src/core/lib/event_engine/default_event_engine.h" |
|
|
|
|
#include "src/core/lib/gprpp/env.h" |
|
|
|
|
#include "src/core/lib/gprpp/load_file.h" |
|
|
|
|
#include "src/core/lib/gprpp/status_helper.h" |
|
|
|
|
#include "src/core/lib/iomgr/error.h" |
|
|
|
|
#include "src/core/lib/json/json.h" |
|
|
|
|
#include "src/core/lib/json/json_reader.h" |
|
|
|
|
#include "src/core/lib/security/util/json_util.h" |
|
|
|
|
#include "src/cpp/client/create_channel_internal.h" |
|
|
|
|
#include "src/cpp/common/secure_auth_context.h" |
|
|
|
|
#include "src/cpp/server/thread_pool_interface.h" |
|
|
|
|
|
|
|
|
|
namespace grpc { |
|
|
|
|
|
|
|
|
|
SecureChannelCredentials::SecureChannelCredentials( |
|
|
|
|
grpc_channel_credentials* c_creds) |
|
|
|
|
: c_creds_(c_creds) {} |
|
|
|
|
|
|
|
|
|
std::shared_ptr<Channel> SecureChannelCredentials::CreateChannelImpl( |
|
|
|
|
const std::string& target, const ChannelArguments& args) { |
|
|
|
|
return CreateChannelWithInterceptors( |
|
|
|
|
target, args, |
|
|
|
|
std::vector<std::unique_ptr< |
|
|
|
|
grpc::experimental::ClientInterceptorFactoryInterface>>()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::shared_ptr<Channel> |
|
|
|
|
SecureChannelCredentials::CreateChannelWithInterceptors( |
|
|
|
|
const std::string& target, const ChannelArguments& args, |
|
|
|
|
std::vector< |
|
|
|
|
std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>> |
|
|
|
|
interceptor_creators) { |
|
|
|
|
grpc_channel_args channel_args; |
|
|
|
|
args.SetChannelArgs(&channel_args); |
|
|
|
|
return grpc::CreateChannelInternal( |
|
|
|
|
args.GetSslTargetNameOverride(), |
|
|
|
|
grpc_channel_create(target.c_str(), c_creds_, &channel_args), |
|
|
|
|
std::move(interceptor_creators)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SecureCallCredentials::SecureCallCredentials(grpc_call_credentials* c_creds) |
|
|
|
|
: c_creds_(c_creds) {} |
|
|
|
|
namespace { |
|
|
|
|
class WrappedCallCredentials : public CallCredentials { |
|
|
|
|
public: |
|
|
|
|
explicit WrappedCallCredentials(grpc_call_credentials* creds) |
|
|
|
|
: CallCredentials(creds) {} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
bool SecureCallCredentials::ApplyToCall(grpc_call* call) { |
|
|
|
|
return grpc_call_set_credentials(call, c_creds_) == GRPC_CALL_OK; |
|
|
|
|
std::shared_ptr<WrappedCallCredentials> WrapCallCredentials( |
|
|
|
|
grpc_call_credentials* creds) { |
|
|
|
|
return creds == nullptr ? nullptr |
|
|
|
|
: std::make_shared<WrappedCallCredentials>(creds); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
namespace internal { |
|
|
|
|
class WrappedChannelCredentials final : public ChannelCredentials { |
|
|
|
|
public: |
|
|
|
|
explicit WrappedChannelCredentials(grpc_channel_credentials* c_creds) |
|
|
|
|
: ChannelCredentials(c_creds) {} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
std::shared_ptr<ChannelCredentials> WrapChannelCredentials( |
|
|
|
|
std::shared_ptr<WrappedChannelCredentials> WrapChannelCredentials( |
|
|
|
|
grpc_channel_credentials* creds) { |
|
|
|
|
return creds == nullptr ? nullptr |
|
|
|
|
: std::shared_ptr<ChannelCredentials>( |
|
|
|
|
new SecureChannelCredentials(creds)); |
|
|
|
|
: std::make_shared<WrappedChannelCredentials>(creds); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
std::shared_ptr<CallCredentials> WrapCallCredentials( |
|
|
|
|
grpc_call_credentials* creds) { |
|
|
|
|
return creds == nullptr ? nullptr |
|
|
|
|
: std::shared_ptr<CallCredentials>( |
|
|
|
|
new SecureCallCredentials(creds)); |
|
|
|
|
} |
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() { |
|
|
|
|
grpc::internal::GrpcLibrary init; // To call grpc_init().
|
|
|
|
|
return internal::WrapChannelCredentials( |
|
|
|
|
return WrapChannelCredentials( |
|
|
|
|
grpc_google_default_credentials_create(nullptr)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -130,12 +102,10 @@ std::shared_ptr<ChannelCredentials> SslCredentials( |
|
|
|
|
grpc::internal::GrpcLibrary init; // To call grpc_init().
|
|
|
|
|
grpc_ssl_pem_key_cert_pair pem_key_cert_pair = { |
|
|
|
|
options.pem_private_key.c_str(), options.pem_cert_chain.c_str()}; |
|
|
|
|
|
|
|
|
|
grpc_channel_credentials* c_creds = grpc_ssl_credentials_create( |
|
|
|
|
return WrapChannelCredentials(grpc_ssl_credentials_create( |
|
|
|
|
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(), |
|
|
|
|
options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr, |
|
|
|
|
nullptr); |
|
|
|
|
return internal::WrapChannelCredentials(c_creds); |
|
|
|
|
nullptr)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
namespace experimental { |
|
|
|
@ -259,21 +229,6 @@ std::shared_ptr<CallCredentials> StsCredentials( |
|
|
|
|
return WrapCallCredentials(grpc_sts_credentials_create(&opts, nullptr)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin( |
|
|
|
|
std::unique_ptr<MetadataCredentialsPlugin> plugin, |
|
|
|
|
grpc_security_level min_security_level) { |
|
|
|
|
grpc::internal::GrpcLibrary init; // To call grpc_init().
|
|
|
|
|
const char* type = plugin->GetType(); |
|
|
|
|
grpc::MetadataCredentialsPluginWrapper* wrapper = |
|
|
|
|
new grpc::MetadataCredentialsPluginWrapper(std::move(plugin)); |
|
|
|
|
grpc_metadata_credentials_plugin c_plugin = { |
|
|
|
|
grpc::MetadataCredentialsPluginWrapper::GetMetadata, |
|
|
|
|
grpc::MetadataCredentialsPluginWrapper::DebugString, |
|
|
|
|
grpc::MetadataCredentialsPluginWrapper::Destroy, wrapper, type}; |
|
|
|
|
return WrapCallCredentials(grpc_metadata_credentials_create_from_plugin( |
|
|
|
|
c_plugin, min_security_level, nullptr)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Builds ALTS Credentials given ALTS specific options
|
|
|
|
|
std::shared_ptr<ChannelCredentials> AltsCredentials( |
|
|
|
|
const AltsCredentialsOptions& options) { |
|
|
|
@ -286,20 +241,20 @@ std::shared_ptr<ChannelCredentials> AltsCredentials( |
|
|
|
|
} |
|
|
|
|
grpc_channel_credentials* c_creds = grpc_alts_credentials_create(c_options); |
|
|
|
|
grpc_alts_credentials_options_destroy(c_options); |
|
|
|
|
return internal::WrapChannelCredentials(c_creds); |
|
|
|
|
return WrapChannelCredentials(c_creds); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Builds Local Credentials
|
|
|
|
|
std::shared_ptr<ChannelCredentials> LocalCredentials( |
|
|
|
|
grpc_local_connect_type type) { |
|
|
|
|
grpc::internal::GrpcLibrary init; // To call grpc_init().
|
|
|
|
|
return internal::WrapChannelCredentials(grpc_local_credentials_create(type)); |
|
|
|
|
return WrapChannelCredentials(grpc_local_credentials_create(type)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Builds TLS Credentials given TLS options.
|
|
|
|
|
std::shared_ptr<ChannelCredentials> TlsCredentials( |
|
|
|
|
const TlsChannelCredentialsOptions& options) { |
|
|
|
|
return internal::WrapChannelCredentials( |
|
|
|
|
return WrapChannelCredentials( |
|
|
|
|
grpc_tls_credentials_create(options.c_credentials_options())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -361,93 +316,24 @@ std::shared_ptr<ChannelCredentials> CompositeChannelCredentials( |
|
|
|
|
// here. This is OK because the underlying C objects (i.e., channel_creds and
|
|
|
|
|
// call_creds) into grpc_composite_credentials_create will see their refcounts
|
|
|
|
|
// incremented.
|
|
|
|
|
SecureChannelCredentials* s_channel_creds = |
|
|
|
|
channel_creds->AsSecureCredentials(); |
|
|
|
|
SecureCallCredentials* s_call_creds = call_creds->AsSecureCredentials(); |
|
|
|
|
if (s_channel_creds && s_call_creds) { |
|
|
|
|
return internal::WrapChannelCredentials( |
|
|
|
|
grpc_composite_channel_credentials_create( |
|
|
|
|
s_channel_creds->GetRawCreds(), s_call_creds->GetRawCreds(), |
|
|
|
|
nullptr)); |
|
|
|
|
} |
|
|
|
|
return nullptr; |
|
|
|
|
return channel_creds->c_creds_ == nullptr |
|
|
|
|
? nullptr |
|
|
|
|
: WrapChannelCredentials(grpc_composite_channel_credentials_create( |
|
|
|
|
channel_creds->c_creds_, call_creds->c_creds_, nullptr)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class CompositeCallCredentialsImpl : public CallCredentials { |
|
|
|
|
public: |
|
|
|
|
CompositeCallCredentialsImpl(const std::shared_ptr<CallCredentials>& creds1, |
|
|
|
|
const std::shared_ptr<CallCredentials>& creds2) |
|
|
|
|
: CallCredentials(grpc_composite_call_credentials_create( |
|
|
|
|
creds1->c_creds_, creds2->c_creds_, nullptr)) {} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
std::shared_ptr<CallCredentials> CompositeCallCredentials( |
|
|
|
|
const std::shared_ptr<CallCredentials>& creds1, |
|
|
|
|
const std::shared_ptr<CallCredentials>& creds2) { |
|
|
|
|
SecureCallCredentials* s_creds1 = creds1->AsSecureCredentials(); |
|
|
|
|
SecureCallCredentials* s_creds2 = creds2->AsSecureCredentials(); |
|
|
|
|
if (s_creds1 != nullptr && s_creds2 != nullptr) { |
|
|
|
|
return WrapCallCredentials(grpc_composite_call_credentials_create( |
|
|
|
|
s_creds1->GetRawCreds(), s_creds2->GetRawCreds(), nullptr)); |
|
|
|
|
} |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin( |
|
|
|
|
std::unique_ptr<MetadataCredentialsPlugin> plugin) { |
|
|
|
|
grpc::internal::GrpcLibrary init; // To call grpc_init().
|
|
|
|
|
const char* type = plugin->GetType(); |
|
|
|
|
grpc::MetadataCredentialsPluginWrapper* wrapper = |
|
|
|
|
new grpc::MetadataCredentialsPluginWrapper(std::move(plugin)); |
|
|
|
|
grpc_metadata_credentials_plugin c_plugin = { |
|
|
|
|
grpc::MetadataCredentialsPluginWrapper::GetMetadata, |
|
|
|
|
grpc::MetadataCredentialsPluginWrapper::DebugString, |
|
|
|
|
grpc::MetadataCredentialsPluginWrapper::Destroy, wrapper, type}; |
|
|
|
|
return WrapCallCredentials(grpc_metadata_credentials_create_from_plugin( |
|
|
|
|
c_plugin, GRPC_PRIVACY_AND_INTEGRITY, nullptr)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
char* MetadataCredentialsPluginWrapper::DebugString(void* wrapper) { |
|
|
|
|
GPR_ASSERT(wrapper); |
|
|
|
|
MetadataCredentialsPluginWrapper* w = |
|
|
|
|
static_cast<MetadataCredentialsPluginWrapper*>(wrapper); |
|
|
|
|
return gpr_strdup(w->plugin_->DebugString().c_str()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MetadataCredentialsPluginWrapper::Destroy(void* wrapper) { |
|
|
|
|
if (wrapper == nullptr) return; |
|
|
|
|
grpc_event_engine::experimental::GetDefaultEventEngine()->Run([wrapper] { |
|
|
|
|
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; |
|
|
|
|
grpc_core::ExecCtx exec_ctx; |
|
|
|
|
delete static_cast<MetadataCredentialsPluginWrapper*>(wrapper); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int MetadataCredentialsPluginWrapper::GetMetadata( |
|
|
|
|
void* wrapper, grpc_auth_metadata_context context, |
|
|
|
|
grpc_credentials_plugin_metadata_cb cb, void* user_data, |
|
|
|
|
grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX], |
|
|
|
|
size_t* num_creds_md, grpc_status_code* status, |
|
|
|
|
const char** error_details) { |
|
|
|
|
GPR_ASSERT(wrapper); |
|
|
|
|
MetadataCredentialsPluginWrapper* w = |
|
|
|
|
static_cast<MetadataCredentialsPluginWrapper*>(wrapper); |
|
|
|
|
if (!w->plugin_) { |
|
|
|
|
*num_creds_md = 0; |
|
|
|
|
*status = GRPC_STATUS_OK; |
|
|
|
|
*error_details = nullptr; |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
if (w->plugin_->IsBlocking()) { |
|
|
|
|
// The internals of context may be destroyed if GetMetadata is cancelled.
|
|
|
|
|
// Make a copy for InvokePlugin.
|
|
|
|
|
grpc_auth_metadata_context context_copy = grpc_auth_metadata_context(); |
|
|
|
|
grpc_auth_metadata_context_copy(&context, &context_copy); |
|
|
|
|
// Asynchronous return.
|
|
|
|
|
w->thread_pool_->Add([w, context_copy, cb, user_data]() mutable { |
|
|
|
|
w->MetadataCredentialsPluginWrapper::InvokePlugin( |
|
|
|
|
context_copy, cb, user_data, nullptr, nullptr, nullptr, nullptr); |
|
|
|
|
grpc_auth_metadata_context_reset(&context_copy); |
|
|
|
|
}); |
|
|
|
|
return 0; |
|
|
|
|
} else { |
|
|
|
|
// Synchronous return.
|
|
|
|
|
w->InvokePlugin(context, cb, user_data, creds_md, num_creds_md, status, |
|
|
|
|
error_details); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
return std::make_shared<CompositeCallCredentialsImpl>(creds1, creds2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
@ -459,61 +345,147 @@ void UnrefMetadata(const std::vector<grpc_metadata>& md) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void MetadataCredentialsPluginWrapper::InvokePlugin( |
|
|
|
|
grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, |
|
|
|
|
void* user_data, grpc_metadata creds_md[4], size_t* num_creds_md, |
|
|
|
|
grpc_status_code* status_code, const char** error_details) { |
|
|
|
|
std::multimap<std::string, std::string> metadata; |
|
|
|
|
|
|
|
|
|
// const_cast is safe since the SecureAuthContext only inc/dec the refcount
|
|
|
|
|
// and the object is passed as a const ref to plugin_->GetMetadata.
|
|
|
|
|
SecureAuthContext cpp_channel_auth_context( |
|
|
|
|
const_cast<grpc_auth_context*>(context.channel_auth_context)); |
|
|
|
|
|
|
|
|
|
Status status = plugin_->GetMetadata(context.service_url, context.method_name, |
|
|
|
|
cpp_channel_auth_context, &metadata); |
|
|
|
|
std::vector<grpc_metadata> md; |
|
|
|
|
for (auto& metadatum : metadata) { |
|
|
|
|
grpc_metadata md_entry; |
|
|
|
|
md_entry.key = SliceFromCopiedString(metadatum.first); |
|
|
|
|
md_entry.value = SliceFromCopiedString(metadatum.second); |
|
|
|
|
md.push_back(md_entry); |
|
|
|
|
class MetadataCredentialsPluginWrapper final : private internal::GrpcLibrary { |
|
|
|
|
public: |
|
|
|
|
static void Destroy(void* wrapper) { |
|
|
|
|
if (wrapper == nullptr) return; |
|
|
|
|
grpc_event_engine::experimental::GetDefaultEventEngine()->Run([wrapper] { |
|
|
|
|
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; |
|
|
|
|
grpc_core::ExecCtx exec_ctx; |
|
|
|
|
delete static_cast<MetadataCredentialsPluginWrapper*>(wrapper); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
if (creds_md != nullptr) { |
|
|
|
|
// Synchronous return.
|
|
|
|
|
if (md.size() > GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX) { |
|
|
|
|
|
|
|
|
|
static int GetMetadata( |
|
|
|
|
void* wrapper, grpc_auth_metadata_context context, |
|
|
|
|
grpc_credentials_plugin_metadata_cb cb, void* user_data, |
|
|
|
|
grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX], |
|
|
|
|
size_t* num_creds_md, grpc_status_code* status, |
|
|
|
|
const char** error_details) { |
|
|
|
|
GPR_ASSERT(wrapper); |
|
|
|
|
MetadataCredentialsPluginWrapper* w = |
|
|
|
|
static_cast<MetadataCredentialsPluginWrapper*>(wrapper); |
|
|
|
|
if (!w->plugin_) { |
|
|
|
|
*num_creds_md = 0; |
|
|
|
|
*status_code = GRPC_STATUS_INTERNAL; |
|
|
|
|
*error_details = gpr_strdup( |
|
|
|
|
"blocking plugin credentials returned too many metadata keys"); |
|
|
|
|
UnrefMetadata(md); |
|
|
|
|
*status = GRPC_STATUS_OK; |
|
|
|
|
*error_details = nullptr; |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
if (w->plugin_->IsBlocking()) { |
|
|
|
|
// The internals of context may be destroyed if GetMetadata is cancelled.
|
|
|
|
|
// Make a copy for InvokePlugin.
|
|
|
|
|
grpc_auth_metadata_context context_copy = grpc_auth_metadata_context(); |
|
|
|
|
grpc_auth_metadata_context_copy(&context, &context_copy); |
|
|
|
|
// Asynchronous return.
|
|
|
|
|
// TODO(hork): replace with EventEngine::Run
|
|
|
|
|
w->thread_pool_->Add([w, context_copy, cb, user_data]() mutable { |
|
|
|
|
w->MetadataCredentialsPluginWrapper::InvokePlugin( |
|
|
|
|
context_copy, cb, user_data, nullptr, nullptr, nullptr, nullptr); |
|
|
|
|
grpc_auth_metadata_context_reset(&context_copy); |
|
|
|
|
}); |
|
|
|
|
return 0; |
|
|
|
|
} else { |
|
|
|
|
for (const auto& elem : md) { |
|
|
|
|
creds_md[*num_creds_md].key = elem.key; |
|
|
|
|
creds_md[*num_creds_md].value = elem.value; |
|
|
|
|
++(*num_creds_md); |
|
|
|
|
// Synchronous return.
|
|
|
|
|
w->InvokePlugin(context, cb, user_data, creds_md, num_creds_md, status, |
|
|
|
|
error_details); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static char* DebugString(void* wrapper) { |
|
|
|
|
GPR_ASSERT(wrapper); |
|
|
|
|
MetadataCredentialsPluginWrapper* w = |
|
|
|
|
static_cast<MetadataCredentialsPluginWrapper*>(wrapper); |
|
|
|
|
return gpr_strdup(w->plugin_->DebugString().c_str()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
explicit MetadataCredentialsPluginWrapper( |
|
|
|
|
std::unique_ptr<MetadataCredentialsPlugin> plugin) |
|
|
|
|
: plugin_(std::move(plugin)) { |
|
|
|
|
if (plugin_->IsBlocking()) { |
|
|
|
|
thread_pool_.reset(CreateDefaultThreadPool()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
void InvokePlugin( |
|
|
|
|
grpc_auth_metadata_context context, |
|
|
|
|
grpc_credentials_plugin_metadata_cb cb, void* user_data, |
|
|
|
|
grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX], |
|
|
|
|
size_t* num_creds_md, grpc_status_code* status_code, |
|
|
|
|
const char** error_details) { |
|
|
|
|
std::multimap<std::string, std::string> metadata; |
|
|
|
|
|
|
|
|
|
// const_cast is safe since the SecureAuthContext only inc/dec the refcount
|
|
|
|
|
// and the object is passed as a const ref to plugin_->GetMetadata.
|
|
|
|
|
SecureAuthContext cpp_channel_auth_context( |
|
|
|
|
const_cast<grpc_auth_context*>(context.channel_auth_context)); |
|
|
|
|
|
|
|
|
|
Status status = |
|
|
|
|
plugin_->GetMetadata(context.service_url, context.method_name, |
|
|
|
|
cpp_channel_auth_context, &metadata); |
|
|
|
|
std::vector<grpc_metadata> md; |
|
|
|
|
for (auto& metadatum : metadata) { |
|
|
|
|
grpc_metadata md_entry; |
|
|
|
|
md_entry.key = SliceFromCopiedString(metadatum.first); |
|
|
|
|
md_entry.value = SliceFromCopiedString(metadatum.second); |
|
|
|
|
md.push_back(md_entry); |
|
|
|
|
} |
|
|
|
|
if (creds_md != nullptr) { |
|
|
|
|
// Synchronous return.
|
|
|
|
|
if (md.size() > GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX) { |
|
|
|
|
*num_creds_md = 0; |
|
|
|
|
*status_code = GRPC_STATUS_INTERNAL; |
|
|
|
|
*error_details = gpr_strdup( |
|
|
|
|
"blocking plugin credentials returned too many metadata keys"); |
|
|
|
|
UnrefMetadata(md); |
|
|
|
|
} else { |
|
|
|
|
for (const auto& elem : md) { |
|
|
|
|
creds_md[*num_creds_md].key = elem.key; |
|
|
|
|
creds_md[*num_creds_md].value = elem.value; |
|
|
|
|
++(*num_creds_md); |
|
|
|
|
} |
|
|
|
|
*status_code = static_cast<grpc_status_code>(status.error_code()); |
|
|
|
|
*error_details = |
|
|
|
|
status.ok() ? nullptr : gpr_strdup(status.error_message().c_str()); |
|
|
|
|
} |
|
|
|
|
*status_code = static_cast<grpc_status_code>(status.error_code()); |
|
|
|
|
*error_details = |
|
|
|
|
status.ok() ? nullptr : gpr_strdup(status.error_message().c_str()); |
|
|
|
|
} else { |
|
|
|
|
// Asynchronous return.
|
|
|
|
|
cb(user_data, md.empty() ? nullptr : &md[0], md.size(), |
|
|
|
|
static_cast<grpc_status_code>(status.error_code()), |
|
|
|
|
status.error_message().c_str()); |
|
|
|
|
UnrefMetadata(md); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// Asynchronous return.
|
|
|
|
|
cb(user_data, md.empty() ? nullptr : &md[0], md.size(), |
|
|
|
|
static_cast<grpc_status_code>(status.error_code()), |
|
|
|
|
status.error_message().c_str()); |
|
|
|
|
UnrefMetadata(md); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::unique_ptr<ThreadPoolInterface> thread_pool_; |
|
|
|
|
std::unique_ptr<MetadataCredentialsPlugin> plugin_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
namespace experimental { |
|
|
|
|
std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin( |
|
|
|
|
std::unique_ptr<MetadataCredentialsPlugin> plugin, |
|
|
|
|
grpc_security_level min_security_level) { |
|
|
|
|
grpc::internal::GrpcLibrary init; // To call grpc_init().
|
|
|
|
|
const char* type = plugin->GetType(); |
|
|
|
|
MetadataCredentialsPluginWrapper* wrapper = |
|
|
|
|
new MetadataCredentialsPluginWrapper(std::move(plugin)); |
|
|
|
|
grpc_metadata_credentials_plugin c_plugin = { |
|
|
|
|
MetadataCredentialsPluginWrapper::GetMetadata, |
|
|
|
|
MetadataCredentialsPluginWrapper::DebugString, |
|
|
|
|
MetadataCredentialsPluginWrapper::Destroy, wrapper, type}; |
|
|
|
|
return WrapCallCredentials(grpc_metadata_credentials_create_from_plugin( |
|
|
|
|
c_plugin, min_security_level, nullptr)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper( |
|
|
|
|
std::unique_ptr<MetadataCredentialsPlugin> plugin) |
|
|
|
|
: plugin_(std::move(plugin)) { |
|
|
|
|
if (plugin_->IsBlocking()) { |
|
|
|
|
thread_pool_.reset(CreateDefaultThreadPool()); |
|
|
|
|
} |
|
|
|
|
} // namespace experimental
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin( |
|
|
|
|
std::unique_ptr<MetadataCredentialsPlugin> plugin) { |
|
|
|
|
return experimental::MetadataCredentialsFromPlugin( |
|
|
|
|
std::move(plugin), GRPC_PRIVACY_AND_INTEGRITY); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace grpc
|
|
|
|
|