1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
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
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 *
17 */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/security/credentials/credentials.h"
22
23 #include <openssl/rsa.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <string>
28
29 #include "absl/strings/str_cat.h"
30 #include "absl/strings/str_format.h"
31
32 #include <grpc/grpc_security.h>
33 #include <grpc/slice.h>
34 #include <grpc/support/alloc.h>
35 #include <grpc/support/log.h>
36 #include <grpc/support/string_util.h>
37 #include <grpc/support/time.h>
38
39 #include "src/core/lib/gpr/env.h"
40 #include "src/core/lib/gpr/string.h"
41 #include "src/core/lib/gpr/tmpfile.h"
42 #include "src/core/lib/gprpp/host_port.h"
43 #include "src/core/lib/http/httpcli.h"
44 #include "src/core/lib/iomgr/error.h"
45 #include "src/core/lib/security/credentials/composite/composite_credentials.h"
46 #include "src/core/lib/security/credentials/fake/fake_credentials.h"
47 #include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
48 #include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
49 #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
50 #include "src/core/lib/security/transport/auth_filters.h"
51 #include "src/core/lib/uri/uri_parser.h"
52 #include "test/core/util/test_config.h"
53
54 using grpc_core::internal::grpc_flush_cached_google_default_credentials;
55 using grpc_core::internal::set_gce_tenancy_checker_for_testing;
56
57 /* -- Constants. -- */
58
59 static const char test_google_iam_authorization_token[] = "blahblahblhahb";
60 static const char test_google_iam_authority_selector[] = "respectmyauthoritah";
61 static const char test_oauth2_bearer_token[] =
62 "Bearer blaaslkdjfaslkdfasdsfasf";
63
64 /* This JSON key was generated with the GCE console and revoked immediately.
65 The identifiers have been changed as well.
66 Maximum size for a string literal is 509 chars in C89, yay! */
67 static const char test_json_key_str_part1[] =
68 "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----"
69 "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE"
70 "qg"
71 "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/"
72 "rWBQvS4hle4LfijkP3J5BG+"
73 "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+"
74 "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/"
75 "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/"
76 "8HpCqFYM9V8f34SBWfD4fRFT+n/"
77 "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+";
78 static const char test_json_key_str_part2[] =
79 "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+"
80 "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/"
81 "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA"
82 "G"
83 "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz"
84 "A"
85 "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+"
86 "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/"
87 "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ"
88 "Y"
89 "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", ";
90 static const char test_json_key_str_part3[] =
91 "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
92 "\"client_email\": "
93 "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
94 "com\", \"client_id\": "
95 "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
96 "com\", \"type\": \"service_account\" }";
97
98 /* Test refresh token. */
99 static const char test_refresh_token_str[] =
100 "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
101 " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
102 " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\","
103 " \"type\": \"authorized_user\"}";
104
105 static const char valid_oauth2_json_response[] =
106 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
107 " \"expires_in\":3599, "
108 " \"token_type\":\"Bearer\"}";
109
110 static const char valid_sts_json_response[] =
111 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
112 " \"expires_in\":3599, "
113 " \"issued_token_type\":\"urn:ietf:params:oauth:token-type:access_token\", "
114 " \"token_type\":\"Bearer\"}";
115
116 static const char test_scope[] = "perm1 perm2";
117
118 static const char test_signed_jwt[] =
119 "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM4YW"
120 "U0MDcyZTViYTdmZDkwODg2YzcifQ";
121 static const char test_signed_jwt_token_type[] =
122 "urn:ietf:params:oauth:token-type:id_token";
123 static const char test_signed_jwt2[] =
124 "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM5YW"
125 "U2MDcyZTViYTdnZDkwODg5YzcifQ";
126 static const char test_signed_jwt_token_type2[] =
127 "urn:ietf:params:oauth:token-type:jwt";
128 static const char test_signed_jwt_path_prefix[] = "test_sign_jwt";
129
130 static const char test_service_url[] = "https://foo.com/foo.v1";
131 static const char other_test_service_url[] = "https://bar.com/bar.v1";
132
133 static const char test_sts_endpoint_url[] =
134 "https://foo.com:5555/v1/token-exchange";
135
136 static const char test_method[] = "ThisIsNotAMethod";
137
138 /* -- Global state flags. -- */
139
140 static bool g_test_is_on_gce = false;
141
142 static bool g_test_gce_tenancy_checker_called = false;
143
144 /* -- Utils. -- */
145
test_json_key_str(void)146 static char* test_json_key_str(void) {
147 size_t result_len = strlen(test_json_key_str_part1) +
148 strlen(test_json_key_str_part2) +
149 strlen(test_json_key_str_part3);
150 char* result = static_cast<char*>(gpr_malloc(result_len + 1));
151 char* current = result;
152 strcpy(result, test_json_key_str_part1);
153 current += strlen(test_json_key_str_part1);
154 strcpy(current, test_json_key_str_part2);
155 current += strlen(test_json_key_str_part2);
156 strcpy(current, test_json_key_str_part3);
157 return result;
158 }
159
http_response(int status,const char * body)160 static grpc_httpcli_response http_response(int status, const char* body) {
161 grpc_httpcli_response response;
162 response = {};
163 response.status = status;
164 response.body = gpr_strdup(const_cast<char*>(body));
165 response.body_length = strlen(body);
166 return response;
167 }
168
169 /* -- Tests. -- */
170
test_empty_md_array(void)171 static void test_empty_md_array(void) {
172 grpc_core::ExecCtx exec_ctx;
173 grpc_credentials_mdelem_array md_array;
174 md_array = {};
175 GPR_ASSERT(md_array.md == nullptr);
176 GPR_ASSERT(md_array.size == 0);
177 grpc_credentials_mdelem_array_destroy(&md_array);
178 }
179
test_add_to_empty_md_array(void)180 static void test_add_to_empty_md_array(void) {
181 grpc_core::ExecCtx exec_ctx;
182 grpc_credentials_mdelem_array md_array;
183 md_array = {};
184 const char* key = "hello";
185 const char* value = "there blah blah blah blah blah blah blah";
186 grpc_mdelem md = grpc_mdelem_from_slices(
187 grpc_slice_from_copied_string(key), grpc_slice_from_copied_string(value));
188 grpc_credentials_mdelem_array_add(&md_array, md);
189 GPR_ASSERT(md_array.size == 1);
190 GPR_ASSERT(grpc_mdelem_eq(md, md_array.md[0]));
191 GRPC_MDELEM_UNREF(md);
192 grpc_credentials_mdelem_array_destroy(&md_array);
193 }
194
test_add_abunch_to_md_array(void)195 static void test_add_abunch_to_md_array(void) {
196 grpc_core::ExecCtx exec_ctx;
197 grpc_credentials_mdelem_array md_array;
198 md_array = {};
199 const char* key = "hello";
200 const char* value = "there blah blah blah blah blah blah blah";
201 grpc_mdelem md = grpc_mdelem_from_slices(
202 grpc_slice_from_copied_string(key), grpc_slice_from_copied_string(value));
203 size_t num_entries = 1000;
204 for (size_t i = 0; i < num_entries; ++i) {
205 grpc_credentials_mdelem_array_add(&md_array, md);
206 }
207 for (size_t i = 0; i < num_entries; ++i) {
208 GPR_ASSERT(grpc_mdelem_eq(md_array.md[i], md));
209 }
210 GRPC_MDELEM_UNREF(md);
211 grpc_credentials_mdelem_array_destroy(&md_array);
212 }
213
test_oauth2_token_fetcher_creds_parsing_ok(void)214 static void test_oauth2_token_fetcher_creds_parsing_ok(void) {
215 grpc_core::ExecCtx exec_ctx;
216 grpc_mdelem token_md = GRPC_MDNULL;
217 grpc_millis token_lifetime;
218 grpc_httpcli_response response =
219 http_response(200, valid_oauth2_json_response);
220 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
221 &response, &token_md, &token_lifetime) == GRPC_CREDENTIALS_OK);
222 GPR_ASSERT(token_lifetime == 3599 * GPR_MS_PER_SEC);
223 GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(token_md), "authorization") == 0);
224 GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(token_md),
225 "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") ==
226 0);
227 GRPC_MDELEM_UNREF(token_md);
228 grpc_http_response_destroy(&response);
229 }
230
test_oauth2_token_fetcher_creds_parsing_bad_http_status(void)231 static void test_oauth2_token_fetcher_creds_parsing_bad_http_status(void) {
232 grpc_core::ExecCtx exec_ctx;
233 grpc_mdelem token_md = GRPC_MDNULL;
234 grpc_millis token_lifetime;
235 grpc_httpcli_response response =
236 http_response(401, valid_oauth2_json_response);
237 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
238 &response, &token_md, &token_lifetime) ==
239 GRPC_CREDENTIALS_ERROR);
240 grpc_http_response_destroy(&response);
241 }
242
test_oauth2_token_fetcher_creds_parsing_empty_http_body(void)243 static void test_oauth2_token_fetcher_creds_parsing_empty_http_body(void) {
244 grpc_core::ExecCtx exec_ctx;
245 grpc_mdelem token_md = GRPC_MDNULL;
246 grpc_millis token_lifetime;
247 grpc_httpcli_response response = http_response(200, "");
248 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
249 &response, &token_md, &token_lifetime) ==
250 GRPC_CREDENTIALS_ERROR);
251 grpc_http_response_destroy(&response);
252 }
253
test_oauth2_token_fetcher_creds_parsing_invalid_json(void)254 static void test_oauth2_token_fetcher_creds_parsing_invalid_json(void) {
255 grpc_core::ExecCtx exec_ctx;
256 grpc_mdelem token_md = GRPC_MDNULL;
257 grpc_millis token_lifetime;
258 grpc_httpcli_response response =
259 http_response(200,
260 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
261 " \"expires_in\":3599, "
262 " \"token_type\":\"Bearer\"");
263 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
264 &response, &token_md, &token_lifetime) ==
265 GRPC_CREDENTIALS_ERROR);
266 grpc_http_response_destroy(&response);
267 }
268
test_oauth2_token_fetcher_creds_parsing_missing_token(void)269 static void test_oauth2_token_fetcher_creds_parsing_missing_token(void) {
270 grpc_core::ExecCtx exec_ctx;
271 grpc_mdelem token_md = GRPC_MDNULL;
272 grpc_millis token_lifetime;
273 grpc_httpcli_response response = http_response(200,
274 "{"
275 " \"expires_in\":3599, "
276 " \"token_type\":\"Bearer\"}");
277 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
278 &response, &token_md, &token_lifetime) ==
279 GRPC_CREDENTIALS_ERROR);
280 grpc_http_response_destroy(&response);
281 }
282
test_oauth2_token_fetcher_creds_parsing_missing_token_type(void)283 static void test_oauth2_token_fetcher_creds_parsing_missing_token_type(void) {
284 grpc_core::ExecCtx exec_ctx;
285 grpc_mdelem token_md = GRPC_MDNULL;
286 grpc_millis token_lifetime;
287 grpc_httpcli_response response =
288 http_response(200,
289 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
290 " \"expires_in\":3599, "
291 "}");
292 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
293 &response, &token_md, &token_lifetime) ==
294 GRPC_CREDENTIALS_ERROR);
295 grpc_http_response_destroy(&response);
296 }
297
test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(void)298 static void test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(
299 void) {
300 grpc_core::ExecCtx exec_ctx;
301 grpc_mdelem token_md = GRPC_MDNULL;
302 grpc_millis token_lifetime;
303 grpc_httpcli_response response =
304 http_response(200,
305 "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
306 " \"token_type\":\"Bearer\"}");
307 GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
308 &response, &token_md, &token_lifetime) ==
309 GRPC_CREDENTIALS_ERROR);
310 grpc_http_response_destroy(&response);
311 }
312
313 typedef struct {
314 const char* key;
315 const char* value;
316 } expected_md;
317
318 typedef struct {
319 grpc_error* expected_error;
320 const expected_md* expected;
321 size_t expected_size;
322 grpc_credentials_mdelem_array md_array;
323 grpc_closure on_request_metadata;
324 grpc_call_credentials* creds;
325 grpc_polling_entity pollent;
326 } request_metadata_state;
327
check_metadata(const expected_md * expected,grpc_credentials_mdelem_array * md_array)328 static void check_metadata(const expected_md* expected,
329 grpc_credentials_mdelem_array* md_array) {
330 for (size_t i = 0; i < md_array->size; ++i) {
331 size_t j;
332 for (j = 0; j < md_array->size; ++j) {
333 if (0 ==
334 grpc_slice_str_cmp(GRPC_MDKEY(md_array->md[j]), expected[i].key)) {
335 GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md_array->md[j]),
336 expected[i].value) == 0);
337 break;
338 }
339 }
340 if (j == md_array->size) {
341 gpr_log(GPR_ERROR, "key %s not found", expected[i].key);
342 GPR_ASSERT(0);
343 }
344 }
345 }
346
check_request_metadata(void * arg,grpc_error * error)347 static void check_request_metadata(void* arg, grpc_error* error) {
348 request_metadata_state* state = static_cast<request_metadata_state*>(arg);
349 gpr_log(GPR_INFO, "expected_error: %s",
350 grpc_error_string(state->expected_error));
351 gpr_log(GPR_INFO, "actual_error: %s", grpc_error_string(error));
352 if (state->expected_error == GRPC_ERROR_NONE) {
353 GPR_ASSERT(error == GRPC_ERROR_NONE);
354 } else {
355 grpc_slice expected_error;
356 GPR_ASSERT(grpc_error_get_str(state->expected_error,
357 GRPC_ERROR_STR_DESCRIPTION, &expected_error));
358 grpc_slice actual_error;
359 GPR_ASSERT(
360 grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error));
361 GPR_ASSERT(grpc_slice_cmp(expected_error, actual_error) == 0);
362 GRPC_ERROR_UNREF(state->expected_error);
363 }
364 gpr_log(GPR_INFO, "expected_size=%" PRIdPTR " actual_size=%" PRIdPTR,
365 state->expected_size, state->md_array.size);
366 GPR_ASSERT(state->md_array.size == state->expected_size);
367 check_metadata(state->expected, &state->md_array);
368 grpc_credentials_mdelem_array_destroy(&state->md_array);
369 grpc_pollset_set_destroy(grpc_polling_entity_pollset_set(&state->pollent));
370 gpr_free(state);
371 }
372
make_request_metadata_state(grpc_error * expected_error,const expected_md * expected,size_t expected_size)373 static request_metadata_state* make_request_metadata_state(
374 grpc_error* expected_error, const expected_md* expected,
375 size_t expected_size) {
376 request_metadata_state* state =
377 static_cast<request_metadata_state*>(gpr_zalloc(sizeof(*state)));
378 state->expected_error = expected_error;
379 state->expected = expected;
380 state->expected_size = expected_size;
381 state->pollent =
382 grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create());
383 GRPC_CLOSURE_INIT(&state->on_request_metadata, check_request_metadata, state,
384 grpc_schedule_on_exec_ctx);
385 return state;
386 }
387
run_request_metadata_test(grpc_call_credentials * creds,grpc_auth_metadata_context auth_md_ctx,request_metadata_state * state)388 static void run_request_metadata_test(grpc_call_credentials* creds,
389 grpc_auth_metadata_context auth_md_ctx,
390 request_metadata_state* state) {
391 grpc_error* error = GRPC_ERROR_NONE;
392 if (creds->get_request_metadata(&state->pollent, auth_md_ctx,
393 &state->md_array, &state->on_request_metadata,
394 &error)) {
395 // Synchronous result. Invoke the callback directly.
396 check_request_metadata(state, error);
397 GRPC_ERROR_UNREF(error);
398 }
399 }
400
test_google_iam_creds(void)401 static void test_google_iam_creds(void) {
402 grpc_core::ExecCtx exec_ctx;
403 expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
404 test_google_iam_authorization_token},
405 {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
406 test_google_iam_authority_selector}};
407 request_metadata_state* state =
408 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
409 grpc_call_credentials* creds = grpc_google_iam_credentials_create(
410 test_google_iam_authorization_token, test_google_iam_authority_selector,
411 nullptr);
412 /* Check security level. */
413 GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
414 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
415 nullptr, nullptr};
416 run_request_metadata_test(creds, auth_md_ctx, state);
417 creds->Unref();
418 }
419
test_access_token_creds(void)420 static void test_access_token_creds(void) {
421 grpc_core::ExecCtx exec_ctx;
422 expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}};
423 request_metadata_state* state =
424 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
425 grpc_call_credentials* creds =
426 grpc_access_token_credentials_create("blah", nullptr);
427 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
428 nullptr, nullptr};
429 GPR_ASSERT(strcmp(creds->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
430 /* Check security level. */
431 GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
432 run_request_metadata_test(creds, auth_md_ctx, state);
433 creds->Unref();
434 }
435
436 namespace {
437 class check_channel_oauth2 final : public grpc_channel_credentials {
438 public:
check_channel_oauth2()439 check_channel_oauth2() : grpc_channel_credentials("mock") {}
440 ~check_channel_oauth2() override = default;
441
442 grpc_core::RefCountedPtr<grpc_channel_security_connector>
create_security_connector(grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,const char *,const grpc_channel_args *,grpc_channel_args **)443 create_security_connector(
444 grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
445 const char* /*target*/, const grpc_channel_args* /*args*/,
446 grpc_channel_args** /*new_args*/) override {
447 GPR_ASSERT(strcmp(type(), "mock") == 0);
448 GPR_ASSERT(call_creds != nullptr);
449 GPR_ASSERT(strcmp(call_creds->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) ==
450 0);
451 return nullptr;
452 }
453 };
454 } // namespace
455
test_channel_oauth2_composite_creds(void)456 static void test_channel_oauth2_composite_creds(void) {
457 grpc_core::ExecCtx exec_ctx;
458 grpc_channel_args* new_args;
459 grpc_channel_credentials* channel_creds = new check_channel_oauth2();
460 grpc_call_credentials* oauth2_creds =
461 grpc_access_token_credentials_create("blah", nullptr);
462 grpc_channel_credentials* channel_oauth2_creds =
463 grpc_composite_channel_credentials_create(channel_creds, oauth2_creds,
464 nullptr);
465 grpc_channel_credentials_release(channel_creds);
466 grpc_call_credentials_release(oauth2_creds);
467 channel_oauth2_creds->create_security_connector(nullptr, nullptr, nullptr,
468 &new_args);
469 grpc_channel_credentials_release(channel_oauth2_creds);
470 }
471
test_oauth2_google_iam_composite_creds(void)472 static void test_oauth2_google_iam_composite_creds(void) {
473 grpc_core::ExecCtx exec_ctx;
474 expected_md emd[] = {
475 {GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token},
476 {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
477 test_google_iam_authorization_token},
478 {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
479 test_google_iam_authority_selector}};
480 request_metadata_state* state =
481 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
482 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
483 nullptr, nullptr};
484 grpc_call_credentials* oauth2_creds = grpc_md_only_test_credentials_create(
485 "authorization", test_oauth2_bearer_token, 0);
486
487 /* Check security level of fake credentials. */
488 GPR_ASSERT(oauth2_creds->min_security_level() == GRPC_SECURITY_NONE);
489
490 grpc_call_credentials* google_iam_creds = grpc_google_iam_credentials_create(
491 test_google_iam_authorization_token, test_google_iam_authority_selector,
492 nullptr);
493 grpc_call_credentials* composite_creds =
494 grpc_composite_call_credentials_create(oauth2_creds, google_iam_creds,
495 nullptr);
496 /* Check security level of composite credentials. */
497 GPR_ASSERT(composite_creds->min_security_level() ==
498 GRPC_PRIVACY_AND_INTEGRITY);
499
500 oauth2_creds->Unref();
501 google_iam_creds->Unref();
502 GPR_ASSERT(strcmp(composite_creds->type(),
503 GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
504 const grpc_composite_call_credentials::CallCredentialsList& creds_list =
505 static_cast<const grpc_composite_call_credentials*>(composite_creds)
506 ->inner();
507 GPR_ASSERT(creds_list.size() == 2);
508 GPR_ASSERT(strcmp(creds_list[0]->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) ==
509 0);
510 GPR_ASSERT(strcmp(creds_list[1]->type(), GRPC_CALL_CREDENTIALS_TYPE_IAM) ==
511 0);
512 run_request_metadata_test(composite_creds, auth_md_ctx, state);
513 composite_creds->Unref();
514 }
515
516 namespace {
517 class check_channel_oauth2_google_iam final : public grpc_channel_credentials {
518 public:
check_channel_oauth2_google_iam()519 check_channel_oauth2_google_iam() : grpc_channel_credentials("mock") {}
520 ~check_channel_oauth2_google_iam() override = default;
521
522 grpc_core::RefCountedPtr<grpc_channel_security_connector>
create_security_connector(grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,const char *,const grpc_channel_args *,grpc_channel_args **)523 create_security_connector(
524 grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
525 const char* /*target*/, const grpc_channel_args* /*args*/,
526 grpc_channel_args** /*new_args*/) override {
527 GPR_ASSERT(strcmp(type(), "mock") == 0);
528 GPR_ASSERT(call_creds != nullptr);
529 GPR_ASSERT(
530 strcmp(call_creds->type(), GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
531 const grpc_composite_call_credentials::CallCredentialsList& creds_list =
532 static_cast<const grpc_composite_call_credentials*>(call_creds.get())
533 ->inner();
534 GPR_ASSERT(
535 strcmp(creds_list[0]->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
536 GPR_ASSERT(strcmp(creds_list[1]->type(), GRPC_CALL_CREDENTIALS_TYPE_IAM) ==
537 0);
538 return nullptr;
539 }
540 };
541 } // namespace
542
test_channel_oauth2_google_iam_composite_creds(void)543 static void test_channel_oauth2_google_iam_composite_creds(void) {
544 grpc_core::ExecCtx exec_ctx;
545 grpc_channel_args* new_args;
546 grpc_channel_credentials* channel_creds =
547 new check_channel_oauth2_google_iam();
548 grpc_call_credentials* oauth2_creds =
549 grpc_access_token_credentials_create("blah", nullptr);
550 grpc_channel_credentials* channel_oauth2_creds =
551 grpc_composite_channel_credentials_create(channel_creds, oauth2_creds,
552 nullptr);
553 grpc_call_credentials* google_iam_creds = grpc_google_iam_credentials_create(
554 test_google_iam_authorization_token, test_google_iam_authority_selector,
555 nullptr);
556
557 grpc_channel_credentials* channel_oauth2_iam_creds =
558 grpc_composite_channel_credentials_create(channel_oauth2_creds,
559 google_iam_creds, nullptr);
560 grpc_channel_credentials_release(channel_creds);
561 grpc_call_credentials_release(oauth2_creds);
562 grpc_channel_credentials_release(channel_oauth2_creds);
563 grpc_call_credentials_release(google_iam_creds);
564
565 channel_oauth2_iam_creds->create_security_connector(nullptr, nullptr, nullptr,
566 &new_args);
567
568 grpc_channel_credentials_release(channel_oauth2_iam_creds);
569 }
570
validate_compute_engine_http_request(const grpc_httpcli_request * request)571 static void validate_compute_engine_http_request(
572 const grpc_httpcli_request* request) {
573 GPR_ASSERT(request->handshaker != &grpc_httpcli_ssl);
574 GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0);
575 GPR_ASSERT(
576 strcmp(request->http.path,
577 "/computeMetadata/v1/instance/service-accounts/default/token") ==
578 0);
579 GPR_ASSERT(request->http.hdr_count == 1);
580 GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Metadata-Flavor") == 0);
581 GPR_ASSERT(strcmp(request->http.hdrs[0].value, "Google") == 0);
582 }
583
compute_engine_httpcli_get_success_override(const grpc_httpcli_request * request,grpc_millis,grpc_closure * on_done,grpc_httpcli_response * response)584 static int compute_engine_httpcli_get_success_override(
585 const grpc_httpcli_request* request, grpc_millis /*deadline*/,
586 grpc_closure* on_done, grpc_httpcli_response* response) {
587 validate_compute_engine_http_request(request);
588 *response = http_response(200, valid_oauth2_json_response);
589 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
590 return 1;
591 }
592
compute_engine_httpcli_get_failure_override(const grpc_httpcli_request * request,grpc_millis,grpc_closure * on_done,grpc_httpcli_response * response)593 static int compute_engine_httpcli_get_failure_override(
594 const grpc_httpcli_request* request, grpc_millis /*deadline*/,
595 grpc_closure* on_done, grpc_httpcli_response* response) {
596 validate_compute_engine_http_request(request);
597 *response = http_response(403, "Not Authorized.");
598 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
599 return 1;
600 }
601
httpcli_post_should_not_be_called(const grpc_httpcli_request *,const char *,size_t,grpc_millis,grpc_closure *,grpc_httpcli_response *)602 static int httpcli_post_should_not_be_called(
603 const grpc_httpcli_request* /*request*/, const char* /*body_bytes*/,
604 size_t /*body_size*/, grpc_millis /*deadline*/, grpc_closure* /*on_done*/,
605 grpc_httpcli_response* /*response*/) {
606 GPR_ASSERT("HTTP POST should not be called" == nullptr);
607 return 1;
608 }
609
httpcli_get_should_not_be_called(const grpc_httpcli_request *,grpc_millis,grpc_closure *,grpc_httpcli_response *)610 static int httpcli_get_should_not_be_called(
611 const grpc_httpcli_request* /*request*/, grpc_millis /*deadline*/,
612 grpc_closure* /*on_done*/, grpc_httpcli_response* /*response*/) {
613 GPR_ASSERT("HTTP GET should not be called" == nullptr);
614 return 1;
615 }
616
test_compute_engine_creds_success()617 static void test_compute_engine_creds_success() {
618 grpc_core::ExecCtx exec_ctx;
619 expected_md emd[] = {
620 {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
621 const char expected_creds_debug_string[] =
622 "GoogleComputeEngineTokenFetcherCredentials{"
623 "OAuth2TokenFetcherCredentials}";
624 grpc_call_credentials* creds =
625 grpc_google_compute_engine_credentials_create(nullptr);
626 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
627 nullptr, nullptr};
628 /* Check security level. */
629 GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
630
631 /* First request: http get should be called. */
632 request_metadata_state* state =
633 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
634 grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
635 httpcli_post_should_not_be_called);
636 run_request_metadata_test(creds, auth_md_ctx, state);
637 grpc_core::ExecCtx::Get()->Flush();
638
639 /* Second request: the cached token should be served directly. */
640 state =
641 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
642 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
643 httpcli_post_should_not_be_called);
644 run_request_metadata_test(creds, auth_md_ctx, state);
645 grpc_core::ExecCtx::Get()->Flush();
646
647 GPR_ASSERT(
648 strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
649 creds->Unref();
650 grpc_httpcli_set_override(nullptr, nullptr);
651 }
652
test_compute_engine_creds_failure(void)653 static void test_compute_engine_creds_failure(void) {
654 grpc_core::ExecCtx exec_ctx;
655 const char expected_creds_debug_string[] =
656 "GoogleComputeEngineTokenFetcherCredentials{"
657 "OAuth2TokenFetcherCredentials}";
658 request_metadata_state* state = make_request_metadata_state(
659 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
660 "Error occurred when fetching oauth2 token."),
661 nullptr, 0);
662 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
663 nullptr, nullptr};
664 grpc_call_credentials* creds =
665 grpc_google_compute_engine_credentials_create(nullptr);
666 grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override,
667 httpcli_post_should_not_be_called);
668 run_request_metadata_test(creds, auth_md_ctx, state);
669 GPR_ASSERT(
670 strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
671 creds->Unref();
672 grpc_httpcli_set_override(nullptr, nullptr);
673 }
674
validate_refresh_token_http_request(const grpc_httpcli_request * request,const char * body,size_t body_size)675 static void validate_refresh_token_http_request(
676 const grpc_httpcli_request* request, const char* body, size_t body_size) {
677 /* The content of the assertion is tested extensively in json_token_test. */
678 GPR_ASSERT(body != nullptr);
679 GPR_ASSERT(body_size != 0);
680 std::string expected_body = absl::StrFormat(
681 GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
682 "32555999999.apps.googleusercontent.com", "EmssLNjJy1332hD4KFsecret",
683 "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42");
684 GPR_ASSERT(expected_body.size() == body_size);
685 GPR_ASSERT(memcmp(expected_body.data(), body, body_size) == 0);
686 GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
687 GPR_ASSERT(strcmp(request->host, GRPC_GOOGLE_OAUTH2_SERVICE_HOST) == 0);
688 GPR_ASSERT(
689 strcmp(request->http.path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0);
690 GPR_ASSERT(request->http.hdr_count == 1);
691 GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Content-Type") == 0);
692 GPR_ASSERT(strcmp(request->http.hdrs[0].value,
693 "application/x-www-form-urlencoded") == 0);
694 }
695
refresh_token_httpcli_post_success(const grpc_httpcli_request * request,const char * body,size_t body_size,grpc_millis,grpc_closure * on_done,grpc_httpcli_response * response)696 static int refresh_token_httpcli_post_success(
697 const grpc_httpcli_request* request, const char* body, size_t body_size,
698 grpc_millis /*deadline*/, grpc_closure* on_done,
699 grpc_httpcli_response* response) {
700 validate_refresh_token_http_request(request, body, body_size);
701 *response = http_response(200, valid_oauth2_json_response);
702 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
703 return 1;
704 }
705
token_httpcli_post_failure(const grpc_httpcli_request *,const char *,size_t,grpc_millis,grpc_closure * on_done,grpc_httpcli_response * response)706 static int token_httpcli_post_failure(const grpc_httpcli_request* /*request*/,
707 const char* /*body*/,
708 size_t /*body_size*/,
709 grpc_millis /*deadline*/,
710 grpc_closure* on_done,
711 grpc_httpcli_response* response) {
712 *response = http_response(403, "Not Authorized.");
713 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
714 return 1;
715 }
716
test_refresh_token_creds_success(void)717 static void test_refresh_token_creds_success(void) {
718 grpc_core::ExecCtx exec_ctx;
719 expected_md emd[] = {
720 {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
721 const char expected_creds_debug_string[] =
722 "GoogleRefreshToken{ClientID:32555999999.apps.googleusercontent.com,"
723 "OAuth2TokenFetcherCredentials}";
724 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
725 nullptr, nullptr};
726 grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
727 test_refresh_token_str, nullptr);
728
729 /* Check security level. */
730 GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
731
732 /* First request: http put should be called. */
733 request_metadata_state* state =
734 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
735 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
736 refresh_token_httpcli_post_success);
737 run_request_metadata_test(creds, auth_md_ctx, state);
738 grpc_core::ExecCtx::Get()->Flush();
739
740 /* Second request: the cached token should be served directly. */
741 state =
742 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
743 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
744 httpcli_post_should_not_be_called);
745 run_request_metadata_test(creds, auth_md_ctx, state);
746 grpc_core::ExecCtx::Get()->Flush();
747 GPR_ASSERT(
748 strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
749
750 creds->Unref();
751 grpc_httpcli_set_override(nullptr, nullptr);
752 }
753
test_refresh_token_creds_failure(void)754 static void test_refresh_token_creds_failure(void) {
755 grpc_core::ExecCtx exec_ctx;
756 const char expected_creds_debug_string[] =
757 "GoogleRefreshToken{ClientID:32555999999.apps.googleusercontent.com,"
758 "OAuth2TokenFetcherCredentials}";
759 request_metadata_state* state = make_request_metadata_state(
760 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
761 "Error occurred when fetching oauth2 token."),
762 nullptr, 0);
763 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
764 nullptr, nullptr};
765 grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
766 test_refresh_token_str, nullptr);
767 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
768 token_httpcli_post_failure);
769 run_request_metadata_test(creds, auth_md_ctx, state);
770 GPR_ASSERT(
771 strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
772
773 creds->Unref();
774 grpc_httpcli_set_override(nullptr, nullptr);
775 }
776
test_valid_sts_creds_options(void)777 static void test_valid_sts_creds_options(void) {
778 grpc_sts_credentials_options valid_options = {
779 test_sts_endpoint_url, // sts_endpoint_url
780 nullptr, // resource
781 nullptr, // audience
782 nullptr, // scope
783 nullptr, // requested_token_type
784 test_signed_jwt_path_prefix, // subject_token_path
785 test_signed_jwt_token_type, // subject_token_type
786 nullptr, // actor_token_path
787 nullptr // actor_token_type
788 };
789 grpc_uri* sts_url;
790 grpc_error* error =
791 grpc_core::ValidateStsCredentialsOptions(&valid_options, &sts_url);
792 GPR_ASSERT(error == GRPC_ERROR_NONE);
793 GPR_ASSERT(sts_url != nullptr);
794 absl::string_view host;
795 absl::string_view port;
796 GPR_ASSERT(grpc_core::SplitHostPort(sts_url->authority, &host, &port));
797 GPR_ASSERT(host == "foo.com");
798 GPR_ASSERT(port == "5555");
799 grpc_uri_destroy(sts_url);
800 }
801
test_invalid_sts_creds_options(void)802 static void test_invalid_sts_creds_options(void) {
803 grpc_sts_credentials_options invalid_options = {
804 test_sts_endpoint_url, // sts_endpoint_url
805 nullptr, // resource
806 nullptr, // audience
807 nullptr, // scope
808 nullptr, // requested_token_type
809 nullptr, // subject_token_path (Required)
810 test_signed_jwt_token_type, // subject_token_type
811 nullptr, // actor_token_path
812 nullptr // actor_token_type
813 };
814 grpc_uri* url_should_be_null;
815 grpc_error* error = grpc_core::ValidateStsCredentialsOptions(
816 &invalid_options, &url_should_be_null);
817 GPR_ASSERT(error != GRPC_ERROR_NONE);
818 GRPC_ERROR_UNREF(error);
819 GPR_ASSERT(url_should_be_null == nullptr);
820
821 invalid_options = {
822 test_sts_endpoint_url, // sts_endpoint_url
823 nullptr, // resource
824 nullptr, // audience
825 nullptr, // scope
826 nullptr, // requested_token_type
827 test_signed_jwt_path_prefix, // subject_token_path
828 nullptr, // subject_token_type (Required)
829 nullptr, // actor_token_path
830 nullptr // actor_token_type
831 };
832 error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
833 &url_should_be_null);
834 GPR_ASSERT(error != GRPC_ERROR_NONE);
835 GRPC_ERROR_UNREF(error);
836 GPR_ASSERT(url_should_be_null == nullptr);
837
838 invalid_options = {
839 nullptr, // sts_endpoint_url (Required)
840 nullptr, // resource
841 nullptr, // audience
842 nullptr, // scope
843 nullptr, // requested_token_type
844 test_signed_jwt_path_prefix, // subject_token_path
845 test_signed_jwt_token_type, // subject_token_type (Required)
846 nullptr, // actor_token_path
847 nullptr // actor_token_type
848 };
849 error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
850 &url_should_be_null);
851 GPR_ASSERT(error != GRPC_ERROR_NONE);
852 GRPC_ERROR_UNREF(error);
853 GPR_ASSERT(url_should_be_null == nullptr);
854
855 invalid_options = {
856 "not_a_valid_uri", // sts_endpoint_url
857 nullptr, // resource
858 nullptr, // audience
859 nullptr, // scope
860 nullptr, // requested_token_type
861 test_signed_jwt_path_prefix, // subject_token_path
862 test_signed_jwt_token_type, // subject_token_type (Required)
863 nullptr, // actor_token_path
864 nullptr // actor_token_type
865 };
866 error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
867 &url_should_be_null);
868 GPR_ASSERT(error != GRPC_ERROR_NONE);
869 GRPC_ERROR_UNREF(error);
870 GPR_ASSERT(url_should_be_null == nullptr);
871
872 invalid_options = {
873 "ftp://ftp.is.not.a.valid.scheme/bar", // sts_endpoint_url
874 nullptr, // resource
875 nullptr, // audience
876 nullptr, // scope
877 nullptr, // requested_token_type
878 test_signed_jwt_path_prefix, // subject_token_path
879 test_signed_jwt_token_type, // subject_token_type (Required)
880 nullptr, // actor_token_path
881 nullptr // actor_token_type
882 };
883 error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
884 &url_should_be_null);
885 GPR_ASSERT(error != GRPC_ERROR_NONE);
886 GRPC_ERROR_UNREF(error);
887 GPR_ASSERT(url_should_be_null == nullptr);
888 }
889
validate_sts_token_http_request(const grpc_httpcli_request * request,const char * body,size_t body_size,bool expect_actor_token)890 static void validate_sts_token_http_request(const grpc_httpcli_request* request,
891 const char* body, size_t body_size,
892 bool expect_actor_token) {
893 // Check that the body is constructed properly.
894 GPR_ASSERT(body != nullptr);
895 GPR_ASSERT(body_size != 0);
896 GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
897 std::string get_url_equivalent =
898 absl::StrFormat("%s?%s", test_sts_endpoint_url, body);
899 grpc_uri* url = grpc_uri_parse(get_url_equivalent.c_str(), false);
900 GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "resource"), "resource") == 0);
901 GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "audience"), "audience") == 0);
902 GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "scope"), "scope") == 0);
903 GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "requested_token_type"),
904 "requested_token_type") == 0);
905 GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "subject_token"),
906 test_signed_jwt) == 0);
907 GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "subject_token_type"),
908 test_signed_jwt_token_type) == 0);
909 if (expect_actor_token) {
910 GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "actor_token"),
911 test_signed_jwt2) == 0);
912 GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "actor_token_type"),
913 test_signed_jwt_token_type2) == 0);
914 } else {
915 GPR_ASSERT(grpc_uri_get_query_arg(url, "actor_token") == nullptr);
916 GPR_ASSERT(grpc_uri_get_query_arg(url, "actor_token_type") == nullptr);
917 }
918 grpc_uri_destroy(url);
919
920 // Check the rest of the request.
921 GPR_ASSERT(strcmp(request->host, "foo.com:5555") == 0);
922 GPR_ASSERT(strcmp(request->http.path, "/v1/token-exchange") == 0);
923 GPR_ASSERT(request->http.hdr_count == 1);
924 GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Content-Type") == 0);
925 GPR_ASSERT(strcmp(request->http.hdrs[0].value,
926 "application/x-www-form-urlencoded") == 0);
927 }
928
sts_token_httpcli_post_success(const grpc_httpcli_request * request,const char * body,size_t body_size,grpc_millis,grpc_closure * on_done,grpc_httpcli_response * response)929 static int sts_token_httpcli_post_success(const grpc_httpcli_request* request,
930 const char* body, size_t body_size,
931 grpc_millis /*deadline*/,
932 grpc_closure* on_done,
933 grpc_httpcli_response* response) {
934 validate_sts_token_http_request(request, body, body_size, true);
935 *response = http_response(200, valid_sts_json_response);
936 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
937 return 1;
938 }
939
sts_token_httpcli_post_success_no_actor_token(const grpc_httpcli_request * request,const char * body,size_t body_size,grpc_millis,grpc_closure * on_done,grpc_httpcli_response * response)940 static int sts_token_httpcli_post_success_no_actor_token(
941 const grpc_httpcli_request* request, const char* body, size_t body_size,
942 grpc_millis /*deadline*/, grpc_closure* on_done,
943 grpc_httpcli_response* response) {
944 validate_sts_token_http_request(request, body, body_size, false);
945 *response = http_response(200, valid_sts_json_response);
946 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
947 return 1;
948 }
949
write_tmp_jwt_file(const char * jwt_contents)950 static char* write_tmp_jwt_file(const char* jwt_contents) {
951 char* path;
952 FILE* tmp = gpr_tmpfile(test_signed_jwt_path_prefix, &path);
953 GPR_ASSERT(path != nullptr);
954 GPR_ASSERT(tmp != nullptr);
955 size_t jwt_length = strlen(jwt_contents);
956 GPR_ASSERT(fwrite(jwt_contents, 1, jwt_length, tmp) == jwt_length);
957 fclose(tmp);
958 return path;
959 }
960
test_sts_creds_success(void)961 static void test_sts_creds_success(void) {
962 grpc_core::ExecCtx exec_ctx;
963 expected_md emd[] = {
964 {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
965 const char expected_creds_debug_string[] =
966 "StsTokenFetcherCredentials{Path:/v1/"
967 "token-exchange,Authority:foo.com:5555,OAuth2TokenFetcherCredentials}";
968 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
969 nullptr, nullptr};
970 char* subject_token_path = write_tmp_jwt_file(test_signed_jwt);
971 char* actor_token_path = write_tmp_jwt_file(test_signed_jwt2);
972 grpc_sts_credentials_options valid_options = {
973 test_sts_endpoint_url, // sts_endpoint_url
974 "resource", // resource
975 "audience", // audience
976 "scope", // scope
977 "requested_token_type", // requested_token_type
978 subject_token_path, // subject_token_path
979 test_signed_jwt_token_type, // subject_token_type
980 actor_token_path, // actor_token_path
981 test_signed_jwt_token_type2 // actor_token_type
982 };
983 grpc_call_credentials* creds =
984 grpc_sts_credentials_create(&valid_options, nullptr);
985
986 /* Check security level. */
987 GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
988
989 /* First request: http put should be called. */
990 request_metadata_state* state =
991 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
992 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
993 sts_token_httpcli_post_success);
994 run_request_metadata_test(creds, auth_md_ctx, state);
995 grpc_core::ExecCtx::Get()->Flush();
996
997 /* Second request: the cached token should be served directly. */
998 state =
999 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
1000 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
1001 httpcli_post_should_not_be_called);
1002 run_request_metadata_test(creds, auth_md_ctx, state);
1003 grpc_core::ExecCtx::Get()->Flush();
1004 GPR_ASSERT(
1005 strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
1006
1007 creds->Unref();
1008 grpc_httpcli_set_override(nullptr, nullptr);
1009 gpr_free(subject_token_path);
1010 gpr_free(actor_token_path);
1011 }
1012
test_sts_creds_token_file_not_found(void)1013 static void test_sts_creds_token_file_not_found(void) {
1014 grpc_core::ExecCtx exec_ctx;
1015 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1016 nullptr, nullptr};
1017 grpc_sts_credentials_options valid_options = {
1018 test_sts_endpoint_url, // sts_endpoint_url
1019 "resource", // resource
1020 "audience", // audience
1021 "scope", // scope
1022 "requested_token_type", // requested_token_type
1023 "/some/completely/random/path", // subject_token_path
1024 test_signed_jwt_token_type, // subject_token_type
1025 "", // actor_token_path
1026 "" // actor_token_type
1027 };
1028 grpc_call_credentials* creds =
1029 grpc_sts_credentials_create(&valid_options, nullptr);
1030
1031 /* Check security level. */
1032 GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
1033
1034 request_metadata_state* state = make_request_metadata_state(
1035 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1036 "Error occurred when fetching oauth2 token."),
1037 nullptr, 0);
1038 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
1039 httpcli_post_should_not_be_called);
1040 run_request_metadata_test(creds, auth_md_ctx, state);
1041 grpc_core::ExecCtx::Get()->Flush();
1042
1043 /* Cleanup. */
1044 creds->Unref();
1045 grpc_httpcli_set_override(nullptr, nullptr);
1046 }
1047
test_sts_creds_no_actor_token_success(void)1048 static void test_sts_creds_no_actor_token_success(void) {
1049 grpc_core::ExecCtx exec_ctx;
1050 expected_md emd[] = {
1051 {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
1052 const char expected_creds_debug_string[] =
1053 "StsTokenFetcherCredentials{Path:/v1/"
1054 "token-exchange,Authority:foo.com:5555,OAuth2TokenFetcherCredentials}";
1055 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1056 nullptr, nullptr};
1057 char* subject_token_path = write_tmp_jwt_file(test_signed_jwt);
1058 grpc_sts_credentials_options valid_options = {
1059 test_sts_endpoint_url, // sts_endpoint_url
1060 "resource", // resource
1061 "audience", // audience
1062 "scope", // scope
1063 "requested_token_type", // requested_token_type
1064 subject_token_path, // subject_token_path
1065 test_signed_jwt_token_type, // subject_token_type
1066 "", // actor_token_path
1067 "" // actor_token_type
1068 };
1069 grpc_call_credentials* creds =
1070 grpc_sts_credentials_create(&valid_options, nullptr);
1071
1072 /* Check security level. */
1073 GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
1074
1075 /* First request: http put should be called. */
1076 request_metadata_state* state =
1077 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
1078 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
1079 sts_token_httpcli_post_success_no_actor_token);
1080 run_request_metadata_test(creds, auth_md_ctx, state);
1081 grpc_core::ExecCtx::Get()->Flush();
1082
1083 /* Second request: the cached token should be served directly. */
1084 state =
1085 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
1086 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
1087 httpcli_post_should_not_be_called);
1088 run_request_metadata_test(creds, auth_md_ctx, state);
1089 grpc_core::ExecCtx::Get()->Flush();
1090 GPR_ASSERT(
1091 strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
1092
1093 creds->Unref();
1094 grpc_httpcli_set_override(nullptr, nullptr);
1095 gpr_free(subject_token_path);
1096 }
1097
test_sts_creds_load_token_failure(void)1098 static void test_sts_creds_load_token_failure(void) {
1099 const char expected_creds_debug_string[] =
1100 "StsTokenFetcherCredentials{Path:/v1/"
1101 "token-exchange,Authority:foo.com:5555,OAuth2TokenFetcherCredentials}";
1102 grpc_core::ExecCtx exec_ctx;
1103 request_metadata_state* state = make_request_metadata_state(
1104 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1105 "Error occurred when fetching oauth2 token."),
1106 nullptr, 0);
1107 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1108 nullptr, nullptr};
1109 char* test_signed_jwt_path = write_tmp_jwt_file(test_signed_jwt);
1110 grpc_sts_credentials_options options = {
1111 test_sts_endpoint_url, // sts_endpoint_url
1112 "resource", // resource
1113 "audience", // audience
1114 "scope", // scope
1115 "requested_token_type", // requested_token_type
1116 "invalid_path", // subject_token_path
1117 test_signed_jwt_token_type, // subject_token_type
1118 nullptr, // actor_token_path
1119 nullptr // actor_token_type
1120 };
1121 grpc_call_credentials* creds = grpc_sts_credentials_create(&options, nullptr);
1122 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
1123 httpcli_post_should_not_be_called);
1124 run_request_metadata_test(creds, auth_md_ctx, state);
1125 GPR_ASSERT(
1126 strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
1127
1128 creds->Unref();
1129 grpc_httpcli_set_override(nullptr, nullptr);
1130 gpr_free(test_signed_jwt_path);
1131 }
1132
test_sts_creds_http_failure(void)1133 static void test_sts_creds_http_failure(void) {
1134 const char expected_creds_debug_string[] =
1135 "StsTokenFetcherCredentials{Path:/v1/"
1136 "token-exchange,Authority:foo.com:5555,OAuth2TokenFetcherCredentials}";
1137 grpc_core::ExecCtx exec_ctx;
1138 request_metadata_state* state = make_request_metadata_state(
1139 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1140 "Error occurred when fetching oauth2 token."),
1141 nullptr, 0);
1142 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1143 nullptr, nullptr};
1144 char* test_signed_jwt_path = write_tmp_jwt_file(test_signed_jwt);
1145 grpc_sts_credentials_options valid_options = {
1146 test_sts_endpoint_url, // sts_endpoint_url
1147 "resource", // resource
1148 "audience", // audience
1149 "scope", // scope
1150 "requested_token_type", // requested_token_type
1151 test_signed_jwt_path, // subject_token_path
1152 test_signed_jwt_token_type, // subject_token_type
1153 nullptr, // actor_token_path
1154 nullptr // actor_token_type
1155 };
1156 grpc_call_credentials* creds =
1157 grpc_sts_credentials_create(&valid_options, nullptr);
1158 grpc_httpcli_set_override(httpcli_get_should_not_be_called,
1159 token_httpcli_post_failure);
1160 run_request_metadata_test(creds, auth_md_ctx, state);
1161 GPR_ASSERT(
1162 strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
1163 creds->Unref();
1164 grpc_httpcli_set_override(nullptr, nullptr);
1165 gpr_free(test_signed_jwt_path);
1166 }
1167
validate_jwt_encode_and_sign_params(const grpc_auth_json_key * json_key,const char * scope,gpr_timespec token_lifetime)1168 static void validate_jwt_encode_and_sign_params(
1169 const grpc_auth_json_key* json_key, const char* scope,
1170 gpr_timespec token_lifetime) {
1171 GPR_ASSERT(grpc_auth_json_key_is_valid(json_key));
1172 GPR_ASSERT(json_key->private_key != nullptr);
1173 GPR_ASSERT(RSA_check_key(json_key->private_key));
1174 GPR_ASSERT(json_key->type != nullptr &&
1175 strcmp(json_key->type, "service_account") == 0);
1176 GPR_ASSERT(json_key->private_key_id != nullptr &&
1177 strcmp(json_key->private_key_id,
1178 "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0);
1179 GPR_ASSERT(json_key->client_id != nullptr &&
1180 strcmp(json_key->client_id,
1181 "777-abaslkan11hlb6nmim3bpspl31ud.apps."
1182 "googleusercontent.com") == 0);
1183 GPR_ASSERT(json_key->client_email != nullptr &&
1184 strcmp(json_key->client_email,
1185 "777-abaslkan11hlb6nmim3bpspl31ud@developer."
1186 "gserviceaccount.com") == 0);
1187 if (scope != nullptr) GPR_ASSERT(strcmp(scope, test_scope) == 0);
1188 GPR_ASSERT(gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime()) == 0);
1189 }
1190
encode_and_sign_jwt_success(const grpc_auth_json_key * json_key,const char *,gpr_timespec token_lifetime,const char * scope)1191 static char* encode_and_sign_jwt_success(const grpc_auth_json_key* json_key,
1192 const char* /*audience*/,
1193 gpr_timespec token_lifetime,
1194 const char* scope) {
1195 validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime);
1196 return gpr_strdup(test_signed_jwt);
1197 }
1198
encode_and_sign_jwt_failure(const grpc_auth_json_key * json_key,const char *,gpr_timespec token_lifetime,const char * scope)1199 static char* encode_and_sign_jwt_failure(const grpc_auth_json_key* json_key,
1200 const char* /*audience*/,
1201 gpr_timespec token_lifetime,
1202 const char* scope) {
1203 validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime);
1204 return nullptr;
1205 }
1206
encode_and_sign_jwt_should_not_be_called(const grpc_auth_json_key *,const char *,gpr_timespec,const char *)1207 static char* encode_and_sign_jwt_should_not_be_called(
1208 const grpc_auth_json_key* /*json_key*/, const char* /*audience*/,
1209 gpr_timespec /*token_lifetime*/, const char* /*scope*/) {
1210 GPR_ASSERT("grpc_jwt_encode_and_sign should not be called" == nullptr);
1211 return nullptr;
1212 }
1213
creds_as_jwt(grpc_call_credentials * creds)1214 static grpc_service_account_jwt_access_credentials* creds_as_jwt(
1215 grpc_call_credentials* creds) {
1216 GPR_ASSERT(creds != nullptr);
1217 GPR_ASSERT(strcmp(creds->type(), GRPC_CALL_CREDENTIALS_TYPE_JWT) == 0);
1218 return reinterpret_cast<grpc_service_account_jwt_access_credentials*>(creds);
1219 }
1220
test_jwt_creds_lifetime(void)1221 static void test_jwt_creds_lifetime(void) {
1222 char* json_key_string = test_json_key_str();
1223 const char expected_creds_debug_string_prefix[] =
1224 "JWTAccessCredentials{ExpirationTime:";
1225 // Max lifetime.
1226 grpc_call_credentials* jwt_creds =
1227 grpc_service_account_jwt_access_credentials_create(
1228 json_key_string, grpc_max_auth_token_lifetime(), nullptr);
1229 GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime(),
1230 grpc_max_auth_token_lifetime()) == 0);
1231 /* Check security level. */
1232 GPR_ASSERT(jwt_creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
1233 GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
1234 jwt_creds->debug_string().c_str(),
1235 strlen(expected_creds_debug_string_prefix)) == 0);
1236 grpc_call_credentials_release(jwt_creds);
1237
1238 // Shorter lifetime.
1239 gpr_timespec token_lifetime = {10, 0, GPR_TIMESPAN};
1240 GPR_ASSERT(gpr_time_cmp(grpc_max_auth_token_lifetime(), token_lifetime) > 0);
1241 jwt_creds = grpc_service_account_jwt_access_credentials_create(
1242 json_key_string, token_lifetime, nullptr);
1243 GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime(),
1244 token_lifetime) == 0);
1245 GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
1246 jwt_creds->debug_string().c_str(),
1247 strlen(expected_creds_debug_string_prefix)) == 0);
1248 grpc_call_credentials_release(jwt_creds);
1249
1250 // Cropped lifetime.
1251 gpr_timespec add_to_max = {10, 0, GPR_TIMESPAN};
1252 token_lifetime = gpr_time_add(grpc_max_auth_token_lifetime(), add_to_max);
1253 jwt_creds = grpc_service_account_jwt_access_credentials_create(
1254 json_key_string, token_lifetime, nullptr);
1255 GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime(),
1256 grpc_max_auth_token_lifetime()) == 0);
1257 GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
1258 jwt_creds->debug_string().c_str(),
1259 strlen(expected_creds_debug_string_prefix)) == 0);
1260 grpc_call_credentials_release(jwt_creds);
1261
1262 gpr_free(json_key_string);
1263 }
1264
test_jwt_creds_success(void)1265 static void test_jwt_creds_success(void) {
1266 const char expected_creds_debug_string_prefix[] =
1267 "JWTAccessCredentials{ExpirationTime:";
1268
1269 char* json_key_string = test_json_key_str();
1270 grpc_core::ExecCtx exec_ctx;
1271 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1272 nullptr, nullptr};
1273 std::string expected_md_value = absl::StrCat("Bearer ", test_signed_jwt);
1274 expected_md emd[] = {{"authorization", expected_md_value.c_str()}};
1275 grpc_call_credentials* creds =
1276 grpc_service_account_jwt_access_credentials_create(
1277 json_key_string, grpc_max_auth_token_lifetime(), nullptr);
1278
1279 /* First request: jwt_encode_and_sign should be called. */
1280 request_metadata_state* state =
1281 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
1282 grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
1283 run_request_metadata_test(creds, auth_md_ctx, state);
1284 grpc_core::ExecCtx::Get()->Flush();
1285
1286 /* Second request: the cached token should be served directly. */
1287 state =
1288 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
1289 grpc_jwt_encode_and_sign_set_override(
1290 encode_and_sign_jwt_should_not_be_called);
1291 run_request_metadata_test(creds, auth_md_ctx, state);
1292 grpc_core::ExecCtx::Get()->Flush();
1293
1294 /* Third request: Different service url so jwt_encode_and_sign should be
1295 called again (no caching). */
1296 state =
1297 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
1298 auth_md_ctx.service_url = other_test_service_url;
1299 grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
1300 run_request_metadata_test(creds, auth_md_ctx, state);
1301 grpc_core::ExecCtx::Get()->Flush();
1302 GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
1303 creds->debug_string().c_str(),
1304 strlen(expected_creds_debug_string_prefix)) == 0);
1305
1306 creds->Unref();
1307 gpr_free(json_key_string);
1308 grpc_jwt_encode_and_sign_set_override(nullptr);
1309 }
1310
test_jwt_creds_signing_failure(void)1311 static void test_jwt_creds_signing_failure(void) {
1312 const char expected_creds_debug_string_prefix[] =
1313 "JWTAccessCredentials{ExpirationTime:";
1314 char* json_key_string = test_json_key_str();
1315 grpc_core::ExecCtx exec_ctx;
1316 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1317 nullptr, nullptr};
1318 request_metadata_state* state = make_request_metadata_state(
1319 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT."), nullptr,
1320 0);
1321 grpc_call_credentials* creds =
1322 grpc_service_account_jwt_access_credentials_create(
1323 json_key_string, grpc_max_auth_token_lifetime(), nullptr);
1324
1325 grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
1326 run_request_metadata_test(creds, auth_md_ctx, state);
1327
1328 gpr_free(json_key_string);
1329 GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
1330 creds->debug_string().c_str(),
1331 strlen(expected_creds_debug_string_prefix)) == 0);
1332
1333 creds->Unref();
1334 grpc_jwt_encode_and_sign_set_override(nullptr);
1335 }
1336
set_google_default_creds_env_var_with_file_contents(const char * file_prefix,const char * contents)1337 static void set_google_default_creds_env_var_with_file_contents(
1338 const char* file_prefix, const char* contents) {
1339 size_t contents_len = strlen(contents);
1340 char* creds_file_name;
1341 FILE* creds_file = gpr_tmpfile(file_prefix, &creds_file_name);
1342 GPR_ASSERT(creds_file_name != nullptr);
1343 GPR_ASSERT(creds_file != nullptr);
1344 GPR_ASSERT(fwrite(contents, 1, contents_len, creds_file) == contents_len);
1345 fclose(creds_file);
1346 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, creds_file_name);
1347 gpr_free(creds_file_name);
1348 }
1349
test_google_default_creds_auth_key(void)1350 static void test_google_default_creds_auth_key(void) {
1351 grpc_core::ExecCtx exec_ctx;
1352 grpc_composite_channel_credentials* creds;
1353 char* json_key = test_json_key_str();
1354 grpc_flush_cached_google_default_credentials();
1355 set_google_default_creds_env_var_with_file_contents(
1356 "json_key_google_default_creds", json_key);
1357 gpr_free(json_key);
1358 creds = reinterpret_cast<grpc_composite_channel_credentials*>(
1359 grpc_google_default_credentials_create());
1360 auto* default_creds =
1361 reinterpret_cast<const grpc_google_default_channel_credentials*>(
1362 creds->inner_creds());
1363 GPR_ASSERT(default_creds->ssl_creds() != nullptr);
1364 auto* jwt =
1365 reinterpret_cast<const grpc_service_account_jwt_access_credentials*>(
1366 creds->call_creds());
1367 GPR_ASSERT(
1368 strcmp(jwt->key().client_id,
1369 "777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") ==
1370 0);
1371 creds->Unref();
1372 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
1373 }
1374
test_google_default_creds_refresh_token(void)1375 static void test_google_default_creds_refresh_token(void) {
1376 grpc_core::ExecCtx exec_ctx;
1377 grpc_composite_channel_credentials* creds;
1378 grpc_flush_cached_google_default_credentials();
1379 set_google_default_creds_env_var_with_file_contents(
1380 "refresh_token_google_default_creds", test_refresh_token_str);
1381 creds = reinterpret_cast<grpc_composite_channel_credentials*>(
1382 grpc_google_default_credentials_create());
1383 auto* default_creds =
1384 reinterpret_cast<const grpc_google_default_channel_credentials*>(
1385 creds->inner_creds());
1386 GPR_ASSERT(default_creds->ssl_creds() != nullptr);
1387 auto* refresh =
1388 reinterpret_cast<const grpc_google_refresh_token_credentials*>(
1389 creds->call_creds());
1390 GPR_ASSERT(strcmp(refresh->refresh_token().client_id,
1391 "32555999999.apps.googleusercontent.com") == 0);
1392 creds->Unref();
1393 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
1394 }
1395
default_creds_metadata_server_detection_httpcli_get_success_override(const grpc_httpcli_request * request,grpc_millis,grpc_closure * on_done,grpc_httpcli_response * response)1396 static int default_creds_metadata_server_detection_httpcli_get_success_override(
1397 const grpc_httpcli_request* request, grpc_millis /*deadline*/,
1398 grpc_closure* on_done, grpc_httpcli_response* response) {
1399 *response = http_response(200, "");
1400 grpc_http_header* headers =
1401 static_cast<grpc_http_header*>(gpr_malloc(sizeof(*headers) * 1));
1402 headers[0].key = gpr_strdup("Metadata-Flavor");
1403 headers[0].value = gpr_strdup("Google");
1404 response->hdr_count = 1;
1405 response->hdrs = headers;
1406 GPR_ASSERT(strcmp(request->http.path, "/") == 0);
1407 GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0);
1408 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
1409 return 1;
1410 }
1411
null_well_known_creds_path_getter(void)1412 static std::string null_well_known_creds_path_getter(void) { return ""; }
1413
test_gce_tenancy_checker(void)1414 static bool test_gce_tenancy_checker(void) {
1415 g_test_gce_tenancy_checker_called = true;
1416 return g_test_is_on_gce;
1417 }
1418
test_google_default_creds_gce(void)1419 static void test_google_default_creds_gce(void) {
1420 grpc_core::ExecCtx exec_ctx;
1421 expected_md emd[] = {
1422 {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
1423 request_metadata_state* state =
1424 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
1425 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1426 nullptr, nullptr};
1427 grpc_flush_cached_google_default_credentials();
1428 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
1429 grpc_override_well_known_credentials_path_getter(
1430 null_well_known_creds_path_getter);
1431 set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
1432 g_test_gce_tenancy_checker_called = false;
1433 g_test_is_on_gce = true;
1434
1435 /* Simulate a successful detection of GCE. */
1436 grpc_composite_channel_credentials* creds =
1437 reinterpret_cast<grpc_composite_channel_credentials*>(
1438 grpc_google_default_credentials_create());
1439
1440 /* Verify that the default creds actually embeds a GCE creds. */
1441 GPR_ASSERT(creds != nullptr);
1442 GPR_ASSERT(creds->call_creds() != nullptr);
1443 grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
1444 httpcli_post_should_not_be_called);
1445 run_request_metadata_test(creds->mutable_call_creds(), auth_md_ctx, state);
1446 grpc_core::ExecCtx::Get()->Flush();
1447
1448 GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
1449
1450 /* Cleanup. */
1451 creds->Unref();
1452 grpc_httpcli_set_override(nullptr, nullptr);
1453 grpc_override_well_known_credentials_path_getter(nullptr);
1454 }
1455
test_google_default_creds_non_gce(void)1456 static void test_google_default_creds_non_gce(void) {
1457 grpc_core::ExecCtx exec_ctx;
1458 expected_md emd[] = {
1459 {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
1460 request_metadata_state* state =
1461 make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
1462 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1463 nullptr, nullptr};
1464 grpc_flush_cached_google_default_credentials();
1465 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
1466 grpc_override_well_known_credentials_path_getter(
1467 null_well_known_creds_path_getter);
1468 set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
1469 g_test_gce_tenancy_checker_called = false;
1470 g_test_is_on_gce = false;
1471 /* Simulate a successful detection of metadata server. */
1472 grpc_httpcli_set_override(
1473 default_creds_metadata_server_detection_httpcli_get_success_override,
1474 httpcli_post_should_not_be_called);
1475 grpc_composite_channel_credentials* creds =
1476 reinterpret_cast<grpc_composite_channel_credentials*>(
1477 grpc_google_default_credentials_create());
1478 /* Verify that the default creds actually embeds a GCE creds. */
1479 GPR_ASSERT(creds != nullptr);
1480 GPR_ASSERT(creds->call_creds() != nullptr);
1481 grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
1482 httpcli_post_should_not_be_called);
1483 run_request_metadata_test(creds->mutable_call_creds(), auth_md_ctx, state);
1484 grpc_core::ExecCtx::Get()->Flush();
1485 GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
1486 /* Cleanup. */
1487 creds->Unref();
1488 grpc_httpcli_set_override(nullptr, nullptr);
1489 grpc_override_well_known_credentials_path_getter(nullptr);
1490 }
1491
default_creds_gce_detection_httpcli_get_failure_override(const grpc_httpcli_request * request,grpc_millis,grpc_closure * on_done,grpc_httpcli_response * response)1492 static int default_creds_gce_detection_httpcli_get_failure_override(
1493 const grpc_httpcli_request* request, grpc_millis /*deadline*/,
1494 grpc_closure* on_done, grpc_httpcli_response* response) {
1495 /* No magic header. */
1496 GPR_ASSERT(strcmp(request->http.path, "/") == 0);
1497 GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0);
1498 *response = http_response(200, "");
1499 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
1500 return 1;
1501 }
1502
test_no_google_default_creds(void)1503 static void test_no_google_default_creds(void) {
1504 grpc_flush_cached_google_default_credentials();
1505 gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
1506 grpc_override_well_known_credentials_path_getter(
1507 null_well_known_creds_path_getter);
1508 set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
1509 g_test_gce_tenancy_checker_called = false;
1510 g_test_is_on_gce = false;
1511 grpc_httpcli_set_override(
1512 default_creds_gce_detection_httpcli_get_failure_override,
1513 httpcli_post_should_not_be_called);
1514 /* Simulate a successful detection of GCE. */
1515 GPR_ASSERT(grpc_google_default_credentials_create() == nullptr);
1516 /* Try a second one. GCE detection should occur again. */
1517 g_test_gce_tenancy_checker_called = false;
1518 GPR_ASSERT(grpc_google_default_credentials_create() == nullptr);
1519 GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
1520 /* Cleanup. */
1521 grpc_override_well_known_credentials_path_getter(nullptr);
1522 grpc_httpcli_set_override(nullptr, nullptr);
1523 }
1524
1525 typedef enum {
1526 PLUGIN_INITIAL_STATE,
1527 PLUGIN_GET_METADATA_CALLED_STATE,
1528 PLUGIN_DESTROY_CALLED_STATE
1529 } plugin_state;
1530
1531 static const expected_md plugin_md[] = {{"foo", "bar"}, {"hi", "there"}};
1532
plugin_get_metadata_success(void * state,grpc_auth_metadata_context context,grpc_credentials_plugin_metadata_cb,void *,grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],size_t * num_creds_md,grpc_status_code *,const char **)1533 static int plugin_get_metadata_success(
1534 void* state, grpc_auth_metadata_context context,
1535 grpc_credentials_plugin_metadata_cb /*cb*/, void* /*user_data*/,
1536 grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
1537 size_t* num_creds_md, grpc_status_code* /*status*/,
1538 const char** /*error_details*/) {
1539 GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
1540 GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
1541 GPR_ASSERT(context.channel_auth_context == nullptr);
1542 GPR_ASSERT(context.reserved == nullptr);
1543 GPR_ASSERT(GPR_ARRAY_SIZE(plugin_md) <
1544 GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX);
1545 plugin_state* s = static_cast<plugin_state*>(state);
1546 *s = PLUGIN_GET_METADATA_CALLED_STATE;
1547 for (size_t i = 0; i < GPR_ARRAY_SIZE(plugin_md); ++i) {
1548 memset(&creds_md[i], 0, sizeof(grpc_metadata));
1549 creds_md[i].key = grpc_slice_from_copied_string(plugin_md[i].key);
1550 creds_md[i].value = grpc_slice_from_copied_string(plugin_md[i].value);
1551 }
1552 *num_creds_md = GPR_ARRAY_SIZE(plugin_md);
1553 return true; // Synchronous return.
1554 }
1555
1556 static const char* plugin_error_details = "Could not get metadata for plugin.";
1557
plugin_get_metadata_failure(void * state,grpc_auth_metadata_context context,grpc_credentials_plugin_metadata_cb,void *,grpc_metadata[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],size_t *,grpc_status_code * status,const char ** error_details)1558 static int plugin_get_metadata_failure(
1559 void* state, grpc_auth_metadata_context context,
1560 grpc_credentials_plugin_metadata_cb /*cb*/, void* /*user_data*/,
1561 grpc_metadata /*creds_md*/[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
1562 size_t* /*num_creds_md*/, grpc_status_code* status,
1563 const char** error_details) {
1564 GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
1565 GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
1566 GPR_ASSERT(context.channel_auth_context == nullptr);
1567 GPR_ASSERT(context.reserved == nullptr);
1568 plugin_state* s = static_cast<plugin_state*>(state);
1569 *s = PLUGIN_GET_METADATA_CALLED_STATE;
1570 *status = GRPC_STATUS_UNAUTHENTICATED;
1571 *error_details = gpr_strdup(plugin_error_details);
1572 return true; // Synchronous return.
1573 }
1574
plugin_destroy(void * state)1575 static void plugin_destroy(void* state) {
1576 plugin_state* s = static_cast<plugin_state*>(state);
1577 *s = PLUGIN_DESTROY_CALLED_STATE;
1578 }
1579
plugin_debug_string(void * state)1580 static char* plugin_debug_string(void* state) {
1581 plugin_state* s = static_cast<plugin_state*>(state);
1582 char* ret = nullptr;
1583 switch (*s) {
1584 case PLUGIN_INITIAL_STATE:
1585 gpr_asprintf(&ret, "TestPluginCredentials{state:INITIAL}");
1586 break;
1587 case PLUGIN_GET_METADATA_CALLED_STATE:
1588 gpr_asprintf(&ret, "TestPluginCredentials{state:GET_METADATA_CALLED}");
1589 break;
1590 case PLUGIN_DESTROY_CALLED_STATE:
1591 gpr_asprintf(&ret, "TestPluginCredentials{state:DESTROY}");
1592 break;
1593 default:
1594 gpr_asprintf(&ret, "TestPluginCredentials{state:UNKNOWN}");
1595 break;
1596 }
1597 return ret;
1598 }
1599
test_metadata_plugin_success(void)1600 static void test_metadata_plugin_success(void) {
1601 const char expected_creds_debug_string[] =
1602 "TestPluginCredentials{state:GET_METADATA_CALLED}";
1603 plugin_state state = PLUGIN_INITIAL_STATE;
1604 grpc_metadata_credentials_plugin plugin;
1605 grpc_core::ExecCtx exec_ctx;
1606 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1607 nullptr, nullptr};
1608 request_metadata_state* md_state = make_request_metadata_state(
1609 GRPC_ERROR_NONE, plugin_md, GPR_ARRAY_SIZE(plugin_md));
1610
1611 plugin.state = &state;
1612 plugin.get_metadata = plugin_get_metadata_success;
1613 plugin.destroy = plugin_destroy;
1614 plugin.debug_string = plugin_debug_string;
1615
1616 grpc_call_credentials* creds = grpc_metadata_credentials_create_from_plugin(
1617 plugin, GRPC_PRIVACY_AND_INTEGRITY, nullptr);
1618 /* Check security level. */
1619 GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
1620 GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
1621 run_request_metadata_test(creds, auth_md_ctx, md_state);
1622 GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
1623 GPR_ASSERT(
1624 strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
1625 creds->Unref();
1626
1627 GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
1628 }
1629
test_metadata_plugin_failure(void)1630 static void test_metadata_plugin_failure(void) {
1631 const char expected_creds_debug_string[] =
1632 "TestPluginCredentials{state:GET_METADATA_CALLED}";
1633
1634 plugin_state state = PLUGIN_INITIAL_STATE;
1635 grpc_metadata_credentials_plugin plugin;
1636 grpc_core::ExecCtx exec_ctx;
1637 grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
1638 nullptr, nullptr};
1639 std::string expected_error = absl::StrCat(
1640 "Getting metadata from plugin failed with error: ", plugin_error_details);
1641 request_metadata_state* md_state = make_request_metadata_state(
1642 GRPC_ERROR_CREATE_FROM_COPIED_STRING(expected_error.c_str()), nullptr, 0);
1643
1644 plugin.state = &state;
1645 plugin.get_metadata = plugin_get_metadata_failure;
1646 plugin.destroy = plugin_destroy;
1647 plugin.debug_string = plugin_debug_string;
1648
1649 grpc_call_credentials* creds = grpc_metadata_credentials_create_from_plugin(
1650 plugin, GRPC_PRIVACY_AND_INTEGRITY, nullptr);
1651 GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
1652 run_request_metadata_test(creds, auth_md_ctx, md_state);
1653 GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
1654 GPR_ASSERT(
1655 strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
1656 creds->Unref();
1657
1658 GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
1659 }
1660
test_get_well_known_google_credentials_file_path(void)1661 static void test_get_well_known_google_credentials_file_path(void) {
1662 char* home = gpr_getenv("HOME");
1663 bool restore_home_env = false;
1664 #if defined(GRPC_BAZEL_BUILD) && \
1665 (defined(GPR_POSIX_ENV) || defined(GPR_LINUX_ENV))
1666 // when running under bazel locally, the HOME variable is not set
1667 // so we set it to some fake value
1668 restore_home_env = true;
1669 gpr_setenv("HOME", "/fake/home/for/bazel");
1670 #endif /* defined(GRPC_BAZEL_BUILD) && (defined(GPR_POSIX_ENV) || \
1671 defined(GPR_LINUX_ENV)) */
1672 std::string path = grpc_get_well_known_google_credentials_file_path();
1673 GPR_ASSERT(!path.empty());
1674 #if defined(GPR_POSIX_ENV) || defined(GPR_LINUX_ENV)
1675 restore_home_env = true;
1676 gpr_unsetenv("HOME");
1677 path = grpc_get_well_known_google_credentials_file_path();
1678 GPR_ASSERT(path.empty());
1679 #endif /* GPR_POSIX_ENV || GPR_LINUX_ENV */
1680 if (restore_home_env) {
1681 if (home) {
1682 gpr_setenv("HOME", home);
1683 } else {
1684 gpr_unsetenv("HOME");
1685 }
1686 }
1687 gpr_free(home);
1688 }
1689
test_channel_creds_duplicate_without_call_creds(void)1690 static void test_channel_creds_duplicate_without_call_creds(void) {
1691 const char expected_creds_debug_string[] =
1692 "AccessTokenCredentials{Token:present}";
1693 grpc_core::ExecCtx exec_ctx;
1694
1695 grpc_channel_credentials* channel_creds =
1696 grpc_fake_transport_security_credentials_create();
1697
1698 grpc_core::RefCountedPtr<grpc_channel_credentials> dup =
1699 channel_creds->duplicate_without_call_credentials();
1700 GPR_ASSERT(dup == channel_creds);
1701 dup.reset();
1702
1703 grpc_call_credentials* call_creds =
1704 grpc_access_token_credentials_create("blah", nullptr);
1705 grpc_channel_credentials* composite_creds =
1706 grpc_composite_channel_credentials_create(channel_creds, call_creds,
1707 nullptr);
1708 GPR_ASSERT(strcmp(call_creds->debug_string().c_str(),
1709 expected_creds_debug_string) == 0);
1710
1711 call_creds->Unref();
1712 dup = composite_creds->duplicate_without_call_credentials();
1713 GPR_ASSERT(dup == channel_creds);
1714 dup.reset();
1715
1716 channel_creds->Unref();
1717 composite_creds->Unref();
1718 }
1719
1720 typedef struct {
1721 const char* url_scheme;
1722 const char* call_host;
1723 const char* call_method;
1724 const char* desired_service_url;
1725 const char* desired_method_name;
1726 } auth_metadata_context_test_case;
1727
test_auth_metadata_context(void)1728 static void test_auth_metadata_context(void) {
1729 auth_metadata_context_test_case test_cases[] = {
1730 // No service nor method.
1731 {"https", "www.foo.com", "", "https://www.foo.com", ""},
1732 // No method.
1733 {"https", "www.foo.com", "/Service", "https://www.foo.com/Service", ""},
1734 // Empty service and method.
1735 {"https", "www.foo.com", "//", "https://www.foo.com/", ""},
1736 // Empty method.
1737 {"https", "www.foo.com", "/Service/", "https://www.foo.com/Service", ""},
1738 // Malformed url.
1739 {"https", "www.foo.com:", "/Service/", "https://www.foo.com:/Service",
1740 ""},
1741 // https, default explicit port.
1742 {"https", "www.foo.com:443", "/Service/FooMethod",
1743 "https://www.foo.com/Service", "FooMethod"},
1744 // https, default implicit port.
1745 {"https", "www.foo.com", "/Service/FooMethod",
1746 "https://www.foo.com/Service", "FooMethod"},
1747 // https with ipv6 literal, default explicit port.
1748 {"https", "[1080:0:0:0:8:800:200C:417A]:443", "/Service/FooMethod",
1749 "https://[1080:0:0:0:8:800:200C:417A]/Service", "FooMethod"},
1750 // https with ipv6 literal, default implicit port.
1751 {"https", "[1080:0:0:0:8:800:200C:443]", "/Service/FooMethod",
1752 "https://[1080:0:0:0:8:800:200C:443]/Service", "FooMethod"},
1753 // https, custom port.
1754 {"https", "www.foo.com:8888", "/Service/FooMethod",
1755 "https://www.foo.com:8888/Service", "FooMethod"},
1756 // https with ipv6 literal, custom port.
1757 {"https", "[1080:0:0:0:8:800:200C:417A]:8888", "/Service/FooMethod",
1758 "https://[1080:0:0:0:8:800:200C:417A]:8888/Service", "FooMethod"},
1759 // custom url scheme, https default port.
1760 {"blah", "www.foo.com:443", "/Service/FooMethod",
1761 "blah://www.foo.com:443/Service", "FooMethod"}};
1762 for (uint32_t i = 0; i < GPR_ARRAY_SIZE(test_cases); i++) {
1763 const char* url_scheme = test_cases[i].url_scheme;
1764 grpc_slice call_host =
1765 grpc_slice_from_copied_string(test_cases[i].call_host);
1766 grpc_slice call_method =
1767 grpc_slice_from_copied_string(test_cases[i].call_method);
1768 grpc_auth_metadata_context auth_md_context;
1769 memset(&auth_md_context, 0, sizeof(auth_md_context));
1770 grpc_auth_metadata_context_build(url_scheme, call_host, call_method,
1771 nullptr, &auth_md_context);
1772 if (strcmp(auth_md_context.service_url,
1773 test_cases[i].desired_service_url) != 0) {
1774 gpr_log(GPR_ERROR, "Invalid service url, want: %s, got %s.",
1775 test_cases[i].desired_service_url, auth_md_context.service_url);
1776 GPR_ASSERT(false);
1777 }
1778 if (strcmp(auth_md_context.method_name,
1779 test_cases[i].desired_method_name) != 0) {
1780 gpr_log(GPR_ERROR, "Invalid method name, want: %s, got %s.",
1781 test_cases[i].desired_method_name, auth_md_context.method_name);
1782 GPR_ASSERT(false);
1783 }
1784 GPR_ASSERT(auth_md_context.channel_auth_context == nullptr);
1785 grpc_slice_unref(call_host);
1786 grpc_slice_unref(call_method);
1787 grpc_auth_metadata_context_reset(&auth_md_context);
1788 }
1789 }
1790
main(int argc,char ** argv)1791 int main(int argc, char** argv) {
1792 grpc::testing::TestEnvironment env(argc, argv);
1793 grpc_init();
1794 test_empty_md_array();
1795 test_add_to_empty_md_array();
1796 test_add_abunch_to_md_array();
1797 test_oauth2_token_fetcher_creds_parsing_ok();
1798 test_oauth2_token_fetcher_creds_parsing_bad_http_status();
1799 test_oauth2_token_fetcher_creds_parsing_empty_http_body();
1800 test_oauth2_token_fetcher_creds_parsing_invalid_json();
1801 test_oauth2_token_fetcher_creds_parsing_missing_token();
1802 test_oauth2_token_fetcher_creds_parsing_missing_token_type();
1803 test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime();
1804 test_google_iam_creds();
1805 test_access_token_creds();
1806 test_channel_oauth2_composite_creds();
1807 test_oauth2_google_iam_composite_creds();
1808 test_channel_oauth2_google_iam_composite_creds();
1809 test_compute_engine_creds_success();
1810 test_compute_engine_creds_failure();
1811 test_refresh_token_creds_success();
1812 test_refresh_token_creds_failure();
1813 test_valid_sts_creds_options();
1814 test_invalid_sts_creds_options();
1815 test_sts_creds_success();
1816 test_sts_creds_no_actor_token_success();
1817 test_sts_creds_load_token_failure();
1818 test_sts_creds_http_failure();
1819 test_sts_creds_token_file_not_found();
1820 test_jwt_creds_lifetime();
1821 test_jwt_creds_success();
1822 test_jwt_creds_signing_failure();
1823 test_google_default_creds_auth_key();
1824 test_google_default_creds_refresh_token();
1825 test_google_default_creds_gce();
1826 test_google_default_creds_non_gce();
1827 test_no_google_default_creds();
1828 test_metadata_plugin_success();
1829 test_metadata_plugin_failure();
1830 test_get_well_known_google_credentials_file_path();
1831 test_channel_creds_duplicate_without_call_creds();
1832 test_auth_metadata_context();
1833 grpc_shutdown();
1834 return 0;
1835 }
1836