Putting the auth metadata processor on the server creds.

pull/2777/head
Julien Boeuf 9 years ago
parent 6bdc9b47bc
commit 66a27daef6
  1. 32
      src/core/security/security_context.c
  2. 4
      src/core/security/security_context.h
  3. 11
      src/core/security/server_auth_filter.c
  4. 11
      src/core/security/server_secure_chttp2.c
  5. 42
      test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
  6. 199
      test/core/end2end/tests/request_response_with_payload_and_call_creds.c

@ -295,3 +295,35 @@ void grpc_auth_property_reset(grpc_auth_property *property) {
memset(property, 0, sizeof(grpc_auth_property));
}
grpc_arg grpc_auth_metadata_processor_to_arg(grpc_auth_metadata_processor *p) {
grpc_arg arg;
memset(&arg, 0, sizeof(grpc_arg));
arg.type = GRPC_ARG_POINTER;
arg.key = GRPC_AUTH_METADATA_PROCESSOR_ARG;
arg.value.pointer.p = p;
return arg;
}
grpc_auth_metadata_processor *grpc_auth_metadata_processor_from_arg(
const grpc_arg *arg) {
if (strcmp(arg->key, GRPC_AUTH_METADATA_PROCESSOR_ARG) != 0) return NULL;
if (arg->type != GRPC_ARG_POINTER) {
gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
GRPC_AUTH_METADATA_PROCESSOR_ARG);
return NULL;
}
return arg->value.pointer.p;
}
grpc_auth_metadata_processor *grpc_find_auth_metadata_processor_in_args(
const grpc_channel_args *args) {
size_t i;
if (args == NULL) return NULL;
for (i = 0; i < args->num_args; i++) {
grpc_auth_metadata_processor *p =
grpc_auth_metadata_processor_from_arg(&args->args[i]);
if (p != NULL) return p;
}
return NULL;
}

