Firebase 为您提供了多种工具来管理您的规则,每一种都在特定情况下很有用,并且每一种都使用相同的后端 Firebase 安全规则管理 API。
无论使用哪个工具调用它,管理 API:
- 提取规则源:一组规则,通常是包含 Firebase 安全规则语句的代码文件。
- 将摄取的源存储为不可变的规则集。
- 跟踪发布中每个规则集的部署。启用 Firebase 安全规则的服务会查找项目的发布,以评估对安全资源的每个请求。
- 提供运行规则集的句法和语义测试的能力。
使用 Firebase CLI
使用Firebase CLI ,您可以上传本地资源并部署发布。 CLI 的 Firebase Local Emulator Suite 允许您对源执行完整的本地测试。
使用 CLI 允许您使用应用程序代码将规则置于版本控制之下,并将规则部署为现有部署过程的一部分。
生成配置文件
使用 Firebase CLI 配置 Firebase 项目时,您会在项目目录中创建一个.rules
配置文件。使用以下命令开始配置您的 Firebase 项目:
云端 Firestore
// Set up Firestore in your project directory, creates a .rules file firebase init firestore
实时数据库
// Set up Realtime Database in your project directory, creates a .rules file firebase init database
云储存
// Set up Storage in your project directory, creates a .rules file firebase init storage
编辑和更新您的规则
直接在.rules
配置文件中编辑规则源。确保您在 Firebase CLI 中所做的任何编辑都反映在 Firebase 控制台中,或者您始终使用 Firebase 控制台或 Firebase CLI 进行更新。否则,您可能会覆盖在 Firebase 控制台中所做的任何更新。
测试您的更新
Local Emulator Suite 为所有支持安全规则的产品提供模拟器。每个模拟器的安全规则引擎执行规则的句法和语义评估,因此超过了安全规则管理 API 提供的句法测试。
如果您使用 CLI,该套件是 Firebase 安全规则测试的绝佳工具。使用Local Emulator Suite在本地测试您的更新并确认您的应用程序规则表现出您想要的行为。
部署您的更新
更新并测试规则后,将源代码部署到生产环境中。使用以下命令有选择地单独部署您的规则,或将它们部署为正常部署过程的一部分。
云端 Firestore
// Deploy your .rules file firebase deploy --only firestore:rules
实时数据库
// Deploy your .rules file firebase deploy --only database
云储存
// Deploy your .rules file firebase deploy --only storage
使用 Firebase 控制台
您还可以编辑规则源并将它们部署为来自 Firebase 控制台的版本。当您在 Firebase 控制台 UI 中编辑时执行语法测试,并且可以使用 Rules Playground 进行语义测试。
编辑和更新您的规则
- 打开Firebase 控制台并选择您的项目。
- 然后,从产品导航中选择Realtime Database 、 Cloud Firestore或Storage ,然后单击Rules以导航到规则编辑器。
- 直接在编辑器中编辑您的规则。
测试您的更新
除了在编辑器 UI 中测试语法外,您还可以直接在 Firebase 控制台中使用Rules Playground使用项目的数据库和存储资源来测试语义规则行为。在规则编辑器中打开规则游乐场屏幕,修改设置并单击运行。在编辑器顶部查找确认消息。
部署您的更新
一旦您对您的更新符合预期感到满意,请点击发布。
使用管理 SDK
您可以使用 Admin SDK for Node.js规则集。通过这种编程访问,您可以:
- 实施自定义工具、脚本、仪表板和 CI/CD 管道以管理规则。
- 跨多个 Firebase 项目更轻松地管理规则。
以编程方式更新规则时,避免对应用程序的访问控制进行意外更改非常重要。在编写 Admin SDK 代码时,请将安全放在首位,尤其是在更新或部署规则时。
另一件需要牢记的重要事情是,Firebase 安全规则发布需要几分钟时间才能完全传播。使用 Admin SDK 部署规则时,请确保避免您的应用立即依赖部署尚未完成的规则的竞争条件。如果您的用例需要频繁更新访问控制规则,请考虑使用 Cloud Firestore 的解决方案,它旨在减少频繁更新的竞争条件。
另请注意以下限制:
- 序列化时,规则必须小于 256 KiB 的 UTF-8 编码文本。
- 一个项目总共最多可以部署 2500 个规则集。一旦达到此限制,您必须在创建新规则集之前删除一些旧规则集。
创建和部署 Cloud Storage 或 Cloud Firestore 规则集
使用 Admin SDK 管理安全规则的典型工作流程可能包括三个独立的步骤:
- 创建规则文件源(可选)
- 创建规则集
- 发布或部署新规则集
SDK 提供了一种方法,可以将这些步骤合并到针对 Cloud Storage 和 Cloud Firestore 安全规则的单个 API 调用中。例如:
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);
同样的模式适用于带有releaseFirestoreRulesetFromSource()
的 Cloud Storage 规则。
或者,您可以将规则文件创建为内存中对象,创建规则集,然后单独部署规则集以更紧密地控制这些事件。例如:
const rf = admin.securityRules().createRulesFileFromSource('firestore.rules', source);
const rs = await admin.securityRules().createRuleset(rf);
await admin.securityRules().releaseFirestoreRuleset(rs);
更新实时数据库规则集
要使用 Admin SDK 更新实时数据库规则集,请使用admin.database
的getRules()
和setRules()
方法。您可以检索 JSON 格式的规则集,或作为包含注释的字符串。
要更新规则集:
const source = `{
"rules": {
"scores": {
".indexOn": "score",
"$uid": {
".read": "$uid == auth.uid",
".write": "$uid == auth.uid"
}
}
}
}`;
await admin.database().setRules(source);
管理规则集
为了帮助管理大型规则集,Admin SDK 允许您使用admin.securityRules().listRulesetMetadata
列出所有现有规则。例如:
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;
}
}
对于随着时间的推移达到 2500 个规则集限制的超大型部署,您可以创建逻辑以按固定时间周期删除最旧的规则。例如,要删除部署时间超过 30 天的所有规则集:
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.`);
使用 REST API
上述工具非常适合各种工作流程,但您可能希望使用管理 API 本身来管理和部署 Firebase 安全规则。管理 API 为您提供最大的灵活性。
请注意,Firebase 安全规则发布需要几分钟时间才能完全传播。使用管理 REST API 进行部署时,请确保避免应用程序立即依赖部署尚未完成的规则的竞争条件。
另请注意以下限制:
- 序列化时,规则必须小于 256 KiB 的 UTF-8 编码文本。
- 一个项目总共最多可以部署 2500 个规则集。一旦达到此限制,您必须在创建新规则集之前删除一些旧规则集。
使用 REST 创建和部署 Cloud Storage 或 Cloud Firestore 规则集
本部分中的示例使用存储规则,但它们也适用于 Cloud Firestore 规则。
这些示例还使用 cURL 进行 API 调用。省略了设置和传递身份验证令牌的步骤。您可以使用与参考文档集成的 API Explorer 试验此 API。
使用管理 API 创建和部署规则集的典型步骤是:
- 创建规则文件源
- 创建规则集
- 发布(部署)新规则集
假设您正在处理secure_commerce
Firebase 项目并希望部署锁定的云存储规则。您可以在storage.rules
文件中实施这些规则。
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if false;
}
}
}
现在,为这个文件生成一个 base64 编码的指纹。然后,您可以使用此文件中的源来填充通过projects.rulesets.create
REST 调用创建规则集所需的负载。在这里,我们使用cat
命令将storage.rules
的内容插入到 REST 负载中。
curl -X POST -d '{
"source": {
{
"files": [
{
"content": "' $(cat storage.rules) '",
"name": "storage.rules",
"fingerprint": <sha fingerprint>
}
]
}
}
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/rulesets'
API 返回验证响应和规则集名称,例如projects/secure_commerce/rulesets/uuid123
。如果规则集有效,最后一步是在命名版本中部署新规则集。
curl -X POST -d '{
"name": "projects/secure_commerce/releases/prod/v23 " ,
"rulesetName": "projects/secure_commerce/rulesets/uuid123",
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/releases'
使用 REST 更新实时数据库规则集
实时数据库提供自己的 REST 接口来管理规则。请参阅通过 REST 管理 Firebase 实时数据库规则。
使用 REST 管理规则集
为了帮助管理大型规则部署,除了用于创建规则集和发布的 REST 方法之外,管理 API 还提供了以下方法:
- 列出、获取和删除规则集
- 列出、获取和删除规则发布
对于随着时间的推移达到 2500 个规则集限制的超大型部署,您可以创建逻辑以按固定时间周期删除最旧的规则。例如,要删除所有部署时间超过 30 天的规则集,可以调用projects.rulesets.list
方法,在其createTime
键上解析Ruleset
对象的 JSON 列表,然后通过ruleset_id
在相应的规则集上调用project.rulesets.delete
.
使用 REST 测试您的更新
最后,管理 API 允许您对生产项目中的 Cloud Firestore 和 Cloud Storage 资源运行语法和语义测试。
使用此 API 组件进行的测试包括:
- 定义一个
TestSuite
JSON 对象来表示一组TestCase
对象 - 提交
TestSuite
- 解析返回
TestResult
对象
让我们在testcase.json
文件中定义一个带有单个TestCase
的TestSuite
对象。在此示例中,我们传递与 REST 有效负载内联的规则语言源,以及要在这些规则上运行的测试套件。我们指定规则评估期望,以及要测试规则集的客户端请求。您还可以指定测试报告的完整程度,使用值“FULL”指示所有规则语言表达式的结果应包含在报告中,包括与请求不匹配的表达式。
{ "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"}}} } ] } ] } }
然后我们可以使用projects.test
方法提交这个TestSuite
进行评估。
curl -X POST -d '{
' $(cat testcase.json) '
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/rulesets/uuid123:test'
返回的测试TestReport
(包含测试 SUCCESS/FAILURE 状态、调试消息列表、访问规则表达式列表及其评估报告)将以 SUCCESS 状态确认访问被正确允许。
管理跨服务云存储安全规则的权限
如果您创建使用Cloud Firestore 文档内容评估安全条件的 Cloud Storage 安全规则,系统会在 Firebase 控制台或 Firebase CLI 中提示您启用连接这两个产品的权限。
如果您决定禁用此类跨服务安全性:
首先,在禁用该功能之前,编辑您的规则,删除所有使用规则函数访问 Cloud Firestore 的语句。否则,禁用该功能后,规则评估将导致您的存储请求失败。
使用 Google Cloud Console 中的IAM页面按照Cloud guide for revoking roles删除“Firebase Rules Firestore Service Agent”角色。
下次您从 Firebase CLI 或 Firebase 控制台保存跨服务规则时,系统将提示您重新启用该功能。