管道作業的安全性規則

管道作業規則可讓您比對現有規則引擎的篩選功能。雖然管道作業提供豐富的功能,但規則引擎僅限於辨識簡單的篩選器,以確保查詢可滿足需求和安全性。

版本和模式需求

本文適用於原生模式的 Firestore Enterprise 版。

支援的篩選運算式

查詢必須使用標準比較運算子與常數,才能受到規則限制。規則引擎可辨識下列篩選器類型:

  • 相等和不相等:eq、neq。
  • 比較:gt、gte、lt、lte。
  • 會員資格:in、arrayContains。

例如:

  • where(eq("foo", 2))
  • where(lt("foo", 2))
  • documents("/user/1", "/user/2").where(...)

要求屬性

您可以繼續使用 request 物件驗證驗證和查詢內容,但管道不支援標準查詢中的部分屬性。

支援的屬性

新引擎仍支援下列屬性:

  • request.auth:存取使用者 UID 和權杖資料。
  • request.method:識別作業 (例如 get、list)。
  • request.path:存取資源的路徑。
  • request.time:要求的伺服器端時間戳記。

不支援的屬性

由於在多級式查詢中判斷這些值相當複雜,因此管道規則檢查不支援 request.query 屬性,例如 limit、offset 和 orderBy。

管道階段處理和權限

管道階段有許多種,分別對應安全性規則中的特定精細作業:

  • allow list 權限:由 collection()、collectionGroup() 和 database() 階段觸發。
  • allow get 權限:由 documents() 階段觸發,處理方式與批次 get 作業類似。
  • allow create 權限:建立新文件時,由 insert() 階段和 upsert() 階段觸發。
  • allow update 權限:由 update() 階段觸發,更新現有文件時則由 upsert() 階段觸發。
  • allow delete 權限:由 delete() 個階段觸發。
  • allow write 權限:適用於所有 DML 作業 (insert()、update()、upsert() 和 delete())。
  • 欄位修改階段:規則只會對儲存的資料執行,不會對衍生值執行。如果管道包含修改欄位的階段 (例如 AddFields、ReplaceWith、Select),規則引擎會在遇到該階段後停止套用篩選器限制。
  • 常值階段:literals() 階段不會從資料庫讀取資料,但可能會產生費用。為防範濫用情形,必須與可由規則驗證的其他階段 (例如 collection()) 搭配使用。

data manipulation language (DML) 階段和安全性規則

執行資料操縱語言 (DML) 階段 (insert()、update()、upsert() 和 delete()) 時,安全性規則評估權限的方式與讀取查詢不同:

  • 逐一評估文件規則:讀取管道需要預先提供篩選運算式,以便在規劃階段限制查詢,但 DML 作業會針對每項文件異動評估安全性規則。
  • 規則變數:
    • request.resource:包含 insert()、update() 和 upsert() 作業的建議文件資料。
    • resource:包含修改前儲存在資料庫中的目前文件資料 (適用於現有文件的 update()、delete() 和 upsert())。

DML 的系統限制和執行行為

使用安全性規則執行 DML 作業時,請注意下列系統限制和執行行為:

get() 和 exists() 的查詢次數上限為 20 次

Firebase 安全性規則允許在整個要求中最多執行 20 次文件查詢 (get() 或 exists())。

如果 DML 管道在明確交易外執行,文件會分批處理。由於每個批次都會在自己的交易中執行,且文件可能會在批次之間同時修改,因此系統會針對每個寫入批次重新評估安全性規則和文件查詢。

即使安全性規則是針對單一靜態文件進行評估,例如檢查使用者是否為管理員:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /posts/{postId} {
      allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin == true;
    }
  }
}

每批寫入的文件都會執行查詢。因此,在寫入所有可能的文件後,要求達到 20 次查詢限制,管道失敗並顯示 PERMISSION_DENIED 錯誤。此外,每個寫入批次執行的每次查詢,都會產生各自的讀取費用。

部分成功和PERMISSION_DENIED

在交易外執行時,DML 作業會依序批次提交寫入作業。如果批次作業失敗 (可能是因為文件不符合規則條件,或超過 20 次查詢限制),管道就會停止並傳回 PERMISSION_DENIED 錯誤。

不過,已提交的批次不會復原。資料庫會維持在部分更新狀態。由於用戶端收到的錯誤訊息不含已修改文件的清單,因此您必須查詢資料,檢查哪些寫入作業成功。

使用 Cloud 稽核記錄診斷規則失敗

基於安全考量,用戶端 PERMISSION_DENIED 錯誤不會揭露失敗的安全規則條件,或是否達到 20 次查詢限制。

如要診斷規則評估失敗的原因,專案管理員可以在 Google Cloud 控制台 (依序前往「Firestore」 >「Monitoring」或「Logs Explorer」) 查看 Cloud 稽核記錄,檢視詳細的EvaluationError項目。