Merge pull request #4154 from jboeuf/new_creds_plugin_api

Changing the credentials plugin API.
pull/4208/head
jboeuf 9 years ago
commit b1c41d7b0d
  1. 177
      include/grpc/grpc_security.h
  2. 48
      src/core/security/client_auth_filter.c
  3. 74
      src/core/security/credentials.c
  4. 5
      src/core/security/credentials.h
  5. 8
      src/cpp/client/secure_credentials.cc
  6. 2
      src/cpp/client/secure_credentials.h
  7. 8
      src/csharp/ext/grpc_csharp_ext.c
  8. 5
      src/node/ext/call_credentials.cc
  9. 2
      src/node/ext/call_credentials.h
  10. 74
      test/core/security/credentials_test.c
  11. 4
      test/core/security/oauth2_utils.c
  12. 5
      test/core/security/print_google_default_creds_token.c

@ -41,6 +41,81 @@
extern "C" {
#endif
/* --- Authentication Context. --- */
#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
typedef struct grpc_auth_context grpc_auth_context;
typedef struct grpc_auth_property_iterator {
const grpc_auth_context *ctx;
size_t index;
const char *name;
} grpc_auth_property_iterator;
/* value, if not NULL, is guaranteed to be NULL terminated. */
typedef struct grpc_auth_property {
char *name;
char *value;
size_t value_length;
} grpc_auth_property;
/* Returns NULL when the iterator is at the end. */
const grpc_auth_property *grpc_auth_property_iterator_next(
grpc_auth_property_iterator *it);
/* Iterates over the auth context. */
grpc_auth_property_iterator grpc_auth_context_property_iterator(
const grpc_auth_context *ctx);
/* Gets the peer identity. Returns an empty iterator (first _next will return
NULL) if the peer is not authenticated. */
grpc_auth_property_iterator grpc_auth_context_peer_identity(
const grpc_auth_context *ctx);
/* Finds a property in the context. May return an empty iterator (first _next
will return NULL) if no property with this name was found in the context. */
grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
const grpc_auth_context *ctx, const char *name);
/* Gets the name of the property that indicates the peer identity. Will return
NULL if the peer is not authenticated. */
const char *grpc_auth_context_peer_identity_property_name(
const grpc_auth_context *ctx);
/* Returns 1 if the peer is authenticated, 0 otherwise. */
int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
/* Gets the auth context from the call. Caller needs to call
grpc_auth_context_release on the returned context. */
grpc_auth_context *grpc_call_auth_context(grpc_call *call);
/* Releases the auth context returned from grpc_call_auth_context. */
void grpc_auth_context_release(grpc_auth_context *context);
/* --
The following auth context methods should only be called by a server metadata
processor to set properties extracted from auth metadata.
-- */
/* Add a property. */
void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
const char *value, size_t value_length);
/* Add a C string property. */
void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
const char *name,
const char *value);
/* Sets the property name. Returns 1 if successful or 0 in case of failure
(which means that no property with this name exists). */
int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
const char *name);
/* --- grpc_channel_credentials object. ---
A channel credentials object represents a way to authenticate a client on a
@ -165,6 +240,24 @@ typedef void (*grpc_credentials_plugin_metadata_cb)(
void *user_data, const grpc_metadata *creds_md, size_t num_creds_md,
grpc_status_code status, const char *error_details);
/* Context that can be used by metadata credentials plugin in order to create
auth related metadata. */
typedef struct {
/* The fully qualifed service url. */
const char *service_url;
/* The method name of the RPC being called (not fully qualified).
The fully qualified method name can be built from the service_url:
full_qualified_method_name = ctx->service_url + '/' + ctx->method_name. */
const char *method_name;
/* The auth_context of the channel which gives the server's identity. */
const grpc_auth_context *channel_auth_context;
/* Reserved for future use. */
void *reserved;
} grpc_auth_metadata_context;
/* grpc_metadata_credentials plugin is an API user provided structure used to
create grpc_credentials objects that can be set on a channel (composed) or
a call. See grpc_credentials_metadata_create_from_plugin below.
@ -172,11 +265,11 @@ typedef void (*grpc_credentials_plugin_metadata_cb)(
every call in scope for the credentials created from it. */
typedef struct {
/* The implementation of this method has to be non-blocking.
- service_url is the fully qualified URL that the client stack is
connecting to.
- context is the information that can be used by the plugin to create auth
metadata.
- cb is the callback that needs to be called when the metadata is ready.
- user_data needs to be passed as the first parameter of the callback. */
void (*get_metadata)(void *state, const char *service_url,
void (*get_metadata)(void *state, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb, void *user_data);
/* Destroys the plugin state. */
@ -184,6 +277,9 @@ typedef struct {
/* State that will be set as the first parameter of the methods above. */
void *state;
/* Type of credentials that this plugin is implementing. */
const char *type;
} grpc_metadata_credentials_plugin;
/* Creates a credentials object from a plugin. */
@ -239,81 +335,6 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_call_credentials *creds);
/* --- Authentication Context. --- */
#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
typedef struct grpc_auth_context grpc_auth_context;
typedef struct grpc_auth_property_iterator {
const grpc_auth_context *ctx;
size_t index;
const char *name;
} grpc_auth_property_iterator;
/* value, if not NULL, is guaranteed to be NULL terminated. */
typedef struct grpc_auth_property {
char *name;
char *value;
size_t value_length;
} grpc_auth_property;
/* Returns NULL when the iterator is at the end. */
const grpc_auth_property *grpc_auth_property_iterator_next(
grpc_auth_property_iterator *it);
/* Iterates over the auth context. */
grpc_auth_property_iterator grpc_auth_context_property_iterator(
const grpc_auth_context *ctx);
/* Gets the peer identity. Returns an empty iterator (first _next will return
NULL) if the peer is not authenticated. */
grpc_auth_property_iterator grpc_auth_context_peer_identity(
const grpc_auth_context *ctx);
/* Finds a property in the context. May return an empty iterator (first _next
will return NULL) if no property with this name was found in the context. */
grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
const grpc_auth_context *ctx, const char *name);
/* Gets the name of the property that indicates the peer identity. Will return
NULL if the peer is not authenticated. */
const char *grpc_auth_context_peer_identity_property_name(
const grpc_auth_context *ctx);
/* Returns 1 if the peer is authenticated, 0 otherwise. */
int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
/* Gets the auth context from the call. Caller needs to call
grpc_auth_context_release on the returned context. */
grpc_auth_context *grpc_call_auth_context(grpc_call *call);
/* Releases the auth context returned from grpc_call_auth_context. */
void grpc_auth_context_release(grpc_auth_context *context);
/* --
The following auth context methods should only be called by a server metadata
processor to set properties extracted from auth metadata.
-- */
/* Add a property. */
void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
const char *value, size_t value_length);
/* Add a C string property. */
void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
const char *name,
const char *value);
/* Sets the property name. Returns 1 if successful or 0 in case of failure
(which means that no property with this name exists). */
int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
const char *name);
/* --- Auth Metadata Processing --- */
/* Callback function that is called when the metadata processing is done.

@ -63,7 +63,7 @@ typedef struct {
int sent_initial_metadata;
gpr_uint8 security_context_set;
grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
char *service_url;
grpc_auth_metadata_context auth_md_context;
} call_data;
/* We can have a per-channel credentials. */
@ -76,11 +76,20 @@ typedef struct {
grpc_mdstr *status_key;
} channel_data;
static void reset_service_url(call_data *calld) {
if (calld->service_url != NULL) {
gpr_free(calld->service_url);
calld->service_url = NULL;
static void reset_auth_metadata_context(
grpc_auth_metadata_context *auth_md_context) {
if (auth_md_context->service_url != NULL) {
gpr_free((char *)auth_md_context->service_url);
auth_md_context->service_url = NULL;
}
if (auth_md_context->method_name != NULL) {
gpr_free((char *)auth_md_context->method_name);
auth_md_context->method_name = NULL;
}
GRPC_AUTH_CONTEXT_UNREF(
(grpc_auth_context *)auth_md_context->channel_auth_context,
"grpc_auth_metadata_context");
auth_md_context->channel_auth_context = NULL;
}
static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
@ -101,7 +110,7 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_transport_stream_op *op = &calld->op;
grpc_metadata_batch *mdb;
size_t i;
reset_service_url(calld);
reset_auth_metadata_context(&calld->auth_md_context);
if (status != GRPC_CREDENTIALS_OK) {
bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
"Credentials failed to get metadata.");
@ -120,9 +129,13 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_call_next_op(exec_ctx, elem, op);
}
void build_service_url(const char *url_scheme, call_data *calld) {
void build_auth_metadata_context(grpc_security_connector *sc,
call_data *calld) {
char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
char *last_slash = strrchr(service, '/');
char *method_name = NULL;
char *service_url = NULL;
reset_auth_metadata_context(&calld->auth_md_context);
if (last_slash == NULL) {
gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
service[0] = '\0';
@ -131,11 +144,16 @@ void build_service_url(const char *url_scheme, call_data *calld) {
service[1] = '\0';
} else {
*last_slash = '\0';
method_name = gpr_strdup(last_slash + 1);
}
if (url_scheme == NULL) url_scheme = "";
reset_service_url(calld);
gpr_asprintf(&calld->service_url, "%s://%s%s", url_scheme,
if (method_name == NULL) method_name = gpr_strdup("");
gpr_asprintf(&service_url, "%s://%s%s",
sc->url_scheme == NULL ? "" : sc->url_scheme,
grpc_mdstr_as_c_string(calld->host), service);
calld->auth_md_context.service_url = service_url;
calld->auth_md_context.method_name = method_name;
calld->auth_md_context.channel_auth_context = GRPC_AUTH_CONTEXT_REF(
sc->auth_context, "grpc_auth_metadata_context");
gpr_free(service);
}
@ -169,12 +187,12 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx,
call_creds_has_md ? ctx->creds : channel_call_creds);
}
build_service_url(chand->security_connector->base.url_scheme, calld);
build_auth_metadata_context(&chand->security_connector->base, calld);
calld->op = *op; /* Copy op (originates from the caller's stack). */
GPR_ASSERT(calld->pollset);
grpc_call_credentials_get_request_metadata(exec_ctx, calld->creds,
calld->pollset, calld->service_url,
on_credentials_metadata, elem);
grpc_call_credentials_get_request_metadata(
exec_ctx, calld->creds, calld->pollset, calld->auth_md_context,
on_credentials_metadata, elem);
}
static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
@ -297,7 +315,7 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
if (calld->method != NULL) {
GRPC_MDSTR_UNREF(calld->method);
}
reset_service_url(calld);
reset_auth_metadata_context(&calld->auth_md_context);
}
/* Constructor for channel_data */

