Thanks to visit codestin.com
Credit goes to github.com

Skip to content

bug in with_target_audience method of google.auth.compute_engine.IDTokenCredentials #359

@lmiglio

Description

@lmiglio

Hi, I think I found a problem with google.auth.compute_engine.credentials.IDTokenCredentials. When the methods with_target_audience and then refresh are called, a TypeError: 'Signer' object is not callable is raised.

Environment details

  • OS: Debian GNU/Linux 9 (stretch) (but I believe it does not depend on the os)
  • Python version: 2.7/3.7
  • google-auth version: 1.6.3

Steps to reproduce

  1. have access either to dev shell or to a vm shell
  2. run python
>>> import google.auth
>>> cred, _ = google.auth.default()
>>> cred
<google.auth.compute_engine.credentials.Credentials object at 0x7fcfb4612810>
>>> from google.auth.transport.requests import Request
>>> from google.auth.compute_engine.credentials import IDTokenCredentials                                                                                                                                            
>>> id_credentials = IDTokenCredentials(Request(), None)
>>> id_credentials
<google.auth.compute_engine.credentials.IDTokenCredentials object at 0x7fcfb3dd4650>
>>> cred_with_audience = id_credentials.with_target_audience("some-existing-client-id") # client id has been removed, put an existing one
>>> cred_with_audience.refresh(Request())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/google/auth/compute_engine/credentials.py", line 217, in refresh
    assertion = self._make_authorization_grant_assertion()
  File "/usr/local/lib/python2.7/dist-packages/google/auth/compute_engine/credentials.py", line 211, in _make_authorization_grant_assertion
    token = jwt.encode(self._signer, payload)
  File "/usr/local/lib/python2.7/dist-packages/google/auth/jwt.py", line 97, in encode
    signature = signer.sign(signing_input)
  File "/usr/local/lib/python2.7/dist-packages/google/auth/iam.py", line 101, in sign
    response = self._make_signing_request(message)
  File "/usr/local/lib/python2.7/dist-packages/google/auth/iam.py", line 78, in _make_signing_request
    self._credentials.before_request(self._request, method, url, headers)
  File "/usr/local/lib/python2.7/dist-packages/google/auth/credentials.py", line 122, in before_request
    self.refresh(request)
  File "/usr/local/lib/python2.7/dist-packages/google/auth/compute_engine/credentials.py", line 96, in refresh
    self._retrieve_info(request)
  File "/usr/local/lib/python2.7/dist-packages/google/auth/compute_engine/credentials.py", line 78, in _retrieve_info
    service_account=self._service_account_email)
  File "/usr/local/lib/python2.7/dist-packages/google/auth/compute_engine/_metadata.py", line 186, in get_service_account_info
    recursive=True)
  File "/usr/local/lib/python2.7/dist-packages/google/auth/compute_engine/_metadata.py", line 122, in get
    response = request(url=url, method='GET', headers=_METADATA_HEADERS)
TypeError: 'Signer' object is not callable

Possible fix

I believe that the problem is in this line of code. When the copy of the credentials is created, the constructor of IDTokenCredentials is called and the self._signer is passed as first parameter instead of the Request object. That is why it fails with TypeError: 'Signer' object is not callable.

A possible clean solution could consist in adding signer as parameter to the constructor.

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,
                 signer = None):
        """
...
        if signer is None:
            signer = iam.Signer(
                request=request,
                credentials=Credentials(),
                service_account_email=service_account_email)
        self._signer = signer
...

    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__(
            Request(),
            service_account_email=self._service_account_email,
            token_uri=self._token_uri,
            target_audience=target_audience,
            additional_claims=self._additional_claims.copy(),
            signer=self._signer)

Metadata

Metadata

Labels

🚨This issue needs some love.priority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions