管理及部署 Firebase 安全性規則

Firebase 提供數種工具,方便您管理規則,每種工具在特定情況下都能派上用場,每項工具都使用相同的後端 Firebase Security Rules Management API。

無論叫用工具時使用的工具為何,管理 API 都會:

  • 擷取規則「來源」:一組規則,通常是包含 Firebase 安全性規則陳述式的程式碼檔案。
  • 將擷取的來源儲存為不可變更的規則
  • 追蹤版本中每個規則集的部署情況。已啟用 Firebase 安全性規則的服務會查詢專案的版本,藉此評估各項要求是否取得安全資源。
  • 可讓您執行規則集的語法和語意測試

使用 Firebase CLI

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

使用 CLI 可讓您確保規則與應用程式程式碼受到版本管控,並在現有部署程序中部署規則。

產生設定檔

使用 Firebase CLI 設定 Firebase 專案時,您必須在專案目錄中建立 .rules 設定檔。使用下列指令開始設定 Firebase 專案:

Cloud 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

Cloud Storage

// Set up Storage in your project directory, creates a .rules file
firebase init storage

編輯及更新規則

直接在 .rules 設定檔中編輯規則來源。

請確保您在 Firebase CLI 中做的任何變更都反映在 Firebase 控制台中,或者您持續使用 Firebase 主控台或 Firebase CLI 進行更新。否則,您可能會覆寫在 Firebase 控制台所做的任何更新。

測試更新

本機模擬器套件可為所有已啟用安全性規則的產品提供模擬器。每個模擬器的安全性規則引擎會同時執行規則的語法和語意評估,因此超越 Security Rules Management API 提供的語法測試作業。

如果您正在使用 CLI,則非常適合使用套件來測試 Firebase 安全性規則。使用本機模擬器套件在本機測試更新,並確認應用程式的規則表現出您想要的行為。

部署更新

更新及測試規則之後,請將來源部署至實際工作環境。

針對 Cloud Firestore 安全性規則,請查看並更新 firebase.json 檔案,將 .rules 檔案與預設及其他已命名的資料庫建立關聯。

您可以使用下列指令來選擇性部署規則,或將其做為正常部署程序的一部分進行部署。

Cloud 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

Cloud Storage

// Deploy your .rules file
firebase deploy --only storage

使用 Firebase 控制台

您也可以在 Firebase 控制台編輯規則「來源」,並將其部署為「版本」。系統會在 Firebase 主控台 UI 中編輯時,執行語法測試,並使用「規則 Playground」進行語意測試。

編輯及更新規則

  1. 開啟 Firebase 控制台,然後選取所需專案。
  2. 接著在產品導覽介面中選取「即時資料庫」、「Cloud Firestore」或「儲存空間」,然後點選「規則」前往「規則」編輯器。
  3. 直接在編輯器中編輯規則。

測試更新

除了在編輯器 UI 中測試語法外,您還可以使用 Rules Playground,直接在 Firebase 控制台中使用專案的資料庫和儲存空間資源測試語意規則行為。在「規則」編輯器中開啟「Rules Playground」畫面,修改設定,然後按一下「Run」。查看編輯器頂端是否有確認訊息。

部署更新

確認更新內容正確無誤後,請按一下「發布」

使用 Admin 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 安全性規則,但建議您使用 Management API 本身來管理及部署 Firebase 安全性規則。Management API 給您最大的彈性。

此外,也請注意下列限制:

  • 規則序列化時,必須小於 256 KiB (採用 UTF-8 編碼的文字)。
  • 每項專案的已部署規則集最多可達 2500 個。達到此上限後,您必須先刪除一些舊規則集,才能建立新規則集。

使用 REST 建立及部署 Cloud Firestore 或 Cloud Storage 規則集

本節中的範例使用的是 Firestore 規則,但也適用於 Cloud Storage 規則。

這些範例也使用 cURL 發出 API 呼叫。並未提供設定及傳遞驗證權杖的步驟。您可以使用與參考說明文件整合的 API Explorer 試用這個 API。

使用 Management 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 酬載。

如要進行追蹤,請將 attachment_point 設為 east_store,以將這個資料庫與資料庫建立關聯。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 安全性規則版本需要幾分鐘才能全面生效。使用 Management 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 (包含測試成功/失敗狀態、偵錯訊息清單、已造訪的規則運算式清單及評估報告) 會以 SUCCESS 狀態確認已允許存取。

管理跨服務的 Cloud Storage 安全性規則權限

如果您建立使用Cloud Firestore 文件內容來評估安全性條件的 Cloud Storage 安全性規則,系統會在 Firebase 主控台或 Firebase CLI 中提示您啟用連線這兩項產品的權限。

如果決定停用這類跨服務安全防護機制:

  1. 首先,請先編輯規則,移除使用規則函式存取 Cloud Firestore 的所有陳述式。否則,在停用這項功能後,規則評估會導致 Storage 要求失敗。

  2. 按照撤銷角色的 Cloud 指南操作,使用 Google Cloud 控制台中的「IAM」頁面刪除「Firebase Rules Firestore 服務代理」角色。

下次透過 Firebase CLI 或 Firebase 主控台儲存跨服務規則時,系統會提示您重新啟用功能。