Google Cloud Storage C++ Client 2.13.0
A C++ Client Library for Google Cloud Storage
Loading...
Searching...
No Matches
service_account_credentials.h
1// Copyright 2018 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_OAUTH2_SERVICE_ACCOUNT_CREDENTIALS_H
16#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_OAUTH2_SERVICE_ACCOUNT_CREDENTIALS_H
17
18#include "google/cloud/storage/internal/curl_request_builder.h"
19#include "google/cloud/storage/internal/openssl_util.h"
20#include "google/cloud/storage/oauth2/credential_constants.h"
21#include "google/cloud/storage/oauth2/credentials.h"
22#include "google/cloud/storage/oauth2/refreshing_credentials_wrapper.h"
23#include "google/cloud/storage/version.h"
24#include "google/cloud/internal/getenv.h"
25#include "google/cloud/internal/oauth2_service_account_credentials.h"
26#include "google/cloud/internal/sha256_hash.h"
27#include "google/cloud/optional.h"
28#include "google/cloud/status_or.h"
29#include "absl/types/optional.h"
30#include <chrono>
31#include <condition_variable>
32#include <ctime>
33#include <iostream>
34#include <mutex>
35#include <set>
36#include <string>
37#include <vector>
38
39namespace google {
40namespace cloud {
41namespace storage {
42GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
43namespace oauth2 {
44
45/**
46 * Object to hold information used to instantiate an ServiceAccountCredentials.
47 *
48 * @deprecated Prefer using the unified credentials documented in @ref guac
49 */
51 std::string client_email;
52 std::string private_key_id;
53 std::string private_key;
54 std::string token_uri;
55 // If no set is supplied, a default set of scopes will be used.
56 absl::optional<std::set<std::string>> scopes;
57 // See https://developers.google.com/identity/protocols/OAuth2ServiceAccount.
58 absl::optional<std::string> subject;
59};
60
61/**
62 * Parses the contents of a JSON keyfile into a ServiceAccountCredentialsInfo.
63 *
64 * @deprecated Prefer using the unified credentials documented in @ref guac
65 */
66
68 std::string const& content, std::string const& source,
69 std::string const& default_token_uri = GoogleOAuthRefreshEndpoint());
70
71/**
72 * Parses the contents of a P12 keyfile into a ServiceAccountCredentialsInfo.
73 *
74 * @warning We strongly recommend that applications use JSON keyfiles instead.
75 *
76 * @note Note that P12 keyfiles do not contain the `client_email` for the
77 * service account, the application must obtain this through some other means
78 * and provide them to the function.
79 *
80 * @deprecated Prefer using the unified credentials documented in @ref guac
81 */
83 std::string const& source,
84 std::string const& default_token_uri = GoogleOAuthRefreshEndpoint());
85
86/**
87 * Parses a refresh response JSON string and uses the current time to create a
88 * TemporaryToken.
89 *
90 * @deprecated Prefer using the unified credentials documented in @ref guac
91 */
94 storage::internal::HttpResponse const& response,
95 std::chrono::system_clock::time_point now);
96
97/**
98 * Splits a ServiceAccountCredentialsInfo into header and payload components
99 * and uses the current time to make a JWT assertion.
100 *
101 * @see
102 * https://cloud.google.com/endpoints/docs/frameworks/java/troubleshoot-jwt
103 *
104 * @see https://tools.ietf.org/html/rfc7523
105 *
106 * @deprecated Prefer using the unified credentials documented in @ref guac
107 */
108std::pair<std::string, std::string> AssertionComponentsFromInfo(
110 std::chrono::system_clock::time_point now);
111
112/**
113 * Given a key and a JSON header and payload, creates a JWT assertion string.
114 *
115 * @see https://tools.ietf.org/html/rfc7519
116 *
117 * @deprecated Prefer using the unified credentials documented in @ref guac
118 */
119std::string MakeJWTAssertion(std::string const& header,
120 std::string const& payload,
121 std::string const& pem_contents);
122
123/**
124 * Uses a ServiceAccountCredentialsInfo and the current time to construct a JWT
125 * assertion.
126 *
127 * The assertion combined with the grant type is used to create the refresh
128 * payload.
129 *
130 * @deprecated Prefer using the unified credentials documented in @ref guac
131 */
133 ServiceAccountCredentialsInfo const& info, std::string const& grant_type,
134 std::chrono::system_clock::time_point now);
135
136/**
137 * Make a self-signed JWT from the service account.
138 *
139 * [Self-signed JWTs] bypass the intermediate step of exchanging client
140 * assertions for OAuth tokens. The advantages of self-signed JTWs include:
141 *
142 * - They are more efficient, as they require more or less the same amount of
143 * local work, and save a round-trip to the token endpoint, typically
144 * https://oauth2.googleapis.com/token.
145 * - While this service is extremely reliable, removing external dependencies in
146 * the critical path almost always improves reliability.
147 * - They work better in VPC-SC environments and other environments with limited
148 * Internet access.
149 *
150 * @warning At this time only scope-based self-signed JWTs are supported.
151 *
152 * [Self-signed JWTs]: https://google.aip.dev/auth/4111
153 *
154 * @param info the parsed service account information, see
155 * `ParseServiceAccountCredentials()`
156 * @param tp the current time
157 * @return a bearer token for authentication. Include this value in the
158 * `Authorization` header with the "Bearer" type.
159 *
160 * @deprecated Prefer using the unified credentials documented in @ref guac
161 */
162StatusOr<std::string> MakeSelfSignedJWT(
164 std::chrono::system_clock::time_point tp);
165
166/**
167 * Return true if we need to use the OAuth path to create tokens
168 *
169 * @deprecated Prefer using the unified credentials documented in @ref guac
170 */
172
173/**
174 * Wrapper class for Google OAuth 2.0 service account credentials.
175 *
176 * Takes a ServiceAccountCredentialsInfo and obtains access tokens from the
177 * Google Authorization Service as needed. Instances of this class should
178 * usually be created via the convenience methods declared in
179 * google_credentials.h.
180 *
181 * An HTTP Authorization header, with an access token as its value,
182 * can be obtained by calling the AuthorizationHeader() method; if the current
183 * access token is invalid or nearing expiration, this will class will first
184 * obtain a new access token before returning the Authorization header string.
185 *
186 * @see https://developers.google.com/identity/protocols/OAuth2ServiceAccount
187 * for an overview of using service accounts with Google's OAuth 2.0 system.
188 *
189 * @see https://cloud.google.com/storage/docs/reference/libraries for details on
190 * how to obtain and get started with service account credentials.
191 *
192 * @tparam HttpRequestBuilderType a dependency injection point. It makes it
193 * possible to mock internal libcurl wrappers. This should generally not be
194 * overridden except for testing.
195 * @tparam ClockType a dependency injection point to fetch the current time.
196 * This should generally not be overridden except for testing.
197 *
198 * @deprecated Prefer using the unified credentials documented in @ref guac
199 */
200template <typename HttpRequestBuilderType =
201 storage::internal::CurlRequestBuilder,
202 typename ClockType = std::chrono::system_clock>
203class ServiceAccountCredentials;
204
205/// @copydoc ServiceAccountCredentials
206template <>
207class ServiceAccountCredentials<storage::internal::CurlRequestBuilder,
208 std::chrono::system_clock>
209 : public Credentials {
210 public:
211 explicit ServiceAccountCredentials(ServiceAccountCredentialsInfo info)
212 : ServiceAccountCredentials(std::move(info), {}) {}
213 ServiceAccountCredentials(ServiceAccountCredentialsInfo info,
214 ChannelOptions const& options);
215
216 StatusOr<std::string> AuthorizationHeader() override {
217 return oauth2_internal::AuthorizationHeaderJoined(*impl_);
218 }
219
220 /**
221 * Create a RSA SHA256 signature of the blob using the Credential object.
222 *
223 * @param signing_account the desired service account which should sign
224 * @p blob. If not set, uses this object's account. If set, it must match
225 * this object's service account.
226 * @param blob the string to sign. Note that sometimes the application must
227 * Base64-encode the data before signing.
228 * @return the signed blob as raw bytes. An error if the @p signing_account
229 * does not match the email for the credential's account.
230 *
231 * @deprecated Prefer using the unified credentials documented in @ref guac
232 */
233 StatusOr<std::vector<std::uint8_t>> SignBlob(
234 SigningAccount const& signing_account,
235 std::string const& blob) const override {
236 return impl_->SignBlob((signing_account.has_value()
237 ? signing_account.value()
238 : absl::optional<std::string>(absl::nullopt)),
239 blob);
240 }
241
242 std::string AccountEmail() const override { return impl_->AccountEmail(); }
243 std::string KeyId() const override { return impl_->KeyId(); }
244
245 private:
246 friend struct ServiceAccountCredentialsTester;
247 StatusOr<std::string> AuthorizationHeaderForTesting(
248 std::chrono::system_clock::time_point tp) {
249 return oauth2_internal::AuthorizationHeaderJoined(*impl_, tp);
250 }
251 std::unique_ptr<oauth2_internal::Credentials> impl_;
252};
253
254/// @copydoc ServiceAccountCredentials
255template <typename HttpRequestBuilderType, typename ClockType>
256class ServiceAccountCredentials : public Credentials {
257 public:
259 : ServiceAccountCredentials(std::move(info), {}) {}
261 ChannelOptions const& options)
262 : info_(std::move(info)),
264 clock_() {}
265
266 StatusOr<std::string> AuthorizationHeader() override {
267 std::unique_lock<std::mutex> lock(mu_);
268 return refreshing_creds_.AuthorizationHeader(clock_.now(),
269 [this] { return Refresh(); });
270 }
271
272 /**
273 * Create a RSA SHA256 signature of the blob using the Credential object.
274 *
275 * @param signing_account the desired service account which should sign
276 * @p blob. If not set, uses this object's account. If set, it must match
277 * this object's service account.
278 * @param blob the string to sign. Note that sometimes the application must
279 * Base64-encode the data before signing.
280 * @return the signed blob as raw bytes. An error if the @p signing_account
281 * does not match the email for the credential's account.
282 *
283 * @deprecated Prefer using the unified credentials documented in @ref guac
284 */
285 StatusOr<std::vector<std::uint8_t>> SignBlob(
286 SigningAccount const& signing_account,
287 std::string const& blob) const override {
288 if (signing_account.has_value() &&
289 signing_account.value() != info_.client_email) {
290 return Status(StatusCode::kInvalidArgument,
291 "The current_credentials cannot sign blobs for " +
292 signing_account.value());
293 }
294 return internal::SignStringWithPem(blob, info_.private_key,
296 }
297
298 std::string AccountEmail() const override { return info_.client_email; }
299 std::string KeyId() const override { return info_.private_key_id; }
300
301 private:
302 bool UseOAuth() const { return ServiceAccountUseOAuth(info_); }
303
304 StatusOr<RefreshingCredentialsWrapper::TemporaryToken> Refresh() {
305 if (UseOAuth()) return RefreshOAuth();
306 return RefreshSelfSigned();
307 }
308
309 StatusOr<RefreshingCredentialsWrapper::TemporaryToken> RefreshOAuth() const {
310 HttpRequestBuilderType builder(
311 info_.token_uri,
312 storage::internal::GetDefaultCurlHandleFactory(options_));
313 builder.AddHeader("Content-Type: application/x-www-form-urlencoded");
314 // This is the value of grant_type for JSON-formatted service account
315 // keyfiles downloaded from Cloud Console.
316 std::string grant_type("grant_type=");
317 grant_type +=
318 builder.MakeEscapedString("urn:ietf:params:oauth:grant-type:jwt-bearer")
319 .get();
320
321 auto payload =
322 CreateServiceAccountRefreshPayload(info_, grant_type, clock_.now());
323 auto response = std::move(builder).BuildRequest().MakeRequest(payload);
324 if (!response) return std::move(response).status();
325 if (response->status_code >= 300) return AsStatus(*response);
326 return ParseServiceAccountRefreshResponse(*response, clock_.now());
327 }
328
329 StatusOr<RefreshingCredentialsWrapper::TemporaryToken> RefreshSelfSigned()
330 const {
331 auto const tp = clock_.now();
332 auto token = MakeSelfSignedJWT(info_, tp);
333 if (!token) return std::move(token).status();
335 "Authorization: Bearer " + *token,
337 }
338
340 Options options_;
341 mutable std::mutex mu_;
342 RefreshingCredentialsWrapper refreshing_creds_;
343 ClockType clock_;
344};
345
346} // namespace oauth2
347
348namespace internal {
349
350oauth2_internal::ServiceAccountCredentialsInfo MapServiceAccountCredentialsInfo(
352
353} // namespace internal
354GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
355} // namespace storage
356} // namespace cloud
357} // namespace google
358
359#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_OAUTH2_SERVICE_ACCOUNT_CREDENTIALS_H
Options & set(ValueTypeT< T > v)
Options(Options const &rhs)
Status(StatusCode code, std::string message, ErrorInfo info={})
Describes the configuration for low-level connection features.
Definition: client_options.h:74
std::string ssl_root_path() const
Definition: client_options.h:77
Interface for OAuth 2.0 credentials used to access Google Cloud services.
Definition: credentials.h:47
Wrapper for refreshable parts of a Credentials object.
Definition: refreshing_credentials_wrapper.h:37
std::string KeyId() const override
Return the account's key_id associated with these credentials, if any.
Definition: service_account_credentials.h:299
ServiceAccountCredentials(ServiceAccountCredentialsInfo info)
Definition: service_account_credentials.h:258
StatusOr< std::vector< std::uint8_t > > SignBlob(SigningAccount const &signing_account, std::string const &blob) const override
Create a RSA SHA256 signature of the blob using the Credential object.
Definition: service_account_credentials.h:285
StatusOr< std::string > AuthorizationHeader() override
Attempts to obtain a value for the Authorization HTTP header.
Definition: service_account_credentials.h:266
std::string AccountEmail() const override
Return the account's email associated with these credentials, if any.
Definition: service_account_credentials.h:298
ServiceAccountCredentials(ServiceAccountCredentialsInfo info, ChannelOptions const &options)
Definition: service_account_credentials.h:260
Authentication components for Google Cloud Storage.
Definition: anonymous_credentials.h:26
std::pair< std::string, std::string > AssertionComponentsFromInfo(ServiceAccountCredentialsInfo const &info, std::chrono::system_clock::time_point now)
Splits a ServiceAccountCredentialsInfo into header and payload components and uses the current time t...
bool ServiceAccountUseOAuth(ServiceAccountCredentialsInfo const &info)
Return true if we need to use the OAuth path to create tokens.
std::string CreateServiceAccountRefreshPayload(ServiceAccountCredentialsInfo const &info, std::string const &grant_type, std::chrono::system_clock::time_point now)
Uses a ServiceAccountCredentialsInfo and the current time to construct a JWT assertion.
StatusOr< ServiceAccountCredentialsInfo > ParseServiceAccountCredentials(std::string const &content, std::string const &source, std::string const &default_token_uri=GoogleOAuthRefreshEndpoint())
Parses the contents of a JSON keyfile into a ServiceAccountCredentialsInfo.
char const * GoogleOAuthRefreshEndpoint()
The endpoint to fetch an OAuth 2.0 access token from.
Definition: credential_constants.h:67
StatusOr< RefreshingCredentialsWrapper::TemporaryToken > ParseServiceAccountRefreshResponse(storage::internal::HttpResponse const &response, std::chrono::system_clock::time_point now)
Parses a refresh response JSON string and uses the current time to create a TemporaryToken.
StatusOr< ServiceAccountCredentialsInfo > ParseServiceAccountP12File(std::string const &source, std::string const &default_token_uri=GoogleOAuthRefreshEndpoint())
Parses the contents of a P12 keyfile into a ServiceAccountCredentialsInfo.
StatusOr< std::string > MakeSelfSignedJWT(ServiceAccountCredentialsInfo const &info, std::chrono::system_clock::time_point tp)
Make a self-signed JWT from the service account.
constexpr std::chrono::seconds GoogleOAuthAccessTokenLifetime()
The max lifetime in seconds of an access token.
Definition: credential_constants.h:43
JwtSigningAlgorithms
Supported signing algorithms used in JWT auth flows.
Definition: credential_constants.h:36
std::string MakeJWTAssertion(std::string const &header, std::string const &payload, std::string const &pem_contents)
Given a key and a JSON header and payload, creates a JWT assertion string.
Contains all the Google Cloud Storage C++ client APIs.
Definition: auto_finalize.h:24
Specify the service account used to sign a blob.
Definition: signed_url_options.h:186
Object to hold information used to instantiate an ServiceAccountCredentials.
Definition: service_account_credentials.h:50
absl::optional< std::string > subject
Definition: service_account_credentials.h:58
std::string private_key
Definition: service_account_credentials.h:53
absl::optional< std::set< std::string > > scopes
Definition: service_account_credentials.h:56
std::string client_email
Definition: service_account_credentials.h:51
std::string token_uri
Definition: service_account_credentials.h:54
std::string private_key_id
Definition: service_account_credentials.h:52