Skip to content

Commit 78de790

Browse files
authored
fix(auth): Add temporary patch to workload cert logic to accomodate Cloud Run mis-configuration (#1880)
This patch adds a fallback logic to look for Cloud Run cert/keys in the well-known location if the cert config contains the exact incorrect cert/key paths AND the incorrect cert/key paths point to non-existent files. Note: This patch will be reverted sometime in Jan 2026, after Cloud Run environment is updated with the correct cert configs. The revert will be tracked by #1881
1 parent 3e8a566 commit 78de790

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

google/auth/transport/_mtls_helper.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,20 @@
4747
b"-----BEGIN PASSPHRASE-----(.+)-----END PASSPHRASE-----", re.DOTALL
4848
)
4949

50+
# Temporary patch to accomodate incorrect cert config in Cloud Run prod environment.
51+
_WELL_KNOWN_CLOUD_RUN_CERT_PATH = (
52+
"/var/run/secrets/workload-spiffe-credentials/certificates.pem"
53+
)
54+
_WELL_KNOWN_CLOUD_RUN_KEY_PATH = (
55+
"/var/run/secrets/workload-spiffe-credentials/private_key.pem"
56+
)
57+
_INCORRECT_CLOUD_RUN_CERT_PATH = (
58+
"/var/lib/volumes/certificate/workload-certificates/certificates.pem"
59+
)
60+
_INCORRECT_CLOUD_RUN_KEY_PATH = (
61+
"/var/lib/volumes/certificate/workload-certificates/private_key.pem"
62+
)
63+
5064

5165
def _check_config_path(config_path):
5266
"""Checks for config file path. If it exists, returns the absolute path with user expansion;
@@ -183,6 +197,25 @@ def _get_workload_cert_and_key_paths(config_path):
183197
)
184198
key_path = workload["key_path"]
185199

200+
# == BEGIN Temporary Cloud Run PATCH ==
201+
# See https://github.com/googleapis/google-auth-library-python/issues/1881
202+
if (cert_path == _INCORRECT_CLOUD_RUN_CERT_PATH) and (
203+
key_path == _INCORRECT_CLOUD_RUN_KEY_PATH
204+
):
205+
if not path.exists(cert_path) and not path.exists(key_path):
206+
_LOGGER.debug(
207+
"Applying Cloud Run certificate path patch. "
208+
"Configured paths not found: %s, %s. "
209+
"Using well-known paths: %s, %s",
210+
cert_path,
211+
key_path,
212+
_WELL_KNOWN_CLOUD_RUN_CERT_PATH,
213+
_WELL_KNOWN_CLOUD_RUN_KEY_PATH,
214+
)
215+
cert_path = _WELL_KNOWN_CLOUD_RUN_CERT_PATH
216+
key_path = _WELL_KNOWN_CLOUD_RUN_KEY_PATH
217+
# == END Temporary Cloud Run PATCH ==
218+
186219
return cert_path, key_path
187220

188221

tests/transport/test__mtls_helper.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,93 @@ def test_success_with_certificate_config(
334334
assert key == pytest.private_key_bytes
335335
assert passphrase is None
336336

337+
@mock.patch(
338+
"google.auth.transport._mtls_helper._read_cert_and_key_files", autospec=True
339+
)
340+
@mock.patch(
341+
"google.auth.transport._mtls_helper._get_cert_config_path", autospec=True
342+
)
343+
@mock.patch("google.auth.transport._mtls_helper._load_json_file", autospec=True)
344+
@mock.patch("google.auth.transport._mtls_helper._check_config_path", autospec=True)
345+
def test_success_with_certificate_config_cloud_run_patch(
346+
self,
347+
mock_check_config_path,
348+
mock_load_json_file,
349+
mock_get_cert_config_path,
350+
mock_read_cert_and_key_files,
351+
):
352+
cert_config_path = "/path/to/config"
353+
mock_check_config_path.return_value = cert_config_path
354+
mock_load_json_file.return_value = {
355+
"cert_configs": {
356+
"workload": {
357+
"cert_path": _mtls_helper._INCORRECT_CLOUD_RUN_CERT_PATH,
358+
"key_path": _mtls_helper._INCORRECT_CLOUD_RUN_KEY_PATH,
359+
}
360+
}
361+
}
362+
mock_get_cert_config_path.return_value = cert_config_path
363+
mock_read_cert_and_key_files.return_value = (
364+
pytest.public_cert_bytes,
365+
pytest.private_key_bytes,
366+
)
367+
368+
has_cert, cert, key, passphrase = _mtls_helper.get_client_ssl_credentials()
369+
assert has_cert
370+
assert cert == pytest.public_cert_bytes
371+
assert key == pytest.private_key_bytes
372+
assert passphrase is None
373+
374+
mock_read_cert_and_key_files.assert_called_once_with(
375+
_mtls_helper._WELL_KNOWN_CLOUD_RUN_CERT_PATH,
376+
_mtls_helper._WELL_KNOWN_CLOUD_RUN_KEY_PATH,
377+
)
378+
379+
@mock.patch("os.path.exists", autospec=True)
380+
@mock.patch(
381+
"google.auth.transport._mtls_helper._read_cert_and_key_files", autospec=True
382+
)
383+
@mock.patch(
384+
"google.auth.transport._mtls_helper._get_cert_config_path", autospec=True
385+
)
386+
@mock.patch("google.auth.transport._mtls_helper._load_json_file", autospec=True)
387+
@mock.patch("google.auth.transport._mtls_helper._check_config_path", autospec=True)
388+
def test_success_with_certificate_config_cloud_run_patch_skipped_if_cert_exists(
389+
self,
390+
mock_check_config_path,
391+
mock_load_json_file,
392+
mock_get_cert_config_path,
393+
mock_read_cert_and_key_files,
394+
mock_os_path_exists,
395+
):
396+
cert_config_path = "/path/to/config"
397+
mock_check_config_path.return_value = cert_config_path
398+
mock_os_path_exists.return_value = True
399+
mock_load_json_file.return_value = {
400+
"cert_configs": {
401+
"workload": {
402+
"cert_path": _mtls_helper._INCORRECT_CLOUD_RUN_CERT_PATH,
403+
"key_path": _mtls_helper._INCORRECT_CLOUD_RUN_KEY_PATH,
404+
}
405+
}
406+
}
407+
mock_get_cert_config_path.return_value = cert_config_path
408+
mock_read_cert_and_key_files.return_value = (
409+
pytest.public_cert_bytes,
410+
pytest.private_key_bytes,
411+
)
412+
413+
has_cert, cert, key, passphrase = _mtls_helper.get_client_ssl_credentials()
414+
assert has_cert
415+
assert cert == pytest.public_cert_bytes
416+
assert key == pytest.private_key_bytes
417+
assert passphrase is None
418+
419+
mock_read_cert_and_key_files.assert_called_once_with(
420+
_mtls_helper._INCORRECT_CLOUD_RUN_CERT_PATH,
421+
_mtls_helper._INCORRECT_CLOUD_RUN_KEY_PATH,
422+
)
423+
337424
@mock.patch(
338425
"google.auth.transport._mtls_helper._get_workload_cert_and_key", autospec=True
339426
)

0 commit comments

Comments
 (0)