blob: 25f6bab7f25838a73f7bf426c70deb42411d7e62 [file] [log] [blame]
Craig Tiller47c83fd2015-02-21 22:45:35 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Craig Tiller47c83fd2015-02-21 22:45:35 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Craig Tillerf40df232016-03-25 13:38:14 -070034#include "src/cpp/client/secure_credentials.h"
yang-g8c2be9f2015-08-19 16:28:09 -070035#include <grpc++/channel.h>
yang-ge71a6b02015-08-10 15:48:34 -070036#include <grpc++/impl/grpc_library.h>
yang-g9e2f90c2015-08-21 15:35:03 -070037#include <grpc++/support/channel_arguments.h>
yang-gd88e1d82015-12-02 13:23:33 -080038#include <grpc/support/log.h>
yang-gc317f072015-08-20 12:18:08 -070039#include "src/cpp/client/create_channel_internal.h"
Julien Boeuf114f3942015-11-19 21:45:52 -080040#include "src/cpp/common/secure_auth_context.h"
Craig Tiller47c83fd2015-02-21 22:45:35 -080041
42namespace grpc {
43
David Garcia Quintasd79ef3a2016-01-28 00:21:27 -080044static internal::GrpcLibraryInitializer g_gli_initializer;
David Garcia Quintase1300de2016-01-27 18:41:26 -080045SecureChannelCredentials::SecureChannelCredentials(
46 grpc_channel_credentials* c_creds)
47 : c_creds_(c_creds) {
David Garcia Quintasd79ef3a2016-01-28 00:21:27 -080048 g_gli_initializer.summon();
David Garcia Quintase1300de2016-01-27 18:41:26 -080049}
50
Julien Boeuf54a902e2015-10-12 13:26:21 -070051std::shared_ptr<grpc::Channel> SecureChannelCredentials::CreateChannel(
Julien Boeuf1d2240c2015-04-09 21:07:56 -070052 const string& target, const grpc::ChannelArguments& args) {
53 grpc_channel_args channel_args;
54 args.SetChannelArgs(&channel_args);
yang-gc317f072015-08-20 12:18:08 -070055 return CreateChannelInternal(
yang-gd556da92015-07-31 15:59:04 -070056 args.GetSslTargetNameOverride(),
Julien Boeufc5b570f2015-08-25 17:47:55 -070057 grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args,
58 nullptr));
Julien Boeuf1d2240c2015-04-09 21:07:56 -070059}
Craig Tiller47c83fd2015-02-21 22:45:35 -080060
David Garcia Quintase1300de2016-01-27 18:41:26 -080061SecureCallCredentials::SecureCallCredentials(grpc_call_credentials* c_creds)
62 : c_creds_(c_creds) {
David Garcia Quintas146070d2016-03-18 15:53:28 -070063 g_gli_initializer.summon();
David Garcia Quintase1300de2016-01-27 18:41:26 -080064}
65
Julien Boeuf54a902e2015-10-12 13:26:21 -070066bool SecureCallCredentials::ApplyToCall(grpc_call* call) {
Yang Gaoa8938922015-05-14 11:51:07 -070067 return grpc_call_set_credentials(call, c_creds_) == GRPC_CALL_OK;
68}
69
Craig Tillerad9d0c42015-02-23 10:53:01 -080070namespace {
Julien Boeuf54a902e2015-10-12 13:26:21 -070071std::shared_ptr<ChannelCredentials> WrapChannelCredentials(
72 grpc_channel_credentials* creds) {
73 return creds == nullptr ? nullptr : std::shared_ptr<ChannelCredentials>(
74 new SecureChannelCredentials(creds));
75}
76
77std::shared_ptr<CallCredentials> WrapCallCredentials(
78 grpc_call_credentials* creds) {
79 return creds == nullptr ? nullptr : std::shared_ptr<CallCredentials>(
80 new SecureCallCredentials(creds));
Craig Tiller47c83fd2015-02-21 22:45:35 -080081}
82} // namespace
83
Julien Boeuf54a902e2015-10-12 13:26:21 -070084std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
David Garcia Quintas60ee8dd2016-03-08 17:21:42 -080085 GrpcLibraryCodegen init; // To call grpc_init().
Julien Boeuf54a902e2015-10-12 13:26:21 -070086 return WrapChannelCredentials(grpc_google_default_credentials_create());
Craig Tiller47c83fd2015-02-21 22:45:35 -080087}
88
89// Builds SSL Credentials given SSL specific options
Julien Boeuf54a902e2015-10-12 13:26:21 -070090std::shared_ptr<ChannelCredentials> SslCredentials(
Craig Tiller47c83fd2015-02-21 22:45:35 -080091 const SslCredentialsOptions& options) {
David Garcia Quintas60ee8dd2016-03-08 17:21:42 -080092 GrpcLibraryCodegen init; // To call grpc_init().
Craig Tiller47c83fd2015-02-21 22:45:35 -080093 grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
94 options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
95
Julien Boeuf54a902e2015-10-12 13:26:21 -070096 grpc_channel_credentials* c_creds = grpc_ssl_credentials_create(
Craig Tiller47c83fd2015-02-21 22:45:35 -080097 options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
Julien Boeufc5b570f2015-08-25 17:47:55 -070098 options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr);
Julien Boeuf54a902e2015-10-12 13:26:21 -070099 return WrapChannelCredentials(c_creds);
Craig Tiller47c83fd2015-02-21 22:45:35 -0800100}
101
102// Builds credentials for use when running in GCE
Julien Boeuf54a902e2015-10-12 13:26:21 -0700103std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
David Garcia Quintas60ee8dd2016-03-08 17:21:42 -0800104 GrpcLibraryCodegen init; // To call grpc_init().
Julien Boeuf54a902e2015-10-12 13:26:21 -0700105 return WrapCallCredentials(
Julien Boeuf510a9202015-08-25 21:51:07 -0700106 grpc_google_compute_engine_credentials_create(nullptr));
Craig Tiller47c83fd2015-02-21 22:45:35 -0800107}
108
Yang Gao0535da32015-03-11 14:51:03 -0700109// Builds JWT credentials.
Julien Boeuf54a902e2015-10-12 13:26:21 -0700110std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700111 const grpc::string& json_key, long token_lifetime_seconds) {
David Garcia Quintas60ee8dd2016-03-08 17:21:42 -0800112 GrpcLibraryCodegen init; // To call grpc_init().
Nicolas "Pixel" Noblee24dde52015-04-24 00:43:09 +0200113 if (token_lifetime_seconds <= 0) {
Yang Gao94e296c2015-03-13 16:06:56 -0700114 gpr_log(GPR_ERROR,
115 "Trying to create JWTCredentials with non-positive lifetime");
Julien Boeuf54a902e2015-10-12 13:26:21 -0700116 return WrapCallCredentials(nullptr);
Yang Gao05e3eef2015-03-12 23:41:46 -0700117 }
Craig Tiller677c50c2015-07-13 10:49:06 -0700118 gpr_timespec lifetime =
119 gpr_time_from_seconds(token_lifetime_seconds, GPR_TIMESPAN);
Julien Boeuf54a902e2015-10-12 13:26:21 -0700120 return WrapCallCredentials(grpc_service_account_jwt_access_credentials_create(
Julien Boeufc5b570f2015-08-25 17:47:55 -0700121 json_key.c_str(), lifetime, nullptr));
Yang Gao0535da32015-03-11 14:51:03 -0700122}
123
Yang Gao5ebd6c72015-03-17 16:22:32 -0700124// Builds refresh token credentials.
Julien Boeuf54a902e2015-10-12 13:26:21 -0700125std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
Yang Gao5ebd6c72015-03-17 16:22:32 -0700126 const grpc::string& json_refresh_token) {
David Garcia Quintas60ee8dd2016-03-08 17:21:42 -0800127 GrpcLibraryCodegen init; // To call grpc_init().
Julien Boeuf54a902e2015-10-12 13:26:21 -0700128 return WrapCallCredentials(grpc_google_refresh_token_credentials_create(
Julien Boeufc5b570f2015-08-25 17:47:55 -0700129 json_refresh_token.c_str(), nullptr));
Yang Gao5ebd6c72015-03-17 16:22:32 -0700130}
131
Julien Boeuf2805be12015-07-01 02:47:18 -0700132// Builds access token credentials.
Julien Boeuf54a902e2015-10-12 13:26:21 -0700133std::shared_ptr<CallCredentials> AccessTokenCredentials(
Julien Boeuf2805be12015-07-01 02:47:18 -0700134 const grpc::string& access_token) {
David Garcia Quintas60ee8dd2016-03-08 17:21:42 -0800135 GrpcLibraryCodegen init; // To call grpc_init().
Julien Boeuf54a902e2015-10-12 13:26:21 -0700136 return WrapCallCredentials(
Julien Boeufc5b570f2015-08-25 17:47:55 -0700137 grpc_access_token_credentials_create(access_token.c_str(), nullptr));
Julien Boeuf2805be12015-07-01 02:47:18 -0700138}
139
Craig Tiller47c83fd2015-02-21 22:45:35 -0800140// Builds IAM credentials.
Julien Boeuf54a902e2015-10-12 13:26:21 -0700141std::shared_ptr<CallCredentials> GoogleIAMCredentials(
Craig Tiller47c83fd2015-02-21 22:45:35 -0800142 const grpc::string& authorization_token,
143 const grpc::string& authority_selector) {
David Garcia Quintas60ee8dd2016-03-08 17:21:42 -0800144 GrpcLibraryCodegen init; // To call grpc_init().
Julien Boeuf54a902e2015-10-12 13:26:21 -0700145 return WrapCallCredentials(grpc_google_iam_credentials_create(
Julien Boeufc5b570f2015-08-25 17:47:55 -0700146 authorization_token.c_str(), authority_selector.c_str(), nullptr));
Craig Tiller47c83fd2015-02-21 22:45:35 -0800147}
148
Julien Boeuf54a902e2015-10-12 13:26:21 -0700149// Combines one channel credentials and one call credentials into a channel
150// composite credentials.
151std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
152 const std::shared_ptr<ChannelCredentials>& channel_creds,
153 const std::shared_ptr<CallCredentials>& call_creds) {
154 // Note that we are not saving shared_ptrs to the two credentials passed in
155 // here. This is OK because the underlying C objects (i.e., channel_creds and
156 // call_creds) into grpc_composite_credentials_create will see their refcounts
157 // incremented.
158 SecureChannelCredentials* s_channel_creds =
159 channel_creds->AsSecureCredentials();
160 SecureCallCredentials* s_call_creds = call_creds->AsSecureCredentials();
161 if (s_channel_creds && s_call_creds) {
162 return WrapChannelCredentials(grpc_composite_channel_credentials_create(
163 s_channel_creds->GetRawCreds(), s_call_creds->GetRawCreds(), nullptr));
Craig Tiller47c83fd2015-02-21 22:45:35 -0800164 }
165 return nullptr;
166}
167
Julien Boeuf2d041182015-08-31 20:30:09 -0700168void MetadataCredentialsPluginWrapper::Destroy(void* wrapper) {
169 if (wrapper == nullptr) return;
170 MetadataCredentialsPluginWrapper* w =
171 reinterpret_cast<MetadataCredentialsPluginWrapper*>(wrapper);
172 delete w;
173}
174
175void MetadataCredentialsPluginWrapper::GetMetadata(
Julien Boeuf3c957e62015-11-18 21:33:58 -0800176 void* wrapper, grpc_auth_metadata_context context,
Julien Boeuf2d041182015-08-31 20:30:09 -0700177 grpc_credentials_plugin_metadata_cb cb, void* user_data) {
Vijay Paie547bdf2015-09-29 23:29:38 +0000178 GPR_ASSERT(wrapper);
Julien Boeuf2d041182015-08-31 20:30:09 -0700179 MetadataCredentialsPluginWrapper* w =
180 reinterpret_cast<MetadataCredentialsPluginWrapper*>(wrapper);
Vijay Paie57abcf2015-09-29 22:55:34 +0000181 if (!w->plugin_) {
Julien Boeuf2d041182015-08-31 20:30:09 -0700182 cb(user_data, NULL, 0, GRPC_STATUS_OK, NULL);
183 return;
184 }
185 if (w->plugin_->IsBlocking()) {
186 w->thread_pool_->Add(
Julien Boeuf114f3942015-11-19 21:45:52 -0800187 std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w, context,
188 cb, user_data));
Julien Boeuf2d041182015-08-31 20:30:09 -0700189 } else {
Julien Boeuf114f3942015-11-19 21:45:52 -0800190 w->InvokePlugin(context, cb, user_data);
Julien Boeuf2d041182015-08-31 20:30:09 -0700191 }
192}
193
194void MetadataCredentialsPluginWrapper::InvokePlugin(
Julien Boeuf114f3942015-11-19 21:45:52 -0800195 grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb,
Julien Boeuf2d041182015-08-31 20:30:09 -0700196 void* user_data) {
Julien Boeuf8b0b6f42015-09-22 13:31:16 -0700197 std::multimap<grpc::string, grpc::string> metadata;
Julien Boeuf114f3942015-11-19 21:45:52 -0800198
199 // const_cast is safe since the SecureAuthContext does not take owndership and
200 // the object is passed as a const ref to plugin_->GetMetadata.
201 SecureAuthContext cpp_channel_auth_context(
202 const_cast<grpc_auth_context*>(context.channel_auth_context), false);
203
204 Status status = plugin_->GetMetadata(context.service_url, context.method_name,
205 cpp_channel_auth_context, &metadata);
Julien Boeuf2d041182015-08-31 20:30:09 -0700206 std::vector<grpc_metadata> md;
207 for (auto it = metadata.begin(); it != metadata.end(); ++it) {
Vijay Paie57abcf2015-09-29 22:55:34 +0000208 grpc_metadata md_entry;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800209 md_entry.key = SliceFromCopiedString(it->first);
210 md_entry.value = SliceFromCopiedString(it->second);
Vijay Paie57abcf2015-09-29 22:55:34 +0000211 md_entry.flags = 0;
212 md.push_back(md_entry);
Julien Boeuf2d041182015-08-31 20:30:09 -0700213 }
Julien Boeuf14929d42015-09-21 20:57:26 -0700214 cb(user_data, md.empty() ? nullptr : &md[0], md.size(),
Julien Boeuf2d041182015-08-31 20:30:09 -0700215 static_cast<grpc_status_code>(status.error_code()),
216 status.error_message().c_str());
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800217 for (auto it = md.begin(); it != md.end(); ++it) {
218 grpc_slice_unref(it->key);
219 grpc_slice_unref(it->value);
220 }
Julien Boeuf2d041182015-08-31 20:30:09 -0700221}
222
223MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
224 std::unique_ptr<MetadataCredentialsPlugin> plugin)
225 : thread_pool_(CreateDefaultThreadPool()), plugin_(std::move(plugin)) {}
226
Julien Boeuf54a902e2015-10-12 13:26:21 -0700227std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
Julien Boeuf2d041182015-08-31 20:30:09 -0700228 std::unique_ptr<MetadataCredentialsPlugin> plugin) {
David Garcia Quintas60ee8dd2016-03-08 17:21:42 -0800229 GrpcLibraryCodegen init; // To call grpc_init().
Julien Boeuf114f3942015-11-19 21:45:52 -0800230 const char* type = plugin->GetType();
Julien Boeuf2d041182015-08-31 20:30:09 -0700231 MetadataCredentialsPluginWrapper* wrapper =
232 new MetadataCredentialsPluginWrapper(std::move(plugin));
233 grpc_metadata_credentials_plugin c_plugin = {
234 MetadataCredentialsPluginWrapper::GetMetadata,
Julien Boeuf114f3942015-11-19 21:45:52 -0800235 MetadataCredentialsPluginWrapper::Destroy, wrapper, type};
Julien Boeuf54a902e2015-10-12 13:26:21 -0700236 return WrapCallCredentials(
Julien Boeuf2d041182015-08-31 20:30:09 -0700237 grpc_metadata_credentials_create_from_plugin(c_plugin, nullptr));
238}
239
Craig Tiller47c83fd2015-02-21 22:45:35 -0800240} // namespace grpc