If your architecture is using multiple services, these services likely need to communicate with each other, using either asynchronous or synchronous means. Many of these services may be private and require credentials for access.
For asynchronous communication, you can use the following Google Cloud services:
- Cloud Tasks for one to one asynchronous communication
- Pub/Sub for one to many, one to one, and many to one asynchronous communication
- Cloud Scheduler for regularly scheduled asynchronous communication
- Eventarc for event-based communication
In all of these cases, the service used manages the interaction with the receiving service, based on the configuration you set up.
But for synchronous communication, your service calls another service
directly, over HTTP, using its endpoint URL. For this use case, you should make
sure that each service is only able to make requests to specific
services. For example, if you have a login
service, it should be able
to access the user-profiles
service, but not the search
service.
In this situation, Google recommends that you use IAM and a service identity based on a per-service user-managed service account that has been granted the minimum set of permissions required to do its work.
In addition, the request must present proof of the calling service's identity. To do this, configure your calling service to add a Google-signed OpenID Connect ID token as part of the request.
Set up the service account
To set up a service account, you configure the receiving service to accept requests from
the calling service by making the calling service's service account a member
on the receiving service. Then you grant that service account the Cloud Run Invoker
(roles/run.invoker
) role. To do both of these tasks, follow the instructions in the appropriate tab:
Console UI
Go to the Google Cloud console:
Select the receiving service.
Click Show Info Panel in the top right corner to show the Permissions tab.
In the Add members field, enter the identity of the calling service. This is usually an email address, by default
PROJECT_NUMBER-compute@developer.gserviceaccount.com
.Select the
Cloud Run Invoker
role from the Select a role drop-down menu.Click Add.
gcloud
Use the gcloud run services add-iam-policy-binding
command:
gcloud run services add-iam-policy-binding RECEIVING_SERVICE \ --member='serviceAccount:CALLING_SERVICE_IDENTITY' \ --role='roles/run.invoker'
where RECEIVING_SERVICE
is the name of the receiving
service, and CALLING_SERVICE_IDENTITY
is the email
address of the service account, by default
PROJECT_NUMBER-compute@developer.gserviceaccount.com
.
Acquire and configure the ID token
Once the calling service account has been granted the proper role, you need to:
Fetch a Google-signed ID token with the audience claim (
aud
) set to the URL of the receiving service. Theaud
value should remain as the URL of the service, even when making requests to a specific traffic tag.Include the ID token in an
Authorization: Bearer ID_TOKEN
header in the request to the receiving service.
The easiest and most reliable way to manage this process is to use the authentication libraries, as shown below, to generate and use this token. This code works in any environment - even outside of Google Cloud - where the libraries can obtain authentication credentials, including environments that support local Application Default Credentials.
Node.js
Python
Go
Java
Use the metadata server
If for some reason you cannot use the authentication libraries, you can fetch an ID token from the Compute metadata server while your container is running on Cloud Run. Note that this method does not work outside of Google Cloud, including from your local machine.
curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=[AUDIENCE]" \
-H "Metadata-Flavor: Google"
Where AUDIENCE is the URL of the service you are invoking.
For an end-to-end walkthrough of an application using this service-to-service authentication technique, follow the securing Cloud Run services tutorial.
Call from outside Google Cloud
You can call a private service from outside Google Cloud using workload identity federation or by using a downloaded service account key. Both methods are described in the following sections.
Use workload identity federation
If your environment uses an identity provider supported by workload identity federation, you can use this method to securely authenticate to your Cloud Run service:
Set up your service account as described in Set up the service account on this page.
Configure workload identity federation for your identity provider as described in Configuring workload identity federation.
Follow the instructions in Granting external identities permission to impersonate a service account.
Use the REST API to acquire a short-lived token, but instead of calling
generateAccessToken
to obtain an access token, callgenerateIdToken
instead to get an ID token.For example, using cURL:
ID_TOKEN=$(curl -0 -X POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT:generateIdToken \ -H "Content-Type: text/json; charset=utf-8" \ -H "Authorization: Bearer $STS_TOKEN" \ -d @- <<EOF | jq -r .token { "audience": "SERVICE_URL" } EOF) echo $ID_TOKEN
Where
SERVICE_ACCOUNT
is the email address of the service account the workload identity pool is configured to access, andSERVICE_URL
is the URL of the Cloud Run service you are invoking. This value should remain as the URL of the service, even when making requests to a specific traffic tag.$STS_TOKEN
is the Security Token Service token you received in the previous step in the workload identity federation instructions.
Once you have the ID token, you can include it in an
Authorization: Bearer ID_TOKEN
header in the request to the receiving service.
Use a downloaded service account key
If workload identity federation is not appropriate for your environment, you can use a downloaded service account key to authenticate. Update your client code to use the authentication libraries as described above with Application Default Credentials.
You can acquire a Google-signed ID token using a self-signed JWT, but this is quite complicated and potentially error-prone. The basic steps are:
Self-sign a service account JWT with the
target_audience
claim set to the URL of the receiving service. Thetarget_audience
value should remain as the URL of the service, even when making requests to a specific traffic tag.Exchange the self-signed JWT for a Google-signed ID token, which should have the
aud
claim set to the above URL.Include the ID token in an
Authorization: Bearer ID_TOKEN
header in the request to the service.
You can examine this Cloud Functions example for a sample of the above steps.