Skip to content

Commit fb08254

Browse files
committed
Implement additional unit tests for the trust boundary
1 parent baefc0f commit fb08254

File tree

7 files changed

+460
-55
lines changed

7 files changed

+460
-55
lines changed

google/auth/credentials.py

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@
2525
from google.auth import exceptions
2626
from google.auth import metrics
2727
from google.auth._credentials_base import _BaseCredentials
28+
from google.auth._default import _LOGGER
2829
from google.auth._refresh_worker import RefreshThreadManager
2930

3031
DEFAULT_UNIVERSE_DOMAIN = "googleapis.com"
3132
NO_OP_TRUST_BOUNDARY_LOCATIONS: "typing.Tuple[str]" = ()
3233
NO_OP_TRUST_BOUNDARY_ENCODED_LOCATIONS = "0x0"
33-
TRUST_BOUNDARY_ENV_VAR = "GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED"
3434

3535

3636
class Credentials(_BaseCredentials):
@@ -310,7 +310,16 @@ def apply(self, headers, token=None):
310310
"""Apply the token to the authentication header."""
311311
super().apply(headers, token)
312312
if self._trust_boundary is not None:
313-
headers["x-allowed-locations"] = self._trust_boundary["encodedLocations"]
313+
if (
314+
self._trust_boundary["encodedLocations"]
315+
== NO_OP_TRUST_BOUNDARY_ENCODED_LOCATIONS
316+
):
317+
# STS expects an empty string if the trust boundary value is no-op.
318+
headers["x-allowed-locations"] = ""
319+
else:
320+
headers["x-allowed-locations"] = self._trust_boundary[
321+
"encodedLocations"
322+
]
314323

315324
def _refresh_trust_boundary(self, request):
316325
"""Triggers a refresh of the trust boundary and updates the cache if necessary.
@@ -333,7 +342,11 @@ def _refresh_trust_boundary(self, request):
333342
# If the call to the lookup API failed, check if there is a trust boundary
334343
# already cached. If there is, do nothing. If not, then throw the error.
335344
if self._trust_boundary is None:
336-
raise (error)
345+
raise error
346+
if _helpers.is_logging_enabled(_LOGGER):
347+
_LOGGER.debug(
348+
"Using cached trust boundary due to refresh error: %s", error
349+
)
337350
return
338351
else:
339352
self._trust_boundary = new_trust_boundary
@@ -353,9 +366,12 @@ def _lookup_trust_boundary(self, request):
353366
retrieved.
354367
"""
355368
from google.oauth2 import _client
356-
357-
# Verify the trust boundary feature flag is enabled.
358-
if os.getenv(TRUST_BOUNDARY_ENV_VAR, "").lower() != "true":
369+
370+
# Verify the trust boundary feature flag is enabled.
371+
if (
372+
os.getenv(environment_vars.GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED, "").lower()
373+
!= "true"
374+
):
359375
# Skip the lookup and return early if it's not explicitly enabled.
360376
return
361377

@@ -364,6 +380,8 @@ def _lookup_trust_boundary(self, request):
364380
return
365381

366382
url = self._build_trust_boundary_lookup_url()
383+
if not url:
384+
raise exceptions.InvalidValue("Failed to build trust boundary lookup URL.")
367385
return _client.lookup_trust_boundary(request, url, self.token)
368386

