Hello community, here is the log from the commit of package python-google-auth for openSUSE:Factory checked in at 2018-09-14 00:01:16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-google-auth (Old) and /work/SRC/openSUSE:Factory/.python-google-auth.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-auth" Fri Sep 14 00:01:16 2018 rev:4 rq:635375 version:1.5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-google-auth/python-google-auth.changes 2018-06-02 12:08:54.931104021 +0200 +++ /work/SRC/openSUSE:Factory/.python-google-auth.new/python-google-auth.changes 2018-09-14 00:01:18.489957528 +0200 @@ -1,0 +2,12 @@ +Wed Sep 12 19:59:10 UTC 2018 - Thomas Bechtold <tbecht...@suse.com> + +- update to 1.5.1: + - Fix check for error text on Python 3.7. (#278) + - Use new Auth URIs. (#281) + - Add code-of-conduct document. (#270) + - Fix some typos in test_urllib3.py (#268) + - Warn when using user credentials from the Cloud SDK (#266) + - Add compute engine-based IDTokenCredentials (#236) + - Corrected some typos (#265) + +------------------------------------------------------------------- Old: ---- google-auth-1.4.2.tar.gz New: ---- google-auth-1.5.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-google-auth.spec ++++++ --- /var/tmp/diff_new_pack.vg89fj/_old 2018-09-14 00:01:19.701956602 +0200 +++ /var/tmp/diff_new_pack.vg89fj/_new 2018-09-14 00:01:19.705956599 +0200 @@ -12,13 +12,13 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-google-auth -Version: 1.4.2 +Version: 1.5.1 Release: 0 Summary: Google Authentication Library License: Apache-2.0 ++++++ google-auth-1.4.2.tar.gz -> google-auth-1.5.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/CHANGELOG.rst new/google-auth-1.5.1/CHANGELOG.rst --- old/google-auth-1.4.2/CHANGELOG.rst 2018-05-24 22:41:18.000000000 +0200 +++ new/google-auth-1.5.1/CHANGELOG.rst 2018-08-01 01:16:19.000000000 +0200 @@ -1,6 +1,21 @@ Changelog ========= +v1.5.1 +------ + +- Fix check for error text on Python 3.7. (#278) +- Use new Auth URIs. (#281) +- Add code-of-conduct document. (#270) +- Fix some typos in test_urllib3.py (#268) + +v1.5.0 +------ + +- Warn when using user credentials from the Cloud SDK (#266) +- Add compute engine-based IDTokenCredentials (#236) +- Corrected some typos (#265) + v1.4.2 ------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/PKG-INFO new/google-auth-1.5.1/PKG-INFO --- old/google-auth-1.4.2/PKG-INFO 2018-05-29 17:51:21.000000000 +0200 +++ new/google-auth-1.5.1/PKG-INFO 2018-08-01 01:23:36.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: google-auth -Version: 1.4.2 +Version: 1.5.1 Summary: Google Authentication Library Home-page: https://github.com/GoogleCloudPlatform/google-auth-library-python Author: Google Cloud Platform diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/google/auth/_cloud_sdk.py new/google-auth-1.5.1/google/auth/_cloud_sdk.py --- old/google-auth-1.4.2/google/auth/_cloud_sdk.py 2018-05-16 20:01:59.000000000 +0200 +++ new/google-auth-1.5.1/google/auth/_cloud_sdk.py 2018-05-31 23:53:20.000000000 +0200 @@ -34,6 +34,9 @@ _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's application-default client ID +CLOUD_SDK_CLIENT_ID = ( + '764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com') def get_config_path(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/google/auth/_default.py new/google-auth-1.5.1/google/auth/_default.py --- old/google-auth-1.4.2/google/auth/_default.py 2018-05-16 20:01:59.000000000 +0200 +++ new/google-auth-1.5.1/google/auth/_default.py 2018-05-31 23:53:20.000000000 +0200 @@ -21,6 +21,7 @@ import json import logging import os +import warnings import six @@ -36,13 +37,34 @@ _VALID_TYPES = (_AUTHORIZED_USER_TYPE, _SERVICE_ACCOUNT_TYPE) # Help message when no credentials can be found. -_HELP_MESSAGE = """ -Could not automatically determine credentials. Please set {env} or -explicitly create credential and re-run the application. For more -information, please see +_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://developers.google.com/accounts/docs/application-default-credentials. """.format(env=environment_vars.CREDENTIALS).strip() +# Warning when using Cloud SDK user credentials +_CLOUD_SDK_CREDENTIALS_WARNING = """\ +Your application has authenticated using end user credentials from Google \ +Cloud SDK. We recommend that most server applications use service accounts \ +instead. If your application continues to use end user credentials from Cloud \ +SDK, you might receive a "quota exceeded" or "API not enabled" error. For \ +more information about service accounts, see \ +https://cloud.google.com/docs/authentication/.""" + + +def _warn_about_problematic_credentials(credentials): + """Determines if the credentials are problematic. + + Credentials from the Cloud SDK that are associated with Cloud SDK's project + are problematic because they may not have APIs enabled and have limited + quota. If this is the case, warn about it. + """ + from google.auth import _cloud_sdk + if credentials.client_id == _cloud_sdk.CLOUD_SDK_CLIENT_ID: + warnings.warn(_CLOUD_SDK_CREDENTIALS_WARNING) + def _load_credentials_from_file(filename): """Loads credentials from a file. @@ -90,6 +112,7 @@ new_exc = exceptions.DefaultCredentialsError(msg, caught_exc) six.raise_from(new_exc, caught_exc) # Authorized user credentials do not contain the project ID. + _warn_about_problematic_credentials(credentials) return credentials, None elif credential_type == _SERVICE_ACCOUNT_TYPE: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/google/auth/compute_engine/__init__.py new/google-auth-1.5.1/google/auth/compute_engine/__init__.py --- old/google-auth-1.4.2/google/auth/compute_engine/__init__.py 2018-05-16 20:01:59.000000000 +0200 +++ new/google-auth-1.5.1/google/auth/compute_engine/__init__.py 2018-05-31 20:16:54.000000000 +0200 @@ -15,8 +15,10 @@ """Google Compute Engine authentication.""" from google.auth.compute_engine.credentials import Credentials +from google.auth.compute_engine.credentials import IDTokenCredentials __all__ = [ - 'Credentials' + 'Credentials', + 'IDTokenCredentials', ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/google/auth/compute_engine/credentials.py new/google-auth-1.5.1/google/auth/compute_engine/credentials.py --- old/google-auth-1.4.2/google/auth/compute_engine/credentials.py 2018-05-16 20:01:59.000000000 +0200 +++ new/google-auth-1.5.1/google/auth/compute_engine/credentials.py 2018-05-31 20:16:54.000000000 +0200 @@ -19,11 +19,17 @@ """ +import datetime + import six +from google.auth import _helpers from google.auth import credentials from google.auth import exceptions +from google.auth import iam +from google.auth import jwt from google.auth.compute_engine import _metadata +from google.oauth2 import _client class Credentials(credentials.ReadOnlyScoped, credentials.Credentials): @@ -108,3 +114,126 @@ def requires_scopes(self): """False: Compute Engine credentials can not be scoped.""" return False + + +_DEFAULT_TOKEN_LIFETIME_SECS = 3600 # 1 hour in seconds +_DEFAULT_TOKEN_URI = 'https://www.googleapis.com/oauth2/v4/token' + + +class IDTokenCredentials(credentials.Credentials, credentials.Signing): + """Open ID Connect ID Token-based service account credentials. + + These credentials relies on the default service account of a GCE instance. + + In order for this to work, the GCE instance must have been started with + a service account that has access to the IAM Cloud API. + """ + def __init__(self, request, target_audience, + token_uri=_DEFAULT_TOKEN_URI, + additional_claims=None, + service_account_email=None): + """ + Args: + request (google.auth.transport.Request): The object used to make + HTTP requests. + target_audience (str): The intended audience for these credentials, + used when requesting the ID Token. The ID Token's ``aud`` claim + will be set to this string. + token_uri (str): The OAuth 2.0 Token URI. + additional_claims (Mapping[str, str]): Any additional claims for + the JWT assertion used in the authorization grant. + service_account_email (str): Optional explicit service account to + use to sign JWT tokens. + By default, this is the default GCE service account. + """ + super(IDTokenCredentials, self).__init__() + + if service_account_email is None: + sa_info = _metadata.get_service_account_info(request) + service_account_email = sa_info['email'] + self._service_account_email = service_account_email + + self._signer = iam.Signer( + request=request, + credentials=Credentials(), + service_account_email=service_account_email) + + self._token_uri = token_uri + self._target_audience = target_audience + + if additional_claims is not None: + self._additional_claims = additional_claims + else: + self._additional_claims = {} + + def with_target_audience(self, target_audience): + """Create a copy of these credentials with the specified target + audience. + Args: + target_audience (str): The intended audience for these credentials, + used when requesting the ID Token. + Returns: + google.auth.service_account.IDTokenCredentials: A new credentials + instance. + """ + return self.__class__( + self._signer, + service_account_email=self._service_account_email, + token_uri=self._token_uri, + target_audience=target_audience, + additional_claims=self._additional_claims.copy()) + + def _make_authorization_grant_assertion(self): + """Create the OAuth 2.0 assertion. + This assertion is used during the OAuth 2.0 grant to acquire an + ID token. + Returns: + bytes: The authorization grant assertion. + """ + now = _helpers.utcnow() + lifetime = datetime.timedelta(seconds=_DEFAULT_TOKEN_LIFETIME_SECS) + expiry = now + lifetime + + payload = { + 'iat': _helpers.datetime_to_secs(now), + 'exp': _helpers.datetime_to_secs(expiry), + # The issuer must be the service account email. + 'iss': self.service_account_email, + # The audience must be the auth token endpoint's URI + 'aud': self._token_uri, + # The target audience specifies which service the ID token is + # intended for. + 'target_audience': self._target_audience + } + + payload.update(self._additional_claims) + + token = jwt.encode(self._signer, payload) + + return token + + @_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 + + @property + @_helpers.copy_docstring(credentials.Signing) + def signer(self): + return self._signer + + @_helpers.copy_docstring(credentials.Signing) + def sign_bytes(self, message): + return self._signer.sign(message) + + @property + def service_account_email(self): + """The service account email.""" + return self._service_account_email + + @property + def signer_email(self): + return self._service_account_email diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/google/oauth2/credentials.py new/google-auth-1.5.1/google/oauth2/credentials.py --- old/google-auth-1.4.2/google/oauth2/credentials.py 2018-05-24 22:34:23.000000000 +0200 +++ new/google-auth-1.5.1/google/oauth2/credentials.py 2018-08-01 00:38:49.000000000 +0200 @@ -43,7 +43,7 @@ # The Google OAuth 2.0 token endpoint. Used for authorized user credentials. -_GOOGLE_OAUTH2_TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token' +_GOOGLE_OAUTH2_TOKEN_ENDPOINT = 'https://oauth2.googleapis.com/token' class Credentials(credentials.ReadOnlyScoped, credentials.Credentials): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/google_auth.egg-info/PKG-INFO new/google-auth-1.5.1/google_auth.egg-info/PKG-INFO --- old/google-auth-1.4.2/google_auth.egg-info/PKG-INFO 2018-05-29 17:51:21.000000000 +0200 +++ new/google-auth-1.5.1/google_auth.egg-info/PKG-INFO 2018-08-01 01:23:36.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: google-auth -Version: 1.4.2 +Version: 1.5.1 Summary: Google Authentication Library Home-page: https://github.com/GoogleCloudPlatform/google-auth-library-python Author: Google Cloud Platform diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/google_auth.egg-info/SOURCES.txt new/google-auth-1.5.1/google_auth.egg-info/SOURCES.txt --- old/google-auth-1.4.2/google_auth.egg-info/SOURCES.txt 2018-05-29 17:51:21.000000000 +0200 +++ new/google-auth-1.5.1/google_auth.egg-info/SOURCES.txt 2018-08-01 01:23:36.000000000 +0200 @@ -61,6 +61,7 @@ tests/crypt/test__python_rsa.py tests/crypt/test_crypt.py tests/data/authorized_user.json +tests/data/authorized_user_cloud_sdk.json tests/data/client_secrets.json tests/data/cloud_sdk_config.json tests/data/other_cert.pem diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/setup.py new/google-auth-1.5.1/setup.py --- old/google-auth-1.4.2/setup.py 2018-05-24 22:41:49.000000000 +0200 +++ new/google-auth-1.5.1/setup.py 2018-08-01 01:16:19.000000000 +0200 @@ -31,7 +31,7 @@ setup( name='google-auth', - version='1.4.2', + version='1.5.1', author='Google Cloud Platform', author_email='jonwayne+google-a...@google.com', description='Google Authentication Library', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/tests/compute_engine/test_credentials.py new/google-auth-1.5.1/tests/compute_engine/test_credentials.py --- old/google-auth-1.4.2/tests/compute_engine/test_credentials.py 2018-05-16 20:01:59.000000000 +0200 +++ new/google-auth-1.5.1/tests/compute_engine/test_credentials.py 2018-05-31 20:16:54.000000000 +0200 @@ -19,6 +19,7 @@ from google.auth import _helpers from google.auth import exceptions +from google.auth import jwt from google.auth import transport from google.auth.compute_engine import credentials @@ -105,3 +106,278 @@ # Credentials should now be valid. assert self.credentials.valid + + +class TestIDTokenCredentials(object): + credentials = None + + @mock.patch('google.auth.compute_engine._metadata.get', autospec=True) + def test_default_state(self, get): + get.side_effect = [{ + 'email': 'service-acco...@example.com', + 'scope': ['one', 'two'], + }] + + request = mock.create_autospec(transport.Request, instance=True) + self.credentials = credentials.IDTokenCredentials( + request=request, target_audience="https://example.com") + + assert not self.credentials.valid + # Expiration hasn't been set yet + assert not self.credentials.expired + # Service account email hasn't been populated + assert (self.credentials.service_account_email + == 'service-acco...@example.com') + # Signer is initialized + assert self.credentials.signer + assert self.credentials.signer_email == 'service-acco...@example.com' + + @mock.patch( + 'google.auth._helpers.utcnow', + return_value=datetime.datetime.utcfromtimestamp(0)) + @mock.patch('google.auth.compute_engine._metadata.get', autospec=True) + @mock.patch('google.auth.iam.Signer.sign', autospec=True) + def test_make_authorization_grant_assertion(self, sign, get, utcnow): + get.side_effect = [{ + 'email': 'service-acco...@example.com', + 'scopes': ['one', 'two'] + }] + sign.side_effect = [b'signature'] + + request = mock.create_autospec(transport.Request, instance=True) + self.credentials = credentials.IDTokenCredentials( + request=request, target_audience="https://audience.com") + + # Generate authorization grant: + token = self.credentials._make_authorization_grant_assertion() + payload = jwt.decode(token, verify=False) + + # The JWT token signature is 'signature' encoded in base 64: + assert token.endswith(b'.c2lnbmF0dXJl') + + # Check that the credentials have the token and proper expiration + assert payload == { + 'aud': 'https://www.googleapis.com/oauth2/v4/token', + 'exp': 3600, + 'iat': 0, + 'iss': 'service-acco...@example.com', + 'target_audience': 'https://audience.com'} + + @mock.patch( + 'google.auth._helpers.utcnow', + return_value=datetime.datetime.utcfromtimestamp(0)) + @mock.patch('google.auth.compute_engine._metadata.get', autospec=True) + @mock.patch('google.auth.iam.Signer.sign', autospec=True) + def test_with_service_account(self, sign, get, utcnow): + sign.side_effect = [b'signature'] + + request = mock.create_autospec(transport.Request, instance=True) + self.credentials = credentials.IDTokenCredentials( + request=request, target_audience="https://audience.com", + service_account_email="service-acco...@other.com") + + # Generate authorization grant: + token = self.credentials._make_authorization_grant_assertion() + payload = jwt.decode(token, verify=False) + + # The JWT token signature is 'signature' encoded in base 64: + assert token.endswith(b'.c2lnbmF0dXJl') + + # Check that the credentials have the token and proper expiration + assert payload == { + 'aud': 'https://www.googleapis.com/oauth2/v4/token', + 'exp': 3600, + 'iat': 0, + 'iss': 'service-acco...@other.com', + 'target_audience': 'https://audience.com'} + + @mock.patch( + 'google.auth._helpers.utcnow', + return_value=datetime.datetime.utcfromtimestamp(0)) + @mock.patch('google.auth.compute_engine._metadata.get', autospec=True) + @mock.patch('google.auth.iam.Signer.sign', autospec=True) + def test_additional_claims(self, sign, get, utcnow): + get.side_effect = [{ + 'email': 'service-acco...@example.com', + 'scopes': ['one', 'two'] + }] + sign.side_effect = [b'signature'] + + request = mock.create_autospec(transport.Request, instance=True) + self.credentials = credentials.IDTokenCredentials( + request=request, target_audience="https://audience.com", + additional_claims={'foo': 'bar'}) + + # Generate authorization grant: + token = self.credentials._make_authorization_grant_assertion() + payload = jwt.decode(token, verify=False) + + # The JWT token signature is 'signature' encoded in base 64: + assert token.endswith(b'.c2lnbmF0dXJl') + + # Check that the credentials have the token and proper expiration + assert payload == { + 'aud': 'https://www.googleapis.com/oauth2/v4/token', + 'exp': 3600, + 'iat': 0, + 'iss': 'service-acco...@example.com', + 'target_audience': 'https://audience.com', + 'foo': 'bar'} + + @mock.patch( + 'google.auth._helpers.utcnow', + return_value=datetime.datetime.utcfromtimestamp(0)) + @mock.patch('google.auth.compute_engine._metadata.get', autospec=True) + @mock.patch('google.auth.iam.Signer.sign', autospec=True) + def test_with_target_audience(self, sign, get, utcnow): + get.side_effect = [{ + 'email': 'service-acco...@example.com', + 'scopes': ['one', 'two'] + }] + sign.side_effect = [b'signature'] + + request = mock.create_autospec(transport.Request, instance=True) + self.credentials = credentials.IDTokenCredentials( + request=request, target_audience="https://audience.com") + self.credentials = ( + self.credentials.with_target_audience("https://actually.not")) + + # Generate authorization grant: + token = self.credentials._make_authorization_grant_assertion() + payload = jwt.decode(token, verify=False) + + # The JWT token signature is 'signature' encoded in base 64: + assert token.endswith(b'.c2lnbmF0dXJl') + + # Check that the credentials have the token and proper expiration + assert payload == { + 'aud': 'https://www.googleapis.com/oauth2/v4/token', + 'exp': 3600, + 'iat': 0, + 'iss': 'service-acco...@example.com', + 'target_audience': 'https://actually.not'} + + @mock.patch( + 'google.auth._helpers.utcnow', + return_value=datetime.datetime.utcfromtimestamp(0)) + @mock.patch('google.auth.compute_engine._metadata.get', autospec=True) + @mock.patch('google.auth.iam.Signer.sign', autospec=True) + @mock.patch('google.oauth2._client.id_token_jwt_grant', autospec=True) + def test_refresh_success(self, id_token_jwt_grant, sign, get, utcnow): + get.side_effect = [{ + 'email': 'service-acco...@example.com', + 'scopes': ['one', 'two'] + }] + sign.side_effect = [b'signature'] + id_token_jwt_grant.side_effect = [( + 'idtoken', + datetime.datetime.utcfromtimestamp(3600), + {}, + )] + + request = mock.create_autospec(transport.Request, instance=True) + self.credentials = credentials.IDTokenCredentials( + request=request, target_audience="https://audience.com") + + # Refresh credentials + self.credentials.refresh(None) + + # Check that the credentials have the token and proper expiration + assert self.credentials.token == 'idtoken' + assert self.credentials.expiry == ( + datetime.datetime.utcfromtimestamp(3600)) + + # Check the credential info + assert (self.credentials.service_account_email == + 'service-acco...@example.com') + + # Check that the credentials are valid (have a token and are not + # expired) + assert self.credentials.valid + + @mock.patch( + 'google.auth._helpers.utcnow', + return_value=datetime.datetime.utcfromtimestamp(0)) + @mock.patch('google.auth.compute_engine._metadata.get', autospec=True) + @mock.patch('google.auth.iam.Signer.sign', autospec=True) + def test_refresh_error(self, sign, get, utcnow): + get.side_effect = [{ + 'email': 'service-acco...@example.com', + 'scopes': ['one', 'two'], + }] + sign.side_effect = [b'signature'] + + request = mock.create_autospec(transport.Request, instance=True) + response = mock.Mock() + response.data = b'{"error": "http error"}' + response.status = 500 + request.side_effect = [response] + + self.credentials = credentials.IDTokenCredentials( + request=request, target_audience="https://audience.com") + + with pytest.raises(exceptions.RefreshError) as excinfo: + self.credentials.refresh(request) + + assert excinfo.match(r'http error') + + @mock.patch( + 'google.auth._helpers.utcnow', + return_value=datetime.datetime.utcfromtimestamp(0)) + @mock.patch('google.auth.compute_engine._metadata.get', autospec=True) + @mock.patch('google.auth.iam.Signer.sign', autospec=True) + @mock.patch('google.oauth2._client.id_token_jwt_grant', autospec=True) + def test_before_request_refreshes( + self, id_token_jwt_grant, sign, get, utcnow): + get.side_effect = [{ + 'email': 'service-acco...@example.com', + 'scopes': 'one two' + }] + sign.side_effect = [b'signature'] + id_token_jwt_grant.side_effect = [( + 'idtoken', + datetime.datetime.utcfromtimestamp(3600), + {}, + )] + + request = mock.create_autospec(transport.Request, instance=True) + self.credentials = credentials.IDTokenCredentials( + request=request, target_audience="https://audience.com") + + # Credentials should start as invalid + assert not self.credentials.valid + + # before_request should cause a refresh + request = mock.create_autospec(transport.Request, instance=True) + self.credentials.before_request( + request, 'GET', 'http://example.com?a=1#3', {}) + + # The refresh endpoint should've been called. + assert get.called + + # Credentials should now be valid. + assert self.credentials.valid + + @mock.patch('google.auth.compute_engine._metadata.get', autospec=True) + @mock.patch('google.auth.iam.Signer.sign', autospec=True) + def test_sign_bytes(self, sign, get): + get.side_effect = [{ + 'email': 'service-acco...@example.com', + 'scopes': ['one', 'two'] + }] + sign.side_effect = [b'signature'] + + request = mock.create_autospec(transport.Request, instance=True) + response = mock.Mock() + response.data = b'{"signature": "c2lnbmF0dXJl"}' + response.status = 200 + request.side_effect = [response] + + self.credentials = credentials.IDTokenCredentials( + request=request, target_audience="https://audience.com") + + # Generate authorization grant: + signature = self.credentials.sign_bytes(b"some bytes") + + # The JWT token signature is 'signature' encoded in base 64: + assert signature == b'signature' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/tests/data/authorized_user_cloud_sdk.json new/google-auth-1.5.1/tests/data/authorized_user_cloud_sdk.json --- old/google-auth-1.4.2/tests/data/authorized_user_cloud_sdk.json 1970-01-01 01:00:00.000000000 +0100 +++ new/google-auth-1.5.1/tests/data/authorized_user_cloud_sdk.json 2018-05-31 23:53:20.000000000 +0200 @@ -0,0 +1,6 @@ +{ + "client_id": "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com", + "client_secret": "secret", + "refresh_token": "alabalaportocala", + "type": "authorized_user" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/tests/test__default.py new/google-auth-1.5.1/tests/test__default.py --- old/google-auth-1.4.2/tests/test__default.py 2018-05-16 20:01:59.000000000 +0200 +++ new/google-auth-1.5.1/tests/test__default.py 2018-05-31 23:53:20.000000000 +0200 @@ -33,6 +33,9 @@ with open(AUTHORIZED_USER_FILE) as fh: AUTHORIZED_USER_FILE_DATA = json.load(fh) +AUTHORIZED_USER_CLOUD_SDK_FILE = os.path.join( + DATA_DIR, 'authorized_user_cloud_sdk.json') + SERVICE_ACCOUNT_FILE = os.path.join(DATA_DIR, 'service_account.json') with open(SERVICE_ACCOUNT_FILE) as fh: @@ -88,6 +91,14 @@ assert excinfo.match(r'missing fields') +def test__load_credentials_from_file_authorized_user_cloud_sdk(): + with pytest.warns(UserWarning, matches='Cloud SDK'): + credentials, project_id = _default._load_credentials_from_file( + AUTHORIZED_USER_CLOUD_SDK_FILE) + assert isinstance(credentials, google.oauth2.credentials.Credentials) + assert project_id is None + + def test__load_credentials_from_file_service_account(): credentials, project_id = _default._load_credentials_from_file( SERVICE_ACCOUNT_FILE) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/tests/test_jwt.py new/google-auth-1.5.1/tests/test_jwt.py --- old/google-auth-1.4.2/tests/test_jwt.py 2018-05-16 20:01:59.000000000 +0200 +++ new/google-auth-1.5.1/tests/test_jwt.py 2018-08-01 00:38:49.000000000 +0200 @@ -118,7 +118,7 @@ def test_decode_bad_token_not_base64(): with pytest.raises((ValueError, TypeError)) as excinfo: jwt.decode('1.2.3', PUBLIC_CERT_BYTES) - assert excinfo.match(r'Incorrect padding') + assert excinfo.match(r'Incorrect padding|more than a multiple of 4') def test_decode_bad_token_not_json(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-1.4.2/tests/transport/test_urllib3.py new/google-auth-1.5.1/tests/transport/test_urllib3.py --- old/google-auth-1.4.2/tests/transport/test_urllib3.py 2018-05-16 20:01:59.000000000 +0200 +++ new/google-auth-1.5.1/tests/transport/test_urllib3.py 2018-06-15 19:31:05.000000000 +0200 @@ -34,13 +34,13 @@ assert http.request.call_args[1]['timeout'] == 5 -def test__make_default_http_with_certfi(): +def test__make_default_http_with_certifi(): http = google.auth.transport.urllib3._make_default_http() assert 'cert_reqs' in http.connection_pool_kw @mock.patch.object(google.auth.transport.urllib3, 'certifi', new=None) -def test__make_default_http_without_certfi(): +def test__make_default_http_without_certifi(): http = google.auth.transport.urllib3._make_default_http() assert 'cert_reqs' not in http.connection_pool_kw