From 386f4791ab708be24f338634c4b1c9696b39d029 Mon Sep 17 00:00:00 2001 From: Matt Castelaz Date: Thu, 7 May 2026 17:09:33 +0000 Subject: [PATCH 1/2] feat(auth): implement in-place Regional Access Boundary configuration & public getters - Rename _with_regional_access_boundary to _set_regional_access_boundary and _with_blocking_regional_access_boundary_lookup to _set_blocking_regional_access_boundary_lookup. - Modify both methods to apply changes in-place on self and return self instead of making copies. - Add public getters regional_access_boundary and regional_access_boundary_expiry to CredentialsWithRegionalAccessBoundary. - Update and split unit tests to verify in-place mutation and getters independently. --- .../google-auth/google/auth/credentials.py | 38 +++++++++++------- .../tests/compute_engine/test_credentials.py | 8 ++-- .../tests/oauth2/test_credentials.py | 8 ++-- .../test__regional_access_boundary_utils.py | 40 +++++++++++++++---- .../google-auth/tests/test_credentials.py | 2 +- 5 files changed, 64 insertions(+), 32 deletions(-) diff --git a/packages/google-auth/google/auth/credentials.py b/packages/google-auth/google/auth/credentials.py index 8d39f871c86a..5421bf917bd4 100644 --- a/packages/google-auth/google/auth/credentials.py +++ b/packages/google-auth/google/auth/credentials.py @@ -309,6 +309,16 @@ def __init__(self): _regional_access_boundary_utils._RegionalAccessBoundaryManager() ) + @property + def regional_access_boundary(self): + """Optional[str]: The encoded Regional Access Boundary locations.""" + return self._rab_manager._data.encoded_locations + + @property + def regional_access_boundary_expiry(self): + """Optional[datetime.datetime]: The expiration time of the Regional Access Boundary.""" + return self._rab_manager._data.expiry + @abc.abstractmethod def _perform_refresh_token(self, request): """Refreshes the access token. @@ -361,39 +371,37 @@ def _copy_regional_access_boundary_manager(self, target): new_manager._data = self._rab_manager._data target._rab_manager = new_manager - def _with_regional_access_boundary(self, seed): - """Returns a copy of these credentials with the the regional_access_boundary - set to the provided seed. This is intended for internal use only as invalid + def _set_regional_access_boundary(self, seed): + """Applies the regional_access_boundary set to the provided seed on these + credentials. This is intended for internal use only as invalid seeds would produce unexpected results until automatic recovery is supported. Currently this is used by the gcloud CLI and therefore changes to the contract MUST be backwards compatible (e.g. the method signature must be - unchanged and a copy of the credenials with the RAB set must be returned). + unchanged and the credentials with the RAB set must be returned). Returns: - google.auth.credentials.Credentials: A new credentials instance. + google.auth.credentials.Credentials: The credentials instance. """ - creds = self._make_copy() - creds._rab_manager.set_initial_regional_access_boundary( + self._rab_manager.set_initial_regional_access_boundary( encoded_locations=seed.get("encodedLocations", None), expiry=seed.get("expiry", None), ) - return creds + return self - def _with_blocking_regional_access_boundary_lookup(self): - """Returns a copy of these credentials with the blocking lookup mode enabled. + def _set_blocking_regional_access_boundary_lookup(self): + """Enables the blocking lookup mode on these credentials. This is intended for internal use only as blocking lookup requires additional care and consideration. Currently this is used by the gcloud CLI and therefore changes to the contract MUST be backwards compatible (e.g. the - method signature must be unchanged and a copy of the credentials with the + method signature must be unchanged and the credentials with the blocking lookup flag set to true must be returned). Returns: - google.auth.credentials.Credentials: A new credentials instance. + google.auth.credentials.Credentials: The credentials instance. """ - creds = self._make_copy() - creds._rab_manager.enable_blocking_lookup() - return creds + self._rab_manager.enable_blocking_lookup() + return self def _maybe_start_regional_access_boundary_refresh(self, request, url): """ diff --git a/packages/google-auth/tests/compute_engine/test_credentials.py b/packages/google-auth/tests/compute_engine/test_credentials.py index 7cd4dc445da5..5a60ffd44145 100644 --- a/packages/google-auth/tests/compute_engine/test_credentials.py +++ b/packages/google-auth/tests/compute_engine/test_credentials.py @@ -451,13 +451,13 @@ def test_refresh_with_agent_identity_opt_out_or_not_agent( kwargs = mock_metadata_get.call_args[1] assert "bindCertificateFingerprint" not in kwargs.get("params", {}) - def test_with_blocking_regional_access_boundary_lookup(self): + def test_set_blocking_regional_access_boundary_lookup(self): creds = self.credentials assert not creds._rab_manager._use_blocking_regional_access_boundary_lookup - new_creds = creds._with_blocking_regional_access_boundary_lookup() - assert new_creds._rab_manager._use_blocking_regional_access_boundary_lookup - assert new_creds is not creds + new_creds = creds._set_blocking_regional_access_boundary_lookup() + assert creds._rab_manager._use_blocking_regional_access_boundary_lookup + assert new_creds is creds class TestIDTokenCredentials(object): diff --git a/packages/google-auth/tests/oauth2/test_credentials.py b/packages/google-auth/tests/oauth2/test_credentials.py index 67c5308450c3..5a1ec2f757ad 100644 --- a/packages/google-auth/tests/oauth2/test_credentials.py +++ b/packages/google-auth/tests/oauth2/test_credentials.py @@ -96,13 +96,13 @@ def test_default_state(self): assert credentials.rapt_token == self.RAPT_TOKEN assert credentials.refresh_handler is None - def test_with_blocking_regional_access_boundary_lookup(self): + def test_set_blocking_regional_access_boundary_lookup(self): creds = self.make_credentials() assert not creds._rab_manager._use_blocking_regional_access_boundary_lookup - new_creds = creds._with_blocking_regional_access_boundary_lookup() - assert new_creds._rab_manager._use_blocking_regional_access_boundary_lookup - assert new_creds is not creds + new_creds = creds._set_blocking_regional_access_boundary_lookup() + assert creds._rab_manager._use_blocking_regional_access_boundary_lookup + assert new_creds is creds def test_get_cred_info(self): credentials = self.make_credentials() diff --git a/packages/google-auth/tests/test__regional_access_boundary_utils.py b/packages/google-auth/tests/test__regional_access_boundary_utils.py index cce8ec2725e8..ab6ec75fd9b8 100644 --- a/packages/google-auth/tests/test__regional_access_boundary_utils.py +++ b/packages/google-auth/tests/test__regional_access_boundary_utils.py @@ -224,23 +224,47 @@ def test_apply_headers_removes_header_if_empty(self): creds._rab_manager.apply_headers(headers) assert headers == {} - def test_with_blocking_regional_access_boundary_lookup(self): + def test_set_blocking_regional_access_boundary_lookup(self): creds = CredentialsImpl() assert not creds._rab_manager._use_blocking_regional_access_boundary_lookup - new_creds = creds._with_blocking_regional_access_boundary_lookup() - assert new_creds._rab_manager._use_blocking_regional_access_boundary_lookup + new_creds = creds._set_blocking_regional_access_boundary_lookup() + assert new_creds is creds + assert creds._rab_manager._use_blocking_regional_access_boundary_lookup - def test_with_regional_access_boundary(self): + def test_set_regional_access_boundary(self): creds = CredentialsImpl() seed = { "encodedLocations": "0xABC", "expiry": _helpers.utcnow() + datetime.timedelta(hours=1), } - new_creds = creds._with_regional_access_boundary(seed) - assert new_creds._rab_manager._data.encoded_locations == "0xABC" - assert new_creds._rab_manager._data.expiry == seed["expiry"] - assert new_creds._rab_manager._data.cooldown_expiry is None + new_creds = creds._set_regional_access_boundary(seed) + assert new_creds is creds + assert creds._rab_manager._data.encoded_locations == "0xABC" + assert creds._rab_manager._data.expiry == seed["expiry"] + assert creds._rab_manager._data.cooldown_expiry is None + + def test_regional_access_boundary_getter(self): + creds = CredentialsImpl() + assert creds.regional_access_boundary is None + + seed = { + "encodedLocations": "0xABC", + "expiry": _helpers.utcnow() + datetime.timedelta(hours=1), + } + creds._set_regional_access_boundary(seed) + assert creds.regional_access_boundary == "0xABC" + + def test_regional_access_boundary_expiry_getter(self): + creds = CredentialsImpl() + assert creds.regional_access_boundary_expiry is None + + seed = { + "encodedLocations": "0xABC", + "expiry": _helpers.utcnow() + datetime.timedelta(hours=1), + } + creds._set_regional_access_boundary(seed) + assert creds.regional_access_boundary_expiry == seed["expiry"] def test_copy_regional_access_boundary_state(self): source_creds = CredentialsImpl() diff --git a/packages/google-auth/tests/test_credentials.py b/packages/google-auth/tests/test_credentials.py index d79a1ef06ba9..e1528a3ce365 100644 --- a/packages/google-auth/tests/test_credentials.py +++ b/packages/google-auth/tests/test_credentials.py @@ -403,7 +403,7 @@ def test_before_request_triggers_rab_refresh(): lookup.return_value = {"encodedLocations": "0xA30"} creds = CredentialsImpl() - creds = creds._with_blocking_regional_access_boundary_lookup() + creds = creds._set_blocking_regional_access_boundary_lookup() request = mock.Mock() headers = {} From 8461ce01c07c4f561b5c8b3c3075e6faf8313b32 Mon Sep 17 00:00:00 2001 From: macastelaz <34776182+macastelaz@users.noreply.github.com> Date: Thu, 7 May 2026 12:36:03 -0500 Subject: [PATCH 2/2] feat(auth): Fix typo in docstring for _set_regional_access_boundary --- packages/google-auth/google/auth/credentials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google-auth/google/auth/credentials.py b/packages/google-auth/google/auth/credentials.py index 5421bf917bd4..4a686cb01907 100644 --- a/packages/google-auth/google/auth/credentials.py +++ b/packages/google-auth/google/auth/credentials.py @@ -372,7 +372,7 @@ def _copy_regional_access_boundary_manager(self, target): target._rab_manager = new_manager def _set_regional_access_boundary(self, seed): - """Applies the regional_access_boundary set to the provided seed on these + """Applies the regional_access_boundary provided via the seed on these credentials. This is intended for internal use only as invalid seeds would produce unexpected results until automatic recovery is supported. Currently this is used by the gcloud CLI and therefore changes to the