From 03c071332c651a40cdf262d2649950730bb87390 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Tue, 20 Feb 2024 12:01:19 -0800 Subject: [PATCH 1/5] Update _metadata.py Move the logic to read GCE_METADATA_TIMEOUT env variable so we can better control it in app_identity component. Related internal change is 607513254. --- google/auth/compute_engine/_metadata.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/google/auth/compute_engine/_metadata.py b/google/auth/compute_engine/_metadata.py index 108cbfe93..cf5c35b84 100644 --- a/google/auth/compute_engine/_metadata.py +++ b/google/auth/compute_engine/_metadata.py @@ -53,10 +53,7 @@ # Timeout in seconds to wait for the GCE metadata server when detecting the # GCE environment. -try: - _METADATA_DEFAULT_TIMEOUT = int(os.getenv("GCE_METADATA_TIMEOUT", 3)) -except ValueError: # pragma: NO COVER - _METADATA_DEFAULT_TIMEOUT = 3 +_METADATA_DEFAULT_TIMEOUT = 3 # Detect GCE Residency _GOOGLE = "Google" @@ -119,6 +116,11 @@ def ping(request, timeout=_METADATA_DEFAULT_TIMEOUT, retry_count=3): # could lead to false negatives in the event that we are on GCE, but # the metadata resolution was particularly slow. The latter case is # "unlikely". + try: + timeout = float(os.getenv("GCE_METADATA_TIMEOUT", timeout)) + except ValueError: # pragma: NO COVER + pass + retries = 0 headers = _METADATA_HEADERS.copy() headers[metrics.API_CLIENT_HEADER] = metrics.mds_ping() From 7100b593d39fcd07a6fa244a3f80d1da6c91a03d Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Fri, 23 Feb 2024 12:24:58 -0800 Subject: [PATCH 2/5] Update _metadata.py --- google/auth/compute_engine/_metadata.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/google/auth/compute_engine/_metadata.py b/google/auth/compute_engine/_metadata.py index cf5c35b84..4b10d2d3c 100644 --- a/google/auth/compute_engine/_metadata.py +++ b/google/auth/compute_engine/_metadata.py @@ -97,7 +97,7 @@ def detect_gce_residency_linux(): return content.startswith(_GOOGLE) -def ping(request, timeout=_METADATA_DEFAULT_TIMEOUT, retry_count=3): +def ping(request, timeout=None, retry_count=3): """Checks to see if the metadata server is available. Args: @@ -116,10 +116,8 @@ def ping(request, timeout=_METADATA_DEFAULT_TIMEOUT, retry_count=3): # could lead to false negatives in the event that we are on GCE, but # the metadata resolution was particularly slow. The latter case is # "unlikely". - try: - timeout = float(os.getenv("GCE_METADATA_TIMEOUT", timeout)) - except ValueError: # pragma: NO COVER - pass + if timeout is None: + timeout = float(os.getenv("GCE_METADATA_TIMEOUT", _METADATA_DEFAULT_TIMEOUT)) retries = 0 headers = _METADATA_HEADERS.copy() From d5620def3d0a66e374256e96e0f4096c9427ac93 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Fri, 12 Apr 2024 13:31:31 -0700 Subject: [PATCH 3/5] Add a test with new _metadata.py changes --- google/auth/compute_engine/_metadata.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/google/auth/compute_engine/_metadata.py b/google/auth/compute_engine/_metadata.py index 786d39b03..d3ca4c8d7 100644 --- a/google/auth/compute_engine/_metadata.py +++ b/google/auth/compute_engine/_metadata.py @@ -53,8 +53,7 @@ # Timeout in seconds to wait for the GCE metadata server when detecting the # GCE environment. -_METADATA_DEFAULT_TIMEOUT = 3 - +_METADATA_PING_DEFAULT_TIMEOUT = 3 # Detect GCE Residency _GOOGLE = "Google" _GCE_PRODUCT_NAME_FILE = "/sys/class/dmi/id/product_name" @@ -117,7 +116,12 @@ def ping(request, timeout=None, retry_count=3): # the metadata resolution was particularly slow. The latter case is # "unlikely". if timeout is None: - timeout = float(os.getenv("GCE_METADATA_TIMEOUT", _METADATA_DEFAULT_TIMEOUT)) + try: + timeout = float(os.getenv( + environment_vars.GCE_METADATA_TIMEOUT, + str(_METADATA_PING_DEFAULT_TIMEOUT))) + except ValueError: + timeout = _METADATA_PING_DEFAULT_TIMEOUT retries = 0 headers = _METADATA_HEADERS.copy() From afb2519ae4ac5263921a6ff0b2ec9c28ed7ece2d Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Fri, 12 Apr 2024 13:32:23 -0700 Subject: [PATCH 4/5] Add tests for metadata changes. --- tests/compute_engine/test__metadata.py | 43 ++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/tests/compute_engine/test__metadata.py b/tests/compute_engine/test__metadata.py index 60ae355ac..846e968b9 100644 --- a/tests/compute_engine/test__metadata.py +++ b/tests/compute_engine/test__metadata.py @@ -105,8 +105,45 @@ def test_ping_success(mock_metrics_header_value): request.assert_called_once_with( method="GET", url=_metadata._METADATA_IP_ROOT, - headers=MDS_PING_REQUEST_HEADER, - timeout=_metadata._METADATA_DEFAULT_TIMEOUT, + headers=_metadata._METADATA_HEADER, + timeout=_metadata._METADATA_PING_DEFAULT_TIMEOUT, + ) + +@mock.patch("google.auth.metrics.mds_ping", return_value=MDS_PING_METRICS_HEADER_VALUE) +def test_ping_success_with_gce_metadata_timeout(mock_metrics_header_value): + request = make_request("", headers=_metadata._METADATA_HEADERS) + gce_metadata_timeout = .5 + os.environ[ + environment_vars.GCE_METADATA_TIMEOUT] = str(gce_metadata_timeout) + + try: + assert _metadata.ping(request) + finally: + del os.environ[environment_vars.GCE_METADATA_TIMEOUT] + + request.assert_called_once_with( + method="GET", + url=_metadata._METADATA_IP_ROOT, + headers=_metadata._METADATA_HEADER, + timeout=gce_metadata_timeout, + ) + +@mock.patch("google.auth.metrics.mds_ping", return_value=MDS_PING_METRICS_HEADER_VALUE) +def test_ping_success_with_invalid_gce_metadata_timeout(mock_metrics_header_value): + request = make_request("", headers=_metadata._METADATA_HEADERS) + os.environ[ + environment_vars.GCE_METADATA_TIMEOUT] = "Not a valid float value!" + + try: + assert _metadata.ping(request) + finally: + del os.environ[environment_vars.GCE_METADATA_TIMEOUT] + + request.assert_called_once_with( + method="GET", + url=_metadata._METADATA_IP_ROOT, + headers=_metadata._METADATA_HEADERS, + timeout=_metadata._METADATA_PING_DEFAULT_TIMEOUT, # Fallback value. ) @@ -156,7 +193,7 @@ def test_ping_success_custom_root(mock_metrics_header_value): method="GET", url="http://" + fake_ip, headers=MDS_PING_REQUEST_HEADER, - timeout=_metadata._METADATA_DEFAULT_TIMEOUT, + timeout=_metadata._METADATA_PING_DEFAULT_TIMEOUT, ) From 6b89d5637e3b08674ef0c8f8486940d51dd30c81 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Fri, 12 Apr 2024 13:53:16 -0700 Subject: [PATCH 5/5] Update environment_vars.py --- google/auth/environment_vars.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/google/auth/environment_vars.py b/google/auth/environment_vars.py index 81f31571e..93cc8838a 100644 --- a/google/auth/environment_vars.py +++ b/google/auth/environment_vars.py @@ -72,6 +72,9 @@ Used to distinguish between GAE gen1 and GAE gen2+. """ +GCE_METADATA_TIMEOUT = "GCE_METADATA_TIMEOUT" +"""Environment variable for setting timeouts in seconds for metadata queries.""" + # AWS environment variables used with AWS workload identity pools to retrieve # AWS security credentials and the AWS region needed to create a serialized # signed requests to the AWS STS GetCalledIdentity API that can be exchanged