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 2023-12-09 22:49:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-google-auth (Old) and /work/SRC/openSUSE:Factory/.python-google-auth.new.25432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-auth" Sat Dec 9 22:49:03 2023 rev:36 rq:1131735 version:2.25.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-google-auth/python-google-auth.changes 2023-11-26 19:36:48.805085622 +0100 +++ /work/SRC/openSUSE:Factory/.python-google-auth.new.25432/python-google-auth.changes 2023-12-09 22:49:08.646612520 +0100 @@ -1,0 +2,20 @@ +Thu Dec 7 22:38:03 UTC 2023 - Dirk Müller <[email protected]> + +- update to 2.25.1: + * Fix vm universe_domain bug (#1433) (8683520) + * Add custom tls signer for ECP Provider. (39eb287) + * Add custom tls signer for ECP Provider. (#1402) (39eb287) + * Add with_universe_domain (#1408) (505910c) + * Fixes issue where Python37DeprecationWarning cannot be + filtered (#1428) (f22f767) + * Remove broken link in Python37DeprecationWarning (#1430) + * Add support for Python 3.12 (#1421) (307916c) + * Add universe domain support for VM cred (#1409) (7ab0fce) + * Modify the token refresh window (#1419) (c6af1d6) + * Add missing before request to async oauth2 credentials. + (#1420) (8eaa878) + * Auto create self signed jwt cred (#1418) (6c610a5) + * Migrate datetime.utcnow for python 3.12 (#1413) (e4d9c27) + * Update user cred doc (#1414) (3f426bc) + +------------------------------------------------------------------- Old: ---- google-auth-2.23.4.tar.gz New: ---- google-auth-2.25.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-google-auth.spec ++++++ --- /var/tmp/diff_new_pack.YHWcoC/_old 2023-12-09 22:49:09.278635337 +0100 +++ /var/tmp/diff_new_pack.YHWcoC/_new 2023-12-09 22:49:09.278635337 +0100 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-google-auth -Version: 2.23.4 +Version: 2.25.1 Release: 0 Summary: Google Authentication Library License: Apache-2.0 ++++++ google-auth-2.23.4.tar.gz -> google-auth-2.25.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/PKG-INFO new/google-auth-2.25.1/PKG-INFO --- old/google-auth-2.23.4/PKG-INFO 2023-10-31 20:38:28.224912200 +0100 +++ new/google-auth-2.25.1/PKG-INFO 2023-12-06 02:45:01.775611400 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: google-auth -Version: 2.23.4 +Version: 2.25.1 Summary: Google Authentication Library Home-page: https://github.com/googleapis/google-auth-library-python Author: Google Cloud Platform @@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License @@ -22,12 +23,23 @@ Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Requires-Python: >=3.7 +License-File: LICENSE +Requires-Dist: cachetools<6.0,>=2.0.0 +Requires-Dist: pyasn1-modules>=0.2.1 +Requires-Dist: rsa<5,>=3.1.4 Provides-Extra: aiohttp +Requires-Dist: aiohttp<4.0.0.dev0,>=3.6.2; extra == "aiohttp" +Requires-Dist: requests<3.0.0.dev0,>=2.20.0; extra == "aiohttp" Provides-Extra: pyopenssl +Requires-Dist: pyopenssl>=20.0.0; extra == "pyopenssl" +Requires-Dist: cryptography>=38.0.3; extra == "pyopenssl" Provides-Extra: requests +Requires-Dist: requests<3.0.0.dev0,>=2.20.0; extra == "requests" Provides-Extra: reauth -Provides-Extra: enterprise_cert -License-File: LICENSE +Requires-Dist: pyu2f>=0.1.5; extra == "reauth" +Provides-Extra: enterprise-cert +Requires-Dist: cryptography==36.0.2; extra == "enterprise-cert" +Requires-Dist: pyopenssl==22.0.0; extra == "enterprise-cert" Google Auth Python Library ========================== @@ -51,7 +63,7 @@ For more information on setting up your Python development environment, please refer to `Python Development Environment Setup Guide`_ for Google Cloud Platform. -.. _`Python Development Environment Setup Guide`: https://cloud.google.com/python/setup +.. _`Python Development Environment Setup Guide`: https://cloud.google.com/python/docs/setup Extras ------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/README.rst new/google-auth-2.25.1/README.rst --- old/google-auth-2.23.4/README.rst 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/README.rst 2023-12-06 02:42:14.000000000 +0100 @@ -20,7 +20,7 @@ For more information on setting up your Python development environment, please refer to `Python Development Environment Setup Guide`_ for Google Cloud Platform. -.. _`Python Development Environment Setup Guide`: https://cloud.google.com/python/setup +.. _`Python Development Environment Setup Guide`: https://cloud.google.com/python/docs/setup Extras ------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/auth/__init__.py new/google-auth-2.25.1/google/auth/__init__.py --- old/google-auth-2.23.4/google/auth/__init__.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/auth/__init__.py 2023-12-06 02:42:14.000000000 +0100 @@ -35,8 +35,7 @@ class Python37DeprecationWarning(DeprecationWarning): # pragma: NO COVER """ Deprecation warning raised when Python 3.7 runtime is detected. - Python 3.7 support will be dropped after January 1, 2024. See - https://cloud.google.com/python/docs/python37-sunset/ for more information. + Python 3.7 support will be dropped after January 1, 2024. """ pass @@ -46,12 +45,8 @@ if sys.version_info.major == 3 and sys.version_info.minor == 7: # pragma: NO COVER message = ( "After January 1, 2024, new releases of this library will drop support " - "for Python 3.7. More details about Python 3.7 support " - "can be found at https://cloud.google.com/python/docs/python37-sunset/" + "for Python 3.7." ) - - # Configure the Python37DeprecationWarning warning so that it is only emitted once. - warnings.simplefilter("once", Python37DeprecationWarning) warnings.warn(message, Python37DeprecationWarning) # Set default logging handler to avoid "No handler found" warnings. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/auth/_helpers.py new/google-auth-2.25.1/google/auth/_helpers.py --- old/google-auth-2.23.4/google/auth/_helpers.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/auth/_helpers.py 2023-12-06 02:42:14.000000000 +0100 @@ -23,11 +23,9 @@ from google.auth import exceptions -# Token server doesn't provide a new a token when doing refresh unless the -# token is expiring within 30 seconds, so refresh threshold should not be -# more than 30 seconds. Otherwise auth lib will send tons of refresh requests -# until 30 seconds before the expiration, and cause a spike of CPU usage. -REFRESH_THRESHOLD = datetime.timedelta(seconds=20) +# The smallest MDS cache used by this library stores tokens until 4 minutes from +# expiry. +REFRESH_THRESHOLD = datetime.timedelta(minutes=3, seconds=45) def copy_docstring(source_class): @@ -92,7 +90,14 @@ Returns: datetime: The current time in UTC. """ - return datetime.datetime.utcnow() + # We used datetime.utcnow() before, since it's deprecated from python 3.12, + # we are using datetime.now(timezone.utc) now. "utcnow()" is offset-native + # (no timezone info), but "now()" is offset-aware (with timezone info). + # This will cause datetime comparison problem. For backward compatibility, + # we need to remove the timezone info. + now = datetime.datetime.now(datetime.timezone.utc) + now = now.replace(tzinfo=None) + return now def datetime_to_secs(value): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/auth/compute_engine/_metadata.py new/google-auth-2.25.1/google/auth/compute_engine/_metadata.py --- old/google-auth-2.23.4/google/auth/compute_engine/_metadata.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/auth/compute_engine/_metadata.py 2023-12-06 02:42:14.000000000 +0100 @@ -156,6 +156,7 @@ recursive=False, retry_count=5, headers=None, + return_none_for_not_found_error=False, ): """Fetch a resource from the metadata server. @@ -173,6 +174,8 @@ retry_count (int): How many times to attempt connecting to metadata server using above timeout. headers (Optional[Mapping[str, str]]): Headers for the request. + return_none_for_not_found_error (Optional[bool]): If True, returns None + for 404 error instead of throwing an exception. Returns: Union[Mapping, str]: If the metadata server returns JSON, a mapping of @@ -216,8 +219,17 @@ "metadata service. Compute Engine Metadata server unavailable".format(url) ) + content = _helpers.from_bytes(response.data) + + if response.status == http_client.NOT_FOUND and return_none_for_not_found_error: + _LOGGER.info( + "Compute Engine Metadata server call to %s returned 404, reason: %s", + path, + content, + ) + return None + if response.status == http_client.OK: - content = _helpers.from_bytes(response.data) if ( _helpers.parse_content_type(response.headers["content-type"]) == "application/json" @@ -232,14 +244,14 @@ raise new_exc from caught_exc else: return content - else: - raise exceptions.TransportError( - "Failed to retrieve {} from the Google Compute Engine " - "metadata service. Status: {} Response:\n{}".format( - url, response.status, response.data - ), - response, - ) + + raise exceptions.TransportError( + "Failed to retrieve {} from the Google Compute Engine " + "metadata service. Status: {} Response:\n{}".format( + url, response.status, response.data + ), + response, + ) def get_project_id(request): @@ -259,6 +271,29 @@ return get(request, "project/project-id") +def get_universe_domain(request): + """Get the universe domain value from the metadata server. + + Args: + request (google.auth.transport.Request): A callable used to make + HTTP requests. + + Returns: + str: The universe domain value. If the universe domain endpoint is not + not found, return the default value, which is googleapis.com + + Raises: + google.auth.exceptions.TransportError: if an error other than + 404 occurs while retrieving metadata. + """ + universe_domain = get( + request, "universe/universe_domain", return_none_for_not_found_error=True + ) + if not universe_domain: + return "googleapis.com" + return universe_domain + + def get_service_account_info(request, service_account="default"): """Get information about a service account from the metadata server. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/auth/compute_engine/credentials.py new/google-auth-2.25.1/google/auth/compute_engine/credentials.py --- old/google-auth-2.23.4/google/auth/compute_engine/credentials.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/auth/compute_engine/credentials.py 2023-12-06 02:42:14.000000000 +0100 @@ -28,6 +28,7 @@ from google.auth import jwt from google.auth import metrics from google.auth.compute_engine import _metadata +from google.auth.transport import requests as google_auth_requests from google.oauth2 import _client @@ -73,6 +74,8 @@ self._quota_project_id = quota_project_id self._scopes = scopes self._default_scopes = default_scopes + self._universe_domain_cached = False + self._universe_domain_request = google_auth_requests.Request() def _retrieve_info(self, request): """Retrieve information about the service account. @@ -131,6 +134,16 @@ def requires_scopes(self): return not self._scopes + @property + def universe_domain(self): + if self._universe_domain_cached: + return self._universe_domain + self._universe_domain = _metadata.get_universe_domain( + self._universe_domain_request + ) + self._universe_domain_cached = True + return self._universe_domain + @_helpers.copy_docstring(credentials.CredentialsWithQuotaProject) def with_quota_project(self, quota_project_id): return self.__class__( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/auth/external_account.py new/google-auth-2.25.1/google/auth/external_account.py --- old/google-auth-2.23.4/google/auth/external_account.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/auth/external_account.py 2023-12-06 02:42:14.000000000 +0100 @@ -415,6 +415,22 @@ new_cred._metrics_options = self._metrics_options return new_cred + def with_universe_domain(self, universe_domain): + """Create a copy of these credentials with the given universe domain. + + Args: + universe_domain (str): The universe domain value. + + Returns: + google.auth.external_account.Credentials: A new credentials + instance. + """ + kwargs = self._constructor_args() + kwargs.update(universe_domain=universe_domain) + new_cred = self.__class__(**kwargs) + new_cred._metrics_options = self._metrics_options + return new_cred + def _initialize_impersonated_credentials(self): """Generates an impersonated credentials. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/auth/transport/_custom_tls_signer.py new/google-auth-2.25.1/google/auth/transport/_custom_tls_signer.py --- old/google-auth-2.23.4/google/auth/transport/_custom_tls_signer.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/auth/transport/_custom_tls_signer.py 2023-12-06 02:42:14.000000000 +0100 @@ -107,6 +107,22 @@ return lib +def load_provider_lib(provider_lib_path): + _LOGGER.debug("loading provider library from %s", provider_lib_path) + + # winmode parameter is only available for python 3.8+. + lib = ( + ctypes.CDLL(provider_lib_path, winmode=0) + if sys.version_info >= (3, 8) and os.name == "nt" + else ctypes.CDLL(provider_lib_path) + ) + + lib.ECP_attach_to_ctx.argtypes = [ctypes.c_void_p, ctypes.c_char_p] + lib.ECP_attach_to_ctx.restype = ctypes.c_int + + return lib + + # Computes SHA256 hash. def _compute_sha256_digest(to_be_signed, to_be_signed_len): from cryptography.hazmat.primitives import hashes @@ -199,21 +215,31 @@ self._enterprise_cert_file_path = enterprise_cert_file_path self._cert = None self._sign_callback = None + self._provider_lib = None def load_libraries(self): - try: - with open(self._enterprise_cert_file_path, "r") as f: - enterprise_cert_json = json.load(f) - libs = enterprise_cert_json["libs"] - signer_library = libs["ecp_client"] - offload_library = libs["tls_offload"] - except (KeyError, ValueError) as caught_exc: - new_exc = exceptions.MutualTLSChannelError( - "enterprise cert file is invalid", caught_exc - ) - raise new_exc from caught_exc - self._offload_lib = load_offload_lib(offload_library) - self._signer_lib = load_signer_lib(signer_library) + with open(self._enterprise_cert_file_path, "r") as f: + enterprise_cert_json = json.load(f) + libs = enterprise_cert_json.get("libs", {}) + + signer_library = libs.get("ecp_client", None) + offload_library = libs.get("tls_offload", None) + provider_library = libs.get("ecp_provider", None) + + # Using newer provider implementation. This is mutually exclusive to the + # offload implementation. + if provider_library: + self._provider_lib = load_provider_lib(provider_library) + return + + # Using old offload implementation + if offload_library and signer_library: + self._offload_lib = load_offload_lib(offload_library) + self._signer_lib = load_signer_lib(signer_library) + self.set_up_custom_key() + return + + raise exceptions.MutualTLSChannelError("enterprise cert file is invalid") def set_up_custom_key(self): # We need to keep a reference of the cert and sign callback so it won't @@ -224,11 +250,22 @@ ) def attach_to_ssl_context(self, ctx): - # In the TLS handshake, the signing operation will be done by the - # sign_callback. - if not self._offload_lib.ConfigureSslContext( - self._sign_callback, - ctypes.c_char_p(self._cert), - _cast_ssl_ctx_to_void_p(ctx._ctx._context), - ): - raise exceptions.MutualTLSChannelError("failed to configure SSL context") + if self._provider_lib: + if not self._provider_lib.ECP_attach_to_ctx( + _cast_ssl_ctx_to_void_p(ctx._ctx._context), + self._enterprise_cert_file_path.encode("ascii"), + ): + raise exceptions.MutualTLSChannelError( + "failed to configure ECP Provider SSL context" + ) + elif self._offload_lib and self._signer_lib: + if not self._offload_lib.ConfigureSslContext( + self._sign_callback, + ctypes.c_char_p(self._cert), + _cast_ssl_ctx_to_void_p(ctx._ctx._context), + ): + raise exceptions.MutualTLSChannelError( + "failed to configure ECP Offload SSL context" + ) + else: + raise exceptions.MutualTLSChannelError("Invalid ECP configuration.") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/auth/transport/requests.py new/google-auth-2.25.1/google/auth/transport/requests.py --- old/google-auth-2.23.4/google/auth/transport/requests.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/auth/transport/requests.py 2023-12-06 02:42:14.000000000 +0100 @@ -274,7 +274,6 @@ self.signer = _custom_tls_signer.CustomTlsSigner(enterprise_cert_file_path) self.signer.load_libraries() - self.signer.set_up_custom_key() poolmanager = create_urllib3_context() poolmanager.load_verify_locations(cafile=certifi.where()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/auth/version.py new/google-auth-2.25.1/google/auth/version.py --- old/google-auth-2.23.4/google/auth/version.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/auth/version.py 2023-12-06 02:42:14.000000000 +0100 @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "2.23.4" +__version__ = "2.25.1" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/oauth2/__init__.py new/google-auth-2.25.1/google/oauth2/__init__.py --- old/google-auth-2.23.4/google/oauth2/__init__.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/oauth2/__init__.py 2023-12-06 02:42:14.000000000 +0100 @@ -21,8 +21,7 @@ class Python37DeprecationWarning(DeprecationWarning): # pragma: NO COVER """ Deprecation warning raised when Python 3.7 runtime is detected. - Python 3.7 support will be dropped after January 1, 2024. See - https://cloud.google.com/python/docs/python37-sunset/ for more information. + Python 3.7 support will be dropped after January 1, 2024. """ pass @@ -32,9 +31,6 @@ if sys.version_info.major == 3 and sys.version_info.minor == 7: # pragma: NO COVER message = ( "After January 1, 2024, new releases of this library will drop support " - "for Python 3.7. More details about Python 3.7 support " - "can be found at https://cloud.google.com/python/docs/python37-sunset/" + "for Python 3.7." ) - # Configure the Python37DeprecationWarning warning so that it is only emitted once. - warnings.simplefilter("once", Python37DeprecationWarning) warnings.warn(message, Python37DeprecationWarning) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/oauth2/_credentials_async.py new/google-auth-2.25.1/google/oauth2/_credentials_async.py --- old/google-auth-2.23.4/google/oauth2/_credentials_async.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/oauth2/_credentials_async.py 2023-12-06 02:42:14.000000000 +0100 @@ -96,6 +96,12 @@ ) ) + @_helpers.copy_docstring(credentials.Credentials) + async def before_request(self, request, method, url, headers): + if not self.valid: + await self.refresh(request) + self.apply(headers) + class UserAccessTokenCredentials(oauth2_credentials.UserAccessTokenCredentials): """Access token credentials for user account. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/oauth2/credentials.py new/google-auth-2.25.1/google/oauth2/credentials.py --- old/google-auth-2.23.4/google/oauth2/credentials.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/oauth2/credentials.py 2023-12-06 02:42:14.000000000 +0100 @@ -49,13 +49,15 @@ # The Google OAuth 2.0 token endpoint. Used for authorized user credentials. _GOOGLE_OAUTH2_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token" +_DEFAULT_UNIVERSE_DOMAIN = "googleapis.com" class Credentials(credentials.ReadOnlyScoped, credentials.CredentialsWithQuotaProject): """Credentials using OAuth 2.0 access and refresh tokens. - The credentials are considered immutable. If you want to modify the - quota project, use :meth:`with_quota_project` or :: + The credentials are considered immutable except the tokens and the token + expiry, which are updated after refresh. If you want to modify the quota + project, use :meth:`with_quota_project` or :: credentials = credentials.with_quota_project('myproject-123') @@ -84,6 +86,7 @@ enable_reauth_refresh=False, granted_scopes=None, trust_boundary=None, + universe_domain=_DEFAULT_UNIVERSE_DOMAIN, ): """ Args: @@ -125,6 +128,9 @@ granted_scopes (Optional[Sequence[str]]): The scopes that were consented/granted by the user. This could be different from the requested scopes and it could be empty if granted and requested scopes were same. + trust_boundary (str): String representation of trust boundary meta. + universe_domain (Optional[str]): The universe domain. The default + universe domain is googleapis.com. """ super(Credentials, self).__init__() self.token = token @@ -142,6 +148,7 @@ self.refresh_handler = refresh_handler self._enable_reauth_refresh = enable_reauth_refresh self._trust_boundary = trust_boundary + self._universe_domain = universe_domain or _DEFAULT_UNIVERSE_DOMAIN def __getstate__(self): """A __getstate__ method must exist for the __setstate__ to be called @@ -272,6 +279,7 @@ rapt_token=self.rapt_token, enable_reauth_refresh=self._enable_reauth_refresh, trust_boundary=self._trust_boundary, + universe_domain=self._universe_domain, ) @_helpers.copy_docstring(credentials.CredentialsWithTokenUri) @@ -291,6 +299,34 @@ rapt_token=self.rapt_token, enable_reauth_refresh=self._enable_reauth_refresh, trust_boundary=self._trust_boundary, + universe_domain=self._universe_domain, + ) + + def with_universe_domain(self, universe_domain): + """Create a copy of the credential with the given universe domain. + + Args: + universe_domain (str): The universe domain value. + + Returns: + google.oauth2.credentials.Credentials: A new credentials instance. + """ + + return self.__class__( + self.token, + refresh_token=self.refresh_token, + id_token=self.id_token, + token_uri=self._token_uri, + client_id=self.client_id, + client_secret=self.client_secret, + scopes=self.scopes, + default_scopes=self.default_scopes, + granted_scopes=self.granted_scopes, + quota_project_id=self.quota_project_id, + rapt_token=self.rapt_token, + enable_reauth_refresh=self._enable_reauth_refresh, + trust_boundary=self._trust_boundary, + universe_domain=universe_domain, ) def _metric_header_for_usage(self): @@ -298,6 +334,17 @@ @_helpers.copy_docstring(credentials.Credentials) def refresh(self, request): + if self._universe_domain != _DEFAULT_UNIVERSE_DOMAIN: + raise exceptions.RefreshError( + "User credential refresh is only supported in the default " + "googleapis.com universe domain, but the current universe " + "domain is {}. If you created the credential with an access " + "token, it's likely that the provided token is expired now, " + "please update your code with a valid token.".format( + self._universe_domain + ) + ) + scopes = self._scopes if self._scopes is not None else self._default_scopes # Use refresh handler if available and no refresh token is # available. This is useful in general when tokens are obtained by calling @@ -427,6 +474,7 @@ expiry=expiry, rapt_token=info.get("rapt_token"), # may not exist trust_boundary=info.get("trust_boundary"), # may not exist + universe_domain=info.get("universe_domain"), # may not exist ) @classmethod @@ -470,6 +518,7 @@ "client_secret": self.client_secret, "scopes": self.scopes, "rapt_token": self.rapt_token, + "universe_domain": self._universe_domain, } if self.expiry: # flatten expiry timestamp prep["expiry"] = self.expiry.isoformat() + "Z" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google/oauth2/service_account.py new/google-auth-2.25.1/google/oauth2/service_account.py --- old/google-auth-2.23.4/google/oauth2/service_account.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/google/oauth2/service_account.py 2023-12-06 02:42:14.000000000 +0100 @@ -182,10 +182,7 @@ self._quota_project_id = quota_project_id self._token_uri = token_uri self._always_use_jwt_access = always_use_jwt_access - if not universe_domain: - self._universe_domain = _DEFAULT_UNIVERSE_DOMAIN - else: - self._universe_domain = universe_domain + self._universe_domain = universe_domain or _DEFAULT_UNIVERSE_DOMAIN if universe_domain != _DEFAULT_UNIVERSE_DOMAIN: self._always_use_jwt_access = True @@ -328,6 +325,22 @@ cred._always_use_jwt_access = always_use_jwt_access return cred + def with_universe_domain(self, universe_domain): + """Create a copy of these credentials with the given universe domain. + + Args: + universe_domain (str): The universe domain value. + + Returns: + google.auth.service_account.Credentials: A new credentials + instance. + """ + cred = self._make_copy() + cred._universe_domain = universe_domain + if universe_domain != _DEFAULT_UNIVERSE_DOMAIN: + cred._always_use_jwt_access = True + return cred + def with_subject(self, subject): """Create a copy of these credentials with the specified subject. @@ -417,13 +430,11 @@ @_helpers.copy_docstring(credentials.Credentials) def refresh(self, request): - if ( - self._universe_domain != _DEFAULT_UNIVERSE_DOMAIN - and not self._jwt_credentials - ): - raise exceptions.RefreshError( - "self._jwt_credentials is missing for non-default universe domain" - ) + if self._always_use_jwt_access and not self._jwt_credentials: + # If self signed jwt should be used but jwt credential is not + # created, try to create one with scopes + self._create_self_signed_jwt(None) + if self._universe_domain != _DEFAULT_UNIVERSE_DOMAIN and self._subject: raise exceptions.RefreshError( "domain wide delegation is not supported for non-default universe domain" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google_auth.egg-info/PKG-INFO new/google-auth-2.25.1/google_auth.egg-info/PKG-INFO --- old/google-auth-2.23.4/google_auth.egg-info/PKG-INFO 2023-10-31 20:38:28.000000000 +0100 +++ new/google-auth-2.25.1/google_auth.egg-info/PKG-INFO 2023-12-06 02:45:01.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: google-auth -Version: 2.23.4 +Version: 2.25.1 Summary: Google Authentication Library Home-page: https://github.com/googleapis/google-auth-library-python Author: Google Cloud Platform @@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License @@ -22,12 +23,23 @@ Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Requires-Python: >=3.7 +License-File: LICENSE +Requires-Dist: cachetools<6.0,>=2.0.0 +Requires-Dist: pyasn1-modules>=0.2.1 +Requires-Dist: rsa<5,>=3.1.4 Provides-Extra: aiohttp +Requires-Dist: aiohttp<4.0.0.dev0,>=3.6.2; extra == "aiohttp" +Requires-Dist: requests<3.0.0.dev0,>=2.20.0; extra == "aiohttp" Provides-Extra: pyopenssl +Requires-Dist: pyopenssl>=20.0.0; extra == "pyopenssl" +Requires-Dist: cryptography>=38.0.3; extra == "pyopenssl" Provides-Extra: requests +Requires-Dist: requests<3.0.0.dev0,>=2.20.0; extra == "requests" Provides-Extra: reauth -Provides-Extra: enterprise_cert -License-File: LICENSE +Requires-Dist: pyu2f>=0.1.5; extra == "reauth" +Provides-Extra: enterprise-cert +Requires-Dist: cryptography==36.0.2; extra == "enterprise-cert" +Requires-Dist: pyopenssl==22.0.0; extra == "enterprise-cert" Google Auth Python Library ========================== @@ -51,7 +63,7 @@ For more information on setting up your Python development environment, please refer to `Python Development Environment Setup Guide`_ for Google Cloud Platform. -.. _`Python Development Environment Setup Guide`: https://cloud.google.com/python/setup +.. _`Python Development Environment Setup Guide`: https://cloud.google.com/python/docs/setup Extras ------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/google_auth.egg-info/SOURCES.txt new/google-auth-2.25.1/google_auth.egg-info/SOURCES.txt --- old/google-auth-2.23.4/google_auth.egg-info/SOURCES.txt 2023-10-31 20:38:28.000000000 +0100 +++ new/google-auth-2.25.1/google_auth.egg-info/SOURCES.txt 2023-12-06 02:45:01.000000000 +0100 @@ -109,6 +109,7 @@ tests/data/context_aware_metadata.json tests/data/enterprise_cert_invalid.json tests/data/enterprise_cert_valid.json +tests/data/enterprise_cert_valid_provider.json tests/data/es256_privatekey.pem tests/data/es256_public_cert.pem tests/data/es256_publickey.pem diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/setup.py new/google-auth-2.25.1/setup.py --- old/google-auth-2.23.4/setup.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/setup.py 2023-12-06 02:42:14.000000000 +0100 @@ -70,6 +70,7 @@ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/tests/compute_engine/test__metadata.py new/google-auth-2.25.1/tests/compute_engine/test__metadata.py --- old/google-auth-2.23.4/tests/compute_engine/test__metadata.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/tests/compute_engine/test__metadata.py 2023-12-06 02:42:14.000000000 +0100 @@ -325,6 +325,18 @@ ) +def test_get_return_none_for_not_found_error(): + request = make_request("Metadata error", status=http_client.NOT_FOUND) + + assert _metadata.get(request, PATH, return_none_for_not_found_error=True) is None + + request.assert_called_once_with( + method="GET", + url=_metadata._METADATA_ROOT + PATH, + headers=_metadata._METADATA_HEADERS, + ) + + def test_get_failure_connection_failed(): request = make_request("") request.side_effect = exceptions.TransportError() @@ -371,6 +383,53 @@ assert project_id == project +def test_get_universe_domain_success(): + request = make_request( + "fake_universe_domain", headers={"content-type": "text/plain"} + ) + + universe_domain = _metadata.get_universe_domain(request) + + request.assert_called_once_with( + method="GET", + url=_metadata._METADATA_ROOT + "universe/universe_domain", + headers=_metadata._METADATA_HEADERS, + ) + assert universe_domain == "fake_universe_domain" + + +def test_get_universe_domain_not_found(): + # Test that if the universe domain endpoint returns 404 error, we should + # use googleapis.com as the universe domain + request = make_request("not found", status=http_client.NOT_FOUND) + + universe_domain = _metadata.get_universe_domain(request) + + request.assert_called_once_with( + method="GET", + url=_metadata._METADATA_ROOT + "universe/universe_domain", + headers=_metadata._METADATA_HEADERS, + ) + assert universe_domain == "googleapis.com" + + +def test_get_universe_domain_other_error(): + # Test that if the universe domain endpoint returns an error other than 404 + # we should throw the error + request = make_request("unauthorized", status=http_client.UNAUTHORIZED) + + with pytest.raises(exceptions.TransportError) as excinfo: + _metadata.get_universe_domain(request) + + assert excinfo.match(r"unauthorized") + + request.assert_called_once_with( + method="GET", + url=_metadata._METADATA_ROOT + "universe/universe_domain", + headers=_metadata._METADATA_HEADERS, + ) + + @mock.patch( "google.auth.metrics.token_request_access_token_mds", return_value=ACCESS_TOKEN_REQUEST_METRICS_HEADER_VALUE, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/tests/compute_engine/test_credentials.py new/google-auth-2.25.1/tests/compute_engine/test_credentials.py --- old/google-auth-2.23.4/tests/compute_engine/test_credentials.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/tests/compute_engine/test_credentials.py 2023-12-06 02:42:14.000000000 +0100 @@ -208,6 +208,30 @@ assert headers["authorization"] == "Bearer token" assert headers["x-goog-api-client"] == "cred-type/mds" + @mock.patch( + "google.auth.compute_engine._metadata.get_universe_domain", + return_value="fake_universe_domain", + ) + def test_universe_domain(self, get_universe_domain): + self.credentials._universe_domain_cached = False + self.credentials._universe_domain = "googleapis.com" + + # calling the universe_domain property should trigger a call to + # get_universe_domain to fetch the value. The value should be cached. + assert self.credentials.universe_domain == "fake_universe_domain" + assert self.credentials._universe_domain == "fake_universe_domain" + assert self.credentials._universe_domain_cached + get_universe_domain.assert_called_once_with( + self.credentials._universe_domain_request + ) + + # calling the universe_domain property the second time should use the + # cached value instead of calling get_universe_domain + assert self.credentials.universe_domain == "fake_universe_domain" + get_universe_domain.assert_called_once_with( + self.credentials._universe_domain_request + ) + class TestIDTokenCredentials(object): credentials = None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/tests/data/enterprise_cert_valid_provider.json new/google-auth-2.25.1/tests/data/enterprise_cert_valid_provider.json --- old/google-auth-2.23.4/tests/data/enterprise_cert_valid_provider.json 1970-01-01 01:00:00.000000000 +0100 +++ new/google-auth-2.25.1/tests/data/enterprise_cert_valid_provider.json 2023-12-06 02:42:14.000000000 +0100 @@ -0,0 +1,6 @@ +{ + "libs": { + "ecp_client": "/path/to/signer/lib", + "ecp_provider": "/path/to/provider/lib" + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/tests/oauth2/test_credentials.py new/google-auth-2.25.1/tests/oauth2/test_credentials.py --- old/google-auth-2.23.4/tests/oauth2/test_credentials.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/tests/oauth2/test_credentials.py 2023-12-06 02:42:14.000000000 +0100 @@ -122,6 +122,17 @@ assert excinfo.match("The provided refresh_handler is not a callable or None.") + def test_refresh_with_non_default_universe_domain(self): + creds = credentials.Credentials( + token="token", universe_domain="dummy_universe.com" + ) + with pytest.raises(exceptions.RefreshError) as excinfo: + creds.refresh(mock.Mock()) + + assert excinfo.match( + "refresh is only supported in the default googleapis.com universe domain" + ) + @mock.patch("google.oauth2.reauth.refresh_grant", autospec=True) @mock.patch( "google.auth._helpers.utcnow", @@ -774,6 +785,12 @@ creds.apply(headers) assert "x-goog-user-project" in headers + def test_with_universe_domain(self): + creds = credentials.Credentials(token="token") + assert creds.universe_domain == "googleapis.com" + new_creds = creds.with_universe_domain("dummy_universe.com") + assert new_creds.universe_domain == "dummy_universe.com" + def test_with_token_uri(self): info = AUTH_USER_INFO.copy() @@ -868,6 +885,7 @@ assert json_asdict.get("scopes") == creds.scopes assert json_asdict.get("client_secret") == creds.client_secret assert json_asdict.get("expiry") == info["expiry"] + assert json_asdict.get("universe_domain") == creds.universe_domain # Test with a `strip` arg json_output = creds.to_json(strip=["client_secret"]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/tests/oauth2/test_service_account.py new/google-auth-2.25.1/tests/oauth2/test_service_account.py --- old/google-auth-2.23.4/tests/oauth2/test_service_account.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/tests/oauth2/test_service_account.py 2023-12-06 02:42:14.000000000 +0100 @@ -205,6 +205,17 @@ creds_with_new_token_uri = credentials.with_token_uri(new_token_uri) assert creds_with_new_token_uri._token_uri == new_token_uri + def test_with_universe_domain(self): + credentials = self.make_credentials() + + new_credentials = credentials.with_universe_domain("dummy_universe.com") + assert new_credentials.universe_domain == "dummy_universe.com" + assert new_credentials._always_use_jwt_access + + new_credentials = credentials.with_universe_domain("googleapis.com") + assert new_credentials.universe_domain == "googleapis.com" + assert not new_credentials._always_use_jwt_access + def test__with_always_use_jwt_access(self): credentials = self.make_credentials() assert not credentials._always_use_jwt_access @@ -557,12 +568,16 @@ assert jwt_grant.called assert not self_signed_jwt_refresh.called - def test_refresh_non_gdu_missing_jwt_credentials(self): - credentials = self.make_credentials(universe_domain="foo") + def test_refresh_missing_jwt_credentials(self): + credentials = self.make_credentials() + credentials = credentials.with_scopes(["foo", "bar"]) + credentials = credentials.with_always_use_jwt_access(True) + assert not credentials._jwt_credentials + + credentials.refresh(mock.Mock()) - with pytest.raises(exceptions.RefreshError) as excinfo: - credentials.refresh(None) - assert excinfo.match("self._jwt_credentials is missing") + # jwt credentials should have been automatically created with scopes + assert credentials._jwt_credentials is not None def test_refresh_non_gdu_domain_wide_delegation_not_supported(self): credentials = self.make_credentials(universe_domain="foo") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/tests/test_credentials.py new/google-auth-2.25.1/tests/test_credentials.py --- old/google-auth-2.23.4/tests/test_credentials.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/tests/test_credentials.py 2023-12-06 02:42:14.000000000 +0100 @@ -55,9 +55,7 @@ # Set the expiration to one second more than now plus the clock skew # accomodation. These credentials should be valid. credentials.expiry = ( - datetime.datetime.utcnow() - + _helpers.REFRESH_THRESHOLD - + datetime.timedelta(seconds=1) + _helpers.utcnow() + _helpers.REFRESH_THRESHOLD + datetime.timedelta(seconds=1) ) assert credentials.valid @@ -65,7 +63,7 @@ # Set the credentials expiration to now. Because of the clock skew # accomodation, these credentials should report as expired. - credentials.expiry = datetime.datetime.utcnow() + credentials.expiry = _helpers.utcnow() assert not credentials.valid assert credentials.expired diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/tests/test_external_account.py new/google-auth-2.25.1/tests/test_external_account.py --- old/google-auth-2.23.4/tests/test_external_account.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/tests/test_external_account.py 2023-12-06 02:42:14.000000000 +0100 @@ -505,6 +505,11 @@ credentials = self.make_credentials() assert credentials.universe_domain == external_account._DEFAULT_UNIVERSE_DOMAIN + def test_with_universe_domain(self): + credentials = self.make_credentials() + new_credentials = credentials.with_universe_domain("dummy_universe.com") + assert new_credentials.universe_domain == "dummy_universe.com" + def test_info_workforce_pool(self): credentials = self.make_workforce_pool_credentials( workforce_pool_user_project=self.WORKFORCE_POOL_USER_PROJECT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/tests/transport/test__custom_tls_signer.py new/google-auth-2.25.1/tests/transport/test__custom_tls_signer.py --- old/google-auth-2.23.4/tests/transport/test__custom_tls_signer.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/tests/transport/test__custom_tls_signer.py 2023-12-06 02:42:14.000000000 +0100 @@ -11,7 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - import base64 import ctypes import os @@ -30,11 +29,19 @@ ENTERPRISE_CERT_FILE = os.path.join( os.path.dirname(__file__), "../data/enterprise_cert_valid.json" ) +ENTERPRISE_CERT_FILE_PROVIDER = os.path.join( + os.path.dirname(__file__), "../data/enterprise_cert_valid_provider.json" +) INVALID_ENTERPRISE_CERT_FILE = os.path.join( os.path.dirname(__file__), "../data/enterprise_cert_invalid.json" ) +def test_load_provider_lib(): + with mock.patch("ctypes.CDLL", return_value=mock.MagicMock()): + _custom_tls_signer.load_provider_lib("/path/to/provider/lib") + + def test_load_offload_lib(): with mock.patch("ctypes.CDLL", return_value=mock.MagicMock()): lib = _custom_tls_signer.load_offload_lib("/path/to/offload/lib") @@ -173,62 +180,81 @@ ) as load_offload_lib: load_offload_lib.return_value = offload_lib load_signer_lib.return_value = signer_lib - signer_object = _custom_tls_signer.CustomTlsSigner(ENTERPRISE_CERT_FILE) - signer_object.load_libraries() - assert signer_object._cert is None + with mock.patch( + "google.auth.transport._custom_tls_signer.get_cert" + ) as get_cert: + with mock.patch( + "google.auth.transport._custom_tls_signer.get_sign_callback" + ) as get_sign_callback: + get_cert.return_value = b"mock_cert" + signer_object = _custom_tls_signer.CustomTlsSigner( + ENTERPRISE_CERT_FILE + ) + signer_object.load_libraries() + signer_object.attach_to_ssl_context(create_urllib3_context()) + get_cert.assert_called_once() + get_sign_callback.assert_called_once() + offload_lib.ConfigureSslContext.assert_called_once() assert signer_object._enterprise_cert_file_path == ENTERPRISE_CERT_FILE assert signer_object._offload_lib == offload_lib assert signer_object._signer_lib == signer_lib load_signer_lib.assert_called_with("/path/to/signer/lib") load_offload_lib.assert_called_with("/path/to/offload/lib") - # Test set_up_custom_key and set_up_ssl_context methods - with mock.patch("google.auth.transport._custom_tls_signer.get_cert") as get_cert: - with mock.patch( - "google.auth.transport._custom_tls_signer.get_sign_callback" - ) as get_sign_callback: - get_cert.return_value = b"mock_cert" - signer_object.set_up_custom_key() - signer_object.attach_to_ssl_context(create_urllib3_context()) - get_cert.assert_called_once() - get_sign_callback.assert_called_once() - offload_lib.ConfigureSslContext.assert_called_once() +def test_custom_tls_signer_provider(): + provider_lib = mock.MagicMock() -def test_custom_tls_signer_failed_to_load_libraries(): # Test load_libraries method + with mock.patch( + "google.auth.transport._custom_tls_signer.load_provider_lib" + ) as load_provider_lib: + load_provider_lib.return_value = provider_lib + signer_object = _custom_tls_signer.CustomTlsSigner( + ENTERPRISE_CERT_FILE_PROVIDER + ) + signer_object.load_libraries() + signer_object.attach_to_ssl_context(mock.MagicMock()) + + assert signer_object._enterprise_cert_file_path == ENTERPRISE_CERT_FILE_PROVIDER + assert signer_object._provider_lib == provider_lib + load_provider_lib.assert_called_with("/path/to/provider/lib") + + +def test_custom_tls_signer_failed_to_load_libraries(): with pytest.raises(exceptions.MutualTLSChannelError) as excinfo: signer_object = _custom_tls_signer.CustomTlsSigner(INVALID_ENTERPRISE_CERT_FILE) signer_object.load_libraries() assert excinfo.match("enterprise cert file is invalid") -def test_custom_tls_signer_fail_to_offload(): - offload_lib = mock.MagicMock() - signer_lib = mock.MagicMock() +def test_custom_tls_signer_failed_to_attach(): + with pytest.raises(exceptions.MutualTLSChannelError) as excinfo: + signer_object = _custom_tls_signer.CustomTlsSigner(ENTERPRISE_CERT_FILE) + signer_object._offload_lib = mock.MagicMock() + signer_object._signer_lib = mock.MagicMock() + signer_object._sign_callback = mock.MagicMock() + signer_object._cert = b"mock cert" + signer_object._offload_lib.ConfigureSslContext.return_value = False + signer_object.attach_to_ssl_context(mock.MagicMock()) + assert excinfo.match("failed to configure ECP Offload SSL context") - with mock.patch( - "google.auth.transport._custom_tls_signer.load_signer_lib" - ) as load_signer_lib: - with mock.patch( - "google.auth.transport._custom_tls_signer.load_offload_lib" - ) as load_offload_lib: - load_offload_lib.return_value = offload_lib - load_signer_lib.return_value = signer_lib - signer_object = _custom_tls_signer.CustomTlsSigner(ENTERPRISE_CERT_FILE) - signer_object.load_libraries() - # set the return value to be 0 which indicts offload fails - offload_lib.ConfigureSslContext.return_value = 0 +def test_custom_tls_signer_failed_to_attach_provider(): + with pytest.raises(exceptions.MutualTLSChannelError) as excinfo: + signer_object = _custom_tls_signer.CustomTlsSigner( + ENTERPRISE_CERT_FILE_PROVIDER + ) + signer_object._provider_lib = mock.MagicMock() + signer_object._provider_lib.ECP_attach_to_ctx.return_value = False + signer_object.attach_to_ssl_context(mock.MagicMock()) + assert excinfo.match("failed to configure ECP Provider SSL context") + +def test_custom_tls_signer_failed_to_attach_no_libs(): with pytest.raises(exceptions.MutualTLSChannelError) as excinfo: - with mock.patch( - "google.auth.transport._custom_tls_signer.get_cert" - ) as get_cert: - with mock.patch( - "google.auth.transport._custom_tls_signer.get_sign_callback" - ): - get_cert.return_value = b"mock_cert" - signer_object.set_up_custom_key() - signer_object.attach_to_ssl_context(create_urllib3_context()) - assert excinfo.match("failed to configure SSL context") + signer_object = _custom_tls_signer.CustomTlsSigner(ENTERPRISE_CERT_FILE) + signer_object._offload_lib = None + signer_object._signer_lib = None + signer_object.attach_to_ssl_context(mock.MagicMock()) + assert excinfo.match("Invalid ECP configuration.") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.23.4/tests/transport/test_requests.py new/google-auth-2.25.1/tests/transport/test_requests.py --- old/google-auth-2.23.4/tests/transport/test_requests.py 2023-10-31 20:35:33.000000000 +0100 +++ new/google-auth-2.25.1/tests/transport/test_requests.py 2023-12-06 02:42:14.000000000 +0100 @@ -545,16 +545,12 @@ google.auth.transport._custom_tls_signer.CustomTlsSigner, "load_libraries" ) @mock.patch.object( - google.auth.transport._custom_tls_signer.CustomTlsSigner, "set_up_custom_key" - ) - @mock.patch.object( google.auth.transport._custom_tls_signer.CustomTlsSigner, "attach_to_ssl_context", ) def test_success( self, mock_attach_to_ssl_context, - mock_set_up_custom_key, mock_load_libraries, mock_proxy_manager_for, mock_init_poolmanager, @@ -565,7 +561,6 @@ ) mock_load_libraries.assert_called_once() - mock_set_up_custom_key.assert_called_once() assert mock_attach_to_ssl_context.call_count == 2 adapter.init_poolmanager()