@ -33,16 +33,16 @@
#include "src/core/security/credentials.h"
#include <string.h>
#include <stdio.h>
#include <string.h>
#include "src/core/channel/channel_args.h"
#include "src/core/channel/http_client_filter.h"
#include "src/core/json/json.h"
#include "src/core/httpcli/httpcli.h"
#include "src/core/iomgr/iomgr.h"
#include "src/core/surface/api_trace.h"
#include "src/core/json/json.h"
#include "src/core/support/string.h"
#include "src/core/surface/api_trace.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -117,15 +117,16 @@ void grpc_call_credentials_release(grpc_call_credentials *creds) {
}
void grpc_call_credentials_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_pollset *pollset, grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb, void *user_data) {
if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
if (cb != NULL) {
cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
}
return;
}
creds->vtable->get_request_metadata(exec_ctx, creds, pollset, service_url, cb,
creds->vtable->get_request_metadata(exec_ctx, creds, pollset, context, cb,
user_data);
}
@ -207,8 +208,7 @@ grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) {
return arg;
}
grpc_server_credentials *grpc_server_credentials_from_arg(
const grpc_arg *arg) {
grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg) {
if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL;
if (arg->type != GRPC_ARG_POINTER) {
gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
@ -424,9 +424,12 @@ static void jwt_destruct(grpc_call_credentials *creds) {
gpr_mu_destroy(&c->cache_mu);
}
static void jwt_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_service_account_jwt_access_credentials *c =
(grpc_service_account_jwt_access_credentials *)creds;
gpr_timespec refresh_threshold = gpr_time_from_seconds(
@ -437,7 +440,7 @@ static void jwt_get_request_metadata(
{
gpr_mu_lock(&c->cache_mu);
if (c->cached.service_url != NULL &&
strcmp(c->cached.service_url, service_url) == 0 &&
strcmp(c->cached.service_url, context.service_url) == 0 &&
c->cached.jwt_md != NULL &&
(gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
gpr_now(GPR_CLOCK_REALTIME)),
@ -452,14 +455,15 @@ static void jwt_get_request_metadata(
/* Generate a new jwt. */
gpr_mu_lock(&c->cache_mu);
jwt_reset_cache(c);
jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url,
c->jwt_lifetime, NULL);
if (jwt != NULL) {
char *md_value;
gpr_asprintf(&md_value, "Bearer %s", jwt);
gpr_free(jwt);
c->cached.jwt_expiration =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
c->cached.service_url = gpr_strdup(service_url);
c->cached.service_url = gpr_strdup(context.service_url);
c->cached.jwt_md = grpc_credentials_md_store_create(1);
grpc_credentials_md_store_add_cstrings(
c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
@ -644,7 +648,7 @@ static void on_oauth2_token_fetcher_http_response(
static void oauth2_token_fetcher_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_pollset *pollset, const char *service_url,
grpc_pollset *pollset, grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb, void *user_data) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
@ -800,8 +804,9 @@ static void on_simulated_token_fetch_done(void *user_data) {
}
static void md_only_test_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_pollset *pollset, grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb, void *user_data) {
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
if (c->is_async) {
@ -839,8 +844,9 @@ static void access_token_destruct(grpc_call_credentials *creds) {
}
static void access_token_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_pollset *pollset, grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb, void *user_data) {
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
}
@ -921,7 +927,7 @@ typedef struct {
grpc_composite_call_credentials *composite_creds;
size_t creds_index;
grpc_credentials_md_store *md_elems;
char *service_url;
grpc_auth_metadata_context auth_md_context;
void *user_data;
grpc_pollset *pollset;
grpc_credentials_metadata_cb cb;
@ -939,7 +945,6 @@ static void composite_call_destruct(grpc_call_credentials *creds) {
static void composite_call_md_context_destroy(
grpc_composite_call_credentials_metadata_context *ctx) {
grpc_credentials_md_store_unref(ctx->md_elems);
if (ctx->service_url != NULL) gpr_free(ctx->service_url);
gpr_free(ctx);
}
@ -967,9 +972,9 @@ static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
grpc_call_credentials *inner_creds =
ctx->composite_creds->inner.creds_array[ctx->creds_index++];
grpc_call_credentials_get_request_metadata(exec_ctx, inner_creds,
ctx->pollset, ctx->service_url,
composite_call_metadata_cb, ctx);
grpc_call_credentials_get_request_metadata(
exec_ctx, inner_creds, ctx->pollset, ctx->auth_md_context,
composite_call_metadata_cb, ctx);
return;
}
@ -980,22 +985,23 @@ static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
}
static void composite_call_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_pollset *pollset, grpc_auth_metadata_context auth_md_context,
grpc_credentials_metadata_cb cb, void *user_data) {
grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
grpc_composite_call_credentials_metadata_context *ctx;
ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
ctx->service_url = gpr_strdup(service_url);
ctx->auth_md_context = auth_md_context;
ctx->user_data = user_data;
ctx->cb = cb;
ctx->composite_creds = c;
ctx->pollset = pollset;
ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
grpc_call_credentials_get_request_metadata(
exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset, service_url,
composite_call_metadata_cb, ctx);
exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset,
auth_md_context, composite_call_metadata_cb, ctx);
}
static grpc_call_credentials_vtable composite_call_credentials_vtable = {
@ -1089,7 +1095,7 @@ static void iam_destruct(grpc_call_credentials *creds) {
static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
@ -1098,7 +1104,7 @@ static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
}
static grpc_call_credentials_vtable iam_vtable = {iam_destruct,
iam_get_request_metadata};
iam_get_request_metadata};
grpc_call_credentials *grpc_google_iam_credentials_create(
const char *token, const char *authority_selector, void *reserved) {
@ -1178,7 +1184,7 @@ static void plugin_md_request_metadata_ready(void *request,
static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
@ -1187,7 +1193,7 @@ static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
memset(request, 0, sizeof(*request));
request->user_data = user_data;
request->cb = cb;
c->plugin.get_metadata(c->plugin.state, service_url,
c->plugin.get_metadata(c->plugin.state, context,
plugin_md_request_metadata_ready, request);
} else {
cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
@ -1204,7 +1210,7 @@ grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
(reserved));
GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(*c));
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN;
c->base.type = plugin.type;
c->base.vtable = &plugin_vtable;
gpr_ref_init(&c->base.refcount, 1);
c->plugin = plugin;

@ -59,7 +59,6 @@ typedef enum {
"FakeTransportSecurity"
#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
#define GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
#define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam"
#define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite"
@ -162,7 +161,7 @@ typedef struct {
void (*destruct)(grpc_call_credentials *c);
void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *c, grpc_pollset *pollset,
const char *service_url,
grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb,
void *user_data);
} grpc_call_credentials_vtable;
@ -178,7 +177,7 @@ void grpc_call_credentials_unref(grpc_call_credentials *creds);
void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb,
void *user_data);

@ -160,7 +160,7 @@ void MetadataCredentialsPluginWrapper::Destroy(void* wrapper) {
}
void MetadataCredentialsPluginWrapper::GetMetadata(
void* wrapper, const char* service_url,
void* wrapper, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb, void* user_data) {
GPR_ASSERT(wrapper);
MetadataCredentialsPluginWrapper* w =
@ -172,9 +172,9 @@ void MetadataCredentialsPluginWrapper::GetMetadata(
if (w->plugin_->IsBlocking()) {
w->thread_pool_->Add(
std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w,
service_url, cb, user_data));
context.service_url, cb, user_data));
} else {
w->InvokePlugin(service_url, cb, user_data);
w->InvokePlugin(context.service_url, cb, user_data);
}
}
@ -208,7 +208,7 @@ std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
new MetadataCredentialsPluginWrapper(std::move(plugin));
grpc_metadata_credentials_plugin c_plugin = {
MetadataCredentialsPluginWrapper::GetMetadata,
MetadataCredentialsPluginWrapper::Destroy, wrapper};
MetadataCredentialsPluginWrapper::Destroy, wrapper, ""};
return WrapCallCredentials(
grpc_metadata_credentials_create_from_plugin(c_plugin, nullptr));
}

@ -80,7 +80,7 @@ class SecureCallCredentials GRPC_FINAL : public CallCredentials {
class MetadataCredentialsPluginWrapper GRPC_FINAL {
public:
static void Destroy(void* wrapper);
static void GetMetadata(void* wrapper, const char* service_url,
static void GetMetadata(void* wrapper, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void* user_data);

@ -930,11 +930,12 @@ typedef void(GPR_CALLTYPE *grpcsharp_metadata_interceptor_func)(
void *state, const char *service_url, grpc_credentials_plugin_metadata_cb cb,
void *user_data, gpr_int32 is_destroy);
static void grpcsharp_get_metadata_handler(void *state, const char *service_url,
grpc_credentials_plugin_metadata_cb cb, void *user_data) {
static void grpcsharp_get_metadata_handler(
void *state, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb, void *user_data) {
grpcsharp_metadata_interceptor_func interceptor =
(grpcsharp_metadata_interceptor_func)(gpr_intptr)state;
interceptor(state, service_url, cb, user_data, 0);
interceptor(state, context.service_url, cb, user_data, 0);
}
static void grpcsharp_metadata_credentials_destroy_handler(void *state) {
@ -949,6 +950,7 @@ GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_cr
plugin.get_metadata = grpcsharp_get_metadata_handler;
plugin.destroy = grpcsharp_metadata_credentials_destroy_handler;
plugin.state = (void*)(gpr_intptr)metadata_interceptor;
plugin.type = "";
return grpc_metadata_credentials_create_from_plugin(plugin, NULL);
}

@ -162,6 +162,7 @@ NAN_METHOD(CallCredentials::CreateFromPlugin) {
plugin.get_metadata = plugin_get_metadata;
plugin.destroy = plugin_destroy_state;
plugin.state = reinterpret_cast<void*>(state);
plugin.type = "";
grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin(
plugin, NULL);
info.GetReturnValue().Set(WrapStruct(creds));
@ -225,7 +226,7 @@ NAUV_WORK_CB(SendPluginCallback) {
uv_close((uv_handle_t *)async, (uv_close_cb)free);
}
void plugin_get_metadata(void *state, const char *service_url,
void plugin_get_metadata(void *state, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data) {
uv_async_t *async = static_cast<uv_async_t*>(malloc(sizeof(uv_async_t)));
@ -234,7 +235,7 @@ void plugin_get_metadata(void *state, const char *service_url,
SendPluginCallback);
plugin_callback_data *data = new plugin_callback_data;
data->state = reinterpret_cast<plugin_state*>(state);
data->service_url = service_url;
data->service_url = context.service_url;
data->cb = cb;
data->user_data = user_data;
async->data = data;

@ -84,7 +84,7 @@ typedef struct plugin_callback_data {
void *user_data;
} plugin_callback_data;
void plugin_get_metadata(void *state, const char *service_url,
void plugin_get_metadata(void *state, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data);

@ -126,6 +126,8 @@ static const char test_signed_jwt[] =
static const char test_service_url[] = "https://foo.com/foo.v1";
static const char other_test_service_url[] = "https://bar.com/bar.v1";
static const char test_method[] = "ThisIsNotAMethod";
/* -- Utils. -- */
static char *test_json_key_str(void) {
@ -352,9 +354,10 @@ static void test_google_iam_creds(void) {
grpc_call_credentials *creds = grpc_google_iam_credentials_create(
test_google_iam_authorization_token, test_google_iam_authority_selector,
NULL);
grpc_call_credentials_get_request_metadata(&exec_ctx, creds, NULL,
test_service_url,
check_google_iam_metadata, creds);
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
grpc_call_credentials_get_request_metadata(
&exec_ctx, creds, NULL, auth_md_ctx, check_google_iam_metadata, creds);
grpc_exec_ctx_finish(&exec_ctx);
}
@ -375,9 +378,11 @@ static void test_access_token_creds(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_call_credentials *creds =
grpc_access_token_credentials_create("blah", NULL);
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
grpc_call_credentials_get_request_metadata(
&exec_ctx, creds, NULL, test_service_url, check_access_token_metadata,
&exec_ctx, creds, NULL, auth_md_ctx, check_access_token_metadata,
creds);
grpc_exec_ctx_finish(&exec_ctx);
}
@ -430,6 +435,8 @@ static void check_oauth2_google_iam_composite_metadata(
static void test_oauth2_google_iam_composite_creds(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
const grpc_call_credentials_array *creds_array;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
"authorization", test_oauth2_bearer_token, 0);
grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create(
@ -449,7 +456,7 @@ static void test_oauth2_google_iam_composite_creds(void) {
GPR_ASSERT(strcmp(creds_array->creds_array[1]->type,
GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0);
grpc_call_credentials_get_request_metadata(
&exec_ctx, composite_creds, NULL, test_service_url,
&exec_ctx, composite_creds, NULL, auth_md_ctx,
check_oauth2_google_iam_composite_metadata, composite_creds);
grpc_exec_ctx_finish(&exec_ctx);
}
@ -576,12 +583,14 @@ static void test_compute_engine_creds_success(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_call_credentials *compute_engine_creds =
grpc_google_compute_engine_credentials_create(NULL);
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
/* First request: http get should be called. */
grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
httpcli_post_should_not_be_called);
grpc_call_credentials_get_request_metadata(
&exec_ctx, compute_engine_creds, NULL, test_service_url,
&exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
@ -589,7 +598,7 @@ static void test_compute_engine_creds_success(void) {
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
grpc_call_credentials_get_request_metadata(
&exec_ctx, compute_engine_creds, NULL, test_service_url,
&exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_finish(&exec_ctx);
@ -599,12 +608,14 @@ static void test_compute_engine_creds_success(void) {
static void test_compute_engine_creds_failure(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
grpc_call_credentials *compute_engine_creds =
grpc_google_compute_engine_credentials_create(NULL);
grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override,
httpcli_post_should_not_be_called);
grpc_call_credentials_get_request_metadata(
&exec_ctx, compute_engine_creds, NULL, test_service_url,
&exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
grpc_call_credentials_unref(compute_engine_creds);
grpc_httpcli_set_override(NULL, NULL);
@ -656,6 +667,8 @@ static int refresh_token_httpcli_post_failure(
static void test_refresh_token_creds_success(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
grpc_call_credentials *refresh_token_creds =
grpc_google_refresh_token_credentials_create(test_refresh_token_str,
NULL);
@ -664,7 +677,7 @@ static void test_refresh_token_creds_success(void) {
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
refresh_token_httpcli_post_success);
grpc_call_credentials_get_request_metadata(
&exec_ctx, refresh_token_creds, NULL, test_service_url,
&exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
@ -672,7 +685,7 @@ static void test_refresh_token_creds_success(void) {
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
grpc_call_credentials_get_request_metadata(
&exec_ctx, refresh_token_creds, NULL, test_service_url,
&exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
@ -683,13 +696,15 @@ static void test_refresh_token_creds_success(void) {
static void test_refresh_token_creds_failure(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
grpc_call_credentials *refresh_token_creds =
grpc_google_refresh_token_credentials_create(test_refresh_token_str,
NULL);
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
refresh_token_httpcli_post_failure);
grpc_call_credentials_get_request_metadata(
&exec_ctx, refresh_token_creds, NULL, test_service_url,
&exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
grpc_call_credentials_unref(refresh_token_creds);
grpc_httpcli_set_override(NULL, NULL);
@ -772,6 +787,8 @@ static void on_jwt_creds_get_metadata_failure(grpc_exec_ctx *exec_ctx,
static void test_jwt_creds_success(void) {
char *json_key_string = test_json_key_str();
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
grpc_call_credentials *jwt_creds =
grpc_service_account_jwt_access_credentials_create(
json_key_string, grpc_max_auth_token_lifetime, NULL);
@ -779,7 +796,7 @@ static void test_jwt_creds_success(void) {
/* First request: jwt_encode_and_sign should be called. */
grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
grpc_call_credentials_get_request_metadata(
&exec_ctx, jwt_creds, NULL, test_service_url,
&exec_ctx, jwt_creds, NULL, auth_md_ctx,
on_jwt_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
@ -787,15 +804,16 @@ static void test_jwt_creds_success(void) {
grpc_jwt_encode_and_sign_set_override(
encode_and_sign_jwt_should_not_be_called);
grpc_call_credentials_get_request_metadata(
&exec_ctx, jwt_creds, NULL, test_service_url,
&exec_ctx, jwt_creds, NULL, auth_md_ctx,
on_jwt_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
/* Third request: Different service url so jwt_encode_and_sign should be
called again (no caching). */
auth_md_ctx.service_url = other_test_service_url;
grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
grpc_call_credentials_get_request_metadata(
&exec_ctx, jwt_creds, NULL, other_test_service_url,
&exec_ctx, jwt_creds, NULL, auth_md_ctx,
on_jwt_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
@ -807,13 +825,15 @@ static void test_jwt_creds_success(void) {
static void test_jwt_creds_signing_failure(void) {
char *json_key_string = test_json_key_str();
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
grpc_call_credentials *jwt_creds =
grpc_service_account_jwt_access_credentials_create(
json_key_string, grpc_max_auth_token_lifetime, NULL);
grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
grpc_call_credentials_get_request_metadata(
&exec_ctx, jwt_creds, NULL, test_service_url,
&exec_ctx, jwt_creds, NULL, auth_md_ctx,
on_jwt_creds_get_metadata_failure, (void *)test_user_data);
gpr_free(json_key_string);
@ -884,13 +904,17 @@ typedef struct {
static const plugin_metadata plugin_md[] = {{"foo", "bar"}, {"hi", "there"}};
static void plugin_get_metadata_success(void *state, const char *service_url,
static void plugin_get_metadata_success(void *state,
grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data) {
size_t i;
grpc_metadata md[GPR_ARRAY_SIZE(plugin_md)];
plugin_state *s = (plugin_state *)state;
GPR_ASSERT(strcmp(service_url, test_service_url) == 0);
GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
GPR_ASSERT(context.channel_auth_context == NULL);
GPR_ASSERT(context.reserved == NULL);
*s = PLUGIN_GET_METADATA_CALLED_STATE;
for (i = 0; i < GPR_ARRAY_SIZE(plugin_md); i++) {
memset(&md[i], 0, sizeof(grpc_metadata));
@ -901,11 +925,15 @@ static void plugin_get_metadata_success(void *state, const char *service_url,
cb(user_data, md, GPR_ARRAY_SIZE(md), GRPC_STATUS_OK, NULL);
}
static void plugin_get_metadata_failure(void *state, const char *service_url,
static void plugin_get_metadata_failure(void *state,
grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data) {
plugin_state *s = (plugin_state *)state;
GPR_ASSERT(strcmp(service_url, test_service_url) == 0);
GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
GPR_ASSERT(context.channel_auth_context == NULL);
GPR_ASSERT(context.reserved == NULL);
*s = PLUGIN_GET_METADATA_CALLED_STATE;
cb(user_data, NULL, 0, GRPC_STATUS_UNAUTHENTICATED,
"Could not get metadata for plugin.");
@ -943,6 +971,8 @@ static void test_metadata_plugin_success(void) {
plugin_state state = PLUGIN_INITIAL_STATE;
grpc_metadata_credentials_plugin plugin;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
plugin.state = &state;
plugin.get_metadata = plugin_get_metadata_success;
@ -951,7 +981,7 @@ static void test_metadata_plugin_success(void) {
creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL);
GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
grpc_call_credentials_get_request_metadata(
&exec_ctx, creds, NULL, test_service_url,
&exec_ctx, creds, NULL, auth_md_ctx,
on_plugin_metadata_received_success, NULL);
GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
grpc_call_credentials_release(creds);
@ -964,6 +994,8 @@ static void test_metadata_plugin_failure(void) {
plugin_state state = PLUGIN_INITIAL_STATE;
grpc_metadata_credentials_plugin plugin;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
NULL};
plugin.state = &state;
plugin.get_metadata = plugin_get_metadata_failure;
@ -972,7 +1004,7 @@ static void test_metadata_plugin_failure(void) {
creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL);
GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
grpc_call_credentials_get_request_metadata(
&exec_ctx, creds, NULL, test_service_url,
&exec_ctx, creds, NULL, auth_md_ctx,
on_plugin_metadata_received_failure, NULL);
GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
grpc_call_credentials_release(creds);

@ -80,13 +80,15 @@ char *grpc_test_fetch_oauth2_token_with_credentials(
oauth2_request request;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_closure do_nothing_closure;
grpc_auth_metadata_context null_ctx = {"", "", NULL, NULL};
grpc_pollset_init(&request.pollset);
request.is_done = 0;
grpc_closure_init(&do_nothing_closure, do_nothing, NULL);
grpc_call_credentials_get_request_metadata(&exec_ctx, creds, &request.pollset,
"", on_oauth2_response, &request);
null_ctx, on_oauth2_response, &request);
grpc_exec_ctx_finish(&exec_ctx);

@ -74,10 +74,13 @@ int main(int argc, char **argv) {
synchronizer sync;
grpc_channel_credentials *creds = NULL;
char *service_url = "https://test.foo.google.com/Foo";
grpc_auth_metadata_context context;
gpr_cmdline *cl = gpr_cmdline_create("print_google_default_creds_token");
gpr_cmdline_add_string(cl, "service_url",
"Service URL for the token request.", &service_url);
gpr_cmdline_parse(cl, argc, argv);
memset(&context, 0, sizeof(context));
context.service_url = service_url;
grpc_init();
@ -93,7 +96,7 @@ int main(int argc, char **argv) {
grpc_call_credentials_get_request_metadata(
&exec_ctx, ((grpc_composite_channel_credentials *)creds)->call_creds,
&sync.pollset, service_url, on_metadata_response, &sync);
&sync.pollset, context, on_metadata_response, &sync);
gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
while (!sync.is_done) {

Loading…
Cancel
Save