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 2024-12-08 11:36:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-google-auth (Old)
 and      /work/SRC/openSUSE:Factory/.python-google-auth.new.21547 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-google-auth"

Sun Dec  8 11:36:24 2024 rev:50 rq:1228735 version:2.36.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-google-auth/python-google-auth.changes    
2024-10-03 18:00:03.069365643 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-google-auth.new.21547/python-google-auth.changes
 2024-12-08 11:37:32.766657731 +0100
@@ -1,0 +2,16 @@
+Thu Dec  5 11:00:48 UTC 2024 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to version 2.36.0
+  * IAM signblob retries (#1600)
+  * Making IAM endpoint universe-aware (#1604)
+  * Support External Account Authorized User as a Source
+    Credential for impersonated credentials in ADC (#1608)
+  * Adding default parameters to updated interfaces (#1622)
+  * Change universe_domain to universe-domain (#1613)
+  * Remove base class to avoid type conflict (#1619)
+  * Revert templates for iam endpoints (#1614)
+  * Update secret (#1611)
+  * Update secret (#1617)
+  * Update secret (#1621)
+
+-------------------------------------------------------------------

Old:
----
  google_auth-2.35.0.tar.gz

New:
----
  google_auth-2.36.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-google-auth.spec ++++++
--- /var/tmp/diff_new_pack.SD3yOx/_old  2024-12-08 11:37:33.266678503 +0100
+++ /var/tmp/diff_new_pack.SD3yOx/_new  2024-12-08 11:37:33.270678670 +0100
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-google-auth
-Version:        2.35.0
+Version:        2.36.0
 Release:        0
 Summary:        Google Authentication Library
 License:        Apache-2.0
@@ -34,9 +34,9 @@
 BuildRequires:  %{python_module freezegun}
 BuildRequires:  %{python_module pyOpenSSL >= 22.0.0}
 BuildRequires:  %{python_module pyasn1-modules >= 0.2.1}
+BuildRequires:  %{python_module pytest-asyncio}
 BuildRequires:  %{python_module pytest-localserver}
 BuildRequires:  %{python_module pytest}
-BuildRequires:  %{python_module pytest-asyncio}
 BuildRequires:  %{python_module pyu2f >= 0.1.5}
 BuildRequires:  %{python_module requests >= 2.20.0}
 BuildRequires:  %{python_module responses}

++++++ google_auth-2.35.0.tar.gz -> google_auth-2.36.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/PKG-INFO 
new/google_auth-2.36.0/PKG-INFO
--- old/google_auth-2.35.0/PKG-INFO     2024-09-19 20:07:29.919246000 +0200
+++ new/google_auth-2.36.0/PKG-INFO     2024-11-06 19:05:17.942188700 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: google-auth
-Version: 2.35.0
+Version: 2.36.0
 Summary: Google Authentication Library
 Home-page: https://github.com/googleapis/google-auth-library-python
 Author: Google Cloud Platform
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/google/auth/_default.py 
new/google_auth-2.36.0/google/auth/_default.py
--- old/google_auth-2.35.0/google/auth/_default.py      2024-09-19 
20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/google/auth/_default.py      2024-11-06 
19:02:16.000000000 +0100
@@ -472,6 +472,10 @@
             source_credentials, _ = _get_service_account_credentials(
                 filename, source_credentials_info
             )
+        elif source_credentials_type == _EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE:
+            source_credentials, _ = 
_get_external_account_authorized_user_credentials(
+                filename, source_credentials_info
+            )
         else:
             raise exceptions.InvalidType(
                 "source credential of type {} is not supported.".format(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/google_auth-2.35.0/google/auth/compute_engine/_metadata.py 
new/google_auth-2.36.0/google/auth/compute_engine/_metadata.py
--- old/google_auth-2.35.0/google/auth/compute_engine/_metadata.py      
2024-09-19 20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/google/auth/compute_engine/_metadata.py      
2024-11-06 19:02:16.000000000 +0100
@@ -294,7 +294,7 @@
             404 occurs while retrieving metadata.
     """
     universe_domain = get(
-        request, "universe/universe_domain", 
return_none_for_not_found_error=True
+        request, "universe/universe-domain", 
return_none_for_not_found_error=True
     )
     if not universe_domain:
         return "googleapis.com"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/google/auth/iam.py 
new/google_auth-2.36.0/google/auth/iam.py
--- old/google_auth-2.35.0/google/auth/iam.py   2024-09-19 20:05:39.000000000 
+0200
+++ new/google_auth-2.36.0/google/auth/iam.py   2024-11-06 19:02:16.000000000 
+0100
@@ -23,10 +23,18 @@
 import http.client as http_client
 import json
 
+from google.auth import _exponential_backoff
 from google.auth import _helpers
+from google.auth import credentials
 from google.auth import crypt
 from google.auth import exceptions
 
+IAM_RETRY_CODES = {
+    http_client.INTERNAL_SERVER_ERROR,
+    http_client.BAD_GATEWAY,
+    http_client.SERVICE_UNAVAILABLE,
+    http_client.GATEWAY_TIMEOUT,
+}
 
 _IAM_SCOPE = ["https://www.googleapis.com/auth/iam";]
 
@@ -82,21 +90,30 @@
         message = _helpers.to_bytes(message)
 
         method = "POST"
-        url = _IAM_SIGN_ENDPOINT.format(self._service_account_email)
+        url = _IAM_SIGN_ENDPOINT.replace(
+            credentials.DEFAULT_UNIVERSE_DOMAIN, 
self._credentials.universe_domain
+        ).format(self._service_account_email)
         headers = {"Content-Type": "application/json"}
         body = json.dumps(
             {"payload": base64.b64encode(message).decode("utf-8")}
         ).encode("utf-8")
 
-        self._credentials.before_request(self._request, method, url, headers)
-        response = self._request(url=url, method=method, body=body, 
headers=headers)
+        retries = _exponential_backoff.ExponentialBackoff()
+        for _ in retries:
+            self._credentials.before_request(self._request, method, url, 
headers)
+
+            response = self._request(url=url, method=method, body=body, 
headers=headers)
+
+            if response.status in IAM_RETRY_CODES:
+                continue
+
+            if response.status != http_client.OK:
+                raise exceptions.TransportError(
+                    "Error calling the IAM signBlob API: 
{}".format(response.data)
+                )
 
-        if response.status != http_client.OK:
-            raise exceptions.TransportError(
-                "Error calling the IAM signBlob API: {}".format(response.data)
-            )
-
-        return json.loads(response.data.decode("utf-8"))
+            return json.loads(response.data.decode("utf-8"))
+        raise exceptions.TransportError("exhausted signBlob endpoint retries")
 
     @property
     def key_id(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/google_auth-2.35.0/google/auth/impersonated_credentials.py 
new/google_auth-2.36.0/google/auth/impersonated_credentials.py
--- old/google_auth-2.35.0/google/auth/impersonated_credentials.py      
2024-09-19 20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/google/auth/impersonated_credentials.py      
2024-11-06 19:02:16.000000000 +0100
@@ -31,6 +31,7 @@
 import http.client as http_client
 import json
 
+from google.auth import _exponential_backoff
 from google.auth import _helpers
 from google.auth import credentials
 from google.auth import exceptions
@@ -45,7 +46,12 @@
 
 
 def _make_iam_token_request(
-    request, principal, headers, body, iam_endpoint_override=None
+    request,
+    principal,
+    headers,
+    body,
+    universe_domain=credentials.DEFAULT_UNIVERSE_DOMAIN,
+    iam_endpoint_override=None,
 ):
     """Makes a request to the Google Cloud IAM service for an access token.
     Args:
@@ -66,7 +72,9 @@
             `iamcredentials.googleapis.com` is not enabled or the
             `Service Account Token Creator` is not assigned
     """
-    iam_endpoint = iam_endpoint_override or iam._IAM_ENDPOINT.format(principal)
+    iam_endpoint = iam_endpoint_override or iam._IAM_ENDPOINT.replace(
+        credentials.DEFAULT_UNIVERSE_DOMAIN, universe_domain
+    ).format(principal)
 
     body = json.dumps(body).encode("utf-8")
 
@@ -218,6 +226,8 @@
                 and self._source_credentials._always_use_jwt_access
             ):
                 self._source_credentials._create_self_signed_jwt(None)
+
+        self._universe_domain = source_credentials.universe_domain
         self._target_principal = target_principal
         self._target_scopes = target_scopes
         self._delegates = delegates
@@ -270,13 +280,16 @@
             principal=self._target_principal,
             headers=headers,
             body=body,
+            universe_domain=self.universe_domain,
             iam_endpoint_override=self._iam_endpoint_override,
         )
 
     def sign_bytes(self, message):
         from google.auth.transport.requests import AuthorizedSession
 
-        iam_sign_endpoint = 
iam._IAM_SIGN_ENDPOINT.format(self._target_principal)
+        iam_sign_endpoint = iam._IAM_SIGN_ENDPOINT.replace(
+            credentials.DEFAULT_UNIVERSE_DOMAIN, self.universe_domain
+        ).format(self._target_principal)
 
         body = {
             "payload": base64.b64encode(message).decode("utf-8"),
@@ -288,18 +301,22 @@
         authed_session = AuthorizedSession(self._source_credentials)
 
         try:
-            response = authed_session.post(
-                url=iam_sign_endpoint, headers=headers, json=body
-            )
+            retries = _exponential_backoff.ExponentialBackoff()
+            for _ in retries:
+                response = authed_session.post(
+                    url=iam_sign_endpoint, headers=headers, json=body
+                )
+                if response.status_code in iam.IAM_RETRY_CODES:
+                    continue
+                if response.status_code != http_client.OK:
+                    raise exceptions.TransportError(
+                        "Error calling sign_bytes: {}".format(response.json())
+                    )
+
+                return base64.b64decode(response.json()["signedBlob"])
         finally:
             authed_session.close()
-
-        if response.status_code != http_client.OK:
-            raise exceptions.TransportError(
-                "Error calling sign_bytes: {}".format(response.json())
-            )
-
-        return base64.b64decode(response.json()["signedBlob"])
+        raise exceptions.TransportError("exhausted signBlob endpoint retries")
 
     @property
     def signer_email(self):
@@ -422,9 +439,10 @@
     def refresh(self, request):
         from google.auth.transport.requests import AuthorizedSession
 
-        iam_sign_endpoint = iam._IAM_IDTOKEN_ENDPOINT.format(
-            self._target_credentials.signer_email
-        )
+        iam_sign_endpoint = iam._IAM_IDTOKEN_ENDPOINT.replace(
+            credentials.DEFAULT_UNIVERSE_DOMAIN,
+            self._target_credentials.universe_domain,
+        ).format(self._target_credentials.signer_email)
 
         body = {
             "audience": self._target_audience,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/google_auth-2.35.0/google/auth/transport/_requests_base.py 
new/google_auth-2.36.0/google/auth/transport/_requests_base.py
--- old/google_auth-2.35.0/google/auth/transport/_requests_base.py      
2024-09-19 20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/google/auth/transport/_requests_base.py      
2024-11-06 19:02:16.000000000 +0100
@@ -13,7 +13,8 @@
 # limitations under the License.
 
 """Transport adapter for Base Requests."""
-
+# NOTE: The coverage for this file is temporarily disabled in `.coveragerc`
+# since it is currently unused.
 
 import abc
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/google/auth/transport/requests.py 
new/google_auth-2.36.0/google/auth/transport/requests.py
--- old/google_auth-2.35.0/google/auth/transport/requests.py    2024-09-19 
20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/google/auth/transport/requests.py    2024-11-06 
19:02:16.000000000 +0100
@@ -38,7 +38,6 @@
 from google.auth import exceptions
 from google.auth import transport
 import google.auth.transport._mtls_helper
-from google.auth.transport._requests_base import _BaseAuthorizedSession
 from google.oauth2 import service_account
 
 _LOGGER = logging.getLogger(__name__)
@@ -293,7 +292,7 @@
         return super(_MutualTlsOffloadAdapter, self).proxy_manager_for(*args, 
**kwargs)
 
 
-class AuthorizedSession(requests.Session, _BaseAuthorizedSession):
+class AuthorizedSession(requests.Session):
     """A Requests Session class with credentials.
 
     This class is used to perform requests to API endpoints that require
@@ -390,7 +389,7 @@
         default_host=None,
     ):
         super(AuthorizedSession, self).__init__()
-        _BaseAuthorizedSession.__init__(self, credentials)
+        self.credentials = credentials
         self._refresh_status_codes = refresh_status_codes
         self._max_refresh_attempts = max_refresh_attempts
         self._refresh_timeout = refresh_timeout
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/google/auth/version.py 
new/google_auth-2.36.0/google/auth/version.py
--- old/google_auth-2.35.0/google/auth/version.py       2024-09-19 
20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/google/auth/version.py       2024-11-06 
19:02:16.000000000 +0100
@@ -12,4 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-__version__ = "2.35.0"
+__version__ = "2.36.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/google/oauth2/_client.py 
new/google_auth-2.36.0/google/oauth2/_client.py
--- old/google_auth-2.35.0/google/oauth2/_client.py     2024-09-19 
20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/google/oauth2/_client.py     2024-11-06 
19:02:16.000000000 +0100
@@ -30,6 +30,7 @@
 
 from google.auth import _exponential_backoff
 from google.auth import _helpers
+from google.auth import credentials
 from google.auth import exceptions
 from google.auth import jwt
 from google.auth import metrics
@@ -319,7 +320,12 @@
 
 
 def call_iam_generate_id_token_endpoint(
-    request, iam_id_token_endpoint, signer_email, audience, access_token
+    request,
+    iam_id_token_endpoint,
+    signer_email,
+    audience,
+    access_token,
+    universe_domain=credentials.DEFAULT_UNIVERSE_DOMAIN,
 ):
     """Call iam.generateIdToken endpoint to get ID token.
 
@@ -339,7 +345,9 @@
 
     response_data = _token_endpoint_request(
         request,
-        iam_id_token_endpoint.format(signer_email),
+        iam_id_token_endpoint.replace(
+            credentials.DEFAULT_UNIVERSE_DOMAIN, universe_domain
+        ).format(signer_email),
         body,
         access_token=access_token,
         use_json=True,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/google/oauth2/service_account.py 
new/google_auth-2.36.0/google/oauth2/service_account.py
--- old/google_auth-2.35.0/google/oauth2/service_account.py     2024-09-19 
20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/google/oauth2/service_account.py     2024-11-06 
19:02:16.000000000 +0100
@@ -812,6 +812,7 @@
             self.signer_email,
             self._target_audience,
             jwt_credentials.token.decode(),
+            self._universe_domain,
         )
 
     @_helpers.copy_docstring(credentials.Credentials)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/google_auth.egg-info/PKG-INFO 
new/google_auth-2.36.0/google_auth.egg-info/PKG-INFO
--- old/google_auth-2.35.0/google_auth.egg-info/PKG-INFO        2024-09-19 
20:07:29.000000000 +0200
+++ new/google_auth-2.36.0/google_auth.egg-info/PKG-INFO        2024-11-06 
19:05:17.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: google-auth
-Version: 2.35.0
+Version: 2.36.0
 Summary: Google Authentication Library
 Home-page: https://github.com/googleapis/google-auth-library-python
 Author: Google Cloud Platform
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/google_auth.egg-info/SOURCES.txt 
new/google_auth-2.36.0/google_auth.egg-info/SOURCES.txt
--- old/google_auth-2.35.0/google_auth.egg-info/SOURCES.txt     2024-09-19 
20:07:29.000000000 +0200
+++ new/google_auth-2.36.0/google_auth.egg-info/SOURCES.txt     2024-11-06 
19:05:17.000000000 +0100
@@ -135,6 +135,7 @@
 tests/data/external_subject_token.txt
 tests/data/gdch_service_account.json
 tests/data/impersonated_service_account_authorized_user_source.json
+tests/data/impersonated_service_account_external_account_authorized_user_source.json
 tests/data/impersonated_service_account_service_account_source.json
 tests/data/impersonated_service_account_with_quota_project.json
 tests/data/old_oauth_credentials_py3.pickle
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/google_auth-2.35.0/tests/compute_engine/test__metadata.py 
new/google_auth-2.36.0/tests/compute_engine/test__metadata.py
--- old/google_auth-2.35.0/tests/compute_engine/test__metadata.py       
2024-09-19 20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/tests/compute_engine/test__metadata.py       
2024-11-06 19:02:16.000000000 +0100
@@ -397,7 +397,7 @@
 
     request.assert_called_once_with(
         method="GET",
-        url=_metadata._METADATA_ROOT + "universe/universe_domain",
+        url=_metadata._METADATA_ROOT + "universe/universe-domain",
         headers=_metadata._METADATA_HEADERS,
     )
     assert universe_domain == "fake_universe_domain"
@@ -410,7 +410,7 @@
 
     request.assert_called_once_with(
         method="GET",
-        url=_metadata._METADATA_ROOT + "universe/universe_domain",
+        url=_metadata._METADATA_ROOT + "universe/universe-domain",
         headers=_metadata._METADATA_HEADERS,
     )
     assert universe_domain == "googleapis.com"
@@ -425,7 +425,7 @@
 
     request.assert_called_once_with(
         method="GET",
-        url=_metadata._METADATA_ROOT + "universe/universe_domain",
+        url=_metadata._METADATA_ROOT + "universe/universe-domain",
         headers=_metadata._METADATA_HEADERS,
     )
     assert universe_domain == "googleapis.com"
@@ -445,7 +445,7 @@
 
     request.assert_called_with(
         method="GET",
-        url=_metadata._METADATA_ROOT + "universe/universe_domain",
+        url=_metadata._METADATA_ROOT + "universe/universe-domain",
         headers=_metadata._METADATA_HEADERS,
     )
     assert request.call_count == 5
@@ -487,12 +487,12 @@
 
     request_error.assert_called_once_with(
         method="GET",
-        url=_metadata._METADATA_ROOT + "universe/universe_domain",
+        url=_metadata._METADATA_ROOT + "universe/universe-domain",
         headers=_metadata._METADATA_HEADERS,
     )
     request_ok.assert_called_once_with(
         method="GET",
-        url=_metadata._METADATA_ROOT + "universe/universe_domain",
+        url=_metadata._METADATA_ROOT + "universe/universe-domain",
         headers=_metadata._METADATA_HEADERS,
     )
 
@@ -511,7 +511,7 @@
 
     request.assert_called_once_with(
         method="GET",
-        url=_metadata._METADATA_ROOT + "universe/universe_domain",
+        url=_metadata._METADATA_ROOT + "universe/universe-domain",
         headers=_metadata._METADATA_HEADERS,
     )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/google_auth-2.35.0/tests/compute_engine/test_credentials.py 
new/google_auth-2.36.0/tests/compute_engine/test_credentials.py
--- old/google_auth-2.35.0/tests/compute_engine/test_credentials.py     
2024-09-19 20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/tests/compute_engine/test_credentials.py     
2024-11-06 19:02:16.000000000 +0100
@@ -487,6 +487,16 @@
             },
         )
 
+        # mock information about universe_domain
+        responses.add(
+            responses.GET,
+            "http://metadata.google.internal/computeMetadata/v1/universe/";
+            "universe-domain",
+            status=200,
+            content_type="application/json",
+            json={},
+        )
+
         # mock token for credentials
         responses.add(
             responses.GET,
@@ -659,6 +669,16 @@
             },
         )
 
+        # stubby response about universe_domain
+        responses.add(
+            responses.GET,
+            "http://metadata.google.internal/computeMetadata/v1/universe/";
+            "universe-domain",
+            status=200,
+            content_type="application/json",
+            json={},
+        )
+
         # mock sign blob endpoint
         signature = base64.b64encode(b"some-signature").decode("utf-8")
         responses.add(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/google_auth-2.35.0/tests/data/impersonated_service_account_external_account_authorized_user_source.json
 
new/google_auth-2.36.0/tests/data/impersonated_service_account_external_account_authorized_user_source.json
--- 
old/google_auth-2.35.0/tests/data/impersonated_service_account_external_account_authorized_user_source.json
 1970-01-01 01:00:00.000000000 +0100
+++ 
new/google_auth-2.36.0/tests/data/impersonated_service_account_external_account_authorized_user_source.json
 2024-11-06 19:02:16.000000000 +0100
@@ -0,0 +1,16 @@
+{
+    "delegates": [
+        "[email protected]"
+    ],
+    "service_account_impersonation_url": 
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/[email protected]:generateAccessToken";,
+    "source_credentials": {
+        "type": "external_account_authorized_user",
+        "audience": 
"//iam.googleapis.com/locations/global/workforcePools/$WORKFORCE_POOL_ID/providers/$PROVIDER_ID",
+        "refresh_token": "refreshToken",
+        "token_url": "https://sts.googleapis.com/v1/oauth/token";,
+        "token_info_url": "https://sts.googleapis.com/v1/instrospect";,
+        "client_id": "clientId",
+        "client_secret": "clientSecret"
+    },
+    "type": "impersonated_service_account"
+}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/tests/oauth2/test__client.py 
new/google_auth-2.36.0/tests/oauth2/test__client.py
--- old/google_auth-2.35.0/tests/oauth2/test__client.py 2024-09-19 
20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/tests/oauth2/test__client.py 2024-11-06 
19:02:16.000000000 +0100
@@ -324,6 +324,7 @@
         "fake_email",
         "fake_audience",
         "fake_access_token",
+        "googleapis.com",
     )
 
     assert (
@@ -361,6 +362,7 @@
             "fake_email",
             "fake_audience",
             "fake_access_token",
+            "googleapis.com",
         )
     assert excinfo.match("No ID token in response")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/google_auth-2.35.0/tests/oauth2/test_service_account.py 
new/google_auth-2.36.0/tests/oauth2/test_service_account.py
--- old/google_auth-2.35.0/tests/oauth2/test_service_account.py 2024-09-19 
20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/tests/oauth2/test_service_account.py 2024-11-06 
19:02:16.000000000 +0100
@@ -789,7 +789,7 @@
         )
         request = mock.Mock()
         credentials.refresh(request)
-        req, iam_endpoint, signer_email, target_audience, access_token = 
call_iam_generate_id_token_endpoint.call_args[
+        req, iam_endpoint, signer_email, target_audience, access_token, 
universe_domain = call_iam_generate_id_token_endpoint.call_args[
             0
         ]
         assert req == request
@@ -811,7 +811,7 @@
         )
         request = mock.Mock()
         credentials.refresh(request)
-        req, iam_endpoint, signer_email, target_audience, access_token = 
call_iam_generate_id_token_endpoint.call_args[
+        req, iam_endpoint, signer_email, target_audience, access_token, 
universe_domain = call_iam_generate_id_token_endpoint.call_args[
             0
         ]
         assert req == request
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/tests/test__default.py 
new/google_auth-2.36.0/tests/test__default.py
--- old/google_auth-2.35.0/tests/test__default.py       2024-09-19 
20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/tests/test__default.py       2024-11-06 
19:02:16.000000000 +0100
@@ -153,6 +153,11 @@
     DATA_DIR, "impersonated_service_account_service_account_source.json"
 )
 
+IMPERSONATED_SERVICE_ACCOUNT_EXTERNAL_ACCOUNT_AUTHORIZED_USER_SOURCE_FILE = 
os.path.join(
+    DATA_DIR,
+    
"impersonated_service_account_external_account_authorized_user_source.json",
+)
+
 EXTERNAL_ACCOUNT_AUTHORIZED_USER_FILE = os.path.join(
     DATA_DIR, "external_account_authorized_user.json"
 )
@@ -365,6 +370,17 @@
     assert not credentials._quota_project_id
 
 
+def 
test_load_credentials_from_file_impersonated_with_external_account_authorized_user_source():
+    credentials, _ = _default.load_credentials_from_file(
+        
IMPERSONATED_SERVICE_ACCOUNT_EXTERNAL_ACCOUNT_AUTHORIZED_USER_SOURCE_FILE
+    )
+    assert isinstance(credentials, impersonated_credentials.Credentials)
+    assert isinstance(
+        credentials._source_credentials, 
external_account_authorized_user.Credentials
+    )
+    assert not credentials._quota_project_id
+
+
 def test_load_credentials_from_file_impersonated_passing_quota_project():
     credentials, _ = _default.load_credentials_from_file(
         IMPERSONATED_SERVICE_ACCOUNT_SERVICE_ACCOUNT_SOURCE_FILE,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/google_auth-2.35.0/tests/test_iam.py 
new/google_auth-2.36.0/tests/test_iam.py
--- old/google_auth-2.35.0/tests/test_iam.py    2024-09-19 20:05:39.000000000 
+0200
+++ new/google_auth-2.36.0/tests/test_iam.py    2024-11-06 19:02:16.000000000 
+0100
@@ -91,6 +91,7 @@
         assert returned_signature == signature
         kwargs = request.call_args[1]
         assert kwargs["headers"]["Content-Type"] == "application/json"
+        request.call_count == 1
 
     def test_sign_bytes_failure(self):
         request = make_request(http_client.UNAUTHORIZED)
@@ -100,3 +101,15 @@
 
         with pytest.raises(exceptions.TransportError):
             signer.sign("123")
+        request.call_count == 1
+
+    @mock.patch("time.sleep", return_value=None)
+    def test_sign_bytes_retryable_failure(self, mock_time):
+        request = make_request(http_client.INTERNAL_SERVER_ERROR)
+        credentials = make_credentials()
+
+        signer = iam.Signer(request, credentials, 
mock.sentinel.service_account_email)
+
+        with pytest.raises(exceptions.TransportError):
+            signer.sign("123")
+        request.call_count == 3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/google_auth-2.35.0/tests/test_impersonated_credentials.py 
new/google_auth-2.36.0/tests/test_impersonated_credentials.py
--- old/google_auth-2.35.0/tests/test_impersonated_credentials.py       
2024-09-19 20:05:39.000000000 +0200
+++ new/google_auth-2.36.0/tests/test_impersonated_credentials.py       
2024-11-06 19:02:16.000000000 +0100
@@ -146,6 +146,13 @@
             "principal": "[email protected]",
         }
 
+    def test_universe_domain_matching_source(self):
+        source_credentials = service_account.Credentials(
+            SIGNER, "[email protected]", TOKEN_URI, universe_domain="foo.bar"
+        )
+        credentials = 
self.make_credentials(source_credentials=source_credentials)
+        assert credentials.universe_domain == "foo.bar"
+
     def test__make_copy_get_cred_info(self):
         credentials = self.make_credentials()
         credentials._cred_file_path = "/path/to/file"
@@ -232,6 +239,38 @@
         )
 
     @pytest.mark.parametrize("use_data_bytes", [True, False])
+    def test_refresh_success_nonGdu(self, use_data_bytes, 
mock_donor_credentials):
+        source_credentials = service_account.Credentials(
+            SIGNER, "[email protected]", TOKEN_URI, universe_domain="foo.bar"
+        )
+        credentials = self.make_credentials(
+            lifetime=None, source_credentials=source_credentials
+        )
+        token = "token"
+
+        expire_time = (
+            _helpers.utcnow().replace(microsecond=0) + 
datetime.timedelta(seconds=500)
+        ).isoformat("T") + "Z"
+        response_body = {"accessToken": token, "expireTime": expire_time}
+
+        request = self.make_request(
+            data=json.dumps(response_body),
+            status=http_client.OK,
+            use_data_bytes=use_data_bytes,
+        )
+
+        credentials.refresh(request)
+
+        assert credentials.valid
+        assert not credentials.expired
+        # Confirm override endpoint used.
+        request_kwargs = request.call_args[1]
+        assert (
+            request_kwargs["url"]
+            == 
"https://iamcredentials.foo.bar/v1/projects/-/serviceAccounts/[email protected]:generateAccessToken";
+        )
+
+    @pytest.mark.parametrize("use_data_bytes", [True, False])
     def test_refresh_success_iam_endpoint_override(
         self, use_data_bytes, mock_donor_credentials
     ):
@@ -397,6 +436,38 @@
 
     def test_sign_bytes(self, mock_donor_credentials, 
mock_authorizedsession_sign):
         credentials = self.make_credentials(lifetime=None)
+        expected_url = 
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/[email protected]:signBlob";
+        self._sign_bytes_helper(
+            credentials,
+            mock_donor_credentials,
+            mock_authorizedsession_sign,
+            expected_url,
+        )
+
+    def test_sign_bytes_nonGdu(
+        self, mock_donor_credentials, mock_authorizedsession_sign
+    ):
+        source_credentials = service_account.Credentials(
+            SIGNER, "[email protected]", TOKEN_URI, universe_domain="foo.bar"
+        )
+        credentials = self.make_credentials(
+            lifetime=None, source_credentials=source_credentials
+        )
+        expected_url = 
"https://iamcredentials.foo.bar/v1/projects/-/serviceAccounts/[email protected]:signBlob";
+        self._sign_bytes_helper(
+            credentials,
+            mock_donor_credentials,
+            mock_authorizedsession_sign,
+            expected_url,
+        )
+
+    def _sign_bytes_helper(
+        self,
+        credentials,
+        mock_donor_credentials,
+        mock_authorizedsession_sign,
+        expected_url,
+    ):
         token = "token"
 
         expire_time = (
@@ -412,11 +483,19 @@
         request.return_value = response
 
         credentials.refresh(request)
-
         assert credentials.valid
         assert not credentials.expired
 
         signature = credentials.sign_bytes(b"signed bytes")
+        mock_authorizedsession_sign.assert_called_with(
+            mock.ANY,
+            "POST",
+            expected_url,
+            None,
+            json={"payload": "c2lnbmVkIGJ5dGVz", "delegates": []},
+            headers={"Content-Type": "application/json"},
+        )
+
         assert signature == b"signature"
 
     def test_sign_bytes_failure(self):
@@ -426,12 +505,28 @@
             "google.auth.transport.requests.AuthorizedSession.request", 
autospec=True
         ) as auth_session:
             data = {"error": {"code": 403, "message": "unauthorized"}}
-            auth_session.return_value = MockResponse(data, 
http_client.FORBIDDEN)
+            mock_response = MockResponse(data, http_client.UNAUTHORIZED)
+            auth_session.return_value = mock_response
 
             with pytest.raises(exceptions.TransportError) as excinfo:
                 credentials.sign_bytes(b"foo")
             assert excinfo.match("'code': 403")
 
+    @mock.patch("time.sleep", return_value=None)
+    def test_sign_bytes_retryable_failure(self, mock_time):
+        credentials = self.make_credentials(lifetime=None)
+
+        with mock.patch(
+            "google.auth.transport.requests.AuthorizedSession.request", 
autospec=True
+        ) as auth_session:
+            data = {"error": {"code": 500, "message": "internal_failure"}}
+            mock_response = MockResponse(data, 
http_client.INTERNAL_SERVER_ERROR)
+            auth_session.return_value = mock_response
+
+            with pytest.raises(exceptions.TransportError) as excinfo:
+                credentials.sign_bytes(b"foo")
+            assert excinfo.match("exhausted signBlob endpoint retries")
+
     def test_with_quota_project(self):
         credentials = self.make_credentials()
 
@@ -547,6 +642,45 @@
         self, mock_donor_credentials, mock_authorizedsession_idtoken
     ):
         credentials = self.make_credentials(lifetime=None)
+        target_credentials = self.make_credentials(lifetime=None)
+        expected_url = 
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/[email protected]:generateIdToken";
+        self._test_id_token_helper(
+            credentials,
+            target_credentials,
+            mock_donor_credentials,
+            mock_authorizedsession_idtoken,
+            expected_url,
+        )
+
+    def test_id_token_from_credential_nonGdu(
+        self, mock_donor_credentials, mock_authorizedsession_idtoken
+    ):
+        source_credentials = service_account.Credentials(
+            SIGNER, "[email protected]", TOKEN_URI, universe_domain="foo.bar"
+        )
+        credentials = self.make_credentials(
+            lifetime=None, source_credentials=source_credentials
+        )
+        target_credentials = self.make_credentials(
+            lifetime=None, source_credentials=source_credentials
+        )
+        expected_url = 
"https://iamcredentials.foo.bar/v1/projects/-/serviceAccounts/[email protected]:generateIdToken";
+        self._test_id_token_helper(
+            credentials,
+            target_credentials,
+            mock_donor_credentials,
+            mock_authorizedsession_idtoken,
+            expected_url,
+        )
+
+    def _test_id_token_helper(
+        self,
+        credentials,
+        target_credentials,
+        mock_donor_credentials,
+        mock_authorizedsession_idtoken,
+        expected_url,
+    ):
         token = "token"
         target_audience = "https://foo.bar";
 
@@ -564,17 +698,19 @@
         assert credentials.valid
         assert not credentials.expired
 
-        new_credentials = self.make_credentials(lifetime=None)
-
         id_creds = impersonated_credentials.IDTokenCredentials(
             credentials, target_audience=target_audience, include_email=True
         )
-        id_creds = 
id_creds.from_credentials(target_credentials=new_credentials)
+        id_creds = 
id_creds.from_credentials(target_credentials=target_credentials)
         id_creds.refresh(request)
 
+        args = mock_authorizedsession_idtoken.call_args.args
+
+        assert args[2] == expected_url
+
         assert id_creds.token == ID_TOKEN_DATA
         assert id_creds._include_email is True
-        assert id_creds._target_credentials is new_credentials
+        assert id_creds._target_credentials is target_credentials
 
     def test_id_token_with_target_audience(
         self, mock_donor_credentials, mock_authorizedsession_idtoken

Reply via email to