Firebase provides you with several tools to manage your Rules, each
one useful in particular cases, and each one using the same backend Firebase
Security Rules management API.
No matter which tool is used to invoke it, the management API:
- Ingests a Rules
source
: a set of rules, typically a code file containing
Firebase Security Rules statements.
- Stores ingested source as an immutable
ruleset
.
- Tracks deployment of each ruleset in a
release
. Firebase Security
Rules-enabled services lookup the release for a project to evaluate each request
for a secured resource.
- Provides the capability to run syntactic and semantic
tests
of a ruleset.
Use the Firebase CLI
With the
Firebase CLI
, you can
upload local
sources
and deploy
releases
. The CLI's
Firebase Local Emulator Suite lets you perform full local testing of
sources
.
Using the CLI allows you to keep your rules under version control with your
application code and deploy rules as part of your existing deployment process.
Generate a configuration file
When you configure your Firebase project using the Firebase CLI, you create
a
.rules
configuration file in your project directory. Use the following
command to start configuring your Firebase project:
Cloud Firestore
// Set up Firestore in your project directory, creates a .rules file
firebase init firestore
Realtime Database
// Set up Realtime Database in your project directory, creates a .rules file
firebase init database
Cloud Storage
// Set up Storage in your project directory, creates a .rules file
firebase init storage
Edit and update your rules
Edit your rules source directly in the
.rules
configuration file.
Make sure that any edits you make in the Firebase CLI are reflected in the
Firebase console, or that you consistently make updates using either the
Firebase console or the Firebase CLI. Otherwise, you might overwrite any
updates made in the Firebase console.
Test your updates
The Local Emulator Suite provides emulators for all Security Rules-enabled
products. The Security Rules engine for each emulator performs both syntactic
and semantic evaluation of rules, thus exceeding the syntactic testing the
Security Rules management API offers.
If you're working with the CLI, the Suite is an excellent tool for Firebase Security Rules
testing. Use the
Local Emulator Suite
to test your updates
locally and confirm that your app's Rules exhibit the behavior you
want.
Deploy your updates
Once you've updated and tested your Rules, deploy the sources to
production.
For Cloud Firestore Security Rules, associate
.rules
files with your default and
additional named databases by reviewing and updating your
firebase.json
file
.
Use the following commands to selectively deploy your Rules alone or
deploy them as part of your normal deployment process.
Cloud Firestore
// Deploy rules for all databases configured in your firebase.json
firebase deploy --only firestore:rules
// Deploy rules for the specified database configured in your firebase.json
firebase deploy --only firestore:<databaseId>
Realtime Database
// Deploy your .rules file
firebase deploy --only database
Cloud Storage
// Deploy your .rules file
firebase deploy --only storage
Use the Firebase console
You can also edit Rules
sources
and deploy them as
releases
from
the Firebase console. Syntactic
testing
is performed as you edit in the
Firebase console UI, and semantic testing is available using the
Rules Playground.
Edit and update your rules
- Open the
Firebase console
and select your project.
- Then, select
Realtime Database
,
Cloud Firestore
or
Storage
from
the product navigation, then click
Rules
to navigate to the
Rules editor.
- Edit your rules directly in the editor.
Test your updates
In addition to testing syntax in the editor UI, you can test semantic
Rules behavior, using your project's database and storage resources,
directly in the Firebase console, using the
Rules Playground
. Open the
Rules Playground
screen in the Rules editor, modify the settings and click
Run
.
Look for the confirmation message at the top of the editor.
Deploy your updates
Once you're satisfied that your updates are what you expect, click
Publish
.
Use the Admin SDK
You can use the Admin SDK for Node.js
rulesets
. With this programmatic access, you can:
- Implement custom tools, scripts, dashboards and CI/CD pipelines for managing rules.
- Manage rules more easily across multiple Firebase projects.
When updating rules programmatically, it is very important to avoid making
unintended changes to the access control for your app. Write your
Admin SDK code
with security foremost in mind, especially when updating or deploying rules.
Another important thing to keep in mind is that Firebase Security Rules releases take a
period of several minutes to fully propagate. When using the Admin SDK to deploy
rules, make sure to avoid race conditions in which your app immediately relies
on rules whose deployment is not yet complete. If your use case requires
frequent updates to access control rules, consider solutions using Cloud Firestore,
which is designed to reduce race conditions despite frequent updates.
Also note these limits:
- Rules must be smaller than 256 KiB of UTF-8 encoded text when serialized.
- A project can have at most 2500 total deployed rulesets. Once this limit is
reached, you must delete some old rulesets before creating new ones.
Create and deploy Cloud Storage or Cloud Firestore rulesets
A typical workflow for managing security rules with the Admin SDK could include
three discrete steps:
- Create a rules file source (optional)
- Create a ruleset
- Release, or deploy, the new ruleset
The SDK provides a method to combine these steps into a single API call for
Cloud Storage and Cloud Firestore security rules. For example:
const source = `service cloud.firestore {
match /databases/{database}/documents {
match /carts/{cartID} {
allow create: if request.auth != null && request.auth.uid == request.resource.data.ownerUID;
allow read, update, delete: if request.auth != null && request.auth.uid == resource.data.ownerUID;
}
}
}`;
// Alternatively, load rules from a file
// const fs = require('fs');
// const source = fs.readFileSync('path/to/firestore.rules', 'utf8');
await admin.securityRules().releaseFirestoreRulesetFromSource(source);
This same pattern works for Cloud Storage rules with
releaseFirestoreRulesetFromSource()
.
Alternatively, you can create the rules file as an in-memory object, create the
ruleset, and deploy the ruleset separately for closer control of these events.
For example:
const rf = admin.securityRules().createRulesFileFromSource('firestore.rules', source);
const rs = await admin.securityRules().createRuleset(rf);
await admin.securityRules().releaseFirestoreRuleset(rs);
Update Realtime Database rulesets
To update Realtime Database rulesets with the Admin SDK, use the
getRules()
and
setRules()
methods of
admin.database
. You can retrieve rulesets in JSON
format, or as a string with comments included.
To update a ruleset:
const source = `{
"rules": {
"scores": {
".indexOn": "score",
"$uid": {
".read": "$uid == auth.uid",
".write": "$uid == auth.uid"
}
}
}
}`;
await admin.database().setRules(source);
Manage rulesets
To help manage large rulesets, the Admin SDK lets you list all existing rules
with
admin.securityRules().listRulesetMetadata
. For example:
const allRulesets = [];
let pageToken = null;
while (true) {
const result = await admin.securityRules().listRulesetMetadata(pageToken: pageToken);
allRulesets.push(...result.rulesets);
pageToken = result.nextPageToken;
if (!pageToken) {
break;
}
}
For very large deployments that reach the 2500 ruleset limit over time, you can
create logic to delete the oldest rules on a fixed time cycle. For example, to
delete
all
rulesets deployed for longer than 30 days:
const thirtyDays = new Date(Date.now() - THIRTY_DAYS_IN_MILLIS);
const promises = [];
allRulesets.forEach((rs) => {
if (new Date(rs.createTime) < thirtyDays) {
promises.push(admin.securityRules().deleteRuleset(rs.name));
}
});
await Promise.all(promises);
console.log(`Deleted ${promises.length} rulesets.`);
Use the REST API
The tools described above are well suited to various workflows, including
Firebase Security Rules management for multiple Cloud Firestore databases in your project,
but you may want to manage and deploy Firebase Security Rules using the management API itself.
The management API gives you the greatest flexibility.
Also note these limits:
- Rules must be smaller than 256 KiB of UTF-8 encoded text when serialized.
- A project can have at most 2500 total deployed rulesets. Once this limit is
reached, you must delete some old rulesets before creating new ones.
Create and deploy Cloud Firestore or Cloud Storage rulesets with REST
The examples in this section use Firestore Rules, though they apply to
Cloud Storage Rules as well.
The examples also use cURL to make API calls. Steps to set up and pass
authentication tokens are omitted. You can experiment with this API using the
API Explorer integrated with the
reference documentation.
Typical steps for creating and deploying a ruleset using the management API are:
- Create rules file sources
- Create a ruleset
- Release (deploy) the new ruleset.
Create a source
Let's assume you're working on your
secure_commerce
Firebase project and want
to deploy locked-down Cloud Firestore Rules to a database in your
project named
east_store
.
You can implement these rules in a
firestore.rules
file.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
Create a ruleset
Now, generate a base64-encoded fingerprint for this file. You can then use the
source in this file to populate the payload needed to create a ruleset with the
projects.rulesets.create
REST call. Here, use the
cat
command to insert
the contents of
firestore.rules
into the REST payload.
For tracking, to associate this with your
east_store
database, set the
attachment_point
to
east_store
.
curl -X POST -d '{
"source": {
{
"files": [
{
"content": "' $(cat storage.rules) '",
"name": "firestore.rules",
"fingerprint": <sha fingerprint>
},
"attachment_point": "firestore.googleapis.com/databases/east_store"
]
}
}
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/rulesets'
The API returns a validation response and a ruleset name, for example
projects/secure_commerce/rulesets/uuid123
.
Release (deploy) a ruleset
If the ruleset is valid, the final step is to deploy the new ruleset in a named
release.
curl -X POST -d '{
"name": "projects/secure_commerce/releases/cloud.firestore/east_store" ,
"rulesetName": "projects/secure_commerce/rulesets/uuid123"
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/releases'
Be aware that Firebase Security Rules releases take a period of several minutes to fully
propagate. When using the management REST API to deploy, make sure to avoid race
conditions in which your app immediately relies on rules whose deployment is not
yet complete.
Update Realtime Database rulesets with REST
Realtime Database provides its own REST interface for managing Rules. See
Managing Firebase Realtime Database Rules via REST
.
Manage rulesets with REST
To help manage large rules deployments, in addition to a REST method for
creating rulesets and releases, the management API provides methods to:
- list, get, and delete
rulesets
- list, get, and delete rules
releases
For very large deployments that reach the 2500 ruleset limit over time, you can
create logic to delete the oldest rules on a fixed time cycle. For example, to
delete
all
rulesets deployed for longer than 30 days, you can call the
projects.rulesets.list
method, parse the JSON list of
Ruleset
objects on
their
createTime
keys, then call
project.rulesets.delete
on the
corresponding rulesets by
ruleset_id
.
Test your updates with REST
Finally, the management API allows you to run syntactic and semantic tests on
Cloud Firestore and Cloud Storage resources in your production
projects.
Testing with this component of the API consists of:
- Defining a
TestSuite
JSON object to represent a set of
TestCase
objects
- Submitting the
TestSuite
- Parsing returned
TestResult
objects
Let's define a
TestSuite
object with a single
TestCase
in a
testcase.json
file. In this example, we pass the Rules
language source inline with the REST payload, alongside the test suite to run
on those rules. We specify a Rules evaluation expectation, and the client
request against which the ruleset is to be tested. You can also specify how
complete the test report is, using value "FULL" to indicate results for all
Rules language expressions should be included in the report, including
expressions that were not matched to the request.
{
"source":
{
"files":
[
{
"name": "firestore.rules",
"content": "service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId}{
allow read: if (request.auth.uid == userId);
}
function doc(subpath) {
return get(/databases/$(database)/documents/$(subpath)).data;
}
function isAccountOwner(accountId) {
return request.auth.uid == accountId
|| doc(/users/$(request.auth.uid)).accountId == accountId;
}
match /licenses/{accountId} {
allow read: if isAccountOwner(accountId);
}
}
}"
}
]
},
"testSuite":
{
"testCases":
[
{
"expectation": "ALLOW",
"request": {
"auth": {"uid": "123"},
"path": "/databases/(default)/documents/licenses/abcd",
"method": "get"},
"functionMocks": [
{
"function": "get",
"args": [{"exact_value": "/databases/(default)/documents/users/123"}],
"result": {"value": {"data": {"accountId": "abcd"}}}
}
]
}
]
}
}
We can then submit this
TestSuite
for evalution with the
projects.test
method.
curl -X POST -d '{
' $(cat testcase.json) '
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/rulesets/uuid123:test'
The returned
TestReport
(containing test SUCCESS/FAILURE status, lists of
debug messages, lists of visited Rules expressions and their evaluation reports)
would confirm with status SUCCESS that access is properly allowed.
Manage permissions for cross-service Cloud Storage Security Rules
If you create Cloud Storage Security Rules that use
Cloud Firestore document contents
to evaluate security conditions
,
you'll be prompted in the Firebase console or Firebase CLI to enable
permissions to connect the two products.
If you decide to disable such cross-service security:
First, before disabling the feature, edit your rules, removing all
statements that use Rules functions to access Cloud Firestore.
Otherwise, after the feature is disabled, Rules evaluations will
cause your Storage requests to fail.
Use the
IAM
page in the Google Cloud Console to delete the "Firebase
Rules Firestore Service Agent" role by following the
Cloud guide for
revoking roles
.
You will be prompted to re-enable the feature the next time you save
cross-service Rules from the Firebase CLI or the Firebase console.