Catch up on highlights from Firebase at Google I/O 2023. Learn more

管理和部署 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文件中定義一個帶有單個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 中提示您啟用連接這兩個產品的權限。

如果您決定禁​​用此類跨服務安全性:

  1. 首先,在禁用該功能之前,編輯您的規則,刪除所有使用規則函數訪問 Cloud Firestore 的語句。否則,禁用該功能後,規則評估將導致您的存儲請求失敗。

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

下次您從 Firebase CLI 或 Firebase 控制台保存跨服務規則時,系統將提示您重新啟用該功能。