aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/grpc++/security/credentials.h21
-rw-r--r--src/core/security/credentials.c86
-rw-r--r--src/core/security/credentials.h9
-rw-r--r--src/cpp/client/secure_credentials.cc60
-rw-r--r--src/cpp/client/secure_credentials.h19
5 files changed, 195 insertions, 0 deletions
diff --git a/include/grpc++/security/credentials.h b/include/grpc++/security/credentials.h
index ce5a9e0606..03d3550197 100644
--- a/include/grpc++/security/credentials.h
+++ b/include/grpc++/security/credentials.h
@@ -34,10 +34,13 @@
#ifndef GRPCXX_CREDENTIALS_H
#define GRPCXX_CREDENTIALS_H
+#include <map>
#include <memory>
#include <grpc++/impl/grpc_library.h>
#include <grpc++/support/config.h>
+#include <grpc++/support/status.h>
+#include <grpc++/support/string_ref.h>
namespace grpc {
class ChannelArguments;
@@ -129,6 +132,24 @@ std::shared_ptr<Credentials> CompositeCredentials(
// Credentials for an unencrypted, unauthenticated channel
std::shared_ptr<Credentials> InsecureCredentials();
+// User defined metadata credentials.
+class MetadataCredentialsPlugin {
+ public:
+ virtual ~MetadataCredentialsPlugin() {}
+
+ // If this method returns true, the Process function will be scheduled in
+ // a different thread from the one processing the call.
+ virtual bool IsBlocking() const { return true; }
+
+ // Gets the auth metatada produced by this plugin. */
+ virtual Status GetMetadata(
+ grpc::string_ref service_url,
+ std::multimap<grpc::string, grpc::string_ref>* metadata) = 0;
+};
+
+std::shared_ptr<Credentials> MetadataCredentialsFromPlugin(
+ std::unique_ptr<MetadataCredentialsPlugin> plugin);
+
} // namespace grpc
#endif // GRPCXX_CREDENTIALS_H
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index a764413300..afe980a5b0 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -1185,3 +1185,89 @@ grpc_credentials *grpc_google_iam_credentials_create(
c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
return &c->base;
}
+
+/* -- Plugin credentials. -- */
+
+typedef struct {
+ void *user_data;
+ grpc_credentials_metadata_cb cb;
+} grpc_metadata_plugin_request;
+
+static void plugin_destruct(grpc_credentials *creds) {
+ grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
+ if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
+ c->plugin.destroy(c->plugin.state);
+ }
+}
+
+static int plugin_has_request_metadata(const grpc_credentials *creds) {
+ return 1;
+}
+
+static int plugin_has_request_metadata_only(const grpc_credentials *creds) {
+ return 1;
+}
+
+static void plugin_md_request_metadata_ready(void *request,
+ const grpc_metadata *md,
+ size_t num_md,
+ grpc_status_code status,
+ const char *error_details) {
+ grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
+ if (status != GRPC_STATUS_OK) {
+ if (error_details != NULL) {
+ gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s",
+ error_details);
+ }
+ r->cb(r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
+ } else {
+ grpc_credentials_md *md_array = NULL;
+ if (num_md > 0) {
+ size_t i;
+ md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
+ for (i = 0; i < num_md; i++) {
+ md_array[i].key = gpr_slice_from_copied_string(md[i].key);
+ md_array[i].value =
+ gpr_slice_from_copied_buffer(md[i].value, md[i].value_length);
+ }
+ }
+ r->cb(r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK);
+ if (md_array != NULL) gpr_free(md_array);
+ }
+ gpr_free(r);
+}
+
+static void plugin_get_request_metadata(grpc_credentials *creds,
+ grpc_pollset *pollset,
+ const char *service_url,
+ grpc_credentials_metadata_cb cb,
+ void *user_data) {
+ grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
+ if (c->plugin.get_metadata != NULL) {
+ grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
+ memset(request, 0, sizeof(*request));
+ request->user_data = user_data;
+ request->cb = cb;
+ c->plugin.get_metadata(c->plugin.state, service_url,
+ plugin_md_request_metadata_ready, request);
+ } else {
+ cb(user_data, NULL, 0, GRPC_CREDENTIALS_OK);
+ }
+}
+
+static grpc_credentials_vtable plugin_vtable = {
+ plugin_destruct, plugin_has_request_metadata,
+ plugin_has_request_metadata_only, plugin_get_request_metadata, NULL};
+
+grpc_credentials *grpc_metadata_credentials_create_from_plugin(
+ grpc_metadata_credentials_plugin plugin, void *reserved) {
+ grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
+ GPR_ASSERT(reserved == NULL);
+ memset(c, 0, sizeof(*c));
+ c->base.type = GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN;
+ c->base.vtable = &plugin_vtable;
+ gpr_ref_init(&c->base.refcount, 1);
+ c->plugin = plugin;
+ return &c->base;
+}
+
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 8e4fed7615..38ce0f8ba6 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -56,6 +56,7 @@ typedef enum {
#define GRPC_CREDENTIALS_TYPE_SSL "Ssl"
#define GRPC_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
+#define GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
#define GRPC_CREDENTIALS_TYPE_JWT "Jwt"
#define GRPC_CREDENTIALS_TYPE_IAM "Iam"
#define GRPC_CREDENTIALS_TYPE_COMPOSITE "Composite"
@@ -322,4 +323,12 @@ typedef struct {
grpc_credentials *connector_creds;
} grpc_composite_credentials;
+/* -- Plugin credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_metadata_credentials_plugin plugin;
+ grpc_credentials_md_store *plugin_md;
+} grpc_plugin_credentials;
+
#endif /* GRPC_INTERNAL_CORE_SECURITY_CREDENTIALS_H */
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index 2260f6d33e..8333b01f29 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -144,4 +144,64 @@ std::shared_ptr<Credentials> CompositeCredentials(
return nullptr;
}
+void MetadataCredentialsPluginWrapper::Destroy(void* wrapper) {
+ if (wrapper == nullptr) return;
+ MetadataCredentialsPluginWrapper* w =
+ reinterpret_cast<MetadataCredentialsPluginWrapper*>(wrapper);
+ delete w;
+}
+
+void MetadataCredentialsPluginWrapper::GetMetadata(
+ void* wrapper, const char* service_url,
+ grpc_credentials_plugin_metadata_cb cb, void* user_data) {
+ GPR_ASSERT(wrapper != nullptr);
+ MetadataCredentialsPluginWrapper* w =
+ reinterpret_cast<MetadataCredentialsPluginWrapper*>(wrapper);
+ if (w->plugin_ == nullptr) {
+ cb(user_data, NULL, 0, GRPC_STATUS_OK, NULL);
+ return;
+ }
+ if (w->plugin_->IsBlocking()) {
+ w->thread_pool_->Add(
+ std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w,
+ service_url, cb, user_data));
+ } else {
+ w->InvokePlugin(service_url, cb, user_data);
+ }
+}
+
+void MetadataCredentialsPluginWrapper::InvokePlugin(
+ const char* service_url, grpc_credentials_plugin_metadata_cb cb,
+ void* user_data) {
+ std::multimap<grpc::string, grpc::string_ref> metadata;
+ Status status = plugin_->GetMetadata(service_url, &metadata);
+ std::vector<grpc_metadata> md;
+ for (auto it = metadata.begin(); it != metadata.end(); ++it) {
+ md.push_back({it->first.c_str(),
+ it->second.data(),
+ it->second.size(),
+ 0,
+ {{nullptr, nullptr, nullptr, nullptr}}});
+ }
+ cb(user_data, &md[0], md.size(),
+ static_cast<grpc_status_code>(status.error_code()),
+ status.error_message().c_str());
+}
+
+MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
+ std::unique_ptr<MetadataCredentialsPlugin> plugin)
+ : thread_pool_(CreateDefaultThreadPool()), plugin_(std::move(plugin)) {}
+
+std::shared_ptr<Credentials> MetadataCredentialsFromPlugin(
+ std::unique_ptr<MetadataCredentialsPlugin> plugin) {
+ GrpcLibrary init; // To call grpc_init().
+ MetadataCredentialsPluginWrapper* wrapper =
+ new MetadataCredentialsPluginWrapper(std::move(plugin));
+ grpc_metadata_credentials_plugin c_plugin = {
+ MetadataCredentialsPluginWrapper::GetMetadata,
+ MetadataCredentialsPluginWrapper::Destroy, wrapper};
+ return WrapCredentials(
+ grpc_metadata_credentials_create_from_plugin(c_plugin, nullptr));
+}
+
} // namespace grpc
diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h
index 8deff856c4..d354827725 100644
--- a/src/cpp/client/secure_credentials.h
+++ b/src/cpp/client/secure_credentials.h
@@ -39,6 +39,8 @@
#include <grpc++/support/config.h>
#include <grpc++/security/credentials.h>
+#include "src/cpp/server/thread_pool_interface.h"
+
namespace grpc {
class SecureCredentials GRPC_FINAL : public Credentials {
@@ -56,6 +58,23 @@ class SecureCredentials GRPC_FINAL : public Credentials {
grpc_credentials* const c_creds_;
};
+class MetadataCredentialsPluginWrapper GRPC_FINAL {
+ public:
+ static void Destroy(void* wrapper);
+ static void GetMetadata(void* wrapper, const char* service_url,
+ grpc_credentials_plugin_metadata_cb cb,
+ void* user_data);
+
+ explicit MetadataCredentialsPluginWrapper(
+ std::unique_ptr<MetadataCredentialsPlugin> plugin);
+
+ private:
+ void InvokePlugin(const char* service_url,
+ grpc_credentials_plugin_metadata_cb cb, void* user_data);
+ std::unique_ptr<ThreadPoolInterface> thread_pool_;
+ std::unique_ptr<MetadataCredentialsPlugin> plugin_;
+};
+
} // namespace grpc
#endif // GRPC_INTERNAL_CPP_CLIENT_SECURE_CREDENTIALS_H