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 therefore 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 principal
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.
Click Add principal.
Enter the identity of the calling service. This is usually an email address, by default
[email protected]
.Select the
Cloud Run Invoker
role from the Select a role drop-down menu.Click Save.
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
[email protected]
.
Terraform
To learn how to apply or remove a Terraform configuration, see Basic Terraform commands.
The following Terraform code creates an initial Cloud Run service intended to be public.
Replace us-docker.pkg.dev/cloudrun/container/hello
with a reference to your container image.
The following Terraform code makes the initial service public.
The following Terraform code creates a second Cloud Run service intended to be private.
Replace us-docker.pkg.dev/cloudrun/container/hello
with a reference to your container image.
The following Terraform code makes the second service private.
The following Terraform code creates a service account.
The following Terraform code allows services attached to the service account invoke the initial private Cloud Run service.
Acquire and configure the ID token
After you grant the proper role to the calling service account, follow these steps:
Fetch a Google-signed ID token by using one of the methods described in the following section. Set the audience claim (
aud
) to the URL of the receiving service or a configured custom audience. If you are not using a custom audience, theaud
value must remain as the URL of the service, even when making requests to a specific traffic tag.Add the ID token you fetched from the previous step into one of the following headers in the request to the receiving service:
- An
Authorization: Bearer ID_TOKEN
header. - An
X-Serverless-Authorization: Bearer ID_TOKEN
header. You can use this header if your application already uses theAuthorization
header for custom authorization. This removes the signature before passing the token to the user container.
- An
For other ways to get an ID token that are not described on this page, see Methods for getting an ID token.
Use the authentication libraries
The easiest and most reliable way to acquire and configure the ID token process
is to use the authentication libraries.
This code works in any environment, even outside of Google Cloud,
where the libraries can obtain authentication credentials for a service
account, including environments
that support local Application Default Credentials.
To set
Application Default Credentials,
download a service account key file, and
set the environment variable GOOGLE_APPLICATION_CREDENTIALS
to the path of the
service account key file. For more information, see
How Application Default Credentials works.
This code does not work for obtaining authentication credentials for a user account.
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 or a configured custom audience.
The following table summarizes the main parts of a metadata query request:
Components | Description |
---|---|
Root URL | All metadata values are defined as sub-paths below the following root URL: http://metadata.google.internal/computeMetadata/v1 |
Request header | The following header must be in each request: Metadata-Flavor: Google This header indicates that the request was sent with the intention of retrieving metadata values, rather than unintentionally from an insecure source, and lets the metadata server return the data you requested. If you don't provide this header, the metadata server denies your request. |
For an end-to-end walkthrough of an application using this service-to-service authentication technique, follow the securing Cloud Run services tutorial.
Use workload identity federation from outside Google Cloud
If your environment uses an identity provider supported by workload identity federation, you can use the following method to securely authenticate to your Cloud Run service from outside Google Cloud:
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.
You can include the ID token from the previous step in the request to the
service by using an Authorization: Bearer ID_TOKEN
header or an X-Serverless-Authorization: Bearer ID_TOKEN
header. If
both headers are provided, only the X-Serverless-Authorization
header is checked.
Use a downloaded service account key from outside Google Cloud
If Workload Identity Federation is not appropriate for your environment, you can use a downloaded service account key to authenticate from outside Google Cloud. Update your client code to use the authentication libraries as described previously with Application Default Credentials.
You can acquire a Google-signed ID token by using a self-signed JWT, but this is quite complicated and potentially error-prone. The basic steps are as follows:
Self-sign a service account JWT with the
target_audience
claim set to the URL of the receiving service or a configured custom audience. If not using custom domains, 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 preceding URL.Include the ID token in the request to the service by using an
Authorization: Bearer ID_TOKEN
header or anX-Serverless-Authorization: Bearer ID_TOKEN
header. If both headers are provided, only theX-Serverless-Authorization
header is checked.
Receive authenticated requests
Within the receiving private service, you can parse the authorization header to receive the information being sent by the Bearer token.
Python
What's next
- Learn more about ID token validation