aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/security/credentials
diff options
context:
space:
mode:
authorGravatar Mark D. Roth <roth@google.com>2016-06-29 07:50:18 -0700
committerGravatar Mark D. Roth <roth@google.com>2016-06-29 07:50:18 -0700
commit89ebe55985a705ddee72d28c1b93cfa681585a8c (patch)
treef062eab0150ddbdcfd486726aa12955de34c7a57 /src/core/lib/security/credentials
parent07cd9c9e064e636c432500724bf5f91ad15d041a (diff)
parent76d24420d7a6471dc3b135b62318277991ebdb08 (diff)
Merge branch 'filter_call_init_failure' into filter_api
Diffstat (limited to 'src/core/lib/security/credentials')
-rw-r--r--src/core/lib/security/credentials/credentials.c2
-rw-r--r--src/core/lib/security/credentials/credentials.h1
-rw-r--r--src/core/lib/security/credentials/fake/fake_credentials.c7
-rw-r--r--src/core/lib/security/credentials/google_default/google_default_credentials.c105
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_verifier.c35
-rw-r--r--src/core/lib/security/credentials/oauth2/oauth2_credentials.c21
-rw-r--r--src/core/lib/security/credentials/oauth2/oauth2_credentials.h2
7 files changed, 125 insertions, 48 deletions
diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c
index f45a8d8ff6..0eadaec191 100644
--- a/src/core/lib/security/credentials/credentials.c
+++ b/src/core/lib/security/credentials/credentials.c
@@ -58,6 +58,7 @@ grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
void *user_data) {
grpc_credentials_metadata_request *r =
gpr_malloc(sizeof(grpc_credentials_metadata_request));
+ memset(&r->response, 0, sizeof(r->response));
r->creds = grpc_call_credentials_ref(creds);
r->cb = cb;
r->user_data = user_data;
@@ -67,6 +68,7 @@ grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
void grpc_credentials_metadata_request_destroy(
grpc_credentials_metadata_request *r) {
grpc_call_credentials_unref(r->creds);
+ grpc_http_response_destroy(&r->response);
gpr_free(r);
}
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
index 15dcfe473d..ce235e3a1d 100644
--- a/src/core/lib/security/credentials/credentials.h
+++ b/src/core/lib/security/credentials/credentials.h
@@ -225,6 +225,7 @@ grpc_server_credentials *grpc_find_server_credentials_in_args(
typedef struct {
grpc_call_credentials *creds;
grpc_credentials_metadata_cb cb;
+ grpc_http_response response;
void *user_data;
} grpc_credentials_metadata_request;
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c
index 005777d3c6..ee6d964de1 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.c
+++ b/src/core/lib/security/credentials/fake/fake_credentials.c
@@ -95,7 +95,7 @@ static void md_only_test_destruct(grpc_call_credentials *creds) {
}
static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
- void *user_data, bool success) {
+ void *user_data, grpc_error *error) {
grpc_credentials_metadata_request *r =
(grpc_credentials_metadata_request *)user_data;
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
@@ -113,8 +113,9 @@ static void md_only_test_get_request_metadata(
if (c->is_async) {
grpc_credentials_metadata_request *cb_arg =
grpc_credentials_metadata_request_create(creds, cb, user_data);
- grpc_executor_enqueue(
- grpc_closure_create(on_simulated_token_fetch_done, cb_arg), true);
+ grpc_executor_push(
+ grpc_closure_create(on_simulated_token_fetch_done, cb_arg),
+ GRPC_ERROR_NONE);
} else {
cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
}
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.c b/src/core/lib/security/credentials/google_default/google_default_credentials.c
index 98df68e7b3..312a3d4f90 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.c
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.c
@@ -41,11 +41,12 @@
#include "src/core/lib/http/httpcli.h"
#include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
#include "src/core/lib/support/env.h"
-#include "src/core/lib/support/load_file.h"
+#include "src/core/lib/support/string.h"
#include "src/core/lib/surface/api_trace.h"
/* -- Constants. -- */
@@ -66,18 +67,20 @@ typedef struct {
grpc_polling_entity pollent;
int is_done;
int success;
+ grpc_http_response response;
} compute_engine_detector;
-static void on_compute_engine_detection_http_response(
- grpc_exec_ctx *exec_ctx, void *user_data,
- const grpc_http_response *response) {
+static void on_compute_engine_detection_http_response(grpc_exec_ctx *exec_ctx,
+ void *user_data,
+ grpc_error *error) {
compute_engine_detector *detector = (compute_engine_detector *)user_data;
- if (response != NULL && response->status == 200 && response->hdr_count > 0) {
+ if (error == GRPC_ERROR_NONE && detector->response.status == 200 &&
+ detector->response.hdr_count > 0) {
/* Internet providers can return a generic response to all requests, so
it is necessary to check that metadata header is present also. */
size_t i;
- for (i = 0; i < response->hdr_count; i++) {
- grpc_http_header *header = &response->hdrs[i];
+ for (i = 0; i < detector->response.hdr_count; i++) {
+ grpc_http_header *header = &detector->response.hdrs[i];
if (strcmp(header->key, "Metadata-Flavor") == 0 &&
strcmp(header->value, "Google") == 0) {
detector->success = 1;
@@ -87,11 +90,13 @@ static void on_compute_engine_detection_http_response(
}
gpr_mu_lock(g_polling_mu);
detector->is_done = 1;
- grpc_pollset_kick(grpc_polling_entity_pollset(&detector->pollent), NULL);
+ GRPC_LOG_IF_ERROR(
+ "Pollset kick",
+ grpc_pollset_kick(grpc_polling_entity_pollset(&detector->pollent), NULL));
gpr_mu_unlock(g_polling_mu);
}
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool s) {
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *e) {
grpc_pollset_destroy(p);
}
@@ -112,6 +117,7 @@ static int is_stack_running_on_compute_engine(void) {
detector.is_done = 0;
detector.success = 0;
+ memset(&detector.response, 0, sizeof(detector.response));
memset(&request, 0, sizeof(grpc_httpcli_request));
request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST;
request.http.path = "/";
@@ -121,18 +127,25 @@ static int is_stack_running_on_compute_engine(void) {
grpc_httpcli_get(
&exec_ctx, &context, &detector.pollent, &request,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
- on_compute_engine_detection_http_response, &detector);
+ grpc_closure_create(on_compute_engine_detection_http_response, &detector),
+ &detector.response);
- grpc_exec_ctx_finish(&exec_ctx);
+ grpc_exec_ctx_flush(&exec_ctx);
/* Block until we get the response. This is not ideal but this should only be
called once for the lifetime of the process by the default credentials. */
gpr_mu_lock(g_polling_mu);
while (!detector.is_done) {
grpc_pollset_worker *worker = NULL;
- grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&detector.pollent),
- &worker, gpr_now(GPR_CLOCK_MONOTONIC),
- gpr_inf_future(GPR_CLOCK_MONOTONIC));
+ if (!GRPC_LOG_IF_ERROR(
+ "pollset_work",
+ grpc_pollset_work(&exec_ctx,
+ grpc_polling_entity_pollset(&detector.pollent),
+ &worker, gpr_now(GPR_CLOCK_MONOTONIC),
+ gpr_inf_future(GPR_CLOCK_MONOTONIC)))) {
+ detector.is_done = 1;
+ detector.success = 0;
+ }
}
gpr_mu_unlock(g_polling_mu);
@@ -146,24 +159,37 @@ static int is_stack_running_on_compute_engine(void) {
g_polling_mu = NULL;
gpr_free(grpc_polling_entity_pollset(&detector.pollent));
+ grpc_http_response_destroy(&detector.response);
return detector.success;
}
/* Takes ownership of creds_path if not NULL. */
-static grpc_call_credentials *create_default_creds_from_path(char *creds_path) {
+static grpc_error *create_default_creds_from_path(
+ char *creds_path, grpc_call_credentials **creds) {
grpc_json *json = NULL;
grpc_auth_json_key key;
grpc_auth_refresh_token token;
grpc_call_credentials *result = NULL;
gpr_slice creds_data = gpr_empty_slice();
- int file_ok = 0;
- if (creds_path == NULL) goto end;
- creds_data = gpr_load_file(creds_path, 0, &file_ok);
- if (!file_ok) goto end;
+ grpc_error *error = GRPC_ERROR_NONE;
+ if (creds_path == NULL) {
+ error = GRPC_ERROR_CREATE("creds_path unset");
+ goto end;
+ }
+ error = grpc_load_file(creds_path, 0, &creds_data);
+ if (error != GRPC_ERROR_NONE) {
+ goto end;
+ }
json = grpc_json_parse_string_with_len(
(char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data));
- if (json == NULL) goto end;
+ if (json == NULL) {
+ char *dump = gpr_dump_slice(creds_data, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ error = grpc_error_set_str(GRPC_ERROR_CREATE("Failed to parse JSON"),
+ GRPC_ERROR_STR_RAW_BYTES, dump);
+ gpr_free(dump);
+ goto end;
+ }
/* First, try an auth json key. */
key = grpc_auth_json_key_create_from_json(json);
@@ -171,6 +197,11 @@ static grpc_call_credentials *create_default_creds_from_path(char *creds_path) {
result =
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
key, grpc_max_auth_token_lifetime());
+ if (result == NULL) {
+ error = GRPC_ERROR_CREATE(
+ "grpc_service_account_jwt_access_credentials_create_from_auth_json_"
+ "key failed");
+ }
goto end;
}
@@ -179,19 +210,28 @@ static grpc_call_credentials *create_default_creds_from_path(char *creds_path) {
if (grpc_auth_refresh_token_is_valid(&token)) {
result =
grpc_refresh_token_credentials_create_from_auth_refresh_token(token);
+ if (result == NULL) {
+ error = GRPC_ERROR_CREATE(
+ "grpc_refresh_token_credentials_create_from_auth_refresh_token "
+ "failed");
+ }
goto end;
}
end:
+ GPR_ASSERT((result == NULL) + (error == GRPC_ERROR_NONE) == 1);
if (creds_path != NULL) gpr_free(creds_path);
gpr_slice_unref(creds_data);
if (json != NULL) grpc_json_destroy(json);
- return result;
+ *creds = result;
+ return error;
}
grpc_channel_credentials *grpc_google_default_credentials_create(void) {
grpc_channel_credentials *result = NULL;
grpc_call_credentials *call_creds = NULL;
+ grpc_error *error = GRPC_ERROR_CREATE("Failed to create Google credentials");
+ grpc_error *err;
GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
@@ -205,14 +245,16 @@ grpc_channel_credentials *grpc_google_default_credentials_create(void) {
}
/* First, try the environment variable. */
- call_creds = create_default_creds_from_path(
- gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
- if (call_creds != NULL) goto end;
+ err = create_default_creds_from_path(
+ gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds);
+ if (err == GRPC_ERROR_NONE) goto end;
+ error = grpc_error_add_child(error, err);
/* Then the well-known file. */
- call_creds = create_default_creds_from_path(
- grpc_get_well_known_google_credentials_file_path());
- if (call_creds != NULL) goto end;
+ err = create_default_creds_from_path(
+ grpc_get_well_known_google_credentials_file_path(), &call_creds);
+ if (err == GRPC_ERROR_NONE) goto end;
+ error = grpc_error_add_child(error, err);
/* At last try to see if we're on compute engine (do the detection only once
since it requires a network test). */
@@ -221,6 +263,10 @@ grpc_channel_credentials *grpc_google_default_credentials_create(void) {
compute_engine_detection_done = 1;
if (need_compute_engine_creds) {
call_creds = grpc_google_compute_engine_credentials_create(NULL);
+ if (call_creds == NULL) {
+ error = grpc_error_add_child(
+ error, GRPC_ERROR_CREATE("Failed to get credentials from network"));
+ }
}
}
@@ -244,6 +290,11 @@ end:
}
}
gpr_mu_unlock(&g_state_mu);
+ if (result == NULL) {
+ GRPC_LOG_IF_ERROR("grpc_google_default_credentials_create", error);
+ } else {
+ GRPC_ERROR_UNREF(error);
+ }
return result;
}
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c
index 1f67db103c..73eb2e3258 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.c
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c
@@ -45,6 +45,7 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
+#include <grpc/support/useful.h>
#include <openssl/pem.h>
/* --- Utils. --- */
@@ -320,6 +321,12 @@ grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
/* --- verifier_cb_ctx object. --- */
+typedef enum {
+ HTTP_RESPONSE_OPENID = 0,
+ HTTP_RESPONSE_KEYS,
+ HTTP_RESPONSE_COUNT /* must be last */
+} http_response_index;
+
typedef struct {
grpc_jwt_verifier *verifier;
grpc_polling_entity pollent;
@@ -330,6 +337,7 @@ typedef struct {
gpr_slice signed_data;
void *user_data;
grpc_jwt_verification_done_cb user_cb;
+ grpc_http_response responses[HTTP_RESPONSE_COUNT];
} verifier_cb_ctx;
/* Takes ownership of the header, claims and signature. */
@@ -360,6 +368,9 @@ void verifier_cb_ctx_destroy(verifier_cb_ctx *ctx) {
gpr_slice_unref(ctx->signature);
gpr_slice_unref(ctx->signed_data);
jose_header_destroy(ctx->header);
+ for (size_t i = 0; i < HTTP_RESPONSE_COUNT; i++) {
+ grpc_http_response_destroy(&ctx->responses[i]);
+ }
/* TODO: see what to do with claims... */
gpr_free(ctx);
}
@@ -574,9 +585,9 @@ end:
}
static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
- const grpc_httpcli_response *response) {
- grpc_json *json = json_from_http(response);
+ grpc_error *error) {
verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
+ grpc_json *json = json_from_http(&ctx->responses[HTTP_RESPONSE_KEYS]);
EVP_PKEY *verification_key = NULL;
grpc_jwt_verifier_status status = GRPC_JWT_VERIFIER_GENERIC_ERROR;
grpc_jwt_claims *claims = NULL;
@@ -615,10 +626,11 @@ end:
}
static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
- const grpc_httpcli_response *response) {
+ grpc_error *error) {
const grpc_json *cur;
- grpc_json *json = json_from_http(response);
verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
+ const grpc_http_response *response = &ctx->responses[HTTP_RESPONSE_OPENID];
+ grpc_json *json = json_from_http(response);
grpc_httpcli_request req;
const char *jwks_uri;
@@ -644,10 +656,12 @@ static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
} else {
*(req.host + (req.http.path - jwks_uri)) = '\0';
}
+
grpc_httpcli_get(
exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, &req,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
- on_keys_retrieved, ctx);
+ grpc_closure_create(on_keys_retrieved, ctx),
+ &ctx->responses[HTTP_RESPONSE_KEYS]);
grpc_json_destroy(json);
gpr_free(req.host);
return;
@@ -689,12 +703,13 @@ static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain,
static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
verifier_cb_ctx *ctx) {
const char *at_sign;
- grpc_httpcli_response_cb http_cb;
+ grpc_closure *http_cb;
char *path_prefix = NULL;
const char *iss;
grpc_httpcli_request req;
memset(&req, 0, sizeof(grpc_httpcli_request));
req.handshaker = &grpc_httpcli_ssl;
+ http_response_index rsp_idx;
GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL);
iss = ctx->claims->iss;
@@ -733,7 +748,8 @@ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
*(path_prefix++) = '\0';
gpr_asprintf(&req.http.path, "/%s/%s", path_prefix, iss);
}
- http_cb = on_keys_retrieved;
+ http_cb = grpc_closure_create(on_keys_retrieved, ctx);
+ rsp_idx = HTTP_RESPONSE_KEYS;
} else {
req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss);
path_prefix = strchr(req.host, '/');
@@ -744,13 +760,14 @@ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
gpr_asprintf(&req.http.path, "/%s%s", path_prefix,
GRPC_OPENID_CONFIG_URL_SUFFIX);
}
- http_cb = on_openid_config_retrieved;
+ http_cb = grpc_closure_create(on_openid_config_retrieved, ctx);
+ rsp_idx = HTTP_RESPONSE_OPENID;
}
grpc_httpcli_get(
exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, &req,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
- http_cb, ctx);
+ http_cb, &ctx->responses[rsp_idx]);
gpr_free(req.host);
gpr_free(req.http.path);
return;
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
index 268026b9f0..1102553dd3 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
@@ -216,9 +216,9 @@ end:
return status;
}
-static void on_oauth2_token_fetcher_http_response(
- grpc_exec_ctx *exec_ctx, void *user_data,
- const grpc_http_response *response) {
+static void on_oauth2_token_fetcher_http_response(grpc_exec_ctx *exec_ctx,
+ void *user_data,
+ grpc_error *error) {
grpc_credentials_metadata_request *r =
(grpc_credentials_metadata_request *)user_data;
grpc_oauth2_token_fetcher_credentials *c =
@@ -226,9 +226,11 @@ static void on_oauth2_token_fetcher_http_response(
gpr_timespec token_lifetime;
grpc_credentials_status status;
+ GRPC_LOG_IF_ERROR("oauth_fetch", GRPC_ERROR_REF(error));
+
gpr_mu_lock(&c->mu);
status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
- response, &c->access_token_md, &token_lifetime);
+ &r->response, &c->access_token_md, &token_lifetime);
if (status == GRPC_CREDENTIALS_OK) {
c->token_expiration =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
@@ -296,7 +298,7 @@ static grpc_call_credentials_vtable compute_engine_vtable = {
static void compute_engine_fetch_oauth2(
grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
grpc_httpcli_context *httpcli_context, grpc_polling_entity *pollent,
- grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
+ grpc_iomgr_cb_func response_cb, gpr_timespec deadline) {
grpc_http_header header = {"Metadata-Flavor", "Google"};
grpc_httpcli_request request;
memset(&request, 0, sizeof(grpc_httpcli_request));
@@ -305,7 +307,8 @@ static void compute_engine_fetch_oauth2(
request.http.hdr_count = 1;
request.http.hdrs = &header;
grpc_httpcli_get(exec_ctx, httpcli_context, pollent, &request, deadline,
- response_cb, metadata_req);
+ grpc_closure_create(response_cb, metadata_req),
+ &metadata_req->response);
}
grpc_call_credentials *grpc_google_compute_engine_credentials_create(
@@ -337,7 +340,7 @@ static grpc_call_credentials_vtable refresh_token_vtable = {
static void refresh_token_fetch_oauth2(
grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
grpc_httpcli_context *httpcli_context, grpc_polling_entity *pollent,
- grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
+ grpc_iomgr_cb_func response_cb, gpr_timespec deadline) {
grpc_google_refresh_token_credentials *c =
(grpc_google_refresh_token_credentials *)metadata_req->creds;
grpc_http_header header = {"Content-Type",
@@ -354,7 +357,9 @@ static void refresh_token_fetch_oauth2(
request.http.hdrs = &header;
request.handshaker = &grpc_httpcli_ssl;
grpc_httpcli_post(exec_ctx, httpcli_context, pollent, &request, body,
- strlen(body), deadline, response_cb, metadata_req);
+ strlen(body), deadline,
+ grpc_closure_create(response_cb, metadata_req),
+ &metadata_req->response);
gpr_free(body);
}
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
index 3bc8360a41..7f6f205c22 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
@@ -71,7 +71,7 @@ typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx,
grpc_credentials_metadata_request *req,
grpc_httpcli_context *http_context,
grpc_polling_entity *pollent,
- grpc_httpcli_response_cb response_cb,
+ grpc_iomgr_cb_func cb,
gpr_timespec deadline);
typedef struct {
grpc_call_credentials base;