Skip to content

Commit b42122e

Browse files
authored
Revert "fix(auth): parse hostname for mTLS and PSC endpoint certifica… (#18189)
(#18153) This reverts commit b642373.
1 parent b02d467 commit b42122e

6 files changed

Lines changed: 21 additions & 238 deletions

File tree

packages/google-auth/google/auth/transport/_mtls_helper.py

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import sys
2525
import tempfile
2626
from typing import cast, Generator, List, Optional, Tuple, Union
27-
from urllib.parse import urlsplit
2827

2928
from google.auth import _agent_identity_utils
3029
from google.auth import _cloud_sdk
@@ -841,50 +840,3 @@ def call_client_cert_callback():
841840
generate_encrypted_key=True
842841
)
843842
return cert_bytes, key_bytes
844-
845-
846-
_MTLS_HOST_SUFFIXES = (
847-
".mtls.googleapis.com",
848-
".mtls.sandbox.googleapis.com",
849-
".p.googleapis.com",
850-
)
851-
_MTLS_EXACT_HOSTS = (
852-
"mtls.googleapis.com",
853-
"mtls.sandbox.googleapis.com",
854-
"p.googleapis.com",
855-
)
856-
857-
858-
def is_mtls_endpoint(url: Optional[Union[str, bytes, object]]) -> bool:
859-
"""Checks if the given URL corresponds to an mTLS or Private Service Connect (PSC) endpoint.
860-
861-
Args:
862-
url (Optional[Union[str, bytes, object]]): The request URL.
863-
864-
Returns:
865-
bool: True if the URL targets an mTLS or PSC endpoint, False otherwise.
866-
"""
867-
if not url:
868-
return False
869-
if hasattr(url, "url") and isinstance(url.url, (str, bytes)):
870-
url = url.url
871-
if isinstance(url, bytes):
872-
try:
873-
url = url.decode("utf-8")
874-
except (UnicodeDecodeError, AttributeError):
875-
return False
876-
elif not isinstance(url, str):
877-
url = str(url)
878-
try:
879-
hostname = urlsplit(url).hostname
880-
except (ValueError, TypeError, AttributeError):
881-
return False
882-
883-
if not hostname:
884-
return False
885-
886-
hostname = hostname.rstrip(".").lower()
887-
if not hostname:
888-
return False
889-
890-
return hostname in _MTLS_EXACT_HOSTS or hostname.endswith(_MTLS_HOST_SUFFIXES)

