iT邦幫忙

2025 iThome 鐵人賽

DAY 9
0
Security

『零信任』的革命:從 FIDO 協議到自動化部署,30天打造次世代身分認證系統系列 第 9

Day 09: 【數據庫安全】Firestore 的安全規則與資料庫結構設計

  • 分享至 

  • xImage
  •  

前言:定義數據持久層與存取控制

在 Day 08 完成後端執行環境的部署後,今天的核心任務是建構我們應用的數據持久層。我們將使用 Cloud Firestore,一個 NoSQL、文件導向的資料庫,來儲存使用者及 FIDO 憑證資訊。

在零信任架構中,數據庫本身就是一道關鍵的安全防線。因此,我們的工作將分為兩個主要部分:

  1. 資料庫結構 (Schema) 設計:根據 Day 06 的規劃,我們將實現一個清晰、可擴展的資料結構。
  2. 安全規則 (Security Rules) 編寫:我們將定義一組伺服器端的存取控制規則,以實踐「最小權限原則」,確保數據只能被合法授權的實體存取。

這個階段的目標是建立一個不僅結構合理,而且本質安全的數據基礎。


章節一:Firestore 資料結構實現

Firestore 以「集合 (Collections)」和「文件 (Documents)」的形式組織數據。基於 Day 06 的設計,我們將實現以下結構:

1. users 集合
此集合用於儲存使用者帳戶的基本資訊。每個文件代表一個獨立的使用者。

  • 路徑: /users/{userId}
  • 結構:
    • email (String): 使用者的唯一識別符,用於登入流程。
    • displayName (String): 使用者的顯示名稱。
    • createdAt (Timestamp): 帳戶建立的時間戳。

2. credentials 子集合
這是 FIDO 的核心數據儲存區。我們將其設計為 users 文件下的一個子集合,以清晰地表達使用者與其憑證之間的一對多關係。

  • 路徑: /users/{userId}/credentials/{credentialId}
  • 結構:
    • publicKey (String): Base64 編碼後的公鑰字串(CBOR 格式)。這是後端驗證簽章的必要數據。
    • signCount (Number): 簽章計數器,用於防範重放攻擊,初始值為 0。
    • transports (Array of Strings): 記錄驗證器的傳輸類型,例如 ["internal"]["usb"]
    • createdAt (Timestamp): 憑證註冊的時間戳。

這個結構將用戶身份資訊與更敏感的加密憑證資訊進行了邏輯隔離,便於我們後續定義更精細的存取權限。


章節二:編寫 Firestore 安全規則

Firestore 安全規則提供強大的伺服器端授權能力。我們的核心原則是預設拒絕 (Default Deny):除非有規則明確允許,否則所有對數據的讀寫操作都將被拒絕。

打開專案根目錄下的 firestore.rules 檔案,並用以下內容覆蓋:

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {

    // 規則 1: 保護 users 集合
    match /users/{userId} {
      // 僅允許已驗證身分的用戶讀取或建立自己的資料文件。
      // request.auth.uid 是 Firebase Authentication 提供的用戶唯一 ID。
      allow read, create: if request.auth != null && request.auth.uid == userId;

      // 禁止用戶端直接更新或刪除用戶文件,這些操作應由後端邏輯控制。
      allow update, delete: if false;
    }

    // 規則 2: 保護 credentials 子集合
    match /users/{userId}/credentials/{credentialId} {
      // 僅允許用戶為自己建立新的憑證(在 FIDO 註冊流程中)。
      allow create: if request.auth != null && request.auth.uid == userId;

      // **極其重要**: 明確禁止任何來自用戶端的讀取、更新、刪除操作。
      // credential 資料只應由我們的後端服務(使用 Admin SDK)進行讀取與更新。
      // 這可以防止用戶端直接查詢到公鑰、簽章計數等敏感資訊。
      allow read, update, delete: if false;
    }
  }
}

規則解釋:

  • match /users/{userId}: 此規則應用於 users 集合下的所有文件。
    • allow read, create: 我們允許一個經過 Firebase Authentication 驗證的用戶讀取和創建與其 uid 相符的文件。這涵蓋了用戶註冊和讀取自己個人資料的場景。
    • allow update, delete: if false;: 我們明確禁止了從客戶端直接修改或刪除用戶資料,這確保了數據的一致性與安全性。
  • match /users/{userId}/credentials/{credentialId}: 此規則應用於 credentials 子集合。
    • allow create: 允許用戶在註冊新的 FIDO 驗證器時,創建一筆新的憑證記錄。
    • allow read, update, delete: if false;: 這是我們安全模型的核心。我們不允許客戶端以任何方式讀取或修改已存在的憑證。例如,在登入驗證時,是我們的後端 Functions 需要讀取 publicKeysignCount,而不是前端應用。後端服務使用 Admin SDK 進行初始化,它將繞過這些安全規則,以管理員權限存取數據。此設計有效防止了不必要的資訊洩漏風險。

章節三:部署與測試安全規則

完成規則編寫後,需要將其部署到雲端使其生效。

  1. 部署規則:
    在專案根目錄的終端機中,執行以下指令:

    firebase deploy --only firestore:rules
    

    成功後,新的安全規則將立即生效。

  2. 使用 Rules Playground 進行測試:
    在 Firebase Console 中,導航至 Firestore Database > 規則 (Rules) 標籤頁,即可找到「規則模擬遊樂場」(Rules Playground)。這是驗證規則邏輯的強大工具。

    測試案例 1: 用戶讀取自己的資料 (預期: 成功)

    • 模擬類型: get
    • 路徑: /users/testUser123
    • 驗證: 開啟「已驗證」,並在 uid 欄位中輸入 testUser123
    • 結果: 點擊「執行」,模擬請求應被允許。

    測試案例 2: 用戶讀取他人的資料 (預期: 失敗)

    • 模擬類型: get
    • 路徑: /users/anotherUser456
    • 驗證: 開啟「已驗證」,uid 欄位仍為 testUser123
    • 結果: 請求應被拒絕。

    測試案例 3: 用戶讀取自己的憑證 (預期: 失敗)

    • 模擬類型: get
    • 路徑: /users/testUser123/credentials/someCredentialId
    • 驗證: 開啟「已驗證」,uidtestUser123
    • 結果: 請求應被明確拒絕,證明我們的 allow read: if false; 規則有效。

結論:建立安全的數據基礎

今天,我們基於 Day 06 的設計,成功在 Firestore 中定義了數據結構,並部署了一套遵循「最小權限原則」的安全規則。這確保了我們的數據庫層本身就是一道堅固的防線,客戶端僅被授予絕對必要的操作權限,而敏感的憑證數據則被保護起來,僅供後端服務存取。

在資料庫層面建立起安全屏障後,我們明天的任務將是為後端程式碼選擇並設定一個 FIDO2/WebAuthn 的伺-服器端函式庫。這將是我們開始處理複雜密碼學驗證的關鍵一步。


上一篇
Day 08: 【後端起手式】Firebase Functions:打造 Serverless FIDO 後端服務
系列文
『零信任』的革命:從 FIDO 協議到自動化部署,30天打造次世代身分認證系統9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言