@ -108,8 +108,10 @@ void grpc_server_security_context_destroy(void *ctx);
#define GRPC_AUTH_METADATA_PROCESSOR_ARG "grpc.auth_metadata_processor"
grpc_arg grpc_auth_metadata_processor_to_arg(grpc_auth_metadata_processor *p);
grpc_auth_metadata_processor grpc_auth_metadata_processor_from_arg(
grpc_auth_metadata_processor *grpc_auth_metadata_processor_from_arg(
const grpc_arg *arg);
grpc_auth_metadata_processor *grpc_find_auth_metadata_processor_in_args(
const grpc_channel_args *args);
#endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */

@ -59,6 +59,7 @@ typedef struct call_data {
typedef struct channel_data {
grpc_security_connector *security_connector;
grpc_auth_metadata_processor processor;
grpc_mdctx *mdctx;
} channel_data;
@ -142,15 +143,13 @@ static void auth_on_recv(void *user_data, int success) {
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;
if (chand->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->processor.process(chand->processor.state, &calld->ticket,
chand->security_connector->auth_context,
md_array.metadata, md_array.count,
on_md_processing_done, elem);
@ -233,6 +232,8 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx,
int is_first, int is_last) {
grpc_security_connector *sc = grpc_find_security_connector_in_args(args);
grpc_auth_metadata_processor *processor =
grpc_find_auth_metadata_processor_in_args(args);
/* grab pointers to our data from the channel element */
channel_data *chand = elem->channel_data;
@ -242,12 +243,14 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
GPR_ASSERT(!is_first);
GPR_ASSERT(!is_last);
GPR_ASSERT(sc != NULL);
GPR_ASSERT(processor != NULL);
/* initialize members */
GPR_ASSERT(!sc->is_client_side);
chand->security_connector =
GRPC_SECURITY_CONNECTOR_REF(sc, "server_auth_filter");
chand->mdctx = mdctx;
chand->processor = *processor;
}
/* Destructor for channel data */

@ -43,6 +43,7 @@
#include "src/core/security/auth_filters.h"
#include "src/core/security/credentials.h"
#include "src/core/security/security_connector.h"
#include "src/core/security/security_context.h"
#include "src/core/security/secure_transport_setup.h"
#include "src/core/surface/server.h"
#include "src/core/transport/chttp2_transport.h"
@ -87,9 +88,13 @@ static void setup_transport(void *statep, grpc_transport *transport,
static grpc_channel_filter const *extra_filters[] = {
&grpc_server_auth_filter, &grpc_http_server_filter};
grpc_server_secure_state *state = statep;
grpc_arg connector_arg = grpc_security_connector_to_arg(state->sc);
grpc_channel_args *args_copy = grpc_channel_args_copy_and_add(
grpc_server_get_channel_args(state->server), &connector_arg, 1);
grpc_channel_args *args_copy;
grpc_arg args_to_add[2];
args_to_add[0] = grpc_security_connector_to_arg(state->sc);
args_to_add[1] = grpc_auth_metadata_processor_to_arg(&state->processor);
args_copy = grpc_channel_args_copy_and_add(
grpc_server_get_channel_args(state->server), args_to_add,
GPR_ARRAY_SIZE(args_to_add));
grpc_server_setup_transport(state->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx, args_copy);
grpc_channel_args_destroy(args_copy);

@ -46,10 +46,46 @@
#include "test/core/util/port.h"
#include "test/core/end2end/data/ssl_test_data.h"
static const char oauth2_md[] = "Bearer aaslkfjs424535asdf";
static const char *client_identity_property_name = "smurf_name";
static const char *client_identity = "Brainy Smurf";
typedef struct fullstack_secure_fixture_data {
char *localaddr;
} fullstack_secure_fixture_data;
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;
}
void process_oauth2(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) {
const grpc_metadata *oauth2 =
find_metadata(md, md_count, "Authorization", oauth2_md);
grpc_auth_context *new_ctx;
GPR_ASSERT(state == NULL);
GPR_ASSERT(oauth2 != NULL);
new_ctx = grpc_auth_context_create(channel_ctx);
grpc_auth_context_add_cstring_property(new_ctx, client_identity_property_name,
client_identity);
GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(
new_ctx, client_identity_property_name) == 1);
cb(user_data, oauth2, 1, 1, new_ctx);
grpc_auth_context_release(new_ctx);
}
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
grpc_channel_args *client_args, grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
@ -100,8 +136,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_md_only_test_credentials_create(
"Authorization", "Bearer aaslkfjs424535asdf", 1);
grpc_credentials *oauth2_creds =
grpc_md_only_test_credentials_create("Authorization", oauth2_md, 1);
grpc_credentials *ssl_oauth2_creds =
grpc_composite_credentials_create(ssl_creds, oauth2_creds);
grpc_arg ssl_name_override = {GRPC_ARG_STRING,
@ -121,6 +157,8 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
test_server1_cert};
grpc_server_credentials *ssl_creds =
grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1);
grpc_auth_metadata_processor processor = {process_oauth2, NULL};
grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
}

@ -46,11 +46,6 @@
#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";
@ -62,73 +57,9 @@ enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
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_config config, const char *test_name) {
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(NULL, NULL);
config.init_client(&f, NULL);
@ -191,24 +122,10 @@ 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", p);
grpc_end2end_test_fixture f = begin_test(config, "test_call_creds_failure");
gpr_timespec deadline = five_seconds_time();
c = grpc_channel_create_call(f.client, f.cq, "/foo", "foo.test.google.fr",
deadline);
@ -237,7 +154,6 @@ 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_auth_metadata_processor p;
grpc_end2end_test_fixture f;
cq_verifier *cqv;
grpc_op ops[6];
@ -256,15 +172,13 @@ static void request_response_with_payload_and_call_creds(
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);
f = begin_test(config, test_name);
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);
creds = grpc_iam_credentials_create(iam_token, iam_selector);
GPR_ASSERT(creds != NULL);
GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK);
switch (mode) {
@ -272,7 +186,7 @@ static void request_response_with_payload_and_call_creds(
break;
case OVERRIDE:
grpc_credentials_release(creds);
creds = iam_custom_composite_creds_create(overridden_iam_token,
creds = grpc_iam_credentials_create(overridden_iam_token,
overridden_iam_selector);
GPR_ASSERT(creds != NULL);
GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK);
@ -378,10 +292,6 @@ 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,
@ -390,7 +300,6 @@ 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,
@ -399,7 +308,6 @@ 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,
@ -457,108 +365,11 @@ static void test_request_response_with_payload_and_deleted_call_creds(
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);
}
}

Loading…
Cancel
Save