firebase / firebase/firebase-tools

"firebase init" loads Firestore security rules from non-default database

Open
#7,981 5 comments 0 reactions 1 assignee Claimed by @aalej View on GitHub
api: firestore reproducible type: bug
Dominant language
TypeScript
Stars
4.5k
Forks
1.3k
Avg merge
1d 12h
Merged PRs (30d)
84

Description

### [REQUIRED] Environment info

**firebase-tools:** 13.26.0

**Platform:** macOS

### [REQUIRED] Test case

When there are two Firestore databases in one Firebase project, `firebase init` loads security rules from the non-default database. Expected: load rules from the default database.

### [REQUIRED] Steps to reproduce

#### Prerequisite - setup project with different rules in different databases

Take a Firebase project with enabled Firestore and enabled billing. Mine is called `test-non-default-rules`.

* `firebase init firestore --project test-non-default-rules`.
* Create non-default database: `firebase --project test-non-default-rules firestore:databases:create non-default --location=nam5`
* Duplicate rules and indexes:
* `cp firestore.rules firestore-non-default.rules`
* `cp firestore.indexes.json firestore-indexes-non-default.indexes.json`
* Make `firestore.rules` and `firestore-non-default.rules` different. E.g.
`firestore.rules`:
```
rules_version = '2';

// Default database rules
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
```
`firestore-non-default.rules`:
```
rules_version = '2';

// Non-default database rules
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
```
* Update `firebase.json` to include the second database:
```
{
"firestore":
[
{
"database": "(default)",
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
{
"database": "non-default",
"rules": "firestore-non-default.rules",
"indexes": "firestore-non-default.indexes.json"
}
]
}

```
* Deploy: `firebase --project test-non-default-rules deploy --only firestore`
* Verify rules in Firebase console:
* Default: https://console.firebase.google.com/project/test-non-default-rules/firestore/databases/-default-/rules
* Non-default: https://console.firebase.google.com/project/test-non-default-rules/firestore/databases/non-default/rules

#### Run firebase init again

In a different folder:
* `firebase init firestore --project test-non-default-rules`.
* `cat firestore.rules`

### [REQUIRED] Expected behavior

Expect to see rules for the default database.

It'd be even better if there was a way to choose the database, but if there isn't then it should use the default one.

### [REQUIRED] Actual behavior

I see rules for the non-default database:
```
rules_version = '2';

// Non-default database rules
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
```

