As the user interface container does not need any configuration, you do not need to configure any environment variables. It will also run without needing any additional permissions, so you do not need to configure any IAM roles. However, by default, it will use the default service account for the project which has more permissions than is needed. You can create a new service account with the minimum permissions needed and use that instead to follow the security principle of least privilege.
This will open the UI in a browser; however, it will not be able to talk to the API, as the API is not yet deployed. This is one way of hosting the UI, and it may be useful for testing purposes. However, Cloud Run is relatively expensive in this case as you are paying for compute when you don’t need to; the website is static.
Hosting the UI in a Cloud Storage Bucket
While you can use Cloud Run to host the UI, there is an easier and cheaper alternative; keeping to cloud native principles, you should always be considering simpler and more cost-effective alternatives when available. You can host the UI in a Cloud Storage bucket.
How much will this cost?
Cloud Storage offers a highly cost-effective option for hosting static websites because it charges only for storage (which is minimal for static sites) and network egress. Cloud Storage is designed to provide high scalability and availability, making it a great choice for serving high-traffic websites.
If you were to use Cloud Run, you would still be paying for egress costs, but you would also be paying for compute time, which is not needed for a static website.
Although storage costs will be negligible, check the Cloud Storage pricing site for current pricing, especially of data egress, as the files are served to your users.
Configuring the API
A template OpenAPI configuration is in the project directory named api.yaml.template. This contains placeholders for project-specific information such as the project ID and the URLs of the Cloud Run services.
The project ID is substituted for the placeholder ${PROJECT_ID} in two places that are used to create the JWT that is used for authentication. The x-google-issuer is the issuer of the JWT and the x-google-audiences is the audience of the JWT. Both of these contain the project ID.
By default, the API Gateway will pass the {id} parameter as a query parameter, and the service will not know how to deal with it, so you need to use the path_translation option to ensure the parameter is passed in the path. With this in place, the underlying Cloud Run service will receive the request at the URL https://fact-service-<instanceid>.a.run.app/api/facts/{id} with the {id} parameter in the path, as expected.
Tip
When authenticating with the Cloud Run alone, the JWT of the authenticated user is passed in the Authorization header. When using the API Gateway, the Authorization header contains a JWT for the service account the API Gateway uses.
This is because the API Gateway is not able to validate the JWT of the user, as it does not have the public key to validate the JWT. The API Gateway will validate the JWT of the service account and then pass the JWT of the user in the x-forwarded-authorization header to the Cloud Run service. In the services previously created, the code checks both the Authorization and x-forwarded-authorization headers for the JWT of the user.
With the API configuration complete, you can deploy it to the API Gateway.