I have a React web application hosted on Firebase hosting that utilizes a Python API hosted on Cloud Run. Currently, the API is public, and I would like to restrict access to it so that only calls made from my React application can access it.
I believe the solution involves configuring the networking and security settings in Cloud Run, but as a novice, I am not quite sure how to proceed.
Could someone provide me with a reliable source to learn more about this topic or help me find a solution to this problem?
Thank you and have a great day.
We have a guide on private networking on Cloud Run. Please let us know if you have any questions - https://cloud.google.com/run/docs/securing/private-networking
1 Like
- Deploy your Cloud Run service as a private service. As Google documentation says
Private services cannot be directly loaded by a web browser. Instead, use curl or a similar HTTP request CLI tool that allows injecting an Authorization header.
This means the url canāt be accessed directly e.g. by typing it in a browser. We have a blog article with step by step instruction for deploying your Cloud Run service as private.
- Now that your Cloud Run service is restricted, you basically need to get an ID token and add it when youāre making the call to the Cloud Run service (this means you add it to your code for the React Web application for when it invokes the Cloud Run url).
- See this example from Google.
- Also see this documentation from Google which explains service-to-service authentication which is what your Firebase App will be doing to the Cloud Run url.
⦠NoCommandLine ā¦
https://nocommandline.com
A GUI for Google App Engine
2 Likes
The problem is that firebase hosting does not support VPC. It is therefore impossible to create a VPC between firebase hosting and cloud run.
Hi there!
Thanks for your reply, I did indeed do it that way.
I allowed my firebase service account to access cloud run. I then retrieve the tokenID with the following code :
async function getIdTokenFromMetadataServer() {
const googleAuth = new GoogleAuth({
keyFilename: ā./compte.jsonā
});
const client = await googleAuth.getClient();
// Get the ID token.
// Once youāve obtained the ID token, you can use it to make an authenticated call
// to the target audience.
let Token = await client.fetchIdToken(url);
console.log(Token);
const response = await axios.get(url, {
headers: {
āAuthorizationā: Bearer ${Token}
}
});
console.log(response);
}
getIdTokenFromMetadataServer();
There is still a security flaw. I need to have the JSON file containing the private key for the firebase service account on the client side.
Do you have any idea how to fix this?
Hi,
If youāre running this on Googleās servers, I donāt believe you need to specify a JSON file containing the key. The system will automatically pick up the ādefaultā service account (if you look at the example I linked to in my response, thereās no service account).
⦠NoCommandLine ā¦
https://nocommandline.com
A GUI for Google App Engine
1 Like
Okk I get it, thanks for your reply and for the time you took.
Iāll get back to you once Iāve managed to deploy the code on firebase hosting. I have one last error with the following line of code: sded
This line creates a large number of errors in my react code and I donāt know why. However, with node locally it works very well.
const { GoogleAuth } from āgoogle-auth-libraryā; *
Iām not a React person but the above code looks incorrect to me. I think it should be
const {GoogleAuth} = require('google-auth-library');
or
import { GoogleAuth } from 'google-auth-library';
⦠NoCommandLine ā¦
https://nocommandline.com
A GUI for Google App Engine
@NoCommandLine You still need to change the ingress setting on cloud run to āallow and internal and LBā or does it really not matter?
No. You donāt have to do anything like that. A Cloud Run service that is deployed as Private is automatically not available when you type its url in a browser. You should also take a look at this response
⦠NoCommandLine ā¦
https://nocommandline.com
A GUI for Google App Engine
Okay. So in this case āprivate accessā is achieved by enforcing the calling service to generate a access token to be able to call the CR service?
I donāt understand your question. Have you taken a look at the linked posts/articles?
My previous response to you includes working code (deploying a cloud run service as private and confirming it isnāt accessible when you type the url in a browser. In fact, in Google cloud console, youāll see the entry āRequire authenticationā for the deployed service)
⦠NoCommandLine ā¦
https://nocommandline.com
A GUI for Google App Engine
Yes i have taken a look at the post. What i understand there are several ways to enforce private access one of them is via code using a access token to invoke the service but there is also a ingress setting that can be used (this is an infra side change) by setting to āinternalā only but beyond that it is not clear.
Hi @NoCommandLine , I have an Frontend Standard App Engine service which needs to be connected to backend Cloud Run service through the Serverless VPC connector. The Cloud Run was able to connect Serverless VPC connector as its direct in UI whereas my App Engine was not able to. I have added the vpc_connector attribute to app.yaml file and using the default Service Account which has Editor role (has excess permissions) and also added " Serverless VPC Access User and Compute Viewer " permissions for my App Engine service account but during the deployment it shows ācompute.globalOperations.getā and āvpcaccess.connectors.useā permissions error.