369387
@abc.abstractmethod
@@ -378,22 +396,9 @@ def _build_trust_boundary_lookup_url(self):
378396
str: The URL for the trust boundary lookup endpoint, or None
379397
if lookup should be skipped (e.g., for non-applicable universe domains).
380398
"""
381-
raise NotImplementedError("_build_trust_boundary_lookup_url must be implemented")
382-
383-
@staticmethod
384-
def _parse_trust_boundary(trust_boundary_string: str):
385-
try:
386-
trust_boundary = json.loads(trust_boundary_string)
387-
if (
388-
"locations" not in trust_boundary
389-
or "encodedLocations" not in trust_boundary
390-
):
391-
raise exceptions.MalformedError
392-
return trust_boundary
393-
except Exception:
394-
raise exceptions.MalformedError(
395-
"Cannot parse trust boundary {}".format(trust_boundary_string)
396-
)
399+
raise NotImplementedError(
400+
"_build_trust_boundary_lookup_url must be implemented"
401+
)
397402

398403
def _has_no_op_trust_boundary(self):
399404
# A no-op trust boundary is indicated by encodedLocations being "0x0".
@@ -490,8 +495,7 @@ def default_scopes(self):
490495

491496
@abc.abstractproperty
492497
def requires_scopes(self):
493-
"""True if these credentials require scopes to obtain an access token.
494-
"""
498+
"""True if these credentials require scopes to obtain an access token."""
495499
return False
496500

497501
def has_scopes(self, scopes):

google/auth/environment_vars.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,7 @@
8282
AWS_SESSION_TOKEN = "AWS_SESSION_TOKEN"
8383
AWS_REGION = "AWS_REGION"
8484
AWS_DEFAULT_REGION = "AWS_DEFAULT_REGION"
85+
86+
GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED = "GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED"
87+
"""Environment variable controlling whether to enable trust boundary feature.
88+
The default value is false. Users have to explicitly set this value to true."""

google/oauth2/_client.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,17 @@ def _token_endpoint_request(
256256
an error.
257257
"""
258258

259-
response_status_ok, response_data, retryable_error = _token_endpoint_request_no_throw(
260-
request,
261-
token_uri,
262-
body,
263-
access_token=access_token,
264-
use_json=use_json,
265-
can_retry=can_retry,
266-
headers=headers,
267-
**kwargs
259+
response_status_ok, response_data, retryable_error = (
260+
_token_endpoint_request_no_throw(
261+
request,
262+
token_uri,
263+
body,
264+
access_token=access_token,
265+
use_json=use_json,
266+
can_retry=can_retry,
267+
headers=headers,
268+
**kwargs
269+
)
268270
)
269271
if not response_status_ok:
270272
_handle_error_response(response_data, retryable_error)
@@ -509,7 +511,7 @@ def refresh_grant(
509511

510512

511513
def lookup_trust_boundary(request, url, access_token):
512-
""" Implements the global lookup of a credential trust boundary.
514+
"""Implements the global lookup of a credential trust boundary.
513515
For the lookup, we send a request to the global lookup endpoint and then
514516
parse the response. Service account credentials, workload identity
515517
pools and workforce pools implementation may have trust boundaries configured.
@@ -549,7 +551,7 @@ def lookup_trust_boundary(request, url, access_token):
549551
"""
550552

551553
response_data = _lookup_trust_boundary_request(request, url, access_token, True)
552-
#In case of no-op response, the "locations" list may or may not be present as an empty list.
554+
# In case of no-op response, the "locations" list may or may not be present as an empty list.
553555
if "encodedLocations" not in response_data:
554556
raise exceptions.MalformedError(
555557
"Invalid trust boundary info: {}".format(response_data)
@@ -583,8 +585,10 @@ def _lookup_trust_boundary_request(
583585
google.auth.exceptions.RefreshError: If the token endpoint returned
584586
an error.
585587
"""
586-
response_status_ok, response_data, retryable_error = _lookup_trust_boundary_request_no_throw(
587-
request, url, access_token=access_token, can_retry=can_retry, **kwargs
588+
response_status_ok, response_data, retryable_error = (
589+
_lookup_trust_boundary_request_no_throw(
590+
request, url, access_token=access_token, can_retry=can_retry, **kwargs
591+
)
588592
)
589593
if not response_status_ok:
590594
_handle_error_response(response_data, retryable_error)

tests/oauth2/test__client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ def test_lookup_trust_boundary():
650650
assert response["encodedLocations"] == "0x80080000000000"
651651
assert response["locations"] == ["us-central1", "us-east1"]
652652

653+
653654
def test_lookup_trust_boundary_no_op_response_without_locations():
654655
response_data = {"encodedLocations": "0x0"}
655656

@@ -665,6 +666,7 @@ def test_lookup_trust_boundary_no_op_response_without_locations():
665666
assert response["encodedLocations"] == "0x0"
666667
assert "locations" not in response
667668

669+
668670
def test_lookup_trust_boundary_no_op_response():
669671
response_data = {"locations": [], "encodedLocations": "0x0"}
670672

0 commit comments

Comments
 (0)