管理和部署 Firebase 安全規則

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

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

  • 攝取規則:一組規則,通常含有火力地堡安全規則語句的代碼文件。
  • 存儲攝取源作為一個不可變的規則集
  • 跟踪釋放每個規則集的部署。啟用 Firebase 安全規則的服務查找項目的版本以評估對安全資源的每個請求。
  • 提供運行規則集的句法和語義的測試能力。

使用 Firebase CLI

隨著火力地堡CLI ,您可以上傳本地信號源和部署版本。該CLI的火力地堡本地模擬器套房可以執行的來源完全本地測試。

使用 CLI,您可以通過應用程序代碼將規則置於版本控制之下,並將規則部署為現有部署過程的一部分。

生成配置文件

當您配置使用CLI火力地堡火力地堡的項目,創建一個.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 控制台

您也可以編輯規則代碼,將其部署為從火力地堡的控制台版本。語法測試,你在火力地堡控制台UI編輯進行,symantic測試可使用規則遊樂場。

編輯和更新您的規則

  1. 打開火力地堡控制台,並選擇您的項目。
  2. 然後,從產品導航選擇實時數據庫雲計算公司的FireStore寄存,然後單擊規則導航到規則編輯器。
  3. 直接在編輯器中編輯您的規則。

測試您的更新

除了在編輯器UI測試語法,你可以測試語義規則的行為,使用項目的數據庫和存儲資源,直接在火力地堡控制台,使用規則遊樂場。打開規則遊樂場屏幕在規則編輯器,修改設置,然後點擊運行。在編輯器頂部查找確認消息。

部署更新

一旦你確信自己的更新您的期望,點擊發布

使用管理 SDK

您可以使用Node.js的規則集管理員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()

或者,您可以將規則文件創建為內存對象,創建規則集,然後單獨部署規則集以更密切地控制這些事件。例如:

    const rf = admin.securityRules().createRulesFileFromSource('firestore.rules', source);
    const rs = await admin.securityRules().createRuleset(rf);
    await admin.securityRules().releaseFirestoreRuleset(rs);

更新實時數據庫規則集

要更新管理SDK實時數據庫規則集,使用getRules()setRules()方法admin.database 。您可以檢索 JSON 格式的規則集,也可以檢索包含註釋的字符串。

要更新規則集:

    const source = `{
      "rules": {
        "scores": {
          ".indexOn": "score",
          "$uid": {
            ".read": "$uid == auth.uid",
            ".write": "$uid == auth.uid"
          }
        }
      }
    }`;
    await admin.database().setRules(source);

管理規則集

為了幫助管理大規則集,管理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這個API實驗參考文檔

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

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

讓我們假設你在你的工作secure_commerce火力地堡項目,並希望部署鎖定的雲存儲規則。您可以實現在這些規則storage.rules文件。

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if false;
    }
  }
}

現在,為此文件生成一個 base64 編碼的指紋。然後,您可以使用源文件來填充創建具有一個規則集所需的有效載荷projects.rulesets.create REST調用。在這裡,我們使用cat命令的內容插入storage.rules進入休息有效載荷。

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管理火力地堡實時的數據庫規則

使用 REST 管理規則集

為了幫助管理大型規則部署,除了用於創建規則集和發布的 REST 方法之外,管理 API 還提供了以下方法:

  • 列表,獲取和刪除規則集
  • 列表,獲取和刪除規則發布

對於隨著時間的推移達到 2500 個規則集限制的超大型部署,您可以創建邏輯以在固定時間週期內刪除最舊的規則。例如,要刪除部署了超過30天的所有規則集,你可以調用projects.rulesets.list方法,解析的JSON名單Ruleset對它們的對象createTime鍵,然後調用project.rulesets.delete由相應的規則集ruleset_id .

使用 REST 測試您的更新

最後,管理 API 允許您對生產項目中的 Cloud Firestore 和 Cloud Storage 資源運行句法和語義測試。

使用 API 的這個組件進行測試包括:

  1. 限定TestSuite JSON對象來表示的一組TestCase對象
  2. 提交TestSuite
  3. 解析返回TestResult對象

讓我們定義一個TestSuite對象與單一TestCasetestcase.json文件。在此示例中,我們傳遞了與 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"}}}
            }
          ]
      }
    ]
  }
}

然後,我們可以提出這樣TestSuite的評價;與projects.test方法。

curl -X POST -d '{
    ' $(cat testcase.json) '
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/rulesets/uuid123:test'

返回TestReport (含測試成功/失敗狀態,調試信息的列表,訪問規則表達式及其評價報告的列表)將與狀態成功確認訪問正確允許。