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-05-19 11:55:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-google-auth (Old) and /work/SRC/openSUSE:Factory/.python-google-auth.new.1533 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-auth" Fri May 19 11:55:10 2023 rev:30 rq:1085995 version:2.17.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-google-auth/python-google-auth.changes 2023-04-22 22:01:37.393633563 +0200 +++ /work/SRC/openSUSE:Factory/.python-google-auth.new.1533/python-google-auth.changes 2023-05-19 11:55:35.723288578 +0200 @@ -1,0 +2,28 @@ +Wed May 10 07:14:23 UTC 2023 - Daniel Garcia <[email protected]> + +- Add urllib3-2.patch to support newer urllib3 -- gh#googleapis/google-auth-library-python#1290 +- Remove no-python3.patch +- Update to 2.17.3: + * Add useEmailAzp claim for id token iam flow (#1270) (7a9c6f2) +- 2.17.2: + * Do not create new JWT credentials if they make the same claims as + the existing. (#1267) (eebb7b6) +- 2.17.1: + * Print out reauth plugin error and raise if challenge output is + None (#1265) (08d22fe) +- 2.17.0: + * Experimental service account iam endpoint flow for id token + (#1258) (8ff0de5) + * Python: Remove aws url validation (#1254) (20a966b) +- 2.16.3: + * Read both applicationId and relyingPartyId. (#1246) (e125dfe) +- 2.16.2: + * Call gcloud config get project to get project for user cred + (#1243) (c078a13) + * Do not use hardcoded string 'python', when you mean + sys.executable. (#1233) (91ac8e6) + * Don't retry if error or error_description is not string (#1241) + (e2d263a) + * Improve ADC related errors and warnings (#1237) (2dfa213) + +------------------------------------------------------------------- Old: ---- google-auth-2.16.1.tar.gz no-python3.patch New: ---- google-auth-2.17.3.tar.gz urllib3-2.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-google-auth.spec ++++++ --- /var/tmp/diff_new_pack.7jCUMD/_old 2023-05-19 11:55:36.339292103 +0200 +++ /var/tmp/diff_new_pack.7jCUMD/_new 2023-05-19 11:55:36.347292149 +0200 @@ -19,7 +19,7 @@ %define skip_python2 1 %{?sle15_python_module_pythons} Name: python-google-auth -Version: 2.16.1 +Version: 2.17.3 Release: 0 Summary: Google Authentication Library License: Apache-2.0 @@ -27,9 +27,8 @@ Source: https://files.pythonhosted.org/packages/source/g/google-auth/google-auth-%{version}.tar.gz # https://github.com/googleapis/google-auth-library-python/issues/1055 Patch1: python-google-auth-no-mock.patch -# PATCH-FIX-UPSTREAM no-python3.patch gh#googleapis/google-auth-library-python!1233 [email protected] -# don't use 'python3' literal when you mean sys.executable -Patch2: no-python3.patch +# PATCH-FIX-OPENSUSE urllib3-2.patch -- gh#googleapis/google-auth-library-python#1290 +Patch2: urllib3-2.patch BuildRequires: %{python_module Flask} # START TESTING SECTION BuildRequires: %{python_module aiohttp >= 3.6.2} ++++++ google-auth-2.16.1.tar.gz -> google-auth-2.17.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/PKG-INFO new/google-auth-2.17.3/PKG-INFO --- old/google-auth-2.16.1/PKG-INFO 2023-02-17 21:43:54.041481700 +0100 +++ new/google-auth-2.17.3/PKG-INFO 2023-04-13 00:31:34.129980000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: google-auth -Version: 2.16.1 +Version: 2.17.3 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.16.1/google/auth/_cloud_sdk.py new/google-auth-2.17.3/google/auth/_cloud_sdk.py --- old/google-auth-2.16.1/google/auth/_cloud_sdk.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/google/auth/_cloud_sdk.py 2023-04-13 00:29:01.000000000 +0200 @@ -14,12 +14,12 @@ """Helpers for reading the Google Cloud SDK's configuration.""" -import json import os import subprocess import six +from google.auth import _helpers from google.auth import environment_vars from google.auth import exceptions @@ -35,7 +35,7 @@ _CLOUD_SDK_POSIX_COMMAND = "gcloud" _CLOUD_SDK_WINDOWS_COMMAND = "gcloud.cmd" # The command to get the Cloud SDK configuration -_CLOUD_SDK_CONFIG_COMMAND = ("config", "config-helper", "--format", "json") +_CLOUD_SDK_CONFIG_GET_PROJECT_COMMAND = ("config", "get", "project") # The command to get google user access token _CLOUD_SDK_USER_ACCESS_TOKEN_COMMAND = ("auth", "print-access-token") # Cloud SDK's application-default client ID @@ -105,20 +105,16 @@ try: # Ignore the stderr coming from gcloud, so it won't be mixed into the output. # https://github.com/googleapis/google-auth-library-python/issues/673 - output = _run_subprocess_ignore_stderr((command,) + _CLOUD_SDK_CONFIG_COMMAND) + project = _run_subprocess_ignore_stderr( + (command,) + _CLOUD_SDK_CONFIG_GET_PROJECT_COMMAND + ) + + # Turn bytes into a string and remove "\n" + project = _helpers.from_bytes(project).strip() + return project if project else None except (subprocess.CalledProcessError, OSError, IOError): return None - try: - configuration = json.loads(output.decode("utf-8")) - except ValueError: - return None - - try: - return configuration["configuration"]["properties"]["core"]["project"] - except KeyError: - return None - def get_auth_access_token(account=None): """Load user access token with the ``gcloud auth print-access-token`` command. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/google/auth/_default.py new/google-auth-2.17.3/google/auth/_default.py --- old/google-auth-2.16.1/google/auth/_default.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/google/auth/_default.py 2023-04-13 00:29:01.000000000 +0200 @@ -48,23 +48,18 @@ ) # Help message when no credentials can be found. -_HELP_MESSAGE = """\ -Could not automatically determine credentials. Please set {env} or \ -explicitly create credentials and re-run the application. For more \ -information, please see \ -https://cloud.google.com/docs/authentication/getting-started -""".format( - env=environment_vars.CREDENTIALS -).strip() +_CLOUD_SDK_MISSING_CREDENTIALS = """\ +Your default credentials were not found. To set up Application Default Credentials, \ +see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.\ +""" # Warning when using Cloud SDK user credentials _CLOUD_SDK_CREDENTIALS_WARNING = """\ Your application has authenticated using end user credentials from Google \ Cloud SDK without a quota project. You might receive a "quota exceeded" \ -or "API not enabled" error. We recommend you rerun \ -`gcloud auth application-default login` and make sure a quota project is \ -added. Or you can use service accounts instead. For more information \ -about service accounts, see https://cloud.google.com/docs/authentication/""" +or "API not enabled" error. See the following page for troubleshooting: \ +https://cloud.google.com/docs/authentication/adc-troubleshooting/user-creds. \ +""" # The subject token type used for AWS external_account credentials. _AWS_SUBJECT_TOKEN_TYPE = "urn:ietf:params:aws:token-type:aws4_request" @@ -650,4 +645,4 @@ ) return credentials, effective_project_id - raise exceptions.DefaultCredentialsError(_HELP_MESSAGE) + raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/google/auth/_default_async.py new/google-auth-2.17.3/google/auth/_default_async.py --- old/google-auth-2.16.1/google/auth/_default_async.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/google/auth/_default_async.py 2023-04-13 00:29:01.000000000 +0200 @@ -281,4 +281,4 @@ ) return credentials, effective_project_id - raise exceptions.DefaultCredentialsError(_default._HELP_MESSAGE) + raise exceptions.DefaultCredentialsError(_default._CLOUD_SDK_MISSING_CREDENTIALS) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/google/auth/aws.py new/google-auth-2.17.3/google/auth/aws.py --- old/google-auth-2.16.1/google/auth/aws.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/google/auth/aws.py 2023-04-13 00:29:01.000000000 +0200 @@ -47,7 +47,6 @@ from six.moves import http_client from six.moves import urllib from six.moves.urllib.parse import urljoin -from six.moves.urllib.parse import urlparse from google.auth import _helpers from google.auth import environment_vars @@ -398,8 +397,6 @@ self._request_signer = None self._target_resource = audience - self.validate_metadata_server_urls() - # Get the environment ID. Currently, only one version supported (v1). matches = re.match(r"^(aws)([\d]+)$", self._environment_id) if matches: @@ -418,22 +415,6 @@ ) ) - def validate_metadata_server_urls(self): - self.validate_metadata_server_url_if_any(self._region_url, "region_url") - self.validate_metadata_server_url_if_any(self._security_credentials_url, "url") - self.validate_metadata_server_url_if_any( - self._imdsv2_session_token_url, "imdsv2_session_token_url" - ) - - @staticmethod - def validate_metadata_server_url_if_any(url_string, name_of_data): - if url_string: - url = urlparse(url_string) - if url.hostname != "169.254.169.254" and url.hostname != "fd00:ec2::254": - raise exceptions.InvalidResource( - "Invalid hostname '{}' for '{}'".format(url.hostname, name_of_data) - ) - def retrieve_subject_token(self, request): """Retrieves the subject token using the credential_source object. The subject token is a serialized `AWS GetCallerIdentity signed request`_. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/google/auth/jwt.py new/google-auth-2.17.3/google/auth/jwt.py --- old/google-auth-2.16.1/google/auth/jwt.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/google/auth/jwt.py 2023-04-13 00:29:01.000000000 +0200 @@ -590,6 +590,11 @@ def signer(self): return self._signer + @property # type: ignore + def additional_claims(self): + """ Additional claims the JWT object was created with.""" + return self._additional_claims + class OnDemandCredentials( google.auth.credentials.Signing, google.auth.credentials.CredentialsWithQuotaProject diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/google/auth/version.py new/google-auth-2.17.3/google/auth/version.py --- old/google-auth-2.16.1/google/auth/version.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/google/auth/version.py 2023-04-13 00:29:01.000000000 +0200 @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "2.16.1" +__version__ = "2.17.3" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/google/oauth2/_client.py new/google-auth-2.17.3/google/oauth2/_client.py --- old/google-auth-2.16.1/google/oauth2/_client.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/google/oauth2/_client.py 2023-04-13 00:29:01.000000000 +0200 @@ -40,6 +40,10 @@ _JSON_CONTENT_TYPE = "application/json" _JWT_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer" _REFRESH_GRANT_TYPE = "refresh_token" +_IAM_IDTOKEN_ENDPOINT = ( + "https://iamcredentials.googleapis.com/v1/" + + "projects/-/serviceAccounts/{}:generateIdToken" +) def _handle_error_response(response_data, retryable_error): @@ -90,6 +94,11 @@ error_desc = response_data.get("error_description") or "" error_code = response_data.get("error") or "" + if not isinstance(error_code, six.string_types) or not isinstance( + error_desc, six.string_types + ): + return False + # Per Oauth 2.0 RFC https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.2.1 # This is needed because a redirect will not return a 500 status code. retryable_error_descriptions = { @@ -308,6 +317,44 @@ return access_token, expiry, response_data +def call_iam_generate_id_token_endpoint(request, signer_email, audience, access_token): + """Call iam.generateIdToken endpoint to get ID token. + + Args: + request (google.auth.transport.Request): A callable used to make + HTTP requests. + signer_email (str): The signer email used to form the IAM + generateIdToken endpoint. + audience (str): The audience for the ID token. + access_token (str): The access token used to call the IAM endpoint. + + Returns: + Tuple[str, datetime]: The ID token and expiration. + """ + body = {"audience": audience, "includeEmail": "true", "useEmailAzp": "true"} + + response_data = _token_endpoint_request( + request, + _IAM_IDTOKEN_ENDPOINT.format(signer_email), + body, + access_token=access_token, + use_json=True, + ) + + try: + id_token = response_data["token"] + except KeyError as caught_exc: + new_exc = exceptions.RefreshError( + "No ID token in response.", response_data, retryable=False + ) + six.raise_from(new_exc, caught_exc) + + payload = jwt.decode(id_token, verify=False) + expiry = datetime.datetime.utcfromtimestamp(payload["exp"]) + + return id_token, expiry + + def id_token_jwt_grant(request, token_uri, assertion, can_retry=True): """Implements the JWT Profile for OAuth 2.0 Authorization Grants, but requests an OpenID Connect ID Token instead of an access token. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/google/oauth2/challenges.py new/google-auth-2.17.3/google/oauth2/challenges.py --- old/google-auth-2.16.1/google/oauth2/challenges.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/google/oauth2/challenges.py 2023-04-13 00:29:01.000000000 +0200 @@ -124,7 +124,16 @@ ) sk = metadata["securityKey"] challenges = sk["challenges"] - app_id = sk["applicationId"] + # Read both 'applicationId' and 'relyingPartyId', if they are the same, use + # applicationId, if they are different, use relyingPartyId first and retry + # with applicationId + application_id = sk["applicationId"] + relying_party_id = sk["relyingPartyId"] + + if application_id != relying_party_id: + application_parameters = [relying_party_id, application_id] + else: + application_parameters = [application_id] challenge_data = [] for c in challenges: @@ -134,24 +143,38 @@ challenge = base64.urlsafe_b64decode(challenge) challenge_data.append({"key": key, "challenge": challenge}) - try: - api = pyu2f.convenience.authenticator.CreateCompositeAuthenticator( - REAUTH_ORIGIN - ) - response = api.Authenticate( - app_id, challenge_data, print_callback=sys.stderr.write - ) - return {"securityKey": response} - except pyu2f.errors.U2FError as e: - if e.code == pyu2f.errors.U2FError.DEVICE_INELIGIBLE: - sys.stderr.write("Ineligible security key.\n") - elif e.code == pyu2f.errors.U2FError.TIMEOUT: - sys.stderr.write("Timed out while waiting for security key touch.\n") - else: - raise e - except pyu2f.errors.NoDeviceFoundError: - sys.stderr.write("No security key found.\n") - return None + # Track number of tries to suppress error message until all application_parameters + # are tried. + tries = 0 + for app_id in application_parameters: + try: + tries += 1 + api = pyu2f.convenience.authenticator.CreateCompositeAuthenticator( + REAUTH_ORIGIN + ) + response = api.Authenticate( + app_id, challenge_data, print_callback=sys.stderr.write + ) + return {"securityKey": response} + except pyu2f.errors.U2FError as e: + if e.code == pyu2f.errors.U2FError.DEVICE_INELIGIBLE: + # Only show error if all app_ids have been tried + if tries == len(application_parameters): + sys.stderr.write("Ineligible security key.\n") + return None + continue + if e.code == pyu2f.errors.U2FError.TIMEOUT: + sys.stderr.write( + "Timed out while waiting for security key touch.\n" + ) + else: + raise e + except pyu2f.errors.PluginError as e: + sys.stderr.write("Plugin error: {}.\n".format(e)) + continue + except pyu2f.errors.NoDeviceFoundError: + sys.stderr.write("No security key found.\n") + return None class SamlChallenge(ReauthChallenge): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/google/oauth2/reauth.py new/google-auth-2.17.3/google/oauth2/reauth.py --- old/google-auth-2.16.1/google/oauth2/reauth.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/google/oauth2/reauth.py 2023-04-13 00:29:01.000000000 +0200 @@ -225,6 +225,8 @@ msg = _run_next_challenge(msg, request, access_token) + if not msg: + raise exceptions.ReauthFailError("Failed to obtain rapt token.") if msg["status"] == _AUTHENTICATED: return msg["encodedProofOfReauthToken"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/google/oauth2/service_account.py new/google-auth-2.17.3/google/oauth2/service_account.py --- old/google-auth-2.16.1/google/oauth2/service_account.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/google/oauth2/service_account.py 2023-04-13 00:29:01.000000000 +0200 @@ -441,19 +441,32 @@ # https://google.aip.dev/auth/4111 if self._always_use_jwt_access: if self._scopes: - self._jwt_credentials = jwt.Credentials.from_signing_credentials( - self, None, additional_claims={"scope": " ".join(self._scopes)} - ) + additional_claims = {"scope": " ".join(self._scopes)} + if ( + self._jwt_credentials is None + or self._jwt_credentials.additional_claims != additional_claims + ): + self._jwt_credentials = jwt.Credentials.from_signing_credentials( + self, None, additional_claims=additional_claims + ) elif audience: - self._jwt_credentials = jwt.Credentials.from_signing_credentials( - self, audience - ) + if ( + self._jwt_credentials is None + or self._jwt_credentials._audience != audience + ): + + self._jwt_credentials = jwt.Credentials.from_signing_credentials( + self, audience + ) elif self._default_scopes: - self._jwt_credentials = jwt.Credentials.from_signing_credentials( - self, - None, - additional_claims={"scope": " ".join(self._default_scopes)}, - ) + additional_claims = {"scope": " ".join(self._default_scopes)} + if ( + self._jwt_credentials is None + or additional_claims != self._jwt_credentials.additional_claims + ): + self._jwt_credentials = jwt.Credentials.from_signing_credentials( + self, None, additional_claims=additional_claims + ) elif not self._scopes and audience: self._jwt_credentials = jwt.Credentials.from_signing_credentials( self, audience @@ -554,6 +567,7 @@ self._token_uri = token_uri self._target_audience = target_audience self._quota_project_id = quota_project_id + self._use_iam_endpoint = False if additional_claims is not None: self._additional_claims = additional_claims @@ -639,6 +653,31 @@ quota_project_id=self.quota_project_id, ) + def _with_use_iam_endpoint(self, use_iam_endpoint): + """Create a copy of these credentials with the use_iam_endpoint value. + + Args: + use_iam_endpoint (bool): If True, IAM generateIdToken endpoint will + be used instead of the token_uri. Note that + iam.serviceAccountTokenCreator role is required to use the IAM + endpoint. The default value is False. This feature is currently + experimental and subject to change without notice. + + Returns: + google.auth.service_account.IDTokenCredentials: A new credentials + instance. + """ + cred = self.__class__( + self._signer, + service_account_email=self._service_account_email, + token_uri=self._token_uri, + target_audience=self._target_audience, + additional_claims=self._additional_claims.copy(), + quota_project_id=self.quota_project_id, + ) + cred._use_iam_endpoint = use_iam_endpoint + return cred + @_helpers.copy_docstring(credentials.CredentialsWithQuotaProject) def with_quota_project(self, quota_project_id): return self.__class__( @@ -692,14 +731,49 @@ return token + def _refresh_with_iam_endpoint(self, request): + """Use IAM generateIdToken endpoint to obtain an ID token. + + It works as follows: + + 1. First we create a self signed jwt with + https://www.googleapis.com/auth/iam being the scope. + + 2. Next we use the self signed jwt as the access token, and make a POST + request to IAM generateIdToken endpoint. The request body is: + { + "audience": self._target_audience, + "includeEmail": "true", + "useEmailAzp": "true", + } + + If the request is succesfully, it will return {"token":"the ID token"}, + and we can extract the ID token and compute its expiry. + """ + jwt_credentials = jwt.Credentials.from_signing_credentials( + self, + None, + additional_claims={"scope": "https://www.googleapis.com/auth/iam"}, + ) + jwt_credentials.refresh(request) + self.token, self.expiry = _client.call_iam_generate_id_token_endpoint( + request, + self.signer_email, + self._target_audience, + jwt_credentials.token.decode(), + ) + @_helpers.copy_docstring(credentials.Credentials) def refresh(self, request): - assertion = self._make_authorization_grant_assertion() - access_token, expiry, _ = _client.id_token_jwt_grant( - request, self._token_uri, assertion - ) - self.token = access_token - self.expiry = expiry + if self._use_iam_endpoint: + self._refresh_with_iam_endpoint(request) + else: + assertion = self._make_authorization_grant_assertion() + access_token, expiry, _ = _client.id_token_jwt_grant( + request, self._token_uri, assertion + ) + self.token = access_token + self.expiry = expiry @property def service_account_email(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/google_auth.egg-info/PKG-INFO new/google-auth-2.17.3/google_auth.egg-info/PKG-INFO --- old/google-auth-2.16.1/google_auth.egg-info/PKG-INFO 2023-02-17 21:43:53.000000000 +0100 +++ new/google-auth-2.17.3/google_auth.egg-info/PKG-INFO 2023-04-13 00:31:34.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: google-auth -Version: 2.16.1 +Version: 2.17.3 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.16.1/google_auth.egg-info/SOURCES.txt new/google-auth-2.17.3/google_auth.egg-info/SOURCES.txt --- old/google-auth-2.16.1/google_auth.egg-info/SOURCES.txt 2023-02-17 21:43:53.000000000 +0100 +++ new/google-auth-2.17.3/google_auth.egg-info/SOURCES.txt 2023-04-13 00:31:34.000000000 +0200 @@ -103,7 +103,6 @@ tests/data/authorized_user_cloud_sdk_with_quota_project_id.json tests/data/authorized_user_with_rapt_token.json tests/data/client_secrets.json -tests/data/cloud_sdk_config.json tests/data/context_aware_metadata.json tests/data/enterprise_cert_invalid.json tests/data/enterprise_cert_valid.json diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/tests/data/cloud_sdk_config.json new/google-auth-2.17.3/tests/data/cloud_sdk_config.json --- old/google-auth-2.16.1/tests/data/cloud_sdk_config.json 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/tests/data/cloud_sdk_config.json 1970-01-01 01:00:00.000000000 +0100 @@ -1,19 +0,0 @@ -{ - "configuration": { - "active_configuration": "default", - "properties": { - "core": { - "account": "[email protected]", - "disable_usage_reporting": "False", - "project": "example-project" - } - } - }, - "credential": { - "access_token": "don't use me", - "token_expiry": "2017-03-23T23:09:49Z" - }, - "sentinels": { - "config_sentinel": "/Users/example/.config/gcloud/config_sentinel" - } -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/tests/oauth2/test__client.py new/google-auth-2.17.3/tests/oauth2/test__client.py --- old/google-auth-2.16.1/tests/oauth2/test__client.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/tests/oauth2/test__client.py 2023-04-13 00:29:01.000000000 +0200 @@ -94,7 +94,14 @@ assert _client._can_retry(http_client.OK, response_data) [email protected]("response_data", [{"error": "invalid_scope"}]) [email protected]( + "response_data", + [ + {"error": "invalid_scope"}, + {"error": {"foo": "bar"}}, + {"error_description": {"foo", "bar"}}, + ], +) def test__can_retry_no_retry_message(response_data): assert not _client._can_retry(http_client.OK, response_data) @@ -298,6 +305,51 @@ assert not excinfo.value.retryable +def test_call_iam_generate_id_token_endpoint(): + now = _helpers.utcnow() + id_token_expiry = _helpers.datetime_to_secs(now) + id_token = jwt.encode(SIGNER, {"exp": id_token_expiry}).decode("utf-8") + request = make_request({"token": id_token}) + + token, expiry = _client.call_iam_generate_id_token_endpoint( + request, "fake_email", "fake_audience", "fake_access_token" + ) + + assert ( + request.call_args[1]["url"] + == "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/fake_email:generateIdToken" + ) + assert request.call_args[1]["headers"]["Content-Type"] == "application/json" + assert ( + request.call_args[1]["headers"]["Authorization"] == "Bearer fake_access_token" + ) + response_body = json.loads(request.call_args[1]["body"]) + assert response_body["audience"] == "fake_audience" + assert response_body["includeEmail"] == "true" + assert response_body["useEmailAzp"] == "true" + + # Check result + assert token == id_token + # JWT does not store microseconds + now = now.replace(microsecond=0) + assert expiry == now + + +def test_call_iam_generate_id_token_endpoint_no_id_token(): + request = make_request( + { + # No access token. + "error": "no token" + } + ) + + with pytest.raises(exceptions.RefreshError) as excinfo: + _client.call_iam_generate_id_token_endpoint( + request, "fake_email", "fake_audience", "fake_access_token" + ) + assert excinfo.match("No ID token in response") + + def test_id_token_jwt_grant(): now = _helpers.utcnow() id_token_expiry = _helpers.datetime_to_secs(now) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/tests/oauth2/test_challenges.py new/google-auth-2.17.3/tests/oauth2/test_challenges.py --- old/google-auth-2.16.1/tests/oauth2/test_challenges.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/tests/oauth2/test_challenges.py 2023-04-13 00:29:01.000000000 +0200 @@ -45,13 +45,15 @@ ).decode("ascii"), } ], + "relyingPartyId": "security_key_application_id", }, } mock_key = mock.Mock() challenge = challenges.SecurityKeyChallenge() - # Test the case that security key challenge is passed. + # Test the case that security key challenge is passed with applicationId and + # relyingPartyId the same. with mock.patch("pyu2f.model.RegisteredKey", return_value=mock_key): with mock.patch( "pyu2f.convenience.authenticator.CompositeAuthenticator.Authenticate" @@ -68,6 +70,56 @@ print_callback=sys.stderr.write, ) + # Test the case that security key challenge is passed with applicationId and + # relyingPartyId different, first call works. + metadata["securityKey"]["relyingPartyId"] = "security_key_relying_party_id" + sys.stderr.write("metadata=" + str(metadata) + "\n") + with mock.patch("pyu2f.model.RegisteredKey", return_value=mock_key): + with mock.patch( + "pyu2f.convenience.authenticator.CompositeAuthenticator.Authenticate" + ) as mock_authenticate: + mock_authenticate.return_value = "security key response" + assert challenge.name == "SECURITY_KEY" + assert challenge.is_locally_eligible + assert challenge.obtain_challenge_input(metadata) == { + "securityKey": "security key response" + } + mock_authenticate.assert_called_with( + "security_key_relying_party_id", + [{"key": mock_key, "challenge": b"some_challenge"}], + print_callback=sys.stderr.write, + ) + + # Test the case that security key challenge is passed with applicationId and + # relyingPartyId different, first call fails, requires retry. + metadata["securityKey"]["relyingPartyId"] = "security_key_relying_party_id" + with mock.patch("pyu2f.model.RegisteredKey", return_value=mock_key): + with mock.patch( + "pyu2f.convenience.authenticator.CompositeAuthenticator.Authenticate" + ) as mock_authenticate: + assert challenge.name == "SECURITY_KEY" + assert challenge.is_locally_eligible + mock_authenticate.side_effect = [ + pyu2f.errors.U2FError(pyu2f.errors.U2FError.DEVICE_INELIGIBLE), + "security key response", + ] + assert challenge.obtain_challenge_input(metadata) == { + "securityKey": "security key response" + } + calls = [ + mock.call( + "security_key_relying_party_id", + [{"key": mock_key, "challenge": b"some_challenge"}], + print_callback=sys.stderr.write, + ), + mock.call( + "security_key_application_id", + [{"key": mock_key, "challenge": b"some_challenge"}], + print_callback=sys.stderr.write, + ), + ] + mock_authenticate.assert_has_calls(calls) + # Test various types of exceptions. with mock.patch("pyu2f.model.RegisteredKey", return_value=mock_key): with mock.patch( @@ -87,6 +139,12 @@ assert challenge.obtain_challenge_input(metadata) is None with mock.patch( + "pyu2f.convenience.authenticator.CompositeAuthenticator.Authenticate" + ) as mock_authenticate: + mock_authenticate.side_effect = pyu2f.errors.PluginError() + assert challenge.obtain_challenge_input(metadata) is None + + with mock.patch( "pyu2f.convenience.authenticator.CompositeAuthenticator.Authenticate" ) as mock_authenticate: mock_authenticate.side_effect = pyu2f.errors.U2FError( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/tests/oauth2/test_reauth.py new/google-auth-2.17.3/tests/oauth2/test_reauth.py --- old/google-auth-2.16.1/tests/oauth2/test_reauth.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/tests/oauth2/test_reauth.py 2023-04-13 00:29:01.000000000 +0200 @@ -204,6 +204,20 @@ assert excinfo.match(r"API error: STATUS_UNSPECIFIED") +def test__obtain_rapt_no_challenge_output(): + challenges_response = copy.deepcopy(CHALLENGES_RESPONSE_TEMPLATE) + with mock.patch( + "google.oauth2.reauth._get_challenges", return_value=challenges_response + ): + with mock.patch("google.oauth2.reauth.is_interactive", return_value=True): + with mock.patch( + "google.oauth2.reauth._run_next_challenge", return_value=None + ): + with pytest.raises(exceptions.ReauthFailError) as excinfo: + reauth._obtain_rapt(MOCK_REQUEST, "token", None) + assert excinfo.match(r"Failed to obtain rapt token") + + def test__obtain_rapt_not_interactive(): with mock.patch( "google.oauth2.reauth._get_challenges", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/tests/oauth2/test_service_account.py new/google-auth-2.17.3/tests/oauth2/test_service_account.py --- old/google-auth-2.16.1/tests/oauth2/test_service_account.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/tests/oauth2/test_service_account.py 2023-04-13 00:29:01.000000000 +0200 @@ -254,6 +254,24 @@ jwt.from_signing_credentials.assert_called_once_with(credentials, audience) @mock.patch("google.auth.jwt.Credentials", instance=True, autospec=True) + def test__create_self_signed_jwt_always_use_jwt_access_with_audience_similar_jwt_is_reused( + self, jwt + ): + credentials = service_account.Credentials( + SIGNER, + self.SERVICE_ACCOUNT_EMAIL, + self.TOKEN_URI, + default_scopes=["bar", "foo"], + always_use_jwt_access=True, + ) + + audience = "https://pubsub.googleapis.com" + credentials._create_self_signed_jwt(audience) + credentials._jwt_credentials._audience = audience + credentials._create_self_signed_jwt(audience) + jwt.from_signing_credentials.assert_called_once_with(credentials, audience) + + @mock.patch("google.auth.jwt.Credentials", instance=True, autospec=True) def test__create_self_signed_jwt_always_use_jwt_access_with_scopes(self, jwt): credentials = service_account.Credentials( SIGNER, @@ -270,6 +288,26 @@ ) @mock.patch("google.auth.jwt.Credentials", instance=True, autospec=True) + def test__create_self_signed_jwt_always_use_jwt_access_with_scopes_similar_jwt_is_reused( + self, jwt + ): + credentials = service_account.Credentials( + SIGNER, + self.SERVICE_ACCOUNT_EMAIL, + self.TOKEN_URI, + scopes=["bar", "foo"], + always_use_jwt_access=True, + ) + + audience = "https://pubsub.googleapis.com" + credentials._create_self_signed_jwt(audience) + credentials._jwt_credentials.additional_claims = {"scope": "bar foo"} + credentials._create_self_signed_jwt(audience) + jwt.from_signing_credentials.assert_called_once_with( + credentials, None, additional_claims={"scope": "bar foo"} + ) + + @mock.patch("google.auth.jwt.Credentials", instance=True, autospec=True) def test__create_self_signed_jwt_always_use_jwt_access_with_default_scopes( self, jwt ): @@ -287,6 +325,25 @@ ) @mock.patch("google.auth.jwt.Credentials", instance=True, autospec=True) + def test__create_self_signed_jwt_always_use_jwt_access_with_default_scopes_similar_jwt_is_reused( + self, jwt + ): + credentials = service_account.Credentials( + SIGNER, + self.SERVICE_ACCOUNT_EMAIL, + self.TOKEN_URI, + default_scopes=["bar", "foo"], + always_use_jwt_access=True, + ) + + credentials._create_self_signed_jwt(None) + credentials._jwt_credentials.additional_claims = {"scope": "bar foo"} + credentials._create_self_signed_jwt(None) + jwt.from_signing_credentials.assert_called_once_with( + credentials, None, additional_claims={"scope": "bar foo"} + ) + + @mock.patch("google.auth.jwt.Credentials", instance=True, autospec=True) def test__create_self_signed_jwt_always_use_jwt_access(self, jwt): credentials = service_account.Credentials( SIGNER, @@ -428,6 +485,7 @@ assert credentials.service_account_email == SERVICE_ACCOUNT_INFO["client_email"] assert credentials._token_uri == SERVICE_ACCOUNT_INFO["token_uri"] assert credentials._target_audience == self.TARGET_AUDIENCE + assert not credentials._use_iam_endpoint def test_from_service_account_file(self): info = SERVICE_ACCOUNT_INFO.copy() @@ -440,6 +498,7 @@ assert credentials._signer.key_id == info["private_key_id"] assert credentials._token_uri == info["token_uri"] assert credentials._target_audience == self.TARGET_AUDIENCE + assert not credentials._use_iam_endpoint def test_default_state(self): credentials = self.make_credentials() @@ -466,6 +525,11 @@ new_credentials = credentials.with_target_audience("https://new.example.com") assert new_credentials._target_audience == "https://new.example.com" + def test__with_use_iam_endpoint(self): + credentials = self.make_credentials() + new_credentials = credentials._with_use_iam_endpoint(True) + assert new_credentials._use_iam_endpoint + def test_with_quota_project(self): credentials = self.make_credentials() new_credentials = credentials.with_quota_project("project-foo") @@ -517,6 +581,28 @@ # expired) assert credentials.valid + @mock.patch( + "google.oauth2._client.call_iam_generate_id_token_endpoint", autospec=True + ) + def test_refresh_iam_flow(self, call_iam_generate_id_token_endpoint): + credentials = self.make_credentials() + credentials._use_iam_endpoint = True + token = "id_token" + call_iam_generate_id_token_endpoint.return_value = ( + token, + _helpers.utcnow() + datetime.timedelta(seconds=500), + ) + request = mock.Mock() + credentials.refresh(request) + req, signer_email, target_audience, access_token = call_iam_generate_id_token_endpoint.call_args[ + 0 + ] + assert req == request + assert signer_email == "[email protected]" + assert target_audience == "https://example.com" + decoded_access_token = jwt.decode(access_token, verify=False) + assert decoded_access_token["scope"] == "https://www.googleapis.com/auth/iam" + @mock.patch("google.oauth2._client.id_token_jwt_grant", autospec=True) def test_before_request_refreshes(self, id_token_jwt_grant): credentials = self.make_credentials() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/tests/test__cloud_sdk.py new/google-auth-2.17.3/tests/test__cloud_sdk.py --- old/google-auth-2.16.1/tests/test__cloud_sdk.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/tests/test__cloud_sdk.py 2023-04-13 00:29:01.000000000 +0200 @@ -16,6 +16,7 @@ import json import os import subprocess +import sys import mock import pytest # type: ignore @@ -36,17 +37,10 @@ with io.open(SERVICE_ACCOUNT_FILE, "rb") as fh: SERVICE_ACCOUNT_FILE_DATA = json.load(fh) -with io.open(os.path.join(DATA_DIR, "cloud_sdk_config.json"), "rb") as fh: - CLOUD_SDK_CONFIG_FILE_DATA = fh.read() - @pytest.mark.parametrize( "data, expected_project_id", - [ - (CLOUD_SDK_CONFIG_FILE_DATA, "example-project"), - (b"I am some bad json", None), - (b"{}", None), - ], + [(b"example-project\n", "example-project"), (b"", None)], ) def test_get_project_id(data, expected_project_id): check_output_patch = mock.patch( @@ -73,7 +67,7 @@ def test__run_subprocess_ignore_stderr(): command = [ - "python", + sys.executable, "-c", "from __future__ import print_function;" + "import sys;" @@ -93,9 +87,7 @@ @mock.patch("os.name", new="nt") def test_get_project_id_windows(): check_output_patch = mock.patch( - "subprocess.check_output", - autospec=True, - return_value=CLOUD_SDK_CONFIG_FILE_DATA, + "subprocess.check_output", autospec=True, return_value=b"example-project\n" ) with check_output_patch as check_output: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/tests/test__default.py new/google-auth-2.17.3/tests/test__default.py --- old/google-auth-2.16.1/tests/test__default.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/tests/test__default.py 2023-04-13 00:29:01.000000000 +0200 @@ -916,9 +916,11 @@ autospec=True, ) def test_default_fail(unused_gce, unused_gae, unused_sdk, unused_explicit): - with pytest.raises(exceptions.DefaultCredentialsError): + with pytest.raises(exceptions.DefaultCredentialsError) as excinfo: assert _default.default() + assert excinfo.match(_default._CLOUD_SDK_MISSING_CREDENTIALS) + @mock.patch( "google.auth._default._get_explicit_environ_credentials", @@ -1128,7 +1130,7 @@ def test_default_warning_without_quota_project_id_for_user_creds(get_adc_path): get_adc_path.return_value = AUTHORIZED_USER_CLOUD_SDK_FILE - with pytest.warns(UserWarning, match="Cloud SDK"): + with pytest.warns(UserWarning, match=_default._CLOUD_SDK_CREDENTIALS_WARNING): credentials, project_id = _default.default(quota_project_id=None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/tests/test_aws.py new/google-auth-2.17.3/tests/test_aws.py --- old/google-auth-2.16.1/tests/test_aws.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/tests/test_aws.py 2023-04-13 00:29:01.000000000 +0200 @@ -1495,39 +1495,6 @@ credentials.retrieve_subject_token(request) assert not request.called - def test_validate_metadata_server_url_if_any(self): - aws.Credentials.validate_metadata_server_url_if_any( - "http://[fd00:ec2::254]/latest/meta-data/placement/availability-zone", "url" - ) - aws.Credentials.validate_metadata_server_url_if_any( - "http://169.254.169.254/latest/meta-data/placement/availability-zone", "url" - ) - - with pytest.raises(ValueError) as excinfo: - aws.Credentials.validate_metadata_server_url_if_any( - "http://fd00:ec2::254/latest/meta-data/placement/availability-zone", - "url", - ) - assert excinfo.match("Invalid hostname 'fd00' for 'url'") - - with pytest.raises(ValueError) as excinfo: - aws.Credentials.validate_metadata_server_url_if_any( - "http://abc.com/latest/meta-data/placement/availability-zone", "url" - ) - assert excinfo.match("Invalid hostname 'abc.com' for 'url'") - - def test_retrieve_subject_token_invalid_hosts(self): - keys = ["url", "region_url", "imdsv2_session_token_url"] - for key in keys: - credential_source = self.CREDENTIAL_SOURCE.copy() - credential_source[ - key - ] = "http://abc.com/latest/meta-data/iam/security-credentials" - - with pytest.raises(ValueError) as excinfo: - self.make_credentials(credential_source=credential_source) - assert excinfo.match("Invalid hostname 'abc.com' for '{}'".format(key)) - @mock.patch("google.auth._helpers.utcnow") def test_retrieve_subject_token_success_ipv6(self, utcnow): utcnow.return_value = datetime.datetime.strptime( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/tests/test_jwt.py new/google-auth-2.17.3/tests/test_jwt.py --- old/google-auth-2.16.1/tests/test_jwt.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/tests/test_jwt.py 2023-04-13 00:29:01.000000000 +0200 @@ -464,6 +464,7 @@ assert new_credentials._subject == self.credentials._subject assert new_credentials._audience == self.credentials._audience assert new_credentials._additional_claims == self.credentials._additional_claims + assert new_credentials.additional_claims == self.credentials._additional_claims assert new_credentials._quota_project_id == quota_project_id def test_sign_bytes(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-2.16.1/tests/transport/test_urllib3.py new/google-auth-2.17.3/tests/transport/test_urllib3.py --- old/google-auth-2.16.1/tests/transport/test_urllib3.py 2023-02-17 21:41:23.000000000 +0100 +++ new/google-auth-2.17.3/tests/transport/test_urllib3.py 2023-04-13 00:29:01.000000000 +0200 @@ -82,6 +82,9 @@ self.requests.append((method, url, body, headers, kwargs)) return self.responses.pop(0) + def clear(self): + pass + class ResponseStub(object): def __init__(self, status=http_client.OK, data=None): ++++++ python-google-auth-no-mock.patch ++++++ --- /var/tmp/diff_new_pack.7jCUMD/_old 2023-05-19 11:55:36.499293019 +0200 +++ /var/tmp/diff_new_pack.7jCUMD/_new 2023-05-19 11:55:36.503293042 +0200 @@ -33,8 +33,10 @@ tests/transport/test_urllib3.py | 2 +- 32 files changed, 32 insertions(+), 32 deletions(-) ---- a/tests/compute_engine/test__metadata.py -+++ b/tests/compute_engine/test__metadata.py +Index: google-auth-2.17.3/tests/compute_engine/test__metadata.py +=================================================================== +--- google-auth-2.17.3.orig/tests/compute_engine/test__metadata.py ++++ google-auth-2.17.3/tests/compute_engine/test__metadata.py @@ -16,7 +16,7 @@ import datetime import json import os @@ -44,8 +46,10 @@ import pytest # type: ignore from six.moves import http_client from six.moves import reload_module ---- a/tests/compute_engine/test_credentials.py -+++ b/tests/compute_engine/test_credentials.py +Index: google-auth-2.17.3/tests/compute_engine/test_credentials.py +=================================================================== +--- google-auth-2.17.3.orig/tests/compute_engine/test_credentials.py ++++ google-auth-2.17.3/tests/compute_engine/test_credentials.py @@ -14,7 +14,7 @@ import base64 import datetime @@ -55,8 +59,10 @@ import pytest # type: ignore import responses # type: ignore ---- a/tests/conftest.py -+++ b/tests/conftest.py +Index: google-auth-2.17.3/tests/conftest.py +=================================================================== +--- google-auth-2.17.3.orig/tests/conftest.py ++++ google-auth-2.17.3/tests/conftest.py @@ -15,7 +15,7 @@ import os import sys @@ -66,8 +72,10 @@ import pytest # type: ignore ---- a/tests/crypt/test__python_rsa.py -+++ b/tests/crypt/test__python_rsa.py +Index: google-auth-2.17.3/tests/crypt/test__python_rsa.py +=================================================================== +--- google-auth-2.17.3.orig/tests/crypt/test__python_rsa.py ++++ google-auth-2.17.3/tests/crypt/test__python_rsa.py @@ -15,7 +15,7 @@ import json import os @@ -77,8 +85,10 @@ from pyasn1_modules import pem # type: ignore import pytest # type: ignore import rsa # type: ignore ---- a/tests/oauth2/test__client.py -+++ b/tests/oauth2/test__client.py +Index: google-auth-2.17.3/tests/oauth2/test__client.py +=================================================================== +--- google-auth-2.17.3.orig/tests/oauth2/test__client.py ++++ google-auth-2.17.3/tests/oauth2/test__client.py @@ -16,7 +16,7 @@ import datetime import json import os @@ -88,8 +98,10 @@ import pytest # type: ignore import six from six.moves import http_client ---- a/tests/oauth2/test_challenges.py -+++ b/tests/oauth2/test_challenges.py +Index: google-auth-2.17.3/tests/oauth2/test_challenges.py +=================================================================== +--- google-auth-2.17.3.orig/tests/oauth2/test_challenges.py ++++ google-auth-2.17.3/tests/oauth2/test_challenges.py @@ -17,7 +17,7 @@ import base64 import sys @@ -99,8 +111,10 @@ import pytest # type: ignore import pyu2f # type: ignore ---- a/tests/oauth2/test_credentials.py -+++ b/tests/oauth2/test_credentials.py +Index: google-auth-2.17.3/tests/oauth2/test_credentials.py +=================================================================== +--- google-auth-2.17.3.orig/tests/oauth2/test_credentials.py ++++ google-auth-2.17.3/tests/oauth2/test_credentials.py @@ -18,7 +18,7 @@ import os import pickle import sys @@ -110,8 +124,10 @@ import pytest # type: ignore from google.auth import _helpers ---- a/tests/oauth2/test_gdch_credentials.py -+++ b/tests/oauth2/test_gdch_credentials.py +Index: google-auth-2.17.3/tests/oauth2/test_gdch_credentials.py +=================================================================== +--- google-auth-2.17.3.orig/tests/oauth2/test_gdch_credentials.py ++++ google-auth-2.17.3/tests/oauth2/test_gdch_credentials.py @@ -17,7 +17,7 @@ import datetime import json import os @@ -121,8 +137,10 @@ import pytest # type: ignore import requests import six ---- a/tests/oauth2/test_id_token.py -+++ b/tests/oauth2/test_id_token.py +Index: google-auth-2.17.3/tests/oauth2/test_id_token.py +=================================================================== +--- google-auth-2.17.3.orig/tests/oauth2/test_id_token.py ++++ google-auth-2.17.3/tests/oauth2/test_id_token.py @@ -15,7 +15,7 @@ import json import os @@ -132,8 +150,10 @@ import pytest # type: ignore from google.auth import environment_vars ---- a/tests/oauth2/test_reauth.py -+++ b/tests/oauth2/test_reauth.py +Index: google-auth-2.17.3/tests/oauth2/test_reauth.py +=================================================================== +--- google-auth-2.17.3.orig/tests/oauth2/test_reauth.py ++++ google-auth-2.17.3/tests/oauth2/test_reauth.py @@ -14,7 +14,7 @@ import copy @@ -143,8 +163,10 @@ import pytest # type: ignore from google.auth import exceptions ---- a/tests/oauth2/test_service_account.py -+++ b/tests/oauth2/test_service_account.py +Index: google-auth-2.17.3/tests/oauth2/test_service_account.py +=================================================================== +--- google-auth-2.17.3.orig/tests/oauth2/test_service_account.py ++++ google-auth-2.17.3/tests/oauth2/test_service_account.py @@ -16,7 +16,7 @@ import datetime import json import os @@ -154,8 +176,10 @@ from google.auth import _helpers from google.auth import crypt ---- a/tests/oauth2/test_sts.py -+++ b/tests/oauth2/test_sts.py +Index: google-auth-2.17.3/tests/oauth2/test_sts.py +=================================================================== +--- google-auth-2.17.3.orig/tests/oauth2/test_sts.py ++++ google-auth-2.17.3/tests/oauth2/test_sts.py @@ -14,7 +14,7 @@ import json @@ -165,19 +189,23 @@ import pytest # type: ignore from six.moves import http_client from six.moves import urllib ---- a/tests/test__cloud_sdk.py -+++ b/tests/test__cloud_sdk.py -@@ -17,7 +17,7 @@ import json - import os +Index: google-auth-2.17.3/tests/test__cloud_sdk.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test__cloud_sdk.py ++++ google-auth-2.17.3/tests/test__cloud_sdk.py +@@ -18,7 +18,7 @@ import os import subprocess + import sys -import mock +from unittest import mock import pytest # type: ignore from google.auth import _cloud_sdk ---- a/tests/test__default.py -+++ b/tests/test__default.py +Index: google-auth-2.17.3/tests/test__default.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test__default.py ++++ google-auth-2.17.3/tests/test__default.py @@ -15,7 +15,7 @@ import json import os @@ -187,8 +215,10 @@ import pytest # type: ignore from google.auth import _default ---- a/tests/test__exponential_backoff.py -+++ b/tests/test__exponential_backoff.py +Index: google-auth-2.17.3/tests/test__exponential_backoff.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test__exponential_backoff.py ++++ google-auth-2.17.3/tests/test__exponential_backoff.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. @@ -198,8 +228,10 @@ from google.auth import _exponential_backoff ---- a/tests/test__oauth2client.py -+++ b/tests/test__oauth2client.py +Index: google-auth-2.17.3/tests/test__oauth2client.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test__oauth2client.py ++++ google-auth-2.17.3/tests/test__oauth2client.py @@ -16,7 +16,7 @@ import datetime import os import sys @@ -209,8 +241,10 @@ import pytest # type: ignore from six.moves import reload_module ---- a/tests/test_app_engine.py -+++ b/tests/test_app_engine.py +Index: google-auth-2.17.3/tests/test_app_engine.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test_app_engine.py ++++ google-auth-2.17.3/tests/test_app_engine.py @@ -14,7 +14,7 @@ import datetime @@ -220,8 +254,10 @@ import pytest # type: ignore from google.auth import app_engine ---- a/tests/test_aws.py -+++ b/tests/test_aws.py +Index: google-auth-2.17.3/tests/test_aws.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test_aws.py ++++ google-auth-2.17.3/tests/test_aws.py @@ -16,7 +16,7 @@ import datetime import json import os @@ -231,8 +267,10 @@ import pytest # type: ignore from six.moves import http_client from six.moves import urllib ---- a/tests/test_downscoped.py -+++ b/tests/test_downscoped.py +Index: google-auth-2.17.3/tests/test_downscoped.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test_downscoped.py ++++ google-auth-2.17.3/tests/test_downscoped.py @@ -15,7 +15,7 @@ import datetime import json @@ -242,8 +280,10 @@ import pytest # type: ignore from six.moves import http_client from six.moves import urllib ---- a/tests/test_external_account.py -+++ b/tests/test_external_account.py +Index: google-auth-2.17.3/tests/test_external_account.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test_external_account.py ++++ google-auth-2.17.3/tests/test_external_account.py @@ -15,7 +15,7 @@ import datetime import json @@ -253,8 +293,10 @@ import pytest # type: ignore from six.moves import http_client from six.moves import urllib ---- a/tests/test_external_account_authorized_user.py -+++ b/tests/test_external_account_authorized_user.py +Index: google-auth-2.17.3/tests/test_external_account_authorized_user.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test_external_account_authorized_user.py ++++ google-auth-2.17.3/tests/test_external_account_authorized_user.py @@ -15,7 +15,7 @@ import datetime import json @@ -264,8 +306,10 @@ import pytest # type: ignore from six.moves import http_client ---- a/tests/test_iam.py -+++ b/tests/test_iam.py +Index: google-auth-2.17.3/tests/test_iam.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test_iam.py ++++ google-auth-2.17.3/tests/test_iam.py @@ -16,7 +16,7 @@ import base64 import datetime import json @@ -275,8 +319,10 @@ import pytest # type: ignore from six.moves import http_client ---- a/tests/test_identity_pool.py -+++ b/tests/test_identity_pool.py +Index: google-auth-2.17.3/tests/test_identity_pool.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test_identity_pool.py ++++ google-auth-2.17.3/tests/test_identity_pool.py @@ -16,7 +16,7 @@ import datetime import json import os @@ -286,8 +332,10 @@ import pytest # type: ignore from six.moves import http_client from six.moves import urllib ---- a/tests/test_impersonated_credentials.py -+++ b/tests/test_impersonated_credentials.py +Index: google-auth-2.17.3/tests/test_impersonated_credentials.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test_impersonated_credentials.py ++++ google-auth-2.17.3/tests/test_impersonated_credentials.py @@ -19,7 +19,7 @@ import os # Because Python 2.7 # from typing import List @@ -297,8 +345,10 @@ import pytest # type: ignore from six.moves import http_client ---- a/tests/test_jwt.py -+++ b/tests/test_jwt.py +Index: google-auth-2.17.3/tests/test_jwt.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test_jwt.py ++++ google-auth-2.17.3/tests/test_jwt.py @@ -17,7 +17,7 @@ import datetime import json import os @@ -308,8 +358,10 @@ import pytest # type: ignore from google.auth import _helpers ---- a/tests/test_pluggable.py -+++ b/tests/test_pluggable.py +Index: google-auth-2.17.3/tests/test_pluggable.py +=================================================================== +--- google-auth-2.17.3.orig/tests/test_pluggable.py ++++ google-auth-2.17.3/tests/test_pluggable.py @@ -17,7 +17,7 @@ import json import os import subprocess @@ -319,8 +371,10 @@ import pytest # type: ignore # from six.moves import http_client ---- a/tests/transport/test__custom_tls_signer.py -+++ b/tests/transport/test__custom_tls_signer.py +Index: google-auth-2.17.3/tests/transport/test__custom_tls_signer.py +=================================================================== +--- google-auth-2.17.3.orig/tests/transport/test__custom_tls_signer.py ++++ google-auth-2.17.3/tests/transport/test__custom_tls_signer.py @@ -16,7 +16,7 @@ import base64 import ctypes import os @@ -330,8 +384,10 @@ import pytest # type: ignore from requests.packages.urllib3.util.ssl_ import create_urllib3_context # type: ignore import urllib3.contrib.pyopenssl # type: ignore ---- a/tests/transport/test__mtls_helper.py -+++ b/tests/transport/test__mtls_helper.py +Index: google-auth-2.17.3/tests/transport/test__mtls_helper.py +=================================================================== +--- google-auth-2.17.3.orig/tests/transport/test__mtls_helper.py ++++ google-auth-2.17.3/tests/transport/test__mtls_helper.py @@ -15,7 +15,7 @@ import os import re @@ -341,8 +397,10 @@ from OpenSSL import crypto import pytest # type: ignore ---- a/tests/transport/test_grpc.py -+++ b/tests/transport/test_grpc.py +Index: google-auth-2.17.3/tests/transport/test_grpc.py +=================================================================== +--- google-auth-2.17.3.orig/tests/transport/test_grpc.py ++++ google-auth-2.17.3/tests/transport/test_grpc.py @@ -16,7 +16,7 @@ import datetime import os import time @@ -352,8 +410,10 @@ import pytest # type: ignore from google.auth import _helpers ---- a/tests/transport/test_mtls.py -+++ b/tests/transport/test_mtls.py +Index: google-auth-2.17.3/tests/transport/test_mtls.py +=================================================================== +--- google-auth-2.17.3.orig/tests/transport/test_mtls.py ++++ google-auth-2.17.3/tests/transport/test_mtls.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. @@ -363,8 +423,10 @@ import pytest # type: ignore from google.auth import exceptions ---- a/tests/transport/test_requests.py -+++ b/tests/transport/test_requests.py +Index: google-auth-2.17.3/tests/transport/test_requests.py +=================================================================== +--- google-auth-2.17.3.orig/tests/transport/test_requests.py ++++ google-auth-2.17.3/tests/transport/test_requests.py @@ -18,7 +18,7 @@ import os import sys @@ -374,8 +436,10 @@ import OpenSSL import pytest # type: ignore import requests ---- a/tests/transport/test_urllib3.py -+++ b/tests/transport/test_urllib3.py +Index: google-auth-2.17.3/tests/transport/test_urllib3.py +=================================================================== +--- google-auth-2.17.3.orig/tests/transport/test_urllib3.py ++++ google-auth-2.17.3/tests/transport/test_urllib3.py @@ -15,7 +15,7 @@ import os import sys ++++++ urllib3-2.patch ++++++ Index: google-auth-2.17.3/google/auth/transport/urllib3.py =================================================================== --- google-auth-2.17.3.orig/google/auth/transport/urllib3.py +++ google-auth-2.17.3/google/auth/transport/urllib3.py @@ -95,8 +95,8 @@ class Request(transport.Request): credentials.refresh(request) Args: - http (urllib3.request.RequestMethods): An instance of any urllib3 - class that implements :class:`~urllib3.request.RequestMethods`, + http (urllib3._request_methods.RequestMethods): An instance of any urllib3 + class that implements :class:`~urllib3._request_methods.RequestMethods`, usually :class:`urllib3.PoolManager`. .. automethod:: __call__ @@ -184,7 +184,7 @@ def _make_mutual_tls_http(cert, key): return http -class AuthorizedHttp(urllib3.request.RequestMethods): +class AuthorizedHttp(urllib3._request_methods.RequestMethods): """A urllib3 HTTP class with credentials. This class is used to perform requests to API endpoints that require @@ -197,8 +197,9 @@ class AuthorizedHttp(urllib3.request.Req response = authed_http.request( 'GET', 'https://www.googleapis.com/storage/v1/b') - This class implements :class:`urllib3.request.RequestMethods` and can be - used just like any other :class:`urllib3.PoolManager`. + This class implements + :class:`urllib3._request_methods.RequestMethods` and can be used + just like any other :class:`urllib3.PoolManager`. The underlying :meth:`urlopen` implementation handles adding the credentials' headers to the request and refreshing credentials as needed.
