How do I restrict access to Google Compute Engine to only my Firebase cloud functions - firebase

Is it possible to secure my service on Compute engine so that only my Firebase functions can access it using vpc / firewall rules?

Rather than using VPC/Firewalls to secure your GCE instance, you could use Identity-Aware Proxy, and have the function authenticate as a service account using the default service account for Cloud Functions (project_id#appspot.gserviceaccount.com). This is very robust against network changes, and is very flexible..

Related

Assign GCP functions service account roles to engage with Firebase using Terraform

I want to use the Firebase Admin SDK in my GCP cloud function, specifically for creating custom auth tokens.
I was getting auth/insufficient-permission errors after deployment and got to this thread. Note that it talks about Firebase functions, while I use pure GCP Cloud Functions.
To my understanding, GCP Cloud Functions uses the default App Engine service account, which is missing the Firebase Admin SDK admin service agent role.
I manually added it through the GCP console and it seems to solve the issue, but now I want to automate it via terraform where I manage my infrastructure.
How do I access the default App Engine service account? I think it's auto created when the GCP project is created.
How do I add the relevant role to it without changing other service accounts using that roles?
Is this it right approach, or is there a better way I'm missing?
The relevant documentation I was looking at is here. Note that I'm using initializeApp() without arguments, i.e. letting the library to discover the service account implicitly.
How to get the default App Engine service account through Terraform: google_app_engine_default_service_account
How to work with 'additional' IAM roles assigned to a service account:
IAM policy for service account
For general recommendations - I would prefer to use a specifically created service account and completely delete (or disable) the default App Engine service account.
Edit ==> Additional details as requested
Here is a description of Cloud Function service account in runtime:
The App Engine service account has the Editor role, which allows it broad access to many Google Cloud services. While this is the fastest way to develop functions, Google recommends using this default service account for testing and development only. For production, you should grant the service account only the minimum set of permissions required to achieve its goal.
Thus, it may be useful to delete/disable App Engine service account, create a specific service account for the given cloud function, assign it all relevant minimum of IAM roles, and use it.
As a side note I also would suggest to delete/disable the default Compute Engine service account, delete the default network with all firewall rules and subnetworks... But this is a separate story.

Firebase web SDK using custom domain for all httpsCallable requests

We have a React application using a Firebase backend. Several of our larger customers discovered that their network security blocks calls to certain URLs where the SSL certificate may be questionable. One URL that was commonly getting blocked was cloudfunctions.net which is used by Firebase Cloud Functions as the default cloud functions endpoint.
Rather than asking every potential customer to update their network security and whitelist cloudfunctions.net we instead need to have a more robust solution that will allow us to host cloud functions at our custom domain with a dedicated SSL certificate. The bulk of this solution should be handled by creating a GCP Static IP address, and using a GCP Load Balancer to reroute calls to this IP address through to our cloud functions.
There are many articles on SO about using Firebase Hosting to reroute calls to your custom domain through to your cloud functions, such as Use custom domain for firebase function http calls
What isn't as clearly documented is how to initialize the firebase-js SDK for your own React client to call a custom domain when using functions().httpsCallable as part of firebase.functions().
When making a request from our web app to cloud functions using httpsCallable:
const { data } = firebase.functions().httpsCallable('myFunction');
the default SDK behaviour makes a request to:
https://<region>-<firebase-project-id>.cloudfunctions.net/myFunction
The official docs make vague reference to initializing Firebase Functions with a region variable. They also share how to do this when initializing the client SDK here.
const functions = firebase().app().functions('region-string');
What I wanted to achieve was to change the default behaviour of the firebase-js SDK so that when making calls to cloud functions within my react client these requests would call my custom domain (I'm using a GCP load balancer to provide a custom domain endpoint for cloud functions).
It turns out that you can provide firebase-js SDK functions with a config of either a region OR a custom domain. This is shown in the SDK code repository here.
So to ensure your client always makes httpsCallable transactions to your custom domain you can initialize Firebase Functions like so:
firebase.initializeApp({
apiKey: '### FIREBASE API KEY ###',
authDomain: '### FIREBASE AUTH DOMAIN ###',
projectId: '### CLOUD FUNCTIONS PROJECT ID ###'
databaseURL: 'https://### YOUR DATABASE NAME ###.firebaseio.com',
});
// Initialize Cloud Functions through Firebase
const functions = firebase.app().functions('https://customdomain.com/');
NOTE: This solution requires you to have also configured DNS configuration to redirect your custom domain to a GCP Load Balancer. When combining a load balancer with a urlMap you can have calls to https://customdomain.com/myFunction routed to your myFunction cloud function.
The full transaction would look like:
client SDK -> httpsCallable -> custom domain -> GCP static IP -> GCP Load Balancer -> GCP urlMap -> GCP cloud functions Backend Network Group -> cloud functions.
You can find instructions for configuring a GCP load balancer and Serverless NEG here: https://cloud.google.com/load-balancing/docs/https/setting-up-https-serverless#cloud-functions
I hope this saves someone else much searching. I was surprised I needed to read the firebase-sdk code to find this out.

Traffic routing when accessing Firestore through Firebase Cloud Functions

Does accessing Firestore through Firebase cloud functions routes requests through Google internal network ?
Yes, request between Firestore through Cloud Functions use Google internal network to route its packages.
To provide a little bit more of context, as mentioned at locations on Firebase, Firebase uses GCP resources which are created as needed, this means that it also creates a VPC network as with any GCP project. As mentioned at VPC network overview, Google uses the internal network for resources in the same VPC network so in short, yes, Firebase end up using the Google internal network when communicating between functions and Firestore
Let me know if the clarified your doubts!

Which service account is used when running Firebase Cloud Functions?

I'm trying to create a schedule Cloud Function exporting my Firestore database to create backups. The code is running fine when serving on my local machine (which uses my personal user account with owner role) but failes once deployed. I already found out that I need to add the 'Storage Admin' and 'Datastore Import Export Admin' to the service account used when running the cloud function, but I can't figure out which service account is used for the functions.
Does anyone know which service account is used?
Firebase Cloud Functions use the {project-id}#appspot.gserviceaccount.com service account (App Engine default service account). Roles and permissions added to this service account carry over to the Cloud Functions runtime.
Good to know: When using Google Cloud Functions, the service account being used while running the function can be defined when deploying the function.
You can specify a custom service account with the runWith() method if you prefer not to use the default one nowadays. It accepts a number of RuntimeOptions that can be defined.

generating access token in Cloud Functions for service-service auth

I am trying to establish service-service authentication between Cloud Functions and Cloud Endpoints.
I am trying to send a HTTP request inside a Firebase Cloud Function to my API running on Google App Engine and managed by Google Cloud Endpoints.
As stated in google docs, the service account that Firebase Cloud Functions uses is ____#cloudservices.gserviceaccount.com
I added that issuer in the security definition of my openAPI config(cloud endpoints). However, I could not find a way to create an access token in Cloud Functions of that service account.
How can I generate an access token in Cloud Functions to authenticate itself to Cloud Endpoints? How am I supposed to sign the JWT on cloud functions to request an access token?
Use Application Default Credentials.

Resources