aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/core/security
diff options
context:
space:
mode:
authorGravatar Julien Boeuf <jboeuf@google.com>2015-02-18 12:24:08 -0800
committerGravatar Julien Boeuf <jboeuf@google.com>2015-02-19 17:29:41 -0800
commitf47a5cb93d84e89359e4807b19383199b3280ea0 (patch)
tree0110152495650947f983bbf95746cc7cf175f5de /test/core/security
parent52978e532679de045db6f6ff99b7130c998d6285 (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.c136
-rw-r--r--test/core/security/fetch_oauth2.c2
-rw-r--r--test/core/security/json_token_test.c77
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;
}