Skip to content

Commit f46998c

Browse files
authored
impl(oauth2): add method populate AllowedLocationsRequest type to Credentials (#16080)
1 parent 7063180 commit f46998c

22 files changed

Lines changed: 294 additions & 60 deletions

google/cloud/BUILD.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ cc_library(
237237
name = "google_cloud_cpp_rest_internal",
238238
srcs = google_cloud_cpp_rest_internal_srcs,
239239
hdrs = google_cloud_cpp_rest_internal_hdrs,
240+
# TODO(#16079): Remove macro definition when GA.
241+
cxxopts = ["-DGOOGLE_CLOUD_CPP_TESTING_ENABLE_RAB"],
240242
linkopts = select({
241243
"@platforms//os:windows": [
242244
"-DEFAULTLIB:bcrypt.lib",
@@ -273,6 +275,8 @@ cc_library(
273275
[cc_test(
274276
name = test.replace("/", "_").replace(".cc", ""),
275277
srcs = [test],
278+
# TODO(#16079): Remove macro definition when GA.
279+
cxxopts = ["-DGOOGLE_CLOUD_CPP_TESTING_ENABLE_RAB"],
276280
deps = [
277281
":google_cloud_cpp_rest_internal",
278282
"//google/cloud/testing_util:google_cloud_cpp_testing_private",

google/cloud/internal/oauth2_api_key_credentials.cc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,9 @@ StatusOr<AccessToken> ApiKeyCredentials::GetToken(
2727
return AccessToken{std::string{}, tp};
2828
}
2929

30-
StatusOr<std::vector<rest_internal::HttpHeader>>
31-
ApiKeyCredentials::AuthenticationHeaders(std::chrono::system_clock::time_point,
32-
std::string_view) {
33-
std::vector<rest_internal::HttpHeader> headers;
34-
headers.emplace_back("x-goog-api-key", api_key_);
35-
return headers;
30+
StatusOr<rest_internal::HttpHeader> ApiKeyCredentials::Authorization(
31+
std::chrono::system_clock::time_point) {
32+
return rest_internal::HttpHeader{"x-goog-api-key", api_key_};
3633
}
3734

3835
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END

google/cloud/internal/oauth2_api_key_credentials.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ class ApiKeyCredentials : public oauth2_internal::Credentials {
3737
StatusOr<AccessToken> GetToken(
3838
std::chrono::system_clock::time_point tp) override;
3939

40-
StatusOr<std::vector<rest_internal::HttpHeader>> AuthenticationHeaders(
41-
std::chrono::system_clock::time_point,
42-
std::string_view endpoint) override;
40+
StatusOr<rest_internal::HttpHeader> Authorization(
41+
std::chrono::system_clock::time_point tp) override;
4342

4443
private:
4544
std::string api_key_;

google/cloud/internal/oauth2_cached_credentials.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ StatusOr<std::string> CachedCredentials::project_id(
8383
return impl_->project_id(options);
8484
}
8585

86+
Credentials::AllowedLocationsRequestType
87+
CachedCredentials::AllowedLocationsRequest() const {
88+
return impl_->AllowedLocationsRequest();
89+
}
90+
8691
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
8792
} // namespace oauth2_internal
8893
} // namespace cloud

google/cloud/internal/oauth2_cached_credentials.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class CachedCredentials : public Credentials {
5454
StatusOr<std::string> universe_domain(Options const& options) const override;
5555
StatusOr<std::string> project_id() const override;
5656
StatusOr<std::string> project_id(Options const& options) const override;
57+
Credentials::AllowedLocationsRequestType AllowedLocationsRequest()
58+
const override;
5759

5860
private:
5961
std::shared_ptr<Credentials> impl_;

google/cloud/internal/oauth2_compute_engine_credentials.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,16 @@ StatusOr<std::string> ComputeEngineCredentials::project_id(
239239
return RetrieveProjectId(lk, options);
240240
}
241241

242+
Credentials::AllowedLocationsRequestType
243+
ComputeEngineCredentials::AllowedLocationsRequest() const {
244+
// TODO(#16079): Remove conditional and else clause when GA.
245+
#ifdef GOOGLE_CLOUD_CPP_TESTING_ENABLE_RAB
246+
return ServiceAccountAllowedLocationsRequest{AccountEmail()};
247+
#else
248+
return std::monostate{};
249+
#endif
250+
}
251+
242252
StatusOr<std::string> ComputeEngineCredentials::RetrieveUniverseDomain(
243253
std::lock_guard<std::mutex> const&, Options const& options) const {
244254
// Fetch the universe domain only once.

google/cloud/internal/oauth2_compute_engine_credentials.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ class ComputeEngineCredentials : public Credentials {
118118
StatusOr<std::string> project_id(
119119
google::cloud::Options const& options) const override;
120120

121+
AllowedLocationsRequestType AllowedLocationsRequest() const override;
122+
121123
/**
122124
* Returns the email or alias of this credential's service account.
123125
*

google/cloud/internal/oauth2_compute_engine_credentials_test.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ using ::testing::Property;
5353
using ::testing::Return;
5454
using ::testing::UnorderedElementsAre;
5555
using ::testing::UnorderedElementsAreArray;
56+
using ::testing::VariantWith;
5657

5758
using MockHttpClientFactory =
5859
::testing::MockFunction<std::unique_ptr<rest_internal::RestClient>(
@@ -387,6 +388,10 @@ TEST(ComputeEngineCredentialsTest, FailedRefresh) {
387388
HasSubstr("Could not find all required fields")));
388389
}
389390

391+
MATCHER_P(RequestServiceAccountEmailIs, email, "has service account email") {
392+
return email == arg.service_account_email;
393+
}
394+
390395
/// @test Verify that we can force a refresh of the service account email.
391396
TEST(ComputeEngineCredentialsTest, AccountEmail) {
392397
auto const alias = std::string{"default"};
@@ -416,6 +421,15 @@ TEST(ComputeEngineCredentialsTest, AccountEmail) {
416421
auto refreshed_email = credentials.AccountEmail();
417422
EXPECT_EQ(email, refreshed_email);
418423
EXPECT_EQ(credentials.service_account_email(), refreshed_email);
424+
// TODO(#16079): Remove conditional and else clause when GA.
425+
#ifdef GOOGLE_CLOUD_CPP_TESTING_ENABLE_RAB
426+
EXPECT_THAT(credentials.AllowedLocationsRequest(),
427+
VariantWith<ServiceAccountAllowedLocationsRequest>(
428+
RequestServiceAccountEmailIs(email)));
429+
#else
430+
EXPECT_THAT(credentials.AllowedLocationsRequest(),
431+
VariantWith<std::monostate>(std::monostate()));
432+
#endif
419433
}
420434

421435
auto expected_universe_domain_request = []() {

google/cloud/internal/oauth2_credentials.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ Credentials::AuthenticationHeaders(std::chrono::system_clock::time_point tp,
3131
if (!authorization->empty()) headers.push_back(*std::move(authorization));
3232

3333
auto allowed_locations = AllowedLocations(tp, endpoint);
34-
// Not all credential types support the x-allowed-locations header. For those
35-
// that do, if there is a problem retrieving the header, omit the header.
34+
// Not all credential types support the x-allowed-locations header. For
35+
// those that do, if there is a problem retrieving the header, omit the
36+
// header.
3637
if (allowed_locations.ok() && !allowed_locations->empty()) {
3738
headers.push_back(*std::move(allowed_locations));
3839
}

google/cloud/internal/oauth2_credentials.h

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,27 @@
2222
#include "google/cloud/version.h"
2323
#include <chrono>
2424
#include <string>
25+
#include <variant>
2526
#include <vector>
2627

2728
namespace google {
2829
namespace cloud {
2930
namespace oauth2_internal {
3031
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
3132

33+
struct ServiceAccountAllowedLocationsRequest {
34+
std::string service_account_email;
35+
};
36+
37+
struct WorkloadIdentityAllowedLocationsRequest {
38+
std::string project_id;
39+
std::string pool_id;
40+
};
41+
42+
struct WorkforceIdentityAllowedLocationsRequest {
43+
std::string pool_id;
44+
};
45+
3246
/**
3347
* Interface for OAuth 2.0 credentials for use with Google's Unified Auth Client
3448
* (GUAC) library. Internally, GUAC credentials are mapped to the appropriate
@@ -69,9 +83,8 @@ class Credentials {
6983
* @param endpoint the endpoint of the GCP service the RPC request will be
7084
* sent to.
7185
*/
72-
virtual StatusOr<std::vector<rest_internal::HttpHeader>>
73-
AuthenticationHeaders(std::chrono::system_clock::time_point tp,
74-
std::string_view endpoint);
86+
StatusOr<std::vector<rest_internal::HttpHeader>> AuthenticationHeaders(
87+
std::chrono::system_clock::time_point tp, std::string_view endpoint);
7588

7689
/**
7790
* Try to sign @p string_to_sign using @p service_account.
@@ -160,6 +173,20 @@ class Credentials {
160173
*/
161174
virtual StatusOr<AccessToken> GetToken(
162175
std::chrono::system_clock::time_point tp) = 0;
176+
177+
using AllowedLocationsRequestType =
178+
std::variant<std::monostate, ServiceAccountAllowedLocationsRequest,
179+
WorkforceIdentityAllowedLocationsRequest,
180+
WorkloadIdentityAllowedLocationsRequest>;
181+
/**
182+
* Obtains the request type from the underlying credential, if supported.
183+
*
184+
* Not all credential types support the `x-allowed-locations` header, but
185+
* those that do vary in the data needed to format the request to IAM.
186+
*/
187+
virtual AllowedLocationsRequestType AllowedLocationsRequest() const {
188+
return std::monostate{};
189+
}
163190
};
164191

165192
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END

0 commit comments

Comments
 (0)