OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * |
| 3 * Copyright 2015-2016, Google Inc. |
| 4 * All rights reserved. |
| 5 * |
| 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions are |
| 8 * met: |
| 9 * |
| 10 * * Redistributions of source code must retain the above copyright |
| 11 * notice, this list of conditions and the following disclaimer. |
| 12 * * Redistributions in binary form must reproduce the above |
| 13 * copyright notice, this list of conditions and the following disclaimer |
| 14 * in the documentation and/or other materials provided with the |
| 15 * distribution. |
| 16 * * Neither the name of Google Inc. nor the names of its |
| 17 * contributors may be used to endorse or promote products derived from |
| 18 * this software without specific prior written permission. |
| 19 * |
| 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 * |
| 32 */ |
| 33 |
| 34 #include <grpc/support/port_platform.h> |
| 35 |
| 36 #include "src/core/security/credentials.h" |
| 37 |
| 38 #include <openssl/rsa.h> |
| 39 #include <stdlib.h> |
| 40 #include <string.h> |
| 41 |
| 42 #include <grpc/support/alloc.h> |
| 43 #include <grpc/support/log.h> |
| 44 #include <grpc/support/string_util.h> |
| 45 #include <grpc/support/time.h> |
| 46 |
| 47 #include "src/core/httpcli/httpcli.h" |
| 48 #include "src/core/security/json_token.h" |
| 49 #include "src/core/support/env.h" |
| 50 #include "src/core/support/tmpfile.h" |
| 51 #include "src/core/support/string.h" |
| 52 #include "test/core/util/test_config.h" |
| 53 |
| 54 /* -- Mock channel credentials. -- */ |
| 55 |
| 56 static grpc_channel_credentials *grpc_mock_channel_credentials_create( |
| 57 const grpc_channel_credentials_vtable *vtable) { |
| 58 grpc_channel_credentials *c = gpr_malloc(sizeof(*c)); |
| 59 memset(c, 0, sizeof(*c)); |
| 60 c->type = "mock"; |
| 61 c->vtable = vtable; |
| 62 gpr_ref_init(&c->refcount, 1); |
| 63 return c; |
| 64 } |
| 65 |
| 66 /* -- Constants. -- */ |
| 67 |
| 68 static const char test_google_iam_authorization_token[] = "blahblahblhahb"; |
| 69 static const char test_google_iam_authority_selector[] = "respectmyauthoritah"; |
| 70 static const char test_oauth2_bearer_token[] = |
| 71 "Bearer blaaslkdjfaslkdfasdsfasf"; |
| 72 |
| 73 /* This JSON key was generated with the GCE console and revoked immediately. |
| 74 The identifiers have been changed as well. |
| 75 Maximum size for a string literal is 509 chars in C89, yay! */ |
| 76 static const char test_json_key_str_part1[] = |
| 77 "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----" |
| 78 "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE" |
| 79 "qg" |
| 80 "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/" |
| 81 "rWBQvS4hle4LfijkP3J5BG+" |
| 82 "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+" |
| 83 "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/" |
| 84 "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/" |
| 85 "8HpCqFYM9V8f34SBWfD4fRFT+n/" |
| 86 "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+"; |
| 87 static const char test_json_key_str_part2[] = |
| 88 "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+" |
| 89 "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/" |
| 90 "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA" |
| 91 "G" |
| 92 "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz" |
| 93 "A" |
| 94 "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+" |
| 95 "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/" |
| 96 "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ" |
| 97 "Y" |
| 98 "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", "; |
| 99 static const char test_json_key_str_part3[] = |
| 100 "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " |
| 101 "\"client_email\": " |
| 102 "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." |
| 103 "com\", \"client_id\": " |
| 104 "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." |
| 105 "com\", \"type\": \"service_account\" }"; |
| 106 |
| 107 /* Test refresh token. */ |
| 108 static const char test_refresh_token_str[] = |
| 109 "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," |
| 110 " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," |
| 111 " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," |
| 112 " \"type\": \"authorized_user\"}"; |
| 113 |
| 114 static const char valid_oauth2_json_response[] = |
| 115 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," |
| 116 " \"expires_in\":3599, " |
| 117 " \"token_type\":\"Bearer\"}"; |
| 118 |
| 119 static const char test_user_data[] = "user data"; |
| 120 |
| 121 static const char test_scope[] = "perm1 perm2"; |
| 122 |
| 123 static const char test_signed_jwt[] = |
| 124 "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM4YW" |
| 125 "U0MDcyZTViYTdmZDkwODg2YzcifQ"; |
| 126 |
| 127 static const char test_service_url[] = "https://foo.com/foo.v1"; |
| 128 static const char other_test_service_url[] = "https://bar.com/bar.v1"; |
| 129 |
| 130 static const char test_method[] = "ThisIsNotAMethod"; |
| 131 |
| 132 /* -- Utils. -- */ |
| 133 |
| 134 static char *test_json_key_str(void) { |
| 135 size_t result_len = strlen(test_json_key_str_part1) + |
| 136 strlen(test_json_key_str_part2) + |
| 137 strlen(test_json_key_str_part3); |
| 138 char *result = gpr_malloc(result_len + 1); |
| 139 char *current = result; |
| 140 strcpy(result, test_json_key_str_part1); |
| 141 current += strlen(test_json_key_str_part1); |
| 142 strcpy(current, test_json_key_str_part2); |
| 143 current += strlen(test_json_key_str_part2); |
| 144 strcpy(current, test_json_key_str_part3); |
| 145 return result; |
| 146 } |
| 147 |
| 148 typedef struct { |
| 149 const char *key; |
| 150 const char *value; |
| 151 } expected_md; |
| 152 |
| 153 static grpc_httpcli_response http_response(int status, const char *body) { |
| 154 grpc_httpcli_response response; |
| 155 memset(&response, 0, sizeof(grpc_httpcli_response)); |
| 156 response.status = status; |
| 157 response.body = (char *)body; |
| 158 response.body_length = strlen(body); |
| 159 return response; |
| 160 } |
| 161 |
| 162 /* -- Tests. -- */ |
| 163 |
| 164 static void test_empty_md_store(void) { |
| 165 grpc_credentials_md_store *store = grpc_credentials_md_store_create(0); |
| 166 GPR_ASSERT(store->num_entries == 0); |
| 167 GPR_ASSERT(store->allocated == 0); |
| 168 grpc_credentials_md_store_unref(store); |
| 169 } |
| 170 |
| 171 static void test_ref_unref_empty_md_store(void) { |
| 172 grpc_credentials_md_store *store = grpc_credentials_md_store_create(0); |
| 173 grpc_credentials_md_store_ref(store); |
| 174 grpc_credentials_md_store_ref(store); |
| 175 GPR_ASSERT(store->num_entries == 0); |
| 176 GPR_ASSERT(store->allocated == 0); |
| 177 grpc_credentials_md_store_unref(store); |
| 178 grpc_credentials_md_store_unref(store); |
| 179 grpc_credentials_md_store_unref(store); |
| 180 } |
| 181 |
| 182 static void test_add_to_empty_md_store(void) { |
| 183 grpc_credentials_md_store *store = grpc_credentials_md_store_create(0); |
| 184 const char *key_str = "hello"; |
| 185 const char *value_str = "there blah blah blah blah blah blah blah"; |
| 186 gpr_slice key = gpr_slice_from_copied_string(key_str); |
| 187 gpr_slice value = gpr_slice_from_copied_string(value_str); |
| 188 grpc_credentials_md_store_add(store, key, value); |
| 189 GPR_ASSERT(store->num_entries == 1); |
| 190 GPR_ASSERT(gpr_slice_cmp(key, store->entries[0].key) == 0); |
| 191 GPR_ASSERT(gpr_slice_cmp(value, store->entries[0].value) == 0); |
| 192 gpr_slice_unref(key); |
| 193 gpr_slice_unref(value); |
| 194 grpc_credentials_md_store_unref(store); |
| 195 } |
| 196 |
| 197 static void test_add_cstrings_to_empty_md_store(void) { |
| 198 grpc_credentials_md_store *store = grpc_credentials_md_store_create(0); |
| 199 const char *key_str = "hello"; |
| 200 const char *value_str = "there blah blah blah blah blah blah blah"; |
| 201 grpc_credentials_md_store_add_cstrings(store, key_str, value_str); |
| 202 GPR_ASSERT(store->num_entries == 1); |
| 203 GPR_ASSERT(gpr_slice_str_cmp(store->entries[0].key, key_str) == 0); |
| 204 GPR_ASSERT(gpr_slice_str_cmp(store->entries[0].value, value_str) == 0); |
| 205 grpc_credentials_md_store_unref(store); |
| 206 } |
| 207 |
| 208 static void test_empty_preallocated_md_store(void) { |
| 209 grpc_credentials_md_store *store = grpc_credentials_md_store_create(4); |
| 210 GPR_ASSERT(store->num_entries == 0); |
| 211 GPR_ASSERT(store->allocated == 4); |
| 212 GPR_ASSERT(store->entries != NULL); |
| 213 grpc_credentials_md_store_unref(store); |
| 214 } |
| 215 |
| 216 static void test_add_abunch_to_md_store(void) { |
| 217 grpc_credentials_md_store *store = grpc_credentials_md_store_create(4); |
| 218 size_t num_entries = 1000; |
| 219 const char *key_str = "hello"; |
| 220 const char *value_str = "there blah blah blah blah blah blah blah"; |
| 221 size_t i; |
| 222 for (i = 0; i < num_entries; i++) { |
| 223 grpc_credentials_md_store_add_cstrings(store, key_str, value_str); |
| 224 } |
| 225 for (i = 0; i < num_entries; i++) { |
| 226 GPR_ASSERT(gpr_slice_str_cmp(store->entries[i].key, key_str) == 0); |
| 227 GPR_ASSERT(gpr_slice_str_cmp(store->entries[i].value, value_str) == 0); |
| 228 } |
| 229 grpc_credentials_md_store_unref(store); |
| 230 } |
| 231 |
| 232 static void test_oauth2_token_fetcher_creds_parsing_ok(void) { |
| 233 grpc_credentials_md_store *token_md = NULL; |
| 234 gpr_timespec token_lifetime; |
| 235 grpc_httpcli_response response = |
| 236 http_response(200, valid_oauth2_json_response); |
| 237 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( |
| 238 &response, &token_md, &token_lifetime) == GRPC_CREDENTIALS_OK); |
| 239 GPR_ASSERT(token_lifetime.tv_sec == 3599); |
| 240 GPR_ASSERT(token_lifetime.tv_nsec == 0); |
| 241 GPR_ASSERT(token_md->num_entries == 1); |
| 242 GPR_ASSERT(gpr_slice_str_cmp(token_md->entries[0].key, "authorization") == 0); |
| 243 GPR_ASSERT(gpr_slice_str_cmp(token_md->entries[0].value, |
| 244 "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") == |
| 245 0); |
| 246 grpc_credentials_md_store_unref(token_md); |
| 247 } |
| 248 |
| 249 static void test_oauth2_token_fetcher_creds_parsing_bad_http_status(void) { |
| 250 grpc_credentials_md_store *token_md = NULL; |
| 251 gpr_timespec token_lifetime; |
| 252 grpc_httpcli_response response = |
| 253 http_response(401, valid_oauth2_json_response); |
| 254 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( |
| 255 &response, &token_md, &token_lifetime) == |
| 256 GRPC_CREDENTIALS_ERROR); |
| 257 } |
| 258 |
| 259 static void test_oauth2_token_fetcher_creds_parsing_empty_http_body(void) { |
| 260 grpc_credentials_md_store *token_md = NULL; |
| 261 gpr_timespec token_lifetime; |
| 262 grpc_httpcli_response response = http_response(200, ""); |
| 263 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( |
| 264 &response, &token_md, &token_lifetime) == |
| 265 GRPC_CREDENTIALS_ERROR); |
| 266 } |
| 267 |
| 268 static void test_oauth2_token_fetcher_creds_parsing_invalid_json(void) { |
| 269 grpc_credentials_md_store *token_md = NULL; |
| 270 gpr_timespec token_lifetime; |
| 271 grpc_httpcli_response response = |
| 272 http_response(200, |
| 273 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," |
| 274 " \"expires_in\":3599, " |
| 275 " \"token_type\":\"Bearer\""); |
| 276 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( |
| 277 &response, &token_md, &token_lifetime) == |
| 278 GRPC_CREDENTIALS_ERROR); |
| 279 } |
| 280 |
| 281 static void test_oauth2_token_fetcher_creds_parsing_missing_token(void) { |
| 282 grpc_credentials_md_store *token_md = NULL; |
| 283 gpr_timespec token_lifetime; |
| 284 grpc_httpcli_response response = http_response(200, |
| 285 "{" |
| 286 " \"expires_in\":3599, " |
| 287 " \"token_type\":\"Bearer\"}"); |
| 288 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( |
| 289 &response, &token_md, &token_lifetime) == |
| 290 GRPC_CREDENTIALS_ERROR); |
| 291 } |
| 292 |
| 293 static void test_oauth2_token_fetcher_creds_parsing_missing_token_type(void) { |
| 294 grpc_credentials_md_store *token_md = NULL; |
| 295 gpr_timespec token_lifetime; |
| 296 grpc_httpcli_response response = |
| 297 http_response(200, |
| 298 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," |
| 299 " \"expires_in\":3599, " |
| 300 "}"); |
| 301 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( |
| 302 &response, &token_md, &token_lifetime) == |
| 303 GRPC_CREDENTIALS_ERROR); |
| 304 } |
| 305 |
| 306 static void test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime( |
| 307 void) { |
| 308 grpc_credentials_md_store *token_md = NULL; |
| 309 gpr_timespec token_lifetime; |
| 310 grpc_httpcli_response response = |
| 311 http_response(200, |
| 312 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," |
| 313 " \"token_type\":\"Bearer\"}"); |
| 314 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( |
| 315 &response, &token_md, &token_lifetime) == |
| 316 GRPC_CREDENTIALS_ERROR); |
| 317 } |
| 318 |
| 319 static void check_metadata(expected_md *expected, grpc_credentials_md *md_elems, |
| 320 size_t num_md) { |
| 321 size_t i; |
| 322 for (i = 0; i < num_md; i++) { |
| 323 size_t j; |
| 324 for (j = 0; j < num_md; j++) { |
| 325 if (0 == gpr_slice_str_cmp(md_elems[j].key, expected[i].key)) { |
| 326 GPR_ASSERT(gpr_slice_str_cmp(md_elems[j].value, expected[i].value) == |
| 327 0); |
| 328 break; |
| 329 } |
| 330 } |
| 331 if (j == num_md) { |
| 332 gpr_log(GPR_ERROR, "key %s not found", expected[i].key); |
| 333 GPR_ASSERT(0); |
| 334 } |
| 335 } |
| 336 } |
| 337 |
| 338 static void check_google_iam_metadata(grpc_exec_ctx *exec_ctx, void *user_data, |
| 339 grpc_credentials_md *md_elems, |
| 340 size_t num_md, |
| 341 grpc_credentials_status status) { |
| 342 grpc_call_credentials *c = (grpc_call_credentials *)user_data; |
| 343 expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, |
| 344 test_google_iam_authorization_token}, |
| 345 {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, |
| 346 test_google_iam_authority_selector}}; |
| 347 GPR_ASSERT(status == GRPC_CREDENTIALS_OK); |
| 348 GPR_ASSERT(num_md == 2); |
| 349 check_metadata(emd, md_elems, num_md); |
| 350 grpc_call_credentials_unref(c); |
| 351 } |
| 352 |
| 353 static void test_google_iam_creds(void) { |
| 354 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 355 grpc_call_credentials *creds = grpc_google_iam_credentials_create( |
| 356 test_google_iam_authorization_token, test_google_iam_authority_selector, |
| 357 NULL); |
| 358 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 359 NULL}; |
| 360 grpc_call_credentials_get_request_metadata( |
| 361 &exec_ctx, creds, NULL, auth_md_ctx, check_google_iam_metadata, creds); |
| 362 grpc_exec_ctx_finish(&exec_ctx); |
| 363 } |
| 364 |
| 365 static void check_access_token_metadata(grpc_exec_ctx *exec_ctx, |
| 366 void *user_data, |
| 367 grpc_credentials_md *md_elems, |
| 368 size_t num_md, |
| 369 grpc_credentials_status status) { |
| 370 grpc_call_credentials *c = (grpc_call_credentials *)user_data; |
| 371 expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}}; |
| 372 GPR_ASSERT(status == GRPC_CREDENTIALS_OK); |
| 373 GPR_ASSERT(num_md == 1); |
| 374 check_metadata(emd, md_elems, num_md); |
| 375 grpc_call_credentials_unref(c); |
| 376 } |
| 377 |
| 378 static void test_access_token_creds(void) { |
| 379 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 380 grpc_call_credentials *creds = |
| 381 grpc_access_token_credentials_create("blah", NULL); |
| 382 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 383 NULL}; |
| 384 GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); |
| 385 grpc_call_credentials_get_request_metadata( |
| 386 &exec_ctx, creds, NULL, auth_md_ctx, check_access_token_metadata, creds); |
| 387 grpc_exec_ctx_finish(&exec_ctx); |
| 388 } |
| 389 |
| 390 static grpc_security_status check_channel_oauth2_create_security_connector( |
| 391 grpc_channel_credentials *c, grpc_call_credentials *call_creds, |
| 392 const char *target, const grpc_channel_args *args, |
| 393 grpc_channel_security_connector **sc, grpc_channel_args **new_args) { |
| 394 GPR_ASSERT(strcmp(c->type, "mock") == 0); |
| 395 GPR_ASSERT(call_creds != NULL); |
| 396 GPR_ASSERT(strcmp(call_creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); |
| 397 return GRPC_SECURITY_OK; |
| 398 } |
| 399 |
| 400 static void test_channel_oauth2_composite_creds(void) { |
| 401 grpc_channel_args *new_args; |
| 402 grpc_channel_credentials_vtable vtable = { |
| 403 NULL, check_channel_oauth2_create_security_connector}; |
| 404 grpc_channel_credentials *channel_creds = |
| 405 grpc_mock_channel_credentials_create(&vtable); |
| 406 grpc_call_credentials *oauth2_creds = |
| 407 grpc_access_token_credentials_create("blah", NULL); |
| 408 grpc_channel_credentials *channel_oauth2_creds = |
| 409 grpc_composite_channel_credentials_create(channel_creds, oauth2_creds, |
| 410 NULL); |
| 411 grpc_channel_credentials_release(channel_creds); |
| 412 grpc_call_credentials_release(oauth2_creds); |
| 413 GPR_ASSERT(grpc_channel_credentials_create_security_connector( |
| 414 channel_oauth2_creds, NULL, NULL, NULL, &new_args) == |
| 415 GRPC_SECURITY_OK); |
| 416 grpc_channel_credentials_release(channel_oauth2_creds); |
| 417 } |
| 418 |
| 419 static void check_oauth2_google_iam_composite_metadata( |
| 420 grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, |
| 421 size_t num_md, grpc_credentials_status status) { |
| 422 grpc_call_credentials *c = (grpc_call_credentials *)user_data; |
| 423 expected_md emd[] = { |
| 424 {GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token}, |
| 425 {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, |
| 426 test_google_iam_authorization_token}, |
| 427 {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, |
| 428 test_google_iam_authority_selector}}; |
| 429 GPR_ASSERT(status == GRPC_CREDENTIALS_OK); |
| 430 GPR_ASSERT(num_md == 3); |
| 431 check_metadata(emd, md_elems, num_md); |
| 432 grpc_call_credentials_unref(c); |
| 433 } |
| 434 |
| 435 static void test_oauth2_google_iam_composite_creds(void) { |
| 436 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 437 const grpc_call_credentials_array *creds_array; |
| 438 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 439 NULL}; |
| 440 grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create( |
| 441 "authorization", test_oauth2_bearer_token, 0); |
| 442 grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create( |
| 443 test_google_iam_authorization_token, test_google_iam_authority_selector, |
| 444 NULL); |
| 445 grpc_call_credentials *composite_creds = |
| 446 grpc_composite_call_credentials_create(oauth2_creds, google_iam_creds, |
| 447 NULL); |
| 448 grpc_call_credentials_unref(oauth2_creds); |
| 449 grpc_call_credentials_unref(google_iam_creds); |
| 450 GPR_ASSERT( |
| 451 strcmp(composite_creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0); |
| 452 creds_array = |
| 453 grpc_composite_call_credentials_get_credentials(composite_creds); |
| 454 GPR_ASSERT(creds_array->num_creds == 2); |
| 455 GPR_ASSERT(strcmp(creds_array->creds_array[0]->type, |
| 456 GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); |
| 457 GPR_ASSERT(strcmp(creds_array->creds_array[1]->type, |
| 458 GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0); |
| 459 grpc_call_credentials_get_request_metadata( |
| 460 &exec_ctx, composite_creds, NULL, auth_md_ctx, |
| 461 check_oauth2_google_iam_composite_metadata, composite_creds); |
| 462 grpc_exec_ctx_finish(&exec_ctx); |
| 463 } |
| 464 |
| 465 static grpc_security_status |
| 466 check_channel_oauth2_google_iam_create_security_connector( |
| 467 grpc_channel_credentials *c, grpc_call_credentials *call_creds, |
| 468 const char *target, const grpc_channel_args *args, |
| 469 grpc_channel_security_connector **sc, grpc_channel_args **new_args) { |
| 470 const grpc_call_credentials_array *creds_array; |
| 471 GPR_ASSERT(strcmp(c->type, "mock") == 0); |
| 472 GPR_ASSERT(call_creds != NULL); |
| 473 GPR_ASSERT(strcmp(call_creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == |
| 474 0); |
| 475 creds_array = grpc_composite_call_credentials_get_credentials(call_creds); |
| 476 GPR_ASSERT(strcmp(creds_array->creds_array[0]->type, |
| 477 GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); |
| 478 GPR_ASSERT(strcmp(creds_array->creds_array[1]->type, |
| 479 GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0); |
| 480 return GRPC_SECURITY_OK; |
| 481 } |
| 482 |
| 483 static void test_channel_oauth2_google_iam_composite_creds(void) { |
| 484 grpc_channel_args *new_args; |
| 485 grpc_channel_credentials_vtable vtable = { |
| 486 NULL, check_channel_oauth2_google_iam_create_security_connector}; |
| 487 grpc_channel_credentials *channel_creds = |
| 488 grpc_mock_channel_credentials_create(&vtable); |
| 489 grpc_call_credentials *oauth2_creds = |
| 490 grpc_access_token_credentials_create("blah", NULL); |
| 491 grpc_channel_credentials *channel_oauth2_creds = |
| 492 grpc_composite_channel_credentials_create(channel_creds, oauth2_creds, |
| 493 NULL); |
| 494 grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create( |
| 495 test_google_iam_authorization_token, test_google_iam_authority_selector, |
| 496 NULL); |
| 497 grpc_channel_credentials *channel_oauth2_iam_creds = |
| 498 grpc_composite_channel_credentials_create(channel_oauth2_creds, |
| 499 google_iam_creds, NULL); |
| 500 grpc_channel_credentials_release(channel_creds); |
| 501 grpc_call_credentials_release(oauth2_creds); |
| 502 grpc_channel_credentials_release(channel_oauth2_creds); |
| 503 grpc_call_credentials_release(google_iam_creds); |
| 504 |
| 505 GPR_ASSERT(grpc_channel_credentials_create_security_connector( |
| 506 channel_oauth2_iam_creds, NULL, NULL, NULL, &new_args) == |
| 507 GRPC_SECURITY_OK); |
| 508 |
| 509 grpc_channel_credentials_release(channel_oauth2_iam_creds); |
| 510 } |
| 511 |
| 512 static void on_oauth2_creds_get_metadata_success( |
| 513 grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, |
| 514 size_t num_md, grpc_credentials_status status) { |
| 515 GPR_ASSERT(status == GRPC_CREDENTIALS_OK); |
| 516 GPR_ASSERT(num_md == 1); |
| 517 GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].key, "authorization") == 0); |
| 518 GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].value, |
| 519 "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") == |
| 520 0); |
| 521 GPR_ASSERT(user_data != NULL); |
| 522 GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); |
| 523 } |
| 524 |
| 525 static void on_oauth2_creds_get_metadata_failure( |
| 526 grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, |
| 527 size_t num_md, grpc_credentials_status status) { |
| 528 GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); |
| 529 GPR_ASSERT(num_md == 0); |
| 530 GPR_ASSERT(user_data != NULL); |
| 531 GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); |
| 532 } |
| 533 |
| 534 static void validate_compute_engine_http_request( |
| 535 const grpc_httpcli_request *request) { |
| 536 GPR_ASSERT(request->handshaker != &grpc_httpcli_ssl); |
| 537 GPR_ASSERT(strcmp(request->host, "metadata") == 0); |
| 538 GPR_ASSERT( |
| 539 strcmp(request->path, |
| 540 "/computeMetadata/v1/instance/service-accounts/default/token") == |
| 541 0); |
| 542 GPR_ASSERT(request->hdr_count == 1); |
| 543 GPR_ASSERT(strcmp(request->hdrs[0].key, "Metadata-Flavor") == 0); |
| 544 GPR_ASSERT(strcmp(request->hdrs[0].value, "Google") == 0); |
| 545 } |
| 546 |
| 547 static int compute_engine_httpcli_get_success_override( |
| 548 grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, |
| 549 gpr_timespec deadline, grpc_httpcli_response_cb on_response, |
| 550 void *user_data) { |
| 551 grpc_httpcli_response response = |
| 552 http_response(200, valid_oauth2_json_response); |
| 553 validate_compute_engine_http_request(request); |
| 554 on_response(exec_ctx, user_data, &response); |
| 555 return 1; |
| 556 } |
| 557 |
| 558 static int compute_engine_httpcli_get_failure_override( |
| 559 grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, |
| 560 gpr_timespec deadline, grpc_httpcli_response_cb on_response, |
| 561 void *user_data) { |
| 562 grpc_httpcli_response response = http_response(403, "Not Authorized."); |
| 563 validate_compute_engine_http_request(request); |
| 564 on_response(exec_ctx, user_data, &response); |
| 565 return 1; |
| 566 } |
| 567 |
| 568 static int httpcli_post_should_not_be_called( |
| 569 grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, |
| 570 const char *body_bytes, size_t body_size, gpr_timespec deadline, |
| 571 grpc_httpcli_response_cb on_response, void *user_data) { |
| 572 GPR_ASSERT("HTTP POST should not be called" == NULL); |
| 573 return 1; |
| 574 } |
| 575 |
| 576 static int httpcli_get_should_not_be_called( |
| 577 grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, |
| 578 gpr_timespec deadline, grpc_httpcli_response_cb on_response, |
| 579 void *user_data) { |
| 580 GPR_ASSERT("HTTP GET should not be called" == NULL); |
| 581 return 1; |
| 582 } |
| 583 |
| 584 static void test_compute_engine_creds_success(void) { |
| 585 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 586 grpc_call_credentials *compute_engine_creds = |
| 587 grpc_google_compute_engine_credentials_create(NULL); |
| 588 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 589 NULL}; |
| 590 |
| 591 /* First request: http get should be called. */ |
| 592 grpc_httpcli_set_override(compute_engine_httpcli_get_success_override, |
| 593 httpcli_post_should_not_be_called); |
| 594 grpc_call_credentials_get_request_metadata( |
| 595 &exec_ctx, compute_engine_creds, NULL, auth_md_ctx, |
| 596 on_oauth2_creds_get_metadata_success, (void *)test_user_data); |
| 597 grpc_exec_ctx_flush(&exec_ctx); |
| 598 |
| 599 /* Second request: the cached token should be served directly. */ |
| 600 grpc_httpcli_set_override(httpcli_get_should_not_be_called, |
| 601 httpcli_post_should_not_be_called); |
| 602 grpc_call_credentials_get_request_metadata( |
| 603 &exec_ctx, compute_engine_creds, NULL, auth_md_ctx, |
| 604 on_oauth2_creds_get_metadata_success, (void *)test_user_data); |
| 605 grpc_exec_ctx_finish(&exec_ctx); |
| 606 |
| 607 grpc_call_credentials_unref(compute_engine_creds); |
| 608 grpc_httpcli_set_override(NULL, NULL); |
| 609 } |
| 610 |
| 611 static void test_compute_engine_creds_failure(void) { |
| 612 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 613 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 614 NULL}; |
| 615 grpc_call_credentials *compute_engine_creds = |
| 616 grpc_google_compute_engine_credentials_create(NULL); |
| 617 grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override, |
| 618 httpcli_post_should_not_be_called); |
| 619 grpc_call_credentials_get_request_metadata( |
| 620 &exec_ctx, compute_engine_creds, NULL, auth_md_ctx, |
| 621 on_oauth2_creds_get_metadata_failure, (void *)test_user_data); |
| 622 grpc_call_credentials_unref(compute_engine_creds); |
| 623 grpc_httpcli_set_override(NULL, NULL); |
| 624 grpc_exec_ctx_finish(&exec_ctx); |
| 625 } |
| 626 |
| 627 static void validate_refresh_token_http_request( |
| 628 const grpc_httpcli_request *request, const char *body, size_t body_size) { |
| 629 /* The content of the assertion is tested extensively in json_token_test. */ |
| 630 char *expected_body = NULL; |
| 631 GPR_ASSERT(body != NULL); |
| 632 GPR_ASSERT(body_size != 0); |
| 633 gpr_asprintf(&expected_body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING, |
| 634 "32555999999.apps.googleusercontent.com", |
| 635 "EmssLNjJy1332hD4KFsecret", |
| 636 "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42"); |
| 637 GPR_ASSERT(strlen(expected_body) == body_size); |
| 638 GPR_ASSERT(memcmp(expected_body, body, body_size) == 0); |
| 639 gpr_free(expected_body); |
| 640 GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); |
| 641 GPR_ASSERT(strcmp(request->host, GRPC_GOOGLE_OAUTH2_SERVICE_HOST) == 0); |
| 642 GPR_ASSERT(strcmp(request->path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0); |
| 643 GPR_ASSERT(request->hdr_count == 1); |
| 644 GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0); |
| 645 GPR_ASSERT( |
| 646 strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded") == 0); |
| 647 } |
| 648 |
| 649 static int refresh_token_httpcli_post_success( |
| 650 grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, |
| 651 const char *body, size_t body_size, gpr_timespec deadline, |
| 652 grpc_httpcli_response_cb on_response, void *user_data) { |
| 653 grpc_httpcli_response response = |
| 654 http_response(200, valid_oauth2_json_response); |
| 655 validate_refresh_token_http_request(request, body, body_size); |
| 656 on_response(exec_ctx, user_data, &response); |
| 657 return 1; |
| 658 } |
| 659 |
| 660 static int refresh_token_httpcli_post_failure( |
| 661 grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, |
| 662 const char *body, size_t body_size, gpr_timespec deadline, |
| 663 grpc_httpcli_response_cb on_response, void *user_data) { |
| 664 grpc_httpcli_response response = http_response(403, "Not Authorized."); |
| 665 validate_refresh_token_http_request(request, body, body_size); |
| 666 on_response(exec_ctx, user_data, &response); |
| 667 return 1; |
| 668 } |
| 669 |
| 670 static void test_refresh_token_creds_success(void) { |
| 671 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 672 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 673 NULL}; |
| 674 grpc_call_credentials *refresh_token_creds = |
| 675 grpc_google_refresh_token_credentials_create(test_refresh_token_str, |
| 676 NULL); |
| 677 |
| 678 /* First request: http get should be called. */ |
| 679 grpc_httpcli_set_override(httpcli_get_should_not_be_called, |
| 680 refresh_token_httpcli_post_success); |
| 681 grpc_call_credentials_get_request_metadata( |
| 682 &exec_ctx, refresh_token_creds, NULL, auth_md_ctx, |
| 683 on_oauth2_creds_get_metadata_success, (void *)test_user_data); |
| 684 grpc_exec_ctx_flush(&exec_ctx); |
| 685 |
| 686 /* Second request: the cached token should be served directly. */ |
| 687 grpc_httpcli_set_override(httpcli_get_should_not_be_called, |
| 688 httpcli_post_should_not_be_called); |
| 689 grpc_call_credentials_get_request_metadata( |
| 690 &exec_ctx, refresh_token_creds, NULL, auth_md_ctx, |
| 691 on_oauth2_creds_get_metadata_success, (void *)test_user_data); |
| 692 grpc_exec_ctx_flush(&exec_ctx); |
| 693 |
| 694 grpc_call_credentials_unref(refresh_token_creds); |
| 695 grpc_httpcli_set_override(NULL, NULL); |
| 696 grpc_exec_ctx_finish(&exec_ctx); |
| 697 } |
| 698 |
| 699 static void test_refresh_token_creds_failure(void) { |
| 700 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 701 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 702 NULL}; |
| 703 grpc_call_credentials *refresh_token_creds = |
| 704 grpc_google_refresh_token_credentials_create(test_refresh_token_str, |
| 705 NULL); |
| 706 grpc_httpcli_set_override(httpcli_get_should_not_be_called, |
| 707 refresh_token_httpcli_post_failure); |
| 708 grpc_call_credentials_get_request_metadata( |
| 709 &exec_ctx, refresh_token_creds, NULL, auth_md_ctx, |
| 710 on_oauth2_creds_get_metadata_failure, (void *)test_user_data); |
| 711 grpc_call_credentials_unref(refresh_token_creds); |
| 712 grpc_httpcli_set_override(NULL, NULL); |
| 713 grpc_exec_ctx_finish(&exec_ctx); |
| 714 } |
| 715 |
| 716 static void validate_jwt_encode_and_sign_params( |
| 717 const grpc_auth_json_key *json_key, const char *scope, |
| 718 gpr_timespec token_lifetime) { |
| 719 GPR_ASSERT(grpc_auth_json_key_is_valid(json_key)); |
| 720 GPR_ASSERT(json_key->private_key != NULL); |
| 721 GPR_ASSERT(RSA_check_key(json_key->private_key)); |
| 722 GPR_ASSERT(json_key->type != NULL && |
| 723 strcmp(json_key->type, "service_account") == 0); |
| 724 GPR_ASSERT(json_key->private_key_id != NULL && |
| 725 strcmp(json_key->private_key_id, |
| 726 "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); |
| 727 GPR_ASSERT(json_key->client_id != NULL && |
| 728 strcmp(json_key->client_id, |
| 729 "777-abaslkan11hlb6nmim3bpspl31ud.apps." |
| 730 "googleusercontent.com") == 0); |
| 731 GPR_ASSERT(json_key->client_email != NULL && |
| 732 strcmp(json_key->client_email, |
| 733 "777-abaslkan11hlb6nmim3bpspl31ud@developer." |
| 734 "gserviceaccount.com") == 0); |
| 735 if (scope != NULL) GPR_ASSERT(strcmp(scope, test_scope) == 0); |
| 736 GPR_ASSERT(!gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime())); |
| 737 } |
| 738 |
| 739 static char *encode_and_sign_jwt_success(const grpc_auth_json_key *json_key, |
| 740 const char *audience, |
| 741 gpr_timespec token_lifetime, |
| 742 const char *scope) { |
| 743 validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime); |
| 744 return gpr_strdup(test_signed_jwt); |
| 745 } |
| 746 |
| 747 static char *encode_and_sign_jwt_failure(const grpc_auth_json_key *json_key, |
| 748 const char *audience, |
| 749 gpr_timespec token_lifetime, |
| 750 const char *scope) { |
| 751 validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime); |
| 752 return NULL; |
| 753 } |
| 754 |
| 755 static char *encode_and_sign_jwt_should_not_be_called( |
| 756 const grpc_auth_json_key *json_key, const char *audience, |
| 757 gpr_timespec token_lifetime, const char *scope) { |
| 758 GPR_ASSERT("grpc_jwt_encode_and_sign should not be called" == NULL); |
| 759 return NULL; |
| 760 } |
| 761 |
| 762 static void on_jwt_creds_get_metadata_success(grpc_exec_ctx *exec_ctx, |
| 763 void *user_data, |
| 764 grpc_credentials_md *md_elems, |
| 765 size_t num_md, |
| 766 grpc_credentials_status status) { |
| 767 char *expected_md_value; |
| 768 gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt); |
| 769 GPR_ASSERT(status == GRPC_CREDENTIALS_OK); |
| 770 GPR_ASSERT(num_md == 1); |
| 771 GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].key, "authorization") == 0); |
| 772 GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].value, expected_md_value) == 0); |
| 773 GPR_ASSERT(user_data != NULL); |
| 774 GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); |
| 775 gpr_free(expected_md_value); |
| 776 } |
| 777 |
| 778 static void on_jwt_creds_get_metadata_failure(grpc_exec_ctx *exec_ctx, |
| 779 void *user_data, |
| 780 grpc_credentials_md *md_elems, |
| 781 size_t num_md, |
| 782 grpc_credentials_status status) { |
| 783 GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); |
| 784 GPR_ASSERT(num_md == 0); |
| 785 GPR_ASSERT(user_data != NULL); |
| 786 GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); |
| 787 } |
| 788 |
| 789 static void test_jwt_creds_success(void) { |
| 790 char *json_key_string = test_json_key_str(); |
| 791 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 792 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 793 NULL}; |
| 794 grpc_call_credentials *jwt_creds = |
| 795 grpc_service_account_jwt_access_credentials_create( |
| 796 json_key_string, grpc_max_auth_token_lifetime(), NULL); |
| 797 |
| 798 /* First request: jwt_encode_and_sign should be called. */ |
| 799 grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); |
| 800 grpc_call_credentials_get_request_metadata( |
| 801 &exec_ctx, jwt_creds, NULL, auth_md_ctx, |
| 802 on_jwt_creds_get_metadata_success, (void *)test_user_data); |
| 803 grpc_exec_ctx_flush(&exec_ctx); |
| 804 |
| 805 /* Second request: the cached token should be served directly. */ |
| 806 grpc_jwt_encode_and_sign_set_override( |
| 807 encode_and_sign_jwt_should_not_be_called); |
| 808 grpc_call_credentials_get_request_metadata( |
| 809 &exec_ctx, jwt_creds, NULL, auth_md_ctx, |
| 810 on_jwt_creds_get_metadata_success, (void *)test_user_data); |
| 811 grpc_exec_ctx_flush(&exec_ctx); |
| 812 |
| 813 /* Third request: Different service url so jwt_encode_and_sign should be |
| 814 called again (no caching). */ |
| 815 auth_md_ctx.service_url = other_test_service_url; |
| 816 grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); |
| 817 grpc_call_credentials_get_request_metadata( |
| 818 &exec_ctx, jwt_creds, NULL, auth_md_ctx, |
| 819 on_jwt_creds_get_metadata_success, (void *)test_user_data); |
| 820 grpc_exec_ctx_flush(&exec_ctx); |
| 821 |
| 822 gpr_free(json_key_string); |
| 823 grpc_call_credentials_unref(jwt_creds); |
| 824 grpc_jwt_encode_and_sign_set_override(NULL); |
| 825 } |
| 826 |
| 827 static void test_jwt_creds_signing_failure(void) { |
| 828 char *json_key_string = test_json_key_str(); |
| 829 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 830 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 831 NULL}; |
| 832 grpc_call_credentials *jwt_creds = |
| 833 grpc_service_account_jwt_access_credentials_create( |
| 834 json_key_string, grpc_max_auth_token_lifetime(), NULL); |
| 835 |
| 836 grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure); |
| 837 grpc_call_credentials_get_request_metadata( |
| 838 &exec_ctx, jwt_creds, NULL, auth_md_ctx, |
| 839 on_jwt_creds_get_metadata_failure, (void *)test_user_data); |
| 840 |
| 841 gpr_free(json_key_string); |
| 842 grpc_call_credentials_unref(jwt_creds); |
| 843 grpc_jwt_encode_and_sign_set_override(NULL); |
| 844 grpc_exec_ctx_finish(&exec_ctx); |
| 845 } |
| 846 |
| 847 static void set_google_default_creds_env_var_with_file_contents( |
| 848 const char *file_prefix, const char *contents) { |
| 849 size_t contents_len = strlen(contents); |
| 850 char *creds_file_name; |
| 851 FILE *creds_file = gpr_tmpfile(file_prefix, &creds_file_name); |
| 852 GPR_ASSERT(creds_file_name != NULL); |
| 853 GPR_ASSERT(creds_file != NULL); |
| 854 GPR_ASSERT(fwrite(contents, 1, contents_len, creds_file) == contents_len); |
| 855 fclose(creds_file); |
| 856 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, creds_file_name); |
| 857 gpr_free(creds_file_name); |
| 858 } |
| 859 |
| 860 static void test_google_default_creds_auth_key(void) { |
| 861 grpc_service_account_jwt_access_credentials *jwt; |
| 862 grpc_composite_channel_credentials *creds; |
| 863 char *json_key = test_json_key_str(); |
| 864 grpc_flush_cached_google_default_credentials(); |
| 865 set_google_default_creds_env_var_with_file_contents( |
| 866 "json_key_google_default_creds", json_key); |
| 867 gpr_free(json_key); |
| 868 creds = (grpc_composite_channel_credentials *) |
| 869 grpc_google_default_credentials_create(); |
| 870 GPR_ASSERT(creds != NULL); |
| 871 jwt = (grpc_service_account_jwt_access_credentials *)creds->call_creds; |
| 872 GPR_ASSERT( |
| 873 strcmp(jwt->key.client_id, |
| 874 "777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") == |
| 875 0); |
| 876 grpc_channel_credentials_unref(&creds->base); |
| 877 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ |
| 878 } |
| 879 |
| 880 static void test_google_default_creds_refresh_token(void) { |
| 881 grpc_google_refresh_token_credentials *refresh; |
| 882 grpc_composite_channel_credentials *creds; |
| 883 grpc_flush_cached_google_default_credentials(); |
| 884 set_google_default_creds_env_var_with_file_contents( |
| 885 "refresh_token_google_default_creds", test_refresh_token_str); |
| 886 creds = (grpc_composite_channel_credentials *) |
| 887 grpc_google_default_credentials_create(); |
| 888 GPR_ASSERT(creds != NULL); |
| 889 refresh = (grpc_google_refresh_token_credentials *)creds->call_creds; |
| 890 GPR_ASSERT(strcmp(refresh->refresh_token.client_id, |
| 891 "32555999999.apps.googleusercontent.com") == 0); |
| 892 grpc_channel_credentials_unref(&creds->base); |
| 893 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ |
| 894 } |
| 895 |
| 896 static int default_creds_gce_detection_httpcli_get_success_override( |
| 897 grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, |
| 898 gpr_timespec deadline, grpc_httpcli_response_cb on_response, |
| 899 void *user_data) { |
| 900 grpc_httpcli_response response = http_response(200, ""); |
| 901 grpc_httpcli_header header; |
| 902 header.key = "Metadata-Flavor"; |
| 903 header.value = "Google"; |
| 904 response.hdr_count = 1; |
| 905 response.hdrs = &header; |
| 906 GPR_ASSERT(strcmp(request->path, "/") == 0); |
| 907 GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); |
| 908 on_response(exec_ctx, user_data, &response); |
| 909 return 1; |
| 910 } |
| 911 |
| 912 static char *null_well_known_creds_path_getter(void) { return NULL; } |
| 913 |
| 914 static void test_google_default_creds_gce(void) { |
| 915 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 916 grpc_composite_channel_credentials *creds; |
| 917 grpc_channel_credentials *cached_creds; |
| 918 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 919 NULL}; |
| 920 grpc_flush_cached_google_default_credentials(); |
| 921 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ |
| 922 grpc_override_well_known_credentials_path_getter( |
| 923 null_well_known_creds_path_getter); |
| 924 |
| 925 /* Simulate a successful detection of GCE. */ |
| 926 grpc_httpcli_set_override( |
| 927 default_creds_gce_detection_httpcli_get_success_override, |
| 928 httpcli_post_should_not_be_called); |
| 929 creds = (grpc_composite_channel_credentials *) |
| 930 grpc_google_default_credentials_create(); |
| 931 |
| 932 /* Verify that the default creds actually embeds a GCE creds. */ |
| 933 GPR_ASSERT(creds != NULL); |
| 934 GPR_ASSERT(creds->call_creds != NULL); |
| 935 grpc_httpcli_set_override(compute_engine_httpcli_get_success_override, |
| 936 httpcli_post_should_not_be_called); |
| 937 grpc_call_credentials_get_request_metadata( |
| 938 &exec_ctx, creds->call_creds, NULL, auth_md_ctx, |
| 939 on_oauth2_creds_get_metadata_success, (void *)test_user_data); |
| 940 grpc_exec_ctx_flush(&exec_ctx); |
| 941 grpc_exec_ctx_finish(&exec_ctx); |
| 942 |
| 943 /* Check that we get a cached creds if we call |
| 944 grpc_google_default_credentials_create again. |
| 945 GCE detection should not occur anymore either. */ |
| 946 grpc_httpcli_set_override(httpcli_get_should_not_be_called, |
| 947 httpcli_post_should_not_be_called); |
| 948 cached_creds = grpc_google_default_credentials_create(); |
| 949 GPR_ASSERT(cached_creds == &creds->base); |
| 950 |
| 951 /* Cleanup. */ |
| 952 grpc_channel_credentials_release(cached_creds); |
| 953 grpc_channel_credentials_release(&creds->base); |
| 954 grpc_httpcli_set_override(NULL, NULL); |
| 955 grpc_override_well_known_credentials_path_getter(NULL); |
| 956 } |
| 957 |
| 958 static int default_creds_gce_detection_httpcli_get_failure_override( |
| 959 grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, |
| 960 gpr_timespec deadline, grpc_httpcli_response_cb on_response, |
| 961 void *user_data) { |
| 962 /* No magic header. */ |
| 963 grpc_httpcli_response response = http_response(200, ""); |
| 964 GPR_ASSERT(strcmp(request->path, "/") == 0); |
| 965 GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); |
| 966 on_response(exec_ctx, user_data, &response); |
| 967 return 1; |
| 968 } |
| 969 |
| 970 static void test_no_google_default_creds(void) { |
| 971 grpc_flush_cached_google_default_credentials(); |
| 972 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ |
| 973 grpc_override_well_known_credentials_path_getter( |
| 974 null_well_known_creds_path_getter); |
| 975 |
| 976 /* Simulate a successful detection of GCE. */ |
| 977 grpc_httpcli_set_override( |
| 978 default_creds_gce_detection_httpcli_get_failure_override, |
| 979 httpcli_post_should_not_be_called); |
| 980 GPR_ASSERT(grpc_google_default_credentials_create() == NULL); |
| 981 |
| 982 /* Try a cached one. GCE detection should not occur anymore. */ |
| 983 grpc_httpcli_set_override(httpcli_get_should_not_be_called, |
| 984 httpcli_post_should_not_be_called); |
| 985 GPR_ASSERT(grpc_google_default_credentials_create() == NULL); |
| 986 |
| 987 /* Cleanup. */ |
| 988 grpc_httpcli_set_override(NULL, NULL); |
| 989 grpc_override_well_known_credentials_path_getter(NULL); |
| 990 } |
| 991 |
| 992 typedef enum { |
| 993 PLUGIN_INITIAL_STATE, |
| 994 PLUGIN_GET_METADATA_CALLED_STATE, |
| 995 PLUGIN_DESTROY_CALLED_STATE |
| 996 } plugin_state; |
| 997 |
| 998 typedef struct { |
| 999 const char *key; |
| 1000 const char *value; |
| 1001 } plugin_metadata; |
| 1002 |
| 1003 static const plugin_metadata plugin_md[] = {{"foo", "bar"}, {"hi", "there"}}; |
| 1004 |
| 1005 static void plugin_get_metadata_success(void *state, |
| 1006 grpc_auth_metadata_context context, |
| 1007 grpc_credentials_plugin_metadata_cb cb, |
| 1008 void *user_data) { |
| 1009 size_t i; |
| 1010 grpc_metadata md[GPR_ARRAY_SIZE(plugin_md)]; |
| 1011 plugin_state *s = (plugin_state *)state; |
| 1012 GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0); |
| 1013 GPR_ASSERT(strcmp(context.method_name, test_method) == 0); |
| 1014 GPR_ASSERT(context.channel_auth_context == NULL); |
| 1015 GPR_ASSERT(context.reserved == NULL); |
| 1016 *s = PLUGIN_GET_METADATA_CALLED_STATE; |
| 1017 for (i = 0; i < GPR_ARRAY_SIZE(plugin_md); i++) { |
| 1018 memset(&md[i], 0, sizeof(grpc_metadata)); |
| 1019 md[i].key = plugin_md[i].key; |
| 1020 md[i].value = plugin_md[i].value; |
| 1021 md[i].value_length = strlen(plugin_md[i].value); |
| 1022 } |
| 1023 cb(user_data, md, GPR_ARRAY_SIZE(md), GRPC_STATUS_OK, NULL); |
| 1024 } |
| 1025 |
| 1026 static void plugin_get_metadata_failure(void *state, |
| 1027 grpc_auth_metadata_context context, |
| 1028 grpc_credentials_plugin_metadata_cb cb, |
| 1029 void *user_data) { |
| 1030 plugin_state *s = (plugin_state *)state; |
| 1031 GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0); |
| 1032 GPR_ASSERT(strcmp(context.method_name, test_method) == 0); |
| 1033 GPR_ASSERT(context.channel_auth_context == NULL); |
| 1034 GPR_ASSERT(context.reserved == NULL); |
| 1035 *s = PLUGIN_GET_METADATA_CALLED_STATE; |
| 1036 cb(user_data, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, |
| 1037 "Could not get metadata for plugin."); |
| 1038 } |
| 1039 |
| 1040 static void on_plugin_metadata_received_success( |
| 1041 grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, |
| 1042 size_t num_md, grpc_credentials_status status) { |
| 1043 size_t i = 0; |
| 1044 GPR_ASSERT(user_data == NULL); |
| 1045 GPR_ASSERT(md_elems != NULL); |
| 1046 GPR_ASSERT(num_md == GPR_ARRAY_SIZE(plugin_md)); |
| 1047 for (i = 0; i < num_md; i++) { |
| 1048 GPR_ASSERT(gpr_slice_str_cmp(md_elems[i].key, plugin_md[i].key) == 0); |
| 1049 GPR_ASSERT(gpr_slice_str_cmp(md_elems[i].value, plugin_md[i].value) == 0); |
| 1050 } |
| 1051 } |
| 1052 |
| 1053 static void on_plugin_metadata_received_failure( |
| 1054 grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, |
| 1055 size_t num_md, grpc_credentials_status status) { |
| 1056 GPR_ASSERT(user_data == NULL); |
| 1057 GPR_ASSERT(md_elems == NULL); |
| 1058 GPR_ASSERT(num_md == 0); |
| 1059 GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); |
| 1060 } |
| 1061 |
| 1062 static void plugin_destroy(void *state) { |
| 1063 plugin_state *s = (plugin_state *)state; |
| 1064 *s = PLUGIN_DESTROY_CALLED_STATE; |
| 1065 } |
| 1066 |
| 1067 static void test_metadata_plugin_success(void) { |
| 1068 grpc_call_credentials *creds; |
| 1069 plugin_state state = PLUGIN_INITIAL_STATE; |
| 1070 grpc_metadata_credentials_plugin plugin; |
| 1071 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 1072 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 1073 NULL}; |
| 1074 |
| 1075 plugin.state = &state; |
| 1076 plugin.get_metadata = plugin_get_metadata_success; |
| 1077 plugin.destroy = plugin_destroy; |
| 1078 |
| 1079 creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL); |
| 1080 GPR_ASSERT(state == PLUGIN_INITIAL_STATE); |
| 1081 grpc_call_credentials_get_request_metadata( |
| 1082 &exec_ctx, creds, NULL, auth_md_ctx, on_plugin_metadata_received_success, |
| 1083 NULL); |
| 1084 GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE); |
| 1085 grpc_call_credentials_release(creds); |
| 1086 GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE); |
| 1087 grpc_exec_ctx_finish(&exec_ctx); |
| 1088 } |
| 1089 |
| 1090 static void test_metadata_plugin_failure(void) { |
| 1091 grpc_call_credentials *creds; |
| 1092 plugin_state state = PLUGIN_INITIAL_STATE; |
| 1093 grpc_metadata_credentials_plugin plugin; |
| 1094 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 1095 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, |
| 1096 NULL}; |
| 1097 |
| 1098 plugin.state = &state; |
| 1099 plugin.get_metadata = plugin_get_metadata_failure; |
| 1100 plugin.destroy = plugin_destroy; |
| 1101 |
| 1102 creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL); |
| 1103 GPR_ASSERT(state == PLUGIN_INITIAL_STATE); |
| 1104 grpc_call_credentials_get_request_metadata( |
| 1105 &exec_ctx, creds, NULL, auth_md_ctx, on_plugin_metadata_received_failure, |
| 1106 NULL); |
| 1107 GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE); |
| 1108 grpc_call_credentials_release(creds); |
| 1109 GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE); |
| 1110 grpc_exec_ctx_finish(&exec_ctx); |
| 1111 } |
| 1112 |
| 1113 static void test_get_well_known_google_credentials_file_path(void) { |
| 1114 #ifdef GPR_POSIX_FILE |
| 1115 char *path; |
| 1116 char *old_home = gpr_getenv("HOME"); |
| 1117 gpr_setenv("HOME", "/tmp"); |
| 1118 path = grpc_get_well_known_google_credentials_file_path(); |
| 1119 GPR_ASSERT(path != NULL); |
| 1120 GPR_ASSERT(0 == strcmp("/tmp/.config/" GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY |
| 1121 "/" GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE, |
| 1122 path)); |
| 1123 gpr_free(path); |
| 1124 #if defined(GPR_POSIX_ENV) || defined(GPR_LINUX_ENV) |
| 1125 unsetenv("HOME"); |
| 1126 path = grpc_get_well_known_google_credentials_file_path(); |
| 1127 GPR_ASSERT(path == NULL); |
| 1128 #endif /* GPR_POSIX_ENV || GPR_LINUX_ENV */ |
| 1129 gpr_setenv("HOME", old_home); |
| 1130 gpr_free(old_home); |
| 1131 #else /* GPR_POSIX_FILE */ |
| 1132 char *path = grpc_get_well_known_google_credentials_file_path(); |
| 1133 GPR_ASSERT(path != NULL); |
| 1134 gpr_free(path); |
| 1135 #endif |
| 1136 } |
| 1137 |
| 1138 int main(int argc, char **argv) { |
| 1139 grpc_test_init(argc, argv); |
| 1140 grpc_init(); |
| 1141 test_empty_md_store(); |
| 1142 test_ref_unref_empty_md_store(); |
| 1143 test_add_to_empty_md_store(); |
| 1144 test_add_cstrings_to_empty_md_store(); |
| 1145 test_empty_preallocated_md_store(); |
| 1146 test_add_abunch_to_md_store(); |
| 1147 test_oauth2_token_fetcher_creds_parsing_ok(); |
| 1148 test_oauth2_token_fetcher_creds_parsing_bad_http_status(); |
| 1149 test_oauth2_token_fetcher_creds_parsing_empty_http_body(); |
| 1150 test_oauth2_token_fetcher_creds_parsing_invalid_json(); |
| 1151 test_oauth2_token_fetcher_creds_parsing_missing_token(); |
| 1152 test_oauth2_token_fetcher_creds_parsing_missing_token_type(); |
| 1153 test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(); |
| 1154 test_google_iam_creds(); |
| 1155 test_access_token_creds(); |
| 1156 test_channel_oauth2_composite_creds(); |
| 1157 test_oauth2_google_iam_composite_creds(); |
| 1158 test_channel_oauth2_google_iam_composite_creds(); |
| 1159 test_compute_engine_creds_success(); |
| 1160 test_compute_engine_creds_failure(); |
| 1161 test_refresh_token_creds_success(); |
| 1162 test_refresh_token_creds_failure(); |
| 1163 test_jwt_creds_success(); |
| 1164 test_jwt_creds_signing_failure(); |
| 1165 test_google_default_creds_auth_key(); |
| 1166 test_google_default_creds_refresh_token(); |
| 1167 test_google_default_creds_gce(); |
| 1168 test_no_google_default_creds(); |
| 1169 test_metadata_plugin_success(); |
| 1170 test_metadata_plugin_failure(); |
| 1171 test_get_well_known_google_credentials_file_path(); |
| 1172 grpc_shutdown(); |
| 1173 return 0; |
| 1174 } |
OLD | NEW |