How to use GCP KMS with Firebase and Firebase Cloud Functions - firebase

I need some advice on how to properly set up a solid security structure for my app.
What my app does
The goal of this app is to provide a data aggregation service.
To do this, the user needs to provide login data for a variety of his accounts.
The user can then trigger a firebase cloud function which performs web scraping with the provided credentials, encrypts the result-data, and stores it to firestore.
Current encryption
Currently, the encryption key is stored in a separate document in the firestore database.
The cloud function gets the key, performs de- and encryption, and stores the data as a cipher.
Now I know this is kind of pointless because if someone would hack my Google account, the data would still be readable for him.
Problems
Besides this security flaw, I am facing some other problems.
As long as the described encryption only happens in a cloud function, this may be relatively secure because the cloud functions are isolated. My problem is, that there is no way to perform a database query from the client because:
there is no "onRead" cloud function, in which I would decrypt the data before sending it to the client
decrypting the data on the client would expose the encryption key to potential hackers (at least that's what I am thinking at the moment)
Conclusion
I have decided to try GCP's KMS which seems to be the solution to all of these problems. However, I am overwhelmed by all these new terms and most of the resources I found seemed outdated.
Closest I came was this post: http://www.geero.net/2017/05/how-to-encrypt-a-google-firebase-realtime-database/ but since it's from 2017, it seems to be outdated (As far as I understand from this answer)
So I am a bit lost on where to start, what to use, and how to manage responsibilities.
Questions
Is it possible to create a secure client-sided decryption with KMS? If
not, how should this get handled?
How do I implement KMS with firebase and firebase cloud functions? (Any pointing in the right
direction would help)
Do you recommend using this package for the cloud function
implementation: https://www.npmjs.com/package/#google-cloud/kms
Did you spot and other security flaws than those I mentioned?
Do you have any additional advice?
Thanks in advance!

Related

What to do about this warning email from Google: Publicly accessible Google API key for Google Cloud Platform?

As the title states, I've gotten this email for both projects I've made public on Github. One is a landing page for a local business and the other is a CRUD app I have on the App Store; both of which are using Firebase as the backend.
Is the API key being visible on Github such a security risk?
I've done some research after following the instructions in the email to restrict my API and have heard that you cannot make web service requests with a restricted API key.
I just want to show my repos for the projects for the application process and obviously don't want anything bad to happen with them by doing so.
Aren't Firebase APIs meant to be public?
If so, is it just my database rules that need to be stronger/more verbose?
If any more context is needed, please let me know!
Cheers!
NOTE: I'm still very new to programming so a lot of this is over my head
For Firebase apiKey in a web app you are intended to make this key public, so you should ignore this email -- see: https://stackoverflow.com/a/37484053/771768
Hopefully Best practices for securely using API keys helps.
I'm uncertain as to what you're doing specifically that's resulting in the email but it is warranted.
Please be very careful with API keys.
As the name suggests, these are like keys in that they unlock access to stuff. With digital keys, the additional challenge is that, once obtained, infinite copies of the key may be distributed (and these are usable until the API key is revoked).
There are (often) other (complementary|alternative) ways to authenticate APIs but, as I think you've discovered, sometimes you are required to use API keys.
In the case where they're required, you should endeavor to use complementary authentication mechanisms too in order to try to mitigate overuse and you should continue to be very judicious in your publication of these keys.
I suspect you should not be including (any) keys (ever) in your GitHub repos.
One rule of thumb is that vendors (like Google) use API keys as a way to limit access to (often paid) resources. If the vendor is giving you a key, they're often (not always) using the key as a way to determine how to charge you for an API too. If you're giving the key to others, you're giving other people the possibility of potentially incurring charges on your behalf.
I don't wish to scare you but I would like you to leave this question being very cautious when using keys even if only this causes you to read up more on the consequences of using them.

Should I query my Firebase database directly, or use Cloud Functions?

I am still new to solo-writing a back-end to my app so I have some concerns,
the concern I am asking about here is a security concern about sharing my database structur in the client app,
As it is known all code that is written on client side is "not safe from interested clients",
I read this medium post by Doug Stevenson from the firebase team,
What I am looking for exactly is an answer to the title of my question (which is the same title as the post on medium):
Should I query my Firebase database directly, or use Cloud Functions?
but I didn't really get an answer as he said that it depends on the situation and requirements of my app,
So can anyone tell me if it is ok,from a security perspective, to do direct queries on the client side that expose the structure of data in my database (firestore), or should I use instead only cloud functions for this?
notes:
I am aware that real-time data can only be achieved using client-sdks and thus I should give up that feature if I don't want to share my database structure in the client app
Allowing direct client access is as safe as you choose to make it.
There's nothing about the structure of data that's not secure. Your implementation lacks security only if users are able to do things that you didn't intend for them to do. That's entirely up to you to implement with security rules. If your rules accurately express what users should and should not be able to do, you will have no problem. If you are unable to use security rules to meet your needs, then you should force access through a backend.

Firebase Cloud Functions Secure HTTPS Endpoints with API key

I've looked at a few places, Including this post and the firebase panel
Is there no way to use these api's to secure these endpoints using an api key you create per client who uses your cloud functions?
I'm able to block every one putting a restriction on the Browser key, but I would like to create a new api key, and use that as a way to authenticate my endpoint for various clients.
Creating a new api key, and using that as a parameter in my query doesn't work (don't now if I'm doing anything wrong)
Is there a way to do this?
Option 1: handle authentication within the function
https://github.com/firebase/functions-samples/tree/master/authorized-https-endpoint
Adapt above to use clients/keys stored in firestore
Option 2: Use an an API Gateway
Google Cloud Endpoints (no direct support for functions yet, need to implement a proxy)
Apigee (higher cost, perhaps more than you need)
Azure API Management (lower entry cost + easy to implement as a facade for services hosted outside Azure)
there are more..
The above gateways are probably best for your use case in that the first two would let you keep everything within Google, albeit with more complexity/cost -- hopefully Endpoints will get support for functions soon. Azure would mean having part of your architecture outside Google, but looks like an easy way to achieve what your after (api key per client for your google cloud / firebase functions)
Here's a good walkthrough of implementing Azure API Management:
https://koukia.ca/a-microservices-implementation-journey-part-4-9c19a16385e9
Not to achieve what you are after, as far as firebase and GCP is concerned your clients is your specific business problem.
One way you could tackle this (with the little information that is provided);
You need somewhere to store a list of clients + their API key (I would use firestore)
For the endpoints you want to secure with a client-specific API key you can include a check to confirm the header exists and also exists in your firestore client record.
Considerations:
Depending on your expected traffic loads and the the number of firestore reads you'll be adding, you might want to double check this kind of solution will work for your budget.
Is the API-key type solution the only option you must go for? You Could probably get pretty far using the https://github.com/firebase/firebaseui-web and doing user checks in your function with no extra DB read required. If you go down this path most of the user signup/ emails / account creation logic is ready to go.
https://firebase.google.com/docs/auth/web/password-auth#before_you_begin
Curious to see what some other firebase users suggest.

Is it a good idea to use an additional server with Firebase?

I've never used Firebase (or Firestore) before and I'm considering using it for my new mobile application. And I'm wondering if using Firebase only, without any additional server is a good idea. Firestore does a lot of things I guess, like authentication, security and scalability. So I really hesitate putting an another server into Architecture. But I have a plan to do many server-side stuffs like searching for text or calculating something.
I think the answer is "it depends", but I want to hear some advices from people who have used Firebase before about this topic. Thank you in advance!
Is it a good idea to use an additional server with Google Firebase?
Firebase will help you build apps fast, without managing infrastructure. So you'll be able to focus on your app development and not on how to maintain servers. Perhaps, if you have requirments that Firebase cannot handle, which I doubt it, you can use an additional server.
I've never used Google Firebase (or Firestore) before and I'm considering using it for my new mobile application.
If you have never used the Firebase suite, I recommend you get started by reading the official documentation. Before starting to use Cloud Firestore, I recommend first get more familiar with NoSQL databases.
And I'm wondering if using Firebase only, without any additional server is a good idea.
There are many apps out there that are not using any other server than Firebase.
Firestore does a lot of things I guess, like authentication, security and scalability.
Firestore is a scalable NoSQL cloud database that allow you to store and sync data for client- and server-side development. It does not authenticate users. For that, there is another product named Firebase Authentication that I encourage you to use it.
But I have a plan to do many server-side stuffs like searching for text or calculating something.
Here you can find more details about Firestore search options. Regarding calculations, you can do pretty much everything you can do in a regular SQL database.

Understanding the Firebase and purpose of google cloud functions

Let's say I'm developing app like Instagram: for iOS, Android and Web. I decided to use Google Firebase as it really seems to simplify the work.
The features user needs in the app are:
Authorization/Registration
Uploading photos
Searching for other people, following them and see their photos
I come from traditional "own-backend" development where I do need to setup a server, create database and finally write the API to let the frontend retrieve the data from the server. That's the reason why it's unclear to me how it all works in Firebase.
So the question is how can I create such app:
Should I create my own API with cloud functions? Or it's ok to work with the database directly from the client-side?
If I work with the database directly why do I need cloud functions? Should I use them?
Sorry for such silly questions, but it is really hard to get from scratch.
The main difference between Firebase and the traditional setup you describe is that with Firebase, as far as the app developer is concerned, the client has direct access to the database, without the need for an intermediate custom API layer. Firebase provides SDKs in various languages that you would typically use to fetch the data you need / commit data updates.
You also have admin SDKs that you can use server-side, but these are meant for you to run some custom business logic - such as analytics, caching in an external service, for exemple - not for you to implement a data fetching API layer.
This has 2 important consequences:
You must define security rules to control who is allowed to read/write at what paths in your database. These security rules are defined at the project level, and rely on the authenticated user (using Firebase Authentication). Typically, if you store the user profile at the path users/$userId, you would define a rule saying that this node can be written to only if the authenticated user has an id of $userId.
You must structure your data in a way that makes it easily readable - without the need for complex database operations such as JOINs that are not supported by Firebase (you do have some limited querying options tough).
These 2 points allow you to skip the 2 main roles of traditional APIs: validating access and fetching/formatting the data.
Cloud functions allow you to react to data changes. Let's say everytime a new user is created, you want to send him a Welcome email: you could define a cloud function sending this email everytime a new node is appended to the users path. They allow you to run the code you would typically run server-side when writes happen, so they can have a very broad range of use-cases: side-effects (such as sending an email), caching data in an external service, caching data within Firebase for easier reads, analytics, etc..
You don't really need a server, you can access the database directly from the client, as long as your users are authenticated and you have defined reasonable security rules on Firebase.
In your use case you could, for example, use cloud functions to create a thumbnail when someone uploads a photo (Firebase Cloud Functions has ImageMagick included for that), or to denormalize your data so your application is faster, or to generate logs. So, basically you can use them whenever you need to do some server side processing when something changes on your database or storage. But I find cloud functions hard to develop and debug, and there are alternatives such as creating a Node application that subscribes to real time changes in your data and processes it. The downside is that you need to host it outside Firebase.
My answer is definitely NOT complete or professional, but here are the reasons why I choose Cloud Functions
Performance
You mentioned that you're writing an instagram-like mobile device app, then I assume that people can comment on others' pictures, as well as view those comments. How would you like to download comments from database and display them on users' devices? I mean, there could be hundreds, maybe thousands of comments on 1 post, you'll need to paginate your results. Why not let the server do all the hard work, free up users' devices and wait for the results? This doesn't seem like a lot better, but let's face it, if your app is incredibly successful, you'll have millions of users, millions of comments that you need to deal with, server will do those hard jobs way better than a mobile phone.
Security
If your project is small, then it's true that you won't worry about performance, but what about security? If you do everything on client side, you're basically allowing every device to connect to your database, meaning that every device can read from/write into your database. Once a malicious user have found out your database url, all he has to do is to
firebase.database().ref(...).remove();
With 1 line of code, you'll lose all your data. Okay, if you say, then I'll just come up with some good security rules like the one below:
This means that for each post, only the owner of that post can make any changes to it or read from it, other people are forbidden to do anything. It's good, but not realistic. People are supposed to be able to comment on the post, that's modifying the post, this rule will not apply to the situation. But again, if you let everybody read/write, it's not safe again. Then, why not just make .read and .write false, like this:
It's 100% safe, because nobody can do anything about anything in your database. Then, you write an API to do all the operations to your database. API limits the operations that can be done to your database. And you have experience in writing APIs, I'm sure you can do something to make your API strong in terms of security, for example, if a user wants to delete a post that he created, in your deletePost API, you're supposed to authenticate the user first. This way, 'nobody' can cause any damage to your database.

Resources