This is part 3 in a series on serverless computing. For the previous parts click below:
In this post I will give a brief overview of Google Cloud’s (GCP) serverless offering.
Firebase
GCP offers a number of managed services that you can combine to create a serverless application. They also conveniently packaged a bunch of them together (auth, database, storage, hosting, functions, …) into a product named Firebase which comes with its own console, SDK, and CLI.
Isolated environments
In GCP there is the concept of a project which allows you to isolate and manage groups of resources (similar to an AWS account). Though you can create projects in GCP with a stand alone google account, you probably want to group and manage your projects under an organization. The simplest way to do this is to create a G Suite account and to create the projects under it.
Though you can create a project through the GCP console, we need to use the Firebase console to create a Firebase project. Projects created through Firebase will show up in the Firebase console while standard GCP projects will not. All projects (Firebase or standard) will show up in the GCP console, and if your Firebase project is setup on the Blaze plan then you can extend it to take advantage of GCP services outside of Firebase.
Creating a new Firebase project is as easy as going to the Firebase console and clicking “Add project”. When you create it you will pick a region where the project will live. Take time to consider your choice because you can’t change it later. You will probably want to pick a multi-region one for high availability in production.
Once it is created you can visit the project settings to allow varying levels of access to other users as shown in the screenshot below.
After you have created a project per environment (dev, test, prod) you can switch between them with the project dropdown at the upper left of the screen as shown in the screenshot below.
Infrastructure Automation
For infrastructure automation GCP provides Deployment Manager (similar to AWS Cloud Formation). With Deployment Manager you define your resources in YAML, Jinja2, or Python files. This is the general purpose infrastructure automation tool for GCP for Firebase we can just use the CLI.
The Firebase CLI reads configuration that is specified in the firebase.json
file that is created when you run firebase init
. It is a pretty simple file that specifies where your code is for each type of resource. You can use the CLI to run local via firebase serve
or to deploy via firebase deploy
. For each you can scope the action to a specific resource by adding a flag like --only functions
or --only hosting
.
The following is a “firebase.json” for firestore, functions, and hosting.
{
"firestore": {
"rules": "firestore/firestore.rules",
"indexes": "firestore/firestore.indexes.json"
},
"functions": {
"predeploy": "npm --prefix \"$RESOURCE_DIR\" run build",
"source": "functions"
},
"hosting": {
"public": "dist/client",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
Serverless Authentication
Firebase provides a managed authentication solution that supports a slew of federated identity providers as well as basic email and password. Through the Firebase console you can manage the sign-in methods and the users.
Now the user management is pretty basic, enabling you to manage usernames and passwords. Below is a screenshot of the user management console.
The auth console doesn’t provide any advanced features like grouping users or adding metadata to them. The recommended solution for organizing your users and building out their profile is to associate a record in the database with their UID.
So, if we are using Firestore, then we create a “users” collection and create a user profile where its document id is the user’s UID. Below is a screenshot of just that.
We can then put anything we want on their profile including a tenant id and a list of roles. This profile is easily accessed via the user’s UID when they try to access various resources. Alternatively we can customize our JWT on sign-in to have it contain the relevant information from the user’s profile.
Serverless Hosting
The standard solution in GCP for static site hosting would be to drop your site in a cloud storage bucket and point a domain to it. Firebase offers a nicer solution where it puts your content on GCP’s global CDN with zero configuration SSL.
That hosting is setup when you initialize the firebase project via the CLI (firebase init
). It generates a firebase.json
file which you can modify to specify which files get deployed and any rewrite rules that you desire.
Through the Firebase hosting console you can connect a domain and view the version history for past deployments. It even lets you rollback to previous deployments if you like. Below is a screenshot of the hosting console.
Serverless Database
Firebase’s original database solution is “Realtime Database” but it is generally recommended to use the newer solution “Firestore”. Firestore is basically GCP’s Datastore solution with real-time subscription capabilities. It is a fully managed NoSQL document database that can be conveniently access via the Firestore SDK.
The Firestore console allows you to manage the data, indexes, and rules for the database. Though you can manage the rules through the console you will want to make sure and save them in your project so they can be versioned and consistently deployed. However, for development, it can be nice to use the console since it has a simulator that lets you test your rules.
The rules are pretty simple. You define a path with potential wildcard matching and associated rules for each basic CRUD permission. These rules have access to the auth context and you can use it to go get the user profile to check their permissions.
Here is an example of a rule that allows authenticated users access to view user profiles. This allows us to get a user’s profile to determine their permissions.
match /users/{user=**} {
allow read: if request.auth != null;
}
Here is an example of a rule that validates that the user has access to the data for a tenant.
match /tenants/{tenant} {
allow read: if request.auth != null && get(/database/$(database)/documents/users/$(request.auth.uid)).data.tenantId == tenant;
}
Automated deployments (CI/CD)
Cloud Build is GCP’s main automated deployment solution. You could use it but in the end you are just using the Firebase CLI anyways. So it doesn’t really provide a big advantage over any other deployment solution. We ended up creating a GitLab script which was pretty short and sweet.
—
In the next post we will finish up this series by doing a comparison of how AWS’s and GCP’s serverless offerings met our needs. Click below to read on:
Erik Murphy
Erik is an agile software developer in Charlotte, NC. He enjoys working full-stack (CSS, JS, C#, SQL) as each layer presents new challenges. His experience involves a variety of applications ranging from developing brochure sites to high-performance streaming applications. He has worked in many domains including military, healthcare, finance, and energy.