0

I am trying to convert the following command from CLI (that works) to python but I am having some problems.

curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" SERVICE_URL

The problem is that I cannot request a valid Bearer with application default local credentials token to make authorized request to Google Cloud Run. If I generate Bearer token from CLI gcloud auth print-identity-token and use it in a python request all works fine

request_url = 'https://<my endpoint>'
identity_token = '<>' # response of gcloud auth print-identity-token)
header= {'Authorization': f'Bearer {identity_token}'}
requests.get(url=request_url, headers=receiving_service_headers)

From google auth documentation I understood that Cloud Run communicationis based on Identity Tokens that support Impersonated authentication but I cannot generate valid credential.

from google.auth import impersonated_credentials, default
from google.auth.transport.requests import AuthorizedSession

request_url = 'https://<my endpoint>'
source_credentials, project = default()

creds = impersonated_credentials.IDTokenCredentials(
    source_credentials,
    target_audience=request_url)

authed_session = AuthorizedSession(creds)
resp = authed_session.get(request_url)
print(resp)

bui I get following error

google.auth.exceptions.GoogleAuthError: Provided Credential must be impersonated_credentials

Thanks

Paolo Fusari
  • 105
  • 12
  • Edit your question with a minimum reproducible example. For example, you are not showing how you are creating credentials (`source_credentials`). Do you actually need to impersonate? What are you impersonating? – John Hanley Sep 09 '20 at 18:33
  • The second snippet of code can be used to reproduce the error. I get local application default creds with `default()` method (after executing `gcloud auth application-default`) rhen I need to get from this creds identity token to make a call on an authorized cloud run endpoint. I don't think I need impersonate but I found this solution as a workaround to use application default credential since `source_credential.id_token` gives unauthorized. If i use `service_account.IDTokenCredentials.from_service_account_file` works correctly. – Paolo Fusari Sep 09 '20 at 19:16

2 Answers2

0

Please follow the enter link if you want to convert the curl command to python request. Here is converted code:

import requests

headers = { 'Authorization': 'Bearer $(gcloud auth print-identity-token)', }

response = requests.get('http://SERVICE_URL', headers=headers)

Mahboob
  • 1,877
  • 5
  • 19
  • 1
    The problem is that `gcloud auth print-identity-token` isn't a plain http request but it's a gcloud cli utility – Paolo Fusari Sep 09 '20 at 19:21
  • Check this https://stackoverflow.com/questions/53472429/how-to-get-a-gcp-bearer-token-programmatically-with-python/53472880 – Mahboob Sep 10 '20 at 20:47
0

Today it's impossible. I talked about it in an article. You need a service account to generate a valid JWT token with the Google Auth library. It's the same problem with all the library and all the languages.

Last week, I pushed a merge request in the Java auth library to solve this. I don't know why Google don't implement it by itself.

On your local environment, if you want to use the same code locally and in the cloud, you have to generate a service account key file and use it with ADC. And it's sadly a security issue...

guillaume blaquiere
  • 66,369
  • 2
  • 47
  • 76