3030from google .auth import metrics
3131from google .auth import transport
3232from google .auth ._exponential_backoff import ExponentialBackoff
33+ from google .auth .compute_engine import _mtls
34+ from google .auth .transport import requests
3335
3436_LOGGER = logging .getLogger (__name__ )
3537
4244 _GCE_METADATA_HOST = os .getenv (
4345 environment_vars .GCE_METADATA_ROOT , "metadata.google.internal"
4446 )
45- _METADATA_ROOT = "http://{}/computeMetadata/v1/" .format (_GCE_METADATA_HOST )
4647
47- # This is used to ping the metadata server, it avoids the cost of a DNS
48- # lookup.
49- _METADATA_IP_ROOT = "http://{}" .format (
50- os .getenv (environment_vars .GCE_METADATA_IP , "169.254.169.254" )
51- )
48+ GCE_MDS_HOSTS = ["metadata.google.internal" , "169.254.169.254" ]
49+
50+
51+ def _get_metadata_root (use_mtls ):
52+ """Returns the metadata server root URL."""
53+ scheme = "https" if use_mtls else "http"
54+ return "{}://{}/computeMetadata/v1/" .format (scheme , _GCE_METADATA_HOST )
55+
56+
57+ def _get_metadata_ip_root (use_mtls ):
58+ """Returns the metadata server IP root URL."""
59+ scheme = "https" if use_mtls else "http"
60+ return "{}://{}" .format (
61+ scheme , os .getenv (environment_vars .GCE_METADATA_IP , "169.254.169.254" )
62+ )
63+
64+
5265_METADATA_FLAVOR_HEADER = "metadata-flavor"
5366_METADATA_FLAVOR_VALUE = "Google"
5467_METADATA_HEADERS = {_METADATA_FLAVOR_HEADER : _METADATA_FLAVOR_VALUE }
@@ -102,6 +115,24 @@ def detect_gce_residency_linux():
102115 return content .startswith (_GOOGLE )
103116
104117
118+ def _prepare_request_for_mds (request , use_mtls = False ):
119+ """Prepares a request for the metadata server.
120+
121+ This will check if mTLS should be used and return a new request object if so.
122+
123+ Args:
124+ request (google.auth.transport.Request): A callable used to make
125+ HTTP requests.
126+
127+ Returns:
128+ google.auth.transport.Request: Request
129+ object to use.
130+ """
131+ if use_mtls :
132+ request = requests .Request (_mtls .create_session ())
133+ return request
134+
135+
105136def ping (request , timeout = _METADATA_DEFAULT_TIMEOUT , retry_count = 3 ):
106137 """Checks to see if the metadata server is available.
107138
@@ -115,6 +146,8 @@ def ping(request, timeout=_METADATA_DEFAULT_TIMEOUT, retry_count=3):
115146 Returns:
116147 bool: True if the metadata server is reachable, False otherwise.
117148 """
149+ use_mtls = _mtls .should_use_mds_mtls ()
150+ request = _prepare_request_for_mds (request , use_mtls = use_mtls )
118151 # NOTE: The explicit ``timeout`` is a workaround. The underlying
119152 # issue is that resolving an unknown host on some networks will take
120153 # 20-30 seconds; making this timeout short fixes the issue, but
@@ -129,7 +162,10 @@ def ping(request, timeout=_METADATA_DEFAULT_TIMEOUT, retry_count=3):
129162 for attempt in backoff :
130163 try :
131164 response = request (
132- url = _METADATA_IP_ROOT , method = "GET" , headers = headers , timeout = timeout
165+ url = _get_metadata_ip_root (use_mtls ),
166+ method = "GET" ,
167+ headers = headers ,
168+ timeout = timeout ,
133169 )
134170
135171 metadata_flavor = response .headers .get (_METADATA_FLAVOR_HEADER )
@@ -153,7 +189,7 @@ def ping(request, timeout=_METADATA_DEFAULT_TIMEOUT, retry_count=3):
153189def get (
154190 request ,
155191 path ,
156- root = _METADATA_ROOT ,
192+ root = None ,
157193 params = None ,
158194 recursive = False ,
159195 retry_count = 5 ,
@@ -190,6 +226,14 @@ def get(
190226 google.auth.exceptions.TransportError: if an error occurred while
191227 retrieving metadata.
192228 """
229+ use_mtls = _mtls .should_use_mds_mtls ()
230+ # Prepare the request object for mTLS if needed.
231+ # This will create a new request object with the mTLS session.
232+ request = _prepare_request_for_mds (request , use_mtls = use_mtls )
233+
234+ if root is None :
235+ root = _get_metadata_root (use_mtls )
236+
193237 base_url = urljoin (root , path )
194238 query_params = {} if params is None else params
195239
0 commit comments