3 * Copyright 2015 gRPC authors.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #include <grpc/support/port_platform.h>
21 #include "src/core/lib/security/credentials/credentials.h"
23 #include <openssl/rsa.h>
27 #include <grpc/slice.h>
29 #include <grpc/support/alloc.h>
30 #include <grpc/support/log.h>
31 #include <grpc/support/string_util.h>
32 #include <grpc/support/time.h>
34 #include "src/core/lib/gpr/env.h"
35 #include "src/core/lib/gpr/string.h"
36 #include "src/core/lib/gpr/tmpfile.h"
37 #include "src/core/lib/http/httpcli.h"
38 #include "src/core/lib/security/credentials/composite/composite_credentials.h"
39 #include "src/core/lib/security/credentials/fake/fake_credentials.h"
40 #include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
41 #include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
42 #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
43 #include "src/core/lib/security/transport/auth_filters.h"
44 #include "test/core/util/test_config.h"
46 using grpc_core::internal::grpc_flush_cached_google_default_credentials;
47 using grpc_core::internal::set_gce_tenancy_checker_for_testing;
49 /* -- Constants. -- */
51 static const char test_google_iam_authorization_token[] = "blahblahblhahb";
52 static const char test_google_iam_authority_selector[] = "respectmyauthoritah";
53 static const char test_oauth2_bearer_token[] =
54 "Bearer blaaslkdjfaslkdfasdsfasf";
56 /* This JSON key was generated with the GCE console and revoked immediately.
57 The identifiers have been changed as well.
58 Maximum size for a string literal is 509 chars in C89, yay! */
59 static const char test_json_key_str_part1[] =
60 "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----"
61 "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE"
63 "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/"
64 "rWBQvS4hle4LfijkP3J5BG+"
65 "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+"
66 "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/"
67 "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/"
68 "8HpCqFYM9V8f34SBWfD4fRFT+n/"
69 "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+";
70 static const char test_json_key_str_part2[] =
71 "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+"
72 "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/"
73 "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA"
75 "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz"
77 "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+"
78 "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/"
79 "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ"
81 "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", ";
82 static const char test_json_key_str_part3[] =
83 "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
85 "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
86 "com\", \"client_id\": "
87 "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
88 "com\", \"type\": \"service_account\" }";
90 /* Test refresh token. */
91 static const char test_refresh_token_str[] =
92 "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
93 " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
94 " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\","
95 " \"type\": \"authorized_user\"}";
97 static const char valid_oauth2_json_response[] =
98 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
99 " \"expires_in\":3599, "
100 " \"token_type\":\"Bearer\"}";
102 static const char test_scope[] = "perm1 perm2";
104 static const char test_signed_jwt[] =
105 "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM4YW"
106 "U0MDcyZTViYTdmZDkwODg2YzcifQ";
108 static const char test_service_url[] = "https://foo.com/foo.v1";
109 static const char other_test_service_url[] = "https://bar.com/bar.v1";
111 static const char test_method[] = "ThisIsNotAMethod";
113 /* -- Global state flags. -- */
115 static bool g_test_is_on_gce = false;
117 static bool g_test_gce_tenancy_checker_called = false;
121 static char* test_json_key_str(void) {
122 size_t result_len = strlen(test_json_key_str_part1) +
123 strlen(test_json_key_str_part2) +
124 strlen(test_json_key_str_part3);
125 char* result = static_cast<char*>(gpr_malloc(result_len + 1));
126 char* current = result;
127 strcpy(result, test_json_key_str_part1);
128 current += strlen(test_json_key_str_part1);
129 strcpy(current, test_json_key_str_part2);
130 current += strlen(test_json_key_str_part2);
131 strcpy(current, test_json_key_str_part3);
135 static grpc_httpcli_response http_response(int status, const char* body) {
136 grpc_httpcli_response response;
137 memset(&response, 0, sizeof(grpc_httpcli_response));
138 response.status = status;
139 response.body = gpr_strdup(const_cast<char*>(body));
140 response.body_length = strlen(body);
146 static void test_empty_md_array(void) {
147 grpc_core::ExecCtx exec_ctx;
148 grpc_credentials_mdelem_array md_array;
149 memset(&md_array, 0, sizeof(md_array));
150 GPR_ASSERT(md_array.md == nullptr);
151 GPR_ASSERT(md_array.size == 0);
152 grpc_credentials_mdelem_array_destroy(&md_array);
155 static void test_add_to_empty_md_array(void) {
156 grpc_core::ExecCtx exec_ctx;
157 grpc_credentials_mdelem_array md_array;
158 memset(&md_array, 0, sizeof(md_array));
159 const char* key = "hello";
160 const char* value = "there blah blah blah blah blah blah blah";
161 grpc_mdelem md = grpc_mdelem_from_slices(
162 grpc_slice_from_copied_string(key), grpc_slice_from_copied_string(value));
163 grpc_credentials_mdelem_array_add(&md_array, md);
164 GPR_ASSERT(md_array.size == 1);
165 GPR_ASSERT(grpc_mdelem_eq(md, md_array.md[0]));
166 GRPC_MDELEM_UNREF(md);
167 grpc_credentials_mdelem_array_destroy(&md_array);
170 static void test_add_abunch_to_md_array(void) {
171 grpc_core::ExecCtx exec_ctx;
172 grpc_credentials_mdelem_array md_array;
173 memset(&md_array, 0, sizeof(md_array));
174 const char* key = "hello";
175 const char* value = "there blah blah blah blah blah blah blah";
176 grpc_mdelem md = grpc_mdelem_from_slices(
177 grpc_slice_from_copied_string(key), grpc_slice_from_copied_string(value));
178 size_t num_entries = 1000;
179 for (size_t i = 0; i < num_entries; ++i) {
180 grpc_credentials_mdelem_array_add(&md_array, md);
182 for (size_t i = 0; i < num_entries; ++i) {
183 GPR_ASSERT(grpc_mdelem_eq(md_array.md[i], md));
185 GRPC_MDELEM_UNREF(md);
186 grpc_credentials_mdelem_array_destroy(&md_array);
189 static void test_oauth2_token_fetcher_creds_parsing_ok(void) {
190 grpc_core::ExecCtx exec_ctx;
191 grpc_mdelem token_md = GRPC_MDNULL;
192 grpc_millis token_lifetime;
193 grpc_httpcli_response response =
194 http_response(200, valid_oauth2_json_response);
195 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
196 &response, &token_md, &token_lifetime) == GRPC_CREDENTIALS_OK);
197 GPR_ASSERT(token_lifetime == 3599 * GPR_MS_PER_SEC);
198 GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(token_md), "authorization") == 0);
199 GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(token_md),
200 "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") ==
202 GRPC_MDELEM_UNREF(token_md);
203 grpc_http_response_destroy(&response);
206 static void test_oauth2_token_fetcher_creds_parsing_bad_http_status(void) {
207 grpc_core::ExecCtx exec_ctx;
208 grpc_mdelem token_md = GRPC_MDNULL;
209 grpc_millis token_lifetime;
210 grpc_httpcli_response response =
211 http_response(401, valid_oauth2_json_response);
212 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
213 &response, &token_md, &token_lifetime) ==
214 GRPC_CREDENTIALS_ERROR);
215 grpc_http_response_destroy(&response);
218 static void test_oauth2_token_fetcher_creds_parsing_empty_http_body(void) {
219 grpc_core::ExecCtx exec_ctx;
220 grpc_mdelem token_md = GRPC_MDNULL;
221 grpc_millis token_lifetime;
222 grpc_httpcli_response response = http_response(200, "");
223 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
224 &response, &token_md, &token_lifetime) ==
225 GRPC_CREDENTIALS_ERROR);
226 grpc_http_response_destroy(&response);
229 static void test_oauth2_token_fetcher_creds_parsing_invalid_json(void) {
230 grpc_core::ExecCtx exec_ctx;
231 grpc_mdelem token_md = GRPC_MDNULL;
232 grpc_millis token_lifetime;
233 grpc_httpcli_response response =
235 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
236 " \"expires_in\":3599, "
237 " \"token_type\":\"Bearer\"");
238 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
239 &response, &token_md, &token_lifetime) ==
240 GRPC_CREDENTIALS_ERROR);
241 grpc_http_response_destroy(&response);
244 static void test_oauth2_token_fetcher_creds_parsing_missing_token(void) {
245 grpc_core::ExecCtx exec_ctx;
246 grpc_mdelem token_md = GRPC_MDNULL;
247 grpc_millis token_lifetime;
248 grpc_httpcli_response response = http_response(200,
250 " \"expires_in\":3599, "
251 " \"token_type\":\"Bearer\"}");
252 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
253 &response, &token_md, &token_lifetime) ==
254 GRPC_CREDENTIALS_ERROR);
255 grpc_http_response_destroy(&response);
258 static void test_oauth2_token_fetcher_creds_parsing_missing_token_type(void) {
259 grpc_core::ExecCtx exec_ctx;
260 grpc_mdelem token_md = GRPC_MDNULL;
261 grpc_millis token_lifetime;
262 grpc_httpcli_response response =
264 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
265 " \"expires_in\":3599, "
267 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
268 &response, &token_md, &token_lifetime) ==
269 GRPC_CREDENTIALS_ERROR);
270 grpc_http_response_destroy(&response);
273 static void test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(
275 grpc_core::ExecCtx exec_ctx;
276 grpc_mdelem token_md = GRPC_MDNULL;
277 grpc_millis token_lifetime;
278 grpc_httpcli_response response =
280 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
281 " \"token_type\":\"Bearer\"}");
282 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
283 &response, &token_md, &token_lifetime) ==
284 GRPC_CREDENTIALS_ERROR);
285 grpc_http_response_destroy(&response);
294 grpc_error* expected_error;
295 const expected_md* expected;
296 size_t expected_size;
297 grpc_credentials_mdelem_array md_array;
298 grpc_closure on_request_metadata;
299 grpc_call_credentials* creds;
300 grpc_polling_entity pollent;
301 } request_metadata_state;
303 static void check_metadata(const expected_md* expected,
304 grpc_credentials_mdelem_array* md_array) {
305 for (size_t i = 0; i < md_array->size; ++i) {
307 for (j = 0; j < md_array->size; ++j) {
309 grpc_slice_str_cmp(GRPC_MDKEY(md_array->md[j]), expected[i].key)) {
310 GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md_array->md[j]),
311 expected[i].value) == 0);
315 if (j == md_array->size) {
316 gpr_log(GPR_ERROR, "key %s not found", expected[i].key);
322 static void check_request_metadata(void* arg, grpc_error* error) {
323 request_metadata_state* state = static_cast<request_metadata_state*>(arg);
324 gpr_log(GPR_INFO, "expected_error: %s",
325 grpc_error_string(state->expected_error));
326 gpr_log(GPR_INFO, "actual_error: %s", grpc_error_string(error));
327 if (state->expected_error == GRPC_ERROR_NONE) {
328 GPR_ASSERT(error == GRPC_ERROR_NONE);
330 grpc_slice expected_error;
331 GPR_ASSERT(grpc_error_get_str(state->expected_error,
332 GRPC_ERROR_STR_DESCRIPTION, &expected_error));
333 grpc_slice actual_error;
335 grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error));
336 GPR_ASSERT(grpc_slice_cmp(expected_error, actual_error) == 0);
337 GRPC_ERROR_UNREF(state->expected_error);
339 gpr_log(GPR_INFO, "expected_size=%" PRIdPTR " actual_size=%" PRIdPTR,
340 state->expected_size, state->md_array.size);
341 GPR_ASSERT(state->md_array.size == state->expected_size);
342 check_metadata(state->expected, &state->md_array);
343 grpc_credentials_mdelem_array_destroy(&state->md_array);
344 grpc_pollset_set_destroy(grpc_polling_entity_pollset_set(&state->pollent));
348 static request_metadata_state* make_request_metadata_state(
349 grpc_error* expected_error, const expected_md* expected,
350 size_t expected_size) {
351 request_metadata_state* state =
352 static_cast<request_metadata_state*>(gpr_zalloc(sizeof(*state)));
353 state->expected_error = expected_error;
354 state->expected = expected;
355 state->expected_size = expected_size;
357 grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create());
358 GRPC_CLOSURE_INIT(&state->on_request_metadata, check_request_metadata, state,
359 grpc_schedule_on_exec_ctx);
363 static void run_request_metadata_test(grpc_call_credentials* creds,
364 grpc_auth_metadata_context auth_md_ctx,
365 request_metadata_state* state) {
366 grpc_error* error = GRPC_ERROR_NONE;
367 if (creds->get_request_metadata(&state->pollent, auth_md_ctx,
368 &state->md_array, &state->on_request_metadata,
370 // Synchronous result. Invoke the callback directly.
371 check_request_metadata(state, error);
372 GRPC_ERROR_UNREF(error);
376 static void test_google_iam_creds(void) {
377 grpc_core::ExecCtx exec_ctx;
378 expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
379 test_google_iam_authorization_token},
380 {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
381 test_google_iam_authority_selector}};
382 request_metadata_state* state =
383 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
384 grpc_call_credentials* creds = grpc_google_iam_credentials_create(
385 test_google_iam_authorization_token, test_google_iam_authority_selector,
387 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
389 run_request_metadata_test(creds, auth_md_ctx, state);
393 static void test_access_token_creds(void) {
394 grpc_core::ExecCtx exec_ctx;
395 expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}};
396 request_metadata_state* state =
397 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
398 grpc_call_credentials* creds =
399 grpc_access_token_credentials_create("blah", nullptr);
400 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
402 GPR_ASSERT(strcmp(creds->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
403 run_request_metadata_test(creds, auth_md_ctx, state);
408 class check_channel_oauth2 final : public grpc_channel_credentials {
410 check_channel_oauth2() : grpc_channel_credentials("mock") {}
411 ~check_channel_oauth2() override = default;
413 grpc_core::RefCountedPtr<grpc_channel_security_connector>
414 create_security_connector(
415 grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
416 const char* target, const grpc_channel_args* args,
417 grpc_channel_args** new_args) override {
418 GPR_ASSERT(strcmp(type(), "mock") == 0);
419 GPR_ASSERT(call_creds != nullptr);
420 GPR_ASSERT(strcmp(call_creds->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) ==
427 static void test_channel_oauth2_composite_creds(void) {
428 grpc_core::ExecCtx exec_ctx;
429 grpc_channel_args* new_args;
430 grpc_channel_credentials* channel_creds =
431 grpc_core::New<check_channel_oauth2>();
432 grpc_call_credentials* oauth2_creds =
433 grpc_access_token_credentials_create("blah", nullptr);
434 grpc_channel_credentials* channel_oauth2_creds =
435 grpc_composite_channel_credentials_create(channel_creds, oauth2_creds,
437 grpc_channel_credentials_release(channel_creds);
438 grpc_call_credentials_release(oauth2_creds);
439 channel_oauth2_creds->create_security_connector(nullptr, nullptr, nullptr,
441 grpc_channel_credentials_release(channel_oauth2_creds);
444 static void test_oauth2_google_iam_composite_creds(void) {
445 grpc_core::ExecCtx exec_ctx;
446 expected_md emd[] = {
447 {GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token},
448 {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
449 test_google_iam_authorization_token},
450 {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
451 test_google_iam_authority_selector}};
452 request_metadata_state* state =
453 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
454 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
456 grpc_call_credentials* oauth2_creds = grpc_md_only_test_credentials_create(
457 "authorization", test_oauth2_bearer_token, 0);
458 grpc_call_credentials* google_iam_creds = grpc_google_iam_credentials_create(
459 test_google_iam_authorization_token, test_google_iam_authority_selector,
461 grpc_call_credentials* composite_creds =
462 grpc_composite_call_credentials_create(oauth2_creds, google_iam_creds,
464 oauth2_creds->Unref();
465 google_iam_creds->Unref();
466 GPR_ASSERT(strcmp(composite_creds->type(),
467 GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
468 const grpc_composite_call_credentials::CallCredentialsList& creds_list =
469 static_cast<const grpc_composite_call_credentials*>(composite_creds)
471 GPR_ASSERT(creds_list.size() == 2);
472 GPR_ASSERT(strcmp(creds_list[0]->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) ==
474 GPR_ASSERT(strcmp(creds_list[1]->type(), GRPC_CALL_CREDENTIALS_TYPE_IAM) ==
476 run_request_metadata_test(composite_creds, auth_md_ctx, state);
477 composite_creds->Unref();
481 class check_channel_oauth2_google_iam final : public grpc_channel_credentials {
483 check_channel_oauth2_google_iam() : grpc_channel_credentials("mock") {}
484 ~check_channel_oauth2_google_iam() override = default;
486 grpc_core::RefCountedPtr<grpc_channel_security_connector>
487 create_security_connector(
488 grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
489 const char* target, const grpc_channel_args* args,
490 grpc_channel_args** new_args) override {
491 GPR_ASSERT(strcmp(type(), "mock") == 0);
492 GPR_ASSERT(call_creds != nullptr);
494 strcmp(call_creds->type(), GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
495 const grpc_composite_call_credentials::CallCredentialsList& creds_list =
496 static_cast<const grpc_composite_call_credentials*>(call_creds.get())
499 strcmp(creds_list[0]->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
500 GPR_ASSERT(strcmp(creds_list[1]->type(), GRPC_CALL_CREDENTIALS_TYPE_IAM) ==
507 static void test_channel_oauth2_google_iam_composite_creds(void) {
508 grpc_core::ExecCtx exec_ctx;
509 grpc_channel_args* new_args;
510 grpc_channel_credentials* channel_creds =
511 grpc_core::New<check_channel_oauth2_google_iam>();
512 grpc_call_credentials* oauth2_creds =
513 grpc_access_token_credentials_create("blah", nullptr);
514 grpc_channel_credentials* channel_oauth2_creds =
515 grpc_composite_channel_credentials_create(channel_creds, oauth2_creds,
517 grpc_call_credentials* google_iam_creds = grpc_google_iam_credentials_create(
518 test_google_iam_authorization_token, test_google_iam_authority_selector,
520 grpc_channel_credentials* channel_oauth2_iam_creds =
521 grpc_composite_channel_credentials_create(channel_oauth2_creds,
522 google_iam_creds, nullptr);
523 grpc_channel_credentials_release(channel_creds);
524 grpc_call_credentials_release(oauth2_creds);
525 grpc_channel_credentials_release(channel_oauth2_creds);
526 grpc_call_credentials_release(google_iam_creds);
528 channel_oauth2_iam_creds->create_security_connector(nullptr, nullptr, nullptr,
531 grpc_channel_credentials_release(channel_oauth2_iam_creds);
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.google.internal.") == 0);
539 strcmp(request->http.path,
540 "/computeMetadata/v1/instance/service-accounts/default/token") ==
542 GPR_ASSERT(request->http.hdr_count == 1);
543 GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Metadata-Flavor") == 0);
544 GPR_ASSERT(strcmp(request->http.hdrs[0].value, "Google") == 0);
547 static int compute_engine_httpcli_get_success_override(
548 const grpc_httpcli_request* request, grpc_millis deadline,
549 grpc_closure* on_done, grpc_httpcli_response* response) {
550 validate_compute_engine_http_request(request);
551 *response = http_response(200, valid_oauth2_json_response);
552 GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
556 static int compute_engine_httpcli_get_failure_override(
557 const grpc_httpcli_request* request, grpc_millis deadline,
558 grpc_closure* on_done, grpc_httpcli_response* response) {
559 validate_compute_engine_http_request(request);
560 *response = http_response(403, "Not Authorized.");
561 GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
565 static int httpcli_post_should_not_be_called(
566 const grpc_httpcli_request* request, const char* body_bytes,
567 size_t body_size, grpc_millis deadline, grpc_closure* on_done,
568 grpc_httpcli_response* response) {
569 GPR_ASSERT("HTTP POST should not be called" == nullptr);
573 static int httpcli_get_should_not_be_called(const grpc_httpcli_request* request,
574 grpc_millis deadline,
575 grpc_closure* on_done,
576 grpc_httpcli_response* response) {
577 GPR_ASSERT("HTTP GET should not be called" == nullptr);
581 static void test_compute_engine_creds_success() {
582 grpc_core::ExecCtx exec_ctx;
583 expected_md emd[] = {
584 {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
585 grpc_call_credentials* creds =
586 grpc_google_compute_engine_credentials_create(nullptr);
587 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
590 /* First request: http get should be called. */
591 request_metadata_state* state =
592 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
593 grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
594 httpcli_post_should_not_be_called);
595 run_request_metadata_test(creds, auth_md_ctx, state);
596 grpc_core::ExecCtx::Get()->Flush();
598 /* Second request: the cached token should be served directly. */
600 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
601 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
602 httpcli_post_should_not_be_called);
603 run_request_metadata_test(creds, auth_md_ctx, state);
604 grpc_core::ExecCtx::Get()->Flush();
607 grpc_httpcli_set_override(nullptr, nullptr);
610 static void test_compute_engine_creds_failure(void) {
611 grpc_core::ExecCtx exec_ctx;
612 request_metadata_state* state = make_request_metadata_state(
613 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
614 "Error occurred when fetching oauth2 token."),
616 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
618 grpc_call_credentials* creds =
619 grpc_google_compute_engine_credentials_create(nullptr);
620 grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override,
621 httpcli_post_should_not_be_called);
622 run_request_metadata_test(creds, auth_md_ctx, state);
624 grpc_httpcli_set_override(nullptr, nullptr);
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 = nullptr;
631 GPR_ASSERT(body != nullptr);
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);
643 strcmp(request->http.path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0);
644 GPR_ASSERT(request->http.hdr_count == 1);
645 GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Content-Type") == 0);
646 GPR_ASSERT(strcmp(request->http.hdrs[0].value,
647 "application/x-www-form-urlencoded") == 0);
650 static int refresh_token_httpcli_post_success(
651 const grpc_httpcli_request* request, const char* body, size_t body_size,
652 grpc_millis deadline, grpc_closure* on_done,
653 grpc_httpcli_response* response) {
654 validate_refresh_token_http_request(request, body, body_size);
655 *response = http_response(200, valid_oauth2_json_response);
656 GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
660 static int refresh_token_httpcli_post_failure(
661 const grpc_httpcli_request* request, const char* body, size_t body_size,
662 grpc_millis deadline, grpc_closure* on_done,
663 grpc_httpcli_response* response) {
664 validate_refresh_token_http_request(request, body, body_size);
665 *response = http_response(403, "Not Authorized.");
666 GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
670 static void test_refresh_token_creds_success(void) {
671 grpc_core::ExecCtx exec_ctx;
672 expected_md emd[] = {
673 {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
674 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
676 grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
677 test_refresh_token_str, nullptr);
679 /* First request: http get should be called. */
680 request_metadata_state* state =
681 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
682 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
683 refresh_token_httpcli_post_success);
684 run_request_metadata_test(creds, auth_md_ctx, state);
685 grpc_core::ExecCtx::Get()->Flush();
687 /* Second request: the cached token should be served directly. */
689 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
690 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
691 httpcli_post_should_not_be_called);
692 run_request_metadata_test(creds, auth_md_ctx, state);
693 grpc_core::ExecCtx::Get()->Flush();
696 grpc_httpcli_set_override(nullptr, nullptr);
699 static void test_refresh_token_creds_failure(void) {
700 grpc_core::ExecCtx exec_ctx;
701 request_metadata_state* state = make_request_metadata_state(
702 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
703 "Error occurred when fetching oauth2 token."),
705 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
707 grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
708 test_refresh_token_str, nullptr);
709 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
710 refresh_token_httpcli_post_failure);
711 run_request_metadata_test(creds, auth_md_ctx, state);
713 grpc_httpcli_set_override(nullptr, nullptr);
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 != nullptr);
721 GPR_ASSERT(RSA_check_key(json_key->private_key));
722 GPR_ASSERT(json_key->type != nullptr &&
723 strcmp(json_key->type, "service_account") == 0);
724 GPR_ASSERT(json_key->private_key_id != nullptr &&
725 strcmp(json_key->private_key_id,
726 "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0);
727 GPR_ASSERT(json_key->client_id != nullptr &&
728 strcmp(json_key->client_id,
729 "777-abaslkan11hlb6nmim3bpspl31ud.apps."
730 "googleusercontent.com") == 0);
731 GPR_ASSERT(json_key->client_email != nullptr &&
732 strcmp(json_key->client_email,
733 "777-abaslkan11hlb6nmim3bpspl31ud@developer."
734 "gserviceaccount.com") == 0);
735 if (scope != nullptr) GPR_ASSERT(strcmp(scope, test_scope) == 0);
736 GPR_ASSERT(!gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime()));
739 static char* encode_and_sign_jwt_success(const grpc_auth_json_key* json_key,
740 const char* audience,
741 gpr_timespec token_lifetime,
743 validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime);
744 return gpr_strdup(test_signed_jwt);
747 static char* encode_and_sign_jwt_failure(const grpc_auth_json_key* json_key,
748 const char* audience,
749 gpr_timespec token_lifetime,
751 validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime);
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" == nullptr);
762 static grpc_service_account_jwt_access_credentials* creds_as_jwt(
763 grpc_call_credentials* creds) {
764 GPR_ASSERT(creds != nullptr);
765 GPR_ASSERT(strcmp(creds->type(), GRPC_CALL_CREDENTIALS_TYPE_JWT) == 0);
766 return reinterpret_cast<grpc_service_account_jwt_access_credentials*>(creds);
769 static void test_jwt_creds_lifetime(void) {
770 char* json_key_string = test_json_key_str();
773 grpc_call_credentials* jwt_creds =
774 grpc_service_account_jwt_access_credentials_create(
775 json_key_string, grpc_max_auth_token_lifetime(), nullptr);
776 GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime(),
777 grpc_max_auth_token_lifetime()) == 0);
778 grpc_call_credentials_release(jwt_creds);
781 gpr_timespec token_lifetime = {10, 0, GPR_TIMESPAN};
782 GPR_ASSERT(gpr_time_cmp(grpc_max_auth_token_lifetime(), token_lifetime) > 0);
783 jwt_creds = grpc_service_account_jwt_access_credentials_create(
784 json_key_string, token_lifetime, nullptr);
785 GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime(),
786 token_lifetime) == 0);
787 grpc_call_credentials_release(jwt_creds);
790 gpr_timespec add_to_max = {10, 0, GPR_TIMESPAN};
791 token_lifetime = gpr_time_add(grpc_max_auth_token_lifetime(), add_to_max);
792 jwt_creds = grpc_service_account_jwt_access_credentials_create(
793 json_key_string, token_lifetime, nullptr);
794 GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime(),
795 grpc_max_auth_token_lifetime()) == 0);
796 grpc_call_credentials_release(jwt_creds);
798 gpr_free(json_key_string);
801 static void test_jwt_creds_success(void) {
802 char* json_key_string = test_json_key_str();
803 grpc_core::ExecCtx exec_ctx;
804 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
806 char* expected_md_value;
807 gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt);
808 expected_md emd[] = {{"authorization", expected_md_value}};
809 grpc_call_credentials* creds =
810 grpc_service_account_jwt_access_credentials_create(
811 json_key_string, grpc_max_auth_token_lifetime(), nullptr);
813 /* First request: jwt_encode_and_sign should be called. */
814 request_metadata_state* state =
815 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
816 grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
817 run_request_metadata_test(creds, auth_md_ctx, state);
818 grpc_core::ExecCtx::Get()->Flush();
820 /* Second request: the cached token should be served directly. */
822 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
823 grpc_jwt_encode_and_sign_set_override(
824 encode_and_sign_jwt_should_not_be_called);
825 run_request_metadata_test(creds, auth_md_ctx, state);
826 grpc_core::ExecCtx::Get()->Flush();
828 /* Third request: Different service url so jwt_encode_and_sign should be
829 called again (no caching). */
831 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
832 auth_md_ctx.service_url = other_test_service_url;
833 grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
834 run_request_metadata_test(creds, auth_md_ctx, state);
835 grpc_core::ExecCtx::Get()->Flush();
838 gpr_free(json_key_string);
839 gpr_free(expected_md_value);
840 grpc_jwt_encode_and_sign_set_override(nullptr);
843 static void test_jwt_creds_signing_failure(void) {
844 char* json_key_string = test_json_key_str();
845 grpc_core::ExecCtx exec_ctx;
846 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
848 request_metadata_state* state = make_request_metadata_state(
849 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT."), nullptr,
851 grpc_call_credentials* creds =
852 grpc_service_account_jwt_access_credentials_create(
853 json_key_string, grpc_max_auth_token_lifetime(), nullptr);
855 grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
856 run_request_metadata_test(creds, auth_md_ctx, state);
858 gpr_free(json_key_string);
860 grpc_jwt_encode_and_sign_set_override(nullptr);
863 static void set_google_default_creds_env_var_with_file_contents(
864 const char* file_prefix, const char* contents) {
865 size_t contents_len = strlen(contents);
866 char* creds_file_name;
867 FILE* creds_file = gpr_tmpfile(file_prefix, &creds_file_name);
868 GPR_ASSERT(creds_file_name != nullptr);
869 GPR_ASSERT(creds_file != nullptr);
870 GPR_ASSERT(fwrite(contents, 1, contents_len, creds_file) == contents_len);
872 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, creds_file_name);
873 gpr_free(creds_file_name);
876 static void test_google_default_creds_auth_key(void) {
877 grpc_core::ExecCtx exec_ctx;
878 grpc_composite_channel_credentials* creds;
879 char* json_key = test_json_key_str();
880 grpc_flush_cached_google_default_credentials();
881 set_google_default_creds_env_var_with_file_contents(
882 "json_key_google_default_creds", json_key);
884 creds = reinterpret_cast<grpc_composite_channel_credentials*>(
885 grpc_google_default_credentials_create());
886 auto* default_creds =
887 reinterpret_cast<const grpc_google_default_channel_credentials*>(
888 creds->inner_creds());
889 GPR_ASSERT(default_creds->ssl_creds() != nullptr);
891 reinterpret_cast<const grpc_service_account_jwt_access_credentials*>(
892 creds->call_creds());
894 strcmp(jwt->key().client_id,
895 "777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") ==
898 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
901 static void test_google_default_creds_refresh_token(void) {
902 grpc_core::ExecCtx exec_ctx;
903 grpc_composite_channel_credentials* creds;
904 grpc_flush_cached_google_default_credentials();
905 set_google_default_creds_env_var_with_file_contents(
906 "refresh_token_google_default_creds", test_refresh_token_str);
907 creds = reinterpret_cast<grpc_composite_channel_credentials*>(
908 grpc_google_default_credentials_create());
909 auto* default_creds =
910 reinterpret_cast<const grpc_google_default_channel_credentials*>(
911 creds->inner_creds());
912 GPR_ASSERT(default_creds->ssl_creds() != nullptr);
914 reinterpret_cast<const grpc_google_refresh_token_credentials*>(
915 creds->call_creds());
916 GPR_ASSERT(strcmp(refresh->refresh_token().client_id,
917 "32555999999.apps.googleusercontent.com") == 0);
919 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
922 static int default_creds_metadata_server_detection_httpcli_get_success_override(
923 const grpc_httpcli_request* request, grpc_millis deadline,
924 grpc_closure* on_done, grpc_httpcli_response* response) {
925 *response = http_response(200, "");
926 grpc_http_header* headers =
927 static_cast<grpc_http_header*>(gpr_malloc(sizeof(*headers) * 1));
928 headers[0].key = gpr_strdup("Metadata-Flavor");
929 headers[0].value = gpr_strdup("Google");
930 response->hdr_count = 1;
931 response->hdrs = headers;
932 GPR_ASSERT(strcmp(request->http.path, "/") == 0);
933 GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0);
934 GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
938 static char* null_well_known_creds_path_getter(void) { return nullptr; }
940 static bool test_gce_tenancy_checker(void) {
941 g_test_gce_tenancy_checker_called = true;
942 return g_test_is_on_gce;
945 static void test_google_default_creds_gce(void) {
946 grpc_core::ExecCtx exec_ctx;
947 expected_md emd[] = {
948 {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
949 request_metadata_state* state =
950 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
951 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
953 grpc_flush_cached_google_default_credentials();
954 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
955 grpc_override_well_known_credentials_path_getter(
956 null_well_known_creds_path_getter);
957 set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
958 g_test_gce_tenancy_checker_called = false;
959 g_test_is_on_gce = true;
961 /* Simulate a successful detection of GCE. */
962 grpc_composite_channel_credentials* creds =
963 reinterpret_cast<grpc_composite_channel_credentials*>(
964 grpc_google_default_credentials_create());
966 /* Verify that the default creds actually embeds a GCE creds. */
967 GPR_ASSERT(creds != nullptr);
968 GPR_ASSERT(creds->call_creds() != nullptr);
969 grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
970 httpcli_post_should_not_be_called);
971 run_request_metadata_test(creds->mutable_call_creds(), auth_md_ctx, state);
972 grpc_core::ExecCtx::Get()->Flush();
974 GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
978 grpc_httpcli_set_override(nullptr, nullptr);
979 grpc_override_well_known_credentials_path_getter(nullptr);
982 static void test_google_default_creds_non_gce(void) {
983 grpc_core::ExecCtx exec_ctx;
984 expected_md emd[] = {
985 {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
986 request_metadata_state* state =
987 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
988 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
990 grpc_flush_cached_google_default_credentials();
991 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
992 grpc_override_well_known_credentials_path_getter(
993 null_well_known_creds_path_getter);
994 set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
995 g_test_gce_tenancy_checker_called = false;
996 g_test_is_on_gce = false;
997 /* Simulate a successful detection of metadata server. */
998 grpc_httpcli_set_override(
999 default_creds_metadata_server_detection_httpcli_get_success_override,
1000 httpcli_post_should_not_be_called);
1001 grpc_composite_channel_credentials* creds =
1002 reinterpret_cast<grpc_composite_channel_credentials*>(
1003 grpc_google_default_credentials_create());
1004 /* Verify that the default creds actually embeds a GCE creds. */
1005 GPR_ASSERT(creds != nullptr);
1006 GPR_ASSERT(creds->call_creds() != nullptr);
1007 grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
1008 httpcli_post_should_not_be_called);
1009 run_request_metadata_test(creds->mutable_call_creds(), auth_md_ctx, state);
1010 grpc_core::ExecCtx::Get()->Flush();
1011 GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
1014 grpc_httpcli_set_override(nullptr, nullptr);
1015 grpc_override_well_known_credentials_path_getter(nullptr);
1018 static int default_creds_gce_detection_httpcli_get_failure_override(
1019 const grpc_httpcli_request* request, grpc_millis deadline,
1020 grpc_closure* on_done, grpc_httpcli_response* response) {
1021 /* No magic header. */
1022 GPR_ASSERT(strcmp(request->http.path, "/") == 0);
1023 GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0);
1024 *response = http_response(200, "");
1025 GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
1029 static void test_no_google_default_creds(void) {
1030 grpc_flush_cached_google_default_credentials();
1031 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
1032 grpc_override_well_known_credentials_path_getter(
1033 null_well_known_creds_path_getter);
1034 set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
1035 g_test_gce_tenancy_checker_called = false;
1036 g_test_is_on_gce = false;
1037 grpc_httpcli_set_override(
1038 default_creds_gce_detection_httpcli_get_failure_override,
1039 httpcli_post_should_not_be_called);
1040 /* Simulate a successful detection of GCE. */
1041 GPR_ASSERT(grpc_google_default_credentials_create() == nullptr);
1042 /* Try a second one. GCE detection should occur again. */
1043 g_test_gce_tenancy_checker_called = false;
1044 GPR_ASSERT(grpc_google_default_credentials_create() == nullptr);
1045 GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
1047 grpc_override_well_known_credentials_path_getter(nullptr);
1048 grpc_httpcli_set_override(nullptr, nullptr);
1052 PLUGIN_INITIAL_STATE,
1053 PLUGIN_GET_METADATA_CALLED_STATE,
1054 PLUGIN_DESTROY_CALLED_STATE
1057 static const expected_md plugin_md[] = {{"foo", "bar"}, {"hi", "there"}};
1059 static int plugin_get_metadata_success(
1060 void* state, grpc_auth_metadata_context context,
1061 grpc_credentials_plugin_metadata_cb cb, void* user_data,
1062 grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
1063 size_t* num_creds_md, grpc_status_code* status,
1064 const char** error_details) {
1065 GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
1066 GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
1067 GPR_ASSERT(context.channel_auth_context == nullptr);
1068 GPR_ASSERT(context.reserved == nullptr);
1069 GPR_ASSERT(GPR_ARRAY_SIZE(plugin_md) <
1070 GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX);
1071 plugin_state* s = static_cast<plugin_state*>(state);
1072 *s = PLUGIN_GET_METADATA_CALLED_STATE;
1073 for (size_t i = 0; i < GPR_ARRAY_SIZE(plugin_md); ++i) {
1074 memset(&creds_md[i], 0, sizeof(grpc_metadata));
1075 creds_md[i].key = grpc_slice_from_copied_string(plugin_md[i].key);
1076 creds_md[i].value = grpc_slice_from_copied_string(plugin_md[i].value);
1078 *num_creds_md = GPR_ARRAY_SIZE(plugin_md);
1079 return true; // Synchronous return.
1082 static const char* plugin_error_details = "Could not get metadata for plugin.";
1084 static int plugin_get_metadata_failure(
1085 void* state, grpc_auth_metadata_context context,
1086 grpc_credentials_plugin_metadata_cb cb, void* user_data,
1087 grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
1088 size_t* num_creds_md, grpc_status_code* status,
1089 const char** error_details) {
1090 GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
1091 GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
1092 GPR_ASSERT(context.channel_auth_context == nullptr);
1093 GPR_ASSERT(context.reserved == nullptr);
1094 plugin_state* s = static_cast<plugin_state*>(state);
1095 *s = PLUGIN_GET_METADATA_CALLED_STATE;
1096 *status = GRPC_STATUS_UNAUTHENTICATED;
1097 *error_details = gpr_strdup(plugin_error_details);
1098 return true; // Synchronous return.
1101 static void plugin_destroy(void* state) {
1102 plugin_state* s = static_cast<plugin_state*>(state);
1103 *s = PLUGIN_DESTROY_CALLED_STATE;
1106 static void test_metadata_plugin_success(void) {
1107 plugin_state state = PLUGIN_INITIAL_STATE;
1108 grpc_metadata_credentials_plugin plugin;
1109 grpc_core::ExecCtx exec_ctx;
1110 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1112 request_metadata_state* md_state = make_request_metadata_state(
1113 GRPC_ERROR_NONE, plugin_md, GPR_ARRAY_SIZE(plugin_md));
1115 plugin.state = &state;
1116 plugin.get_metadata = plugin_get_metadata_success;
1117 plugin.destroy = plugin_destroy;
1119 grpc_call_credentials* creds =
1120 grpc_metadata_credentials_create_from_plugin(plugin, nullptr);
1121 GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
1122 run_request_metadata_test(creds, auth_md_ctx, md_state);
1123 GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
1126 GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
1129 static void test_metadata_plugin_failure(void) {
1130 plugin_state state = PLUGIN_INITIAL_STATE;
1131 grpc_metadata_credentials_plugin plugin;
1132 grpc_core::ExecCtx exec_ctx;
1133 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1135 char* expected_error;
1136 gpr_asprintf(&expected_error,
1137 "Getting metadata from plugin failed with error: %s",
1138 plugin_error_details);
1139 request_metadata_state* md_state = make_request_metadata_state(
1140 GRPC_ERROR_CREATE_FROM_COPIED_STRING(expected_error), nullptr, 0);
1141 gpr_free(expected_error);
1143 plugin.state = &state;
1144 plugin.get_metadata = plugin_get_metadata_failure;
1145 plugin.destroy = plugin_destroy;
1147 grpc_call_credentials* creds =
1148 grpc_metadata_credentials_create_from_plugin(plugin, nullptr);
1149 GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
1150 run_request_metadata_test(creds, auth_md_ctx, md_state);
1151 GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
1154 GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
1157 static void test_get_well_known_google_credentials_file_path(void) {
1159 char* home = gpr_getenv("HOME");
1160 path = grpc_get_well_known_google_credentials_file_path();
1161 GPR_ASSERT(path != nullptr);
1163 #if defined(GPR_POSIX_ENV) || defined(GPR_LINUX_ENV)
1164 gpr_unsetenv("HOME");
1165 path = grpc_get_well_known_google_credentials_file_path();
1166 GPR_ASSERT(path == nullptr);
1167 gpr_setenv("HOME", home);
1169 #endif /* GPR_POSIX_ENV || GPR_LINUX_ENV */
1173 static void test_channel_creds_duplicate_without_call_creds(void) {
1174 grpc_core::ExecCtx exec_ctx;
1176 grpc_channel_credentials* channel_creds =
1177 grpc_fake_transport_security_credentials_create();
1179 grpc_core::RefCountedPtr<grpc_channel_credentials> dup =
1180 channel_creds->duplicate_without_call_credentials();
1181 GPR_ASSERT(dup == channel_creds);
1184 grpc_call_credentials* call_creds =
1185 grpc_access_token_credentials_create("blah", nullptr);
1186 grpc_channel_credentials* composite_creds =
1187 grpc_composite_channel_credentials_create(channel_creds, call_creds,
1189 call_creds->Unref();
1190 dup = composite_creds->duplicate_without_call_credentials();
1191 GPR_ASSERT(dup == channel_creds);
1194 channel_creds->Unref();
1195 composite_creds->Unref();
1199 const char* url_scheme;
1200 const char* call_host;
1201 const char* call_method;
1202 const char* desired_service_url;
1203 const char* desired_method_name;
1204 } auth_metadata_context_test_case;
1206 static void test_auth_metadata_context(void) {
1207 auth_metadata_context_test_case test_cases[] = {
1208 // No service nor method.
1209 {"https", "www.foo.com", "", "https://www.foo.com", ""},
1211 {"https", "www.foo.com", "/Service", "https://www.foo.com/Service", ""},
1212 // Empty service and method.
1213 {"https", "www.foo.com", "//", "https://www.foo.com/", ""},
1215 {"https", "www.foo.com", "/Service/", "https://www.foo.com/Service", ""},
1217 {"https", "www.foo.com:", "/Service/", "https://www.foo.com:/Service",
1219 // https, default explicit port.
1220 {"https", "www.foo.com:443", "/Service/FooMethod",
1221 "https://www.foo.com/Service", "FooMethod"},
1222 // https, default implicit port.
1223 {"https", "www.foo.com", "/Service/FooMethod",
1224 "https://www.foo.com/Service", "FooMethod"},
1225 // https with ipv6 literal, default explicit port.
1226 {"https", "[1080:0:0:0:8:800:200C:417A]:443", "/Service/FooMethod",
1227 "https://[1080:0:0:0:8:800:200C:417A]/Service", "FooMethod"},
1228 // https with ipv6 literal, default implicit port.
1229 {"https", "[1080:0:0:0:8:800:200C:443]", "/Service/FooMethod",
1230 "https://[1080:0:0:0:8:800:200C:443]/Service", "FooMethod"},
1231 // https, custom port.
1232 {"https", "www.foo.com:8888", "/Service/FooMethod",
1233 "https://www.foo.com:8888/Service", "FooMethod"},
1234 // https with ipv6 literal, custom port.
1235 {"https", "[1080:0:0:0:8:800:200C:417A]:8888", "/Service/FooMethod",
1236 "https://[1080:0:0:0:8:800:200C:417A]:8888/Service", "FooMethod"},
1237 // custom url scheme, https default port.
1238 {"blah", "www.foo.com:443", "/Service/FooMethod",
1239 "blah://www.foo.com:443/Service", "FooMethod"}};
1240 for (uint32_t i = 0; i < GPR_ARRAY_SIZE(test_cases); i++) {
1241 const char* url_scheme = test_cases[i].url_scheme;
1242 grpc_slice call_host =
1243 grpc_slice_from_copied_string(test_cases[i].call_host);
1244 grpc_slice call_method =
1245 grpc_slice_from_copied_string(test_cases[i].call_method);
1246 grpc_auth_metadata_context auth_md_context;
1247 memset(&auth_md_context, 0, sizeof(auth_md_context));
1248 grpc_auth_metadata_context_build(url_scheme, call_host, call_method,
1249 nullptr, &auth_md_context);
1250 if (strcmp(auth_md_context.service_url,
1251 test_cases[i].desired_service_url) != 0) {
1252 gpr_log(GPR_ERROR, "Invalid service url, want: %s, got %s.",
1253 test_cases[i].desired_service_url, auth_md_context.service_url);
1256 if (strcmp(auth_md_context.method_name,
1257 test_cases[i].desired_method_name) != 0) {
1258 gpr_log(GPR_ERROR, "Invalid method name, want: %s, got %s.",
1259 test_cases[i].desired_method_name, auth_md_context.method_name);
1262 GPR_ASSERT(auth_md_context.channel_auth_context == nullptr);
1263 grpc_slice_unref(call_host);
1264 grpc_slice_unref(call_method);
1265 grpc_auth_metadata_context_reset(&auth_md_context);
1269 int main(int argc, char** argv) {
1270 grpc::testing::TestEnvironment env(argc, argv);
1272 test_empty_md_array();
1273 test_add_to_empty_md_array();
1274 test_add_abunch_to_md_array();
1275 test_oauth2_token_fetcher_creds_parsing_ok();
1276 test_oauth2_token_fetcher_creds_parsing_bad_http_status();
1277 test_oauth2_token_fetcher_creds_parsing_empty_http_body();
1278 test_oauth2_token_fetcher_creds_parsing_invalid_json();
1279 test_oauth2_token_fetcher_creds_parsing_missing_token();
1280 test_oauth2_token_fetcher_creds_parsing_missing_token_type();
1281 test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime();
1282 test_google_iam_creds();
1283 test_access_token_creds();
1284 test_channel_oauth2_composite_creds();
1285 test_oauth2_google_iam_composite_creds();
1286 test_channel_oauth2_google_iam_composite_creds();
1287 test_compute_engine_creds_success();
1288 test_compute_engine_creds_failure();
1289 test_refresh_token_creds_success();
1290 test_refresh_token_creds_failure();
1291 test_jwt_creds_lifetime();
1292 test_jwt_creds_success();
1293 test_jwt_creds_signing_failure();
1294 test_google_default_creds_auth_key();
1295 test_google_default_creds_refresh_token();
1296 test_google_default_creds_gce();
1297 test_google_default_creds_non_gce();
1298 test_no_google_default_creds();
1299 test_metadata_plugin_success();
1300 test_metadata_plugin_failure();
1301 test_get_well_known_google_credentials_file_path();
1302 test_channel_creds_duplicate_without_call_creds();
1303 test_auth_metadata_context();