@@ -36,6 +36,12 @@ namespace {
3636using ::google::cloud::testing_util::IsOk;
3737using ::google::cloud::testing_util::ScopedEnvironment;
3838
39+ auto constexpr kEndpointThatUsesRAB = " storage.googleapis.com" ;
40+
41+ MATCHER_P (NonEmptyHttpHeaderNameIs, header_name, " has non-empty header named" ) {
42+ return header_name == arg.name () && !arg.EmptyValues ();
43+ }
44+
3945StatusOr<std::unique_ptr<RestResponse>> RetryRestRequest (
4046 std::function<StatusOr<std::unique_ptr<RestResponse>>()> const & request) {
4147 auto backoff = google::cloud::ExponentialBackoffPolicy (
@@ -173,6 +179,134 @@ TEST(UnifiedRestCredentialsIntegrationTest, ServiceAccountCredentials) {
173179 MakeServiceAccountCredentials (contents))));
174180}
175181
182+ TEST (UnifiedRestCredentialsIntegrationTest, RABServiceAccountCredentialsOAuth) {
183+ ScopedEnvironment self_signed_jwt (
184+ " GOOGLE_CLOUD_CPP_EXPERIMENTAL_DISABLE_SELF_SIGNED_JWT" , " 1" );
185+
186+ auto env = internal::GetEnv (" GOOGLE_CLOUD_CPP_REST_TEST_KEY_FILE_JSON" );
187+ ASSERT_TRUE (env.has_value ());
188+ std::string key_file = std::move (*env);
189+ std::ifstream is (key_file);
190+ auto contents = std::string{std::istreambuf_iterator<char >{is}, {}};
191+
192+ auto creds = MakeServiceAccountCredentials (contents);
193+ auto creds_rest = MapCredentials (*creds);
194+
195+ auto headers = creds_rest->AuthenticationHeaders (
196+ std::chrono::system_clock::now (), kEndpointThatUsesRAB );
197+ EXPECT_THAT (headers,
198+ testing_util::IsOkAndHolds (::testing::Contains (
199+ NonEmptyHttpHeaderNameIs (std::string{" authorization" }))));
200+
201+ // x-allowed-locations header is fetched asynchronously.
202+ for (auto delay : {2 , 3 , 5 }) {
203+ std::this_thread::sleep_for (std::chrono::seconds (delay));
204+ headers = creds_rest->AuthenticationHeaders (
205+ std::chrono::system_clock::now (), kEndpointThatUsesRAB );
206+ if (headers.ok () && headers->size () > 1 ) break ;
207+ }
208+
209+ EXPECT_THAT (
210+ headers,
211+ testing_util::IsOkAndHolds (::testing::Contains (
212+ NonEmptyHttpHeaderNameIs (std::string{" x-allowed-locations" }))));
213+ }
214+
215+ TEST (UnifiedRestCredentialsIntegrationTest, RABServiceAccountCredentialsJWT) {
216+ auto env = internal::GetEnv (" GOOGLE_CLOUD_CPP_REST_TEST_KEY_FILE_JSON" );
217+ ASSERT_TRUE (env.has_value ());
218+ std::string key_file = std::move (*env);
219+ std::ifstream is (key_file);
220+ auto contents = std::string{std::istreambuf_iterator<char >{is}, {}};
221+
222+ auto creds = MakeServiceAccountCredentials (contents);
223+ auto creds_rest = MapCredentials (*creds);
224+
225+ auto headers = creds_rest->AuthenticationHeaders (
226+ std::chrono::system_clock::now (), kEndpointThatUsesRAB );
227+ EXPECT_THAT (headers,
228+ testing_util::IsOkAndHolds (::testing::Contains (
229+ NonEmptyHttpHeaderNameIs (std::string{" authorization" }))));
230+
231+ // x-allowed-locations header is fetched asynchronously.
232+ for (auto delay : {2 , 3 , 5 }) {
233+ std::this_thread::sleep_for (std::chrono::seconds (delay));
234+ headers = creds_rest->AuthenticationHeaders (
235+ std::chrono::system_clock::now (), kEndpointThatUsesRAB );
236+ if (headers.ok () && headers->size () > 1 ) break ;
237+ }
238+
239+ EXPECT_THAT (
240+ headers,
241+ testing_util::IsOkAndHolds (::testing::Contains (
242+ NonEmptyHttpHeaderNameIs (std::string{" x-allowed-locations" }))));
243+ }
244+
245+ TEST (UnifiedRestCredentialsIntegrationTest,
246+ RABImpersonateServiceAccountCredentialsJWT) {
247+ auto env = internal::GetEnv (" GOOGLE_CLOUD_CPP_REST_TEST_KEY_FILE_JSON" );
248+ ASSERT_TRUE (env.has_value ());
249+ std::string key_file = std::move (*env);
250+ std::ifstream is (key_file);
251+ auto contents = std::string{std::istreambuf_iterator<char >{is}, {}};
252+
253+ std::string impersonated_service_account =
254+ google::cloud::internal::GetEnv (
255+ " GOOGLE_CLOUD_CPP_PUBSUB_TEST_IMPERSONATED_SERVICE_ACCOUNT" )
256+ .value_or (" " );
257+
258+ auto sa_creds = MakeServiceAccountCredentials (contents);
259+ auto impersonate_creds = MakeImpersonateServiceAccountCredentials (
260+ sa_creds, impersonated_service_account);
261+ auto creds_rest = MapCredentials (*impersonate_creds);
262+
263+ auto headers = creds_rest->AuthenticationHeaders (
264+ std::chrono::system_clock::now (), kEndpointThatUsesRAB );
265+ EXPECT_THAT (headers,
266+ testing_util::IsOkAndHolds (::testing::Contains (
267+ NonEmptyHttpHeaderNameIs (std::string{" authorization" }))));
268+
269+ // x-allowed-locations header is fetched asynchronously.
270+ for (auto delay : {2 , 3 , 5 }) {
271+ std::this_thread::sleep_for (std::chrono::seconds (delay));
272+ headers = creds_rest->AuthenticationHeaders (
273+ std::chrono::system_clock::now (), kEndpointThatUsesRAB );
274+ if (headers.ok () && headers->size () > 1 ) break ;
275+ }
276+
277+ EXPECT_THAT (
278+ headers,
279+ testing_util::IsOkAndHolds (::testing::Contains (
280+ NonEmptyHttpHeaderNameIs (std::string{" x-allowed-locations" }))));
281+ }
282+
283+ TEST (UnifiedRestCredentialsIntegrationTest, RABComputeEngineCredentials) {
284+ auto oauth2_creds = MapCredentials (*MakeComputeEngineCredentials ());
285+ auto token = oauth2_creds->GetToken (std::chrono::system_clock::now ());
286+ // This test only works if we're running in a Google Production VM. Running in
287+ // other environments will always fail.
288+ if (!token.ok ()) GTEST_SKIP ();
289+
290+ auto headers = oauth2_creds->AuthenticationHeaders (
291+ std::chrono::system_clock::now (), kEndpointThatUsesRAB );
292+ EXPECT_THAT (headers,
293+ testing_util::IsOkAndHolds (::testing::Contains (
294+ NonEmptyHttpHeaderNameIs (std::string{" authorization" }))));
295+
296+ // x-allowed-locations header is fetched asynchronously.
297+ for (auto delay : {2 , 3 , 5 }) {
298+ std::this_thread::sleep_for (std::chrono::seconds (delay));
299+ headers = oauth2_creds->AuthenticationHeaders (
300+ std::chrono::system_clock::now (), kEndpointThatUsesRAB );
301+ if (headers.ok () && headers->size () > 1 ) break ;
302+ }
303+
304+ EXPECT_THAT (
305+ headers,
306+ testing_util::IsOkAndHolds (::testing::Contains (
307+ NonEmptyHttpHeaderNameIs (std::string{" x-allowed-locations" }))));
308+ }
309+
176310TEST (UnifiedRestCredentialsIntegrationTest, StorageGoogleDefaultCredentials) {
177311 ASSERT_NO_FATAL_FAILURE (MakeStorageRpcCall (
178312 Options{}.set <UnifiedCredentialsOption>(MakeGoogleDefaultCredentials ())));
0 commit comments