secure_credentials.cc 10 KB

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