Firebase 为您提供了多种 Security Rules 管理工具,每 种工具在特定情况下都很有用,并且都使用相同的后端 Firebase 管理 API。
无论使用哪种工具调用 Management API,该 API 都可以:
- 注入规则来源:一组规则,通常是包含 Firebase Security Rules语句的代码文件。
- 将注入的来源存储为不可变规则集。
- 跟踪版本中每个规则集的部署。启用了 Firebase 安全规则的服务会查找项目的版本,以评估针对受保护资源发出的每个请求。
- 提供运行规则集的语法和语义测试的功能。
使用 Firebase CLI
使用 Firebase CLI,您可以 上传本地 来源 和部署 版本。使用 CLI 的 Firebase Local Emulator Suite,您可以对 来源执行完整的本地测试。
使用 CLI,您可以借助应用代码对规则进行版本控制,并在现有的部署过程中部署规则。
生成配置文件
使用 Firebase CLI 配置 Firebase 项目时,您可在项目目录中创建
.rules 配置文件。使用以下命令开始配置 Firebase 项目:
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
修改和更新您的规则
直接在 .rules 配置文件中修改规则来源。
确保您在 Firebase CLI 中进行的所有修改都体现在 Firebase 控制台中,或者您始终使用 Firebase 控制台或 Firebase CLI 进行更新。否则,您可能会覆盖在 Firebase 控制台中所做的任何 更新。
因此,如果您选择使用安全规则 使用 Firebase 控制台定义或修改,请务必同时更新您在项目目录中定义的规则。测试您的更新
Local Emulator Suite 为所有启用安全规则的 产品提供模拟器。每个模拟器的安全规则引擎都会对规则进行语法和语义评估,因而超出了 Security Rules Management API 提供的语法测试的范围。
如果您使用的是 CLI,则该套件是进行 Firebase Security Rules 测试的绝佳工具。使用 Local Emulator Suite 在本地测试您的更新 ,并确认您的应用 Security Rules 表现出您 期望的行为。
部署您的更新
更新并测试Security Rules后,将来源部署到 生产环境中。
对于 Cloud Firestore Security Rules,请查看并更新您的 firebase.json 文件,将 .rules 文件与默认数据库和
其他命名数据库相关联。
使用以下命令,可以选择单独部署 Security Rules,或者 将其作为正常部署过程的一部分进行部署。
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
使用 Firebase 控制台
您还可以通过 Firebase 控制台修改 Security Rules 来源,并将其部署为 版本。当您在 Firebase控制台界面中进行修改时,执行的是语法测试;您可以使用 Security Rules测试平台进行语义测试。
修改和更新您的规则
- 打开 Firebase 控制台,选择您的项目。
- 然后从 产品导航中选择 Realtime Database 、Cloud Firestore 或 Storage ,再点击 Rules 以导航到 Security Rules 编辑器。
- 直接在编辑器中修改规则。
测试您的更新
除了在编辑器界面中测试语法之外,您还可以使用项目的数据库和存储资源测试语义 Security Rules行为, 直接在 Firebase 控制台中使用 Security Rules 测试平台。在 Security Rules 编辑器中打开 规则测试平台 屏幕,修改设置,然后点击 运行。在编辑器顶部查找确认消息。
部署您的更新
如果您的更新达到您满意的效果,请点击发布。
使用 Admin SDK
您可以使用 Admin SDK for Node.js 规则集。通过以编程方式访问,您可以执行以下操作:
- 实现自定义工具、脚本、信息中心和 CI/CD 流水线以管理规则。
- 更轻松地管理多个 Firebase 项目的规则。
以编程方式更新规则时,需要避免意外更改应用的访问权限控制。在编写 Admin SDK代码 时,请特别注意安全问题,尤其是在更新或部署规则时。
另一个需要注意的重要事项是,Firebase Security Rules版本需要 几分钟的时间才能完全传播。使用 Admin SDK 部署 规则时,请确保避免出现以下竞态条件:应用立即依赖 于部署尚未完成的规则。如果您的用例需要 频繁更新访问权限控制规则,请考虑使用 Cloud Firestore 解决方案, 该方案可有效避免频繁更新时出现争用的情况。
另请注意以下限制:
- 规则在序列化后必须小于 256KiB 的 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);
此模式同样适用于 Cloud Storage 规则,具有 releaseFirestoreRulesetFromSource()。
或者,您可以将规则文件创建为内存对象,创建规则集,并单独部署此规则集以进一步控制这些事件。 例如:
const rf = admin.securityRules().createRulesFileFromSource('firestore.rules', source);
const rs = await admin.securityRules().createRuleset(rf);
await admin.securityRules().releaseFirestoreRuleset(rs);
更新 Realtime Database 规则集
如需使用 Admin SDK 更新 Realtime Database 规则集,请使用 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
上述工具非常适合各种工作流,包括 Firebase Security Rules管理项目中多个 Cloud Firestore 数据库, 但您可能希望使用 Management API 本身管理和部署 Firebase Security Rules。 Management API 为您提供了最大的灵活性。
另请注意以下限制:
- 规则在序列化后必须小于 256KiB 的 UTF-8 编码文本。
- 一个项目最多只能有 2500 个已部署的规则集。达到上限后,您必须先删除一些旧规则集,然后才能创建新规则集。
使用 REST 创建和部署 Cloud Firestore 或 Cloud Storage 规则集
本部分中的示例使用的是 Firestore Security Rules(不过这些示例也适用于 Cloud Storage Security Rules)。
这些示例还使用 c网址 进行 API 调用。设置和传递身份验证令牌的步骤已省略。您可以使用集成了参考文档的 API Explorer 试用此 API。
使用 Management API 创建和部署规则集的典型步骤如下:
- 创建规则文件来源
- 创建规则集
- 发布(部署)新规则集。
创建来源
假设您正在处理您的 secure_commerce Firebase 项目,而且想要将锁定的 Cloud Firestore Security Rules 部署到项目中名为 east_store 的数据库。
您可以在 firestore.rules 文件中实现这些规则。
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
创建规则集
现在,请为此文件生成 base64 编码的指纹。然后,您可以使用此文件中的来源填充通过 projects.rulesets.create
REST 调用创建规则集所需的载荷。我们使用 cat 命令将 firestore.rules 的内容插入 REST 载荷中。
如需进行跟踪,请将此与 east_store 数据库相关联,并将 attachment_point 设置为 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'API 会返回验证响应和规则集名称,例如 projects/secure_commerce/rulesets/uuid123。
发布(部署)规则集
如果规则集有效,则最后一步是在指定版本中部署新规则集。
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'请注意,Firebase Security Rules版本需要几分钟时间才能完成 部署。使用 Management REST API 进行部署时,请确保避免出现以下竞态条件:您的应用立即依赖于部署尚未完成的规则。
使用 REST 更新 Realtime Database 规则集
Realtime Database 提供自己的 REST 接口来管理 Security Rules。请参阅 通过 REST 管理 FirebaseRealtime DatabaseSecurity Rules。
使用 REST 管理规则集
为了帮助管理大型规则部署,除了用于创建规则集和版本的 REST 方法外,Management API 还提供执行以下操作的方法:
- 列出、获取和删除规则集
- 列出、获取和删除规则版本
对于在一段时间内达到 2500 个规则集限制的大型部署,您可以创建逻辑,以删除固定的时间段内最旧的规则。例如,如需删除部署时间超过 30 天的所有规则集,您可以调用 projects.rulesets.list 方法,根据 createTime 键解析 Ruleset 对象的 JSON 列表,然后按 ruleset_id 对相应的规则集调用 project.rulesets.delete。
使用 REST 测试您的更新
最后,您可以通过 Management API 对生产 项目中的 Cloud Firestore和 Cloud Storage资源运行语法和语义测试。
使用 API 的此组件执行的测试包括:
- 定义
TestSuiteJSON 对象,以表示一组TestCase对象 - 提交
TestSuite - 解析返回的
TestResult对象
让我们在 testcase.json 文件中定义一个包含单个 TestCase 的 TestSuite
对象。在此示例中,我们传递与 REST 载荷和测试套件内嵌的 Security Rules
语言源来运行
这些规则。我们会指定规则评估期望,以及要测试规则集的客户端请求。您还可以指定测试报告的完整程度,方法是使用“FULL”值指示所有
Security Rules语言表达式(包括
与请求不匹配的表达式)的结果都应包含在报告中。
{ "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 Storage Security Rules 的权限
如果您创建的 Cloud Storage Security Rules 使用 Cloud Firestore 文档内容 来评估安全条件, 系统会通过 Firebase 控制台或 Firebase CLI 提示您启用 相应权限以将这两款产品关联起来。
如果您决定停用此类跨服务安全性功能,请按以下步骤操作:
首先,在停用该功能之前,您需要先修改规则,移除所有 使用 Security Rules 函数控制对 Cloud Firestore 的访问权限的语句。 否则,在停用该功能后,Security Rules 评估会 导致 Storage 请求失败。
前往 Google Cloud 控制台中的 IAM 页面,参照撤消角色的 Cloud 指南删除 "Firebase Rules Firestore Service Agent" 角色。
当您下次从 Firebase CLI 或 Firebase 控制台保存 跨服务规则时,系统会提示您重新启用该功能。