Google Cloud Storage C++ Client 2.13.0
A C++ Client Library for Google Cloud Storage
Loading...
Searching...
No Matches
compute_engine_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_COMPUTE_ENGINE_CREDENTIALS_H
16#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_OAUTH2_COMPUTE_ENGINE_CREDENTIALS_H
17
18#include "google/cloud/storage/internal/compute_engine_util.h"
19#include "google/cloud/storage/internal/curl_request_builder.h"
20#include "google/cloud/storage/internal/openssl_util.h"
21#include "google/cloud/storage/oauth2/credential_constants.h"
22#include "google/cloud/storage/oauth2/credentials.h"
23#include "google/cloud/storage/oauth2/refreshing_credentials_wrapper.h"
24#include "google/cloud/storage/version.h"
25#include "google/cloud/internal/getenv.h"
26#include "google/cloud/internal/oauth2_cached_credentials.h"
27#include "google/cloud/internal/oauth2_compute_engine_credentials.h"
28#include "google/cloud/status.h"
29#include <chrono>
30#include <ctime>
31#include <mutex>
32#include <set>
33#include <string>
34
35namespace google {
36namespace cloud {
37namespace storage {
38GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
39namespace oauth2 {
40
41/**
42 * A helper struct that contains service account metadata.
43 *
44 * @deprecated Prefer using the unified credentials documented in @ref guac
45 */
47 std::set<std::string> scopes;
48 std::string email;
49};
50
51/**
52 * Parses a metadata server response JSON string into a ServiceAccountMetadata.
53 *
54 * @deprecated Prefer using the unified credentials documented in @ref guac
55 */
57 storage::internal::HttpResponse const& response);
58
59/**
60 * Parses a refresh response JSON string into an authorization header.
61 *
62 * The header and the current time (for the expiration) form a TemporaryToken.
63 *
64 * @deprecated Prefer using the unified credentials documented in @ref guac
65 */
68 storage::internal::HttpResponse const& response,
69 std::chrono::system_clock::time_point now);
70
71/**
72 * Wrapper class for Google OAuth 2.0 GCE instance service account credentials.
73 *
74 * Takes a service account email address or alias (e.g. "default") and uses the
75 * Google Compute Engine instance's metadata server to obtain service account
76 * metadata and OAuth 2.0 access tokens as needed. Instances of this class
77 * should usually be created via the convenience methods declared in
78 * google_credentials.h.
79 *
80 * An HTTP Authorization header, with an access token as its value, can be
81 * obtained by calling the AuthorizationHeader() method; if the current access
82 * token is invalid or nearing expiration, this will class will first obtain a
83 * new access token before returning the Authorization header string.
84 *
85 * @see https://cloud.google.com/compute/docs/authentication#using for details
86 * on how to get started with Compute Engine service account credentials.
87 *
88 * @tparam HttpRequestBuilderType a dependency injection point. It makes it
89 * possible to mock internal libcurl wrappers. This should generally not
90 * be overridden except for testing.
91 * @tparam ClockType a dependency injection point to fetch the current time.
92 * This should generally not be overridden except for testing.
93 *
94 * @deprecated Prefer using the unified credentials documented in @ref guac
95 */
96template <typename HttpRequestBuilderType =
97 storage::internal::CurlRequestBuilder,
98 typename ClockType = std::chrono::system_clock>
99class ComputeEngineCredentials;
100
101/// @copydoc ComputeEngineCredentials
102template <>
103class ComputeEngineCredentials<storage::internal::CurlRequestBuilder,
104 std::chrono::system_clock> : public Credentials {
105 public:
106 explicit ComputeEngineCredentials() : ComputeEngineCredentials("default") {}
107 explicit ComputeEngineCredentials(std::string service_account_email);
108
109 StatusOr<std::string> AuthorizationHeader() override {
110 return oauth2_internal::AuthorizationHeaderJoined(*cached_);
111 }
112
113 std::string AccountEmail() const override { return impl_->AccountEmail(); }
114
115 /**
116 * Returns the email or alias of this credential's service account.
117 *
118 * @note This class must query the Compute Engine instance's metadata server
119 * to fetch service account metadata. Because of this, if an alias (e.g.
120 * "default") was supplied in place of an actual email address when
121 * initializing this credential, that alias is returned as this credential's
122 * email address if the credential has not been refreshed yet.
123 */
124 std::string service_account_email() { return impl_->service_account_email(); }
125
126 /**
127 * Returns the set of scopes granted to this credential's service account.
128 *
129 * @note Because this class must query the Compute Engine instance's metadata
130 * server to fetch service account metadata, this method will return an empty
131 * set if the credential has not been refreshed yet.
132 */
133 std::set<std::string> scopes() const { return impl_->scopes(); }
134
135 private:
136 friend struct ComputeEngineCredentialsTester;
137 ComputeEngineCredentials(std::string service_account_email,
138 oauth2_internal::HttpClientFactory client_factory);
139
140 StatusOr<std::string> AuthorizationHeaderForTesting(
141 std::chrono::system_clock::time_point tp) {
142 return oauth2_internal::AuthorizationHeaderJoined(*cached_, tp);
143 }
144
145 std::shared_ptr<oauth2_internal::ComputeEngineCredentials> impl_;
146 std::shared_ptr<oauth2_internal::CachedCredentials> cached_;
147};
148
149/// @copydoc ComputeEngineCredentials
150template <typename HttpRequestBuilderType, typename ClockType>
151class ComputeEngineCredentials : public Credentials {
152 public:
153 explicit ComputeEngineCredentials() : ComputeEngineCredentials("default") {}
154
155 explicit ComputeEngineCredentials(std::string service_account_email)
156 : clock_(), service_account_email_(std::move(service_account_email)) {}
157
158 StatusOr<std::string> AuthorizationHeader() override {
159 std::unique_lock<std::mutex> lock(mu_);
160 return refreshing_creds_.AuthorizationHeader(clock_.now(),
161 [this] { return Refresh(); });
162 }
163
164 std::string AccountEmail() const override {
165 std::unique_lock<std::mutex> lock(mu_);
166 // Force a refresh on the account info.
167 RetrieveServiceAccountInfo();
168 return service_account_email_;
169 }
170
171 /**
172 * Returns the email or alias of this credential's service account.
173 *
174 * @note This class must query the Compute Engine instance's metadata server
175 * to fetch service account metadata. Because of this, if an alias (e.g.
176 * "default") was supplied in place of an actual email address when
177 * initializing this credential, that alias is returned as this credential's
178 * email address if the credential has not been refreshed yet.
179 */
180 std::string service_account_email() const {
181 std::unique_lock<std::mutex> lock(mu_);
182 return service_account_email_;
183 }
184
185 /**
186 * Returns the set of scopes granted to this credential's service account.
187 *
188 * @note Because this class must query the Compute Engine instance's metadata
189 * server to fetch service account metadata, this method will return an empty
190 * set if the credential has not been refreshed yet.
191 */
192 std::set<std::string> scopes() const {
193 std::unique_lock<std::mutex> lock(mu_);
194 return scopes_;
195 }
196
197 private:
198 /**
199 * Sends an HTTP GET request to the GCE metadata server.
200 *
201 * @see https://cloud.google.com/compute/docs/storing-retrieving-metadata for
202 * an overview of retrieving information from the GCE metadata server.
203 */
204 StatusOr<storage::internal::HttpResponse> DoMetadataServerGetRequest(
205 std::string const& path, bool recursive) const {
206 // Allows mocking the metadata server hostname for testing.
207 std::string metadata_server_hostname =
208 google::cloud::storage::internal::GceMetadataHostname();
209
210 HttpRequestBuilderType builder(
211 std::move("http://" + metadata_server_hostname + path),
212 storage::internal::GetDefaultCurlHandleFactory());
213 builder.AddHeader("metadata-flavor: Google");
214 if (recursive) builder.AddQueryParameter("recursive", "true");
215 return std::move(builder).BuildRequest().MakeRequest(std::string{});
216 }
217
218 /**
219 * Fetches metadata for an instance's service account.
220 *
221 * @see
222 * https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances
223 * for more details.
224 */
225 Status RetrieveServiceAccountInfo() const {
226 auto response = DoMetadataServerGetRequest(
227 "/computeMetadata/v1/instance/service-accounts/" +
228 service_account_email_ + "/",
229 true);
230 if (!response) {
231 return std::move(response).status();
232 }
233 if (response->status_code >= 300) {
234 return AsStatus(*response);
235 }
236
237 auto metadata = ParseMetadataServerResponse(*response);
238 if (!metadata) {
239 return metadata.status();
240 }
241 service_account_email_ = std::move(metadata->email);
242 scopes_ = std::move(metadata->scopes);
243 return Status();
244 }
245
246 StatusOr<RefreshingCredentialsWrapper::TemporaryToken> Refresh() const {
247 auto status = RetrieveServiceAccountInfo();
248 if (!status.ok()) {
249 return status;
250 }
251
252 auto response = DoMetadataServerGetRequest(
253 "/computeMetadata/v1/instance/service-accounts/" +
254 service_account_email_ + "/token",
255 false);
256 if (!response) {
257 return std::move(response).status();
258 }
259 if (response->status_code >= 300) {
260 return AsStatus(*response);
261 }
262
263 return ParseComputeEngineRefreshResponse(*response, clock_.now());
264 }
265
266 ClockType clock_;
267 mutable std::mutex mu_;
268 RefreshingCredentialsWrapper refreshing_creds_;
269 mutable std::set<std::string> scopes_;
270 mutable std::string service_account_email_;
271};
272
273} // namespace oauth2
274GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
275} // namespace storage
276} // namespace cloud
277} // namespace google
278
279#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_OAUTH2_COMPUTE_ENGINE_CREDENTIALS_H
std::string service_account_email() const
Returns the email or alias of this credential's service account.
Definition: compute_engine_credentials.h:180
ComputeEngineCredentials(std::string service_account_email)
Definition: compute_engine_credentials.h:155
StatusOr< std::string > AuthorizationHeader() override
Attempts to obtain a value for the Authorization HTTP header.
Definition: compute_engine_credentials.h:158
ComputeEngineCredentials()
Definition: compute_engine_credentials.h:153
std::set< std::string > scopes() const
Returns the set of scopes granted to this credential's service account.
Definition: compute_engine_credentials.h:192
std::string AccountEmail() const override
Return the account's email associated with these credentials, if any.
Definition: compute_engine_credentials.h:164
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
Authentication components for Google Cloud Storage.
Definition: anonymous_credentials.h:26
StatusOr< ServiceAccountMetadata > ParseMetadataServerResponse(storage::internal::HttpResponse const &response)
Parses a metadata server response JSON string into a ServiceAccountMetadata.
StatusOr< RefreshingCredentialsWrapper::TemporaryToken > ParseComputeEngineRefreshResponse(storage::internal::HttpResponse const &response, std::chrono::system_clock::time_point now)
Parses a refresh response JSON string into an authorization header.
Contains all the Google Cloud Storage C++ client APIs.
Definition: auto_finalize.h:24
A helper struct that contains service account metadata.
Definition: compute_engine_credentials.h:46
std::string email
Definition: compute_engine_credentials.h:48
std::set< std::string > scopes
Definition: compute_engine_credentials.h:47