secure_credentials.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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 "src/cpp/client/secure_credentials.h"
  19. #include <grpc/support/log.h>
  20. #include <grpc/support/string_util.h>
  21. #include <grpcpp/channel.h>
  22. #include <grpcpp/impl/grpc_library.h>
  23. #include <grpcpp/support/channel_arguments.h>
  24. #include "src/cpp/client/create_channel_internal.h"
  25. #include "src/cpp/common/secure_auth_context.h"
  26. namespace grpc {
  27. static internal::GrpcLibraryInitializer g_gli_initializer;
  28. SecureChannelCredentials::SecureChannelCredentials(
  29. grpc_channel_credentials* c_creds)
  30. : c_creds_(c_creds) {
  31. g_gli_initializer.summon();
  32. }
  33. std::shared_ptr<grpc::Channel> SecureChannelCredentials::CreateChannel(
  34. const string& target, const grpc::ChannelArguments& args) {
  35. return CreateChannelWithInterceptors(
  36. target, args,
  37. std::vector<
  38. std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
  39. }
  40. std::shared_ptr<grpc::Channel>
  41. SecureChannelCredentials::CreateChannelWithInterceptors(
  42. const string& target, const grpc::ChannelArguments& args,
  43. std::vector<
  44. std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
  45. interceptor_creators) {
  46. grpc_channel_args channel_args;
  47. args.SetChannelArgs(&channel_args);
  48. return CreateChannelInternal(
  49. args.GetSslTargetNameOverride(),
  50. grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args,
  51. nullptr),
  52. std::move(interceptor_creators));
  53. }
  54. SecureCallCredentials::SecureCallCredentials(grpc_call_credentials* c_creds)
  55. : c_creds_(c_creds) {
  56. g_gli_initializer.summon();
  57. }
  58. bool SecureCallCredentials::ApplyToCall(grpc_call* call) {
  59. return grpc_call_set_credentials(call, c_creds_) == GRPC_CALL_OK;
  60. }
  61. namespace {
  62. std::shared_ptr<ChannelCredentials> WrapChannelCredentials(
  63. grpc_channel_credentials* creds) {
  64. return creds == nullptr ? nullptr
  65. : std::shared_ptr<ChannelCredentials>(
  66. new SecureChannelCredentials(creds));
  67. }
  68. std::shared_ptr<CallCredentials> WrapCallCredentials(
  69. grpc_call_credentials* creds) {
  70. return creds == nullptr ? nullptr
  71. : std::shared_ptr<CallCredentials>(
  72. new SecureCallCredentials(creds));
  73. }
  74. } // namespace
  75. std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
  76. GrpcLibraryCodegen init; // To call grpc_init().
  77. return WrapChannelCredentials(grpc_google_default_credentials_create());
  78. }
  79. // Builds SSL Credentials given SSL specific options
  80. std::shared_ptr<ChannelCredentials> SslCredentials(
  81. const SslCredentialsOptions& options) {
  82. GrpcLibraryCodegen init; // To call grpc_init().
  83. grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
  84. options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
  85. grpc_channel_credentials* c_creds = grpc_ssl_credentials_create(
  86. options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
  87. options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr,
  88. nullptr);
  89. return WrapChannelCredentials(c_creds);
  90. }
  91. namespace experimental {
  92. // Builds ALTS Credentials given ALTS specific options
  93. std::shared_ptr<ChannelCredentials> AltsCredentials(
  94. const AltsCredentialsOptions& options) {
  95. GrpcLibraryCodegen init; // To call grpc_init().
  96. grpc_alts_credentials_options* c_options =
  97. grpc_alts_credentials_client_options_create();
  98. for (auto service_account = options.target_service_accounts.begin();
  99. service_account != options.target_service_accounts.end();
  100. service_account++) {
  101. grpc_alts_credentials_client_options_add_target_service_account(
  102. c_options, service_account->c_str());
  103. }
  104. grpc_channel_credentials* c_creds = grpc_alts_credentials_create(c_options);
  105. grpc_alts_credentials_options_destroy(c_options);
  106. return WrapChannelCredentials(c_creds);
  107. }
  108. // Builds Local Credentials
  109. std::shared_ptr<ChannelCredentials> LocalCredentials(
  110. grpc_local_connect_type type) {
  111. GrpcLibraryCodegen init; // To call grpc_init().
  112. return WrapChannelCredentials(grpc_local_credentials_create(type));
  113. }
  114. } // namespace experimental
  115. // Builds credentials for use when running in GCE
  116. std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
  117. GrpcLibraryCodegen init; // To call grpc_init().
  118. return WrapCallCredentials(
  119. grpc_google_compute_engine_credentials_create(nullptr));
  120. }
  121. // Builds JWT credentials.
  122. std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
  123. const grpc::string& json_key, long token_lifetime_seconds) {
  124. GrpcLibraryCodegen init; // To call grpc_init().
  125. if (token_lifetime_seconds <= 0) {
  126. gpr_log(GPR_ERROR,
  127. "Trying to create JWTCredentials with non-positive lifetime");
  128. return WrapCallCredentials(nullptr);
  129. }
  130. gpr_timespec lifetime =
  131. gpr_time_from_seconds(token_lifetime_seconds, GPR_TIMESPAN);
  132. return WrapCallCredentials(grpc_service_account_jwt_access_credentials_create(
  133. json_key.c_str(), lifetime, nullptr));
  134. }
  135. // Builds refresh token credentials.
  136. std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
  137. const grpc::string& json_refresh_token) {
  138. GrpcLibraryCodegen init; // To call grpc_init().
  139. return WrapCallCredentials(grpc_google_refresh_token_credentials_create(
  140. json_refresh_token.c_str(), nullptr));
  141. }
  142. // Builds access token credentials.
  143. std::shared_ptr<CallCredentials> AccessTokenCredentials(
  144. const grpc::string& access_token) {
  145. GrpcLibraryCodegen init; // To call grpc_init().
  146. return WrapCallCredentials(
  147. grpc_access_token_credentials_create(access_token.c_str(), nullptr));
  148. }
  149. // Builds IAM credentials.
  150. std::shared_ptr<CallCredentials> GoogleIAMCredentials(
  151. const grpc::string& authorization_token,
  152. const grpc::string& authority_selector) {
  153. GrpcLibraryCodegen init; // To call grpc_init().
  154. return WrapCallCredentials(grpc_google_iam_credentials_create(
  155. authorization_token.c_str(), authority_selector.c_str(), nullptr));
  156. }
  157. // Combines one channel credentials and one call credentials into a channel
  158. // composite credentials.
  159. std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
  160. const std::shared_ptr<ChannelCredentials>& channel_creds,
  161. const std::shared_ptr<CallCredentials>& call_creds) {
  162. // Note that we are not saving shared_ptrs to the two credentials passed in
  163. // here. This is OK because the underlying C objects (i.e., channel_creds and
  164. // call_creds) into grpc_composite_credentials_create will see their refcounts
  165. // incremented.
  166. SecureChannelCredentials* s_channel_creds =
  167. channel_creds->AsSecureCredentials();
  168. SecureCallCredentials* s_call_creds = call_creds->AsSecureCredentials();
  169. if (s_channel_creds && s_call_creds) {
  170. return WrapChannelCredentials(grpc_composite_channel_credentials_create(
  171. s_channel_creds->GetRawCreds(), s_call_creds->GetRawCreds(), nullptr));
  172. }
  173. return nullptr;
  174. }
  175. std::shared_ptr<CallCredentials> CompositeCallCredentials(
  176. const std::shared_ptr<CallCredentials>& creds1,
  177. const std::shared_ptr<CallCredentials>& creds2) {
  178. SecureCallCredentials* s_creds1 = creds1->AsSecureCredentials();
  179. SecureCallCredentials* s_creds2 = creds2->AsSecureCredentials();
  180. if (s_creds1 != nullptr && s_creds2 != nullptr) {
  181. return WrapCallCredentials(grpc_composite_call_credentials_create(
  182. s_creds1->GetRawCreds(), s_creds2->GetRawCreds(), nullptr));
  183. }
  184. return nullptr;
  185. }
  186. void MetadataCredentialsPluginWrapper::Destroy(void* wrapper) {
  187. if (wrapper == nullptr) return;
  188. MetadataCredentialsPluginWrapper* w =
  189. static_cast<MetadataCredentialsPluginWrapper*>(wrapper);
  190. delete w;
  191. }
  192. int MetadataCredentialsPluginWrapper::GetMetadata(
  193. void* wrapper, grpc_auth_metadata_context context,
  194. grpc_credentials_plugin_metadata_cb cb, void* user_data,
  195. grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
  196. size_t* num_creds_md, grpc_status_code* status,
  197. const char** error_details) {
  198. GPR_ASSERT(wrapper);
  199. MetadataCredentialsPluginWrapper* w =
  200. static_cast<MetadataCredentialsPluginWrapper*>(wrapper);
  201. if (!w->plugin_) {
  202. *num_creds_md = 0;
  203. *status = GRPC_STATUS_OK;
  204. *error_details = nullptr;
  205. return true;
  206. }
  207. if (w->plugin_->IsBlocking()) {
  208. // Asynchronous return.
  209. w->thread_pool_->Add([w, context, cb, user_data] {
  210. w->MetadataCredentialsPluginWrapper::InvokePlugin(
  211. context, cb, user_data, nullptr, nullptr, nullptr, nullptr);
  212. });
  213. return 0;
  214. } else {
  215. // Synchronous return.
  216. w->InvokePlugin(context, cb, user_data, creds_md, num_creds_md, status,
  217. error_details);
  218. return 1;
  219. }
  220. }
  221. namespace {
  222. void UnrefMetadata(const std::vector<grpc_metadata>& md) {
  223. for (auto it = md.begin(); it != md.end(); ++it) {
  224. grpc_slice_unref(it->key);
  225. grpc_slice_unref(it->value);
  226. }
  227. }
  228. } // namespace
  229. void MetadataCredentialsPluginWrapper::InvokePlugin(
  230. grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb,
  231. void* user_data, grpc_metadata creds_md[4], size_t* num_creds_md,
  232. grpc_status_code* status_code, const char** error_details) {
  233. std::multimap<grpc::string, grpc::string> metadata;
  234. // const_cast is safe since the SecureAuthContext does not take owndership and
  235. // the object is passed as a const ref to plugin_->GetMetadata.
  236. SecureAuthContext cpp_channel_auth_context(
  237. const_cast<grpc_auth_context*>(context.channel_auth_context), false);
  238. Status status = plugin_->GetMetadata(context.service_url, context.method_name,
  239. cpp_channel_auth_context, &metadata);
  240. std::vector<grpc_metadata> md;
  241. for (auto it = metadata.begin(); it != metadata.end(); ++it) {
  242. grpc_metadata md_entry;
  243. md_entry.key = SliceFromCopiedString(it->first);
  244. md_entry.value = SliceFromCopiedString(it->second);
  245. md_entry.flags = 0;
  246. md.push_back(md_entry);
  247. }
  248. if (creds_md != nullptr) {
  249. // Synchronous return.
  250. if (md.size() > GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX) {
  251. *num_creds_md = 0;
  252. *status_code = GRPC_STATUS_INTERNAL;
  253. *error_details = gpr_strdup(
  254. "blocking plugin credentials returned too many metadata keys");
  255. UnrefMetadata(md);
  256. } else {
  257. for (const auto& elem : md) {
  258. creds_md[*num_creds_md].key = elem.key;
  259. creds_md[*num_creds_md].value = elem.value;
  260. creds_md[*num_creds_md].flags = elem.flags;
  261. ++(*num_creds_md);
  262. }
  263. *status_code = static_cast<grpc_status_code>(status.error_code());
  264. *error_details =
  265. status.ok() ? nullptr : gpr_strdup(status.error_message().c_str());
  266. }
  267. } else {
  268. // Asynchronous return.
  269. cb(user_data, md.empty() ? nullptr : &md[0], md.size(),
  270. static_cast<grpc_status_code>(status.error_code()),
  271. status.error_message().c_str());
  272. UnrefMetadata(md);
  273. }
  274. }
  275. MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
  276. std::unique_ptr<MetadataCredentialsPlugin> plugin)
  277. : thread_pool_(CreateDefaultThreadPool()), plugin_(std::move(plugin)) {}
  278. std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
  279. std::unique_ptr<MetadataCredentialsPlugin> plugin) {
  280. GrpcLibraryCodegen init; // To call grpc_init().
  281. const char* type = plugin->GetType();
  282. MetadataCredentialsPluginWrapper* wrapper =
  283. new MetadataCredentialsPluginWrapper(std::move(plugin));
  284. grpc_metadata_credentials_plugin c_plugin = {
  285. MetadataCredentialsPluginWrapper::GetMetadata,
  286. MetadataCredentialsPluginWrapper::Destroy, wrapper, type};
  287. return WrapCallCredentials(
  288. grpc_metadata_credentials_create_from_plugin(c_plugin, nullptr));
  289. }
  290. } // namespace grpc