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
+
+- 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-auth@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-account@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-account@example.com')
+ # Signer is initialized
+ assert self.credentials.signer
+ assert self.credentials.signer_email == 'service-account@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-account@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-account@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-account@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-account@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-account@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-account@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-account@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-account@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-account@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-account@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-account@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-account@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-account@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