管理和部署 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 狀態確認正確允許訪問。