Adding C++ tests and fixing a few things.

pull/3176/head
Julien Boeuf 9 years ago
parent 4ffbf0d22c
commit 1928d496a2
  1. 33
      src/core/security/client_auth_filter.c
  2. 10
      src/core/security/credentials.c
  3. 91
      test/cpp/end2end/end2end_test.cc

@ -63,6 +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;
} call_data;
/* We can have a per-channel credentials. */
@ -75,6 +76,13 @@ 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 bubble_up_error(grpc_call_element *elem, grpc_status_code status,
const char *error_msg) {
call_data *calld = elem->call_data;
@ -93,6 +101,7 @@ static void on_credentials_metadata(void *user_data,
grpc_transport_stream_op *op = &calld->op;
grpc_metadata_batch *mdb;
size_t i;
reset_service_url(calld);
if (status != GRPC_CREDENTIALS_OK) {
bubble_up_error(elem, GRPC_STATUS_UNAUTHENTICATED,
"Credentials failed to get metadata.");
@ -111,8 +120,7 @@ static void on_credentials_metadata(void *user_data,
grpc_call_next_op(elem, op);
}
static char *build_service_url(const char *url_scheme, call_data *calld) {
char *service_url;
void build_service_url(const char *url_scheme, call_data *calld) {
char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
char *last_slash = strrchr(service, '/');
if (last_slash == NULL) {
@ -125,10 +133,10 @@ static char *build_service_url(const char *url_scheme, call_data *calld) {
*last_slash = '\0';
}
if (url_scheme == NULL) url_scheme = "";
gpr_asprintf(&service_url, "%s://%s%s", url_scheme,
reset_service_url(calld);
gpr_asprintf(&calld->service_url, "%s://%s%s", url_scheme,
grpc_mdstr_as_c_string(calld->host), service);
gpr_free(service);
return service_url;
}
static void send_security_metadata(grpc_call_element *elem,
@ -137,7 +145,6 @@ static void send_security_metadata(grpc_call_element *elem,
channel_data *chand = elem->channel_data;
grpc_client_security_context *ctx =
(grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value;
char *service_url = NULL;
grpc_credentials *channel_creds =
chand->security_connector->request_metadata_creds;
int channel_creds_has_md =
@ -165,13 +172,12 @@ static void send_security_metadata(grpc_call_element *elem,
grpc_credentials_ref(call_creds_has_md ? ctx->creds : channel_creds);
}
service_url =
build_service_url(chand->security_connector->base.url_scheme, calld);
calld->op = *op; /* Copy op (originates from the caller's stack). */
GPR_ASSERT(calld->pollset);
grpc_credentials_get_request_metadata(
calld->creds, calld->pollset, service_url, on_credentials_metadata, elem);
gpr_free(service_url);
grpc_credentials_get_request_metadata(calld->creds, calld->pollset,
calld->service_url,
on_credentials_metadata, elem);
}
static void on_host_checked(void *user_data, grpc_security_status status) {
@ -274,13 +280,7 @@ static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
call_data *calld = elem->call_data;
calld->creds = NULL;
calld->host = NULL;
calld->method = NULL;
calld->pollset = NULL;
calld->sent_initial_metadata = 0;
calld->security_context_set = 0;
memset(calld, 0, sizeof(*calld));
GPR_ASSERT(!initial_op || !initial_op->send_ops);
}
@ -294,6 +294,7 @@ static void destroy_call_elem(grpc_call_element *elem) {
if (calld->method != NULL) {
GRPC_MDSTR_UNREF(calld->method);
}
reset_service_url(calld);
}
/* Constructor for channel_data */

@ -1221,9 +1221,9 @@ static void plugin_md_request_metadata_ready(void *request,
}
r->cb(r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
} else {
size_t i;
grpc_credentials_md *md_array = NULL;
if (num_md > 0) {
size_t i;
md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
for (i = 0; i < num_md; i++) {
md_array[i].key = gpr_slice_from_copied_string(md[i].key);
@ -1232,7 +1232,13 @@ static void plugin_md_request_metadata_ready(void *request,
}
}
r->cb(r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK);
if (md_array != NULL) gpr_free(md_array);
if (md_array != NULL) {
for (i = 0; i < num_md; i++) {
gpr_slice_unref(md_array[i].key);
gpr_slice_unref(md_array[i].value);
}
gpr_free(md_array);
}
}
gpr_free(r);
}

@ -108,6 +108,39 @@ bool CheckIsLocalhost(const grpc::string& addr) {
addr.substr(0, kIpv6.size()) == kIpv6;
}
class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin {
public:
static const char kMetadataKey[];
TestMetadataCredentialsPlugin(grpc::string_ref metadata_value,
bool is_blocking, bool is_successful)
: metadata_value_(metadata_value.data(), metadata_value.length()),
is_blocking_(is_blocking),
is_successful_(is_successful) {}
bool IsBlocking() const GRPC_OVERRIDE { return is_blocking_; }
Status GetMetadata(grpc::string_ref service_url,
std::multimap<grpc::string, grpc::string_ref>* metadata)
GRPC_OVERRIDE {
EXPECT_GT(service_url.length(), 0UL);
EXPECT_TRUE(metadata != nullptr);
if (is_successful_) {
metadata->insert(std::make_pair(kMetadataKey, metadata_value_));
return Status::OK;
} else {
return Status(StatusCode::NOT_FOUND, "Could not find plugin metadata.");
}
}
private:
grpc::string metadata_value_;
bool is_blocking_;
bool is_successful_;
};
const char TestMetadataCredentialsPlugin::kMetadataKey[] = "TestPluginMetadata";
class TestAuthMetadataProcessor : public AuthMetadataProcessor {
public:
static const char kGoodGuy[];
@ -115,10 +148,15 @@ class TestAuthMetadataProcessor : public AuthMetadataProcessor {
TestAuthMetadataProcessor(bool is_blocking) : is_blocking_(is_blocking) {}
std::shared_ptr<Credentials> GetCompatibleClientCreds() {
return AccessTokenCredentials(kGoodGuy);
return MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(kGoodGuy, is_blocking_, true)));
}
std::shared_ptr<Credentials> GetIncompatibleClientCreds() {
return AccessTokenCredentials("Mr Hyde");
return MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin("Mr Hyde", is_blocking_, true)));
}
// Interface implementation
@ -130,10 +168,11 @@ class TestAuthMetadataProcessor : public AuthMetadataProcessor {
EXPECT_TRUE(consumed_auth_metadata != nullptr);
EXPECT_TRUE(context != nullptr);
EXPECT_TRUE(response_metadata != nullptr);
auto auth_md = auth_metadata.find(GRPC_AUTHORIZATION_METADATA_KEY);
auto auth_md =
auth_metadata.find(TestMetadataCredentialsPlugin::kMetadataKey);
EXPECT_NE(auth_md, auth_metadata.end());
string_ref auth_md_value = auth_md->second;
if (auth_md_value.ends_with(kGoodGuy)) {
if (auth_md_value == kGoodGuy) {
context->AddProperty(kIdentityPropName, kGoodGuy);
context->SetPeerIdentityPropertyName(kIdentityPropName);
consumed_auth_metadata->insert(
@ -147,7 +186,7 @@ class TestAuthMetadataProcessor : public AuthMetadataProcessor {
}
}
protected:
private:
static const char kIdentityPropName[];
bool is_blocking_;
};
@ -876,7 +915,24 @@ TEST_F(End2endTest, OverridePerCallCredentials) {
EXPECT_TRUE(s.ok());
}
TEST_F(End2endTest, NonBlockingAuthMetadataProcessorSuccess) {
TEST_F(End2endTest, NonBlockingAuthMetadataPluginFailure) {
ResetStub(false);
EchoRequest request;
EchoResponse response;
ClientContext context;
context.set_credentials(
MetadataCredentialsFromPlugin(std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(
"Does not matter, will fail anyway (see 3rd param)", false,
false))));
request.set_message("Hello");
Status s = stub_->Echo(&context, request, &response);
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
}
TEST_F(End2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) {
auto* processor = new TestAuthMetadataProcessor(false);
StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
ResetStub(false);
@ -899,7 +955,7 @@ TEST_F(End2endTest, NonBlockingAuthMetadataProcessorSuccess) {
grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy));
}
TEST_F(End2endTest, NonBlockingAuthMetadataProcessorFailure) {
TEST_F(End2endTest, NonBlockingAuthMetadataPluginAndProcessorFailure) {
auto* processor = new TestAuthMetadataProcessor(false);
StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
ResetStub(false);
@ -914,7 +970,24 @@ TEST_F(End2endTest, NonBlockingAuthMetadataProcessorFailure) {
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
}
TEST_F(End2endTest, BlockingAuthMetadataProcessorSuccess) {
TEST_F(End2endTest, BlockingAuthMetadataPluginFailure) {
ResetStub(false);
EchoRequest request;
EchoResponse response;
ClientContext context;
context.set_credentials(
MetadataCredentialsFromPlugin(std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(
"Does not matter, will fail anyway (see 3rd param)", true,
false))));
request.set_message("Hello");
Status s = stub_->Echo(&context, request, &response);
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
}
TEST_F(End2endTest, BlockingAuthMetadataPluginAndProcessorSuccess) {
auto* processor = new TestAuthMetadataProcessor(true);
StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
ResetStub(false);
@ -937,7 +1010,7 @@ TEST_F(End2endTest, BlockingAuthMetadataProcessorSuccess) {
grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy));
}
TEST_F(End2endTest, BlockingAuthMetadataProcessorFailure) {
TEST_F(End2endTest, BlockingAuthMetadataPluginAndProcessorFailure) {
auto* processor = new TestAuthMetadataProcessor(true);
StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
ResetStub(false);

Loading…
Cancel
Save