Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
lmiglio opened this issue Jul 29, 2019 · 4 comments
Assignees
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. 🚨 This issue needs some love. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.

Comments

@lmiglio
Copy link
Contributor

lmiglio commented Jul 29, 2019

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)
@busunkim96
Copy link
Contributor

Hi @lmiglio, thank you for the report! Would you be able to open a PR with the change?

lmiglio added a commit to lmiglio/google-auth-library-python that referenced this issue Jul 30, 2019
@yoshi-automation yoshi-automation added the triage me I really want to be triaged. label Jul 30, 2019
@tseaver tseaver added priority: p2 Moderately-important priority. Fix may not be included in next release. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. and removed triage me I really want to be triaged. labels Jul 30, 2019
@salrashid123
Copy link
Contributor

salrashid123 commented Aug 12, 2019

@lmiglio

pls take a look at
#362

what that change does is alters how compute_engine gets an id token...prior to this, it used an API to get it through signing (ther'es no reason to do that at all; you an 'just ask the metadata server')

i've left the Signer capability intact though for compute_engine credentials. IMO, not even the signer capability should be part of compute engine credentials since what you're doing thers is basically impersonation and that can now be achieved through:

edit, #348

I'll file an issue for that separately but that PR cited is just for the id_token.


fyi, tried to repro the issue you've filed here with the changes i've got on pr 362 and it works fine: on a gce instance

>>> import google.auth
>>> cred, _ = google.auth.default()
>>> cred
<google.auth.compute_engine.credentials.Credentials object at 0x7f43890bb390>
>>> 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 0x7f43888c0190>
>>> cred_with_audience = id_credentials.with_target_audience("https://foo.bar")
>>> cred_with_audience.refresh(Request())
>>> 

lmiglio added a commit to lmiglio/google-auth-library-python that referenced this issue Aug 19, 2019
@yoshi-automation yoshi-automation added the 🚨 This issue needs some love. label Jan 25, 2020
@JustinBeckwith
Copy link
Contributor

@busunkim96 & @bshaffer - could I trouble y'all to team up on this one?

@busunkim96
Copy link
Contributor

Closed by #438

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. 🚨 This issue needs some love. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Projects
None yet
Development

No branches or pull requests

7 participants