diff options
author | Julien Boeuf <jboeuf@google.com> | 2015-02-18 12:24:08 -0800 |
---|---|---|
committer | Julien Boeuf <jboeuf@google.com> | 2015-02-19 17:29:41 -0800 |
commit | f47a5cb93d84e89359e4807b19383199b3280ea0 (patch) | |
tree | 0110152495650947f983bbf95746cc7cf175f5de /test/core/security | |
parent | 52978e532679de045db6f6ff99b7130c998d6285 (diff) |
Implementing JWT credentials (a.k.a JWT ID Tokens).
- Not tested end to end yet
Diffstat (limited to 'test/core/security')
-rw-r--r-- | test/core/security/credentials_test.c | 136 | ||||
-rw-r--r-- | test/core/security/fetch_oauth2.c | 2 | ||||
-rw-r--r-- | test/core/security/json_token_test.c | 77 |
3 files changed, 177 insertions, 38 deletions
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index f911db6de1..91229c95c2 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -89,12 +89,17 @@ static const char test_user_data[] = "user data"; static const char test_scope[] = "perm1 perm2"; -static const char test_signed_jwt[] = "signed jwt"; +static const char test_signed_jwt[] = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM4YW" + "U0MDcyZTViYTdmZDkwODg2YzcifQ"; static const char expected_service_account_http_body_prefix[] = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" "assertion="; +static const char test_service_url[] = "https://foo.com/foo.v1"; +static const char other_test_service_url[] = "https://bar.com/bar.v1"; + static char *test_json_key_str(void) { size_t result_len = strlen(test_json_key_str_part1) + strlen(test_json_key_str_part2) + @@ -259,7 +264,8 @@ static void test_iam_creds(void) { test_iam_authorization_token, test_iam_authority_selector); GPR_ASSERT(grpc_credentials_has_request_metadata(creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds)); - grpc_credentials_get_request_metadata(creds, check_iam_metadata, creds); + grpc_credentials_get_request_metadata(creds, test_service_url, + check_iam_metadata, creds); } static void check_ssl_oauth2_composite_metadata( @@ -293,8 +299,9 @@ static void test_ssl_oauth2_composite_creds(void) { !strcmp(creds_array->creds_array[0]->type, GRPC_CREDENTIALS_TYPE_SSL)); GPR_ASSERT( !strcmp(creds_array->creds_array[1]->type, GRPC_CREDENTIALS_TYPE_OAUTH2)); - grpc_credentials_get_request_metadata( - composite_creds, check_ssl_oauth2_composite_metadata, composite_creds); + grpc_credentials_get_request_metadata(composite_creds, test_service_url, + check_ssl_oauth2_composite_metadata, + composite_creds); } static void check_ssl_oauth2_iam_composite_metadata( @@ -338,7 +345,7 @@ static void test_ssl_oauth2_iam_composite_creds(void) { !strcmp(creds_array->creds_array[1]->type, GRPC_CREDENTIALS_TYPE_OAUTH2)); GPR_ASSERT( !strcmp(creds_array->creds_array[2]->type, GRPC_CREDENTIALS_TYPE_IAM)); - grpc_credentials_get_request_metadata(composite_creds, + grpc_credentials_get_request_metadata(composite_creds, test_service_url, check_ssl_oauth2_iam_composite_metadata, composite_creds); } @@ -420,14 +427,14 @@ static void test_compute_engine_creds_success(void) { /* First request: http get should be called. */ grpc_httpcli_set_override(compute_engine_httpcli_get_success_override, httpcli_post_should_not_be_called); - grpc_credentials_get_request_metadata(compute_engine_creds, + grpc_credentials_get_request_metadata(compute_engine_creds, test_service_url, on_oauth2_creds_get_metadata_success, (void *)test_user_data); /* Second request: the cached token should be served directly. */ grpc_httpcli_set_override(httpcli_get_should_not_be_called, httpcli_post_should_not_be_called); - grpc_credentials_get_request_metadata(compute_engine_creds, + grpc_credentials_get_request_metadata(compute_engine_creds, test_service_url, on_oauth2_creds_get_metadata_success, (void *)test_user_data); @@ -442,7 +449,7 @@ static void test_compute_engine_creds_failure(void) { httpcli_post_should_not_be_called); GPR_ASSERT(grpc_credentials_has_request_metadata(compute_engine_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(compute_engine_creds)); - grpc_credentials_get_request_metadata(compute_engine_creds, + grpc_credentials_get_request_metadata(compute_engine_creds, test_service_url, on_oauth2_creds_get_metadata_failure, (void *)test_user_data); grpc_credentials_unref(compute_engine_creds); @@ -468,27 +475,29 @@ static void validate_jwt_encode_and_sign_params( !strcmp(json_key->client_email, "777-abaslkan11hlb6nmim3bpspl31ud@developer." "gserviceaccount.com")); - GPR_ASSERT(!strcmp(scope, test_scope)); + if (scope != NULL) GPR_ASSERT(!strcmp(scope, test_scope)); GPR_ASSERT(!gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime)); } static char *encode_and_sign_jwt_success(const grpc_auth_json_key *json_key, - const char *scope, - gpr_timespec token_lifetime) { + const char *audience, + gpr_timespec token_lifetime, + const char *scope) { validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime); return gpr_strdup(test_signed_jwt); } static char *encode_and_sign_jwt_failure(const grpc_auth_json_key *json_key, - const char *scope, - gpr_timespec token_lifetime) { + const char *audience, + gpr_timespec token_lifetime, + const char *scope) { validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime); return NULL; } static char *encode_and_sign_jwt_should_not_be_called( - const grpc_auth_json_key *json_key, const char *scope, - gpr_timespec token_lifetime) { + const grpc_auth_json_key *json_key, const char *audience, + gpr_timespec token_lifetime, const char *scope) { GPR_ASSERT("grpc_jwt_encode_and_sign should not be called" == NULL); } @@ -533,7 +542,7 @@ static int service_account_httpcli_post_failure( return 1; } -static void test_service_accounts_creds_success(void) { +static void test_service_account_creds_success(void) { char *json_key_string = test_json_key_str(); grpc_credentials *service_account_creds = grpc_service_account_credentials_create(json_key_string, test_scope, @@ -545,7 +554,7 @@ static void test_service_accounts_creds_success(void) { grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); grpc_httpcli_set_override(httpcli_get_should_not_be_called, service_account_httpcli_post_success); - grpc_credentials_get_request_metadata(service_account_creds, + grpc_credentials_get_request_metadata(service_account_creds, test_service_url, on_oauth2_creds_get_metadata_success, (void *)test_user_data); @@ -554,7 +563,7 @@ static void test_service_accounts_creds_success(void) { encode_and_sign_jwt_should_not_be_called); grpc_httpcli_set_override(httpcli_get_should_not_be_called, httpcli_post_should_not_be_called); - grpc_credentials_get_request_metadata(service_account_creds, + grpc_credentials_get_request_metadata(service_account_creds, test_service_url, on_oauth2_creds_get_metadata_success, (void *)test_user_data); @@ -564,7 +573,7 @@ static void test_service_accounts_creds_success(void) { grpc_httpcli_set_override(NULL, NULL); } -static void test_service_accounts_creds_http_failure(void) { +static void test_service_account_creds_http_failure(void) { char *json_key_string = test_json_key_str(); grpc_credentials *service_account_creds = grpc_service_account_credentials_create(json_key_string, test_scope, @@ -575,7 +584,7 @@ static void test_service_accounts_creds_http_failure(void) { grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); grpc_httpcli_set_override(httpcli_get_should_not_be_called, service_account_httpcli_post_failure); - grpc_credentials_get_request_metadata(service_account_creds, + grpc_credentials_get_request_metadata(service_account_creds, test_service_url, on_oauth2_creds_get_metadata_failure, (void *)test_user_data); @@ -584,7 +593,7 @@ static void test_service_accounts_creds_http_failure(void) { grpc_httpcli_set_override(NULL, NULL); } -static void test_service_accounts_creds_signing_failure(void) { +static void test_service_account_creds_signing_failure(void) { char *json_key_string = test_json_key_str(); grpc_credentials *service_account_creds = grpc_service_account_credentials_create(json_key_string, test_scope, @@ -595,13 +604,88 @@ static void test_service_accounts_creds_signing_failure(void) { grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure); grpc_httpcli_set_override(httpcli_get_should_not_be_called, httpcli_post_should_not_be_called); - grpc_credentials_get_request_metadata(service_account_creds, + grpc_credentials_get_request_metadata(service_account_creds, test_service_url, on_oauth2_creds_get_metadata_failure, (void *)test_user_data); gpr_free(json_key_string); grpc_credentials_unref(service_account_creds); grpc_httpcli_set_override(NULL, NULL); + grpc_jwt_encode_and_sign_set_override(NULL); +} + +static void on_jwt_creds_get_metadata_success( + void *user_data, grpc_mdelem **md_elems, size_t num_md, + grpc_credentials_status status) { + char *expected_md_value; + gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt); + GPR_ASSERT(status == GRPC_CREDENTIALS_OK); + GPR_ASSERT(num_md == 1); + GPR_ASSERT( + !strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), "Authorization")); + GPR_ASSERT( + !strcmp(grpc_mdstr_as_c_string(md_elems[0]->value), expected_md_value)); + GPR_ASSERT(user_data != NULL); + GPR_ASSERT(!strcmp((const char *)user_data, test_user_data)); + gpr_free(expected_md_value); +} + +static void on_jwt_creds_get_metadata_failure( + void *user_data, grpc_mdelem **md_elems, size_t num_md, + grpc_credentials_status status) { + GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); + GPR_ASSERT(num_md == 0); + GPR_ASSERT(user_data != NULL); + GPR_ASSERT(!strcmp((const char *)user_data, test_user_data)); +} + +static void test_jwt_creds_success(void) { + char *json_key_string = test_json_key_str(); + grpc_credentials *jwt_creds = grpc_jwt_credentials_create( + json_key_string, grpc_max_auth_token_lifetime); + GPR_ASSERT(grpc_credentials_has_request_metadata(jwt_creds)); + GPR_ASSERT(grpc_credentials_has_request_metadata_only(jwt_creds)); + + /* First request: jwt_encode_and_sign should be called. */ + grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); + grpc_credentials_get_request_metadata(jwt_creds, test_service_url, + on_jwt_creds_get_metadata_success, + (void *)test_user_data); + + /* Second request: the cached token should be served directly. */ + grpc_jwt_encode_and_sign_set_override( + encode_and_sign_jwt_should_not_be_called); + grpc_credentials_get_request_metadata(jwt_creds, test_service_url, + on_jwt_creds_get_metadata_success, + (void *)test_user_data); + + /* Third request: Different service url so jwt_encode_and_sign should be + called again (no caching). */ + grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); + grpc_credentials_get_request_metadata(jwt_creds, other_test_service_url, + on_jwt_creds_get_metadata_success, + (void *)test_user_data); + + gpr_free(json_key_string); + grpc_credentials_unref(jwt_creds); + grpc_jwt_encode_and_sign_set_override(NULL); +} + +static void test_jwt_creds_signing_failure(void) { + char *json_key_string = test_json_key_str(); + grpc_credentials *jwt_creds = grpc_jwt_credentials_create( + json_key_string, grpc_max_auth_token_lifetime); + GPR_ASSERT(grpc_credentials_has_request_metadata(jwt_creds)); + GPR_ASSERT(grpc_credentials_has_request_metadata_only(jwt_creds)); + + grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure); + grpc_credentials_get_request_metadata(jwt_creds, test_service_url, + on_jwt_creds_get_metadata_failure, + (void *)test_user_data); + + gpr_free(json_key_string); + grpc_credentials_unref(jwt_creds); + grpc_jwt_encode_and_sign_set_override(NULL); } int main(int argc, char **argv) { @@ -618,8 +702,10 @@ int main(int argc, char **argv) { test_ssl_oauth2_iam_composite_creds(); test_compute_engine_creds_success(); test_compute_engine_creds_failure(); - test_service_accounts_creds_success(); - test_service_accounts_creds_http_failure(); - test_service_accounts_creds_signing_failure(); + test_service_account_creds_success(); + test_service_account_creds_http_failure(); + test_service_account_creds_signing_failure(); + test_jwt_creds_success(); + test_jwt_creds_signing_failure(); return 0; } diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c index 6315087448..951281d5b3 100644 --- a/test/core/security/fetch_oauth2.c +++ b/test/core/security/fetch_oauth2.c @@ -162,7 +162,7 @@ int main(int argc, char **argv) { gpr_cv_init(&sync.cv); sync.is_done = 0; - grpc_credentials_get_request_metadata(creds, on_oauth2_response, &sync); + grpc_credentials_get_request_metadata(creds, "", on_oauth2_response, &sync); gpr_mu_lock(&sync.mu); while (!sync.is_done) gpr_cv_wait(&sync.cv, &sync.mu, gpr_inf_future); diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c index 8615fca5fb..eed0fdf332 100644 --- a/test/core/security/json_token_test.c +++ b/test/core/security/json_token_test.c @@ -76,6 +76,8 @@ static const char test_json_key_str_part3[] = static const char test_scope[] = "myperm1 myperm2"; +static const char test_service_url[] = "https://foo.com/foo.v1"; + static char *test_json_key_str(const char *bad_part3) { const char *part3 = bad_part3 != NULL ? bad_part3 : test_json_key_str_part3; size_t result_len = strlen(test_json_key_str_part1) + @@ -229,12 +231,15 @@ static void check_jwt_header(grpc_json *header) { grpc_json *ptr; grpc_json *alg = NULL; grpc_json *typ = NULL; + grpc_json *kid = NULL; for (ptr = header->child; ptr; ptr = ptr->next) { if (strcmp(ptr->key, "alg") == 0) { alg = ptr; } else if (strcmp(ptr->key, "typ") == 0) { typ = ptr; + } else if (strcmp(ptr->key, "kid") == 0) { + kid = ptr; } } GPR_ASSERT(alg != NULL); @@ -244,9 +249,14 @@ static void check_jwt_header(grpc_json *header) { GPR_ASSERT(typ != NULL); GPR_ASSERT(typ->type == GRPC_JSON_STRING); GPR_ASSERT(!strcmp(typ->value, "JWT")); + + GPR_ASSERT(kid != NULL); + GPR_ASSERT(kid->type == GRPC_JSON_STRING); + GPR_ASSERT(!strcmp(kid->value, "e6b5137873db8d2ef81e06a47289e6434ec8a165")); } -static void check_jwt_claim(grpc_json *claim) { +static void check_jwt_claim(grpc_json *claim, const char *expected_audience, + const char *expected_scope) { gpr_timespec expiration = {0, 0}; gpr_timespec issue_time = {0, 0}; gpr_timespec parsed_lifetime; @@ -255,11 +265,14 @@ static void check_jwt_claim(grpc_json *claim) { grpc_json *aud = NULL; grpc_json *exp = NULL; grpc_json *iat = NULL; + grpc_json *sub = NULL; grpc_json *ptr; for (ptr = claim->child; ptr; ptr = ptr->next) { if (strcmp(ptr->key, "iss") == 0) { iss = ptr; + } else if (strcmp(ptr->key, "sub") == 0) { + sub = ptr; } else if (strcmp(ptr->key, "scope") == 0) { scope = ptr; } else if (strcmp(ptr->key, "aud") == 0) { @@ -278,14 +291,22 @@ static void check_jwt_claim(grpc_json *claim) { iss->value, "777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount.com")); - GPR_ASSERT(scope != NULL); - GPR_ASSERT(scope->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(scope->value, test_scope)); + if (expected_scope != NULL) { + GPR_ASSERT(scope != NULL); + GPR_ASSERT(sub == NULL); + GPR_ASSERT(scope->type == GRPC_JSON_STRING); + GPR_ASSERT(!strcmp(scope->value, expected_scope)); + } else { + /* Claims without scope must have a sub. */ + GPR_ASSERT(scope == NULL); + GPR_ASSERT(sub != NULL); + GPR_ASSERT(sub->type == GRPC_JSON_STRING); + GPR_ASSERT(!strcmp(iss->value, sub->value)); + } GPR_ASSERT(aud != NULL); GPR_ASSERT(aud->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(aud->value, - "https://www.googleapis.com/oauth2/v3/token")); + GPR_ASSERT(!strcmp(aud->value, expected_audience)); GPR_ASSERT(exp != NULL); GPR_ASSERT(exp->type == GRPC_JSON_NUMBER); @@ -324,7 +345,28 @@ static void check_jwt_signature(const char *b64_signature, RSA *rsa_key, if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); } -static void test_jwt_encode_and_sign(void) { +static char *service_account_creds_jwt_encode_and_sign( + const grpc_auth_json_key *key) { + return grpc_jwt_encode_and_sign(key, GRPC_JWT_OAUTH2_AUDIENCE, + grpc_max_auth_token_lifetime, test_scope); +} + +static char *jwt_creds_jwt_encode_and_sign(const grpc_auth_json_key *key) { + return grpc_jwt_encode_and_sign(key, test_service_url, + grpc_max_auth_token_lifetime, NULL); +} + +static void service_account_creds_check_jwt_claim(grpc_json *claim) { + check_jwt_claim(claim, GRPC_JWT_OAUTH2_AUDIENCE, test_scope); +} + +static void jwt_creds_check_jwt_claim(grpc_json *claim) { + check_jwt_claim(claim, test_service_url, NULL); +} + +static void test_jwt_encode_and_sign( + char *(*jwt_encode_and_sign_func)(const grpc_auth_json_key *), + void (*check_jwt_claim_func)(grpc_json *)) { char *json_string = test_json_key_str(NULL); grpc_json *parsed_header = NULL; grpc_json *parsed_claim = NULL; @@ -333,8 +375,7 @@ static void test_jwt_encode_and_sign(void) { grpc_auth_json_key_create_from_string(json_string); const char *b64_signature; size_t offset = 0; - char *jwt = grpc_jwt_encode_and_sign(&json_key, test_scope, - grpc_max_auth_token_lifetime); + char *jwt = jwt_encode_and_sign_func(&json_key); const char *dot = strchr(jwt, '.'); GPR_ASSERT(dot != NULL); parsed_header = parse_json_part_from_jwt(jwt, dot - jwt, &scratchpad); @@ -346,9 +387,10 @@ static void test_jwt_encode_and_sign(void) { dot = strchr(jwt + offset, '.'); GPR_ASSERT(dot != NULL); - parsed_claim = parse_json_part_from_jwt(jwt + offset, dot - (jwt + offset), &scratchpad); + parsed_claim = + parse_json_part_from_jwt(jwt + offset, dot - (jwt + offset), &scratchpad); GPR_ASSERT(parsed_claim != NULL); - check_jwt_claim(parsed_claim); + check_jwt_claim_func(parsed_claim); offset = dot - jwt + 1; grpc_json_destroy(parsed_claim); gpr_free(scratchpad); @@ -363,6 +405,16 @@ static void test_jwt_encode_and_sign(void) { gpr_free(jwt); } +static void test_service_account_creds_jwt_encode_and_sign(void) { + test_jwt_encode_and_sign(service_account_creds_jwt_encode_and_sign, + service_account_creds_check_jwt_claim); +} + +static void test_jwt_creds_jwt_encode_and_sign(void) { + test_jwt_encode_and_sign(jwt_creds_jwt_encode_and_sign, + jwt_creds_check_jwt_claim); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_parse_json_key_success(); @@ -372,6 +424,7 @@ int main(int argc, char **argv) { test_parse_json_key_failure_no_client_email(); test_parse_json_key_failure_no_private_key_id(); test_parse_json_key_failure_no_private_key(); - test_jwt_encode_and_sign(); + test_service_account_creds_jwt_encode_and_sign(); + test_jwt_creds_jwt_encode_and_sign(); return 0; } |