管理和部署 Firebase 安全性規則

Firebase 為您提供了多種管理規則的工具,每種工具在特定情況下都很有用,並且每種工具都使用相同的後端 Firebase 安全規則管理 API。

無論使用哪個工具調用,管理API:

  • 提取規則:一組規則,通常是包含 Firebase 安全規則語句的代碼文件。
  • 將攝取的源存儲為不可變的規則集
  • 跟踪版本中每個規則集的部署。支持 Firebase 安全規則的服務會查找項目的版本,以評估對安全資源的每個請求。
  • 提供運行規則集的語法和語義測試的功能。

使用 Firebase CLI

使用Firebase CLI ,您可以上傳本地並部署版本。 CLI 的 Firebase 本地模擬器套件可讓您對執行完整的本地測試。

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

測試您的更新

本地仿真器套件為所有支持安全規則的產品提供仿真器。每個模擬器的安全規則引擎執行規則的語法和語義評估,從而超出了安全規則管理 API 提供的語法測試。

如果您使用 CLI,該套件是 Firebase 安全規則測試的絕佳工具。使用本地模擬器套件在本地測試您的更新,並確認您的應用程序的規則表現出您想要的行為。

部署您的更新

更新並測試規則後,將源部署到生產環境。

對於 Cloud Firestore 安全規則,通過檢查和更新firebase.json文件.rules文件與默認數據庫和其他命名數據庫關聯。

使用以下命令有選擇地單獨部署您的規則或將它們作為正常部署過程的一部分進行部署。

雲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>

實時數據庫

// 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來測試語義規則行為。在規則編輯器中打開Rules Playground屏幕,修改設置並單擊Run 。在編輯器頂部查找確認消息。

部署您的更新

一旦您對更新符合預期感到滿意,請單擊“發布”

使用管理 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

上述工具非常適合各種工作流程,包括項目中多個 Cloud Firestore 數據庫的 Firebase 安全規則管理,但您可能希望使用管理 API 本身來管理和部署 Firebase 安全規則。管理 API 為您提供最大的靈活性。

另請注意這些限制:

  • 序列化時,規則必須小於 256 KiB 的 UTF-8 編碼文本。
  • 一個項目最多可以有 2500 個已部署的規則集。一旦達到此限制,您必須在創建新規則集之前刪除一些舊規則集。

使用 REST 創建和部署 Cloud Firestore 或 Cloud Storage 規則集

本部分中的示例使用 Firestore 規則,但它們也適用於 Cloud Storage 規則。

這些示例還使用 cURL 進行 API 調用。省略了設置和傳遞身份驗證令牌的步驟。您可以使用與參考文檔集成的 API Explorer 來試驗此 API。

使用管理 API 創建和部署規則集的典型步驟是:

  1. 創建規則文件源
  2. 創建規則集
  3. 發布(部署)新規則集。

創建源

假設您正在開發secure_commerce Firebase 項目,並希望將鎖定的 Cloud Firestore 規則部署到項目中名為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 安全規則發布需要幾分鐘時間才能完全傳播。使用管理 REST API 進行部署時,請確保避免應用程序立即依賴於部署尚未完成的規則的競爭情況。

使用 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 (包含測試成功/失敗狀態、調試消息列表、訪問的規則表達式列表及其評估報告)將通過狀態成功確認訪問被正確允許。

管理跨服務雲存儲安全規則的權限

如果您創建使用Cloud Firestore 文檔內容來評估安全條件的雲存儲安全規則,系統會在 Firebase 控制台或 Firebase CLI 中提示您啟用連接這兩個產品的權限。

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

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

  2. 使用 Google Cloud Console 中的IAM頁面,按照撤銷角色的雲指南刪除“Firebase Rules Firestore Service Agent”角色。

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