|
13 | 13 | // limitations under the License. |
14 | 14 |
|
15 | 15 | #include "google/cloud/internal/oauth2_service_account_credentials.h" |
| 16 | +#include "google/cloud/credentials.h" |
16 | 17 | #include "google/cloud/internal/absl_str_join_quiet.h" |
17 | 18 | #include "google/cloud/internal/getenv.h" |
18 | 19 | #include "google/cloud/internal/make_jwt_assertion.h" |
19 | 20 | #include "google/cloud/internal/make_status.h" |
20 | 21 | #include "google/cloud/internal/oauth2_google_credentials.h" |
21 | 22 | #include "google/cloud/internal/oauth2_universe_domain.h" |
| 23 | +#include "google/cloud/internal/parse_service_account_p12_file.h" |
22 | 24 | #include "google/cloud/internal/rest_response.h" |
23 | 25 | #include "google/cloud/internal/sign_using_sha256.h" |
24 | 26 | #include <nlohmann/json.hpp> |
| 27 | +#include <fstream> |
25 | 28 | #include <functional> |
26 | 29 |
|
27 | 30 | namespace google { |
@@ -240,6 +243,74 @@ StatusOr<std::string> MakeSelfSignedJWT( |
240 | 243 | info.private_key); |
241 | 244 | } |
242 | 245 |
|
| 246 | +StatusOr<std::shared_ptr<Credentials>> |
| 247 | +CreateServiceAccountCredentialsFromJsonContents( |
| 248 | + std::string const& contents, Options const& options, |
| 249 | + HttpClientFactory client_factory) { |
| 250 | + auto info = ParseServiceAccountCredentials(contents, "memory"); |
| 251 | + if (!info) return info.status(); |
| 252 | + |
| 253 | + if (options.has<ScopesOption>()) { |
| 254 | + auto const& s = options.get<ScopesOption>(); |
| 255 | + std::set<std::string> scopes{s.begin(), s.end()}; |
| 256 | + info->scopes = std::move(scopes); |
| 257 | + } |
| 258 | + |
| 259 | + // Verify this is usable before returning it. |
| 260 | + auto const tp = std::chrono::system_clock::time_point{}; |
| 261 | + auto const components = AssertionComponentsFromInfo(*info, tp); |
| 262 | + auto jwt = MakeJWTAssertionNoThrow(components.first, components.second, |
| 263 | + info->private_key); |
| 264 | + if (!jwt) return jwt.status(); |
| 265 | + return StatusOr<std::shared_ptr<Credentials>>( |
| 266 | + std::make_shared<ServiceAccountCredentials>(*info, options, |
| 267 | + std::move(client_factory))); |
| 268 | +} |
| 269 | + |
| 270 | +StatusOr<std::shared_ptr<Credentials>> |
| 271 | +CreateServiceAccountCredentialsFromJsonFilePath( |
| 272 | + std::string const& path, Options const& options, |
| 273 | + HttpClientFactory client_factory) { |
| 274 | + std::ifstream is(path); |
| 275 | + if (!is.is_open()) { |
| 276 | + // We use kUnknown here because we don't know if the file does not exist, or |
| 277 | + // if we were unable to open it for some other reason. |
| 278 | + return internal::UnknownError("Cannot open credentials file " + path, |
| 279 | + GCP_ERROR_INFO()); |
| 280 | + } |
| 281 | + std::string contents(std::istreambuf_iterator<char>{is}, {}); |
| 282 | + return CreateServiceAccountCredentialsFromJsonContents( |
| 283 | + std::move(contents), options, std::move(client_factory)); |
| 284 | +} |
| 285 | + |
| 286 | +StatusOr<std::shared_ptr<Credentials>> |
| 287 | +CreateServiceAccountCredentialsFromP12FilePath( |
| 288 | + std::string const& path, Options const& options, |
| 289 | + HttpClientFactory client_factory) { |
| 290 | + auto info = ParseServiceAccountP12File(path); |
| 291 | + if (!info) return std::move(info).status(); |
| 292 | + |
| 293 | + if (options.has<ScopesOption>()) { |
| 294 | + auto const& s = options.get<ScopesOption>(); |
| 295 | + std::set<std::string> scopes{s.begin(), s.end()}; |
| 296 | + info->scopes = std::move(scopes); |
| 297 | + } |
| 298 | + return StatusOr<std::shared_ptr<Credentials>>( |
| 299 | + std::make_shared<ServiceAccountCredentials>(*info, options, |
| 300 | + std::move(client_factory))); |
| 301 | +} |
| 302 | + |
| 303 | +StatusOr<std::shared_ptr<Credentials>> |
| 304 | +CreateServiceAccountCredentialsFromFilePath(std::string const& path, |
| 305 | + Options const& options, |
| 306 | + HttpClientFactory client_factory) { |
| 307 | + auto credentials = CreateServiceAccountCredentialsFromJsonFilePath( |
| 308 | + path, options, client_factory); |
| 309 | + if (credentials) return *credentials; |
| 310 | + return CreateServiceAccountCredentialsFromP12FilePath( |
| 311 | + path, options, std::move(client_factory)); |
| 312 | +} |
| 313 | + |
243 | 314 | ServiceAccountCredentials::ServiceAccountCredentials( |
244 | 315 | ServiceAccountCredentialsInfo info, Options options, |
245 | 316 | HttpClientFactory client_factory) |
@@ -313,7 +384,8 @@ bool ServiceAccountUseOAuth(ServiceAccountCredentialsInfo const& info) { |
313 | 384 | } |
314 | 385 |
|
315 | 386 | bool ServiceAccountCredentials::UseOAuth() { |
316 | | - return ServiceAccountUseOAuth(info_); |
| 387 | + return options_.has<DisableSelfSignedJWTOption>() || |
| 388 | + ServiceAccountUseOAuth(info_); |
317 | 389 | } |
318 | 390 |
|
319 | 391 | StatusOr<AccessToken> ServiceAccountCredentials::GetTokenOAuth( |
|
0 commit comments