diff options
author | murgatroid99 <mlumish@google.com> | 2015-02-23 10:29:08 -0800 |
---|---|---|
committer | murgatroid99 <mlumish@google.com> | 2015-02-23 10:29:08 -0800 |
commit | 4d736a024ca45738412f7cf73994393b7f162811 (patch) | |
tree | e2b5085817619e9aba3e4f88407f344b36e911af /src/core/security/credentials.c | |
parent | 2822e9ad7598a68597e49e8f1875486aa12bf267 (diff) | |
parent | 8b131922438d96579cb315777ca980e094883496 (diff) |
Resolved merge conflicts
Diffstat (limited to 'src/core/security/credentials.c')
-rw-r--r-- | src/core/security/credentials.c | 158 |
1 files changed, 144 insertions, 14 deletions
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index a21c27bff9..42d1a900fc 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -33,6 +33,10 @@ #include "src/core/security/credentials.h" +#include <string.h> +#include <stdio.h> + +#include "src/core/json/json.h" #include "src/core/httpcli/httpcli.h" #include "src/core/iomgr/iomgr.h" #include "src/core/security/json_token.h" @@ -42,14 +46,9 @@ #include <grpc/support/sync.h> #include <grpc/support/time.h> -#include "src/core/json/json.h" - -#include <string.h> -#include <stdio.h> - /* -- Constants. -- */ -#define GRPC_OAUTH2_TOKEN_REFRESH_THRESHOLD_SECS 60 +#define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60 #define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata" #define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \ @@ -113,6 +112,7 @@ int grpc_credentials_has_request_metadata_only(grpc_credentials *creds) { } void grpc_credentials_get_request_metadata(grpc_credentials *creds, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { if (creds == NULL || !grpc_credentials_has_request_metadata(creds) || @@ -122,7 +122,7 @@ void grpc_credentials_get_request_metadata(grpc_credentials *creds, } return; } - creds->vtable->get_request_metadata(creds, cb, user_data); + creds->vtable->get_request_metadata(creds, service_url, cb, user_data); } void grpc_server_credentials_release(grpc_server_credentials *creds) { @@ -288,6 +288,128 @@ grpc_server_credentials *grpc_ssl_server_credentials_create( return &c->base; } +/* -- Jwt credentials -- */ + +typedef struct { + grpc_credentials base; + grpc_mdctx *md_ctx; + + /* Have a simple cache for now with just 1 entry. We could have a map based on + the service_url for a more sophisticated one. */ + gpr_mu cache_mu; + struct { + grpc_mdelem *jwt_md; + char *service_url; + gpr_timespec jwt_expiration; + } cached; + + grpc_auth_json_key key; + gpr_timespec jwt_lifetime; +} grpc_jwt_credentials; + +static void jwt_reset_cache(grpc_jwt_credentials *c) { + if (c->cached.jwt_md != NULL) { + grpc_mdelem_unref(c->cached.jwt_md); + c->cached.jwt_md = NULL; + } + if (c->cached.service_url != NULL) { + gpr_free(c->cached.service_url); + c->cached.service_url = NULL; + } + c->cached.jwt_expiration = gpr_inf_past; +} + +static void jwt_destroy(grpc_credentials *creds) { + grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds; + grpc_auth_json_key_destruct(&c->key); + jwt_reset_cache(c); + gpr_mu_destroy(&c->cache_mu); + grpc_mdctx_unref(c->md_ctx); + gpr_free(c); +} + +static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; } + +static int jwt_has_request_metadata_only(const grpc_credentials *creds) { + return 1; +} + + +static void jwt_get_request_metadata(grpc_credentials *creds, + const char *service_url, + grpc_credentials_metadata_cb cb, + void *user_data) { + grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds; + gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, + 0}; + + /* See if we can return a cached jwt. */ + grpc_mdelem *jwt_md = NULL; + { + gpr_mu_lock(&c->cache_mu); + if (c->cached.service_url != NULL && + !strcmp(c->cached.service_url, service_url) && + c->cached.jwt_md != NULL && + (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()), + refresh_threshold) > 0)) { + jwt_md = grpc_mdelem_ref(c->cached.jwt_md); + } + gpr_mu_unlock(&c->cache_mu); + } + + if (jwt_md == NULL) { + char *jwt = NULL; + /* Generate a new jwt. */ + gpr_mu_lock(&c->cache_mu); + jwt_reset_cache(c); + jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL); + if (jwt != NULL) { + char *md_value; + gpr_asprintf(&md_value, "Bearer %s", jwt); + gpr_free(jwt); + c->cached.jwt_expiration = gpr_time_add(gpr_now(), c->jwt_lifetime); + c->cached.service_url = gpr_strdup(service_url); + c->cached.jwt_md = grpc_mdelem_from_strings( + c->md_ctx, GRPC_AUTHORIZATION_METADATA_KEY, md_value); + gpr_free(md_value); + jwt_md = grpc_mdelem_ref(c->cached.jwt_md); + } + gpr_mu_unlock(&c->cache_mu); + } + + if (jwt_md != NULL) { + cb(user_data, &jwt_md, 1, GRPC_CREDENTIALS_OK); + grpc_mdelem_unref(jwt_md); + } else { + cb(user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); + } +} + +static grpc_credentials_vtable jwt_vtable = { + jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only, + jwt_get_request_metadata}; + +grpc_credentials *grpc_jwt_credentials_create(const char *json_key, + gpr_timespec token_lifetime) { + grpc_jwt_credentials *c; + grpc_auth_json_key key = grpc_auth_json_key_create_from_string(json_key); + if (!grpc_auth_json_key_is_valid(&key)) { + gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation"); + return NULL; + } + c = gpr_malloc(sizeof(grpc_jwt_credentials)); + memset(c, 0, sizeof(grpc_jwt_credentials)); + c->base.type = GRPC_CREDENTIALS_TYPE_JWT; + gpr_ref_init(&c->base.refcount, 1); + c->base.vtable = &jwt_vtable; + c->md_ctx = grpc_mdctx_create(); + c->key = key; + c->jwt_lifetime = token_lifetime; + gpr_mu_init(&c->cache_mu); + jwt_reset_cache(c); + return &c->base; +} + /* -- Oauth2TokenFetcher credentials -- */ /* This object is a base for credentials that need to acquire an oauth2 token @@ -439,10 +561,11 @@ static void on_oauth2_token_fetcher_http_response( } static void oauth2_token_fetcher_get_request_metadata( - grpc_credentials *creds, grpc_credentials_metadata_cb cb, void *user_data) { + grpc_credentials *creds, const char *service_url, + grpc_credentials_metadata_cb cb, void *user_data) { grpc_oauth2_token_fetcher_credentials *c = (grpc_oauth2_token_fetcher_credentials *)creds; - gpr_timespec refresh_threshold = {GRPC_OAUTH2_TOKEN_REFRESH_THRESHOLD_SECS, + gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, 0}; grpc_mdelem *cached_access_token_md = NULL; { @@ -535,7 +658,8 @@ static void service_account_fetch_oauth2( "application/x-www-form-urlencoded"}; grpc_httpcli_request request; char *body = NULL; - char *jwt = grpc_jwt_encode_and_sign(&c->key, c->scope, c->token_lifetime); + char *jwt = grpc_jwt_encode_and_sign(&c->key, GRPC_JWT_OAUTH2_AUDIENCE, + c->token_lifetime, c->scope); if (jwt == NULL) { grpc_httpcli_response response; memset(&response, 0, sizeof(grpc_httpcli_response)); @@ -616,6 +740,7 @@ void on_simulated_token_fetch_done(void *user_data, int success) { } static void fake_oauth2_get_request_metadata(grpc_credentials *creds, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds; @@ -709,6 +834,7 @@ typedef struct { size_t creds_index; grpc_mdelem **md_elems; size_t num_md; + char *service_url; void *user_data; grpc_credentials_metadata_cb cb; } grpc_composite_credentials_metadata_context; @@ -754,6 +880,7 @@ static void composite_md_context_destroy( grpc_mdelem_unref(ctx->md_elems[i]); } gpr_free(ctx->md_elems); + if (ctx->service_url != NULL) gpr_free(ctx->service_url); gpr_free(ctx); } @@ -783,8 +910,8 @@ static void composite_metadata_cb(void *user_data, grpc_mdelem **md_elems, grpc_credentials *inner_creds = ctx->composite_creds->inner.creds_array[ctx->creds_index++]; if (grpc_credentials_has_request_metadata(inner_creds)) { - grpc_credentials_get_request_metadata(inner_creds, composite_metadata_cb, - ctx); + grpc_credentials_get_request_metadata(inner_creds, ctx->service_url, + composite_metadata_cb, ctx); return; } } @@ -795,6 +922,7 @@ static void composite_metadata_cb(void *user_data, grpc_mdelem **md_elems, } static void composite_get_request_metadata(grpc_credentials *creds, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_composite_credentials *c = (grpc_composite_credentials *)creds; @@ -805,14 +933,15 @@ static void composite_get_request_metadata(grpc_credentials *creds, } ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context)); memset(ctx, 0, sizeof(grpc_composite_credentials_metadata_context)); + ctx->service_url = gpr_strdup(service_url); ctx->user_data = user_data; ctx->cb = cb; ctx->composite_creds = c; while (ctx->creds_index < c->inner.num_creds) { grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++]; if (grpc_credentials_has_request_metadata(inner_creds)) { - grpc_credentials_get_request_metadata(inner_creds, composite_metadata_cb, - ctx); + grpc_credentials_get_request_metadata(inner_creds, service_url, + composite_metadata_cb, ctx); return; } } @@ -916,6 +1045,7 @@ static int iam_has_request_metadata_only(const grpc_credentials *creds) { } static void iam_get_request_metadata(grpc_credentials *creds, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_iam_credentials *c = (grpc_iam_credentials *)creds; |