Securely Call Cloud Run Service From Anywhere
Enabling authentication for your Cloud Run application is easy ‒ a single mouse click (or parameter in your CI/CD) without writing any code. Calling this application from another is less straightforward. It may be easy when both a caller and called applications are hosted under the same identity in Google Cloud. In the rest of cases, it requires acquiring an identity token.
A problem begins with documentation. Sometimes it isn’t clear whether the described token is an identity token or access token. While the first is good for invoking endpoints of user’s applications on Google Cloud, the second is good only for calling Google APIs.
Another challenge is with examples that demonstrate getting an identity token from a metadata server available in Google Cloud VMs and other managed environments such as GKE or Cloud Run. However this method would not work anywhere else.
The following method lets you call a private Cloud Run service regardless whether the calling code runs in Google Cloud or elsewhere. This code example is in Python. Please leave a comment if you need a code snippet in another programming language.
import google.auth
import google.auth.transport.requests
from google.oauth2 import id_token
audience = 'https://your-cloud-run-service-url.run.app'
# acquire ADC
credentials, _ = google.auth.default()
# validate ID token in credentials
if hasattr(credentials, "id_token") and credentials.id_token:
# return ID token if it is valid
return credentials.id_token
else:
# try to refresh ID token
auth_req = Request()
credentials.refresh(auth_req)
if hasattr(credentials, "id_token") and credentials.id_token:
return credentials.id_token
else:
# acquire ID token for current identity from metadata server
return id_token.fetch_id_token(auth_req, audience)
(NOTE: You will need to install google-auth
Python package to use the above code.)
The google.auth.default()
call intelligently searches for credentials in the local environment, checking the GOOGLE_APPLICATION_CREDENTIALS
environment variable; if that’s not found, it looks for credentials created with the gcloud CLI.
Then the code uses found credentials to validate and, if needed, to refresh the identity token.
If it fails to get a valid identity token from the local credentials, the code fetches a new identity token from the metadata server which stores the credentials of the attached service account.
Note that the last part works only when the application is deployed on Google Cloud.
The audience
argument provided to the fetch_id_token
call claims that the token is used to prove identity to Cloud Run service. The argument should contain the URL of the service you are calling.
This powerful chain of discovery is what makes the code so portable. The code returns the acquired identity token which you can use as a bearer token in the Authentication header of HTTP requests to a Cloud Run service. For the full end-to-end demonstration watch the Youtube video (pending reflink update).
For this code to work on your local machine, you only need to run one command:
gcloud auth application-default login
This securely stores your user credentials in a well-known location where the google.auth.default()
call can find them. You do not need to manage service account keys.
If you want to know how to retrieve identity token when you explicitly provide a service account key or use work with non-Google IdP that is synchronized with Google Cloud using Workload Identity, leave a comment to this post.
This post is mirrored to Medium.