為 GCP Cloud Run 加上呼叫 key 保護

之前筆記 使用 Google Api Gateway 為 Google Cloud Functions 加上 API Key 保護 紀錄如何透過 Api Gateway 設定 key 來保護 Cloud Functions 避免被無差異呼叫攻擊,最近剛好有個類似的需求,雖然有著之前的經驗加上筆記 使用 Google Api Gateway 為 Google Cloud Functions 加上 API Key 保護 的幫助下,實作的速度不慢,但也不如預期的快,原因是兩個:

  1. GCP 的 Serverless Solution 改版:Cloud Functions –> Cloud Run (雖然 Cloud Functions 仍然可以使用,但當然要用新的 雲端的 solution 迭代速度常常讓人措手不及)
  2. 筆記 Google Cloud Functions 發送訊息到 Google Cloud Pub/Sub使用 Google Api Gateway 為 Google Cloud Functions 加上 API Key 保護 還是有些地方不夠完整

所以趁著這次機會了解一下 Cloud Run 與補充之前筆記的不足之處

基本環境說明

  • macOS Sonoma 14.6.1 (Apple M2 Pro)
  • OrbStack 1.6.4 (17192)
  • .NET SDK 8.0.401

設定方式

  1. 建立 Cloud Run Service

    • 基本設定

      沒有預設值的是 14,其他部份皆可使用預設值 (2 是選近點的反應比較快、3 是個人熟悉的語言)

      1cloudrun

    • 程式碼

      以下使用預設內容做為範例

    • 設定完成後紀錄端點網址,後續設定 api gateway 時會用到

      16runurl

  2. IAM 與管理 –> 服務帳戶 –> 建立服務帳戶

    • 服務帳戶詳細資料

      設定服務帳戶名稱與服務帳戶 ID

      2createsa

    • 將專案存取權授予這個服務帳戶 (選用)

      需要 Cloud Run 叫用者 權限

      3createsa)

    • 將這個服務帳戶的存取權授予使用者 (選用)

      這不需要額外設定,保持預設值即可

  3. API Gateway –> 建立閘道

    • API

      設定顯示名稱與 API ID

      4createapi

    • API 設定

      • 上傳 API Spec

        • paths./ 是 api url 後面的路徑,設定 route 的部份
        • paths./.post 允許使用 post
        • paths./.post.x-google-backend.address{cloud function url} 要記得改成正確的值
        • paths./.post.parameters 使用 url query 的方式來傳遞型態為 stringname 參數
        • paths./.post.security 表示 / 這個 route 下沒有預設的 api_key
        • securityDefinitions 用來指定 api_key 如何傳遞
      • 設定顯示名稱並選取使用上面建立的服務帳戶

        5apiconfig

    • 閘道詳細資料

      設定顯示名稱與部署位置(部置只有部份地區可以選擇)

      6gateway-detail

  4. API 與服務 –> 啟用API 與服務

    要等上一步驟的 api 確定建立後才能執行啟用

    7apiservice

    8enableapi

  5. API 與服務 –> 建立憑證 (API 金鑰)

    為 api 新增 crendential API Key

    9apikey

  6. API 與服務 –> 編輯 API 金鑰

    為 API Key 加上呼叫限制,限制只能 access 自訂的 api (預設可以存取所有 api)

    10apistrict

  • 使用方式

    • API Gateway 中選取目標 API

      11api

    • 閘道 可以取得對外的 url

      12gatewayurl

    • 實際使用

      • 未帶 api key 或是 key 不正確:會得到 401 UNAUTHENTICATED

        13unauth

      • 使用正確 api key:會得到 Hello world!

        api key 的使用方式是在 url 後面加上 ?key={api key} (這個是由 step 3 中上傳的 api config 所設定的)

        14withkey)

      • 使用正確 api key 並加上 name:會得到 Hello {name}!

        15withkeyname)

心得

Cloud Function 與 Cloud Run 的差異

功能Cloud Functions (第 1 代)Cloud Functions (第 2 代) - Cloud Run
Image registryContainer Registry 或 Artifact Registry僅限 Artifact Registry
Request timeout最長 9 分鐘- HTTP 觸發,最長 60 分鐘
- 事件觸發,最長 9 分鐘
規格最多 2 個 vCPU,最高 8GB 的 RAM最多 4 個 vCPU,最高 16GiB 的 RAM
Concurrency每個 function instance 1 個 request每個 function instance最多 1,000 個 request
流量分配不支援支援
事件類型支援 Pub/Sub triggers、Cloud Storage triggers、Firestore triggers、Google Analytics for Firebase triggers、Firebase Realtime Database triggers、Firebase Authentication triggers、Firebase Remote Config triggers支援 Pub/Sub triggers、Cloud Storage triggers、Firestore triggers 與 Generalized Eventarc triggers (Eventarc 所支援的任何事件類型,包括通過 Cloud Audit Logs 提供的 90 多個事件來源)
CloudEvents只支援 Ruby、.NET 和 PHP runtime所有語言 runtime 都支援

Cloud Run 與 Cloud Functions 就我自己使用起來體感差異不大,甚至連 dotnet 的 project template 都相同,不過後續相關的設定會些許不同,但差異也不大,原則上應該可以直接轉換

參考資訊

  1. Google Cloud Functions 發送訊息到 Google Cloud Pub/Sub
  2. 使用 Google Api Gateway 為 Google Cloud Functions 加上 API Key 保護
  3. Cloud Run functions version comparison