Merge branch 'auth_md_processor' of github.com:jboeuf/grpc into complain-with-both-passion-and-meaning
This commit is contained in:
commit
be043d9ce7
|
|
@ -199,8 +199,6 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call,
|
|||
|
||||
/* --- Authentication Context. --- */
|
||||
|
||||
/* TODO(jboeuf): Define some well-known property names. */
|
||||
|
||||
#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
|
||||
#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
|
||||
|
||||
|
|
@ -255,6 +253,57 @@ 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 that will augment the channel auth context (see below).
|
||||
-- */
|
||||
|
||||
/* Creates a new auth context based off a chained context. */
|
||||
grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained);
|
||||
|
||||
/* 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 --- */
|
||||
|
||||
/* Opaque data structure useful for processors defined in core. */
|
||||
typedef struct grpc_auth_ticket grpc_auth_ticket;
|
||||
|
||||
/* Callback function that is called when the metadata processing is done.
|
||||
success is 1 if processing succeeded, 0 otherwise. */
|
||||
typedef void (*grpc_process_auth_metadata_done_cb)(
|
||||
void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md,
|
||||
int success, grpc_auth_context *result);
|
||||
|
||||
/* Pluggable server-side metadata processor object */
|
||||
typedef struct {
|
||||
void (*process)(void *state, grpc_auth_ticket *ticket,
|
||||
grpc_auth_context *channel_ctx, const grpc_metadata *md,
|
||||
size_t md_count, grpc_process_auth_metadata_done_cb cb,
|
||||
void *user_data);
|
||||
void *state;
|
||||
} grpc_auth_metadata_processor;
|
||||
|
||||
/* XXXX: this is a temporarty interface. Please do NOT use.
|
||||
This function will be moved to the server_credentials in a subsequent
|
||||
pull request. XXXX
|
||||
|
||||
Registration function for metadata processing.
|
||||
Should be called before the server is started. */
|
||||
void grpc_server_register_auth_metadata_processor(
|
||||
grpc_auth_metadata_processor processor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -765,19 +765,19 @@ grpc_credentials *grpc_refresh_token_credentials_create(
|
|||
grpc_auth_refresh_token_create_from_string(json_refresh_token));
|
||||
}
|
||||
|
||||
/* -- Fake Oauth2 credentials. -- */
|
||||
/* -- Metadata-only credentials. -- */
|
||||
|
||||
static void fake_oauth2_destroy(grpc_credentials *creds) {
|
||||
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds;
|
||||
grpc_credentials_md_store_unref(c->access_token_md);
|
||||
static void md_only_test_destroy(grpc_credentials *creds) {
|
||||
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
|
||||
grpc_credentials_md_store_unref(c->md_store);
|
||||
gpr_free(c);
|
||||
}
|
||||
|
||||
static int fake_oauth2_has_request_metadata(const grpc_credentials *creds) {
|
||||
static int md_only_test_has_request_metadata(const grpc_credentials *creds) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fake_oauth2_has_request_metadata_only(
|
||||
static int md_only_test_has_request_metadata_only(
|
||||
const grpc_credentials *creds) {
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -785,19 +785,19 @@ static int fake_oauth2_has_request_metadata_only(
|
|||
void on_simulated_token_fetch_done(void *user_data, int success) {
|
||||
grpc_credentials_metadata_request *r =
|
||||
(grpc_credentials_metadata_request *)user_data;
|
||||
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)r->creds;
|
||||
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
|
||||
GPR_ASSERT(success);
|
||||
r->cb(r->user_data, c->access_token_md->entries,
|
||||
c->access_token_md->num_entries, GRPC_CREDENTIALS_OK);
|
||||
r->cb(r->user_data, c->md_store->entries,
|
||||
c->md_store->num_entries, GRPC_CREDENTIALS_OK);
|
||||
grpc_credentials_metadata_request_destroy(r);
|
||||
}
|
||||
|
||||
static void fake_oauth2_get_request_metadata(grpc_credentials *creds,
|
||||
static void md_only_test_get_request_metadata(grpc_credentials *creds,
|
||||
grpc_pollset *pollset,
|
||||
const char *service_url,
|
||||
grpc_credentials_metadata_cb cb,
|
||||
void *user_data) {
|
||||
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds;
|
||||
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
|
||||
|
||||
if (c->is_async) {
|
||||
grpc_credentials_metadata_request *cb_arg =
|
||||
|
|
@ -806,26 +806,26 @@ static void fake_oauth2_get_request_metadata(grpc_credentials *creds,
|
|||
on_simulated_token_fetch_done, cb_arg);
|
||||
grpc_iomgr_add_callback(cb_arg->on_simulated_token_fetch_done_closure);
|
||||
} else {
|
||||
cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
|
||||
cb(user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
|
||||
}
|
||||
}
|
||||
|
||||
static grpc_credentials_vtable fake_oauth2_vtable = {
|
||||
fake_oauth2_destroy, fake_oauth2_has_request_metadata,
|
||||
fake_oauth2_has_request_metadata_only, fake_oauth2_get_request_metadata,
|
||||
static grpc_credentials_vtable md_only_test_vtable = {
|
||||
md_only_test_destroy, md_only_test_has_request_metadata,
|
||||
md_only_test_has_request_metadata_only, md_only_test_get_request_metadata,
|
||||
NULL};
|
||||
|
||||
grpc_credentials *grpc_fake_oauth2_credentials_create(
|
||||
const char *token_md_value, int is_async) {
|
||||
grpc_fake_oauth2_credentials *c =
|
||||
gpr_malloc(sizeof(grpc_fake_oauth2_credentials));
|
||||
memset(c, 0, sizeof(grpc_fake_oauth2_credentials));
|
||||
grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
|
||||
const char *md_value,
|
||||
int is_async) {
|
||||
grpc_md_only_test_credentials *c =
|
||||
gpr_malloc(sizeof(grpc_md_only_test_credentials));
|
||||
memset(c, 0, sizeof(grpc_md_only_test_credentials));
|
||||
c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
|
||||
c->base.vtable = &fake_oauth2_vtable;
|
||||
c->base.vtable = &md_only_test_vtable;
|
||||
gpr_ref_init(&c->base.refcount, 1);
|
||||
c->access_token_md = grpc_credentials_md_store_create(1);
|
||||
grpc_credentials_md_store_add_cstrings(
|
||||
c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
|
||||
c->md_store = grpc_credentials_md_store_create(1);
|
||||
grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value);
|
||||
c->is_async = is_async;
|
||||
return &c->base;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,9 +190,10 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response(
|
|||
grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime);
|
||||
void grpc_flush_cached_google_default_credentials(void);
|
||||
|
||||
/* Simulates an oauth2 token fetch with the specified value for testing. */
|
||||
grpc_credentials *grpc_fake_oauth2_credentials_create(
|
||||
const char *token_md_value, int is_async);
|
||||
/* Metadata-only credentials with the specified key and value where
|
||||
asynchronicity can be simulated for testing. */
|
||||
grpc_credentials *grpc_md_only_test_credentials_create(
|
||||
const char *md_key, const char *md_value, int is_async);
|
||||
|
||||
/* Private constructor for jwt credentials from an already parsed json key.
|
||||
Takes ownership of the key. */
|
||||
|
|
@ -297,13 +298,13 @@ typedef struct {
|
|||
grpc_credentials_md_store *access_token_md;
|
||||
} grpc_access_token_credentials;
|
||||
|
||||
/* -- Fake Oauth2 credentials. -- */
|
||||
/* -- Metadata-only Test credentials. -- */
|
||||
|
||||
typedef struct {
|
||||
grpc_credentials base;
|
||||
grpc_credentials_md_store *access_token_md;
|
||||
grpc_credentials_md_store *md_store;
|
||||
int is_async;
|
||||
} grpc_fake_oauth2_credentials;
|
||||
} grpc_md_only_test_credentials;
|
||||
|
||||
/* -- IAM credentials. -- */
|
||||
|
||||
|
|
|
|||
|
|
@ -263,9 +263,9 @@ static grpc_security_status fake_check_peer(grpc_security_connector *sc,
|
|||
goto end;
|
||||
}
|
||||
GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector");
|
||||
sc->auth_context = grpc_auth_context_create(NULL, 1);
|
||||
sc->auth_context->properties[0] = grpc_auth_property_init_from_cstring(
|
||||
GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
|
||||
sc->auth_context = grpc_auth_context_create(NULL);
|
||||
grpc_auth_context_add_cstring_property(
|
||||
sc->auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
|
||||
GRPC_FAKE_TRANSPORT_SECURITY_TYPE);
|
||||
|
||||
end:
|
||||
|
|
@ -409,31 +409,35 @@ static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) {
|
|||
grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer) {
|
||||
size_t i;
|
||||
grpc_auth_context *ctx = NULL;
|
||||
const char *peer_identity_property_name = NULL;
|
||||
|
||||
/* The caller has checked the certificate type property. */
|
||||
GPR_ASSERT(peer->property_count >= 1);
|
||||
ctx = grpc_auth_context_create(NULL, peer->property_count);
|
||||
ctx->properties[0] = grpc_auth_property_init_from_cstring(
|
||||
GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
|
||||
ctx = grpc_auth_context_create(NULL);
|
||||
grpc_auth_context_add_cstring_property(
|
||||
ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
|
||||
GRPC_SSL_TRANSPORT_SECURITY_TYPE);
|
||||
ctx->property_count = 1;
|
||||
for (i = 0; i < peer->property_count; i++) {
|
||||
const tsi_peer_property *prop = &peer->properties[i];
|
||||
if (prop->name == NULL) continue;
|
||||
if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
|
||||
/* If there is no subject alt name, have the CN as the identity. */
|
||||
if (ctx->peer_identity_property_name == NULL) {
|
||||
ctx->peer_identity_property_name = GRPC_X509_CN_PROPERTY_NAME;
|
||||
if (peer_identity_property_name == NULL) {
|
||||
peer_identity_property_name = GRPC_X509_CN_PROPERTY_NAME;
|
||||
}
|
||||
ctx->properties[ctx->property_count++] = grpc_auth_property_init(
|
||||
GRPC_X509_CN_PROPERTY_NAME, prop->value.data, prop->value.length);
|
||||
grpc_auth_context_add_property(ctx, GRPC_X509_CN_PROPERTY_NAME,
|
||||
prop->value.data, prop->value.length);
|
||||
} else if (strcmp(prop->name,
|
||||
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
|
||||
ctx->peer_identity_property_name = GRPC_X509_SAN_PROPERTY_NAME;
|
||||
ctx->properties[ctx->property_count++] = grpc_auth_property_init(
|
||||
GRPC_X509_SAN_PROPERTY_NAME, prop->value.data, prop->value.length);
|
||||
peer_identity_property_name = GRPC_X509_SAN_PROPERTY_NAME;
|
||||
grpc_auth_context_add_property(ctx, GRPC_X509_SAN_PROPERTY_NAME,
|
||||
prop->value.data, prop->value.length);
|
||||
}
|
||||
}
|
||||
if (peer_identity_property_name != NULL) {
|
||||
GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(
|
||||
ctx, peer_identity_property_name) == 1);
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,19 @@
|
|||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/string_util.h>
|
||||
|
||||
/* --- grpc_process_auth_metadata_func --- */
|
||||
|
||||
static grpc_auth_metadata_processor server_processor = {NULL, NULL};
|
||||
|
||||
grpc_auth_metadata_processor grpc_server_get_auth_metadata_processor(void) {
|
||||
return server_processor;
|
||||
}
|
||||
|
||||
void grpc_server_register_auth_metadata_processor(
|
||||
grpc_auth_metadata_processor processor) {
|
||||
server_processor = processor;
|
||||
}
|
||||
|
||||
/* --- grpc_call --- */
|
||||
|
||||
grpc_call_error grpc_call_set_credentials(grpc_call *call,
|
||||
|
|
@ -120,15 +133,15 @@ void grpc_server_security_context_destroy(void *ctx) {
|
|||
|
||||
static grpc_auth_property_iterator empty_iterator = {NULL, 0, NULL};
|
||||
|
||||
grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained,
|
||||
size_t property_count) {
|
||||
grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained) {
|
||||
grpc_auth_context *ctx = gpr_malloc(sizeof(grpc_auth_context));
|
||||
memset(ctx, 0, sizeof(grpc_auth_context));
|
||||
ctx->properties = gpr_malloc(property_count * sizeof(grpc_auth_property));
|
||||
memset(ctx->properties, 0, property_count * sizeof(grpc_auth_property));
|
||||
ctx->property_count = property_count;
|
||||
gpr_ref_init(&ctx->refcount, 1);
|
||||
if (chained != NULL) ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained");
|
||||
if (chained != NULL) {
|
||||
ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained");
|
||||
ctx->peer_identity_property_name =
|
||||
ctx->chained->peer_identity_property_name;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
|
@ -162,11 +175,11 @@ void grpc_auth_context_unref(grpc_auth_context *ctx) {
|
|||
if (gpr_unref(&ctx->refcount)) {
|
||||
size_t i;
|
||||
GRPC_AUTH_CONTEXT_UNREF(ctx->chained, "chained");
|
||||
if (ctx->properties != NULL) {
|
||||
for (i = 0; i < ctx->property_count; i++) {
|
||||
grpc_auth_property_reset(&ctx->properties[i]);
|
||||
if (ctx->properties.array != NULL) {
|
||||
for (i = 0; i < ctx->properties.count; i++) {
|
||||
grpc_auth_property_reset(&ctx->properties.array[i]);
|
||||
}
|
||||
gpr_free(ctx->properties);
|
||||
gpr_free(ctx->properties.array);
|
||||
}
|
||||
gpr_free(ctx);
|
||||
}
|
||||
|
|
@ -177,6 +190,20 @@ const char *grpc_auth_context_peer_identity_property_name(
|
|||
return ctx->peer_identity_property_name;
|
||||
}
|
||||
|
||||
int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
|
||||
const char *name) {
|
||||
grpc_auth_property_iterator it =
|
||||
grpc_auth_context_find_properties_by_name(ctx, name);
|
||||
const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it);
|
||||
if (prop == NULL) {
|
||||
gpr_log(GPR_ERROR, "Property name %s not found in auth context.",
|
||||
name != NULL ? name : "NULL");
|
||||
return 0;
|
||||
}
|
||||
ctx->peer_identity_property_name = prop->name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int grpc_auth_context_peer_is_authenticated(
|
||||
const grpc_auth_context *ctx) {
|
||||
return ctx->peer_identity_property_name == NULL ? 0 : 1;
|
||||
|
|
@ -193,16 +220,16 @@ grpc_auth_property_iterator grpc_auth_context_property_iterator(
|
|||
const grpc_auth_property *grpc_auth_property_iterator_next(
|
||||
grpc_auth_property_iterator *it) {
|
||||
if (it == NULL || it->ctx == NULL) return NULL;
|
||||
while (it->index == it->ctx->property_count) {
|
||||
while (it->index == it->ctx->properties.count) {
|
||||
if (it->ctx->chained == NULL) return NULL;
|
||||
it->ctx = it->ctx->chained;
|
||||
it->index = 0;
|
||||
}
|
||||
if (it->name == NULL) {
|
||||
return &it->ctx->properties[it->index++];
|
||||
return &it->ctx->properties.array[it->index++];
|
||||
} else {
|
||||
while (it->index < it->ctx->property_count) {
|
||||
const grpc_auth_property *prop = &it->ctx->properties[it->index++];
|
||||
while (it->index < it->ctx->properties.count) {
|
||||
const grpc_auth_property *prop = &it->ctx->properties.array[it->index++];
|
||||
GPR_ASSERT(prop->name != NULL);
|
||||
if (strcmp(it->name, prop->name) == 0) {
|
||||
return prop;
|
||||
|
|
@ -229,24 +256,37 @@ grpc_auth_property_iterator grpc_auth_context_peer_identity(
|
|||
ctx, ctx->peer_identity_property_name);
|
||||
}
|
||||
|
||||
grpc_auth_property grpc_auth_property_init_from_cstring(const char *name,
|
||||
const char *value) {
|
||||
grpc_auth_property prop;
|
||||
prop.name = gpr_strdup(name);
|
||||
prop.value = gpr_strdup(value);
|
||||
prop.value_length = strlen(value);
|
||||
return prop;
|
||||
static void ensure_auth_context_capacity(grpc_auth_context *ctx) {
|
||||
if (ctx->properties.count == ctx->properties.capacity) {
|
||||
ctx->properties.capacity =
|
||||
GPR_MAX(ctx->properties.capacity + 8, ctx->properties.capacity * 2);
|
||||
ctx->properties.array =
|
||||
gpr_realloc(ctx->properties.array,
|
||||
ctx->properties.capacity * sizeof(grpc_auth_property));
|
||||
}
|
||||
}
|
||||
|
||||
grpc_auth_property grpc_auth_property_init(const char *name, const char *value,
|
||||
size_t value_length) {
|
||||
grpc_auth_property prop;
|
||||
prop.name = gpr_strdup(name);
|
||||
prop.value = gpr_malloc(value_length + 1);
|
||||
memcpy(prop.value, value, value_length);
|
||||
prop.value[value_length] = '\0';
|
||||
prop.value_length = value_length;
|
||||
return prop;
|
||||
void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
|
||||
const char *value, size_t value_length) {
|
||||
grpc_auth_property *prop;
|
||||
ensure_auth_context_capacity(ctx);
|
||||
prop = &ctx->properties.array[ctx->properties.count++];
|
||||
prop->name = gpr_strdup(name);
|
||||
prop->value = gpr_malloc(value_length + 1);
|
||||
memcpy(prop->value, value, value_length);
|
||||
prop->value[value_length] = '\0';
|
||||
prop->value_length = value_length;
|
||||
}
|
||||
|
||||
void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
|
||||
const char *name,
|
||||
const char *value) {
|
||||
grpc_auth_property *prop;
|
||||
ensure_auth_context_capacity(ctx);
|
||||
prop = &ctx->properties.array[ctx->properties.count++];
|
||||
prop->name = gpr_strdup(name);
|
||||
prop->value = gpr_strdup(value);
|
||||
prop->value_length = strlen(value);
|
||||
}
|
||||
|
||||
void grpc_auth_property_reset(grpc_auth_property *property) {
|
||||
|
|
|
|||
|
|
@ -34,11 +34,13 @@
|
|||
#ifndef GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H
|
||||
#define GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H
|
||||
|
||||
#include "src/core/iomgr/pollset.h"
|
||||
#include "src/core/security/credentials.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* --- grpc_auth_ticket --- */
|
||||
struct grpc_auth_ticket {
|
||||
grpc_pollset *pollset;
|
||||
};
|
||||
|
||||
/* --- grpc_auth_context ---
|
||||
|
||||
|
|
@ -46,18 +48,19 @@ extern "C" {
|
|||
|
||||
/* Property names are always NULL terminated. */
|
||||
|
||||
typedef struct {
|
||||
grpc_auth_property *array;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} grpc_auth_property_array;
|
||||
|
||||
struct grpc_auth_context {
|
||||
struct grpc_auth_context *chained;
|
||||
grpc_auth_property *properties;
|
||||
size_t property_count;
|
||||
grpc_auth_property_array properties;
|
||||
gpr_refcount refcount;
|
||||
const char *peer_identity_property_name;
|
||||
};
|
||||
|
||||
/* Constructor. */
|
||||
grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained,
|
||||
size_t property_count);
|
||||
|
||||
/* Refcounting. */
|
||||
#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG
|
||||
#define GRPC_AUTH_CONTEXT_REF(p, r) \
|
||||
|
|
@ -76,12 +79,6 @@ grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy);
|
|||
void grpc_auth_context_unref(grpc_auth_context *policy);
|
||||
#endif
|
||||
|
||||
grpc_auth_property grpc_auth_property_init_from_cstring(const char *name,
|
||||
const char *value);
|
||||
|
||||
grpc_auth_property grpc_auth_property_init(const char *name, const char *value,
|
||||
size_t value_length);
|
||||
|
||||
void grpc_auth_property_reset(grpc_auth_property *property);
|
||||
|
||||
/* --- grpc_client_security_context ---
|
||||
|
|
@ -107,9 +104,9 @@ typedef struct {
|
|||
grpc_server_security_context *grpc_server_security_context_create(void);
|
||||
void grpc_server_security_context_destroy(void *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* --- Auth metadata processing. --- */
|
||||
|
||||
grpc_auth_metadata_processor grpc_server_get_auth_metadata_processor(void);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -31,20 +31,149 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "src/core/security/auth_filters.h"
|
||||
#include "src/core/security/security_connector.h"
|
||||
#include "src/core/security/security_context.h"
|
||||
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
typedef struct call_data {
|
||||
int unused; /* C89 requires at least one struct element */
|
||||
gpr_uint8 got_client_metadata;
|
||||
grpc_stream_op_buffer *recv_ops;
|
||||
/* Closure to call when finished with the auth_on_recv hook. */
|
||||
grpc_iomgr_closure *on_done_recv;
|
||||
/* Receive closures are chained: we inject this closure as the on_done_recv
|
||||
up-call on transport_op, and remember to call our on_done_recv member after
|
||||
handling it. */
|
||||
grpc_iomgr_closure auth_on_recv;
|
||||
grpc_transport_stream_op transport_op;
|
||||
const grpc_metadata *consumed_md;
|
||||
size_t num_consumed_md;
|
||||
grpc_stream_op *md_op;
|
||||
grpc_auth_context **call_auth_context;
|
||||
grpc_auth_ticket ticket;
|
||||
} call_data;
|
||||
|
||||
typedef struct channel_data {
|
||||
grpc_security_connector *security_connector;
|
||||
grpc_mdctx *mdctx;
|
||||
} channel_data;
|
||||
|
||||
static grpc_metadata_array metadata_batch_to_md_array(
|
||||
const grpc_metadata_batch *batch) {
|
||||
grpc_linked_mdelem *l;
|
||||
grpc_metadata_array result;
|
||||
grpc_metadata_array_init(&result);
|
||||
for (l = batch->list.head; l != NULL; l = l->next) {
|
||||
grpc_metadata *usr_md = NULL;
|
||||
grpc_mdelem *md = l->md;
|
||||
grpc_mdstr *key = md->key;
|
||||
grpc_mdstr *value = md->value;
|
||||
if (result.count == result.capacity) {
|
||||
result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2);
|
||||
result.metadata =
|
||||
gpr_realloc(result.metadata, result.capacity * sizeof(grpc_metadata));
|
||||
}
|
||||
usr_md = &result.metadata[result.count++];
|
||||
usr_md->key = grpc_mdstr_as_c_string(key);
|
||||
usr_md->value = grpc_mdstr_as_c_string(value);
|
||||
usr_md->value_length = GPR_SLICE_LENGTH(value->slice);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) {
|
||||
grpc_call_element *elem = user_data;
|
||||
call_data *calld = elem->call_data;
|
||||
size_t i;
|
||||
for (i = 0; i < calld->num_consumed_md; i++) {
|
||||
/* Maybe we could do a pointer comparison but we do not have any guarantee
|
||||
that the metadata processor used the same pointers for consumed_md in the
|
||||
callback. */
|
||||
if (memcmp(GPR_SLICE_START_PTR(md->key->slice), calld->consumed_md[i].key,
|
||||
GPR_SLICE_LENGTH(md->key->slice)) == 0 &&
|
||||
memcmp(GPR_SLICE_START_PTR(md->value->slice),
|
||||
calld->consumed_md[i].value,
|
||||
GPR_SLICE_LENGTH(md->value->slice)) == 0) {
|
||||
return NULL; /* Delete. */
|
||||
}
|
||||
}
|
||||
return md;
|
||||
}
|
||||
|
||||
static void on_md_processing_done(void *user_data,
|
||||
const grpc_metadata *consumed_md,
|
||||
size_t num_consumed_md, int success,
|
||||
grpc_auth_context *result) {
|
||||
grpc_call_element *elem = user_data;
|
||||
call_data *calld = elem->call_data;
|
||||
channel_data *chand = elem->channel_data;
|
||||
|
||||
if (success) {
|
||||
calld->consumed_md = consumed_md;
|
||||
calld->num_consumed_md = num_consumed_md;
|
||||
grpc_metadata_batch_filter(&calld->md_op->data.metadata, remove_consumed_md,
|
||||
elem);
|
||||
GPR_ASSERT(calld->call_auth_context != NULL);
|
||||
GRPC_AUTH_CONTEXT_UNREF(*calld->call_auth_context,
|
||||
"releasing old context.");
|
||||
*calld->call_auth_context =
|
||||
GRPC_AUTH_CONTEXT_REF(result, "refing new context.");
|
||||
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
|
||||
} else {
|
||||
grpc_transport_stream_op_add_cancellation(
|
||||
&calld->transport_op, GRPC_STATUS_UNAUTHENTICATED,
|
||||
grpc_mdstr_from_string(chand->mdctx,
|
||||
"Authentication metadata processing failed."));
|
||||
grpc_call_next_op(elem, &calld->transport_op);
|
||||
}
|
||||
}
|
||||
|
||||
static void auth_on_recv(void *user_data, int success) {
|
||||
grpc_call_element *elem = user_data;
|
||||
call_data *calld = elem->call_data;
|
||||
channel_data *chand = elem->channel_data;
|
||||
if (success) {
|
||||
size_t i;
|
||||
size_t nops = calld->recv_ops->nops;
|
||||
grpc_stream_op *ops = calld->recv_ops->ops;
|
||||
for (i = 0; i < nops; i++) {
|
||||
grpc_metadata_array md_array;
|
||||
grpc_auth_metadata_processor processor =
|
||||
grpc_server_get_auth_metadata_processor();
|
||||
grpc_stream_op *op = &ops[i];
|
||||
if (op->type != GRPC_OP_METADATA || calld->got_client_metadata) continue;
|
||||
calld->got_client_metadata = 1;
|
||||
if (processor.process == NULL) continue;
|
||||
calld->md_op = op;
|
||||
md_array = metadata_batch_to_md_array(&op->data.metadata);
|
||||
processor.process(processor.state, &calld->ticket,
|
||||
chand->security_connector->auth_context,
|
||||
md_array.metadata, md_array.count,
|
||||
on_md_processing_done, elem);
|
||||
grpc_metadata_array_destroy(&md_array);
|
||||
return;
|
||||
}
|
||||
}
|
||||
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
|
||||
}
|
||||
|
||||
static void set_recv_ops_md_callbacks(grpc_call_element *elem,
|
||||
grpc_transport_stream_op *op) {
|
||||
call_data *calld = elem->call_data;
|
||||
|
||||
if (op->recv_ops && !calld->got_client_metadata) {
|
||||
/* substitute our callback for the higher callback */
|
||||
calld->recv_ops = op->recv_ops;
|
||||
calld->on_done_recv = op->on_done_recv;
|
||||
op->on_done_recv = &calld->auth_on_recv;
|
||||
calld->transport_op = *op;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called either:
|
||||
- in response to an API call (or similar) from above, to send something
|
||||
- a network event (or similar) from below, to receive something
|
||||
|
|
@ -52,9 +181,7 @@ typedef struct channel_data {
|
|||
that is being sent or received. */
|
||||
static void auth_start_transport_op(grpc_call_element *elem,
|
||||
grpc_transport_stream_op *op) {
|
||||
/* TODO(jboeuf): Get the metadata and get a new context from it. */
|
||||
|
||||
/* pass control down the stack */
|
||||
set_recv_ops_md_callbacks(elem, op);
|
||||
grpc_call_next_op(elem, op);
|
||||
}
|
||||
|
||||
|
|
@ -68,11 +195,17 @@ static void init_call_elem(grpc_call_element *elem,
|
|||
grpc_server_security_context *server_ctx = NULL;
|
||||
|
||||
/* initialize members */
|
||||
calld->unused = 0;
|
||||
memset(calld, 0, sizeof(*calld));
|
||||
grpc_iomgr_closure_init(&calld->auth_on_recv, auth_on_recv, elem);
|
||||
|
||||
GPR_ASSERT(initial_op && initial_op->context != NULL &&
|
||||
initial_op->context[GRPC_CONTEXT_SECURITY].value == NULL);
|
||||
|
||||
/* Get the pollset for the ticket. */
|
||||
if (initial_op->bind_pollset) {
|
||||
calld->ticket.pollset = initial_op->bind_pollset;
|
||||
}
|
||||
|
||||
/* Create a security context for the call and reference the auth context from
|
||||
the channel. */
|
||||
if (initial_op->context[GRPC_CONTEXT_SECURITY].value != NULL) {
|
||||
|
|
@ -85,10 +218,15 @@ static void init_call_elem(grpc_call_element *elem,
|
|||
initial_op->context[GRPC_CONTEXT_SECURITY].value = server_ctx;
|
||||
initial_op->context[GRPC_CONTEXT_SECURITY].destroy =
|
||||
grpc_server_security_context_destroy;
|
||||
calld->call_auth_context = &server_ctx->auth_context;
|
||||
|
||||
/* Set the metadata callbacks. */
|
||||
set_recv_ops_md_callbacks(elem, initial_op);
|
||||
}
|
||||
|
||||
/* Destructor for call_data */
|
||||
static void destroy_call_elem(grpc_call_element *elem) {}
|
||||
static void destroy_call_elem(grpc_call_element *elem) {
|
||||
}
|
||||
|
||||
/* Constructor for channel_data */
|
||||
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
|
||||
|
|
@ -109,6 +247,7 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
|
|||
GPR_ASSERT(!sc->is_client_side);
|
||||
chand->security_connector =
|
||||
GRPC_SECURITY_CONNECTOR_REF(sc, "server_auth_filter");
|
||||
chand->mdctx = mdctx;
|
||||
}
|
||||
|
||||
/* Destructor for channel data */
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ void grpc_metadata_batch_move(grpc_metadata_batch *dst,
|
|||
grpc_metadata_batch *src);
|
||||
|
||||
/** Add \a storage to the beginning of \a batch. storage->md is
|
||||
assumed to be valid.
|
||||
assumed to be valid.
|
||||
\a storage is owned by the caller and must survive for the
|
||||
lifetime of batch. This usually means it should be around
|
||||
for the lifetime of the call. */
|
||||
|
|
|
|||
|
|
@ -100,8 +100,8 @@ static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
|
|||
grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
|
||||
grpc_credentials *ssl_creds =
|
||||
grpc_ssl_credentials_create(test_root_cert, NULL);
|
||||
grpc_credentials *oauth2_creds =
|
||||
grpc_fake_oauth2_credentials_create("Bearer aaslkfjs424535asdf", 1);
|
||||
grpc_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
|
||||
"Authorization", "Bearer aaslkfjs424535asdf", 1);
|
||||
grpc_credentials *ssl_oauth2_creds =
|
||||
grpc_composite_credentials_create(ssl_creds, oauth2_creds);
|
||||
grpc_arg ssl_name_override = {GRPC_ARG_STRING,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,11 @@
|
|||
#include "src/core/security/credentials.h"
|
||||
#include "src/core/support/string.h"
|
||||
|
||||
static const char *custom_creds_md_name = "custom_creds";
|
||||
static const char *custom_creds_md_value = "custom_value";
|
||||
static const char *client_identity_property_name = "smurf_name";
|
||||
static const char *client_identity = "Brainy Smurf";
|
||||
|
||||
static const char iam_token[] = "token";
|
||||
static const char iam_selector[] = "selector";
|
||||
static const char overridden_iam_token[] = "overridden_token";
|
||||
|
|
@ -57,15 +62,77 @@ enum { TIMEOUT = 200000 };
|
|||
|
||||
static void *tag(gpr_intptr t) { return (void *)t; }
|
||||
|
||||
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
|
||||
const char *test_name,
|
||||
grpc_channel_args *client_args,
|
||||
grpc_channel_args *server_args) {
|
||||
static const grpc_metadata *find_metadata(const grpc_metadata *md,
|
||||
size_t md_count,
|
||||
const char *key,
|
||||
const char *value) {
|
||||
size_t i;
|
||||
for (i = 0; i < md_count; i++) {
|
||||
if (strcmp(key, md[i].key) == 0 && strlen(value) == md[i].value_length &&
|
||||
memcmp(md[i].value, value, md[i].value_length) == 0) {
|
||||
return &md[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void check_peer_identity(grpc_auth_context *ctx,
|
||||
const char *expected_identity) {
|
||||
grpc_auth_property_iterator it = grpc_auth_context_peer_identity(ctx);
|
||||
const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it);
|
||||
GPR_ASSERT(prop != NULL);
|
||||
GPR_ASSERT(strcmp(expected_identity, prop->value) == 0);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
|
||||
}
|
||||
static void process_auth_md_success(void *state, grpc_auth_ticket *t,
|
||||
grpc_auth_context *channel_ctx,
|
||||
const grpc_metadata *md, size_t md_count,
|
||||
grpc_process_auth_metadata_done_cb cb,
|
||||
void *user_data) {
|
||||
override_mode *mode;
|
||||
GPR_ASSERT(state != NULL);
|
||||
mode = (override_mode *)state;
|
||||
if (*mode != DESTROY) {
|
||||
grpc_auth_context *new_auth_ctx = grpc_auth_context_create(channel_ctx);
|
||||
const grpc_metadata *custom_creds_md = find_metadata(
|
||||
md, md_count, custom_creds_md_name, custom_creds_md_value);
|
||||
GPR_ASSERT(custom_creds_md != NULL);
|
||||
grpc_auth_context_add_cstring_property(
|
||||
new_auth_ctx, client_identity_property_name, client_identity);
|
||||
GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(
|
||||
new_auth_ctx, client_identity_property_name) == 1);
|
||||
cb(user_data, custom_creds_md, 1, 1, new_auth_ctx);
|
||||
grpc_auth_context_release(new_auth_ctx);
|
||||
} else {
|
||||
cb(user_data, NULL, 0, 1, channel_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_auth_md_failure(void *state, grpc_auth_ticket *t,
|
||||
grpc_auth_context *channel_ctx,
|
||||
const grpc_metadata *md, size_t md_count,
|
||||
grpc_process_auth_metadata_done_cb cb,
|
||||
void *user_data) {
|
||||
override_mode *mode;
|
||||
GPR_ASSERT(state != NULL);
|
||||
mode = (override_mode *)state;
|
||||
if (*mode != DESTROY) {
|
||||
const grpc_metadata *custom_creds_md = find_metadata(
|
||||
md, md_count, custom_creds_md_name, custom_creds_md_value);
|
||||
GPR_ASSERT(custom_creds_md != NULL);
|
||||
}
|
||||
cb(user_data, NULL, 0, 0, NULL); /* Fail. */
|
||||
}
|
||||
|
||||
static grpc_end2end_test_fixture begin_test(
|
||||
grpc_end2end_test_config config, const char *test_name,
|
||||
grpc_auth_metadata_processor processor) {
|
||||
grpc_end2end_test_fixture f;
|
||||
grpc_server_register_auth_metadata_processor(processor);
|
||||
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
|
||||
f = config.create_fixture(client_args, server_args);
|
||||
config.init_client(&f, client_args);
|
||||
config.init_server(&f, server_args);
|
||||
f = config.create_fixture(NULL, NULL);
|
||||
config.init_client(&f, NULL);
|
||||
config.init_server(&f, NULL);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
|
@ -124,11 +191,24 @@ static void print_auth_context(int is_client, const grpc_auth_context *ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
static grpc_credentials *iam_custom_composite_creds_create(
|
||||
const char *iam_tok, const char *iam_sel) {
|
||||
grpc_credentials *iam_creds = grpc_iam_credentials_create(iam_tok, iam_sel);
|
||||
grpc_credentials *custom_creds = grpc_md_only_test_credentials_create(
|
||||
custom_creds_md_name, custom_creds_md_value, 1);
|
||||
grpc_credentials *result =
|
||||
grpc_composite_credentials_create(iam_creds, custom_creds);
|
||||
grpc_credentials_release(iam_creds);
|
||||
grpc_credentials_release(custom_creds);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void test_call_creds_failure(grpc_end2end_test_config config) {
|
||||
grpc_call *c;
|
||||
grpc_credentials *creds = NULL;
|
||||
grpc_auth_metadata_processor p = {NULL, NULL};
|
||||
grpc_end2end_test_fixture f =
|
||||
begin_test(config, "test_call_creds_failure", NULL, NULL);
|
||||
begin_test(config, "test_call_creds_failure", p);
|
||||
gpr_timespec deadline = five_seconds_time();
|
||||
c = grpc_channel_create_call(f.client, f.cq, "/foo", "foo.test.google.fr",
|
||||
deadline);
|
||||
|
|
@ -157,9 +237,9 @@ static void request_response_with_payload_and_call_creds(
|
|||
grpc_byte_buffer *response_payload =
|
||||
grpc_raw_byte_buffer_create(&response_payload_slice, 1);
|
||||
gpr_timespec deadline = five_seconds_time();
|
||||
|
||||
grpc_end2end_test_fixture f = begin_test(config, test_name, NULL, NULL);
|
||||
cq_verifier *cqv = cq_verifier_create(f.cq);
|
||||
grpc_auth_metadata_processor p;
|
||||
grpc_end2end_test_fixture f;
|
||||
cq_verifier *cqv;
|
||||
grpc_op ops[6];
|
||||
grpc_op *op;
|
||||
grpc_metadata_array initial_metadata_recv;
|
||||
|
|
@ -174,11 +254,17 @@ static void request_response_with_payload_and_call_creds(
|
|||
int was_cancelled = 2;
|
||||
grpc_credentials *creds = NULL;
|
||||
grpc_auth_context *s_auth_context = NULL;
|
||||
grpc_auth_context *c_auth_context = NULL;
|
||||
|
||||
p.process = process_auth_md_success;
|
||||
p.state = &mode;
|
||||
f = begin_test(config, test_name, p);
|
||||
cqv = cq_verifier_create(f.cq);
|
||||
|
||||
c = grpc_channel_create_call(f.client, f.cq, "/foo", "foo.test.google.fr",
|
||||
deadline);
|
||||
GPR_ASSERT(c);
|
||||
creds = grpc_iam_credentials_create(iam_token, iam_selector);
|
||||
creds = iam_custom_composite_creds_create(iam_token, iam_selector);
|
||||
GPR_ASSERT(creds != NULL);
|
||||
GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK);
|
||||
switch (mode) {
|
||||
|
|
@ -186,8 +272,8 @@ static void request_response_with_payload_and_call_creds(
|
|||
break;
|
||||
case OVERRIDE:
|
||||
grpc_credentials_release(creds);
|
||||
creds = grpc_iam_credentials_create(overridden_iam_token,
|
||||
overridden_iam_selector);
|
||||
creds = iam_custom_composite_creds_create(overridden_iam_token,
|
||||
overridden_iam_selector);
|
||||
GPR_ASSERT(creds != NULL);
|
||||
GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK);
|
||||
break;
|
||||
|
|
@ -241,6 +327,11 @@ static void request_response_with_payload_and_call_creds(
|
|||
print_auth_context(0, s_auth_context);
|
||||
grpc_auth_context_release(s_auth_context);
|
||||
|
||||
c_auth_context = grpc_call_auth_context(c);
|
||||
GPR_ASSERT(c_auth_context != NULL);
|
||||
print_auth_context(1, c_auth_context);
|
||||
grpc_auth_context_release(c_auth_context);
|
||||
|
||||
/* Cannot set creds on the server call object. */
|
||||
GPR_ASSERT(grpc_call_set_credentials(s, NULL) != GRPC_CALL_OK);
|
||||
|
||||
|
|
@ -287,6 +378,10 @@ static void request_response_with_payload_and_call_creds(
|
|||
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
|
||||
GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
|
||||
|
||||
/* Has been processed by the auth metadata processor. */
|
||||
GPR_ASSERT(!contains_metadata(&request_metadata_recv, custom_creds_md_name,
|
||||
custom_creds_md_value));
|
||||
|
||||
switch (mode) {
|
||||
case NONE:
|
||||
GPR_ASSERT(contains_metadata(&request_metadata_recv,
|
||||
|
|
@ -295,6 +390,7 @@ static void request_response_with_payload_and_call_creds(
|
|||
GPR_ASSERT(contains_metadata(&request_metadata_recv,
|
||||
GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
|
||||
iam_selector));
|
||||
check_peer_identity(s_auth_context, client_identity);
|
||||
break;
|
||||
case OVERRIDE:
|
||||
GPR_ASSERT(contains_metadata(&request_metadata_recv,
|
||||
|
|
@ -303,6 +399,7 @@ static void request_response_with_payload_and_call_creds(
|
|||
GPR_ASSERT(contains_metadata(&request_metadata_recv,
|
||||
GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
|
||||
overridden_iam_selector));
|
||||
check_peer_identity(s_auth_context, client_identity);
|
||||
break;
|
||||
case DESTROY:
|
||||
GPR_ASSERT(!contains_metadata(&request_metadata_recv,
|
||||
|
|
@ -340,31 +437,128 @@ static void request_response_with_payload_and_call_creds(
|
|||
config.tear_down_data(&f);
|
||||
}
|
||||
|
||||
void test_request_response_with_payload_and_call_creds(
|
||||
static void test_request_response_with_payload_and_call_creds(
|
||||
grpc_end2end_test_config config) {
|
||||
request_response_with_payload_and_call_creds(
|
||||
"test_request_response_with_payload_and_call_creds", config, NONE);
|
||||
}
|
||||
|
||||
void test_request_response_with_payload_and_overridden_call_creds(
|
||||
static void test_request_response_with_payload_and_overridden_call_creds(
|
||||
grpc_end2end_test_config config) {
|
||||
request_response_with_payload_and_call_creds(
|
||||
"test_request_response_with_payload_and_overridden_call_creds", config,
|
||||
OVERRIDE);
|
||||
}
|
||||
|
||||
void test_request_response_with_payload_and_deleted_call_creds(
|
||||
static void test_request_response_with_payload_and_deleted_call_creds(
|
||||
grpc_end2end_test_config config) {
|
||||
request_response_with_payload_and_call_creds(
|
||||
"test_request_response_with_payload_and_deleted_call_creds", config,
|
||||
DESTROY);
|
||||
}
|
||||
|
||||
static void test_request_with_server_rejecting_client_creds(
|
||||
grpc_end2end_test_config config) {
|
||||
grpc_op ops[6];
|
||||
grpc_op *op;
|
||||
grpc_call *c;
|
||||
grpc_auth_metadata_processor p;
|
||||
grpc_end2end_test_fixture f;
|
||||
gpr_timespec deadline = five_seconds_time();
|
||||
cq_verifier *cqv;
|
||||
grpc_metadata_array initial_metadata_recv;
|
||||
grpc_metadata_array trailing_metadata_recv;
|
||||
grpc_metadata_array request_metadata_recv;
|
||||
grpc_call_details call_details;
|
||||
grpc_status_code status;
|
||||
char *details = NULL;
|
||||
size_t details_capacity = 0;
|
||||
grpc_byte_buffer *response_payload_recv = NULL;
|
||||
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
|
||||
grpc_byte_buffer *request_payload =
|
||||
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
|
||||
override_mode mode = NONE;
|
||||
grpc_credentials *creds;
|
||||
|
||||
p.process = process_auth_md_failure;
|
||||
p.state = &mode;
|
||||
f = begin_test(config, "test_request_with_server_rejecting_client_creds", p);
|
||||
cqv = cq_verifier_create(f.cq);
|
||||
|
||||
c = grpc_channel_create_call(f.client, f.cq, "/foo", "foo.test.google.fr",
|
||||
deadline);
|
||||
GPR_ASSERT(c);
|
||||
|
||||
creds = iam_custom_composite_creds_create(iam_token, iam_selector);
|
||||
GPR_ASSERT(creds != NULL);
|
||||
GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK);
|
||||
grpc_credentials_release(creds);
|
||||
|
||||
grpc_metadata_array_init(&initial_metadata_recv);
|
||||
grpc_metadata_array_init(&trailing_metadata_recv);
|
||||
grpc_metadata_array_init(&request_metadata_recv);
|
||||
grpc_call_details_init(&call_details);
|
||||
|
||||
op = ops;
|
||||
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
|
||||
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
|
||||
op->data.recv_status_on_client.status = &status;
|
||||
op->data.recv_status_on_client.status_details = &details;
|
||||
op->data.recv_status_on_client.status_details_capacity = &details_capacity;
|
||||
op->flags = 0;
|
||||
op++;
|
||||
op->op = GRPC_OP_SEND_INITIAL_METADATA;
|
||||
op->data.send_initial_metadata.count = 0;
|
||||
op->flags = 0;
|
||||
op++;
|
||||
op->op = GRPC_OP_SEND_MESSAGE;
|
||||
op->data.send_message = request_payload;
|
||||
op->flags = 0;
|
||||
op++;
|
||||
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
|
||||
op->flags = 0;
|
||||
op++;
|
||||
op->op = GRPC_OP_RECV_INITIAL_METADATA;
|
||||
op->data.recv_initial_metadata = &initial_metadata_recv;
|
||||
op->flags = 0;
|
||||
op++;
|
||||
op->op = GRPC_OP_RECV_MESSAGE;
|
||||
op->data.recv_message = &response_payload_recv;
|
||||
op->flags = 0;
|
||||
op++;
|
||||
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1)));
|
||||
|
||||
cq_expect_completion(cqv, tag(1), 1);
|
||||
cq_verify(cqv);
|
||||
|
||||
/* XXX Should be GRPC_STATUS_UNAUTHENTICATED but it looks like there is a bug
|
||||
(probably in the server_auth_context.c code) where this error on the server
|
||||
does not get to the client. The current error code we are getting is
|
||||
GRPC_STATUS_INTERNAL. */
|
||||
GPR_ASSERT(status != GRPC_STATUS_OK);
|
||||
|
||||
grpc_metadata_array_destroy(&initial_metadata_recv);
|
||||
grpc_metadata_array_destroy(&trailing_metadata_recv);
|
||||
grpc_metadata_array_destroy(&request_metadata_recv);
|
||||
grpc_call_details_destroy(&call_details);
|
||||
|
||||
grpc_byte_buffer_destroy(request_payload);
|
||||
grpc_byte_buffer_destroy(response_payload_recv);
|
||||
gpr_free(details);
|
||||
|
||||
grpc_call_destroy(c);
|
||||
|
||||
cq_verifier_destroy(cqv);
|
||||
end_test(&f);
|
||||
config.tear_down_data(&f);
|
||||
}
|
||||
|
||||
void grpc_end2end_tests(grpc_end2end_test_config config) {
|
||||
if (config.feature_mask & FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS) {
|
||||
test_call_creds_failure(config);
|
||||
test_request_response_with_payload_and_call_creds(config);
|
||||
test_request_response_with_payload_and_overridden_call_creds(config);
|
||||
test_request_response_with_payload_and_deleted_call_creds(config);
|
||||
test_request_with_server_rejecting_client_creds(config);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#include <grpc/support/log.h>
|
||||
|
||||
static void test_empty_context(void) {
|
||||
grpc_auth_context *ctx = grpc_auth_context_create(NULL, 0);
|
||||
grpc_auth_context *ctx = grpc_auth_context_create(NULL);
|
||||
grpc_auth_property_iterator it;
|
||||
|
||||
gpr_log(GPR_INFO, "test_empty_context");
|
||||
|
|
@ -52,87 +52,98 @@ static void test_empty_context(void) {
|
|||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
|
||||
it = grpc_auth_context_find_properties_by_name(ctx, "foo");
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
|
||||
GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(ctx, "bar") ==
|
||||
0);
|
||||
GPR_ASSERT(grpc_auth_context_peer_identity_property_name(ctx) == NULL);
|
||||
GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
|
||||
}
|
||||
|
||||
static void test_simple_context(void) {
|
||||
grpc_auth_context *ctx = grpc_auth_context_create(NULL, 3);
|
||||
grpc_auth_context *ctx = grpc_auth_context_create(NULL);
|
||||
grpc_auth_property_iterator it;
|
||||
size_t i;
|
||||
|
||||
gpr_log(GPR_INFO, "test_simple_context");
|
||||
GPR_ASSERT(ctx != NULL);
|
||||
GPR_ASSERT(ctx->property_count == 3);
|
||||
ctx->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
|
||||
ctx->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
|
||||
ctx->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
|
||||
ctx->peer_identity_property_name = ctx->properties[0].name;
|
||||
grpc_auth_context_add_cstring_property(ctx, "name", "chapi");
|
||||
grpc_auth_context_add_cstring_property(ctx, "name", "chapo");
|
||||
grpc_auth_context_add_cstring_property(ctx, "foo", "bar");
|
||||
GPR_ASSERT(ctx->properties.count == 3);
|
||||
GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(ctx, "name") ==
|
||||
1);
|
||||
|
||||
GPR_ASSERT(
|
||||
strcmp(grpc_auth_context_peer_identity_property_name(ctx), "name") == 0);
|
||||
it = grpc_auth_context_property_iterator(ctx);
|
||||
for (i = 0; i < ctx->property_count; i++) {
|
||||
for (i = 0; i < ctx->properties.count; i++) {
|
||||
const grpc_auth_property *p = grpc_auth_property_iterator_next(&it);
|
||||
GPR_ASSERT(p == &ctx->properties[i]);
|
||||
GPR_ASSERT(p == &ctx->properties.array[i]);
|
||||
}
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
|
||||
|
||||
it = grpc_auth_context_find_properties_by_name(ctx, "foo");
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[2]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) ==
|
||||
&ctx->properties.array[2]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
|
||||
|
||||
it = grpc_auth_context_peer_identity(ctx);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[0]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[1]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) ==
|
||||
&ctx->properties.array[0]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) ==
|
||||
&ctx->properties.array[1]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
|
||||
|
||||
GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
|
||||
}
|
||||
|
||||
static void test_chained_context(void) {
|
||||
grpc_auth_context *chained = grpc_auth_context_create(NULL, 2);
|
||||
grpc_auth_context *ctx = grpc_auth_context_create(chained, 3);
|
||||
grpc_auth_context *chained = grpc_auth_context_create(NULL);
|
||||
grpc_auth_context *ctx = grpc_auth_context_create(chained);
|
||||
grpc_auth_property_iterator it;
|
||||
size_t i;
|
||||
|
||||
gpr_log(GPR_INFO, "test_chained_context");
|
||||
GRPC_AUTH_CONTEXT_UNREF(chained, "chained");
|
||||
chained->properties[0] =
|
||||
grpc_auth_property_init_from_cstring("name", "padapo");
|
||||
chained->properties[1] = grpc_auth_property_init_from_cstring("foo", "baz");
|
||||
ctx->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
|
||||
ctx->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
|
||||
ctx->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
|
||||
ctx->peer_identity_property_name = ctx->properties[0].name;
|
||||
grpc_auth_context_add_cstring_property(chained, "name", "padapo");
|
||||
grpc_auth_context_add_cstring_property(chained, "foo", "baz");
|
||||
grpc_auth_context_add_cstring_property(ctx, "name", "chapi");
|
||||
grpc_auth_context_add_cstring_property(ctx, "name", "chap0");
|
||||
grpc_auth_context_add_cstring_property(ctx, "foo", "bar");
|
||||
GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(ctx, "name") ==
|
||||
1);
|
||||
|
||||
GPR_ASSERT(
|
||||
strcmp(grpc_auth_context_peer_identity_property_name(ctx), "name") == 0);
|
||||
it = grpc_auth_context_property_iterator(ctx);
|
||||
for (i = 0; i < ctx->property_count; i++) {
|
||||
for (i = 0; i < ctx->properties.count; i++) {
|
||||
const grpc_auth_property *p = grpc_auth_property_iterator_next(&it);
|
||||
GPR_ASSERT(p == &ctx->properties[i]);
|
||||
GPR_ASSERT(p == &ctx->properties.array[i]);
|
||||
}
|
||||
for (i = 0; i < chained->property_count; i++) {
|
||||
for (i = 0; i < chained->properties.count; i++) {
|
||||
const grpc_auth_property *p = grpc_auth_property_iterator_next(&it);
|
||||
GPR_ASSERT(p == &chained->properties[i]);
|
||||
GPR_ASSERT(p == &chained->properties.array[i]);
|
||||
}
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
|
||||
|
||||
it = grpc_auth_context_find_properties_by_name(ctx, "foo");
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[2]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &chained->properties[1]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) ==
|
||||
&ctx->properties.array[2]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) ==
|
||||
&chained->properties.array[1]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
|
||||
|
||||
it = grpc_auth_context_peer_identity(ctx);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[0]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[1]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &chained->properties[0]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) ==
|
||||
&ctx->properties.array[0]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) ==
|
||||
&ctx->properties.array[1]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) ==
|
||||
&chained->properties.array[0]);
|
||||
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
|
||||
|
||||
GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
grpc_test_init(argc, argv);
|
||||
test_empty_context();
|
||||
|
|
|
|||
|
|
@ -373,8 +373,8 @@ static void test_ssl_oauth2_composite_creds(void) {
|
|||
grpc_credentials *ssl_creds =
|
||||
grpc_ssl_credentials_create(test_root_cert, NULL);
|
||||
const grpc_credentials_array *creds_array;
|
||||
grpc_credentials *oauth2_creds =
|
||||
grpc_fake_oauth2_credentials_create(test_oauth2_bearer_token, 0);
|
||||
grpc_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
|
||||
"Authorization", test_oauth2_bearer_token, 0);
|
||||
grpc_credentials *composite_creds =
|
||||
grpc_composite_credentials_create(ssl_creds, oauth2_creds);
|
||||
grpc_credentials_unref(ssl_creds);
|
||||
|
|
@ -424,8 +424,8 @@ static void test_ssl_oauth2_iam_composite_creds(void) {
|
|||
grpc_credentials *ssl_creds =
|
||||
grpc_ssl_credentials_create(test_root_cert, NULL);
|
||||
const grpc_credentials_array *creds_array;
|
||||
grpc_credentials *oauth2_creds =
|
||||
grpc_fake_oauth2_credentials_create(test_oauth2_bearer_token, 0);
|
||||
grpc_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
|
||||
"Authorization", test_oauth2_bearer_token, 0);
|
||||
grpc_credentials *aux_creds =
|
||||
grpc_composite_credentials_create(ssl_creds, oauth2_creds);
|
||||
grpc_credentials *iam_creds = grpc_iam_credentials_create(
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <grpc/grpc_security.h>
|
||||
#include <grpc++/auth_context.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include "src/cpp/common/secure_auth_context.h"
|
||||
#include "src/core/security/security_context.h"
|
||||
|
||||
namespace grpc {
|
||||
namespace {
|
||||
|
|
@ -50,14 +50,15 @@ class TestAuthPropertyIterator : public AuthPropertyIterator {
|
|||
class AuthPropertyIteratorTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() GRPC_OVERRIDE {
|
||||
ctx_ = grpc_auth_context_create(NULL, 3);
|
||||
ctx_->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
|
||||
ctx_->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
|
||||
ctx_->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
|
||||
ctx_->peer_identity_property_name = ctx_->properties[0].name;
|
||||
ctx_ = grpc_auth_context_create(NULL);
|
||||
grpc_auth_context_add_cstring_property(ctx_, "name", "chapi");
|
||||
grpc_auth_context_add_cstring_property(ctx_, "name", "chapo");
|
||||
grpc_auth_context_add_cstring_property(ctx_, "foo", "bar");
|
||||
EXPECT_EQ(1,
|
||||
grpc_auth_context_set_peer_identity_property_name(ctx_, "name"));
|
||||
}
|
||||
void TearDown() GRPC_OVERRIDE {
|
||||
GRPC_AUTH_CONTEXT_UNREF(ctx_, "AuthPropertyIteratorTest");
|
||||
grpc_auth_context_release(ctx_);
|
||||
}
|
||||
grpc_auth_context* ctx_;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <grpc/grpc_security.h>
|
||||
#include <grpc++/auth_context.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include "src/cpp/common/secure_auth_context.h"
|
||||
#include "src/core/security/security_context.h"
|
||||
|
||||
namespace grpc {
|
||||
namespace {
|
||||
|
|
@ -52,11 +52,11 @@ TEST_F(SecureAuthContextTest, EmptyContext) {
|
|||
}
|
||||
|
||||
TEST_F(SecureAuthContextTest, Properties) {
|
||||
grpc_auth_context* ctx = grpc_auth_context_create(NULL, 3);
|
||||
ctx->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
|
||||
ctx->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
|
||||
ctx->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
|
||||
ctx->peer_identity_property_name = ctx->properties[0].name;
|
||||
grpc_auth_context* ctx = grpc_auth_context_create(NULL);
|
||||
grpc_auth_context_add_cstring_property(ctx, "name", "chapi");
|
||||
grpc_auth_context_add_cstring_property(ctx, "name", "chapo");
|
||||
grpc_auth_context_add_cstring_property(ctx, "foo", "bar");
|
||||
EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name"));
|
||||
|
||||
SecureAuthContext context(ctx);
|
||||
std::vector<grpc::string> peer_identity = context.GetPeerIdentity();
|
||||
|
|
@ -70,11 +70,11 @@ TEST_F(SecureAuthContextTest, Properties) {
|
|||
}
|
||||
|
||||
TEST_F(SecureAuthContextTest, Iterators) {
|
||||
grpc_auth_context* ctx = grpc_auth_context_create(NULL, 3);
|
||||
ctx->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
|
||||
ctx->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
|
||||
ctx->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
|
||||
ctx->peer_identity_property_name = ctx->properties[0].name;
|
||||
grpc_auth_context* ctx = grpc_auth_context_create(NULL);
|
||||
grpc_auth_context_add_cstring_property(ctx, "name", "chapi");
|
||||
grpc_auth_context_add_cstring_property(ctx, "name", "chapo");
|
||||
grpc_auth_context_add_cstring_property(ctx, "foo", "bar");
|
||||
EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name"));
|
||||
|
||||
SecureAuthContext context(ctx);
|
||||
AuthPropertyIterator iter = context.begin();
|
||||
|
|
|
|||
Loading…
Reference in New Issue