aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorGravatar jboeuf <jboeuf@google.com>2014-12-16 16:32:39 -0800
committerGravatar Nicolas Noble <nnoble@google.com>2014-12-16 17:26:10 -0800
commitab4f91458bc2775a8bfe38451afd882c06ca7bfc (patch)
tree8f28c29f13a3d89903b6cd1fc388f015f723e2c6 /test
parent081e3200c8da1d6bb755191180921270192fec73 (diff)
Adding JWT generation and signing code for service accounts credentials.
Change on 2014/12/16 by jboeuf <jboeuf@google.com> ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=82279249
Diffstat (limited to 'test')
-rw-r--r--test/core/security/json_token_test.c151
1 files changed, 144 insertions, 7 deletions
diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c
index bb36f786c4..32f3cfc40a 100644
--- a/test/core/security/json_token_test.c
+++ b/test/core/security/json_token_test.c
@@ -35,10 +35,14 @@
#include <string.h>
+#include "src/core/security/base64.h"
+#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/slice.h>
#include "test/core/util/test_config.h"
+#include "third_party/cJSON/cJSON.h"
+#include <openssl/evp.h>
/* This JSON key was generated with the GCE console and revoked immediately.
The identifiers have been changed as well.
@@ -70,6 +74,8 @@ static const char test_json_key_str_part3[] =
"\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
"com\", \"type\": \"service_account\" }";
+static const char test_scope[] = "myperm1 myperm2";
+
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) +
@@ -84,7 +90,7 @@ static char *test_json_key_str(const char *bad_part3) {
return result;
}
-static void test_parse_json_key_success() {
+static void test_parse_json_key_success(void) {
char *json_string = test_json_key_str(NULL);
grpc_auth_json_key json_key =
grpc_auth_json_key_create_from_string(json_string);
@@ -107,7 +113,7 @@ static void test_parse_json_key_success() {
grpc_auth_json_key_destruct(&json_key);
}
-static void test_parse_json_key_failure_bad_json() {
+static void test_parse_json_key_failure_bad_json(void) {
const char non_closing_part3[] =
"\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
"\"client_email\": "
@@ -123,7 +129,7 @@ static void test_parse_json_key_failure_bad_json() {
grpc_auth_json_key_destruct(&json_key);
}
-static void test_parse_json_key_failure_no_type() {
+static void test_parse_json_key_failure_no_type(void) {
const char no_type_part3[] =
"\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
"\"client_email\": "
@@ -139,7 +145,7 @@ static void test_parse_json_key_failure_no_type() {
grpc_auth_json_key_destruct(&json_key);
}
-static void test_parse_json_key_failure_no_client_id() {
+static void test_parse_json_key_failure_no_client_id(void) {
const char no_client_id_part3[] =
"\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
"\"client_email\": "
@@ -154,7 +160,7 @@ static void test_parse_json_key_failure_no_client_id() {
grpc_auth_json_key_destruct(&json_key);
}
-static void test_parse_json_key_failure_no_client_email() {
+static void test_parse_json_key_failure_no_client_email(void) {
const char no_client_email_part3[] =
"\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
"\"client_id\": "
@@ -168,7 +174,7 @@ static void test_parse_json_key_failure_no_client_email() {
grpc_auth_json_key_destruct(&json_key);
}
-static void test_parse_json_key_failure_no_private_key_id() {
+static void test_parse_json_key_failure_no_private_key_id(void) {
const char no_private_key_id_part3[] =
"\"client_email\": "
"\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
@@ -183,7 +189,7 @@ static void test_parse_json_key_failure_no_private_key_id() {
grpc_auth_json_key_destruct(&json_key);
}
-static void test_parse_json_key_failure_no_private_key() {
+static void test_parse_json_key_failure_no_private_key(void) {
const char no_private_key_json_string[] =
"{ \"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
"\"client_email\": "
@@ -197,6 +203,136 @@ static void test_parse_json_key_failure_no_private_key() {
grpc_auth_json_key_destruct(&json_key);
}
+static cJSON *parse_json_part_from_jwt(const char *str, size_t len) {
+ char *b64;
+ char *decoded;
+ cJSON *json;
+ gpr_slice slice;
+ b64 = gpr_malloc(len + 1);
+ strncpy(b64, str, len);
+ b64[len] = '\0';
+ slice = grpc_base64_decode(b64, 1);
+ GPR_ASSERT(!GPR_SLICE_IS_EMPTY(slice));
+ decoded = gpr_malloc(GPR_SLICE_LENGTH(slice) + 1);
+ strncpy(decoded, GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice));
+ decoded[GPR_SLICE_LENGTH(slice)] = '\0';
+ json = cJSON_Parse(decoded);
+ gpr_free(b64);
+ gpr_free(decoded);
+ gpr_slice_unref(slice);
+ return json;
+}
+
+static void check_jwt_header(cJSON *header) {
+ cJSON *child = cJSON_GetObjectItem(header, "alg");
+ GPR_ASSERT(child != NULL);
+ GPR_ASSERT(child->type == cJSON_String);
+ GPR_ASSERT(!strcmp(child->valuestring, "RS256"));
+
+ child = cJSON_GetObjectItem(header, "typ");
+ GPR_ASSERT(child != NULL);
+ GPR_ASSERT(child->type == cJSON_String);
+ GPR_ASSERT(!strcmp(child->valuestring, "JWT"));
+}
+
+static void check_jwt_claim(cJSON *claim) {
+ gpr_timespec exp = {0, 0};
+ gpr_timespec issue_time = {0, 0};
+ gpr_timespec parsed_lifetime;
+ cJSON *child = cJSON_GetObjectItem(claim, "iss");
+ GPR_ASSERT(child != NULL);
+ GPR_ASSERT(child->type == cJSON_String);
+ GPR_ASSERT(
+ !strcmp(
+ child->valuestring,
+ "777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount.com"));
+
+ child = cJSON_GetObjectItem(claim, "scope");
+ GPR_ASSERT(child != NULL);
+ GPR_ASSERT(child->type == cJSON_String);
+ GPR_ASSERT(!strcmp(child->valuestring, test_scope));
+
+ child = cJSON_GetObjectItem(claim, "aud");
+ GPR_ASSERT(child != NULL);
+ GPR_ASSERT(child->type == cJSON_String);
+ GPR_ASSERT(!strcmp(child->valuestring,
+ "https://www.googleapis.com/oauth2/v3/token"));
+
+ child = cJSON_GetObjectItem(claim, "exp");
+ GPR_ASSERT(child != NULL);
+ GPR_ASSERT(child->type == cJSON_Number);
+ exp.tv_sec = child->valueint;
+
+ child = cJSON_GetObjectItem(claim, "iat");
+ GPR_ASSERT(child != NULL);
+ GPR_ASSERT(child->type == cJSON_Number);
+ issue_time.tv_sec = child->valueint;
+
+ parsed_lifetime = gpr_time_sub(exp, issue_time);
+ GPR_ASSERT(parsed_lifetime.tv_sec == grpc_max_auth_token_lifetime.tv_sec);
+}
+
+static void check_jwt_signature(const char *b64_signature, RSA *rsa_key,
+ const char *signed_data,
+ size_t signed_data_size) {
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_create();
+ EVP_PKEY *key = EVP_PKEY_new();
+
+ gpr_slice sig = grpc_base64_decode(b64_signature, 1);
+ GPR_ASSERT(!GPR_SLICE_IS_EMPTY(sig));
+ GPR_ASSERT(GPR_SLICE_LENGTH(sig) == 128);
+
+ GPR_ASSERT(md_ctx != NULL);
+ GPR_ASSERT(key != NULL);
+ EVP_PKEY_set1_RSA(key, rsa_key);
+
+ GPR_ASSERT(EVP_DigestVerifyInit(md_ctx, NULL, EVP_sha256(), NULL, key) == 1);
+ GPR_ASSERT(EVP_DigestVerifyUpdate(md_ctx, signed_data, signed_data_size) ==
+ 1);
+ GPR_ASSERT(EVP_DigestVerifyFinal(md_ctx, GPR_SLICE_START_PTR(sig),
+ GPR_SLICE_LENGTH(sig)) == 1);
+
+ gpr_slice_unref(sig);
+ if (key != NULL) EVP_PKEY_free(key);
+ if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
+}
+
+static void test_jwt_encode_and_sign(void) {
+ char *json_string = test_json_key_str(NULL);
+ cJSON *parsed_header = NULL;
+ cJSON *parsed_claim = NULL;
+ grpc_auth_json_key json_key =
+ 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);
+ const char *dot = strchr(jwt, '.');
+ GPR_ASSERT(dot != NULL);
+ parsed_header = parse_json_part_from_jwt(jwt, dot - jwt);
+ GPR_ASSERT(parsed_header != NULL);
+ check_jwt_header(parsed_header);
+ offset = dot - jwt + 1;
+
+ dot = strchr(jwt + offset, '.');
+ GPR_ASSERT(dot != NULL);
+ parsed_claim = parse_json_part_from_jwt(jwt + offset, dot - (jwt + offset));
+ GPR_ASSERT(parsed_claim != NULL);
+ check_jwt_claim(parsed_claim);
+ offset = dot - jwt + 1;
+
+ dot = strchr(jwt + offset, '.');
+ GPR_ASSERT(dot == NULL); /* no more part. */
+ b64_signature = jwt + offset;
+ check_jwt_signature(b64_signature, json_key.private_key, jwt, offset - 1);
+
+ gpr_free(json_string);
+ cJSON_Delete(parsed_header);
+ cJSON_Delete(parsed_claim);
+ grpc_auth_json_key_destruct(&json_key);
+ gpr_free(jwt);
+}
+
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_parse_json_key_success();
@@ -206,5 +342,6 @@ 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();
return 0;
}