credentials_test.cc 160 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624
  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. #include <grpc/support/port_platform.h>
  19. #include "src/core/lib/security/credentials/credentials.h"
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <string>
  23. #include <gmock/gmock.h>
  24. #include <openssl/rsa.h>
  25. #include "absl/strings/match.h"
  26. #include "absl/strings/str_cat.h"
  27. #include "absl/strings/str_format.h"
  28. #include "absl/strings/str_replace.h"
  29. #include <grpc/grpc_security.h>
  30. #include <grpc/slice.h>
  31. #include <grpc/support/alloc.h>
  32. #include <grpc/support/log.h>
  33. #include <grpc/support/string_util.h>
  34. #include <grpc/support/time.h>
  35. #include "src/core/lib/gpr/env.h"
  36. #include "src/core/lib/gpr/string.h"
  37. #include "src/core/lib/gpr/tmpfile.h"
  38. #include "src/core/lib/gprpp/host_port.h"
  39. #include "src/core/lib/gprpp/time.h"
  40. #include "src/core/lib/http/httpcli.h"
  41. #include "src/core/lib/http/httpcli_ssl_credentials.h"
  42. #include "src/core/lib/iomgr/error.h"
  43. #include "src/core/lib/promise/exec_ctx_wakeup_scheduler.h"
  44. #include "src/core/lib/promise/promise.h"
  45. #include "src/core/lib/promise/seq.h"
  46. #include "src/core/lib/security/context/security_context.h"
  47. #include "src/core/lib/security/credentials/composite/composite_credentials.h"
  48. #include "src/core/lib/security/credentials/external/aws_external_account_credentials.h"
  49. #include "src/core/lib/security/credentials/external/external_account_credentials.h"
  50. #include "src/core/lib/security/credentials/external/file_external_account_credentials.h"
  51. #include "src/core/lib/security/credentials/external/url_external_account_credentials.h"
  52. #include "src/core/lib/security/credentials/fake/fake_credentials.h"
  53. #include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
  54. #include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
  55. #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
  56. #include "src/core/lib/security/transport/auth_filters.h"
  57. #include "src/core/lib/transport/error_utils.h"
  58. #include "src/core/lib/uri/uri_parser.h"
  59. #include "test/core/util/test_config.h"
  60. namespace grpc_core {
  61. using internal::grpc_flush_cached_google_default_credentials;
  62. using internal::set_gce_tenancy_checker_for_testing;
  63. namespace {
  64. auto* g_memory_allocator = new MemoryAllocator(
  65. ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
  66. /* -- Constants. -- */
  67. const char test_google_iam_authorization_token[] = "blahblahblhahb";
  68. const char test_google_iam_authority_selector[] = "respectmyauthoritah";
  69. const char test_oauth2_bearer_token[] = "Bearer blaaslkdjfaslkdfasdsfasf";
  70. /* This JSON key was generated with the GCE console and revoked immediately.
  71. The identifiers have been changed as well.
  72. Maximum size for a string literal is 509 chars in C89, yay! */
  73. const char test_json_key_str_part1[] =
  74. "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----"
  75. "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE"
  76. "qg"
  77. "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/"
  78. "rWBQvS4hle4LfijkP3J5BG+"
  79. "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+"
  80. "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/"
  81. "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/"
  82. "8HpCqFYM9V8f34SBWfD4fRFT+n/"
  83. "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+";
  84. const char test_json_key_str_part2[] =
  85. "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+"
  86. "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/"
  87. "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA"
  88. "G"
  89. "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz"
  90. "A"
  91. "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+"
  92. "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/"
  93. "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ"
  94. "Y"
  95. "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", ";
  96. const char test_json_key_str_part3[] =
  97. "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
  98. "\"client_email\": "
  99. "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
  100. "com\", \"client_id\": "
  101. "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
  102. "com\", \"type\": \"service_account\" }";
  103. /* Test refresh token. */
  104. const char test_refresh_token_str[] =
  105. "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
  106. " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
  107. " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\","
  108. " \"type\": \"authorized_user\"}";
  109. /* Test external account credentials. */
  110. const char test_external_account_credentials_str[] =
  111. "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_"
  112. "token_type\":\"subject_token_type\",\"service_account_impersonation_"
  113. "url\":\"https://iamcredentials.googleapis.com:5555/"
  114. "service_account_impersonation_url\",\"token_url\":\"https://"
  115. "sts.googleapis.com:5555/"
  116. "token\",\"token_info_url\":\"https://sts.googleapis.com:5555/"
  117. "token_info\",\"credential_source\":{\"file\":"
  118. "\"credentials_file_path\"},"
  119. "\"quota_project_id\":\"quota_"
  120. "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
  121. "secret\"}";
  122. const char test_external_account_credentials_multi_pattern_sts_str[] =
  123. "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_"
  124. "token_type\":\"subject_token_type\",\"service_account_impersonation_"
  125. "url\":\"https://sts.test.googleapis.com:5555/"
  126. "service_account_impersonation_url\",\"token_url\":\"https://"
  127. "test.sts.googleapis.com:5555/token\",\"token_info_url\":\"https://"
  128. "test-sts.googleapis.com:5555/"
  129. "token_info\",\"credential_source\":{\"file\":\"credentials_file_path\"},"
  130. "\"quota_project_id\":\"quota_"
  131. "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
  132. "secret\"}";
  133. const char test_external_account_credentials_multi_pattern_iam_str[] =
  134. "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_"
  135. "token_type\":\"subject_token_type\",\"service_account_impersonation_"
  136. "url\":\"https://iamcredentials.test.googleapis.com:5555/"
  137. "service_account_impersonation_url\",\"token_url\":\"https://"
  138. "test.iamcredentials.googleapis.com:5555/"
  139. "token\",\"token_info_url\":\"https://"
  140. "test-iamcredentials.googleapis.com:5555/"
  141. "token_info\",\"credential_source\":{\"file\":\"credentials_file_path\"},"
  142. "\"quota_project_id\":\"quota_"
  143. "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
  144. "secret\"}";
  145. const char valid_oauth2_json_response[] =
  146. "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
  147. " \"expires_in\":3599, "
  148. " \"token_type\":\"Bearer\"}";
  149. const char valid_sts_json_response[] =
  150. "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
  151. " \"expires_in\":3599, "
  152. " \"issued_token_type\":\"urn:ietf:params:oauth:token-type:access_token\", "
  153. " \"token_type\":\"Bearer\"}";
  154. const char test_scope[] = "perm1 perm2";
  155. const char test_signed_jwt[] =
  156. "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM4YW"
  157. "U0MDcyZTViYTdmZDkwODg2YzcifQ";
  158. const char test_signed_jwt_token_type[] =
  159. "urn:ietf:params:oauth:token-type:id_token";
  160. const char test_signed_jwt2[] =
  161. "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM5YW"
  162. "U2MDcyZTViYTdnZDkwODg5YzcifQ";
  163. const char test_signed_jwt_token_type2[] =
  164. "urn:ietf:params:oauth:token-type:jwt";
  165. const char test_signed_jwt_path_prefix[] = "test_sign_jwt";
  166. const char test_service_url[] = "https://foo.com/foo.v1";
  167. const char test_service_url_no_service_name[] = "https://foo.com/";
  168. const char other_test_service_url_no_service_name[] = "https://bar.com/";
  169. const char test_method[] = "ThisIsNotAMethod";
  170. const char kTestUrlScheme[] = "https";
  171. const char kTestAuthority[] = "foo.com";
  172. const char kTestPath[] = "/foo.v1/ThisIsNotAMethod";
  173. const char kTestOtherAuthority[] = "bar.com";
  174. const char kTestOtherPath[] = "/bar.v1/ThisIsNotAMethod";
  175. const char test_sts_endpoint_url[] = "https://foo.com:5555/v1/token-exchange";
  176. const char valid_external_account_creds_token_exchange_response[] =
  177. "{\"access_token\":\"token_exchange_access_token\","
  178. " \"expires_in\":3599,"
  179. " \"token_type\":\"Bearer\"}";
  180. const char
  181. valid_external_account_creds_service_account_impersonation_response[] =
  182. "{\"accessToken\":\"service_account_impersonation_access_token\","
  183. " \"expireTime\":\"2050-01-01T00:00:00Z\"}";
  184. const char
  185. valid_url_external_account_creds_options_credential_source_format_text[] =
  186. "{\"url\":\"https://foo.com:5555/generate_subject_token_format_text\","
  187. "\"headers\":{\"Metadata-Flavor\":\"Google\"}}";
  188. const char
  189. valid_url_external_account_creds_options_credential_source_with_qurey_params_format_text
  190. [] = "{\"url\":\"https://foo.com:5555/"
  191. "path/to/url/creds?p1=v1&p2=v2\","
  192. "\"headers\":{\"Metadata-Flavor\":\"Google\"}}";
  193. const char
  194. valid_url_external_account_creds_retrieve_subject_token_response_format_text
  195. [] = "test_subject_token";
  196. const char
  197. valid_url_external_account_creds_options_credential_source_format_json[] =
  198. "{\"url\":\"https://foo.com:5555/generate_subject_token_format_json\","
  199. "\"headers\":{\"Metadata-Flavor\":\"Google\"},"
  200. "\"format\":{\"type\":\"json\",\"subject_token_field_name\":\"access_"
  201. "token\"}}";
  202. const char
  203. valid_url_external_account_creds_retrieve_subject_token_response_format_json
  204. [] = "{\"access_token\":\"test_subject_token\"}";
  205. const char invalid_url_external_account_creds_options_credential_source[] =
  206. "{\"url\":\"invalid_credential_source_url\","
  207. "\"headers\":{\"Metadata-Flavor\":\"Google\"}}";
  208. const char valid_aws_external_account_creds_retrieve_signing_keys_response[] =
  209. "{\"AccessKeyId\":\"test_access_key_id\",\"SecretAccessKey\":"
  210. "\"test_secret_access_key\",\"Token\":\"test_token\"}";
  211. const char valid_aws_external_account_creds_options_credential_source[] =
  212. "{\"environment_id\":\"aws1\","
  213. "\"region_url\":\"https://foo.com:5555/region_url\","
  214. "\"url\":\"https://foo.com:5555/url\","
  215. "\"regional_cred_verification_url\":\"https://foo.com:5555/"
  216. "regional_cred_verification_url_{region}\"}";
  217. const char
  218. invalid_aws_external_account_creds_options_credential_source_unmatched_environment_id
  219. [] = "{\"environment_id\":\"unsupported_aws_version\","
  220. "\"region_url\":\"https://foo.com:5555/region_url\","
  221. "\"url\":\"https://foo.com:5555/url\","
  222. "\"regional_cred_verification_url\":\"https://foo.com:5555/"
  223. "regional_cred_verification_url_{region}\"}";
  224. const char
  225. invalid_aws_external_account_creds_options_credential_source_invalid_region_url
  226. [] = "{\"environment_id\":\"aws1\","
  227. "\"region_url\":\"invalid_region_url\","
  228. "\"url\":\"https://foo.com:5555/url\","
  229. "\"regional_cred_verification_url\":\"https://foo.com:5555/"
  230. "regional_cred_verification_url_{region}\"}";
  231. const char
  232. invalid_aws_external_account_creds_options_credential_source_invalid_url[] =
  233. "{\"environment_id\":\"aws1\","
  234. "\"region_url\":\"https://foo.com:5555/region_url\","
  235. "\"url\":\"invalid_url\","
  236. "\"regional_cred_verification_url\":\"https://foo.com:5555/"
  237. "regional_cred_verification_url_{region}\"}";
  238. const char
  239. invalid_aws_external_account_creds_options_credential_source_missing_role_name
  240. [] = "{\"environment_id\":\"aws1\","
  241. "\"region_url\":\"https://foo.com:5555/region_url\","
  242. "\"url\":\"https://foo.com:5555/url_no_role_name\","
  243. "\"regional_cred_verification_url\":\"https://foo.com:5555/"
  244. "regional_cred_verification_url_{region}\"}";
  245. const char
  246. invalid_aws_external_account_creds_options_credential_source_invalid_regional_cred_verification_url
  247. [] = "{\"environment_id\":\"aws1\","
  248. "\"region_url\":\"https://foo.com:5555/region_url\","
  249. "\"url\":\"https://foo.com:5555/url_no_role_name\","
  250. "\"regional_cred_verification_url\":\"invalid_regional_cred_"
  251. "verification_url\"}";
  252. /* -- Global state flags. -- */
  253. bool g_test_is_on_gce = false;
  254. bool g_test_gce_tenancy_checker_called = false;
  255. /* -- Utils. -- */
  256. char* test_json_key_str(void) {
  257. size_t result_len = strlen(test_json_key_str_part1) +
  258. strlen(test_json_key_str_part2) +
  259. strlen(test_json_key_str_part3);
  260. char* result = static_cast<char*>(gpr_malloc(result_len + 1));
  261. char* current = result;
  262. strcpy(result, test_json_key_str_part1);
  263. current += strlen(test_json_key_str_part1);
  264. strcpy(current, test_json_key_str_part2);
  265. current += strlen(test_json_key_str_part2);
  266. strcpy(current, test_json_key_str_part3);
  267. return result;
  268. }
  269. grpc_http_response http_response(int status, const char* body) {
  270. grpc_http_response response;
  271. response = {};
  272. response.status = status;
  273. response.body = gpr_strdup(const_cast<char*>(body));
  274. response.body_length = strlen(body);
  275. return response;
  276. }
  277. /* -- Tests. -- */
  278. TEST(CredentialsTest, TestOauth2TokenFetcherCredsParsingOk) {
  279. ExecCtx exec_ctx;
  280. absl::optional<Slice> token_value;
  281. Duration token_lifetime;
  282. grpc_http_response response = http_response(200, valid_oauth2_json_response);
  283. GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
  284. &response, &token_value, &token_lifetime) ==
  285. GRPC_CREDENTIALS_OK);
  286. GPR_ASSERT(token_lifetime == Duration::Seconds(3599));
  287. GPR_ASSERT(token_value->as_string_view() ==
  288. "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_");
  289. grpc_http_response_destroy(&response);
  290. }
  291. TEST(CredentialsTest, TestOauth2TokenFetcherCredsParsingBadHttpStatus) {
  292. ExecCtx exec_ctx;
  293. absl::optional<Slice> token_value;
  294. Duration token_lifetime;
  295. grpc_http_response response = http_response(401, valid_oauth2_json_response);
  296. GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
  297. &response, &token_value, &token_lifetime) ==
  298. GRPC_CREDENTIALS_ERROR);
  299. grpc_http_response_destroy(&response);
  300. }
  301. TEST(CredentialsTest, TestOauth2TokenFetcherCredsParsingEmptyHttpBody) {
  302. ExecCtx exec_ctx;
  303. absl::optional<Slice> token_value;
  304. Duration token_lifetime;
  305. grpc_http_response response = http_response(200, "");
  306. GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
  307. &response, &token_value, &token_lifetime) ==
  308. GRPC_CREDENTIALS_ERROR);
  309. grpc_http_response_destroy(&response);
  310. }
  311. TEST(CredentialsTest, TestOauth2TokenFetcherCredsParsingInvalidJson) {
  312. ExecCtx exec_ctx;
  313. absl::optional<Slice> token_value;
  314. Duration token_lifetime;
  315. grpc_http_response response =
  316. http_response(200,
  317. "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
  318. " \"expires_in\":3599, "
  319. " \"token_type\":\"Bearer\"");
  320. GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
  321. &response, &token_value, &token_lifetime) ==
  322. GRPC_CREDENTIALS_ERROR);
  323. grpc_http_response_destroy(&response);
  324. }
  325. TEST(CredentialsTest, TestOauth2TokenFetcherCredsParsingMissingToken) {
  326. ExecCtx exec_ctx;
  327. absl::optional<Slice> token_value;
  328. Duration token_lifetime;
  329. grpc_http_response response = http_response(200,
  330. "{"
  331. " \"expires_in\":3599, "
  332. " \"token_type\":\"Bearer\"}");
  333. GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
  334. &response, &token_value, &token_lifetime) ==
  335. GRPC_CREDENTIALS_ERROR);
  336. grpc_http_response_destroy(&response);
  337. }
  338. TEST(CredentialsTest, TestOauth2TokenFetcherCredsParsingMissingTokenType) {
  339. ExecCtx exec_ctx;
  340. absl::optional<Slice> token_value;
  341. Duration token_lifetime;
  342. grpc_http_response response =
  343. http_response(200,
  344. "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
  345. " \"expires_in\":3599, "
  346. "}");
  347. GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
  348. &response, &token_value, &token_lifetime) ==
  349. GRPC_CREDENTIALS_ERROR);
  350. grpc_http_response_destroy(&response);
  351. }
  352. TEST(CredentialsTest, TestOauth2TokenFetcherCredsParsingMissingTokenLifetime) {
  353. ExecCtx exec_ctx;
  354. absl::optional<Slice> token_value;
  355. Duration token_lifetime;
  356. grpc_http_response response =
  357. http_response(200,
  358. "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
  359. " \"token_type\":\"Bearer\"}");
  360. GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
  361. &response, &token_value, &token_lifetime) ==
  362. GRPC_CREDENTIALS_ERROR);
  363. grpc_http_response_destroy(&response);
  364. }
  365. namespace {
  366. class RequestMetadataState : public RefCounted<RequestMetadataState> {
  367. public:
  368. static RefCountedPtr<RequestMetadataState> NewInstance(
  369. grpc_error_handle expected_error, std::string expected) {
  370. return MakeRefCounted<RequestMetadataState>(
  371. expected_error, std::move(expected),
  372. grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create()));
  373. }
  374. RequestMetadataState(grpc_error_handle expected_error, std::string expected,
  375. grpc_polling_entity pollent)
  376. : expected_error_(expected_error),
  377. expected_(std::move(expected)),
  378. pollent_(pollent) {}
  379. ~RequestMetadataState() override {
  380. grpc_pollset_set_destroy(grpc_polling_entity_pollset_set(&pollent_));
  381. }
  382. void RunRequestMetadataTest(grpc_call_credentials* creds,
  383. const char* url_scheme, const char* authority,
  384. const char* path) {
  385. auto self = Ref();
  386. get_request_metadata_args_.security_connector =
  387. MakeRefCounted<BogusSecurityConnector>(url_scheme);
  388. md_.Set(HttpAuthorityMetadata(), Slice::FromStaticString(authority));
  389. md_.Set(HttpPathMetadata(), Slice::FromStaticString(path));
  390. activity_ = MakeActivity(
  391. [this, creds] {
  392. return Seq(creds->GetRequestMetadata(
  393. ClientInitialMetadata::TestOnlyWrap(&md_),
  394. &get_request_metadata_args_),
  395. [this](absl::StatusOr<ClientInitialMetadata> metadata) {
  396. if (metadata.ok()) {
  397. GPR_ASSERT(metadata->get() == &md_);
  398. }
  399. return metadata.status();
  400. });
  401. },
  402. ExecCtxWakeupScheduler(),
  403. [self](absl::Status status) mutable {
  404. self->CheckRequestMetadata(
  405. absl_status_to_grpc_error(std::move(status)));
  406. self.reset();
  407. },
  408. arena_.get(), &pollent_);
  409. }
  410. private:
  411. // No-op security connector, exists only to inject url_scheme.
  412. class BogusSecurityConnector : public grpc_channel_security_connector {
  413. public:
  414. explicit BogusSecurityConnector(absl::string_view url_scheme)
  415. : grpc_channel_security_connector(url_scheme, nullptr, nullptr) {}
  416. void check_peer(tsi_peer, grpc_endpoint*, RefCountedPtr<grpc_auth_context>*,
  417. grpc_closure*) override {
  418. GPR_ASSERT(false);
  419. }
  420. void cancel_check_peer(grpc_closure*, grpc_error_handle) override {
  421. GPR_ASSERT(false);
  422. }
  423. int cmp(const grpc_security_connector*) const override {
  424. GPR_UNREACHABLE_CODE(return 0);
  425. }
  426. ArenaPromise<absl::Status> CheckCallHost(absl::string_view,
  427. grpc_auth_context*) override {
  428. GPR_UNREACHABLE_CODE(
  429. return Immediate(absl::PermissionDeniedError("should never happen")));
  430. }
  431. void add_handshakers(const grpc_channel_args*, grpc_pollset_set*,
  432. HandshakeManager*) override {
  433. GPR_ASSERT(false);
  434. }
  435. };
  436. void CheckRequestMetadata(grpc_error_handle error) {
  437. gpr_log(GPR_INFO, "expected_error: %s",
  438. grpc_error_std_string(expected_error_).c_str());
  439. gpr_log(GPR_INFO, "actual_error: %s", grpc_error_std_string(error).c_str());
  440. if (expected_error_ == GRPC_ERROR_NONE) {
  441. GPR_ASSERT(error == GRPC_ERROR_NONE);
  442. } else {
  443. std::string expected_error;
  444. GPR_ASSERT(grpc_error_get_str(expected_error_, GRPC_ERROR_STR_DESCRIPTION,
  445. &expected_error));
  446. std::string actual_error;
  447. GPR_ASSERT(
  448. grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error));
  449. GPR_ASSERT(expected_error == actual_error);
  450. GRPC_ERROR_UNREF(expected_error_);
  451. }
  452. md_.Remove(HttpAuthorityMetadata());
  453. md_.Remove(HttpPathMetadata());
  454. gpr_log(GPR_INFO, "expected metadata: %s", expected_.c_str());
  455. gpr_log(GPR_INFO, "actual metadata: %s", md_.DebugString().c_str());
  456. GPR_ASSERT(md_.DebugString() == expected_);
  457. GRPC_ERROR_UNREF(error);
  458. }
  459. private:
  460. grpc_error_handle expected_error_;
  461. std::string expected_;
  462. ScopedArenaPtr arena_ = MakeScopedArena(1024, g_memory_allocator);
  463. grpc_metadata_batch md_{arena_.get()};
  464. grpc_call_credentials::GetRequestMetadataArgs get_request_metadata_args_;
  465. grpc_polling_entity pollent_;
  466. ActivityPtr activity_;
  467. };
  468. } // namespace
  469. TEST(CredentialsTest, TestGoogleIamCreds) {
  470. ExecCtx exec_ctx;
  471. auto state = RequestMetadataState::NewInstance(
  472. GRPC_ERROR_NONE,
  473. absl::StrCat(GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, ": ",
  474. test_google_iam_authorization_token, ", ",
  475. GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, ": ",
  476. test_google_iam_authority_selector));
  477. grpc_call_credentials* creds = grpc_google_iam_credentials_create(
  478. test_google_iam_authorization_token, test_google_iam_authority_selector,
  479. nullptr);
  480. /* Check security level. */
  481. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  482. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  483. kTestPath);
  484. creds->Unref();
  485. }
  486. TEST(CredentialsTest, TestAccessTokenCreds) {
  487. ExecCtx exec_ctx;
  488. auto state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE,
  489. "authorization: Bearer blah");
  490. grpc_call_credentials* creds =
  491. grpc_access_token_credentials_create("blah", nullptr);
  492. GPR_ASSERT(strcmp(creds->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
  493. /* Check security level. */
  494. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  495. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  496. kTestPath);
  497. creds->Unref();
  498. }
  499. namespace {
  500. class check_channel_oauth2 final : public grpc_channel_credentials {
  501. public:
  502. check_channel_oauth2() : grpc_channel_credentials("mock") {}
  503. ~check_channel_oauth2() override = default;
  504. RefCountedPtr<grpc_channel_security_connector> create_security_connector(
  505. RefCountedPtr<grpc_call_credentials> call_creds, const char* /*target*/,
  506. const grpc_channel_args* /*args*/,
  507. grpc_channel_args** /*new_args*/) override {
  508. GPR_ASSERT(strcmp(type(), "mock") == 0);
  509. GPR_ASSERT(call_creds != nullptr);
  510. GPR_ASSERT(strcmp(call_creds->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) ==
  511. 0);
  512. return nullptr;
  513. }
  514. private:
  515. int cmp_impl(const grpc_channel_credentials* other) const override {
  516. // TODO(yashykt): Check if we can do something better here
  517. return QsortCompare(static_cast<const grpc_channel_credentials*>(this),
  518. other);
  519. }
  520. };
  521. } // namespace
  522. TEST(CredentialsTest, TestChannelOauth2CompositeCreds) {
  523. ExecCtx exec_ctx;
  524. grpc_channel_args* new_args;
  525. grpc_channel_credentials* channel_creds = new check_channel_oauth2();
  526. grpc_call_credentials* oauth2_creds =
  527. grpc_access_token_credentials_create("blah", nullptr);
  528. grpc_channel_credentials* channel_oauth2_creds =
  529. grpc_composite_channel_credentials_create(channel_creds, oauth2_creds,
  530. nullptr);
  531. grpc_channel_credentials_release(channel_creds);
  532. grpc_call_credentials_release(oauth2_creds);
  533. channel_oauth2_creds->create_security_connector(nullptr, nullptr, nullptr,
  534. &new_args);
  535. grpc_channel_credentials_release(channel_oauth2_creds);
  536. }
  537. TEST(CredentialsTest, TestOauth2GoogleIamCompositeCreds) {
  538. ExecCtx exec_ctx;
  539. auto state = RequestMetadataState::NewInstance(
  540. GRPC_ERROR_NONE,
  541. absl::StrCat(GRPC_AUTHORIZATION_METADATA_KEY, ": ",
  542. test_oauth2_bearer_token, ", ",
  543. GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, ": ",
  544. test_google_iam_authorization_token, ", ",
  545. GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, ": ",
  546. test_google_iam_authority_selector));
  547. grpc_call_credentials* oauth2_creds = grpc_md_only_test_credentials_create(
  548. "authorization", test_oauth2_bearer_token);
  549. /* Check security level of fake credentials. */
  550. GPR_ASSERT(oauth2_creds->min_security_level() == GRPC_SECURITY_NONE);
  551. grpc_call_credentials* google_iam_creds = grpc_google_iam_credentials_create(
  552. test_google_iam_authorization_token, test_google_iam_authority_selector,
  553. nullptr);
  554. grpc_call_credentials* composite_creds =
  555. grpc_composite_call_credentials_create(oauth2_creds, google_iam_creds,
  556. nullptr);
  557. /* Check security level of composite credentials. */
  558. GPR_ASSERT(composite_creds->min_security_level() ==
  559. GRPC_PRIVACY_AND_INTEGRITY);
  560. oauth2_creds->Unref();
  561. google_iam_creds->Unref();
  562. GPR_ASSERT(strcmp(composite_creds->type(),
  563. GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
  564. const grpc_composite_call_credentials::CallCredentialsList& creds_list =
  565. static_cast<const grpc_composite_call_credentials*>(composite_creds)
  566. ->inner();
  567. GPR_ASSERT(creds_list.size() == 2);
  568. GPR_ASSERT(strcmp(creds_list[0]->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) ==
  569. 0);
  570. GPR_ASSERT(strcmp(creds_list[1]->type(), GRPC_CALL_CREDENTIALS_TYPE_IAM) ==
  571. 0);
  572. state->RunRequestMetadataTest(composite_creds, kTestUrlScheme, kTestAuthority,
  573. kTestPath);
  574. composite_creds->Unref();
  575. }
  576. namespace {
  577. class check_channel_oauth2_google_iam final : public grpc_channel_credentials {
  578. public:
  579. check_channel_oauth2_google_iam() : grpc_channel_credentials("mock") {}
  580. ~check_channel_oauth2_google_iam() override = default;
  581. RefCountedPtr<grpc_channel_security_connector> create_security_connector(
  582. RefCountedPtr<grpc_call_credentials> call_creds, const char* /*target*/,
  583. const grpc_channel_args* /*args*/,
  584. grpc_channel_args** /*new_args*/) override {
  585. GPR_ASSERT(strcmp(type(), "mock") == 0);
  586. GPR_ASSERT(call_creds != nullptr);
  587. GPR_ASSERT(
  588. strcmp(call_creds->type(), GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
  589. const grpc_composite_call_credentials::CallCredentialsList& creds_list =
  590. static_cast<const grpc_composite_call_credentials*>(call_creds.get())
  591. ->inner();
  592. GPR_ASSERT(
  593. strcmp(creds_list[0]->type(), GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
  594. GPR_ASSERT(strcmp(creds_list[1]->type(), GRPC_CALL_CREDENTIALS_TYPE_IAM) ==
  595. 0);
  596. return nullptr;
  597. }
  598. private:
  599. int cmp_impl(const grpc_channel_credentials* other) const override {
  600. // TODO(yashykt): Check if we can do something better here
  601. return QsortCompare(static_cast<const grpc_channel_credentials*>(this),
  602. other);
  603. }
  604. };
  605. } // namespace
  606. TEST(CredentialsTest, TestChannelOauth2GoogleIamCompositeCreds) {
  607. ExecCtx exec_ctx;
  608. grpc_channel_args* new_args;
  609. grpc_channel_credentials* channel_creds =
  610. new check_channel_oauth2_google_iam();
  611. grpc_call_credentials* oauth2_creds =
  612. grpc_access_token_credentials_create("blah", nullptr);
  613. grpc_channel_credentials* channel_oauth2_creds =
  614. grpc_composite_channel_credentials_create(channel_creds, oauth2_creds,
  615. nullptr);
  616. grpc_call_credentials* google_iam_creds = grpc_google_iam_credentials_create(
  617. test_google_iam_authorization_token, test_google_iam_authority_selector,
  618. nullptr);
  619. grpc_channel_credentials* channel_oauth2_iam_creds =
  620. grpc_composite_channel_credentials_create(channel_oauth2_creds,
  621. google_iam_creds, nullptr);
  622. grpc_channel_credentials_release(channel_creds);
  623. grpc_call_credentials_release(oauth2_creds);
  624. grpc_channel_credentials_release(channel_oauth2_creds);
  625. grpc_call_credentials_release(google_iam_creds);
  626. channel_oauth2_iam_creds->create_security_connector(nullptr, nullptr, nullptr,
  627. &new_args);
  628. grpc_channel_credentials_release(channel_oauth2_iam_creds);
  629. }
  630. void validate_compute_engine_http_request(const grpc_http_request* request,
  631. const char* host, const char* path) {
  632. GPR_ASSERT(strcmp(host, "metadata.google.internal.") == 0);
  633. GPR_ASSERT(
  634. strcmp(path,
  635. "/computeMetadata/v1/instance/service-accounts/default/token") ==
  636. 0);
  637. GPR_ASSERT(request->hdr_count == 1);
  638. GPR_ASSERT(strcmp(request->hdrs[0].key, "Metadata-Flavor") == 0);
  639. GPR_ASSERT(strcmp(request->hdrs[0].value, "Google") == 0);
  640. }
  641. int compute_engine_httpcli_get_success_override(
  642. const grpc_http_request* request, const char* host, const char* path,
  643. Timestamp /*deadline*/, grpc_closure* on_done,
  644. grpc_http_response* response) {
  645. validate_compute_engine_http_request(request, host, path);
  646. *response = http_response(200, valid_oauth2_json_response);
  647. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  648. return 1;
  649. }
  650. int compute_engine_httpcli_get_failure_override(
  651. const grpc_http_request* request, const char* host, const char* path,
  652. Timestamp /*deadline*/, grpc_closure* on_done,
  653. grpc_http_response* response) {
  654. validate_compute_engine_http_request(request, host, path);
  655. *response = http_response(403, "Not Authorized.");
  656. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  657. return 1;
  658. }
  659. int httpcli_post_should_not_be_called(
  660. const grpc_http_request* /*request*/, const char* /*host*/,
  661. const char* /*path*/, const char* /*body_bytes*/, size_t /*body_size*/,
  662. Timestamp /*deadline*/, grpc_closure* /*on_done*/,
  663. grpc_http_response* /*response*/) {
  664. GPR_ASSERT("HTTP POST should not be called" == nullptr);
  665. return 1;
  666. }
  667. int httpcli_get_should_not_be_called(const grpc_http_request* /*request*/,
  668. const char* /*host*/, const char* /*path*/,
  669. Timestamp /*deadline*/,
  670. grpc_closure* /*on_done*/,
  671. grpc_http_response* /*response*/) {
  672. GPR_ASSERT("HTTP GET should not be called" == nullptr);
  673. return 1;
  674. }
  675. TEST(CredentialsTest, TestComputeEngineCredsSuccess) {
  676. ExecCtx exec_ctx;
  677. std::string emd = "authorization: Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_";
  678. const char expected_creds_debug_string[] =
  679. "GoogleComputeEngineTokenFetcherCredentials{"
  680. "OAuth2TokenFetcherCredentials}";
  681. grpc_call_credentials* creds =
  682. grpc_google_compute_engine_credentials_create(nullptr);
  683. /* Check security level. */
  684. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  685. /* First request: http get should be called. */
  686. auto state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  687. HttpRequest::SetOverride(compute_engine_httpcli_get_success_override,
  688. httpcli_post_should_not_be_called);
  689. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  690. kTestPath);
  691. ExecCtx::Get()->Flush();
  692. /* Second request: the cached token should be served directly. */
  693. state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  694. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  695. httpcli_post_should_not_be_called);
  696. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  697. kTestPath);
  698. ExecCtx::Get()->Flush();
  699. GPR_ASSERT(
  700. strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
  701. creds->Unref();
  702. HttpRequest::SetOverride(nullptr, nullptr);
  703. }
  704. TEST(CredentialsTest, TestComputeEngineCredsFailure) {
  705. ExecCtx exec_ctx;
  706. const char expected_creds_debug_string[] =
  707. "GoogleComputeEngineTokenFetcherCredentials{"
  708. "OAuth2TokenFetcherCredentials}";
  709. auto state = RequestMetadataState::NewInstance(
  710. GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  711. "Error occurred when fetching oauth2 token."),
  712. {});
  713. grpc_call_credentials* creds =
  714. grpc_google_compute_engine_credentials_create(nullptr);
  715. HttpRequest::SetOverride(compute_engine_httpcli_get_failure_override,
  716. httpcli_post_should_not_be_called);
  717. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  718. kTestPath);
  719. GPR_ASSERT(
  720. strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
  721. creds->Unref();
  722. HttpRequest::SetOverride(nullptr, nullptr);
  723. }
  724. void validate_refresh_token_http_request(const grpc_http_request* request,
  725. const char* host, const char* path,
  726. const char* body, size_t body_size) {
  727. /* The content of the assertion is tested extensively in json_token_test. */
  728. GPR_ASSERT(body != nullptr);
  729. GPR_ASSERT(body_size != 0);
  730. std::string expected_body = absl::StrFormat(
  731. GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
  732. "32555999999.apps.googleusercontent.com", "EmssLNjJy1332hD4KFsecret",
  733. "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42");
  734. GPR_ASSERT(expected_body.size() == body_size);
  735. GPR_ASSERT(memcmp(expected_body.data(), body, body_size) == 0);
  736. GPR_ASSERT(strcmp(host, GRPC_GOOGLE_OAUTH2_SERVICE_HOST) == 0);
  737. GPR_ASSERT(strcmp(path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0);
  738. GPR_ASSERT(request->hdr_count == 1);
  739. GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0);
  740. GPR_ASSERT(
  741. strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded") == 0);
  742. }
  743. int refresh_token_httpcli_post_success(const grpc_http_request* request,
  744. const char* host, const char* path,
  745. const char* body, size_t body_size,
  746. Timestamp /*deadline*/,
  747. grpc_closure* on_done,
  748. grpc_http_response* response) {
  749. validate_refresh_token_http_request(request, host, path, body, body_size);
  750. *response = http_response(200, valid_oauth2_json_response);
  751. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  752. return 1;
  753. }
  754. int token_httpcli_post_failure(const grpc_http_request* /*request*/,
  755. const char* /*host*/, const char* /*path*/,
  756. const char* /*body*/, size_t /*body_size*/,
  757. Timestamp /*deadline*/, grpc_closure* on_done,
  758. grpc_http_response* response) {
  759. *response = http_response(403, "Not Authorized.");
  760. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  761. return 1;
  762. }
  763. TEST(CredentialsTest, TestRefreshTokenCredsSuccess) {
  764. ExecCtx exec_ctx;
  765. std::string emd = "authorization: Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_";
  766. const char expected_creds_debug_string[] =
  767. "GoogleRefreshToken{ClientID:32555999999.apps.googleusercontent.com,"
  768. "OAuth2TokenFetcherCredentials}";
  769. grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
  770. test_refresh_token_str, nullptr);
  771. /* Check security level. */
  772. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  773. /* First request: http put should be called. */
  774. auto state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  775. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  776. refresh_token_httpcli_post_success);
  777. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  778. kTestPath);
  779. ExecCtx::Get()->Flush();
  780. /* Second request: the cached token should be served directly. */
  781. state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  782. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  783. httpcli_post_should_not_be_called);
  784. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  785. kTestPath);
  786. ExecCtx::Get()->Flush();
  787. GPR_ASSERT(
  788. strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
  789. creds->Unref();
  790. HttpRequest::SetOverride(nullptr, nullptr);
  791. }
  792. TEST(CredentialsTest, TestRefreshTokenCredsFailure) {
  793. ExecCtx exec_ctx;
  794. const char expected_creds_debug_string[] =
  795. "GoogleRefreshToken{ClientID:32555999999.apps.googleusercontent.com,"
  796. "OAuth2TokenFetcherCredentials}";
  797. auto state = RequestMetadataState::NewInstance(
  798. GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  799. "Error occurred when fetching oauth2 token."),
  800. {});
  801. grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
  802. test_refresh_token_str, nullptr);
  803. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  804. token_httpcli_post_failure);
  805. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  806. kTestPath);
  807. GPR_ASSERT(
  808. strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
  809. creds->Unref();
  810. HttpRequest::SetOverride(nullptr, nullptr);
  811. }
  812. TEST(CredentialsTest, TestValidStsCredsOptions) {
  813. grpc_sts_credentials_options valid_options = {
  814. test_sts_endpoint_url, // sts_endpoint_url
  815. nullptr, // resource
  816. nullptr, // audience
  817. nullptr, // scope
  818. nullptr, // requested_token_type
  819. test_signed_jwt_path_prefix, // subject_token_path
  820. test_signed_jwt_token_type, // subject_token_type
  821. nullptr, // actor_token_path
  822. nullptr // actor_token_type
  823. };
  824. absl::StatusOr<URI> sts_url = ValidateStsCredentialsOptions(&valid_options);
  825. GPR_ASSERT(sts_url.ok());
  826. absl::string_view host;
  827. absl::string_view port;
  828. GPR_ASSERT(SplitHostPort(sts_url->authority(), &host, &port));
  829. GPR_ASSERT(host == "foo.com");
  830. GPR_ASSERT(port == "5555");
  831. }
  832. TEST(CredentialsTest, TestInvalidStsCredsOptions) {
  833. grpc_sts_credentials_options invalid_options = {
  834. test_sts_endpoint_url, // sts_endpoint_url
  835. nullptr, // resource
  836. nullptr, // audience
  837. nullptr, // scope
  838. nullptr, // requested_token_type
  839. nullptr, // subject_token_path (Required)
  840. test_signed_jwt_token_type, // subject_token_type
  841. nullptr, // actor_token_path
  842. nullptr // actor_token_type
  843. };
  844. absl::StatusOr<URI> url_should_be_invalid =
  845. ValidateStsCredentialsOptions(&invalid_options);
  846. GPR_ASSERT(!url_should_be_invalid.ok());
  847. invalid_options = {
  848. test_sts_endpoint_url, // sts_endpoint_url
  849. nullptr, // resource
  850. nullptr, // audience
  851. nullptr, // scope
  852. nullptr, // requested_token_type
  853. test_signed_jwt_path_prefix, // subject_token_path
  854. nullptr, // subject_token_type (Required)
  855. nullptr, // actor_token_path
  856. nullptr // actor_token_type
  857. };
  858. url_should_be_invalid = ValidateStsCredentialsOptions(&invalid_options);
  859. GPR_ASSERT(!url_should_be_invalid.ok());
  860. invalid_options = {
  861. nullptr, // sts_endpoint_url (Required)
  862. nullptr, // resource
  863. nullptr, // audience
  864. nullptr, // scope
  865. nullptr, // requested_token_type
  866. test_signed_jwt_path_prefix, // subject_token_path
  867. test_signed_jwt_token_type, // subject_token_type (Required)
  868. nullptr, // actor_token_path
  869. nullptr // actor_token_type
  870. };
  871. url_should_be_invalid = ValidateStsCredentialsOptions(&invalid_options);
  872. GPR_ASSERT(!url_should_be_invalid.ok());
  873. invalid_options = {
  874. "not_a_valid_uri", // sts_endpoint_url
  875. nullptr, // resource
  876. nullptr, // audience
  877. nullptr, // scope
  878. nullptr, // requested_token_type
  879. test_signed_jwt_path_prefix, // subject_token_path
  880. test_signed_jwt_token_type, // subject_token_type (Required)
  881. nullptr, // actor_token_path
  882. nullptr // actor_token_type
  883. };
  884. url_should_be_invalid = ValidateStsCredentialsOptions(&invalid_options);
  885. GPR_ASSERT(!url_should_be_invalid.ok());
  886. invalid_options = {
  887. "ftp://ftp.is.not.a.valid.scheme/bar", // sts_endpoint_url
  888. nullptr, // resource
  889. nullptr, // audience
  890. nullptr, // scope
  891. nullptr, // requested_token_type
  892. test_signed_jwt_path_prefix, // subject_token_path
  893. test_signed_jwt_token_type, // subject_token_type (Required)
  894. nullptr, // actor_token_path
  895. nullptr // actor_token_type
  896. };
  897. url_should_be_invalid = ValidateStsCredentialsOptions(&invalid_options);
  898. GPR_ASSERT(!url_should_be_invalid.ok());
  899. }
  900. void assert_query_parameters(const URI& uri, absl::string_view expected_key,
  901. absl::string_view expected_val) {
  902. const auto it = uri.query_parameter_map().find(expected_key);
  903. GPR_ASSERT(it != uri.query_parameter_map().end());
  904. if (it->second != expected_val) {
  905. gpr_log(GPR_ERROR, "%s!=%s", std::string(it->second).c_str(),
  906. std::string(expected_val).c_str());
  907. }
  908. GPR_ASSERT(it->second == expected_val);
  909. }
  910. void validate_sts_token_http_request(const grpc_http_request* request,
  911. const char* host, const char* path,
  912. const char* body, size_t body_size,
  913. bool expect_actor_token) {
  914. // Check that the body is constructed properly.
  915. GPR_ASSERT(body != nullptr);
  916. GPR_ASSERT(body_size != 0);
  917. std::string get_url_equivalent =
  918. absl::StrFormat("%s?%s", test_sts_endpoint_url, body);
  919. absl::StatusOr<URI> url = URI::Parse(get_url_equivalent);
  920. if (!url.ok()) {
  921. gpr_log(GPR_ERROR, "%s", url.status().ToString().c_str());
  922. GPR_ASSERT(url.ok());
  923. }
  924. assert_query_parameters(*url, "resource", "resource");
  925. assert_query_parameters(*url, "audience", "audience");
  926. assert_query_parameters(*url, "scope", "scope");
  927. assert_query_parameters(*url, "requested_token_type", "requested_token_type");
  928. assert_query_parameters(*url, "subject_token", test_signed_jwt);
  929. assert_query_parameters(*url, "subject_token_type",
  930. test_signed_jwt_token_type);
  931. if (expect_actor_token) {
  932. assert_query_parameters(*url, "actor_token", test_signed_jwt2);
  933. assert_query_parameters(*url, "actor_token_type",
  934. test_signed_jwt_token_type2);
  935. } else {
  936. GPR_ASSERT(url->query_parameter_map().find("actor_token") ==
  937. url->query_parameter_map().end());
  938. GPR_ASSERT(url->query_parameter_map().find("actor_token_type") ==
  939. url->query_parameter_map().end());
  940. }
  941. // Check the rest of the request.
  942. GPR_ASSERT(strcmp(host, "foo.com:5555") == 0);
  943. GPR_ASSERT(strcmp(path, "/v1/token-exchange") == 0);
  944. GPR_ASSERT(request->hdr_count == 1);
  945. GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0);
  946. GPR_ASSERT(
  947. strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded") == 0);
  948. }
  949. int sts_token_httpcli_post_success(const grpc_http_request* request,
  950. const char* host, const char* path,
  951. const char* body, size_t body_size,
  952. Timestamp /*deadline*/,
  953. grpc_closure* on_done,
  954. grpc_http_response* response) {
  955. validate_sts_token_http_request(request, host, path, body, body_size, true);
  956. *response = http_response(200, valid_sts_json_response);
  957. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  958. return 1;
  959. }
  960. int sts_token_httpcli_post_success_no_actor_token(
  961. const grpc_http_request* request, const char* host, const char* path,
  962. const char* body, size_t body_size, Timestamp /*deadline*/,
  963. grpc_closure* on_done, grpc_http_response* response) {
  964. validate_sts_token_http_request(request, host, path, body, body_size, false);
  965. *response = http_response(200, valid_sts_json_response);
  966. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  967. return 1;
  968. }
  969. char* write_tmp_jwt_file(const char* jwt_contents) {
  970. char* path;
  971. FILE* tmp = gpr_tmpfile(test_signed_jwt_path_prefix, &path);
  972. GPR_ASSERT(path != nullptr);
  973. GPR_ASSERT(tmp != nullptr);
  974. size_t jwt_length = strlen(jwt_contents);
  975. GPR_ASSERT(fwrite(jwt_contents, 1, jwt_length, tmp) == jwt_length);
  976. fclose(tmp);
  977. return path;
  978. }
  979. TEST(CredentialsTest, TestStsCredsSuccess) {
  980. ExecCtx exec_ctx;
  981. std::string emd = "authorization: Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_";
  982. const char expected_creds_debug_string[] =
  983. "StsTokenFetcherCredentials{Path:/v1/"
  984. "token-exchange,Authority:foo.com:5555,OAuth2TokenFetcherCredentials}";
  985. char* subject_token_path = write_tmp_jwt_file(test_signed_jwt);
  986. char* actor_token_path = write_tmp_jwt_file(test_signed_jwt2);
  987. grpc_sts_credentials_options valid_options = {
  988. test_sts_endpoint_url, // sts_endpoint_url
  989. "resource", // resource
  990. "audience", // audience
  991. "scope", // scope
  992. "requested_token_type", // requested_token_type
  993. subject_token_path, // subject_token_path
  994. test_signed_jwt_token_type, // subject_token_type
  995. actor_token_path, // actor_token_path
  996. test_signed_jwt_token_type2 // actor_token_type
  997. };
  998. grpc_call_credentials* creds =
  999. grpc_sts_credentials_create(&valid_options, nullptr);
  1000. /* Check security level. */
  1001. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  1002. /* First request: http put should be called. */
  1003. auto state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  1004. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  1005. sts_token_httpcli_post_success);
  1006. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1007. kTestPath);
  1008. ExecCtx::Get()->Flush();
  1009. /* Second request: the cached token should be served directly. */
  1010. state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  1011. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  1012. httpcli_post_should_not_be_called);
  1013. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1014. kTestPath);
  1015. ExecCtx::Get()->Flush();
  1016. GPR_ASSERT(
  1017. strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
  1018. creds->Unref();
  1019. HttpRequest::SetOverride(nullptr, nullptr);
  1020. gpr_free(subject_token_path);
  1021. gpr_free(actor_token_path);
  1022. }
  1023. TEST(CredentialsTest, TestStsCredsTokenFileNotFound) {
  1024. ExecCtx exec_ctx;
  1025. grpc_sts_credentials_options valid_options = {
  1026. test_sts_endpoint_url, // sts_endpoint_url
  1027. "resource", // resource
  1028. "audience", // audience
  1029. "scope", // scope
  1030. "requested_token_type", // requested_token_type
  1031. "/some/completely/random/path", // subject_token_path
  1032. test_signed_jwt_token_type, // subject_token_type
  1033. "", // actor_token_path
  1034. "" // actor_token_type
  1035. };
  1036. grpc_call_credentials* creds =
  1037. grpc_sts_credentials_create(&valid_options, nullptr);
  1038. /* Check security level. */
  1039. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  1040. auto state = RequestMetadataState::NewInstance(
  1041. GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  1042. "Error occurred when fetching oauth2 token."),
  1043. {});
  1044. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  1045. httpcli_post_should_not_be_called);
  1046. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1047. kTestPath);
  1048. ExecCtx::Get()->Flush();
  1049. /* Cleanup. */
  1050. creds->Unref();
  1051. HttpRequest::SetOverride(nullptr, nullptr);
  1052. }
  1053. TEST(CredentialsTest, TestStsCredsNoActorTokenSuccess) {
  1054. ExecCtx exec_ctx;
  1055. std::string emd = "authorization: Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_";
  1056. const char expected_creds_debug_string[] =
  1057. "StsTokenFetcherCredentials{Path:/v1/"
  1058. "token-exchange,Authority:foo.com:5555,OAuth2TokenFetcherCredentials}";
  1059. char* subject_token_path = write_tmp_jwt_file(test_signed_jwt);
  1060. grpc_sts_credentials_options valid_options = {
  1061. test_sts_endpoint_url, // sts_endpoint_url
  1062. "resource", // resource
  1063. "audience", // audience
  1064. "scope", // scope
  1065. "requested_token_type", // requested_token_type
  1066. subject_token_path, // subject_token_path
  1067. test_signed_jwt_token_type, // subject_token_type
  1068. "", // actor_token_path
  1069. "" // actor_token_type
  1070. };
  1071. grpc_call_credentials* creds =
  1072. grpc_sts_credentials_create(&valid_options, nullptr);
  1073. /* Check security level. */
  1074. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  1075. /* First request: http put should be called. */
  1076. auto state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  1077. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  1078. sts_token_httpcli_post_success_no_actor_token);
  1079. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1080. kTestPath);
  1081. ExecCtx::Get()->Flush();
  1082. /* Second request: the cached token should be served directly. */
  1083. state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  1084. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  1085. httpcli_post_should_not_be_called);
  1086. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1087. kTestPath);
  1088. ExecCtx::Get()->Flush();
  1089. GPR_ASSERT(
  1090. strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
  1091. creds->Unref();
  1092. HttpRequest::SetOverride(nullptr, nullptr);
  1093. gpr_free(subject_token_path);
  1094. }
  1095. TEST(CredentialsTest, TestStsCredsLoadTokenFailure) {
  1096. const char expected_creds_debug_string[] =
  1097. "StsTokenFetcherCredentials{Path:/v1/"
  1098. "token-exchange,Authority:foo.com:5555,OAuth2TokenFetcherCredentials}";
  1099. ExecCtx exec_ctx;
  1100. auto state = RequestMetadataState::NewInstance(
  1101. GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  1102. "Error occurred when fetching oauth2 token."),
  1103. {});
  1104. char* test_signed_jwt_path = write_tmp_jwt_file(test_signed_jwt);
  1105. grpc_sts_credentials_options options = {
  1106. test_sts_endpoint_url, // sts_endpoint_url
  1107. "resource", // resource
  1108. "audience", // audience
  1109. "scope", // scope
  1110. "requested_token_type", // requested_token_type
  1111. "invalid_path", // subject_token_path
  1112. test_signed_jwt_token_type, // subject_token_type
  1113. nullptr, // actor_token_path
  1114. nullptr // actor_token_type
  1115. };
  1116. grpc_call_credentials* creds = grpc_sts_credentials_create(&options, nullptr);
  1117. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  1118. httpcli_post_should_not_be_called);
  1119. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1120. kTestPath);
  1121. GPR_ASSERT(
  1122. strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
  1123. creds->Unref();
  1124. HttpRequest::SetOverride(nullptr, nullptr);
  1125. gpr_free(test_signed_jwt_path);
  1126. }
  1127. TEST(CredentialsTest, TestStsCredsHttpFailure) {
  1128. const char expected_creds_debug_string[] =
  1129. "StsTokenFetcherCredentials{Path:/v1/"
  1130. "token-exchange,Authority:foo.com:5555,OAuth2TokenFetcherCredentials}";
  1131. ExecCtx exec_ctx;
  1132. auto state = RequestMetadataState::NewInstance(
  1133. GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  1134. "Error occurred when fetching oauth2 token."),
  1135. {});
  1136. char* test_signed_jwt_path = write_tmp_jwt_file(test_signed_jwt);
  1137. grpc_sts_credentials_options valid_options = {
  1138. test_sts_endpoint_url, // sts_endpoint_url
  1139. "resource", // resource
  1140. "audience", // audience
  1141. "scope", // scope
  1142. "requested_token_type", // requested_token_type
  1143. test_signed_jwt_path, // subject_token_path
  1144. test_signed_jwt_token_type, // subject_token_type
  1145. nullptr, // actor_token_path
  1146. nullptr // actor_token_type
  1147. };
  1148. grpc_call_credentials* creds =
  1149. grpc_sts_credentials_create(&valid_options, nullptr);
  1150. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  1151. token_httpcli_post_failure);
  1152. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1153. kTestPath);
  1154. GPR_ASSERT(
  1155. strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
  1156. creds->Unref();
  1157. HttpRequest::SetOverride(nullptr, nullptr);
  1158. gpr_free(test_signed_jwt_path);
  1159. }
  1160. void validate_jwt_encode_and_sign_params(const grpc_auth_json_key* json_key,
  1161. const char* scope,
  1162. gpr_timespec token_lifetime) {
  1163. GPR_ASSERT(grpc_auth_json_key_is_valid(json_key));
  1164. GPR_ASSERT(json_key->private_key != nullptr);
  1165. GPR_ASSERT(RSA_check_key(json_key->private_key));
  1166. GPR_ASSERT(json_key->type != nullptr &&
  1167. strcmp(json_key->type, "service_account") == 0);
  1168. GPR_ASSERT(json_key->private_key_id != nullptr &&
  1169. strcmp(json_key->private_key_id,
  1170. "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0);
  1171. GPR_ASSERT(json_key->client_id != nullptr &&
  1172. strcmp(json_key->client_id,
  1173. "777-abaslkan11hlb6nmim3bpspl31ud.apps."
  1174. "googleusercontent.com") == 0);
  1175. GPR_ASSERT(json_key->client_email != nullptr &&
  1176. strcmp(json_key->client_email,
  1177. "777-abaslkan11hlb6nmim3bpspl31ud@developer."
  1178. "gserviceaccount.com") == 0);
  1179. if (scope != nullptr) GPR_ASSERT(strcmp(scope, test_scope) == 0);
  1180. GPR_ASSERT(gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime()) == 0);
  1181. }
  1182. char* encode_and_sign_jwt_success(const grpc_auth_json_key* json_key,
  1183. const char* audience,
  1184. gpr_timespec token_lifetime,
  1185. const char* scope) {
  1186. if (strcmp(audience, test_service_url_no_service_name) != 0 &&
  1187. strcmp(audience, other_test_service_url_no_service_name) != 0) {
  1188. return nullptr;
  1189. }
  1190. validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime);
  1191. return gpr_strdup(test_signed_jwt);
  1192. }
  1193. char* encode_and_sign_jwt_failure(const grpc_auth_json_key* json_key,
  1194. const char* /*audience*/,
  1195. gpr_timespec token_lifetime,
  1196. const char* scope) {
  1197. validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime);
  1198. return nullptr;
  1199. }
  1200. char* encode_and_sign_jwt_should_not_be_called(
  1201. const grpc_auth_json_key* /*json_key*/, const char* /*audience*/,
  1202. gpr_timespec /*token_lifetime*/, const char* /*scope*/) {
  1203. GPR_ASSERT("grpc_jwt_encode_and_sign should not be called" == nullptr);
  1204. return nullptr;
  1205. }
  1206. grpc_service_account_jwt_access_credentials* creds_as_jwt(
  1207. grpc_call_credentials* creds) {
  1208. GPR_ASSERT(creds != nullptr);
  1209. GPR_ASSERT(strcmp(creds->type(), GRPC_CALL_CREDENTIALS_TYPE_JWT) == 0);
  1210. return reinterpret_cast<grpc_service_account_jwt_access_credentials*>(creds);
  1211. }
  1212. TEST(CredentialsTest, TestJwtCredsLifetime) {
  1213. char* json_key_string = test_json_key_str();
  1214. const char expected_creds_debug_string_prefix[] =
  1215. "JWTAccessCredentials{ExpirationTime:";
  1216. // Max lifetime.
  1217. grpc_call_credentials* jwt_creds =
  1218. grpc_service_account_jwt_access_credentials_create(
  1219. json_key_string, grpc_max_auth_token_lifetime(), nullptr);
  1220. GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime(),
  1221. grpc_max_auth_token_lifetime()) == 0);
  1222. /* Check security level. */
  1223. GPR_ASSERT(jwt_creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  1224. GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
  1225. jwt_creds->debug_string().c_str(),
  1226. strlen(expected_creds_debug_string_prefix)) == 0);
  1227. grpc_call_credentials_release(jwt_creds);
  1228. // Shorter lifetime.
  1229. gpr_timespec token_lifetime = {10, 0, GPR_TIMESPAN};
  1230. GPR_ASSERT(gpr_time_cmp(grpc_max_auth_token_lifetime(), token_lifetime) > 0);
  1231. jwt_creds = grpc_service_account_jwt_access_credentials_create(
  1232. json_key_string, token_lifetime, nullptr);
  1233. GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime(),
  1234. token_lifetime) == 0);
  1235. GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
  1236. jwt_creds->debug_string().c_str(),
  1237. strlen(expected_creds_debug_string_prefix)) == 0);
  1238. grpc_call_credentials_release(jwt_creds);
  1239. // Cropped lifetime.
  1240. gpr_timespec add_to_max = {10, 0, GPR_TIMESPAN};
  1241. token_lifetime = gpr_time_add(grpc_max_auth_token_lifetime(), add_to_max);
  1242. jwt_creds = grpc_service_account_jwt_access_credentials_create(
  1243. json_key_string, token_lifetime, nullptr);
  1244. GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime(),
  1245. grpc_max_auth_token_lifetime()) == 0);
  1246. GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
  1247. jwt_creds->debug_string().c_str(),
  1248. strlen(expected_creds_debug_string_prefix)) == 0);
  1249. grpc_call_credentials_release(jwt_creds);
  1250. gpr_free(json_key_string);
  1251. }
  1252. TEST(CredentialsTest, TestRemoveServiceFromJwtUri) {
  1253. const char wrong_uri[] = "hello world";
  1254. GPR_ASSERT(!RemoveServiceNameFromJwtUri(wrong_uri).ok());
  1255. const char valid_uri[] = "https://foo.com/get/";
  1256. const char expected_uri[] = "https://foo.com/";
  1257. auto output = RemoveServiceNameFromJwtUri(valid_uri);
  1258. GPR_ASSERT(output.ok());
  1259. GPR_ASSERT(strcmp(output->c_str(), expected_uri) == 0);
  1260. }
  1261. TEST(CredentialsTest, TestJwtCredsSuccess) {
  1262. const char expected_creds_debug_string_prefix[] =
  1263. "JWTAccessCredentials{ExpirationTime:";
  1264. char* json_key_string = test_json_key_str();
  1265. ExecCtx exec_ctx;
  1266. std::string expected_md_value = absl::StrCat("Bearer ", test_signed_jwt);
  1267. std::string emd = absl::StrCat("authorization: ", expected_md_value);
  1268. grpc_call_credentials* creds =
  1269. grpc_service_account_jwt_access_credentials_create(
  1270. json_key_string, grpc_max_auth_token_lifetime(), nullptr);
  1271. /* First request: jwt_encode_and_sign should be called. */
  1272. auto state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  1273. grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
  1274. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1275. kTestPath);
  1276. ExecCtx::Get()->Flush();
  1277. /* Second request: the cached token should be served directly. */
  1278. state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  1279. grpc_jwt_encode_and_sign_set_override(
  1280. encode_and_sign_jwt_should_not_be_called);
  1281. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1282. kTestPath);
  1283. ExecCtx::Get()->Flush();
  1284. /* Third request: Different service url so jwt_encode_and_sign should be
  1285. called again (no caching). */
  1286. state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, emd);
  1287. grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
  1288. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestOtherAuthority,
  1289. kTestOtherPath);
  1290. ExecCtx::Get()->Flush();
  1291. GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
  1292. creds->debug_string().c_str(),
  1293. strlen(expected_creds_debug_string_prefix)) == 0);
  1294. creds->Unref();
  1295. gpr_free(json_key_string);
  1296. grpc_jwt_encode_and_sign_set_override(nullptr);
  1297. }
  1298. TEST(CredentialsTest, TestJwtCredsSigningFailure) {
  1299. const char expected_creds_debug_string_prefix[] =
  1300. "JWTAccessCredentials{ExpirationTime:";
  1301. char* json_key_string = test_json_key_str();
  1302. ExecCtx exec_ctx;
  1303. auto state = RequestMetadataState::NewInstance(
  1304. GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT."), {});
  1305. grpc_call_credentials* creds =
  1306. grpc_service_account_jwt_access_credentials_create(
  1307. json_key_string, grpc_max_auth_token_lifetime(), nullptr);
  1308. grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
  1309. state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1310. kTestPath);
  1311. gpr_free(json_key_string);
  1312. GPR_ASSERT(strncmp(expected_creds_debug_string_prefix,
  1313. creds->debug_string().c_str(),
  1314. strlen(expected_creds_debug_string_prefix)) == 0);
  1315. creds->Unref();
  1316. grpc_jwt_encode_and_sign_set_override(nullptr);
  1317. }
  1318. void set_google_default_creds_env_var_with_file_contents(
  1319. const char* file_prefix, const char* contents) {
  1320. size_t contents_len = strlen(contents);
  1321. char* creds_file_name;
  1322. FILE* creds_file = gpr_tmpfile(file_prefix, &creds_file_name);
  1323. GPR_ASSERT(creds_file_name != nullptr);
  1324. GPR_ASSERT(creds_file != nullptr);
  1325. GPR_ASSERT(fwrite(contents, 1, contents_len, creds_file) == contents_len);
  1326. fclose(creds_file);
  1327. gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, creds_file_name);
  1328. gpr_free(creds_file_name);
  1329. }
  1330. bool test_gce_tenancy_checker(void) {
  1331. g_test_gce_tenancy_checker_called = true;
  1332. return g_test_is_on_gce;
  1333. }
  1334. std::string null_well_known_creds_path_getter(void) { return ""; }
  1335. TEST(CredentialsTest, TestGoogleDefaultCredsAuthKey) {
  1336. ExecCtx exec_ctx;
  1337. grpc_composite_channel_credentials* creds;
  1338. char* json_key = test_json_key_str();
  1339. grpc_flush_cached_google_default_credentials();
  1340. set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
  1341. g_test_gce_tenancy_checker_called = false;
  1342. g_test_is_on_gce = true;
  1343. set_google_default_creds_env_var_with_file_contents(
  1344. "json_key_google_default_creds", json_key);
  1345. grpc_override_well_known_credentials_path_getter(
  1346. null_well_known_creds_path_getter);
  1347. gpr_free(json_key);
  1348. creds = reinterpret_cast<grpc_composite_channel_credentials*>(
  1349. grpc_google_default_credentials_create(nullptr));
  1350. auto* default_creds =
  1351. reinterpret_cast<const grpc_google_default_channel_credentials*>(
  1352. creds->inner_creds());
  1353. GPR_ASSERT(default_creds->ssl_creds() != nullptr);
  1354. auto* jwt =
  1355. reinterpret_cast<const grpc_service_account_jwt_access_credentials*>(
  1356. creds->call_creds());
  1357. GPR_ASSERT(
  1358. strcmp(jwt->key().client_id,
  1359. "777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") ==
  1360. 0);
  1361. GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
  1362. creds->Unref();
  1363. gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
  1364. grpc_override_well_known_credentials_path_getter(nullptr);
  1365. }
  1366. TEST(CredentialsTest, TestGoogleDefaultCredsRefreshToken) {
  1367. ExecCtx exec_ctx;
  1368. grpc_composite_channel_credentials* creds;
  1369. grpc_flush_cached_google_default_credentials();
  1370. set_google_default_creds_env_var_with_file_contents(
  1371. "refresh_token_google_default_creds", test_refresh_token_str);
  1372. grpc_override_well_known_credentials_path_getter(
  1373. null_well_known_creds_path_getter);
  1374. creds = reinterpret_cast<grpc_composite_channel_credentials*>(
  1375. grpc_google_default_credentials_create(nullptr));
  1376. auto* default_creds =
  1377. reinterpret_cast<const grpc_google_default_channel_credentials*>(
  1378. creds->inner_creds());
  1379. GPR_ASSERT(default_creds->ssl_creds() != nullptr);
  1380. auto* refresh =
  1381. reinterpret_cast<const grpc_google_refresh_token_credentials*>(
  1382. creds->call_creds());
  1383. GPR_ASSERT(strcmp(refresh->refresh_token().client_id,
  1384. "32555999999.apps.googleusercontent.com") == 0);
  1385. creds->Unref();
  1386. gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
  1387. grpc_override_well_known_credentials_path_getter(nullptr);
  1388. }
  1389. TEST(CredentialsTest, TestGoogleDefaultCredsExternalAccountCredentials) {
  1390. ExecCtx exec_ctx;
  1391. grpc_composite_channel_credentials* creds;
  1392. grpc_flush_cached_google_default_credentials();
  1393. set_google_default_creds_env_var_with_file_contents(
  1394. "google_default_creds_external_account_credentials",
  1395. test_external_account_credentials_str);
  1396. grpc_override_well_known_credentials_path_getter(
  1397. null_well_known_creds_path_getter);
  1398. creds = reinterpret_cast<grpc_composite_channel_credentials*>(
  1399. grpc_google_default_credentials_create(nullptr));
  1400. auto* default_creds =
  1401. reinterpret_cast<const grpc_google_default_channel_credentials*>(
  1402. creds->inner_creds());
  1403. GPR_ASSERT(default_creds->ssl_creds() != nullptr);
  1404. auto* external =
  1405. reinterpret_cast<const ExternalAccountCredentials*>(creds->call_creds());
  1406. GPR_ASSERT(external != nullptr);
  1407. creds->Unref();
  1408. gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
  1409. grpc_override_well_known_credentials_path_getter(nullptr);
  1410. }
  1411. TEST(CredentialsTest,
  1412. TestGoogleDefaultCredsExternalAccountCredentialsMultiPatternSts) {
  1413. ExecCtx exec_ctx;
  1414. grpc_composite_channel_credentials* creds;
  1415. grpc_flush_cached_google_default_credentials();
  1416. set_google_default_creds_env_var_with_file_contents(
  1417. "google_default_creds_external_account_credentials_multi_pattern_sts",
  1418. test_external_account_credentials_multi_pattern_sts_str);
  1419. grpc_override_well_known_credentials_path_getter(
  1420. null_well_known_creds_path_getter);
  1421. creds = reinterpret_cast<grpc_composite_channel_credentials*>(
  1422. grpc_google_default_credentials_create(nullptr));
  1423. auto* default_creds =
  1424. reinterpret_cast<const grpc_google_default_channel_credentials*>(
  1425. creds->inner_creds());
  1426. GPR_ASSERT(default_creds->ssl_creds() != nullptr);
  1427. auto* external =
  1428. reinterpret_cast<const ExternalAccountCredentials*>(creds->call_creds());
  1429. GPR_ASSERT(external != nullptr);
  1430. creds->Unref();
  1431. gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
  1432. grpc_override_well_known_credentials_path_getter(nullptr);
  1433. }
  1434. TEST(CredentialsTest,
  1435. TestGoogleDefaultCredsExternalAccountCredentialsMultiPatternIam) {
  1436. ExecCtx exec_ctx;
  1437. grpc_composite_channel_credentials* creds;
  1438. grpc_flush_cached_google_default_credentials();
  1439. set_google_default_creds_env_var_with_file_contents(
  1440. "google_default_creds_external_account_credentials_multi_pattern_iam",
  1441. test_external_account_credentials_multi_pattern_iam_str);
  1442. grpc_override_well_known_credentials_path_getter(
  1443. null_well_known_creds_path_getter);
  1444. creds = reinterpret_cast<grpc_composite_channel_credentials*>(
  1445. grpc_google_default_credentials_create(nullptr));
  1446. auto* default_creds =
  1447. reinterpret_cast<const grpc_google_default_channel_credentials*>(
  1448. creds->inner_creds());
  1449. GPR_ASSERT(default_creds->ssl_creds() != nullptr);
  1450. auto* external =
  1451. reinterpret_cast<const ExternalAccountCredentials*>(creds->call_creds());
  1452. GPR_ASSERT(external != nullptr);
  1453. creds->Unref();
  1454. gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
  1455. grpc_override_well_known_credentials_path_getter(nullptr);
  1456. }
  1457. int default_creds_metadata_server_detection_httpcli_get_success_override(
  1458. const grpc_http_request* /*request*/, const char* host, const char* path,
  1459. Timestamp /*deadline*/, grpc_closure* on_done,
  1460. grpc_http_response* response) {
  1461. *response = http_response(200, "");
  1462. grpc_http_header* headers =
  1463. static_cast<grpc_http_header*>(gpr_malloc(sizeof(*headers) * 1));
  1464. headers[0].key = gpr_strdup("Metadata-Flavor");
  1465. headers[0].value = gpr_strdup("Google");
  1466. response->hdr_count = 1;
  1467. response->hdrs = headers;
  1468. GPR_ASSERT(strcmp(path, "/") == 0);
  1469. GPR_ASSERT(strcmp(host, "metadata.google.internal.") == 0);
  1470. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  1471. return 1;
  1472. }
  1473. TEST(CredentialsTest, TestGoogleDefaultCredsGce) {
  1474. ExecCtx exec_ctx;
  1475. auto state = RequestMetadataState::NewInstance(
  1476. GRPC_ERROR_NONE,
  1477. "authorization: Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_");
  1478. grpc_flush_cached_google_default_credentials();
  1479. gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
  1480. grpc_override_well_known_credentials_path_getter(
  1481. null_well_known_creds_path_getter);
  1482. set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
  1483. g_test_gce_tenancy_checker_called = false;
  1484. g_test_is_on_gce = true;
  1485. /* Simulate a successful detection of GCE. */
  1486. grpc_composite_channel_credentials* creds =
  1487. reinterpret_cast<grpc_composite_channel_credentials*>(
  1488. grpc_google_default_credentials_create(nullptr));
  1489. /* Verify that the default creds actually embeds a GCE creds. */
  1490. GPR_ASSERT(creds != nullptr);
  1491. GPR_ASSERT(creds->call_creds() != nullptr);
  1492. HttpRequest::SetOverride(compute_engine_httpcli_get_success_override,
  1493. httpcli_post_should_not_be_called);
  1494. state->RunRequestMetadataTest(creds->mutable_call_creds(), kTestUrlScheme,
  1495. kTestAuthority, kTestPath);
  1496. ExecCtx::Get()->Flush();
  1497. GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
  1498. /* Cleanup. */
  1499. creds->Unref();
  1500. HttpRequest::SetOverride(nullptr, nullptr);
  1501. grpc_override_well_known_credentials_path_getter(nullptr);
  1502. }
  1503. TEST(CredentialsTest, TestGoogleDefaultCredsNonGce) {
  1504. ExecCtx exec_ctx;
  1505. auto state = RequestMetadataState::NewInstance(
  1506. GRPC_ERROR_NONE,
  1507. "authorization: Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_");
  1508. grpc_flush_cached_google_default_credentials();
  1509. gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
  1510. grpc_override_well_known_credentials_path_getter(
  1511. null_well_known_creds_path_getter);
  1512. set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
  1513. g_test_gce_tenancy_checker_called = false;
  1514. g_test_is_on_gce = false;
  1515. /* Simulate a successful detection of metadata server. */
  1516. HttpRequest::SetOverride(
  1517. default_creds_metadata_server_detection_httpcli_get_success_override,
  1518. httpcli_post_should_not_be_called);
  1519. grpc_composite_channel_credentials* creds =
  1520. reinterpret_cast<grpc_composite_channel_credentials*>(
  1521. grpc_google_default_credentials_create(nullptr));
  1522. /* Verify that the default creds actually embeds a GCE creds. */
  1523. GPR_ASSERT(creds != nullptr);
  1524. GPR_ASSERT(creds->call_creds() != nullptr);
  1525. HttpRequest::SetOverride(compute_engine_httpcli_get_success_override,
  1526. httpcli_post_should_not_be_called);
  1527. state->RunRequestMetadataTest(creds->mutable_call_creds(), kTestUrlScheme,
  1528. kTestAuthority, kTestPath);
  1529. ExecCtx::Get()->Flush();
  1530. GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
  1531. /* Cleanup. */
  1532. creds->Unref();
  1533. HttpRequest::SetOverride(nullptr, nullptr);
  1534. grpc_override_well_known_credentials_path_getter(nullptr);
  1535. }
  1536. int default_creds_gce_detection_httpcli_get_failure_override(
  1537. const grpc_http_request* /*request*/, const char* host, const char* path,
  1538. Timestamp /*deadline*/, grpc_closure* on_done,
  1539. grpc_http_response* response) {
  1540. /* No magic header. */
  1541. GPR_ASSERT(strcmp(path, "/") == 0);
  1542. GPR_ASSERT(strcmp(host, "metadata.google.internal.") == 0);
  1543. *response = http_response(200, "");
  1544. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  1545. return 1;
  1546. }
  1547. TEST(CredentialsTest, TestNoGoogleDefaultCreds) {
  1548. grpc_flush_cached_google_default_credentials();
  1549. gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
  1550. grpc_override_well_known_credentials_path_getter(
  1551. null_well_known_creds_path_getter);
  1552. set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
  1553. g_test_gce_tenancy_checker_called = false;
  1554. g_test_is_on_gce = false;
  1555. HttpRequest::SetOverride(
  1556. default_creds_gce_detection_httpcli_get_failure_override,
  1557. httpcli_post_should_not_be_called);
  1558. /* Simulate a successful detection of GCE. */
  1559. GPR_ASSERT(grpc_google_default_credentials_create(nullptr) == nullptr);
  1560. /* Try a second one. GCE detection should occur again. */
  1561. g_test_gce_tenancy_checker_called = false;
  1562. GPR_ASSERT(grpc_google_default_credentials_create(nullptr) == nullptr);
  1563. GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
  1564. /* Cleanup. */
  1565. grpc_override_well_known_credentials_path_getter(nullptr);
  1566. HttpRequest::SetOverride(nullptr, nullptr);
  1567. }
  1568. TEST(CredentialsTest, TestGoogleDefaultCredsCallCredsSpecified) {
  1569. auto state = RequestMetadataState::NewInstance(
  1570. GRPC_ERROR_NONE,
  1571. "authorization: Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_");
  1572. ExecCtx exec_ctx;
  1573. grpc_flush_cached_google_default_credentials();
  1574. grpc_call_credentials* call_creds =
  1575. grpc_google_compute_engine_credentials_create(nullptr);
  1576. set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
  1577. g_test_gce_tenancy_checker_called = false;
  1578. g_test_is_on_gce = true;
  1579. HttpRequest::SetOverride(
  1580. default_creds_metadata_server_detection_httpcli_get_success_override,
  1581. httpcli_post_should_not_be_called);
  1582. grpc_composite_channel_credentials* channel_creds =
  1583. reinterpret_cast<grpc_composite_channel_credentials*>(
  1584. grpc_google_default_credentials_create(call_creds));
  1585. GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
  1586. GPR_ASSERT(channel_creds != nullptr);
  1587. GPR_ASSERT(channel_creds->call_creds() != nullptr);
  1588. HttpRequest::SetOverride(compute_engine_httpcli_get_success_override,
  1589. httpcli_post_should_not_be_called);
  1590. state->RunRequestMetadataTest(channel_creds->mutable_call_creds(),
  1591. kTestUrlScheme, kTestAuthority, kTestPath);
  1592. ExecCtx::Get()->Flush();
  1593. channel_creds->Unref();
  1594. HttpRequest::SetOverride(nullptr, nullptr);
  1595. }
  1596. struct fake_call_creds : public grpc_call_credentials {
  1597. public:
  1598. fake_call_creds() : grpc_call_credentials("fake") {}
  1599. ArenaPromise<absl::StatusOr<ClientInitialMetadata>> GetRequestMetadata(
  1600. ClientInitialMetadata initial_metadata,
  1601. const grpc_call_credentials::GetRequestMetadataArgs*) override {
  1602. initial_metadata->Append("foo", Slice::FromStaticString("oof"),
  1603. [](absl::string_view, const Slice&) { abort(); });
  1604. return Immediate(std::move(initial_metadata));
  1605. }
  1606. private:
  1607. int cmp_impl(const grpc_call_credentials* other) const override {
  1608. // TODO(yashykt): Check if we can do something better here
  1609. return QsortCompare(static_cast<const grpc_call_credentials*>(this), other);
  1610. }
  1611. };
  1612. TEST(CredentialsTest, TestGoogleDefaultCredsNotDefault) {
  1613. auto state = RequestMetadataState::NewInstance(GRPC_ERROR_NONE, "foo: oof");
  1614. ExecCtx exec_ctx;
  1615. grpc_flush_cached_google_default_credentials();
  1616. RefCountedPtr<grpc_call_credentials> call_creds =
  1617. MakeRefCounted<fake_call_creds>();
  1618. set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
  1619. g_test_gce_tenancy_checker_called = false;
  1620. g_test_is_on_gce = true;
  1621. HttpRequest::SetOverride(
  1622. default_creds_metadata_server_detection_httpcli_get_success_override,
  1623. httpcli_post_should_not_be_called);
  1624. grpc_composite_channel_credentials* channel_creds =
  1625. reinterpret_cast<grpc_composite_channel_credentials*>(
  1626. grpc_google_default_credentials_create(call_creds.release()));
  1627. GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
  1628. GPR_ASSERT(channel_creds != nullptr);
  1629. GPR_ASSERT(channel_creds->call_creds() != nullptr);
  1630. state->RunRequestMetadataTest(channel_creds->mutable_call_creds(),
  1631. kTestUrlScheme, kTestAuthority, kTestPath);
  1632. ExecCtx::Get()->Flush();
  1633. channel_creds->Unref();
  1634. HttpRequest::SetOverride(nullptr, nullptr);
  1635. }
  1636. typedef enum {
  1637. PLUGIN_INITIAL_STATE,
  1638. PLUGIN_GET_METADATA_CALLED_STATE,
  1639. PLUGIN_DESTROY_CALLED_STATE
  1640. } plugin_state;
  1641. const std::map<std::string, std::string> plugin_md = {{"foo", "bar"},
  1642. {"hi", "there"}};
  1643. int plugin_get_metadata_success(
  1644. void* state, grpc_auth_metadata_context context,
  1645. grpc_credentials_plugin_metadata_cb /*cb*/, void* /*user_data*/,
  1646. grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
  1647. size_t* num_creds_md, grpc_status_code* /*status*/,
  1648. const char** /*error_details*/) {
  1649. GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
  1650. GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
  1651. GPR_ASSERT(context.channel_auth_context == nullptr);
  1652. GPR_ASSERT(context.reserved == nullptr);
  1653. GPR_ASSERT(plugin_md.size() < GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX);
  1654. plugin_state* s = static_cast<plugin_state*>(state);
  1655. *s = PLUGIN_GET_METADATA_CALLED_STATE;
  1656. size_t i = 0;
  1657. for (auto const& md : plugin_md) {
  1658. memset(&creds_md[i], 0, sizeof(grpc_metadata));
  1659. creds_md[i].key = grpc_slice_from_copied_string(md.first.c_str());
  1660. creds_md[i].value = grpc_slice_from_copied_string(md.second.c_str());
  1661. i += 1;
  1662. }
  1663. *num_creds_md = plugin_md.size();
  1664. return true; // Synchronous return.
  1665. }
  1666. const char* plugin_error_details = "Could not get metadata for plugin.";
  1667. int plugin_get_metadata_failure(
  1668. void* state, grpc_auth_metadata_context context,
  1669. grpc_credentials_plugin_metadata_cb /*cb*/, void* /*user_data*/,
  1670. grpc_metadata /*creds_md*/[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
  1671. size_t* /*num_creds_md*/, grpc_status_code* status,
  1672. const char** error_details) {
  1673. GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
  1674. GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
  1675. GPR_ASSERT(context.channel_auth_context == nullptr);
  1676. GPR_ASSERT(context.reserved == nullptr);
  1677. plugin_state* s = static_cast<plugin_state*>(state);
  1678. *s = PLUGIN_GET_METADATA_CALLED_STATE;
  1679. *status = GRPC_STATUS_UNAUTHENTICATED;
  1680. *error_details = gpr_strdup(plugin_error_details);
  1681. return true; // Synchronous return.
  1682. }
  1683. void plugin_destroy(void* state) {
  1684. plugin_state* s = static_cast<plugin_state*>(state);
  1685. *s = PLUGIN_DESTROY_CALLED_STATE;
  1686. }
  1687. char* plugin_debug_string(void* state) {
  1688. plugin_state* s = static_cast<plugin_state*>(state);
  1689. char* ret = nullptr;
  1690. switch (*s) {
  1691. case PLUGIN_INITIAL_STATE:
  1692. gpr_asprintf(&ret, "TestPluginCredentials{state:INITIAL}");
  1693. break;
  1694. case PLUGIN_GET_METADATA_CALLED_STATE:
  1695. gpr_asprintf(&ret, "TestPluginCredentials{state:GET_METADATA_CALLED}");
  1696. break;
  1697. case PLUGIN_DESTROY_CALLED_STATE:
  1698. gpr_asprintf(&ret, "TestPluginCredentials{state:DESTROY}");
  1699. break;
  1700. default:
  1701. gpr_asprintf(&ret, "TestPluginCredentials{state:UNKNOWN}");
  1702. break;
  1703. }
  1704. return ret;
  1705. }
  1706. TEST(CredentialsTest, TestMetadataPluginSuccess) {
  1707. const char expected_creds_debug_string[] =
  1708. "TestPluginCredentials{state:GET_METADATA_CALLED}";
  1709. plugin_state state = PLUGIN_INITIAL_STATE;
  1710. grpc_metadata_credentials_plugin plugin;
  1711. ExecCtx exec_ctx;
  1712. auto md_state =
  1713. RequestMetadataState::NewInstance(GRPC_ERROR_NONE, "foo: bar, hi: there");
  1714. plugin.state = &state;
  1715. plugin.get_metadata = plugin_get_metadata_success;
  1716. plugin.destroy = plugin_destroy;
  1717. plugin.debug_string = plugin_debug_string;
  1718. grpc_call_credentials* creds = grpc_metadata_credentials_create_from_plugin(
  1719. plugin, GRPC_PRIVACY_AND_INTEGRITY, nullptr);
  1720. /* Check security level. */
  1721. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  1722. GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
  1723. md_state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1724. kTestPath);
  1725. GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
  1726. GPR_ASSERT(
  1727. strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
  1728. creds->Unref();
  1729. GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
  1730. }
  1731. TEST(CredentialsTest, TestMetadataPluginFailure) {
  1732. const char expected_creds_debug_string[] =
  1733. "TestPluginCredentials{state:GET_METADATA_CALLED}";
  1734. plugin_state state = PLUGIN_INITIAL_STATE;
  1735. grpc_metadata_credentials_plugin plugin;
  1736. ExecCtx exec_ctx;
  1737. auto md_state = RequestMetadataState::NewInstance(
  1738. GRPC_ERROR_CREATE_FROM_CPP_STRING(
  1739. absl::StrCat("Getting metadata from plugin failed with error: ",
  1740. plugin_error_details)),
  1741. {});
  1742. plugin.state = &state;
  1743. plugin.get_metadata = plugin_get_metadata_failure;
  1744. plugin.destroy = plugin_destroy;
  1745. plugin.debug_string = plugin_debug_string;
  1746. grpc_call_credentials* creds = grpc_metadata_credentials_create_from_plugin(
  1747. plugin, GRPC_PRIVACY_AND_INTEGRITY, nullptr);
  1748. GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
  1749. md_state->RunRequestMetadataTest(creds, kTestUrlScheme, kTestAuthority,
  1750. kTestPath);
  1751. GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
  1752. GPR_ASSERT(
  1753. strcmp(creds->debug_string().c_str(), expected_creds_debug_string) == 0);
  1754. creds->Unref();
  1755. GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
  1756. }
  1757. TEST(CredentialsTest, TestGetWellKnownGoogleCredentialsFilePath) {
  1758. char* home = gpr_getenv("HOME");
  1759. bool restore_home_env = false;
  1760. #if defined(GRPC_BAZEL_BUILD) && \
  1761. (defined(GPR_POSIX_ENV) || defined(GPR_LINUX_ENV))
  1762. // when running under bazel locally, the HOME variable is not set
  1763. // so we set it to some fake value
  1764. restore_home_env = true;
  1765. gpr_setenv("HOME", "/fake/home/for/bazel");
  1766. #endif /* defined(GRPC_BAZEL_BUILD) && (defined(GPR_POSIX_ENV) || \
  1767. defined(GPR_LINUX_ENV)) */
  1768. std::string path = grpc_get_well_known_google_credentials_file_path();
  1769. GPR_ASSERT(!path.empty());
  1770. #if defined(GPR_POSIX_ENV) || defined(GPR_LINUX_ENV)
  1771. restore_home_env = true;
  1772. gpr_unsetenv("HOME");
  1773. path = grpc_get_well_known_google_credentials_file_path();
  1774. GPR_ASSERT(path.empty());
  1775. #endif /* GPR_POSIX_ENV || GPR_LINUX_ENV */
  1776. if (restore_home_env) {
  1777. if (home) {
  1778. gpr_setenv("HOME", home);
  1779. } else {
  1780. gpr_unsetenv("HOME");
  1781. }
  1782. }
  1783. gpr_free(home);
  1784. }
  1785. TEST(CredentialsTest, TestChannelCredsDuplicateWithoutCallCreds) {
  1786. const char expected_creds_debug_string[] =
  1787. "AccessTokenCredentials{Token:present}";
  1788. ExecCtx exec_ctx;
  1789. grpc_channel_credentials* channel_creds =
  1790. grpc_fake_transport_security_credentials_create();
  1791. RefCountedPtr<grpc_channel_credentials> dup =
  1792. channel_creds->duplicate_without_call_credentials();
  1793. GPR_ASSERT(dup == channel_creds);
  1794. dup.reset();
  1795. grpc_call_credentials* call_creds =
  1796. grpc_access_token_credentials_create("blah", nullptr);
  1797. grpc_channel_credentials* composite_creds =
  1798. grpc_composite_channel_credentials_create(channel_creds, call_creds,
  1799. nullptr);
  1800. GPR_ASSERT(strcmp(call_creds->debug_string().c_str(),
  1801. expected_creds_debug_string) == 0);
  1802. call_creds->Unref();
  1803. dup = composite_creds->duplicate_without_call_credentials();
  1804. GPR_ASSERT(dup == channel_creds);
  1805. dup.reset();
  1806. channel_creds->Unref();
  1807. composite_creds->Unref();
  1808. }
  1809. typedef struct {
  1810. const char* url_scheme;
  1811. const char* call_host;
  1812. const char* call_method;
  1813. const char* desired_service_url;
  1814. const char* desired_method_name;
  1815. } auth_metadata_context_test_case;
  1816. void auth_metadata_context_build(const char* url_scheme,
  1817. const grpc_slice& call_host,
  1818. const grpc_slice& call_method,
  1819. grpc_auth_context* auth_context,
  1820. grpc_auth_metadata_context* auth_md_context) {
  1821. char* service = grpc_slice_to_c_string(call_method);
  1822. char* last_slash = strrchr(service, '/');
  1823. char* method_name = nullptr;
  1824. char* service_url = nullptr;
  1825. grpc_auth_metadata_context_reset(auth_md_context);
  1826. if (last_slash == nullptr) {
  1827. gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
  1828. service[0] = '\0';
  1829. method_name = gpr_strdup("");
  1830. } else if (last_slash == service) {
  1831. method_name = gpr_strdup("");
  1832. } else {
  1833. *last_slash = '\0';
  1834. method_name = gpr_strdup(last_slash + 1);
  1835. }
  1836. char* host_and_port = grpc_slice_to_c_string(call_host);
  1837. if (url_scheme != nullptr && strcmp(url_scheme, GRPC_SSL_URL_SCHEME) == 0) {
  1838. /* Remove the port if it is 443. */
  1839. char* port_delimiter = strrchr(host_and_port, ':');
  1840. if (port_delimiter != nullptr && strcmp(port_delimiter + 1, "443") == 0) {
  1841. *port_delimiter = '\0';
  1842. }
  1843. }
  1844. gpr_asprintf(&service_url, "%s://%s%s",
  1845. url_scheme == nullptr ? "" : url_scheme, host_and_port, service);
  1846. auth_md_context->service_url = service_url;
  1847. auth_md_context->method_name = method_name;
  1848. auth_md_context->channel_auth_context =
  1849. auth_context == nullptr
  1850. ? nullptr
  1851. : auth_context->Ref(DEBUG_LOCATION, "grpc_auth_metadata_context")
  1852. .release();
  1853. gpr_free(service);
  1854. gpr_free(host_and_port);
  1855. }
  1856. TEST(CredentialsTest, TestAuthMetadataContext) {
  1857. auth_metadata_context_test_case test_cases[] = {
  1858. // No service nor method.
  1859. {"https", "www.foo.com", "", "https://www.foo.com", ""},
  1860. // No method.
  1861. {"https", "www.foo.com", "/Service", "https://www.foo.com/Service", ""},
  1862. // Empty service and method.
  1863. {"https", "www.foo.com", "//", "https://www.foo.com/", ""},
  1864. // Empty method.
  1865. {"https", "www.foo.com", "/Service/", "https://www.foo.com/Service", ""},
  1866. // Malformed url.
  1867. {"https", "www.foo.com:", "/Service/", "https://www.foo.com:/Service",
  1868. ""},
  1869. // https, default explicit port.
  1870. {"https", "www.foo.com:443", "/Service/FooMethod",
  1871. "https://www.foo.com/Service", "FooMethod"},
  1872. // https, default implicit port.
  1873. {"https", "www.foo.com", "/Service/FooMethod",
  1874. "https://www.foo.com/Service", "FooMethod"},
  1875. // https with ipv6 literal, default explicit port.
  1876. {"https", "[1080:0:0:0:8:800:200C:417A]:443", "/Service/FooMethod",
  1877. "https://[1080:0:0:0:8:800:200C:417A]/Service", "FooMethod"},
  1878. // https with ipv6 literal, default implicit port.
  1879. {"https", "[1080:0:0:0:8:800:200C:443]", "/Service/FooMethod",
  1880. "https://[1080:0:0:0:8:800:200C:443]/Service", "FooMethod"},
  1881. // https, custom port.
  1882. {"https", "www.foo.com:8888", "/Service/FooMethod",
  1883. "https://www.foo.com:8888/Service", "FooMethod"},
  1884. // https with ipv6 literal, custom port.
  1885. {"https", "[1080:0:0:0:8:800:200C:417A]:8888", "/Service/FooMethod",
  1886. "https://[1080:0:0:0:8:800:200C:417A]:8888/Service", "FooMethod"},
  1887. // custom url scheme, https default port.
  1888. {"blah", "www.foo.com:443", "/Service/FooMethod",
  1889. "blah://www.foo.com:443/Service", "FooMethod"}};
  1890. for (uint32_t i = 0; i < GPR_ARRAY_SIZE(test_cases); i++) {
  1891. const char* url_scheme = test_cases[i].url_scheme;
  1892. grpc_slice call_host =
  1893. grpc_slice_from_copied_string(test_cases[i].call_host);
  1894. grpc_slice call_method =
  1895. grpc_slice_from_copied_string(test_cases[i].call_method);
  1896. grpc_auth_metadata_context auth_md_context;
  1897. memset(&auth_md_context, 0, sizeof(auth_md_context));
  1898. auth_metadata_context_build(url_scheme, call_host, call_method, nullptr,
  1899. &auth_md_context);
  1900. if (strcmp(auth_md_context.service_url,
  1901. test_cases[i].desired_service_url) != 0) {
  1902. gpr_log(GPR_ERROR, "Invalid service url, want: %s, got %s.",
  1903. test_cases[i].desired_service_url, auth_md_context.service_url);
  1904. GPR_ASSERT(false);
  1905. }
  1906. if (strcmp(auth_md_context.method_name,
  1907. test_cases[i].desired_method_name) != 0) {
  1908. gpr_log(GPR_ERROR, "Invalid method name, want: %s, got %s.",
  1909. test_cases[i].desired_method_name, auth_md_context.method_name);
  1910. GPR_ASSERT(false);
  1911. }
  1912. GPR_ASSERT(auth_md_context.channel_auth_context == nullptr);
  1913. grpc_slice_unref(call_host);
  1914. grpc_slice_unref(call_method);
  1915. grpc_auth_metadata_context_reset(&auth_md_context);
  1916. }
  1917. }
  1918. void validate_external_account_creds_token_exchage_request(
  1919. const grpc_http_request* request, const char* host, const char* path,
  1920. const char* body, size_t body_size, bool /*expect_actor_token*/) {
  1921. // Check that the body is constructed properly.
  1922. GPR_ASSERT(body != nullptr);
  1923. GPR_ASSERT(body_size != 0);
  1924. std::string get_url_equivalent =
  1925. absl::StrFormat("%s?%s", "https://foo.com:5555/token", body);
  1926. absl::StatusOr<URI> uri = URI::Parse(get_url_equivalent);
  1927. if (!uri.ok()) {
  1928. gpr_log(GPR_ERROR, "%s", uri.status().ToString().c_str());
  1929. GPR_ASSERT(uri.ok());
  1930. }
  1931. assert_query_parameters(*uri, "audience", "audience");
  1932. assert_query_parameters(*uri, "grant_type",
  1933. "urn:ietf:params:oauth:grant-type:token-exchange");
  1934. assert_query_parameters(*uri, "requested_token_type",
  1935. "urn:ietf:params:oauth:token-type:access_token");
  1936. assert_query_parameters(*uri, "subject_token", "test_subject_token");
  1937. assert_query_parameters(*uri, "subject_token_type", "subject_token_type");
  1938. assert_query_parameters(*uri, "scope",
  1939. "https://www.googleapis.com/auth/cloud-platform");
  1940. // Check the rest of the request.
  1941. GPR_ASSERT(strcmp(host, "foo.com:5555") == 0);
  1942. GPR_ASSERT(strcmp(path, "/token") == 0);
  1943. GPR_ASSERT(request->hdr_count == 2);
  1944. GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0);
  1945. GPR_ASSERT(
  1946. strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded") == 0);
  1947. GPR_ASSERT(strcmp(request->hdrs[1].key, "Authorization") == 0);
  1948. GPR_ASSERT(strcmp(request->hdrs[1].value,
  1949. "Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=") == 0);
  1950. }
  1951. void validate_external_account_creds_token_exchage_request_with_url_encode(
  1952. const grpc_http_request* request, const char* host, const char* path,
  1953. const char* body, size_t body_size, bool /*expect_actor_token*/) {
  1954. // Check that the body is constructed properly.
  1955. GPR_ASSERT(body != nullptr);
  1956. GPR_ASSERT(body_size != 0);
  1957. GPR_ASSERT(
  1958. strcmp(
  1959. std::string(body, body_size).c_str(),
  1960. "audience=audience_!%40%23%24&grant_type=urn%3Aietf%3Aparams%3Aoauth%"
  1961. "3Agrant-type%3Atoken-exchange&requested_token_type=urn%3Aietf%"
  1962. "3Aparams%3Aoauth%3Atoken-type%3Aaccess_token&subject_token_type="
  1963. "subject_token_type_!%40%23%24&subject_token=test_subject_token&"
  1964. "scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform&"
  1965. "options=%7B%7D") == 0);
  1966. // Check the rest of the request.
  1967. GPR_ASSERT(strcmp(host, "foo.com:5555") == 0);
  1968. GPR_ASSERT(strcmp(path, "/token_url_encode") == 0);
  1969. GPR_ASSERT(request->hdr_count == 2);
  1970. GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0);
  1971. GPR_ASSERT(
  1972. strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded") == 0);
  1973. GPR_ASSERT(strcmp(request->hdrs[1].key, "Authorization") == 0);
  1974. GPR_ASSERT(strcmp(request->hdrs[1].value,
  1975. "Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=") == 0);
  1976. }
  1977. void validate_external_account_creds_service_account_impersonation_request(
  1978. const grpc_http_request* request, const char* host, const char* path,
  1979. const char* body, size_t body_size, bool /*expect_actor_token*/) {
  1980. // Check that the body is constructed properly.
  1981. GPR_ASSERT(body != nullptr);
  1982. GPR_ASSERT(body_size != 0);
  1983. GPR_ASSERT(strcmp(body, "scope=scope_1 scope_2") == 0);
  1984. // Check the rest of the request.
  1985. GPR_ASSERT(strcmp(host, "foo.com:5555") == 0);
  1986. GPR_ASSERT(strcmp(path, "/service_account_impersonation") == 0);
  1987. GPR_ASSERT(request->hdr_count == 2);
  1988. GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0);
  1989. GPR_ASSERT(
  1990. strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded") == 0);
  1991. GPR_ASSERT(strcmp(request->hdrs[1].key, "Authorization") == 0);
  1992. GPR_ASSERT(strcmp(request->hdrs[1].value,
  1993. "Bearer token_exchange_access_token") == 0);
  1994. }
  1995. int external_account_creds_httpcli_post_success(
  1996. const grpc_http_request* request, const char* host, const char* path,
  1997. const char* body, size_t body_size, Timestamp /*deadline*/,
  1998. grpc_closure* on_done, grpc_http_response* response) {
  1999. if (strcmp(path, "/token") == 0) {
  2000. validate_external_account_creds_token_exchage_request(
  2001. request, host, path, body, body_size, true);
  2002. *response = http_response(
  2003. 200, valid_external_account_creds_token_exchange_response);
  2004. } else if (strcmp(path, "/service_account_impersonation") == 0) {
  2005. validate_external_account_creds_service_account_impersonation_request(
  2006. request, host, path, body, body_size, true);
  2007. *response = http_response(
  2008. 200,
  2009. valid_external_account_creds_service_account_impersonation_response);
  2010. } else if (strcmp(path, "/token_url_encode") == 0) {
  2011. validate_external_account_creds_token_exchage_request_with_url_encode(
  2012. request, host, path, body, body_size, true);
  2013. *response = http_response(
  2014. 200, valid_external_account_creds_token_exchange_response);
  2015. }
  2016. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  2017. return 1;
  2018. }
  2019. int external_account_creds_httpcli_post_failure_token_exchange_response_missing_access_token(
  2020. const grpc_http_request* /*request*/, const char* /*host*/,
  2021. const char* path, const char* /*body*/, size_t /*body_size*/,
  2022. Timestamp /*deadline*/, grpc_closure* on_done,
  2023. grpc_http_response* response) {
  2024. if (strcmp(path, "/token") == 0) {
  2025. *response = http_response(200,
  2026. "{\"not_access_token\":\"not_access_token\","
  2027. "\"expires_in\":3599,"
  2028. " \"token_type\":\"Bearer\"}");
  2029. } else if (strcmp(path, "/service_account_impersonation") == 0) {
  2030. *response = http_response(
  2031. 200,
  2032. valid_external_account_creds_service_account_impersonation_response);
  2033. }
  2034. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  2035. return 1;
  2036. }
  2037. int url_external_account_creds_httpcli_get_success(
  2038. const grpc_http_request* /*request*/, const char* /*host*/,
  2039. const char* path, Timestamp /*deadline*/, grpc_closure* on_done,
  2040. grpc_http_response* response) {
  2041. if (strcmp(path, "/generate_subject_token_format_text") == 0) {
  2042. *response = http_response(
  2043. 200,
  2044. valid_url_external_account_creds_retrieve_subject_token_response_format_text);
  2045. } else if (strcmp(path, "/path/to/url/creds?p1=v1&p2=v2") == 0) {
  2046. *response = http_response(
  2047. 200,
  2048. valid_url_external_account_creds_retrieve_subject_token_response_format_text);
  2049. } else if (strcmp(path, "/generate_subject_token_format_json") == 0) {
  2050. *response = http_response(
  2051. 200,
  2052. valid_url_external_account_creds_retrieve_subject_token_response_format_json);
  2053. }
  2054. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  2055. return 1;
  2056. }
  2057. void validate_aws_external_account_creds_token_exchage_request(
  2058. const grpc_http_request* request, const char* host, const char* path,
  2059. const char* body, size_t body_size, bool /*expect_actor_token*/) {
  2060. // Check that the body is constructed properly.
  2061. GPR_ASSERT(body != nullptr);
  2062. GPR_ASSERT(body_size != 0);
  2063. // Check that the regional_cred_verification_url got constructed
  2064. // with the correct AWS Region ("test_regionz" or "test_region").
  2065. GPR_ASSERT(strstr(body, "regional_cred_verification_url_test_region"));
  2066. std::string get_url_equivalent =
  2067. absl::StrFormat("%s?%s", "https://foo.com:5555/token", body);
  2068. absl::StatusOr<URI> uri = URI::Parse(get_url_equivalent);
  2069. GPR_ASSERT(uri.ok());
  2070. assert_query_parameters(*uri, "audience", "audience");
  2071. assert_query_parameters(*uri, "grant_type",
  2072. "urn:ietf:params:oauth:grant-type:token-exchange");
  2073. assert_query_parameters(*uri, "requested_token_type",
  2074. "urn:ietf:params:oauth:token-type:access_token");
  2075. assert_query_parameters(*uri, "subject_token_type", "subject_token_type");
  2076. assert_query_parameters(*uri, "scope",
  2077. "https://www.googleapis.com/auth/cloud-platform");
  2078. // Check the rest of the request.
  2079. GPR_ASSERT(strcmp(host, "foo.com:5555") == 0);
  2080. GPR_ASSERT(strcmp(path, "/token") == 0);
  2081. GPR_ASSERT(request->hdr_count == 2);
  2082. GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0);
  2083. GPR_ASSERT(
  2084. strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded") == 0);
  2085. GPR_ASSERT(strcmp(request->hdrs[1].key, "Authorization") == 0);
  2086. GPR_ASSERT(strcmp(request->hdrs[1].value,
  2087. "Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=") == 0);
  2088. }
  2089. int aws_external_account_creds_httpcli_get_success(
  2090. const grpc_http_request* /*request*/, const char* /*host*/,
  2091. const char* path, Timestamp /*deadline*/, grpc_closure* on_done,
  2092. grpc_http_response* response) {
  2093. if (strcmp(path, "/region_url") == 0) {
  2094. *response = http_response(200, "test_regionz");
  2095. } else if (strcmp(path, "/url") == 0) {
  2096. *response = http_response(200, "test_role_name");
  2097. } else if (strcmp(path, "/url_no_role_name") == 0) {
  2098. *response = http_response(200, "");
  2099. } else if (strcmp(path, "/url/test_role_name") == 0) {
  2100. *response = http_response(
  2101. 200, valid_aws_external_account_creds_retrieve_signing_keys_response);
  2102. }
  2103. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  2104. return 1;
  2105. }
  2106. int aws_external_account_creds_httpcli_post_success(
  2107. const grpc_http_request* request, const char* host, const char* path,
  2108. const char* body, size_t body_size, Timestamp /*deadline*/,
  2109. grpc_closure* on_done, grpc_http_response* response) {
  2110. if (strcmp(path, "/token") == 0) {
  2111. validate_aws_external_account_creds_token_exchage_request(
  2112. request, host, path, body, body_size, true);
  2113. *response = http_response(
  2114. 200, valid_external_account_creds_token_exchange_response);
  2115. }
  2116. ExecCtx::Run(DEBUG_LOCATION, on_done, GRPC_ERROR_NONE);
  2117. return 1;
  2118. }
  2119. // The subclass of ExternalAccountCredentials for testing.
  2120. // ExternalAccountCredentials is an abstract class so we can't directly test
  2121. // against it.
  2122. class TestExternalAccountCredentials final : public ExternalAccountCredentials {
  2123. public:
  2124. TestExternalAccountCredentials(Options options,
  2125. std::vector<std::string> scopes)
  2126. : ExternalAccountCredentials(std::move(options), std::move(scopes)) {}
  2127. protected:
  2128. void RetrieveSubjectToken(
  2129. HTTPRequestContext* /*ctx*/, const Options& /*options*/,
  2130. std::function<void(std::string, grpc_error_handle)> cb) override {
  2131. cb("test_subject_token", GRPC_ERROR_NONE);
  2132. }
  2133. };
  2134. TEST(CredentialsTest, TestExternalAccountCredsSuccess) {
  2135. ExecCtx exec_ctx;
  2136. Json credential_source("");
  2137. TestExternalAccountCredentials::Options options = {
  2138. "external_account", // type;
  2139. "audience", // audience;
  2140. "subject_token_type", // subject_token_type;
  2141. "", // service_account_impersonation_url;
  2142. "https://foo.com:5555/token", // token_url;
  2143. "https://foo.com:5555/token_info", // token_info_url;
  2144. credential_source, // credential_source;
  2145. "quota_project_id", // quota_project_id;
  2146. "client_id", // client_id;
  2147. "client_secret", // client_secret;
  2148. "", // workforce_pool_user_project;
  2149. };
  2150. TestExternalAccountCredentials creds(options, {});
  2151. /* Check security level. */
  2152. GPR_ASSERT(creds.min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2153. /* First request: http put should be called. */
  2154. auto state = RequestMetadataState::NewInstance(
  2155. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2156. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  2157. external_account_creds_httpcli_post_success);
  2158. state->RunRequestMetadataTest(&creds, kTestUrlScheme, kTestAuthority,
  2159. kTestPath);
  2160. ExecCtx::Get()->Flush();
  2161. /* Second request: the cached token should be served directly. */
  2162. state = RequestMetadataState::NewInstance(
  2163. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2164. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  2165. httpcli_post_should_not_be_called);
  2166. state->RunRequestMetadataTest(&creds, kTestUrlScheme, kTestAuthority,
  2167. kTestPath);
  2168. ExecCtx::Get()->Flush();
  2169. HttpRequest::SetOverride(nullptr, nullptr);
  2170. }
  2171. TEST(CredentialsTest, TestExternalAccountCredsSuccessWithUrlEncode) {
  2172. std::map<std::string, std::string> emd = {
  2173. {"authorization", "Bearer token_exchange_access_token"}};
  2174. ExecCtx exec_ctx;
  2175. Json credential_source("");
  2176. TestExternalAccountCredentials::Options options = {
  2177. "external_account", // type;
  2178. "audience_!@#$", // audience;
  2179. "subject_token_type_!@#$", // subject_token_type;
  2180. "", // service_account_impersonation_url;
  2181. "https://foo.com:5555/token_url_encode", // token_url;
  2182. "https://foo.com:5555/token_info", // token_info_url;
  2183. credential_source, // credential_source;
  2184. "quota_project_id", // quota_project_id;
  2185. "client_id", // client_id;
  2186. "client_secret", // client_secret;
  2187. "", // workforce_pool_user_project;
  2188. };
  2189. TestExternalAccountCredentials creds(options, {});
  2190. auto state = RequestMetadataState::NewInstance(
  2191. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2192. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  2193. external_account_creds_httpcli_post_success);
  2194. state->RunRequestMetadataTest(&creds, kTestUrlScheme, kTestAuthority,
  2195. kTestPath);
  2196. ExecCtx::Get()->Flush();
  2197. HttpRequest::SetOverride(nullptr, nullptr);
  2198. }
  2199. TEST(CredentialsTest,
  2200. TestExternalAccountCredsSuccessWithServiceAccountImpersonation) {
  2201. ExecCtx exec_ctx;
  2202. Json credential_source("");
  2203. TestExternalAccountCredentials::Options options = {
  2204. "external_account", // type;
  2205. "audience", // audience;
  2206. "subject_token_type", // subject_token_type;
  2207. "https://foo.com:5555/service_account_impersonation", // service_account_impersonation_url;
  2208. "https://foo.com:5555/token", // token_url;
  2209. "https://foo.com:5555/token_info", // token_info_url;
  2210. credential_source, // credential_source;
  2211. "quota_project_id", // quota_project_id;
  2212. "client_id", // client_id;
  2213. "client_secret", // client_secret;
  2214. "", // workforce_pool_user_project;
  2215. };
  2216. TestExternalAccountCredentials creds(options, {"scope_1", "scope_2"});
  2217. /* Check security level. */
  2218. GPR_ASSERT(creds.min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2219. /* First request: http put should be called. */
  2220. auto state = RequestMetadataState::NewInstance(
  2221. GRPC_ERROR_NONE,
  2222. "authorization: Bearer service_account_impersonation_access_token");
  2223. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  2224. external_account_creds_httpcli_post_success);
  2225. state->RunRequestMetadataTest(&creds, kTestUrlScheme, kTestAuthority,
  2226. kTestPath);
  2227. ExecCtx::Get()->Flush();
  2228. HttpRequest::SetOverride(nullptr, nullptr);
  2229. }
  2230. TEST(CredentialsTest, TestExternalAccountCredsFailureInvalidTokenUrl) {
  2231. ExecCtx exec_ctx;
  2232. Json credential_source("");
  2233. TestExternalAccountCredentials::Options options = {
  2234. "external_account", // type;
  2235. "audience", // audience;
  2236. "subject_token_type", // subject_token_type;
  2237. "https://foo.com:5555/service_account_impersonation", // service_account_impersonation_url;
  2238. "invalid_token_url", // token_url;
  2239. "https://foo.com:5555/token_info", // token_info_url;
  2240. credential_source, // credential_source;
  2241. "quota_project_id", // quota_project_id;
  2242. "client_id", // client_id;
  2243. "client_secret", // client_secret;
  2244. "", // workforce_pool_user_project;
  2245. };
  2246. TestExternalAccountCredentials creds(options, {});
  2247. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  2248. httpcli_post_should_not_be_called);
  2249. grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  2250. "Invalid token url: invalid_token_url.");
  2251. grpc_error_handle expected_error =
  2252. GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
  2253. "Error occurred when fetching oauth2 token.", &error, 1);
  2254. auto state = RequestMetadataState::NewInstance(expected_error, {});
  2255. state->RunRequestMetadataTest(&creds, kTestUrlScheme, kTestAuthority,
  2256. kTestPath);
  2257. GRPC_ERROR_UNREF(error);
  2258. ExecCtx::Get()->Flush();
  2259. HttpRequest::SetOverride(nullptr, nullptr);
  2260. }
  2261. TEST(CredentialsTest,
  2262. TestExternalAccountCredsFailureInvalidServiceAccountImpersonationUrl) {
  2263. ExecCtx exec_ctx;
  2264. Json credential_source("");
  2265. TestExternalAccountCredentials::Options options = {
  2266. "external_account", // type;
  2267. "audience", // audience;
  2268. "subject_token_type", // subject_token_type;
  2269. "invalid_service_account_impersonation_url", // service_account_impersonation_url;
  2270. "https://foo.com:5555/token", // token_url;
  2271. "https://foo.com:5555/token_info", // token_info_url;
  2272. credential_source, // credential_source;
  2273. "quota_project_id", // quota_project_id;
  2274. "client_id", // client_id;
  2275. "client_secret", // client_secret;
  2276. "", // workforce_pool_user_project;
  2277. };
  2278. TestExternalAccountCredentials creds(options, {});
  2279. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  2280. external_account_creds_httpcli_post_success);
  2281. grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  2282. "Invalid service account impersonation url: "
  2283. "invalid_service_account_impersonation_url.");
  2284. grpc_error_handle expected_error =
  2285. GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
  2286. "Error occurred when fetching oauth2 token.", &error, 1);
  2287. auto state = RequestMetadataState::NewInstance(expected_error, {});
  2288. state->RunRequestMetadataTest(&creds, kTestUrlScheme, kTestAuthority,
  2289. kTestPath);
  2290. GRPC_ERROR_UNREF(error);
  2291. ExecCtx::Get()->Flush();
  2292. HttpRequest::SetOverride(nullptr, nullptr);
  2293. }
  2294. TEST(CredentialsTest,
  2295. TestExternalAccountCredsFailureTokenExchangeResponseMissingAccessToken) {
  2296. ExecCtx exec_ctx;
  2297. Json credential_source("");
  2298. TestExternalAccountCredentials::Options options = {
  2299. "external_account", // type;
  2300. "audience", // audience;
  2301. "subject_token_type", // subject_token_type;
  2302. "https://foo.com:5555/service_account_impersonation", // service_account_impersonation_url;
  2303. "https://foo.com:5555/token", // token_url;
  2304. "https://foo.com:5555/token_info", // token_info_url;
  2305. credential_source, // credential_source;
  2306. "quota_project_id", // quota_project_id;
  2307. "client_id", // client_id;
  2308. "client_secret", // client_secret;
  2309. "", // workforce_pool_user_project;
  2310. };
  2311. TestExternalAccountCredentials creds(options, {});
  2312. HttpRequest::SetOverride(
  2313. httpcli_get_should_not_be_called,
  2314. external_account_creds_httpcli_post_failure_token_exchange_response_missing_access_token);
  2315. grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  2316. "Missing or invalid access_token in "
  2317. "{\"not_access_token\":\"not_access_token\",\"expires_in\":3599,\"token_"
  2318. "type\":\"Bearer\"}.");
  2319. grpc_error_handle expected_error =
  2320. GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
  2321. "Error occurred when fetching oauth2 token.", &error, 1);
  2322. auto state = RequestMetadataState::NewInstance(expected_error, {});
  2323. state->RunRequestMetadataTest(&creds, kTestUrlScheme, kTestAuthority,
  2324. kTestPath);
  2325. GRPC_ERROR_UNREF(error);
  2326. ExecCtx::Get()->Flush();
  2327. HttpRequest::SetOverride(nullptr, nullptr);
  2328. }
  2329. TEST(CredentialsTest, TestUrlExternalAccountCredsSuccessFormatText) {
  2330. ExecCtx exec_ctx;
  2331. grpc_error_handle error = GRPC_ERROR_NONE;
  2332. Json credential_source = Json::Parse(
  2333. valid_url_external_account_creds_options_credential_source_format_text,
  2334. &error);
  2335. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2336. ExternalAccountCredentials::Options options = {
  2337. "external_account", // type;
  2338. "audience", // audience;
  2339. "subject_token_type", // subject_token_type;
  2340. "", // service_account_impersonation_url;
  2341. "https://foo.com:5555/token", // token_url;
  2342. "https://foo.com:5555/token_info", // token_info_url;
  2343. credential_source, // credential_source;
  2344. "quota_project_id", // quota_project_id;
  2345. "client_id", // client_id;
  2346. "client_secret", // client_secret;
  2347. "", // workforce_pool_user_project;
  2348. };
  2349. auto creds = UrlExternalAccountCredentials::Create(options, {}, &error);
  2350. GPR_ASSERT(creds != nullptr);
  2351. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2352. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2353. auto state = RequestMetadataState::NewInstance(
  2354. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2355. HttpRequest::SetOverride(url_external_account_creds_httpcli_get_success,
  2356. external_account_creds_httpcli_post_success);
  2357. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2358. kTestPath);
  2359. ExecCtx::Get()->Flush();
  2360. HttpRequest::SetOverride(nullptr, nullptr);
  2361. }
  2362. TEST(CredentialsTest,
  2363. TestUrlExternalAccountCredsSuccessWithQureyParamsFormatText) {
  2364. std::map<std::string, std::string> emd = {
  2365. {"authorization", "Bearer token_exchange_access_token"}};
  2366. ExecCtx exec_ctx;
  2367. grpc_error_handle error = GRPC_ERROR_NONE;
  2368. Json credential_source = Json::Parse(
  2369. valid_url_external_account_creds_options_credential_source_with_qurey_params_format_text,
  2370. &error);
  2371. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2372. ExternalAccountCredentials::Options options = {
  2373. "external_account", // type;
  2374. "audience", // audience;
  2375. "subject_token_type", // subject_token_type;
  2376. "", // service_account_impersonation_url;
  2377. "https://foo.com:5555/token", // token_url;
  2378. "https://foo.com:5555/token_info", // token_info_url;
  2379. credential_source, // credential_source;
  2380. "quota_project_id", // quota_project_id;
  2381. "client_id", // client_id;
  2382. "client_secret", // client_secret;
  2383. "", // workforce_pool_user_project;
  2384. };
  2385. auto creds = UrlExternalAccountCredentials::Create(options, {}, &error);
  2386. GPR_ASSERT(creds != nullptr);
  2387. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2388. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2389. auto state = RequestMetadataState::NewInstance(
  2390. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2391. HttpRequest::SetOverride(url_external_account_creds_httpcli_get_success,
  2392. external_account_creds_httpcli_post_success);
  2393. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2394. kTestPath);
  2395. ExecCtx::Get()->Flush();
  2396. HttpRequest::SetOverride(nullptr, nullptr);
  2397. }
  2398. TEST(CredentialsTest, TestUrlExternalAccountCredsSuccessFormatJson) {
  2399. ExecCtx exec_ctx;
  2400. grpc_error_handle error = GRPC_ERROR_NONE;
  2401. Json credential_source = Json::Parse(
  2402. valid_url_external_account_creds_options_credential_source_format_json,
  2403. &error);
  2404. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2405. ExternalAccountCredentials::Options options = {
  2406. "external_account", // type;
  2407. "audience", // audience;
  2408. "subject_token_type", // subject_token_type;
  2409. "", // service_account_impersonation_url;
  2410. "https://foo.com:5555/token", // token_url;
  2411. "https://foo.com:5555/token_info", // token_info_url;
  2412. credential_source, // credential_source;
  2413. "quota_project_id", // quota_project_id;
  2414. "client_id", // client_id;
  2415. "client_secret", // client_secret;
  2416. "", // workforce_pool_user_project;
  2417. };
  2418. auto creds = UrlExternalAccountCredentials::Create(options, {}, &error);
  2419. GPR_ASSERT(creds != nullptr);
  2420. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2421. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2422. auto state = RequestMetadataState::NewInstance(
  2423. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2424. HttpRequest::SetOverride(url_external_account_creds_httpcli_get_success,
  2425. external_account_creds_httpcli_post_success);
  2426. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2427. kTestPath);
  2428. ExecCtx::Get()->Flush();
  2429. HttpRequest::SetOverride(nullptr, nullptr);
  2430. }
  2431. TEST(CredentialsTest,
  2432. TestUrlExternalAccountCredsFailureInvalidCredentialSourceUrl) {
  2433. grpc_error_handle error = GRPC_ERROR_NONE;
  2434. Json credential_source = Json::Parse(
  2435. invalid_url_external_account_creds_options_credential_source, &error);
  2436. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2437. ExternalAccountCredentials::Options options = {
  2438. "external_account", // type;
  2439. "audience", // audience;
  2440. "subject_token_type", // subject_token_type;
  2441. "", // service_account_impersonation_url;
  2442. "https://foo.com:5555/token", // token_url;
  2443. "https://foo.com:5555/token_info", // token_info_url;
  2444. credential_source, // credential_source;
  2445. "quota_project_id", // quota_project_id;
  2446. "client_id", // client_id;
  2447. "client_secret", // client_secret;
  2448. "", // workforce_pool_user_project;
  2449. };
  2450. auto creds = UrlExternalAccountCredentials::Create(options, {}, &error);
  2451. GPR_ASSERT(creds == nullptr);
  2452. std::string actual_error;
  2453. GPR_ASSERT(
  2454. grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error));
  2455. GPR_ASSERT(absl::StartsWith(actual_error, "Invalid credential source url."));
  2456. GRPC_ERROR_UNREF(error);
  2457. }
  2458. TEST(CredentialsTest, TestFileExternalAccountCredsSuccessFormatText) {
  2459. ExecCtx exec_ctx;
  2460. grpc_error_handle error = GRPC_ERROR_NONE;
  2461. char* subject_token_path = write_tmp_jwt_file("test_subject_token");
  2462. Json credential_source = Json::Parse(
  2463. absl::StrFormat(
  2464. "{\"file\":\"%s\"}",
  2465. absl::StrReplaceAll(subject_token_path, {{"\\", "\\\\"}})),
  2466. &error);
  2467. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2468. ExternalAccountCredentials::Options options = {
  2469. "external_account", // type;
  2470. "audience", // audience;
  2471. "subject_token_type", // subject_token_type;
  2472. "", // service_account_impersonation_url;
  2473. "https://foo.com:5555/token", // token_url;
  2474. "https://foo.com:5555/token_info", // token_info_url;
  2475. credential_source, // credential_source;
  2476. "quota_project_id", // quota_project_id;
  2477. "client_id", // client_id;
  2478. "client_secret", // client_secret;
  2479. "", // workforce_pool_user_project;
  2480. };
  2481. auto creds = FileExternalAccountCredentials::Create(options, {}, &error);
  2482. GPR_ASSERT(creds != nullptr);
  2483. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2484. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2485. auto state = RequestMetadataState::NewInstance(
  2486. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2487. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  2488. external_account_creds_httpcli_post_success);
  2489. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2490. kTestPath);
  2491. ExecCtx::Get()->Flush();
  2492. HttpRequest::SetOverride(nullptr, nullptr);
  2493. GRPC_ERROR_UNREF(error);
  2494. gpr_free(subject_token_path);
  2495. }
  2496. TEST(CredentialsTest, TestFileExternalAccountCredsSuccessFormatJson) {
  2497. ExecCtx exec_ctx;
  2498. grpc_error_handle error = GRPC_ERROR_NONE;
  2499. char* subject_token_path =
  2500. write_tmp_jwt_file("{\"access_token\":\"test_subject_token\"}");
  2501. Json credential_source = Json::Parse(
  2502. absl::StrFormat(
  2503. "{\n"
  2504. "\"file\":\"%s\",\n"
  2505. "\"format\":\n"
  2506. "{\n"
  2507. "\"type\":\"json\",\n"
  2508. "\"subject_token_field_name\":\"access_token\"\n"
  2509. "}\n"
  2510. "}",
  2511. absl::StrReplaceAll(subject_token_path, {{"\\", "\\\\"}})),
  2512. &error);
  2513. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2514. ExternalAccountCredentials::Options options = {
  2515. "external_account", // type;
  2516. "audience", // audience;
  2517. "subject_token_type", // subject_token_type;
  2518. "", // service_account_impersonation_url;
  2519. "https://foo.com:5555/token", // token_url;
  2520. "https://foo.com:5555/token_info", // token_info_url;
  2521. credential_source, // credential_source;
  2522. "quota_project_id", // quota_project_id;
  2523. "client_id", // client_id;
  2524. "client_secret", // client_secret;
  2525. "", // workforce_pool_user_project;
  2526. };
  2527. auto creds = FileExternalAccountCredentials::Create(options, {}, &error);
  2528. GPR_ASSERT(creds != nullptr);
  2529. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2530. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2531. auto state = RequestMetadataState::NewInstance(
  2532. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2533. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  2534. external_account_creds_httpcli_post_success);
  2535. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2536. kTestPath);
  2537. ExecCtx::Get()->Flush();
  2538. HttpRequest::SetOverride(nullptr, nullptr);
  2539. GRPC_ERROR_UNREF(error);
  2540. gpr_free(subject_token_path);
  2541. }
  2542. TEST(CredentialsTest, TestFileExternalAccountCredsFailureFileNotFound) {
  2543. ExecCtx exec_ctx;
  2544. grpc_error_handle error = GRPC_ERROR_NONE;
  2545. Json credential_source =
  2546. Json::Parse("{\"file\":\"non_exisiting_file\"}", &error);
  2547. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2548. ExternalAccountCredentials::Options options = {
  2549. "external_account", // type;
  2550. "audience", // audience;
  2551. "subject_token_type", // subject_token_type;
  2552. "", // service_account_impersonation_url;
  2553. "https://foo.com:5555/token", // token_url;
  2554. "https://foo.com:5555/token_info", // token_info_url;
  2555. credential_source, // credential_source;
  2556. "quota_project_id", // quota_project_id;
  2557. "client_id", // client_id;
  2558. "client_secret", // client_secret;
  2559. "", // workforce_pool_user_project;
  2560. };
  2561. auto creds = FileExternalAccountCredentials::Create(options, {}, &error);
  2562. GPR_ASSERT(creds != nullptr);
  2563. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2564. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  2565. httpcli_post_should_not_be_called);
  2566. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to load file");
  2567. grpc_error_handle expected_error =
  2568. GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
  2569. "Error occurred when fetching oauth2 token.", &error, 1);
  2570. auto state = RequestMetadataState::NewInstance(expected_error, {});
  2571. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2572. kTestPath);
  2573. ExecCtx::Get()->Flush();
  2574. HttpRequest::SetOverride(nullptr, nullptr);
  2575. GRPC_ERROR_UNREF(error);
  2576. }
  2577. TEST(CredentialsTest, TestFileExternalAccountCredsFailureInvalidJsonContent) {
  2578. ExecCtx exec_ctx;
  2579. grpc_error_handle error = GRPC_ERROR_NONE;
  2580. char* subject_token_path = write_tmp_jwt_file("not_a_valid_json_file");
  2581. Json credential_source = Json::Parse(
  2582. absl::StrFormat(
  2583. "{\n"
  2584. "\"file\":\"%s\",\n"
  2585. "\"format\":\n"
  2586. "{\n"
  2587. "\"type\":\"json\",\n"
  2588. "\"subject_token_field_name\":\"access_token\"\n"
  2589. "}\n"
  2590. "}",
  2591. absl::StrReplaceAll(subject_token_path, {{"\\", "\\\\"}})),
  2592. &error);
  2593. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2594. ExternalAccountCredentials::Options options = {
  2595. "external_account", // type;
  2596. "audience", // audience;
  2597. "subject_token_type", // subject_token_type;
  2598. "", // service_account_impersonation_url;
  2599. "https://foo.com:5555/token", // token_url;
  2600. "https://foo.com:5555/token_info", // token_info_url;
  2601. credential_source, // credential_source;
  2602. "quota_project_id", // quota_project_id;
  2603. "client_id", // client_id;
  2604. "client_secret", // client_secret;
  2605. "", // workforce_pool_user_project;
  2606. };
  2607. auto creds = FileExternalAccountCredentials::Create(options, {}, &error);
  2608. GPR_ASSERT(creds != nullptr);
  2609. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2610. HttpRequest::SetOverride(httpcli_get_should_not_be_called,
  2611. httpcli_post_should_not_be_called);
  2612. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  2613. "The content of the file is not a valid json object.");
  2614. grpc_error_handle expected_error =
  2615. GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
  2616. "Error occurred when fetching oauth2 token.", &error, 1);
  2617. auto state = RequestMetadataState::NewInstance(expected_error, {});
  2618. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2619. kTestPath);
  2620. ExecCtx::Get()->Flush();
  2621. HttpRequest::SetOverride(nullptr, nullptr);
  2622. GRPC_ERROR_UNREF(error);
  2623. gpr_free(subject_token_path);
  2624. }
  2625. TEST(CredentialsTest, TestAwsExternalAccountCredsSuccess) {
  2626. ExecCtx exec_ctx;
  2627. grpc_error_handle error = GRPC_ERROR_NONE;
  2628. Json credential_source = Json::Parse(
  2629. valid_aws_external_account_creds_options_credential_source, &error);
  2630. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2631. ExternalAccountCredentials::Options options = {
  2632. "external_account", // type;
  2633. "audience", // audience;
  2634. "subject_token_type", // subject_token_type;
  2635. "", // service_account_impersonation_url;
  2636. "https://foo.com:5555/token", // token_url;
  2637. "https://foo.com:5555/token_info", // token_info_url;
  2638. credential_source, // credential_source;
  2639. "quota_project_id", // quota_project_id;
  2640. "client_id", // client_id;
  2641. "client_secret", // client_secret;
  2642. "", // workforce_pool_user_project;
  2643. };
  2644. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  2645. GPR_ASSERT(creds != nullptr);
  2646. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2647. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2648. auto state = RequestMetadataState::NewInstance(
  2649. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2650. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  2651. aws_external_account_creds_httpcli_post_success);
  2652. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2653. kTestPath);
  2654. ExecCtx::Get()->Flush();
  2655. HttpRequest::SetOverride(nullptr, nullptr);
  2656. }
  2657. TEST(CredentialsTest, TestAwsExternalAccountCredsSuccessPathRegionEnvKeysUrl) {
  2658. ExecCtx exec_ctx;
  2659. gpr_setenv("AWS_REGION", "test_regionz");
  2660. grpc_error_handle error = GRPC_ERROR_NONE;
  2661. Json credential_source = Json::Parse(
  2662. valid_aws_external_account_creds_options_credential_source, &error);
  2663. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2664. ExternalAccountCredentials::Options options = {
  2665. "external_account", // type;
  2666. "audience", // audience;
  2667. "subject_token_type", // subject_token_type;
  2668. "", // service_account_impersonation_url;
  2669. "https://foo.com:5555/token", // token_url;
  2670. "https://foo.com:5555/token_info", // token_info_url;
  2671. credential_source, // credential_source;
  2672. "quota_project_id", // quota_project_id;
  2673. "client_id", // client_id;
  2674. "client_secret", // client_secret;
  2675. "", // workforce_pool_user_project;
  2676. };
  2677. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  2678. GPR_ASSERT(creds != nullptr);
  2679. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2680. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2681. auto state = RequestMetadataState::NewInstance(
  2682. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2683. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  2684. aws_external_account_creds_httpcli_post_success);
  2685. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2686. kTestPath);
  2687. ExecCtx::Get()->Flush();
  2688. HttpRequest::SetOverride(nullptr, nullptr);
  2689. gpr_unsetenv("AWS_REGION");
  2690. }
  2691. TEST(CredentialsTest,
  2692. TestAwsExternalAccountCredsSuccessPathDefaultRegionEnvKeysUrl) {
  2693. ExecCtx exec_ctx;
  2694. gpr_setenv("AWS_DEFAULT_REGION", "test_regionz");
  2695. grpc_error_handle error = GRPC_ERROR_NONE;
  2696. Json credential_source = Json::Parse(
  2697. valid_aws_external_account_creds_options_credential_source, &error);
  2698. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2699. ExternalAccountCredentials::Options options = {
  2700. "external_account", // type;
  2701. "audience", // audience;
  2702. "subject_token_type", // subject_token_type;
  2703. "", // service_account_impersonation_url;
  2704. "https://foo.com:5555/token", // token_url;
  2705. "https://foo.com:5555/token_info", // token_info_url;
  2706. credential_source, // credential_source;
  2707. "quota_project_id", // quota_project_id;
  2708. "client_id", // client_id;
  2709. "client_secret", // client_secret;
  2710. "", // workforce_pool_user_project;
  2711. };
  2712. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  2713. GPR_ASSERT(creds != nullptr);
  2714. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2715. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2716. auto state = RequestMetadataState::NewInstance(
  2717. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2718. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  2719. aws_external_account_creds_httpcli_post_success);
  2720. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2721. kTestPath);
  2722. ExecCtx::Get()->Flush();
  2723. HttpRequest::SetOverride(nullptr, nullptr);
  2724. gpr_unsetenv("AWS_DEFAULT_REGION");
  2725. }
  2726. TEST(CredentialsTest,
  2727. TestAwsExternalAccountCredsSuccessPathDuplicateRegionEnvKeysUrl) {
  2728. ExecCtx exec_ctx;
  2729. // Make sure that AWS_REGION gets used over AWS_DEFAULT_REGION
  2730. gpr_setenv("AWS_REGION", "test_regionz");
  2731. gpr_setenv("AWS_DEFAULT_REGION", "ERROR_REGION");
  2732. grpc_error_handle error = GRPC_ERROR_NONE;
  2733. Json credential_source = Json::Parse(
  2734. valid_aws_external_account_creds_options_credential_source, &error);
  2735. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2736. ExternalAccountCredentials::Options options = {
  2737. "external_account", // type;
  2738. "audience", // audience;
  2739. "subject_token_type", // subject_token_type;
  2740. "", // service_account_impersonation_url;
  2741. "https://foo.com:5555/token", // token_url;
  2742. "https://foo.com:5555/token_info", // token_info_url;
  2743. credential_source, // credential_source;
  2744. "quota_project_id", // quota_project_id;
  2745. "client_id", // client_id;
  2746. "client_secret", // client_secret;
  2747. "", // workforce_pool_user_project;
  2748. };
  2749. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  2750. GPR_ASSERT(creds != nullptr);
  2751. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2752. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2753. auto state = RequestMetadataState::NewInstance(
  2754. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2755. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  2756. aws_external_account_creds_httpcli_post_success);
  2757. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2758. kTestPath);
  2759. ExecCtx::Get()->Flush();
  2760. HttpRequest::SetOverride(nullptr, nullptr);
  2761. gpr_unsetenv("AWS_REGION");
  2762. gpr_unsetenv("AWS_DEFAULT_REGION");
  2763. }
  2764. TEST(CredentialsTest, TestAwsExternalAccountCredsSuccessPathRegionUrlKeysEnv) {
  2765. ExecCtx exec_ctx;
  2766. gpr_setenv("AWS_ACCESS_KEY_ID", "test_access_key_id");
  2767. gpr_setenv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key");
  2768. gpr_setenv("AWS_SESSION_TOKEN", "test_token");
  2769. grpc_error_handle error = GRPC_ERROR_NONE;
  2770. Json credential_source = Json::Parse(
  2771. valid_aws_external_account_creds_options_credential_source, &error);
  2772. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2773. ExternalAccountCredentials::Options options = {
  2774. "external_account", // type;
  2775. "audience", // audience;
  2776. "subject_token_type", // subject_token_type;
  2777. "", // service_account_impersonation_url;
  2778. "https://foo.com:5555/token", // token_url;
  2779. "https://foo.com:5555/token_info", // token_info_url;
  2780. credential_source, // credential_source;
  2781. "quota_project_id", // quota_project_id;
  2782. "client_id", // client_id;
  2783. "client_secret", // client_secret;
  2784. "", // workforce_pool_user_project;
  2785. };
  2786. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  2787. GPR_ASSERT(creds != nullptr);
  2788. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2789. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2790. auto state = RequestMetadataState::NewInstance(
  2791. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2792. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  2793. aws_external_account_creds_httpcli_post_success);
  2794. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2795. kTestPath);
  2796. ExecCtx::Get()->Flush();
  2797. HttpRequest::SetOverride(nullptr, nullptr);
  2798. gpr_unsetenv("AWS_ACCESS_KEY_ID");
  2799. gpr_unsetenv("AWS_SECRET_ACCESS_KEY");
  2800. gpr_unsetenv("AWS_SESSION_TOKEN");
  2801. }
  2802. TEST(CredentialsTest, TestAwsExternalAccountCredsSuccessPathRegionEnvKeysEnv) {
  2803. ExecCtx exec_ctx;
  2804. gpr_setenv("AWS_REGION", "test_regionz");
  2805. gpr_setenv("AWS_ACCESS_KEY_ID", "test_access_key_id");
  2806. gpr_setenv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key");
  2807. gpr_setenv("AWS_SESSION_TOKEN", "test_token");
  2808. grpc_error_handle error = GRPC_ERROR_NONE;
  2809. Json credential_source = Json::Parse(
  2810. valid_aws_external_account_creds_options_credential_source, &error);
  2811. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2812. ExternalAccountCredentials::Options options = {
  2813. "external_account", // type;
  2814. "audience", // audience;
  2815. "subject_token_type", // subject_token_type;
  2816. "", // service_account_impersonation_url;
  2817. "https://foo.com:5555/token", // token_url;
  2818. "https://foo.com:5555/token_info", // token_info_url;
  2819. credential_source, // credential_source;
  2820. "quota_project_id", // quota_project_id;
  2821. "client_id", // client_id;
  2822. "client_secret", // client_secret;
  2823. "", // workforce_pool_user_project;
  2824. };
  2825. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  2826. GPR_ASSERT(creds != nullptr);
  2827. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2828. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2829. auto state = RequestMetadataState::NewInstance(
  2830. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2831. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  2832. aws_external_account_creds_httpcli_post_success);
  2833. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2834. kTestPath);
  2835. ExecCtx::Get()->Flush();
  2836. HttpRequest::SetOverride(nullptr, nullptr);
  2837. gpr_unsetenv("AWS_REGION");
  2838. gpr_unsetenv("AWS_ACCESS_KEY_ID");
  2839. gpr_unsetenv("AWS_SECRET_ACCESS_KEY");
  2840. gpr_unsetenv("AWS_SESSION_TOKEN");
  2841. }
  2842. TEST(CredentialsTest,
  2843. TestAwsExternalAccountCredsSuccessPathDefaultRegionEnvKeysEnv) {
  2844. std::map<std::string, std::string> emd = {
  2845. {"authorization", "Bearer token_exchange_access_token"}};
  2846. ExecCtx exec_ctx;
  2847. gpr_setenv("AWS_DEFAULT_REGION", "test_regionz");
  2848. gpr_setenv("AWS_ACCESS_KEY_ID", "test_access_key_id");
  2849. gpr_setenv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key");
  2850. gpr_setenv("AWS_SESSION_TOKEN", "test_token");
  2851. grpc_error_handle error = GRPC_ERROR_NONE;
  2852. Json credential_source = Json::Parse(
  2853. valid_aws_external_account_creds_options_credential_source, &error);
  2854. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2855. ExternalAccountCredentials::Options options = {
  2856. "external_account", // type;
  2857. "audience", // audience;
  2858. "subject_token_type", // subject_token_type;
  2859. "", // service_account_impersonation_url;
  2860. "https://foo.com:5555/token", // token_url;
  2861. "https://foo.com:5555/token_info", // token_info_url;
  2862. credential_source, // credential_source;
  2863. "quota_project_id", // quota_project_id;
  2864. "client_id", // client_id;
  2865. "client_secret", // client_secret;
  2866. "", // workforce_pool_user_project;
  2867. };
  2868. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  2869. GPR_ASSERT(creds != nullptr);
  2870. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2871. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2872. auto state = RequestMetadataState::NewInstance(
  2873. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2874. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  2875. aws_external_account_creds_httpcli_post_success);
  2876. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2877. kTestPath);
  2878. ExecCtx::Get()->Flush();
  2879. HttpRequest::SetOverride(nullptr, nullptr);
  2880. gpr_unsetenv("AWS_DEFAULT_REGION");
  2881. gpr_unsetenv("AWS_ACCESS_KEY_ID");
  2882. gpr_unsetenv("AWS_SECRET_ACCESS_KEY");
  2883. gpr_unsetenv("AWS_SESSION_TOKEN");
  2884. }
  2885. TEST(CredentialsTest,
  2886. TestAwsExternalAccountCredsSuccessPathDuplicateRegionEnvKeysEnv) {
  2887. ExecCtx exec_ctx;
  2888. // Make sure that AWS_REGION gets used over AWS_DEFAULT_REGION
  2889. gpr_setenv("AWS_REGION", "test_regionz");
  2890. gpr_setenv("AWS_DEFAULT_REGION", "ERROR_REGION");
  2891. gpr_setenv("AWS_ACCESS_KEY_ID", "test_access_key_id");
  2892. gpr_setenv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key");
  2893. gpr_setenv("AWS_SESSION_TOKEN", "test_token");
  2894. grpc_error_handle error = GRPC_ERROR_NONE;
  2895. Json credential_source = Json::Parse(
  2896. valid_aws_external_account_creds_options_credential_source, &error);
  2897. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2898. ExternalAccountCredentials::Options options = {
  2899. "external_account", // type;
  2900. "audience", // audience;
  2901. "subject_token_type", // subject_token_type;
  2902. "", // service_account_impersonation_url;
  2903. "https://foo.com:5555/token", // token_url;
  2904. "https://foo.com:5555/token_info", // token_info_url;
  2905. credential_source, // credential_source;
  2906. "quota_project_id", // quota_project_id;
  2907. "client_id", // client_id;
  2908. "client_secret", // client_secret;
  2909. "", // workforce_pool_user_project;
  2910. };
  2911. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  2912. GPR_ASSERT(creds != nullptr);
  2913. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2914. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2915. auto state = RequestMetadataState::NewInstance(
  2916. GRPC_ERROR_NONE, "authorization: Bearer token_exchange_access_token");
  2917. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  2918. aws_external_account_creds_httpcli_post_success);
  2919. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2920. kTestPath);
  2921. ExecCtx::Get()->Flush();
  2922. HttpRequest::SetOverride(nullptr, nullptr);
  2923. gpr_unsetenv("AWS_REGION");
  2924. gpr_unsetenv("AWS_DEFAULT_REGION");
  2925. gpr_unsetenv("AWS_ACCESS_KEY_ID");
  2926. gpr_unsetenv("AWS_SECRET_ACCESS_KEY");
  2927. gpr_unsetenv("AWS_SESSION_TOKEN");
  2928. }
  2929. TEST(CredentialsTest,
  2930. TestAwsExternalAccountCredsFailureUnmatchedEnvironmentId) {
  2931. grpc_error_handle error = GRPC_ERROR_NONE;
  2932. Json credential_source = Json::Parse(
  2933. invalid_aws_external_account_creds_options_credential_source_unmatched_environment_id,
  2934. &error);
  2935. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2936. ExternalAccountCredentials::Options options = {
  2937. "external_account", // type;
  2938. "audience", // audience;
  2939. "subject_token_type", // subject_token_type;
  2940. "", // service_account_impersonation_url;
  2941. "https://foo.com:5555/token", // token_url;
  2942. "https://foo.com:5555/token_info", // token_info_url;
  2943. credential_source, // credential_source;
  2944. "quota_project_id", // quota_project_id;
  2945. "client_id", // client_id;
  2946. "client_secret", // client_secret;
  2947. "", // workforce_pool_user_project;
  2948. };
  2949. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  2950. GPR_ASSERT(creds == nullptr);
  2951. std::string expected_error = "environment_id does not match.";
  2952. std::string actual_error;
  2953. GPR_ASSERT(
  2954. grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error));
  2955. GPR_ASSERT(expected_error == actual_error);
  2956. GRPC_ERROR_UNREF(error);
  2957. }
  2958. TEST(CredentialsTest, TestAwsExternalAccountCredsFailureInvalidRegionUrl) {
  2959. ExecCtx exec_ctx;
  2960. grpc_error_handle error = GRPC_ERROR_NONE;
  2961. Json credential_source = Json::Parse(
  2962. invalid_aws_external_account_creds_options_credential_source_invalid_region_url,
  2963. &error);
  2964. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2965. ExternalAccountCredentials::Options options = {
  2966. "external_account", // type;
  2967. "audience", // audience;
  2968. "subject_token_type", // subject_token_type;
  2969. "", // service_account_impersonation_url;
  2970. "https://foo.com:5555/token", // token_url;
  2971. "https://foo.com:5555/token_info", // token_info_url;
  2972. credential_source, // credential_source;
  2973. "quota_project_id", // quota_project_id;
  2974. "client_id", // client_id;
  2975. "client_secret", // client_secret;
  2976. "", // workforce_pool_user_project;
  2977. };
  2978. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  2979. GPR_ASSERT(creds != nullptr);
  2980. GPR_ASSERT(error == GRPC_ERROR_NONE);
  2981. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  2982. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  2983. "Invalid region url: invalid_region_url.");
  2984. grpc_error_handle expected_error =
  2985. GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
  2986. "Error occurred when fetching oauth2 token.", &error, 1);
  2987. auto state = RequestMetadataState::NewInstance(expected_error, {});
  2988. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  2989. aws_external_account_creds_httpcli_post_success);
  2990. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  2991. kTestPath);
  2992. ExecCtx::Get()->Flush();
  2993. HttpRequest::SetOverride(nullptr, nullptr);
  2994. GRPC_ERROR_UNREF(error);
  2995. }
  2996. TEST(CredentialsTest, TestAwsExternalAccountCredsFailureInvalidUrl) {
  2997. ExecCtx exec_ctx;
  2998. grpc_error_handle error = GRPC_ERROR_NONE;
  2999. Json credential_source = Json::Parse(
  3000. invalid_aws_external_account_creds_options_credential_source_invalid_url,
  3001. &error);
  3002. GPR_ASSERT(error == GRPC_ERROR_NONE);
  3003. ExternalAccountCredentials::Options options = {
  3004. "external_account", // type;
  3005. "audience", // audience;
  3006. "subject_token_type", // subject_token_type;
  3007. "", // service_account_impersonation_url;
  3008. "https://foo.com:5555/token", // token_url;
  3009. "https://foo.com:5555/token_info", // token_info_url;
  3010. credential_source, // credential_source;
  3011. "quota_project_id", // quota_project_id;
  3012. "client_id", // client_id;
  3013. "client_secret", // client_secret;
  3014. "", // workforce_pool_user_project;
  3015. };
  3016. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  3017. GPR_ASSERT(creds != nullptr);
  3018. GPR_ASSERT(error == GRPC_ERROR_NONE);
  3019. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  3020. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Invalid url: invalid_url.");
  3021. grpc_error_handle expected_error =
  3022. GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
  3023. "Error occurred when fetching oauth2 token.", &error, 1);
  3024. auto state = RequestMetadataState::NewInstance(expected_error, {});
  3025. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  3026. aws_external_account_creds_httpcli_post_success);
  3027. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  3028. kTestPath);
  3029. ExecCtx::Get()->Flush();
  3030. HttpRequest::SetOverride(nullptr, nullptr);
  3031. GRPC_ERROR_UNREF(error);
  3032. }
  3033. TEST(CredentialsTest, TestAwsExternalAccountCredsFailureMissingRoleName) {
  3034. ExecCtx exec_ctx;
  3035. grpc_error_handle error = GRPC_ERROR_NONE;
  3036. Json credential_source = Json::Parse(
  3037. invalid_aws_external_account_creds_options_credential_source_missing_role_name,
  3038. &error);
  3039. GPR_ASSERT(error == GRPC_ERROR_NONE);
  3040. ExternalAccountCredentials::Options options = {
  3041. "external_account", // type;
  3042. "audience", // audience;
  3043. "subject_token_type", // subject_token_type;
  3044. "", // service_account_impersonation_url;
  3045. "https://foo.com:5555/token", // token_url;
  3046. "https://foo.com:5555/token_info", // token_info_url;
  3047. credential_source, // credential_source;
  3048. "quota_project_id", // quota_project_id;
  3049. "client_id", // client_id;
  3050. "client_secret", // client_secret;
  3051. "", // workforce_pool_user_project;
  3052. };
  3053. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  3054. GPR_ASSERT(creds != nullptr);
  3055. GPR_ASSERT(error == GRPC_ERROR_NONE);
  3056. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  3057. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  3058. "Missing role name when retrieving signing keys.");
  3059. grpc_error_handle expected_error =
  3060. GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
  3061. "Error occurred when fetching oauth2 token.", &error, 1);
  3062. auto state = RequestMetadataState::NewInstance(expected_error, {});
  3063. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  3064. aws_external_account_creds_httpcli_post_success);
  3065. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  3066. kTestPath);
  3067. ExecCtx::Get()->Flush();
  3068. HttpRequest::SetOverride(nullptr, nullptr);
  3069. GRPC_ERROR_UNREF(error);
  3070. }
  3071. TEST(CredentialsTest,
  3072. TestAwsExternalAccountCredsFailureInvalidRegionalCredVerificationUrl) {
  3073. ExecCtx exec_ctx;
  3074. grpc_error_handle error = GRPC_ERROR_NONE;
  3075. Json credential_source = Json::Parse(
  3076. invalid_aws_external_account_creds_options_credential_source_invalid_regional_cred_verification_url,
  3077. &error);
  3078. GPR_ASSERT(error == GRPC_ERROR_NONE);
  3079. ExternalAccountCredentials::Options options = {
  3080. "external_account", // type;
  3081. "audience", // audience;
  3082. "subject_token_type", // subject_token_type;
  3083. "", // service_account_impersonation_url;
  3084. "https://foo.com:5555/token", // token_url;
  3085. "https://foo.com:5555/token_info", // token_info_url;
  3086. credential_source, // credential_source;
  3087. "quota_project_id", // quota_project_id;
  3088. "client_id", // client_id;
  3089. "client_secret", // client_secret;
  3090. "", // workforce_pool_user_project;
  3091. };
  3092. auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
  3093. GPR_ASSERT(creds != nullptr);
  3094. GPR_ASSERT(error == GRPC_ERROR_NONE);
  3095. GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
  3096. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
  3097. "Creating aws request signer failed.");
  3098. grpc_error_handle expected_error =
  3099. GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
  3100. "Error occurred when fetching oauth2 token.", &error, 1);
  3101. auto state = RequestMetadataState::NewInstance(expected_error, {});
  3102. HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
  3103. aws_external_account_creds_httpcli_post_success);
  3104. state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
  3105. kTestPath);
  3106. ExecCtx::Get()->Flush();
  3107. HttpRequest::SetOverride(nullptr, nullptr);
  3108. GRPC_ERROR_UNREF(error);
  3109. }
  3110. TEST(CredentialsTest, TestExternalAccountCredentialsCreateSuccess) {
  3111. // url credentials
  3112. const char* url_options_string =
  3113. "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_"
  3114. "token_type\":\"subject_token_type\",\"service_account_impersonation_"
  3115. "url\":\"service_account_impersonation_url\",\"token_url\":\"https://"
  3116. "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/"
  3117. "token_info\",\"credential_source\":{\"url\":\"https://foo.com:5555/"
  3118. "generate_subject_token_format_json\",\"headers\":{\"Metadata-Flavor\":"
  3119. "\"Google\"},\"format\":{\"type\":\"json\",\"subject_token_field_name\":"
  3120. "\"access_token\"}},\"quota_project_id\":\"quota_"
  3121. "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
  3122. "secret\"}";
  3123. const char* url_scopes_string = "scope1,scope2";
  3124. grpc_call_credentials* url_creds = grpc_external_account_credentials_create(
  3125. url_options_string, url_scopes_string);
  3126. GPR_ASSERT(url_creds != nullptr);
  3127. url_creds->Unref();
  3128. // file credentials
  3129. const char* file_options_string =
  3130. "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_"
  3131. "token_type\":\"subject_token_type\",\"service_account_impersonation_"
  3132. "url\":\"service_account_impersonation_url\",\"token_url\":\"https://"
  3133. "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/"
  3134. "token_info\",\"credential_source\":{\"file\":\"credentials_file_path\"},"
  3135. "\"quota_project_id\":\"quota_"
  3136. "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
  3137. "secret\"}";
  3138. const char* file_scopes_string = "scope1,scope2";
  3139. grpc_call_credentials* file_creds = grpc_external_account_credentials_create(
  3140. file_options_string, file_scopes_string);
  3141. GPR_ASSERT(file_creds != nullptr);
  3142. file_creds->Unref();
  3143. // aws credentials
  3144. const char* aws_options_string =
  3145. "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_"
  3146. "token_type\":\"subject_token_type\",\"service_account_impersonation_"
  3147. "url\":\"service_account_impersonation_url\",\"token_url\":\"https://"
  3148. "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/"
  3149. "token_info\",\"credential_source\":{\"environment_id\":\"aws1\","
  3150. "\"region_url\":\"https://foo.com:5555/region_url\",\"url\":\"https://"
  3151. "foo.com:5555/url\",\"regional_cred_verification_url\":\"https://"
  3152. "foo.com:5555/regional_cred_verification_url_{region}\"},"
  3153. "\"quota_project_id\":\"quota_"
  3154. "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
  3155. "secret\"}";
  3156. const char* aws_scopes_string = "scope1,scope2";
  3157. grpc_call_credentials* aws_creds = grpc_external_account_credentials_create(
  3158. aws_options_string, aws_scopes_string);
  3159. GPR_ASSERT(aws_creds != nullptr);
  3160. aws_creds->Unref();
  3161. }
  3162. TEST(CredentialsTest,
  3163. TestExternalAccountCredentialsCreateFailureInvalidJsonFormat) {
  3164. const char* options_string = "invalid_json";
  3165. grpc_call_credentials* creds =
  3166. grpc_external_account_credentials_create(options_string, "");
  3167. GPR_ASSERT(creds == nullptr);
  3168. }
  3169. TEST(CredentialsTest,
  3170. TestExternalAccountCredentialsCreateFailureInvalidOptionsFormat) {
  3171. const char* options_string = "{\"random_key\":\"random_value\"}";
  3172. grpc_call_credentials* creds =
  3173. grpc_external_account_credentials_create(options_string, "");
  3174. GPR_ASSERT(creds == nullptr);
  3175. }
  3176. TEST(
  3177. CredentialsTest,
  3178. TestExternalAccountCredentialsCreateFailureInvalidOptionsCredentialSource) {
  3179. const char* options_string =
  3180. "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_"
  3181. "token_type\":\"subject_token_type\",\"service_account_impersonation_"
  3182. "url\":\"service_account_impersonation_url\",\"token_url\":\"https://"
  3183. "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/"
  3184. "token_info\",\"credential_source\":{\"random_key\":\"random_value\"},"
  3185. "\"quota_project_id\":\"quota_"
  3186. "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
  3187. "secret\"}";
  3188. grpc_call_credentials* creds =
  3189. grpc_external_account_credentials_create(options_string, "");
  3190. GPR_ASSERT(creds == nullptr);
  3191. }
  3192. TEST(CredentialsTest,
  3193. TestExternalAccountCredentialsCreateSuccessWorkforcePool) {
  3194. const char* url_options_string =
  3195. "{\"type\":\"external_account\",\"audience\":\"//iam.googleapis.com/"
  3196. "locations/location/workforcePools/pool/providers/provider\",\"subject_"
  3197. "token_type\":\"subject_token_type\",\"service_account_impersonation_"
  3198. "url\":\"service_account_impersonation_url\",\"token_url\":\"https://"
  3199. "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/"
  3200. "token_info\",\"credential_source\":{\"url\":\"https://foo.com:5555/"
  3201. "generate_subject_token_format_json\",\"headers\":{\"Metadata-Flavor\":"
  3202. "\"Google\"},\"format\":{\"type\":\"json\",\"subject_token_field_name\":"
  3203. "\"access_token\"}},\"quota_project_id\":\"quota_"
  3204. "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
  3205. "secret\",\"workforce_pool_user_project\":\"workforce_pool_user_"
  3206. "project\"}";
  3207. const char* url_scopes_string = "scope1,scope2";
  3208. grpc_call_credentials* url_creds = grpc_external_account_credentials_create(
  3209. url_options_string, url_scopes_string);
  3210. GPR_ASSERT(url_creds != nullptr);
  3211. url_creds->Unref();
  3212. }
  3213. TEST(CredentialsTest,
  3214. TestExternalAccountCredentialsCreateFailureInvalidWorkforcePoolAudience) {
  3215. const char* url_options_string =
  3216. "{\"type\":\"external_account\",\"audience\":\"invalid_workforce_pool_"
  3217. "audience\",\"subject_"
  3218. "token_type\":\"subject_token_type\",\"service_account_impersonation_"
  3219. "url\":\"service_account_impersonation_url\",\"token_url\":\"https://"
  3220. "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/"
  3221. "token_info\",\"credential_source\":{\"url\":\"https://foo.com:5555/"
  3222. "generate_subject_token_format_json\",\"headers\":{\"Metadata-Flavor\":"
  3223. "\"Google\"},\"format\":{\"type\":\"json\",\"subject_token_field_name\":"
  3224. "\"access_token\"}},\"quota_project_id\":\"quota_"
  3225. "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_"
  3226. "secret\",\"workforce_pool_user_project\":\"workforce_pool_user_"
  3227. "project\"}";
  3228. const char* url_scopes_string = "scope1,scope2";
  3229. grpc_call_credentials* url_creds = grpc_external_account_credentials_create(
  3230. url_options_string, url_scopes_string);
  3231. GPR_ASSERT(url_creds == nullptr);
  3232. }
  3233. TEST(CredentialsTest, TestInsecureCredentialsCompareSuccess) {
  3234. auto insecure_creds_1 = grpc_insecure_credentials_create();
  3235. auto insecure_creds_2 = grpc_insecure_credentials_create();
  3236. ASSERT_EQ(insecure_creds_1->cmp(insecure_creds_2), 0);
  3237. grpc_arg arg_1 = grpc_channel_credentials_to_arg(insecure_creds_1);
  3238. grpc_channel_args args_1 = {1, &arg_1};
  3239. grpc_arg arg_2 = grpc_channel_credentials_to_arg(insecure_creds_2);
  3240. grpc_channel_args args_2 = {1, &arg_2};
  3241. EXPECT_EQ(grpc_channel_args_compare(&args_1, &args_2), 0);
  3242. grpc_channel_credentials_release(insecure_creds_1);
  3243. grpc_channel_credentials_release(insecure_creds_2);
  3244. }
  3245. TEST(CredentialsTest, TestInsecureCredentialsCompareFailure) {
  3246. auto* insecure_creds = grpc_insecure_credentials_create();
  3247. auto* fake_creds = grpc_fake_transport_security_credentials_create();
  3248. ASSERT_NE(insecure_creds->cmp(fake_creds), 0);
  3249. ASSERT_NE(fake_creds->cmp(insecure_creds), 0);
  3250. grpc_arg arg_1 = grpc_channel_credentials_to_arg(insecure_creds);
  3251. grpc_channel_args args_1 = {1, &arg_1};
  3252. grpc_arg arg_2 = grpc_channel_credentials_to_arg(fake_creds);
  3253. grpc_channel_args args_2 = {1, &arg_2};
  3254. EXPECT_NE(grpc_channel_args_compare(&args_1, &args_2), 0);
  3255. grpc_channel_credentials_release(fake_creds);
  3256. grpc_channel_credentials_release(insecure_creds);
  3257. }
  3258. TEST(CredentialsTest, TestInsecureCredentialsSingletonCreate) {
  3259. auto* insecure_creds_1 = grpc_insecure_credentials_create();
  3260. auto* insecure_creds_2 = grpc_insecure_credentials_create();
  3261. EXPECT_EQ(insecure_creds_1, insecure_creds_2);
  3262. }
  3263. TEST(CredentialsTest, TestFakeCallCredentialsCompareSuccess) {
  3264. auto call_creds = MakeRefCounted<fake_call_creds>();
  3265. GPR_ASSERT(call_creds->cmp(call_creds.get()) == 0);
  3266. }
  3267. TEST(CredentialsTest, TestFakeCallCredentialsCompareFailure) {
  3268. auto fake_creds = MakeRefCounted<fake_call_creds>();
  3269. auto* md_creds = grpc_md_only_test_credentials_create("key", "value");
  3270. GPR_ASSERT(fake_creds->cmp(md_creds) != 0);
  3271. GPR_ASSERT(md_creds->cmp(fake_creds.get()) != 0);
  3272. grpc_call_credentials_release(md_creds);
  3273. }
  3274. TEST(CredentialsTest, TestHttpRequestSSLCredentialsCompare) {
  3275. auto creds_1 = CreateHttpRequestSSLCredentials();
  3276. auto creds_2 = CreateHttpRequestSSLCredentials();
  3277. EXPECT_EQ(creds_1->cmp(creds_2.get()), 0);
  3278. EXPECT_EQ(creds_2->cmp(creds_1.get()), 0);
  3279. }
  3280. TEST(CredentialsTest, TestHttpRequestSSLCredentialsSingleton) {
  3281. auto creds_1 = CreateHttpRequestSSLCredentials();
  3282. auto creds_2 = CreateHttpRequestSSLCredentials();
  3283. EXPECT_EQ(creds_1, creds_2);
  3284. }
  3285. TEST(CredentialsTest, TestCompositeChannelCredsCompareSuccess) {
  3286. auto* insecure_creds = grpc_insecure_credentials_create();
  3287. auto fake_creds = MakeRefCounted<fake_call_creds>();
  3288. auto* composite_creds_1 = grpc_composite_channel_credentials_create(
  3289. insecure_creds, fake_creds.get(), nullptr);
  3290. auto* composite_creds_2 = grpc_composite_channel_credentials_create(
  3291. insecure_creds, fake_creds.get(), nullptr);
  3292. EXPECT_EQ(composite_creds_1->cmp(composite_creds_2), 0);
  3293. EXPECT_EQ(composite_creds_2->cmp(composite_creds_1), 0);
  3294. grpc_channel_credentials_release(insecure_creds);
  3295. grpc_channel_credentials_release(composite_creds_1);
  3296. grpc_channel_credentials_release(composite_creds_2);
  3297. }
  3298. TEST(CredentialsTest,
  3299. TestCompositeChannelCredsCompareFailureDifferentChannelCreds) {
  3300. auto* insecure_creds = grpc_insecure_credentials_create();
  3301. auto* fake_channel_creds = grpc_fake_transport_security_credentials_create();
  3302. auto fake_creds = MakeRefCounted<fake_call_creds>();
  3303. auto* composite_creds_1 = grpc_composite_channel_credentials_create(
  3304. insecure_creds, fake_creds.get(), nullptr);
  3305. auto* composite_creds_2 = grpc_composite_channel_credentials_create(
  3306. fake_channel_creds, fake_creds.get(), nullptr);
  3307. EXPECT_NE(composite_creds_1->cmp(composite_creds_2), 0);
  3308. EXPECT_NE(composite_creds_2->cmp(composite_creds_1), 0);
  3309. grpc_channel_credentials_release(insecure_creds);
  3310. grpc_channel_credentials_release(fake_channel_creds);
  3311. grpc_channel_credentials_release(composite_creds_1);
  3312. grpc_channel_credentials_release(composite_creds_2);
  3313. }
  3314. TEST(CredentialsTest,
  3315. TestCompositeChannelCredsCompareFailureDifferentCallCreds) {
  3316. auto* insecure_creds = grpc_insecure_credentials_create();
  3317. auto fake_creds = MakeRefCounted<fake_call_creds>();
  3318. auto* md_creds = grpc_md_only_test_credentials_create("key", "value");
  3319. auto* composite_creds_1 = grpc_composite_channel_credentials_create(
  3320. insecure_creds, fake_creds.get(), nullptr);
  3321. auto* composite_creds_2 = grpc_composite_channel_credentials_create(
  3322. insecure_creds, md_creds, nullptr);
  3323. EXPECT_NE(composite_creds_1->cmp(composite_creds_2), 0);
  3324. EXPECT_NE(composite_creds_2->cmp(composite_creds_1), 0);
  3325. grpc_channel_credentials_release(insecure_creds);
  3326. grpc_call_credentials_release(md_creds);
  3327. grpc_channel_credentials_release(composite_creds_1);
  3328. grpc_channel_credentials_release(composite_creds_2);
  3329. }
  3330. TEST(CredentialsTest, TestXdsCredentialsCompareSucces) {
  3331. auto* insecure_creds = grpc_insecure_credentials_create();
  3332. auto* xds_creds_1 = grpc_xds_credentials_create(insecure_creds);
  3333. auto* xds_creds_2 = grpc_xds_credentials_create(insecure_creds);
  3334. EXPECT_EQ(xds_creds_1->cmp(xds_creds_2), 0);
  3335. EXPECT_EQ(xds_creds_2->cmp(xds_creds_1), 0);
  3336. grpc_channel_credentials_release(insecure_creds);
  3337. grpc_channel_credentials_release(xds_creds_1);
  3338. grpc_channel_credentials_release(xds_creds_2);
  3339. }
  3340. TEST(CredentialsTest, TestXdsCredentialsCompareFailure) {
  3341. auto* insecure_creds = grpc_insecure_credentials_create();
  3342. auto* fake_creds = grpc_fake_transport_security_credentials_create();
  3343. auto* xds_creds_1 = grpc_xds_credentials_create(insecure_creds);
  3344. auto* xds_creds_2 = grpc_xds_credentials_create(fake_creds);
  3345. EXPECT_NE(xds_creds_1->cmp(xds_creds_2), 0);
  3346. EXPECT_NE(xds_creds_2->cmp(xds_creds_1), 0);
  3347. grpc_channel_credentials_release(insecure_creds);
  3348. grpc_channel_credentials_release(fake_creds);
  3349. grpc_channel_credentials_release(xds_creds_1);
  3350. grpc_channel_credentials_release(xds_creds_2);
  3351. }
  3352. } // namespace
  3353. } // namespace grpc_core
  3354. int main(int argc, char** argv) {
  3355. testing::InitGoogleTest(&argc, argv);
  3356. grpc::testing::TestEnvironment env(argc, argv);
  3357. grpc_init();
  3358. auto result = RUN_ALL_TESTS();
  3359. grpc_shutdown();
  3360. return result;
  3361. }