Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 614a3d0

Browse filesBrowse files
fix(auth): use requests transport for GCE MDS (#16480)
Fixes #16090 We were seeing errors on GCE environments, because the library would use _http_client to communicate to the metadata server, even when mTLS is enabled. This resulted in failures, because _http_client doesn't support https. This PR addresses the issue by using requests as the transport instead. This depends on the optional `requests` dependency, but requests is already [required by compute engine](https://github.com/googleapis/google-cloud-python/blob/51a96200324965f071dd9542d25b907c1420b3f6/packages/google-auth/google/auth/compute_engine/_metadata.py#L27), so there are no changes there. I was able to reproduce and verify this test on a GCE VM --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent dea6a1b commit 614a3d0
Copy full SHA for 614a3d0

3 files changed

+47-10Lines changed: 47 additions & 10 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎packages/google-auth/google/auth/_default.py‎

Copy file name to clipboardExpand all lines: packages/google-auth/google/auth/_default.py
+5-9Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,10 @@
2727

2828
from google.auth import environment_vars
2929
from google.auth import exceptions
30-
import google.auth.transport._http_client
3130

3231
if TYPE_CHECKING: # pragma: NO COVER
33-
from google.auth.credentials import Credentials # noqa: F401
34-
from google.auth.transport import Request # noqa: F401
32+
import google.auth.credentials.Credentials # type: ignore
33+
import google.auth.transport.Request # type: ignore
3534

3635
_LOGGER = logging.getLogger(__name__)
3736

@@ -390,22 +389,19 @@ def _get_gae_credentials():
390389

391390
def _get_gce_credentials(request=None, quota_project_id=None):
392391
"""Gets credentials and project ID from the GCE Metadata Service."""
393-
# Ping requires a transport, but we want application default credentials
394-
# to require no arguments. So, we'll use the _http_client transport which
395-
# uses http.client. This is only acceptable because the metadata server
396-
# doesn't do SSL and never requires proxies.
397-
398392
# While this library is normally bundled with compute_engine, there are
399393
# some cases where it's not available, so we tolerate ImportError.
394+
# Compute Engine requires optional `requests` dependency.
400395
try:
401396
from google.auth import compute_engine
402397
from google.auth.compute_engine import _metadata
398+
import google.auth.transport.requests
403399
except ImportError:
404400
_LOGGER.warning("Import of Compute Engine auth library failed.")
405401
return None, None
406402

407403
if request is None:
408-
request = google.auth.transport._http_client.Request()
404+
request = google.auth.transport.requests.Request()
409405

410406
if _metadata.is_on_gce(request=request):
411407
# Get the project ID.
Collapse file

‎packages/google-auth/google/auth/transport/_http_client.py‎

Copy file name to clipboardExpand all lines: packages/google-auth/google/auth/transport/_http_client.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def __call__(
9494
if parts.scheme != "http":
9595
raise exceptions.TransportError(
9696
"http.client transport only supports the http scheme, {}"
97-
"was specified".format(parts.scheme)
97+
" was specified".format(parts.scheme)
9898
)
9999

100100
connection = http_client.HTTPConnection(parts.netloc, timeout=timeout)
Collapse file

‎packages/google-auth/tests/test__default.py‎

Copy file name to clipboardExpand all lines: packages/google-auth/tests/test__default.py
+41Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,18 @@ def test__get_gce_credentials_explicit_request(ping):
890890
ping.assert_called_with(request=mock.sentinel.request)
891891

892892

893+
@mock.patch(
894+
"google.auth.compute_engine._metadata.is_on_gce", return_value=False, autospec=True
895+
)
896+
@mock.patch("google.auth.transport.requests.Request", autospec=True)
897+
def test__get_gce_credentials_default_request(mock_request_cls, ping):
898+
credentials, project_id = _default._get_gce_credentials()
899+
mock_request_cls.assert_called_once()
900+
ping.assert_called_with(request=mock_request_cls.return_value)
901+
assert credentials is None
902+
assert project_id is None
903+
904+
893905
@mock.patch(
894906
"google.auth._default._get_explicit_environ_credentials",
895907
return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),
@@ -1006,6 +1018,35 @@ def test_default_fail(unused_gce, unused_gae, unused_sdk, unused_explicit):
10061018
assert excinfo.match(_default._CLOUD_SDK_MISSING_CREDENTIALS)
10071019

10081020

1021+
@mock.patch(
1022+
"google.auth._default._get_explicit_environ_credentials",
1023+
return_value=(None, None),
1024+
autospec=True,
1025+
)
1026+
@mock.patch(
1027+
"google.auth._default._get_gcloud_sdk_credentials",
1028+
return_value=(None, None),
1029+
autospec=True,
1030+
)
1031+
@mock.patch(
1032+
"google.auth._default._get_gae_credentials",
1033+
return_value=(None, None),
1034+
autospec=True,
1035+
)
1036+
@mock.patch(
1037+
"google.auth.compute_engine._metadata.is_on_gce", return_value=False, autospec=True
1038+
)
1039+
@mock.patch("google.auth.transport.requests.Request", autospec=True)
1040+
def test_default_gce_triggers_request_creation(
1041+
mock_request_cls, is_on_gce, unused_gae, unused_sdk, unused_explicit
1042+
):
1043+
with pytest.raises(exceptions.DefaultCredentialsError):
1044+
_default.default()
1045+
1046+
mock_request_cls.assert_called_once()
1047+
is_on_gce.assert_called_once_with(request=mock_request_cls.return_value)
1048+
1049+
10091050
@mock.patch(
10101051
"google.auth._default._get_explicit_environ_credentials",
10111052
return_value=(MOCK_CREDENTIALS, mock.sentinel.project_id),

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.