• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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