管理和部署 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 控制台儲存跨服務規則時,系統會提示您重新啟用功能。