Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-google-auth for openSUSE:Factory checked in at 2026-09-07 11:27:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-google-auth (Old) and /work/SRC/openSUSE:Factory/.python-google-auth.new.1265 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-auth" Mon Sep 7 11:27:56 2026 rev:71 rq:1375803 version:2.57.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-google-auth/python-google-auth.changes 2026-08-19 17:56:16.305584659 +0200 +++ /work/SRC/openSUSE:Factory/.python-google-auth.new.1265/python-google-auth.changes 2026-09-07 11:28:34.747431654 +0200 @@ -1,0 +2,10 @@ +Thu Sep 3 10:29:35 UTC 2026 - John Paul Adrian Glaubitz <[email protected]> + +- Update to 2.57.0 + * **auth:** add deprecation warning for grpcio < 1.83.0 (PQC support) (#18070) + * **auth:** parse hostname for mTLS and PSC endpoint certificate rotation (#18153) + * **auth:** prevent TypeError and support home-dir cert fallback for X509 WIF on + ECP machines ([#18016) + * **handwritten:** centralize CONTRIBUTING.rst pointers (#17642) + +------------------------------------------------------------------- Old: ---- google_auth-2.56.3.tar.gz New: ---- google_auth-2.57.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-google-auth.spec ++++++ --- /var/tmp/diff_new_pack.NJUUGZ/_old 2026-09-07 11:28:35.472457081 +0200 +++ /var/tmp/diff_new_pack.NJUUGZ/_new 2026-09-07 11:28:35.474457151 +0200 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-google-auth -Version: 2.56.3 +Version: 2.57.0 Release: 0 Summary: Google Authentication Library License: Apache-2.0 ++++++ google_auth-2.56.3.tar.gz -> google_auth-2.57.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth-2.56.3/PKG-INFO new/google_auth-2.57.0/PKG-INFO --- old/google_auth-2.56.3/PKG-INFO 2026-08-06 07:55:49.079683300 +0200 +++ new/google_auth-2.57.0/PKG-INFO 2026-08-24 23:26:18.068862400 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: google-auth -Version: 2.56.3 +Version: 2.57.0 Summary: Google Authentication Library Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-auth Author: Google Cloud Platform diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth-2.56.3/google/auth/identity_pool.py new/google_auth-2.57.0/google/auth/identity_pool.py --- old/google_auth-2.56.3/google/auth/identity_pool.py 2026-08-06 07:54:29.000000000 +0200 +++ new/google_auth-2.57.0/google/auth/identity_pool.py 2026-08-24 23:22:34.297706600 +0200 @@ -412,6 +412,10 @@ def _get_cert_bytes(self): cert_path, _ = self._get_mtls_cert_and_key_paths() + if cert_path is None: + raise exceptions.ClientCertError( + "Workload certificate configuration could not be found or does not contain workload certificate paths." + ) return _mtls_helper._read_cert_file(cert_path) def _mtls_required(self): @@ -568,7 +572,13 @@ cert_fingerprint = None # Check if the credential is X.509 based. if self._credential_source_certificate is not None: - cert_bytes = self._get_cert_bytes() + try: + cert_bytes = self._get_cert_bytes() + except (exceptions.ClientCertError, OSError) as e: + raise exceptions.RefreshError( + "Failed to retrieve certificate bytes for external" + " account credentials" + ) from e cert = _agent_identity_utils.parse_certificate(cert_bytes) if _agent_identity_utils.should_request_bound_token(cert): cert_fingerprint = ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth-2.56.3/google/auth/transport/_mtls_helper.py new/google_auth-2.57.0/google/auth/transport/_mtls_helper.py --- old/google_auth-2.56.3/google/auth/transport/_mtls_helper.py 2026-08-06 07:54:29.000000000 +0200 +++ new/google_auth-2.57.0/google/auth/transport/_mtls_helper.py 2026-08-24 23:22:32.498689400 +0200 @@ -459,7 +459,11 @@ data = _load_json_file(absolute_path) - if "cert_configs" not in data: + if ( + not isinstance(data, dict) + or "cert_configs" not in data + or not isinstance(data["cert_configs"], dict) + ): raise exceptions.ClientCertError( 'Certificate config file {} is in an invalid format, a "cert configs" object is expected'.format( absolute_path @@ -472,11 +476,40 @@ # and we want to gracefully fallback to testing other mTLS configurations # like SecureConnect instead of throwing an exception. - if "workload" not in cert_configs: + if ( + not isinstance(cert_configs, dict) or "workload" not in cert_configs + ) and config_path is None: + default_home_path = path.expanduser( + os.path.join( + _cloud_sdk.get_config_path(), + "certificate_config.json", + ) + ) + if path.exists(default_home_path) and os.path.normpath( + default_home_path + ) != os.path.normpath(absolute_path): + try: + home_data = _load_json_file(default_home_path) + if isinstance(home_data, dict): + home_cert_configs = home_data.get("cert_configs") + if ( + isinstance(home_cert_configs, dict) + and "workload" in home_cert_configs + ): + cert_configs = home_cert_configs + absolute_path = default_home_path + except (exceptions.ClientCertError, OSError): + pass + + if not isinstance(cert_configs, dict) or "workload" not in cert_configs: return None, None workload = cert_configs["workload"] - if "cert_path" not in workload or "key_path" not in workload: + if ( + not isinstance(workload, dict) + or "cert_path" not in workload + or "key_path" not in workload + ): raise exceptions.ClientCertError( 'Workload certificate configuration is missing "cert_path" or "key_path" in {}'.format( absolute_path diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth-2.56.3/google/auth/transport/grpc.py new/google_auth-2.57.0/google/auth/transport/grpc.py --- old/google_auth-2.56.3/google/auth/transport/grpc.py 2026-08-06 07:54:33.000000000 +0200 +++ new/google_auth-2.57.0/google/auth/transport/grpc.py 2026-08-24 23:22:34.255706300 +0200 @@ -17,6 +17,7 @@ from __future__ import absolute_import import logging +import warnings from google.auth import exceptions from google.auth.transport import _mtls_helper @@ -30,6 +31,26 @@ "gRPC is not installed from please install the grpcio package to use the gRPC transport." ) from caught_exc + +_grpc_ver_str = getattr(grpc, "__version__", None) +if isinstance(_grpc_ver_str, str): + _parts = [] + for _part in _grpc_ver_str.split("."): + try: + _parts.append(int(_part)) + except ValueError: + break + if _parts and tuple(_parts) < (1, 83, 0): + warnings.warn( + "grpcio < 1.83.0 does not support Post-Quantum Cryptography (PQC). " + "Support for non-PQC environments is deprecated. In October 2026, " + "google-auth will raise its minimum requirements " + "to enforce grpcio >= 1.83.0. " + "For more details on Google Cloud's post-quantum security migration, visit: " + "https://cloud.google.com/security/resources/post-quantum-cryptography", + FutureWarning, + ) + _LOGGER = logging.getLogger(__name__) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth-2.56.3/google/auth/version.py new/google_auth-2.57.0/google/auth/version.py --- old/google_auth-2.56.3/google/auth/version.py 2026-08-06 07:54:29.000000000 +0200 +++ new/google_auth-2.57.0/google/auth/version.py 2026-08-24 23:22:32.277687000 +0200 @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "2.56.3" +__version__ = "2.57.0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth-2.56.3/google_auth.egg-info/PKG-INFO new/google_auth-2.57.0/google_auth.egg-info/PKG-INFO --- old/google_auth-2.56.3/google_auth.egg-info/PKG-INFO 2026-08-06 07:55:49.000000000 +0200 +++ new/google_auth-2.57.0/google_auth.egg-info/PKG-INFO 2026-08-24 23:26:17.995861800 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: google-auth -Version: 2.56.3 +Version: 2.57.0 Summary: Google Authentication Library Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-auth Author: Google Cloud Platform diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth-2.56.3/tests/test_identity_pool.py new/google_auth-2.57.0/tests/test_identity_pool.py --- old/google_auth-2.56.3/tests/test_identity_pool.py 2026-08-06 07:54:34.000000000 +0200 +++ new/google_auth-2.57.0/tests/test_identity_pool.py 2026-08-24 23:22:35.630719700 +0200 @@ -1784,6 +1784,57 @@ 'The credential is not configured to use mtls requests. The credential should include a "certificate" section in the credential source.' ) + @mock.patch( + "google.auth.transport._mtls_helper._get_workload_cert_and_key_paths", + return_value=(None, None), + ) + def test_get_cert_bytes_none_raises_error( + self, mock_get_workload_cert_and_key_paths + ): + credentials = self.make_credentials( + credential_source=self.CREDENTIAL_SOURCE_CERTIFICATE.copy() + ) + + with pytest.raises(exceptions.ClientCertError) as excinfo: + credentials._get_cert_bytes() + + assert excinfo.match( + "Workload certificate configuration could not be found or does not contain workload certificate paths." + ) + + @mock.patch.object( + identity_pool.Credentials, + "_get_cert_bytes", + side_effect=exceptions.ClientCertError("mock error"), + ) + def test_refresh_cert_error_raises_refresh_error(self, mock_get_cert_bytes): + credentials = self.make_credentials( + credential_source=self.CREDENTIAL_SOURCE_CERTIFICATE.copy() + ) + + with pytest.raises(exceptions.RefreshError) as excinfo: + credentials.refresh(None) + + assert excinfo.match( + "Failed to retrieve certificate bytes for external account credentials" + ) + + @mock.patch.object( + identity_pool.Credentials, + "_get_cert_bytes", + side_effect=OSError("mock os error"), + ) + def test_refresh_os_error_raises_refresh_error(self, mock_get_cert_bytes): + credentials = self.make_credentials( + credential_source=self.CREDENTIAL_SOURCE_CERTIFICATE.copy() + ) + + with pytest.raises(exceptions.RefreshError) as excinfo: + credentials.refresh(None) + + msg = "Failed to retrieve certificate bytes for external" + assert excinfo.match(msg + " account credentials") + @mock.patch("google.auth._agent_identity_utils.parse_certificate") @mock.patch( "google.auth._agent_identity_utils.should_request_bound_token", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth-2.56.3/tests/transport/test__mtls_helper.py new/google_auth-2.57.0/tests/transport/test__mtls_helper.py --- old/google_auth-2.56.3/tests/transport/test__mtls_helper.py 2026-08-06 07:54:30.000000000 +0200 +++ new/google_auth-2.57.0/tests/transport/test__mtls_helper.py 2026-08-24 23:22:32.540689700 +0200 @@ -500,6 +500,43 @@ _mtls_helper._get_workload_cert_and_key("") @mock.patch("google.auth.transport._mtls_helper._load_json_file", autospec=True) + @mock.patch("google.auth.transport._mtls_helper.path.exists", autospec=True) + def test_non_dict_cert_configs_raises_error( + self, mock_path_exists, mock_load_json_file + ): + mock_path_exists.return_value = True + + for val in [None, [], "not_a_dict"]: + mock_load_json_file.return_value = {"cert_configs": val} + with pytest.raises(exceptions.ClientCertError): + _mtls_helper._get_workload_cert_and_key(None) + + @mock.patch("google.auth.transport._mtls_helper._load_json_file", autospec=True) + @mock.patch("google.auth.transport._mtls_helper.path.exists", autospec=True) + def test_malformed_json_returns_error(self, mock_path_exists, mock_load_json_file): + mock_path_exists.return_value = True + + for val in [None, [], "invalid_string"]: + mock_load_json_file.return_value = val + with pytest.raises(exceptions.ClientCertError): + _mtls_helper._get_workload_cert_and_key(None) + + @mock.patch("google.auth.transport._mtls_helper._load_json_file", autospec=True) + @mock.patch("google.auth.transport._mtls_helper.path.exists", autospec=True) + def test_non_dict_workload_raises_error( + self, mock_path_exists, mock_load_json_file + ): + mock_path_exists.return_value = True + + for invalid_workload in [None, 123, "not_a_dict"]: + mock_load_json_file.return_value = { + "cert_configs": {"workload": invalid_workload} + } + + with pytest.raises(exceptions.ClientCertError): + _mtls_helper._get_workload_cert_and_key(None) + + @mock.patch("google.auth.transport._mtls_helper._load_json_file", autospec=True) @mock.patch( "google.auth.transport._mtls_helper._get_cert_config_path", autospec=True ) @@ -511,6 +548,182 @@ assert actual_cert is None assert actual_key is None + @mock.patch( + "google.auth.transport._mtls_helper._load_json_file", autospec=True + ) # noqa: E501 + @mock.patch( + "google.auth.transport._mtls_helper._get_cert_config_path", + autospec=True, + ) # noqa: E501 + @mock.patch( + "google.auth.transport._mtls_helper._read_cert_and_key_files", + autospec=True, + ) # noqa: E501 + @mock.patch( + "google.auth.transport._mtls_helper.path.exists", autospec=True + ) # noqa: E501 + def test_no_workload_fallback_to_home( + self, + mock_path_exists, + mock_read_cert_and_key_files, + mock_get_cert_config_path, + mock_load_json_file, + ): + ecp_path = "/etc/gcloud/certificate_config.json" + home_path = os.path.join( + _mtls_helper._cloud_sdk.get_config_path(), + "certificate_config.json", + ) + mock_get_cert_config_path.return_value = ecp_path + + def exists_side_effect(path): + if path == home_path: + return True + return False + + mock_path_exists.side_effect = exists_side_effect + + def load_json_side_effect(path): + if path == ecp_path: + return {"cert_configs": {"pkcs11": {}}} + elif path == home_path: + return { + "cert_configs": { + "workload": { + "cert_path": "cert/path", + "key_path": "key/path", + } + } + } + return {} + + mock_load_json_file.side_effect = load_json_side_effect + mock_read_cert_and_key_files.return_value = ( + pytest.public_cert_bytes, + pytest.private_key_bytes, + ) + + actual_cert, actual_key = _mtls_helper._get_workload_cert_and_key(None) + assert actual_cert == pytest.public_cert_bytes + assert actual_key == pytest.private_key_bytes + + mock_get_cert_config_path.assert_called_once_with(None, True) + mock_load_json_file.assert_has_calls( + [mock.call(ecp_path), mock.call(home_path)] + ) + mock_read_cert_and_key_files.assert_called_once_with( + "cert/path", "key/path" + ) # noqa: E501 + + @mock.patch( + "google.auth.transport._mtls_helper._load_json_file", autospec=True + ) # noqa: E501 + @mock.patch( + "google.auth.transport._mtls_helper._get_cert_config_path", + autospec=True, + ) # noqa: E501 + @mock.patch( + "google.auth.transport._mtls_helper._read_cert_and_key_files", + autospec=True, + ) # noqa: E501 + @mock.patch( + "google.auth.transport._mtls_helper.path.exists", autospec=True + ) # noqa: E501 + def test_no_workload_fallback_to_home_error( + self, + mock_path_exists, + mock_read_cert_and_key_files, + mock_get_cert_config_path, + mock_load_json_file, + ): + ecp_path = "/etc/gcloud/certificate_config.json" + home_path = os.path.join( + _mtls_helper._cloud_sdk.get_config_path(), + "certificate_config.json", + ) + mock_get_cert_config_path.return_value = ecp_path + + def exists_side_effect(path): + if path == home_path: + return True + return False + + mock_path_exists.side_effect = exists_side_effect + + def load_json_side_effect(path): + if path == ecp_path: + return {"cert_configs": {"pkcs11": {}}} + elif path == home_path: + raise exceptions.ClientCertError("mocked unreadable file") + return {} + + mock_load_json_file.side_effect = load_json_side_effect + + actual_cert, actual_key = _mtls_helper._get_workload_cert_and_key(None) + assert actual_cert is None + assert actual_key is None + + mock_get_cert_config_path.assert_called_once_with(None, True) + mock_load_json_file.assert_has_calls( + [mock.call(ecp_path), mock.call(home_path)] + ) + mock_read_cert_and_key_files.assert_not_called() + + @mock.patch( + "google.auth.transport._mtls_helper._load_json_file", autospec=True + ) # noqa: E501 + @mock.patch( + "google.auth.transport._mtls_helper._get_cert_config_path", + autospec=True, + ) + @mock.patch( + "google.auth.transport._mtls_helper.path.exists", autospec=True + ) # noqa: E501 + @mock.patch("os.path.normpath", autospec=True) + def test_no_workload_fallback_avoided_same_path_normalization( + self, + mock_normpath, + mock_path_exists, + mock_get_cert_config_path, + mock_load_json_file, + ): + ecp_path = "C:/Users/User/.config/gcloud/certificate_config.json" + home_path = "C:\\Users\\User\\.config\\gcloud/certificate_config.json" + mock_get_cert_config_path.return_value = ecp_path + + mock_path_exists.return_value = True + + # When resolving, the first file has no workload. + mock_load_json_file.return_value = {"cert_configs": {"pkcs11": {}}} + + win_path = "C:\\Users\\User\\.config\\gcloud\\certificate_config.json" + + # Mock normpath to return the same string for both paths, + # simulating Windows path normalization. + def normpath_side_effect(path): + if path in [ecp_path, home_path]: + return win_path + return path + + mock_normpath.side_effect = normpath_side_effect + + # Mock get_config_path to construct a path with backslashes + with mock.patch( + "google.auth._cloud_sdk.get_config_path", + return_value="C:\\Users\\User\\.config\\gcloud", + ): + actual_cert, actual_key = _mtls_helper._get_workload_cert_and_key( + None + ) # noqa: E501 + + assert actual_cert is None + assert actual_key is None + + # Check that it resolved ECP path but never attempted to load + # home_path (because it normalized to the same file). + mock_get_cert_config_path.assert_called_once_with(None, True) + mock_load_json_file.assert_called_once_with(ecp_path) + @mock.patch("google.auth.transport._mtls_helper._load_json_file", autospec=True) @mock.patch( "google.auth.transport._mtls_helper._get_cert_config_path", autospec=True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth-2.56.3/tests/transport/test_grpc.py new/google_auth-2.57.0/tests/transport/test_grpc.py --- old/google_auth-2.56.3/tests/transport/test_grpc.py 2026-08-06 07:54:33.000000000 +0200 +++ new/google_auth-2.57.0/tests/transport/test_grpc.py 2026-08-24 23:22:30.200972600 +0200 @@ -13,9 +13,11 @@ # limitations under the License. import datetime +import importlib import os import time from unittest import mock +import warnings import pytest # type: ignore @@ -678,3 +680,25 @@ mock_ssl_channel_credentials.assert_called_once_with( certificate_chain=PUBLIC_CERT_BYTES, private_key=PRIVATE_KEY_BYTES ) + + +def test_grpc_version_warning_for_older_version(monkeypatch): + monkeypatch.setattr(grpc, "__version__", "1.80.0") + with pytest.warns( + FutureWarning, match="does not support Post-Quantum Cryptography" + ): + importlib.reload(google.auth.transport.grpc) + + +def test_grpc_version_warning_not_emitted_for_supported_version(monkeypatch): + monkeypatch.setattr(grpc, "__version__", "1.83.0") + with warnings.catch_warnings(): + warnings.simplefilter("error", FutureWarning) + importlib.reload(google.auth.transport.grpc) + + +def test_grpc_version_warning_not_emitted_when_no_version(monkeypatch): + monkeypatch.delattr(grpc, "__version__", raising=False) + with warnings.catch_warnings(): + warnings.simplefilter("error", FutureWarning) + importlib.reload(google.auth.transport.grpc)
