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 e096127

Browse filesBrowse files
authored
fix: fail-fast on missing ECP config file to avoid 30s hang (#17377)
This PR resolves two issues in the `google-auth` package: First, it adds a fast-fail check for ECP configuration. When the `GOOGLE_API_CERTIFICATE_CONFIG` environment variable is set but the configuration file is missing (common on corporate workstations or clean sandbox test runners), the SDK was falling through to the well-known SPIFFE path and waiting on a 30-second retry loop. We now check if the config path is set but missing, and if we are not in a workload environment (the well-known credentials directory is absent), we immediately return `None` to fallback to unbound tokens. (Fixes b/512912028) Second, it fixes an incorrect mock in `test_mtls.py`. `test_default_client_encrypted_cert_source` was mocking `open` in the test namespace instead of the target module namespace. This caused the test to write actual `cert_path` and `key_path` files to the local disk during test runs. This is fixed by patching `google.auth.transport.mtls.open`. Unit tests have been added to verify the fast-fail behavior, and existing retry tests have been updated to mock the workload directory. All tests now pass without writing files to disk.
1 parent 3f70b2f commit e096127
Copy full SHA for e096127

3 files changed

+44-3Lines changed: 44 additions & 3 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/_agent_identity_utils.py‎

Copy file name to clipboardExpand all lines: packages/google-auth/google/auth/_agent_identity_utils.py
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ def get_agent_identity_certificate_path():
8989
if not cert_config_path and not has_well_known_dir:
9090
return None
9191

92+
# If ECP config path is specified but does not exist, and we are on a workstation, fail-fast immediately.
93+
if (
94+
cert_config_path
95+
and not has_well_known_dir
96+
and not os.path.exists(cert_config_path)
97+
):
98+
return None
99+
92100
has_logged_config_warning = False
93101
has_logged_cert_warning = False
94102

Collapse file

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

Copy file name to clipboardExpand all lines: packages/google-auth/tests/test_agent_identity_utils.py
+33-2Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,29 +165,47 @@ def test_get_agent_identity_certificate_path_success(self, tmpdir, monkeypatch):
165165
assert result == str(cert_path)
166166

167167
@mock.patch("time.sleep")
168+
@mock.patch("google.auth._agent_identity_utils.os.path.exists")
168169
def test_get_agent_identity_certificate_path_retry(
169-
self, mock_sleep, tmpdir, monkeypatch
170+
self, mock_exists, mock_sleep, tmpdir, monkeypatch
170171
):
171172
config_path = tmpdir.join("config.json")
172173
monkeypatch.setenv(
173174
environment_vars.GOOGLE_API_CERTIFICATE_CONFIG, str(config_path)
174175
)
175176

177+
# Simulate workload env (well_known_dir exists) to avoid fail-fast
178+
def exists_side_effect(path):
179+
if path == "/var/run/secrets/workload-spiffe-credentials":
180+
return True
181+
return False
182+
183+
mock_exists.side_effect = exists_side_effect
184+
176185
# File doesn't exist initially
177186
with pytest.raises(exceptions.RefreshError):
178187
_agent_identity_utils.get_agent_identity_certificate_path()
179188

180189
assert mock_sleep.call_count == len(_agent_identity_utils._POLLING_INTERVALS)
181190

182191
@mock.patch("time.sleep")
192+
@mock.patch("google.auth._agent_identity_utils.os.path.exists")
183193
def test_get_agent_identity_certificate_path_failure(
184-
self, mock_sleep, tmpdir, monkeypatch
194+
self, mock_exists, mock_sleep, tmpdir, monkeypatch
185195
):
186196
config_path = tmpdir.join("non_existent_config.json")
187197
monkeypatch.setenv(
188198
environment_vars.GOOGLE_API_CERTIFICATE_CONFIG, str(config_path)
189199
)
190200

201+
# Simulate workload env (well_known_dir exists) to avoid fail-fast
202+
def exists_side_effect(path):
203+
if path == "/var/run/secrets/workload-spiffe-credentials":
204+
return True
205+
return False
206+
207+
mock_exists.side_effect = exists_side_effect
208+
191209
with pytest.raises(exceptions.RefreshError) as excinfo:
192210
_agent_identity_utils.get_agent_identity_certificate_path()
193211

@@ -198,6 +216,19 @@ def test_get_agent_identity_certificate_path_failure(
198216
)
199217
assert mock_sleep.call_count == len(_agent_identity_utils._POLLING_INTERVALS)
200218

219+
def test_get_agent_identity_certificate_path_workstation_fail_fast(
220+
self, tmpdir, monkeypatch
221+
):
222+
config_path = tmpdir.join("non_existent_config.json")
223+
monkeypatch.setenv(
224+
environment_vars.GOOGLE_API_CERTIFICATE_CONFIG, str(config_path)
225+
)
226+
227+
# On a workstation, well_known_dir does not exist, and config file is missing.
228+
# It should fail-fast and return None immediately.
229+
result = _agent_identity_utils.get_agent_identity_certificate_path()
230+
assert result is None
231+
201232
@mock.patch("time.sleep")
202233
@mock.patch("os.path.exists")
203234
def test_get_agent_identity_certificate_path_cert_not_found(
Collapse file

‎packages/google-auth/tests/transport/test_mtls.py‎

Copy file name to clipboardExpand all lines: packages/google-auth/tests/transport/test_mtls.py
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,10 @@ def test_default_client_encrypted_cert_source(
154154
# Test good callback.
155155
get_client_ssl_credentials.return_value = (True, b"cert", b"key", b"passphrase")
156156
callback = mtls.default_client_encrypted_cert_source("cert_path", "key_path")
157-
with mock.patch("{}.open".format(__name__), return_value=mock.MagicMock()):
157+
with mock.patch("google.auth.transport.mtls.open", mock.mock_open()) as mock_file:
158158
assert callback() == ("cert_path", "key_path", b"passphrase")
159+
mock_file.assert_any_call("cert_path", "wb")
160+
mock_file.assert_any_call("key_path", "wb")
159161

160162
# Test bad callback which throws exception.
161163
get_client_ssl_credentials.side_effect = exceptions.ClientCertError()

0 commit comments

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