From ac0f4976e94e245c2d13c1e87b52c53e6076eee9 Mon Sep 17 00:00:00 2001 From: Ana Salazar Date: Tue, 23 Sep 2025 16:16:45 +0000 Subject: [PATCH 1/2] Implement GoogleDefaultCredentials for hard bound tokens --- .../internal/unified_grpc_credentials.cc | 10 +++++++++- .../internal/unified_grpc_credentials_test.cc | 17 ++++++++++++++++ google/cloud/storage/grpc_plugin.h | 7 +++++++ .../storage/internal/grpc/default_options.cc | 20 +++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/google/cloud/internal/unified_grpc_credentials.cc b/google/cloud/internal/unified_grpc_credentials.cc index b1c82e99f2586..5d78768e538f1 100644 --- a/google/cloud/internal/unified_grpc_credentials.cc +++ b/google/cloud/internal/unified_grpc_credentials.cc @@ -102,8 +102,16 @@ std::shared_ptr CreateAuthenticationStrategy( grpc::InsecureChannelCredentials()); } void visit(GoogleDefaultCredentialsConfig const&) override { + auto const options = + storage_internal::DefaultOptionsGrpc::DefaultOptionsGrpc({}); + bool use_bound_tokens = + storage_internal::GrpcEnableBoundTokenssIsSafe() && + options.get(); + grpc::GoogleDefaultCredentialsOptions credentials_options = {}; + credentials_options.use_alts = use_bound_tokens; result = std::make_unique( - grpc::GoogleDefaultCredentials()); + grpc::GoogleDefaultCredentials(&credentials_options)); } void visit(AccessTokenConfig const& cfg) override { result = std::make_unique( diff --git a/google/cloud/internal/unified_grpc_credentials_test.cc b/google/cloud/internal/unified_grpc_credentials_test.cc index 4aa2f6ca1e53e..27781f096cff4 100644 --- a/google/cloud/internal/unified_grpc_credentials_test.cc +++ b/google/cloud/internal/unified_grpc_credentials_test.cc @@ -98,6 +98,23 @@ TEST(UnifiedGrpcCredentialsTest, WithDefaultCredentials) { ASSERT_EQ(nullptr, context.credentials()); } +TEST(UnifiedGrpcCredentialsTest, WithDefaultCredentialsAndHardBoundToken) { + // Create a filename for a file that (most likely) does not exist. We just + // want to initialize the default credentials, the filename won't be used by + // the test. + ScopedEnvironment env("GOOGLE_APPLICATION_CREDENTIALS", "unused.json"); + + CompletionQueue cq; + auto result = CreateAuthenticationStrategy( + *MakeGoogleDefaultCredentials(), cq, + Options{}.set(true)); + ASSERT_NE(nullptr, result.get()); + grpc::ClientContext context; + auto status = result->ConfigureContext(context); + EXPECT_THAT(status, IsOk()); + ASSERT_EQ(nullptr, context.credentials()); +} + TEST(UnifiedGrpcCredentialsTest, WithAccessTokenCredentials) { auto const expiration = std::chrono::system_clock::now() + std::chrono::hours(1); diff --git a/google/cloud/storage/grpc_plugin.h b/google/cloud/storage/grpc_plugin.h index 045c0f7fea0c5..9d58413405c22 100644 --- a/google/cloud/storage/grpc_plugin.h +++ b/google/cloud/storage/grpc_plugin.h @@ -102,6 +102,13 @@ struct GrpcMetricsPeriodOption { using Type = std::chrono::seconds; }; +/** + * Enable gRPC Bound Tokens Authentication. + */ +struct EnableGrpcHardBoundTokensAuthenticationOption { + using Type = bool; +}; + GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace storage_experimental } // namespace cloud diff --git a/google/cloud/storage/internal/grpc/default_options.cc b/google/cloud/storage/internal/grpc/default_options.cc index e693ace81ad81..2c0efefbac392 100644 --- a/google/cloud/storage/internal/grpc/default_options.cc +++ b/google/cloud/storage/internal/grpc/default_options.cc @@ -146,6 +146,26 @@ bool GrpcEnableMetricsIsSafe() { #endif // GRPC_CPP_VERSION_MAJOR } +bool GrpcEnableHardBoundTokensIsSafe(int major, int minor, int patch) { + // Never happens. No 0.x version is supported or implements the version + // macros, but it makes the rest more readable. + if (major < 1) return false; + if (major > 1) return true; + if (minor <= 62) return false; + if (minor == 63) return patch >= 1; + if (minor == 64) return patch >= 1; + return true; +} + +bool GrpcEnableHardBoundTokensIsSafe() { +#ifndef GRPC_CPP_VERSION_MAJOR + return false; +#else + return GrpcEnableHardBoundTokensIsSafe(GRPC_CPP_VERSION_MAJOR, GRPC_CPP_VERSION_MINOR, + GRPC_CPP_VERSION_PATCH); +#endif // GRPC_CPP_VERSION_MAJOR +} + GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace storage_internal } // namespace cloud From 31ca08d8a8669688e6958d05c6553bfceeaf0f4a Mon Sep 17 00:00:00 2001 From: Ana Salazar Date: Tue, 23 Sep 2025 20:25:47 +0000 Subject: [PATCH 2/2] Move new option outside of storage --- google/cloud/grpc_options.cc | 24 +++++++++++++++++++ google/cloud/grpc_options.h | 13 ++++++++++ .../internal/unified_grpc_credentials.cc | 11 ++++----- google/cloud/storage/grpc_plugin.h | 7 ------ .../storage/internal/grpc/default_options.cc | 20 ---------------- 5 files changed, 42 insertions(+), 33 deletions(-) diff --git a/google/cloud/grpc_options.cc b/google/cloud/grpc_options.cc index c5f42ed01c0f9..20422296f75e8 100644 --- a/google/cloud/grpc_options.cc +++ b/google/cloud/grpc_options.cc @@ -160,6 +160,30 @@ BackgroundThreadsFactory MakeBackgroundThreadsFactory(Options const& opts) { }; } +namespace experimental { + +bool GrpcEnableHardBoundTokensIsSafe(int major, int minor, int patch) { + // Never happens. No 0.x version is supported or implements the version + // macros, but it makes the rest more readable. + if (major < 1) return false; + if (major > 1) return true; + if (minor <= 62) return false; + if (minor == 63) return patch >= 1; + if (minor == 64) return patch >= 1; + return true; +} + +bool GrpcEnableHardBoundTokensIsSafe() { +#ifndef GRPC_CPP_VERSION_MAJOR + return false; +#else + return GrpcEnableHardBoundTokensIsSafe( + GRPC_CPP_VERSION_MAJOR, GRPC_CPP_VERSION_MINOR, GRPC_CPP_VERSION_PATCH); +#endif // GRPC_CPP_VERSION_MAJOR +} + +} + } // namespace internal GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace cloud diff --git a/google/cloud/grpc_options.h b/google/cloud/grpc_options.h index 92eee8969f044..f2459a1101491 100644 --- a/google/cloud/grpc_options.h +++ b/google/cloud/grpc_options.h @@ -262,6 +262,19 @@ absl::optional GetStringChannelArgument( */ BackgroundThreadsFactory MakeBackgroundThreadsFactory(Options const& opts = {}); +namespace experimental{ + +/** + * Enable gRPC Bound Tokens Authentication. + */ +struct EnableGrpcHardBoundTokensAuthenticationOption { + using Type = bool; +}; + +bool GrpcEnableHardBoundTokensIsSafe(); + +} // namespace experimental + } // namespace internal GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace cloud diff --git a/google/cloud/internal/unified_grpc_credentials.cc b/google/cloud/internal/unified_grpc_credentials.cc index 5d78768e538f1..0433de94d9d41 100644 --- a/google/cloud/internal/unified_grpc_credentials.cc +++ b/google/cloud/internal/unified_grpc_credentials.cc @@ -102,14 +102,13 @@ std::shared_ptr CreateAuthenticationStrategy( grpc::InsecureChannelCredentials()); } void visit(GoogleDefaultCredentialsConfig const&) override { - auto const options = - storage_internal::DefaultOptionsGrpc::DefaultOptionsGrpc({}); bool use_bound_tokens = - storage_internal::GrpcEnableBoundTokenssIsSafe() && - options.get(); + google::cloud::internal::experimental:: + GrpcEnableHardBoundTokensIsSafe() && + options.get(); grpc::GoogleDefaultCredentialsOptions credentials_options = {}; - credentials_options.use_alts = use_bound_tokens; + credentials_options.use_alts_call_credentials = use_bound_tokens; result = std::make_unique( grpc::GoogleDefaultCredentials(&credentials_options)); } diff --git a/google/cloud/storage/grpc_plugin.h b/google/cloud/storage/grpc_plugin.h index 9d58413405c22..045c0f7fea0c5 100644 --- a/google/cloud/storage/grpc_plugin.h +++ b/google/cloud/storage/grpc_plugin.h @@ -102,13 +102,6 @@ struct GrpcMetricsPeriodOption { using Type = std::chrono::seconds; }; -/** - * Enable gRPC Bound Tokens Authentication. - */ -struct EnableGrpcHardBoundTokensAuthenticationOption { - using Type = bool; -}; - GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace storage_experimental } // namespace cloud diff --git a/google/cloud/storage/internal/grpc/default_options.cc b/google/cloud/storage/internal/grpc/default_options.cc index 2c0efefbac392..e693ace81ad81 100644 --- a/google/cloud/storage/internal/grpc/default_options.cc +++ b/google/cloud/storage/internal/grpc/default_options.cc @@ -146,26 +146,6 @@ bool GrpcEnableMetricsIsSafe() { #endif // GRPC_CPP_VERSION_MAJOR } -bool GrpcEnableHardBoundTokensIsSafe(int major, int minor, int patch) { - // Never happens. No 0.x version is supported or implements the version - // macros, but it makes the rest more readable. - if (major < 1) return false; - if (major > 1) return true; - if (minor <= 62) return false; - if (minor == 63) return patch >= 1; - if (minor == 64) return patch >= 1; - return true; -} - -bool GrpcEnableHardBoundTokensIsSafe() { -#ifndef GRPC_CPP_VERSION_MAJOR - return false; -#else - return GrpcEnableHardBoundTokensIsSafe(GRPC_CPP_VERSION_MAJOR, GRPC_CPP_VERSION_MINOR, - GRPC_CPP_VERSION_PATCH); -#endif // GRPC_CPP_VERSION_MAJOR -} - GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace storage_internal } // namespace cloud