获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

管理和部署 Firebase 安全规则

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 进行语义测试。

编辑和更新您的规则

  1. 打开Firebase 控制台并选择您的项目。
  2. 然后,从产品导航中选择Realtime DatabaseCloud FirestoreStorage ,然后单击Rules以导航到规则编辑器。
  3. 直接在编辑器中编辑您的规则。

测试您的更新

除了在编辑器 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 管理安全规则的典型工作流程可能包括三个独立的步骤:

  1. 创建规则文件源(可选)
  2. 创建规则集
  3. 发布或部署新规则集

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.databasegetRules()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 创建和部署规则集的典型步骤是:

  1. 创建规则文件源
  2. 创建规则集
  3. 发布(部署)新规则集

假设您正在处理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 组件进行的测试包括:

  1. 定义一个TestSuite JSON 对象来表示一组TestCase对象
  2. 提交TestSuite
  3. 解析返回TestResult对象

让我们在testcase.json文件中定义一个带有单个TestCaseTestSuite对象。在此示例中,我们传递与 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 中提示您启用连接这两个产品的权限。

如果您决定禁用此类跨服务安全性:

  1. 首先,在禁用该功能之前,编辑您的规则,删除所有使用规则函数访问 Cloud Firestore 的语句。否则,禁用该功能后,规则评估将导致您的存储请求失败。

  2. 使用 Google Cloud Console 中的IAM页面按照Cloud guide for revoking roles删除“Firebase Rules Firestore Service Agent”角色。

下次您从 Firebase CLI 或 Firebase 控制台保存跨服务规则时,系统将提示您重新启用该功能。