packages/google-auth/google/auth/transport/requests.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,13 @@ def request(
647647
):
648648
# Handle unauthorized permission error(401 status code)
649649
if response.status_code == http_client.UNAUTHORIZED:
650-
use_mtls = self.is_mtls and _mtls_helper.is_mtls_endpoint(url)
650+
MTLS_URL_PREFIXES = [
651+
"mtls.googleapis.com",
652+
"mtls.sandbox.googleapis.com",
653+
]
654+
use_mtls = self.is_mtls and any(
655+
prefix in url for prefix in MTLS_URL_PREFIXES
656+
)
651657
if use_mtls:
652658
(
653659
call_cert_bytes,

packages/google-auth/google/auth/transport/urllib3.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,11 @@ def urlopen(self, method, url, body=None, headers=None, **kwargs):
409409
if headers is None:
410410
headers = self.headers
411411

412+
use_mtls = False
413+
if self._is_mtls:
414+
MTLS_URL_PREFIXES = ["mtls.googleapis.com", "mtls.sandbox.googleapis.com"]
415+
use_mtls = any([prefix in url for prefix in MTLS_URL_PREFIXES])
416+
412417
# Make a copy of the headers. They will be modified by the credentials
413418
# and we want to pass the original headers if we recurse.
414419
request_headers = headers.copy()
@@ -431,7 +436,6 @@ def urlopen(self, method, url, body=None, headers=None, **kwargs):
431436
and _credential_refresh_attempt < self._max_refresh_attempts
432437
):
433438
if response.status == http_client.UNAUTHORIZED:
434-
use_mtls = self._is_mtls and _mtls_helper.is_mtls_endpoint(url)
435439
if use_mtls:
436440
(
437441
call_cert_bytes,

packages/google-auth/tests/transport/test__mtls_helper.py

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
from cryptography.hazmat.primitives import hashes, serialization
2222
from cryptography.hazmat.primitives.asymmetric import ec
2323
import pytest # type: ignore
24-
import urllib3.util
2524

2625
from google.auth import environment_vars, exceptions
2726
from google.auth.transport import _mtls_helper
@@ -1889,80 +1888,3 @@ def test_remove_oserror_ignored(
18891888
mock_fh.flush.assert_called_once()
18901889
mock_fsync.assert_called_once()
18911890
mock_remove.assert_called_once_with("/path/to/secret")
1892-
1893-
1894-
class TestIsMtlsEndpoint(object):
1895-
@pytest.mark.parametrize(
1896-
"url",
1897-
[
1898-
"https://mtls.googleapis.com",
1899-
"https://mtls.googleapis.com/",
1900-
"https://mtls.googleapis.com/v1/projects",
1901-
"https://mtls.sandbox.googleapis.com",
1902-
"https://mtls.sandbox.googleapis.com/v1/projects",
1903-
"https://pubsub.mtls.googleapis.com",
1904-
"https://pubsub.mtls.googleapis.com/v1/projects/my-project",
1905-
"https://storage.mtls.sandbox.googleapis.com/b/my-bucket",
1906-
"https://my-service.us-east1.rep.mtls.googleapis.com/v1",
1907-
"https://my-service.us-east1.rep.mtls.sandbox.googleapis.com/v1",
1908-
"https://storage.p.googleapis.com/b/my-bucket",
1909-
"https://my-custom-endpoint.p.googleapis.com/v1",
1910-
"https://my-service.us-east1.p.googleapis.com/v1",
1911-
"HTTP://PUBSUB.MTLS.GOOGLEAPIS.COM/V1",
1912-
b"https://pubsub.mtls.googleapis.com",
1913-
b"https://storage.p.googleapis.com/b/my-bucket",
1914-
urllib3.util.parse_url("https://pubsub.mtls.googleapis.com/v1"),
1915-
urllib3.util.parse_url("https://storage.p.googleapis.com/b/my-bucket"),
1916-
"https://pubsub.mtls.googleapis.com.",
1917-
"https://storage.p.googleapis.com./b/my-bucket",
1918-
"https://mtls.googleapis.com.",
1919-
"https://pubsub.mtls.googleapis.com:443/v1",
1920-
"https://pubsub.mtls.googleapis.com:8443/v1",
1921-
"https://storage.p.googleapis.com:443/b/my-bucket",
1922-
"https://pubsub.mtls.googleapis.com/v1/projects?pageSize=10#frag",
1923-
"https://pubsub.mtls.googleapis.com:443/v1/projects?pageSize=10&filter=foo#frag",
1924-
"https://storage.p.googleapis.com:443/b/my-bucket?param=1#section",
1925-
"https://mtls.googleapis.com:443/",
1926-
"https://p.googleapis.com",
1927-
"https://p.googleapis.com/",
1928-
"https://p.googleapis.com:443/v1",
1929-
"https://p.googleapis.com.",
1930-
],
1931-
)
1932-
def test_is_mtls_endpoint_true(self, url):
1933-
assert _mtls_helper.is_mtls_endpoint(url) is True
1934-
1935-
@pytest.mark.parametrize(
1936-
"url",
1937-
[
1938-
"https://storage.googleapis.com",
1939-
"https://storage.googleapis.com.",
1940-
"https://storage.googleapis.com:443/b/my-bucket",
1941-
"https://storage.googleapis.com:443/bucket/mtls.googleapis.com?pageSize=10#frag",
1942-
"https://storage.googleapis.com/bucket/mtls.googleapis.com",
1943-
"https://[2001:db8::1]:443/mtls.googleapis.com",
1944-
"https://[::1]:8443/mtls.googleapis.com",
1945-
"https://logging.googleapis.com/v2/entries?filter=mtls.googleapis.com",
1946-
"https://logging.googleapis.com/v2/entries?filter=mtls.sandbox.googleapis.com",
1947-
"https://logging.googleapis.com/v2/entries?filter=service.p.googleapis.com",
1948-
"https://example.com/mtls.googleapis.com",
1949-
"https://fake-mtls.googleapis.com.attacker.com/v1",
1950-
"https://fake-p.googleapis.com.attacker.com/v1",
1951-
"http://localhost:8080/",
1952-
"http://localhost:8080/mtls.googleapis.com",
1953-
b"https://storage.googleapis.com",
1954-
b"https://storage.googleapis.com/bucket/mtls.googleapis.com",
1955-
b"\xff\xfeinvalid",
1956-
urllib3.util.parse_url("https://storage.googleapis.com/b/my-bucket"),
1957-
urllib3.util.parse_url(
1958-
"https://storage.googleapis.com/bucket/mtls.googleapis.com"
1959-
),
1960-
"https://.",
1961-
"",
1962-
None,
1963-
123,
1964-
"not a url",
1965-
],
1966-
)
1967-
def test_is_mtls_endpoint_false(self, url):
1968-
assert _mtls_helper.is_mtls_endpoint(url) is False

packages/google-auth/tests/transport/test_requests.py

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -664,9 +664,6 @@ def test_configure_mtls_channel_cert_loading_exceptions(
664664

665665
assert not auth_session.is_mtls
666666

667-
@mock.patch(
668-
"google.auth.transport._mtls_helper._get_cert_config_path", return_value=None
669-
)
670667
@mock.patch(
671668
"google.auth.transport._mtls_helper.get_client_cert_and_key", autospec=True
672669
)
@@ -680,7 +677,7 @@ def test_configure_mtls_channel_cert_loading_exceptions(
680677
},
681678
)
682679
def test_configure_mtls_channel_without_client_cert_env(
683-
self, get_client_cert_and_key, mock_get_cert_config_path
680+
self, get_client_cert_and_key
684681
):
685682
env_to_patch = {
686683
environment_vars.GOOGLE_API_USE_CLIENT_CERTIFICATE: "",
@@ -942,7 +939,7 @@ def test_cert_rotation_logic_skipped_on_other_refresh_status_codes(self):
942939

943940
def test_cert_rotation_skipped_on_non_mtls_url(self):
944941
"""
945-
Tests that mTLS cert rotation is skipped on non-mTLS URLs even if
942+
Tests that mTLS cert rotation is skipped on a non-mTLS URL even if
946943
mTLS is enabled and an UNAUTHORIZED (401) response is received.
947944
"""
948945
credentials = mock.Mock(wraps=CredentialsStub())
@@ -953,56 +950,22 @@ def test_cert_rotation_skipped_on_non_mtls_url(self):
953950
make_response(status=http_client.OK),
954951
]
955952
)
956-
non_mtls_url = "https://storage.googleapis.com/bucket/mtls.googleapis.com"
957953
authed_session = google.auth.transport.requests.AuthorizedSession(
958954
credentials, refresh_timeout=60
959955
)
960-
authed_session.mount("https://", adapter)
956+
authed_session.mount(self.TEST_URL, adapter)
961957
authed_session._is_mtls = True
962-
authed_session._cached_cert = b"cached_cert"
963958

964-
with mock.patch.object(
965-
google.auth.transport._mtls_helper,
966-
"check_parameters_for_unauthorized_response",
967-
) as mock_check_params:
968-
authed_session.request("GET", non_mtls_url)
959+
with mock.patch(
960+
"google.auth.transport.requests._mtls_helper", autospec=True
961+
) as mock_helper:
962+
authed_session.request("GET", self.TEST_URL)
969963

970964
# Assert refresh happened
971965
assert credentials.refresh.called
972966

973967
# Assert mTLS check logic was SKIPPED
974-
assert not mock_check_params.called
975-
976-
def test_cert_rotation_triggered_on_psc_url(self):
977-
"""
978-
Tests that mTLS cert rotation IS triggered on a Private Service Connect
979-
(PSC) mTLS endpoint when an UNAUTHORIZED (401) response is received.
980-
"""
981-
credentials = mock.Mock(wraps=CredentialsStub())
982-
adapter = AdapterStub(
983-
[
984-
make_response(status=http_client.UNAUTHORIZED),
985-
make_response(status=http_client.OK),
986-
]
987-
)
988-
psc_url = "https://storage.p.googleapis.com/b/my-bucket"
989-
authed_session = google.auth.transport.requests.AuthorizedSession(
990-
credentials, refresh_timeout=60
991-
)
992-
authed_session.mount(psc_url, adapter)
993-
authed_session._is_mtls = True
994-
authed_session._cached_cert = b"cached_cert"
995-
996-
with mock.patch.object(
997-
google.auth.transport._mtls_helper,
998-
"check_parameters_for_unauthorized_response",
999-
return_value=(b"new_cert", b"new_key", "old_fp", "old_fp"),
1000-
) as mock_check_params:
1001-
authed_session.request("GET", psc_url)
1002-
1003-
# Assert mTLS check logic was called on PSC endpoint
1004-
mock_check_params.assert_called_once()
1005-
assert credentials.refresh.called
968+
assert not mock_helper.check_parameters_for_unauthorized_response.called
1006969

1007970
def test_configure_mtls_channel_subsequent_failure(self):
1008971
# 1. Setup successful mTLS configuration

packages/google-auth/tests/transport/test_urllib3.py

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -385,9 +385,6 @@ def test_configure_mtls_channel_cert_loading_exceptions(
385385

386386
assert not authed_http._is_mtls
387387

388-
@mock.patch(
389-
"google.auth.transport._mtls_helper._get_cert_config_path", return_value=None
390-
)
391388
@mock.patch(
392389
"google.auth.transport._mtls_helper.get_client_cert_and_key", autospec=True
393390
)
@@ -401,7 +398,7 @@ def test_configure_mtls_channel_cert_loading_exceptions(
401398
},
402399
)
403400
def test_configure_mtls_channel_without_client_cert_env(
404-
self, get_client_cert_and_key, mock_get_cert_config_path
401+
self, get_client_cert_and_key
405402
):
406403
callback = mock.Mock()
407404

@@ -658,67 +655,6 @@ def test_cert_rotation_logic_skipped_on_other_refresh_status_codes(self):
658655
# Assert mTLS check logic was SKIPPED (Inner Check was False)
659656
assert not mock_helper.check_parameters_for_unauthorized_response.called
660657

661-
def test_cert_rotation_skipped_on_non_mtls_url(self):
662-
"""
663-
Tests that mTLS cert rotation is skipped on non-mTLS URLs even if
664-
mTLS is enabled and an UNAUTHORIZED (401) response is received.
665-
"""
666-
credentials = mock.Mock(wraps=CredentialsStub())
667-
http = HttpStub(
668-
[
669-
ResponseStub(status=http_client.UNAUTHORIZED),
670-
ResponseStub(status=http_client.OK),
671-
]
672-
)
673-
non_mtls_url = "https://storage.googleapis.com/bucket/mtls.googleapis.com"
674-
authed_http = google.auth.transport.urllib3.AuthorizedHttp(
675-
credentials, http=http
676-
)
677-
authed_http._is_mtls = True
678-
authed_http._cached_cert = b"cached_cert"
679-
680-
with mock.patch.object(
681-
google.auth.transport._mtls_helper,
682-
"check_parameters_for_unauthorized_response",
683-
) as mock_check_params:
684-
authed_http.urlopen("GET", non_mtls_url)
685-
686-
# Assert refresh happened
687-
assert credentials.refresh.called
688-
689-
# Assert mTLS check logic was SKIPPED
690-
assert not mock_check_params.called
691-
692-
def test_cert_rotation_triggered_on_psc_url(self):
693-
"""
694-
Tests that mTLS cert rotation IS triggered on a Private Service Connect
695-
(PSC) mTLS endpoint when an UNAUTHORIZED (401) response is received.
696-
"""
697-
credentials = mock.Mock(wraps=CredentialsStub())
698-
http = HttpStub(
699-
[
700-
ResponseStub(status=http_client.UNAUTHORIZED),
701-
ResponseStub(status=http_client.OK),
702-
]
703-
)
704-
psc_url = "https://storage.p.googleapis.com/b/my-bucket"
705-
authed_http = google.auth.transport.urllib3.AuthorizedHttp(
706-
credentials, http=http
707-
)
708-
authed_http._is_mtls = True
709-
authed_http._cached_cert = b"cached_cert"
710-
711-
with mock.patch.object(
712-
google.auth.transport._mtls_helper,
713-
"check_parameters_for_unauthorized_response",
714-
return_value=(b"new_cert", b"new_key", "old_fp", "old_fp"),
715-
) as mock_check_params:
716-
authed_http.urlopen("GET", psc_url)
717-
718-
# Assert mTLS check logic was called on PSC endpoint
719-
mock_check_params.assert_called_once()
720-
assert credentials.refresh.called
721-
722658
@mock.patch("google.auth.transport.urllib3._make_mutual_tls_http", autospec=True)
723659
def test_configure_mtls_channel_subsequent_failure(self, mock_make_mutual_tls_http):
724660
callback = mock.Mock()

0 commit comments

Comments
 (0)