管理及部署 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 中編輯時,系統會執行語法測試,而語意測試則可使用 Rules Playground。

修改及更新規則

  1. 開啟 Firebase 控制台,然後選取所需專案。
  2. 接著,在產品導覽中選取「Realtime Database」、「Cloud Firestore」或「Storage」,然後按一下「Rules」前往「Rules」編輯器。
  3. 直接在編輯器中修改規則。

測試更新

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

部署更新內容

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

使用 Admin SDK

您可以使用 Node.js 適用的 Admin SDK 規則集。透過這項程式輔助存取權,您可以:

  • 導入自訂工具、指令碼、資訊主頁和 CI/CD 管道,以便管理規則。
  • 輕鬆管理多項 Firebase 專案中的規則。

透過程式輔助方式更新規則時,請務必避免對應用程式進行意外的存取權控管變更。編寫 Admin SDK 程式碼時,請將其安全性優先考量,特別是在更新或部署規則時。

另一個重點是,Firebase 安全性規則版本需要幾分鐘才能全面生效。使用 Admin SDK 部署規則時,請務必避免應用程式立即依賴部署作業尚未完成的規則。如果您的用途需要頻繁更新存取控管規則,請考慮使用 Cloud Firestore 的解決方案,這個解決方案旨在即使經常更新,也能減少競爭狀況。

同時請注意下列限制:

  • 序列化文字時,規則必須小於 256 KiB 的 UTF-8 編碼文字。
  • 每項專案最多可以部署 2,500 個部署規則集。一旦達到上限,您必須先刪除部分舊規則集,才能建立新規則。

建立及部署 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 編碼文字。
  • 每項專案最多可以部署 2,500 個部署規則集。一旦達到上限,您必須先刪除部分舊規則集,才能建立新規則。

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

如要追蹤這項資訊,請將該值與您的 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 安全性規則版本需要幾分鐘的時間才能完全生效。使用 Management REST API 部署時,請確保避免應用程式立即依賴部署作業尚未完成的規則。

使用 REST 更新即時資料庫規則集

即時資料庫提供專屬的 REST 介面,可用於管理規則。請參閱透過 REST 管理 Firebase 即時資料庫規則

使用 REST 管理規則集

為協助管理大型規則部署,除了建立規則集和版本的 REST 方法之外,管理 API 也提供以下方法:

  • 列出、取得及刪除規則集
  • 列出、取得及刪除規則的版本

如果是隨著時間達到 2500 規則集限制的非常大型部署,您可以建立邏輯,刪除固定週期中最舊的規則。舉例來說,如要刪除部署超過 30 天的所有規則集,您可以呼叫 projects.rulesets.list 方法,剖析 Ruleset 物件在其 createTime 鍵上的 JSON 清單,然後透過 ruleset_id 對相應規則集呼叫 project.rulesets.delete

使用 REST 測試更新

最後,管理 API 可讓您在實際工作環境專案中,對 Cloud Firestore 和 Cloud Storage 資源執行語法和語意測試。

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

  1. 定義 TestSuite JSON 物件,代表一組 TestCase 物件
  2. 正在提交 TestSuite
  3. 剖析傳回的 TestResult 個物件

接著在 testcase.json 檔案中定義含有單一 TestCaseTestSuite 物件。在這個範例中,我們將內嵌 REST 酬載中的「Rules」語言來源,以及測試套件,以便針對這些規則執行。我們指定了規則評估預期,以及要測試規則集的用戶端要求。您也可以使用「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 Storage 安全性規則使用 Cloud Firestore 文件內容評估安全條件,Firebase 控制台或 Firebase CLI 會提示您啟用權限,以啟用連結這兩項產品的權限。

若您決定停用這類跨服務安全性功能:

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

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

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