`firebase init firestore --project test-non-default-rules --debug`:
```
[2024-11-21T18:09:22.137Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
[2024-11-21T18:09:22.137Z] > authorizing via signed-in user (redacted@example.com)

######## #### ######## ######## ######## ### ###### ########
## ## ## ## ## ## ## ## ## ## ##
###### ## ######## ###### ######## ######### ###### ######
## ## ## ## ## ## ## ## ## ## ##
## #### ## ## ######## ######## ## ## ###### ########

You're about to initialize a Firebase project in this directory:

/Users/redacted/tmp/fb/reinit

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.

[2024-11-21T18:09:22.138Z] Using project from CLI flag: test-non-default-rules
[2024-11-21T18:09:22.139Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:22.139Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:22.139Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/test-non-default-rules [none]
[2024-11-21T18:09:22.531Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/test-non-default-rules 200
[2024-11-21T18:09:22.531Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/test-non-default-rules {"projectId":"test-non-default-rules","projectNumber":"845181815027","displayName":"test-non-default-rules","name":"projects/test-non-default-rules","resources":{"hostingSite":"test-non-default-rules"},"state":"ACTIVE","etag":"1_8f9c418a-7741-42d5-b0c6-b12899191c20"}
i Using project test-non-default-rules (test-non-default-rules)

=== Firestore Setup
[2024-11-21T18:09:22.542Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:22.542Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:22.542Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/test-non-default-rules/services/firestore.googleapis.com [none]
[2024-11-21T18:09:22.542Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/test-non-default-rules/services/firestore.googleapis.com x-goog-quota-user=projects/test-non-default-rules
[2024-11-21T18:09:22.993Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/test-non-default-rules/services/firestore.googleapis.com 200
[2024-11-21T18:09:22.994Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/test-non-default-rules/services/firestore.googleapis.com [omitted]
[2024-11-21T18:09:22.994Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:22.994Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:22.995Z] >>> [apiv2][query] GET https://firestore.googleapis.com/v1/projects/test-non-default-rules/databases/(default) [none]
[2024-11-21T18:09:23.316Z] <<< [apiv2][status] GET https://firestore.googleapis.com/v1/projects/test-non-default-rules/databases/(default) 200
[2024-11-21T18:09:23.317Z] <<< [apiv2][body] GET https://firestore.googleapis.com/v1/projects/test-non-default-rules/databases/(default) {"name":"projects/test-non-default-rules/databases/(default)","uid":"01dad914-35b5-4808-919b-655b2421581f","createTime":"2024-11-21T17:47:12.821827Z","updateTime":"2024-11-21T17:47:12.821827Z","locationId":"nam5","type":"FIRESTORE_NATIVE","concurrencyMode":"PESSIMISTIC","versionRetentionPeriod":"3600s","earliestVersionTime":"2024-11-21T17:47:12.821827Z","appEngineIntegrationMode":"DISABLED","keyPrefix":"s","pointInTimeRecoveryEnablement":"POINT_IN_TIME_RECOVERY_DISABLED","deleteProtectionState":"DELETE_PROTECTION_DISABLED","etag":"IMXEjNSC7okDMJmYgd/97YkD"}
[2024-11-21T18:09:23.317Z] database_type: FIRESTORE_NATIVE
[2024-11-21T18:09:23.317Z] database_type: FIRESTORE_NATIVE
[2024-11-21T18:09:23.318Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
[2024-11-21T18:09:23.318Z] > authorizing via signed-in user (redacted@example.com)
[2024-11-21T18:09:23.318Z] [iam] checking project test-non-default-rules for permissions ["firebase.projects.get"]
[2024-11-21T18:09:23.319Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:23.319Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:23.319Z] >>> [apiv2][query] POST https://cloudresourcemanager.googleapis.com/v1/projects/test-non-default-rules:testIamPermissions [none]
[2024-11-21T18:09:23.319Z] >>> [apiv2][(partial)header] POST https://cloudresourcemanager.googleapis.com/v1/projects/test-non-default-rules:testIamPermissions x-goog-quota-user=projects/test-non-default-rules
[2024-11-21T18:09:23.319Z] >>> [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/test-non-default-rules:testIamPermissions {"permissions":["firebase.projects.get"]}
[2024-11-21T18:09:23.516Z] <<< [apiv2][status] POST https://cloudresourcemanager.googleapis.com/v1/projects/test-non-default-rules:testIamPermissions 200
[2024-11-21T18:09:23.517Z] <<< [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/test-non-default-rules:testIamPermissions {"permissions":["firebase.projects.get"]}

Firestore Security Rules allow you to define how and when to allow
requests. You can keep these rules in your project directory
and publish them with firebase deploy.

? What file should be used for Firestore Rules? (firestore.rules) ? What file should be used for Firestore Rules? firestore.rules
[2024-11-21T18:09:30.665Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:30.665Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:30.666Z] >>> [apiv2][query] GET https://firebaserules.googleapis.com/v1/projects/test-non-default-rules/releases pageSize=10&pageToken=
[2024-11-21T18:09:30.874Z] <<< [apiv2][status] GET https://firebaserules.googleapis.com/v1/projects/test-non-default-rules/releases 200
[2024-11-21T18:09:30.875Z] <<< [apiv2][body] GET https://firebaserules.googleapis.com/v1/projects/test-non-default-rules/releases {"releases":[{"name":"projects/test-non-default-rules/releases/cloud.firestore","rulesetName":"projects/test-non-default-rules/rulesets/d1e2cacb-ebc6-43ec-8992-b7af319e405d","createTime":"2024-11-21T17:47:14.297744Z","updateTime":"2024-11-21T17:56:38.723378Z"},{"name":"projects/test-non-default-rules/releases/cloud.firestore/non-default","rulesetName":"projects/test-non-default-rules/rulesets/7d3651a8-88d9-4f01-9872-35768adcfe2c","createTime":"2024-11-21T17:56:38.907657Z","updateTime":"2024-11-21T17:56:38.907657Z"}]}
[2024-11-21T18:09:30.888Z] Found ruleset: projects/test-non-default-rules/rulesets/7d3651a8-88d9-4f01-9872-35768adcfe2c
[2024-11-21T18:09:30.889Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:30.889Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:30.889Z] >>> [apiv2][query] GET https://firebaserules.googleapis.com/v1/projects/test-non-default-rules/rulesets/7d3651a8-88d9-4f01-9872-35768adcfe2c [none]
[2024-11-21T18:09:31.024Z] <<< [apiv2][status] GET https://firebaserules.googleapis.com/v1/projects/test-non-default-rules/rulesets/7d3651a8-88d9-4f01-9872-35768adcfe2c 200
[2024-11-21T18:09:31.024Z] <<< [apiv2][body] GET https://firebaserules.googleapis.com/v1/projects/test-non-default-rules/rulesets/7d3651a8-88d9-4f01-9872-35768adcfe2c [omitted]

Firestore indexes allow you to perform complex queries while
maintaining performance that scales with the size of the result
set. You can keep index definitions in your project directory
and publish them with firebase deploy.

? What file should be used for Firestore indexes? (firestore.indexes.json) ? What file should be used for Firestore indexes? firestore.indexes.json
[2024-11-21T18:09:31.625Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:31.626Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:31.626Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:31.626Z] Checked if tokens are valid: true, expires at: 1732213850733
[2024-11-21T18:09:31.626Z] >>> [apiv2][query] GET https://firestore.googleapis.com/v1/projects/test-non-default-rules/databases/(default)/collectionGroups/-/indexes [none]
[2024-11-21T18:09:31.629Z] >>> [apiv2][query] GET https://firestore.googleapis.com/v1/projects/test-non-default-rules/databases/(default)/collectionGroups/-/fields?filter=indexConfig.usesAncestorConfig=false OR ttlConfig:* [none]
[2024-11-21T18:09:32.005Z] <<< [apiv2][status] GET https://firestore.googleapis.com/v1/projects/test-non-default-rules/databases/(default)/collectionGroups/-/fields?filter=indexConfig.usesAncestorConfig=false OR ttlConfig:* 200
[2024-11-21T18:09:32.006Z] <<< [apiv2][body] GET https://firestore.googleapis.com/v1/projects/test-non-default-rules/databases/(default)/collectionGroups/-/fields?filter=indexConfig.usesAncestorConfig=false OR ttlConfig:* {"fields":[{"name":"projects/test-non-default-rules/databases/(default)/collectionGroups/__default__/fields/*","indexConfig":{"indexes":[{"queryScope":"COLLECTION","fields":[{"fieldPath":"*","order":"ASCENDING"}],"state":"READY"},{"queryScope":"COLLECTION","fields":[{"fieldPath":"*","order":"DESCENDING"}],"state":"READY"},{"queryScope":"COLLECTION","fields":[{"fieldPath":"*","arrayConfig":"CONTAINS"}],"state":"READY"}]}}]}
[2024-11-21T18:09:32.007Z] <<< [apiv2][status] GET https://firestore.googleapis.com/v1/projects/test-non-default-rules/databases/(default)/collectionGroups/-/indexes 200
[2024-11-21T18:09:32.007Z] <<< [apiv2][body] GET https://firestore.googleapis.com/v1/projects/test-non-default-rules/databases/(default)/collectionGroups/-/indexes {}

i Writing configuration info to firebase.json...
i Writing project information to .firebaserc...

✔ Firebase initialization complete!
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.