Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include <grpc++/channel.h>
35 : #include <grpc++/impl/grpc_library.h>
36 : #include <grpc++/support/channel_arguments.h>
37 : #include <grpc/support/log.h>
38 : #include "src/cpp/client/create_channel_internal.h"
39 : #include "src/cpp/client/secure_credentials.h"
40 : #include "src/cpp/common/secure_auth_context.h"
41 :
42 : namespace grpc {
43 :
44 47 : std::shared_ptr<grpc::Channel> SecureChannelCredentials::CreateChannel(
45 : const string& target, const grpc::ChannelArguments& args) {
46 : grpc_channel_args channel_args;
47 47 : args.SetChannelArgs(&channel_args);
48 : return CreateChannelInternal(
49 : args.GetSslTargetNameOverride(),
50 : grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args,
51 47 : nullptr));
52 : }
53 :
54 8 : bool SecureCallCredentials::ApplyToCall(grpc_call* call) {
55 8 : return grpc_call_set_credentials(call, c_creds_) == GRPC_CALL_OK;
56 : }
57 :
58 : namespace {
59 47 : std::shared_ptr<ChannelCredentials> WrapChannelCredentials(
60 : grpc_channel_credentials* creds) {
61 : return creds == nullptr ? nullptr : std::shared_ptr<ChannelCredentials>(
62 47 : new SecureChannelCredentials(creds));
63 : }
64 :
65 10 : std::shared_ptr<CallCredentials> WrapCallCredentials(
66 : grpc_call_credentials* creds) {
67 : return creds == nullptr ? nullptr : std::shared_ptr<CallCredentials>(
68 10 : new SecureCallCredentials(creds));
69 : }
70 : } // namespace
71 :
72 0 : std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
73 0 : GrpcLibrary init; // To call grpc_init().
74 0 : return WrapChannelCredentials(grpc_google_default_credentials_create());
75 : }
76 :
77 : // Builds SSL Credentials given SSL specific options
78 47 : std::shared_ptr<ChannelCredentials> SslCredentials(
79 : const SslCredentialsOptions& options) {
80 47 : GrpcLibrary init; // To call grpc_init().
81 : grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
82 47 : options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
83 :
84 : grpc_channel_credentials* c_creds = grpc_ssl_credentials_create(
85 94 : options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
86 141 : options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr);
87 47 : return WrapChannelCredentials(c_creds);
88 : }
89 :
90 : // Builds credentials for use when running in GCE
91 0 : std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
92 0 : GrpcLibrary init; // To call grpc_init().
93 : return WrapCallCredentials(
94 0 : grpc_google_compute_engine_credentials_create(nullptr));
95 : }
96 :
97 : // Builds JWT credentials.
98 0 : std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
99 : const grpc::string& json_key, long token_lifetime_seconds) {
100 0 : GrpcLibrary init; // To call grpc_init().
101 0 : if (token_lifetime_seconds <= 0) {
102 : gpr_log(GPR_ERROR,
103 0 : "Trying to create JWTCredentials with non-positive lifetime");
104 0 : return WrapCallCredentials(nullptr);
105 : }
106 : gpr_timespec lifetime =
107 0 : gpr_time_from_seconds(token_lifetime_seconds, GPR_TIMESPAN);
108 : return WrapCallCredentials(grpc_service_account_jwt_access_credentials_create(
109 0 : json_key.c_str(), lifetime, nullptr));
110 : }
111 :
112 : // Builds refresh token credentials.
113 1 : std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
114 : const grpc::string& json_refresh_token) {
115 1 : GrpcLibrary init; // To call grpc_init().
116 : return WrapCallCredentials(grpc_google_refresh_token_credentials_create(
117 1 : json_refresh_token.c_str(), nullptr));
118 : }
119 :
120 : // Builds access token credentials.
121 0 : std::shared_ptr<CallCredentials> AccessTokenCredentials(
122 : const grpc::string& access_token) {
123 0 : GrpcLibrary init; // To call grpc_init().
124 : return WrapCallCredentials(
125 0 : grpc_access_token_credentials_create(access_token.c_str(), nullptr));
126 : }
127 :
128 : // Builds IAM credentials.
129 3 : std::shared_ptr<CallCredentials> GoogleIAMCredentials(
130 : const grpc::string& authorization_token,
131 : const grpc::string& authority_selector) {
132 3 : GrpcLibrary init; // To call grpc_init().
133 : return WrapCallCredentials(grpc_google_iam_credentials_create(
134 3 : authorization_token.c_str(), authority_selector.c_str(), nullptr));
135 : }
136 :
137 : // Combines one channel credentials and one call credentials into a channel
138 : // composite credentials.
139 0 : std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
140 : const std::shared_ptr<ChannelCredentials>& channel_creds,
141 : const std::shared_ptr<CallCredentials>& call_creds) {
142 : // Note that we are not saving shared_ptrs to the two credentials passed in
143 : // here. This is OK because the underlying C objects (i.e., channel_creds and
144 : // call_creds) into grpc_composite_credentials_create will see their refcounts
145 : // incremented.
146 : SecureChannelCredentials* s_channel_creds =
147 0 : channel_creds->AsSecureCredentials();
148 0 : SecureCallCredentials* s_call_creds = call_creds->AsSecureCredentials();
149 0 : if (s_channel_creds && s_call_creds) {
150 : return WrapChannelCredentials(grpc_composite_channel_credentials_create(
151 0 : s_channel_creds->GetRawCreds(), s_call_creds->GetRawCreds(), nullptr));
152 : }
153 0 : return nullptr;
154 : }
155 :
156 6 : void MetadataCredentialsPluginWrapper::Destroy(void* wrapper) {
157 12 : if (wrapper == nullptr) return;
158 : MetadataCredentialsPluginWrapper* w =
159 6 : reinterpret_cast<MetadataCredentialsPluginWrapper*>(wrapper);
160 6 : delete w;
161 : }
162 :
163 6 : void MetadataCredentialsPluginWrapper::GetMetadata(
164 : void* wrapper, grpc_auth_metadata_context context,
165 : grpc_credentials_plugin_metadata_cb cb, void* user_data) {
166 6 : GPR_ASSERT(wrapper);
167 : MetadataCredentialsPluginWrapper* w =
168 6 : reinterpret_cast<MetadataCredentialsPluginWrapper*>(wrapper);
169 6 : if (!w->plugin_) {
170 0 : cb(user_data, NULL, 0, GRPC_STATUS_OK, NULL);
171 6 : return;
172 : }
173 6 : if (w->plugin_->IsBlocking()) {
174 3 : w->thread_pool_->Add(
175 : std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w, context,
176 3 : cb, user_data));
177 : } else {
178 3 : w->InvokePlugin(context, cb, user_data);
179 : }
180 : }
181 :
182 6 : void MetadataCredentialsPluginWrapper::InvokePlugin(
183 : grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb,
184 : void* user_data) {
185 6 : std::multimap<grpc::string, grpc::string> metadata;
186 :
187 : // const_cast is safe since the SecureAuthContext does not take owndership and
188 : // the object is passed as a const ref to plugin_->GetMetadata.
189 : SecureAuthContext cpp_channel_auth_context(
190 12 : const_cast<grpc_auth_context*>(context.channel_auth_context), false);
191 :
192 6 : Status status = plugin_->GetMetadata(context.service_url, context.method_name,
193 12 : cpp_channel_auth_context, &metadata);
194 12 : std::vector<grpc_metadata> md;
195 10 : for (auto it = metadata.begin(); it != metadata.end(); ++it) {
196 : grpc_metadata md_entry;
197 4 : md_entry.key = it->first.c_str();
198 4 : md_entry.value = it->second.data();
199 4 : md_entry.value_length = it->second.size();
200 4 : md_entry.flags = 0;
201 4 : md.push_back(md_entry);
202 : }
203 6 : cb(user_data, md.empty() ? nullptr : &md[0], md.size(),
204 6 : static_cast<grpc_status_code>(status.error_code()),
205 24 : status.error_message().c_str());
206 6 : }
207 :
208 6 : MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
209 : std::unique_ptr<MetadataCredentialsPlugin> plugin)
210 6 : : thread_pool_(CreateDefaultThreadPool()), plugin_(std::move(plugin)) {}
211 :
212 6 : std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
213 : std::unique_ptr<MetadataCredentialsPlugin> plugin) {
214 6 : GrpcLibrary init; // To call grpc_init().
215 6 : const char* type = plugin->GetType();
216 : MetadataCredentialsPluginWrapper* wrapper =
217 6 : new MetadataCredentialsPluginWrapper(std::move(plugin));
218 : grpc_metadata_credentials_plugin c_plugin = {
219 : MetadataCredentialsPluginWrapper::GetMetadata,
220 6 : MetadataCredentialsPluginWrapper::Destroy, wrapper, type};
221 : return WrapCallCredentials(
222 6 : grpc_metadata_credentials_create_from_plugin(c_plugin, nullptr));
223 : }
224 :
225 : } // namespace grpc
|