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

管理和部署 Firebase 安全规则

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

Firebase 为您提供了多种工具来管理您的规则,每种工具在特定情况下都很有用,并且每种工具都使用相同的后端 Firebase 安全规则管理 API。

无论使用哪个工具调用它,管理 API:

  • 摄取规则:一组规则,通常是包含 Firebase 安全规则语句的代码文件。
  • 将摄取的源存储为不可变的规则集
  • 跟踪发布中每个规则集的部署。启用 Firebase 安全规则的服务会查找项目的版本,以评估对安全资源的每个请求。
  • 提供运行规则集的句法和语义测试的能力。

使用 Firebase CLI

使用Firebase CLI ,您可以上传本地资源并部署版本。 CLI 的 Firebase Local Emulator Suite 可让您对执行完整的本地测试。

使用 CLI 允许您使用应用程序代码将规则置于版本控制之下,并将规则部署为现有部署过程的一部分。

生成配置文件

使用 Firebase CLI 配置 Firebase 项目时,您会在项目目录中创建一个.rules配置文件。使用以下命令开始配置您的 Firebase 项目:

云防火墙

// 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 控制台中所做的任何更新。

测试您的更新

本地仿真器套件为所有启用安全规则的产品提供仿真器。每个模拟器的安全规则引擎都执行规则的语法和语义评估,因此超过了安全规则管理 API 提供的语法测试。

如果您使用 CLI,套件是 Firebase 安全规则测试的绝佳工具。使用本地模拟器套件在本地测试您的更新,并确认您的应用程序规则表现出您想要的行为。

部署更新

更新和测试规则后,将源部署到生产环境。使用以下命令有选择地单独部署规则或将它们部署为正常部署过程的一部分。

云防火墙

// 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. 然后,从产品导航中选择实时数据库Cloud Firestore存储,然后单击规则导航到规则编辑器。
  3. 直接在编辑器中编辑您的规则。

测试您的更新

除了在编辑器 UI 中测试语法外,您还可以使用项目的数据库和存储资源直接在 Firebase 控制台中使用Rules Playground测试语义规则行为。在规则编辑器中打开规则游乐场屏幕,修改设置并单击运行。在编辑器顶部查找确认消息。

部署更新

一旦您对更新符合您的预期感到满意,请单击Publish

使用管理 SDK

您可以使用适用于 Node.js规则集的 Admin SDK。通过这种编程访问,您可以:

  • 实施用于管理规则的自定义工具、脚本、仪表板和 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 项目并希望部署锁定的 Cloud Storage 规则。您可以在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页面删除“Firebase Rules Firestore Service Agent”角色,方法是按照Cloud guide for revking roles

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