How to use the same IP address in different Google Cloud projects - firebase

I'm developping an app that uses Firebase (Google Cloud) for back-end application. The project containts several Firebase Functions that are used to get data from a third party that only accept one validated fixed IP address (which I managed to do via a VPC).
My start production is soon so I felt it would be a good time now to set two different environnements, one for developpement and one for production, which would mean two different Google Cloud projects (I want to separate the databases and the functions if I add some new features) with the same IP address. Is there a way to share this setting between two different Google Cloud projects ?

Here my idea, even if I never tested it.
On your current project, create 2 Internet network endpoint group (INEG).
INEG-prod that use the fully qualified url of your firebase prod environment
INEG-dev that use the fully qualified url of your firebase dev environment
Then create a Load balancer in the project where your IP address is reserved; Create 2 backend:
Backend-prod that use the INEG-prod
Backend-dev that use the INEG-dev
Then the URL map
use your /* (for example) to route the request to the backend-prod
use dev-/* (for example) to route the request to the backend-dev
On the frontend, use your static IP, and the HTTPS protocol.
It should work (wait about 5 minutes to let the HTTPS load balancer to take into account the configuration)

Related

Amazon API gateway not accessible using a custom domain name set up using Route 53

We are using an AWS API gateway for our APIs. These APIs are mapped to a custom domain name set up using Amazon Route53 and accessed through a frontend application hosted in amazon s3. We have 3-4 different environments for different stages (dev, stage, prod, etc). With the API domain being in the format stage.api.brighthub.io for other environments and api.brighthub.io for prod. The one in prod works fine, however, recently, the APIs in the other environment's are not accessible using the custom domain name. All the domain mappings and A records and CNAME records have been added in Route53 and it worked until a few days ago. The NS records for stage.api.brighthub.io have been added into brighthub.io. I have also referred this documentation - Routing traffic for subdomains and tried adding the NS records for stage.api.brighthub.io to api.brighthub.io, however, the API is still not accessible. There have been no major updates to the APIs either and suddenly they aren't accessible using the domain name. They can be accessed using the Invoke URL. I have also tested using another REST client, the same issue persists.
Can someone help with this or point to something to troubleshoot?

Cloud Run mapping services by URL path (using custom domain and wildcards)

I've been trying to migrate my solution from Google Cloud App Engine to Google Cloud Run and have been struggling a lot.
I have 3 services in app engine for each staging environment, let's call them api, front1, front2. front1 has custom domain name assigned www.example.com, as well as staging subdomain www.dev.example.com. Using dispatch.yaml rules I route requests to appropriate services, for example: requests containing api/* are routed to api service, default path routes to front1, /foo* routes to front2. Everything is working there perfectly well, however, hosting the solution on Cloud Run would decrease the costs a lot.
So at the moment, I am really struggling to understand how could I fully replicate this behavior in Cloud Run. I've tried following firebase routing, but it requires to host an app on Firebase as well and doesn't route all traffic for route /api/** to my api service.
I've tried following this article, but I cannot select my service since I selected Internet Network Ednpoint Group option for backend type, which only can point to a single url. Also, I am not sure if it will support wildcard routing there.
I'd highly appreciate any help here, I am totally out of options at the moment.

Can I add a domain to Firebase hosting via the API?

I want to be able to add domains to Firebase hosting with the API instead of the web UI, is that possible?
I want to add potentially hundreds of domains, is there a domain limit per project in Firebase?
As far as I can tell from the entire CLI documentation, there isn't any way to do this.
Lets take a step back and consider what the web UI process involves i.e. the generation of a TXT record to add to your DNS records, after verifying the presence of said TXT record on the domain, providing A records that you (authorized owner) add to allow redirecting to your firebase hosted site.
In my opinion, this very manual back and forth is necessary as a security measure. The only way it is taken out of the equation via the CLI is by providing a means for you to authenticate ownership of a domain (registered with any one of many domain registrars), and being granted authorization to change your A records. These are both outside the scope of Firebase, and could potentially introduce severe security flaws. Regardless, even if it existed, it would still have to be step-by-step and somewhat manual via CLI rather than the single command it sounds like you're looking for.
It is not possible to add custom domains automatically through an API at this time.
Nor would it allow you to create a reseller or multi-tenant project (i.e. connect a large number of domains or subdomains dynamically) since you cannot connect more than about 36 domains connected to one project.
It's possible to add domains using Firebase Hosting Rest Api. I am not sure why they didn't put it on their official website but I checked today and it works. https://developers.google.com/resources/api-libraries/documentation/firebasehosting/v1beta1/java/latest/com/google/api/services/firebasehosting/v1beta1/FirebaseHosting.Sites.Domains.html
Answer that I've received from Firebase support:
There is no API yet that would allow you to add custom domains, it was
requested as a feature before but unfortunately we have no more
information on that - so for now, only the Console UI allows you to do
it.
When it comes to the limits, in a project, a custom domain is
attached to a site - there can be 36 sites per project, and for one
site there is no hard limit, but we recommend not exceeding 20 custom
domains. You can experience technical issues with SSL certs when you
exceed 20 domains per site, which we won’t be able to troubleshoot
since the system was not designed for such use cases.

What is the origin of an external API call made by a firebase function?

I'm trying to make a call to an external api using a cloud function.
The external API requires me to register the origin of the call I am making with them.
For example https://mywebsite.com
What would the url to register with them be?
mywebsite.firebaseapp.com?
The domain name registered in firebase console, mywebsite.com?
Or something else like https://us-central1-mywebsite.cloudfunctions.net/functionName ?
When working with massively scalable cloud products like Cloud Functions, you don't have guarantees about where your network traffic appears to come from. Your source IP can (and will) change over time, and addresses of your project's DNS entries (for you cloudfunctions.net hostname) can be expected to change similarly.

Custom domain name with SSL on Firebase Storage

I was able to get a custom domain name mapped to my Firebase Storage bucket by simply naming the bucket the same name as my domain name and then pointing the CNAME record to c.storage.googleapis.com. However, https doesn't work because the common name on the certificate is different. Is it possible for me to upload a certificate or, even better, have GCP or Firebase manage a certificate?
I'm coming a bit late to the party and this question might have been answered elsewhere. However, since this was the first result I found when googling for this feature, here goes nothing:
For starters, let's say you have a CNAME like assets.somedomain.com pointing to c.storage.googleapis.com, and you create a bucket called assets.somedomain.com.
Then you upload a file, whose public url will look like:
https://firebasestorage.googleapis.com/v0/b/assets.somedomain.com/o/arduino.png?alt=media&token=asdf
Which can be seen as:
firebasestorage.googleapis.com/v0/b/
+
assets.somedomain.com
+
/o/
+
arduino.png?alt=media&token=asdf
You should be able to view said file using:
https://assets.somedomain.com/arduino.png?alt=media&token=asdf
Which is
assets.somedomain.com/
+
arduino.png?alt=media&token=asdf
(basically, you strip the original base URL and the /o/ prefix)
But of course you get a big fat warning telling you the certificate is invalid, because it's meant for *.storage.googleapis.com.
In my case, I was able to circumvent this using cloudflare's universal SSL, which acts like a proxy that asks no questions whatsoever.
You try again, but somewhere in the middle the request becomes anonymous and you get an XML stating that you lack the storage.objects.get permission.
<Error>
<Code>AccessDenied</Code>
<Message>Access denied.</Message>
<Details>
Anonymous users does not have storage.objects.get access to object.
</Details>
</Error>
This means that even with the token included in the query string the proxyed request has no permission. Next step, then, is to make the bucket publicly readable in Google Cloud Console -> Storage.
(This can be done using gcloud cli, but I found this method easier to explain)
Pay attention to use the legacy object reader permission, which stops visitors from actually listing the bucket contents.
After that, you should be able to access the image using:
https://assets.somedomain.com/arduino.png
Note that you don't even need to include "alt=media" because cloudflare will serve the file instead of its metadata.
Currently we don't support custom domains in Cloud Storage for Firebase.
You have two options:
Use Firebase Hosting (developer generated content)
Set this up via GCS static hosting (docs)
In either case though, you'll lose the ability to use the Firebase SDKs for Cloud Storage, as well as it's authentication and authorization functionality.
Happy to learn more about the use case to see if it's something we should support in the future.
Update April 2021
Firebase 8.4.0 introduces storage().useEmulator(host, port).
You'll still need a reverse proxy, which you can do with Google Cloud Load Balancer or others.
It's actually quite simple to achieve what you need - i.e to serve your storage content under your custom domain with SSL support. But you'd take a bit different approach.
They key here is that, as I was once prompted by firebase support, storage api is meant for internal usage of a developer, including the urls that point to files and they are not meant to be exposed to end users. That sounded kind of strange to me at first, but after I gave it a bit of though it started to make sense.
So here is how I solved it using the updated perspective.
You can create a dedicated endpoint which redirects to a cloud function.
That endpoint would accept a storage url as a parameter.
Then the cloud function would read the url and just stream its content back.
That's it.
No need for complex proxies setup etc. All your content will now be served under your custom domain.
Here is a brief example of how the core logic of such a function may look like:
(req, res, next) => {
let link = req.query.url
const https = require('https');
//request the content of the link
https.get(link, response => {
if (response.statusCode < 200 || response.statusCode > 299) {
//handle error
} else {
//stream the content back to client
response.pipe(res)
res.on("close", () => response.destroy())
}
});
}
Now you can do something like this (assuming your function is hosted under 'storage/content'):
let contentUrl = https://my-custon-domain.com/storage/content?url={{put your storage url that refers to a file}}
and then for example assign that url to the iframe src
<iframe :src="contentUrl"/> //this is how one will do it in Vue.js
Opening such a link in a browser will display your file content (or download it depending on the browser's settings)
I'll post a more detailed explanation with examples if this answer gets more attention.
I perfectly agree to the previous answer and thanks a lot for that. But I am writing the instruction in a better fashion
Create a bucket with you custom domain name in google cloud platform-> Storage.
Create a permission of legacy object viewer and add it to all users.Note:you have to search legacy object viewer from the filter text
Add a DNS record in your domain service provider account with CNAME assets which will point to c.storage.googleapis.com.
Create a cloudflare account if you do not have
Add website in cloudflre where you need to put your domain name not the subdomain
Copy the nameserver details from cloudflare to your DNS service providers nameserver details
It will take some time to move all the dns records in cloudflare.
Goto page rules in cloudflare and add assets.yourdomain.com and turn on always use https
You are done
For GCloud users,
Just go to console,
Open Load Balancing
Provide an alias and handle your mapping assets.yourdomain.com
points to */images/
It will create a new balancer with ip address and it is
multi-regional don't worry.
Open Cloud CDN, give alias and select your created balancer.
Select your bucket name which is your firebase-storage's bucket
name.
Go to your domain provider like GoDaddy and put this ip address which points
assets.yourdomain.com to balancer's ip.
To sum up;
Google is handling certification progress and it gives you an ip, you add A record which points to given ip.
When you visit assets.yourdomain.com it goes to Google and Google points to your bucket.
It takes 5mins to complete but I have spent 1 week to understand how does it work :)
Using Firebase Storage means you are using a GCP Cloud Storage Bucket.
Using GCP Load Balancing feature, you can basically expose your GCP Storage Bucket to a public IPv4. And manage SSL certificates.
Then, you go to your domain provider console and add an "A record" to your Bucket IP.
Here is a great post : https://deliciousbrains.com/wp-offload-media/doc/how-to-set-up-a-custom-domain-cdn-for-google-cloud-storage/
GCP = Google CLoud Platform
Note that GCP Load Balancing is not free.

Resources