credentials_test.c 49 KB

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