iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
Build on Google AI

將考國際證照的應用程式變成開源系列 第 21

學習筆記:Google Cloud API Gateway (純 CLI 部署與安全防護)

  • 分享至 

  • xImage
  •  

https://www.skills.google/games/7399/labs/45437

📖 學習筆記:Google Cloud API Gateway (純 CLI 部署與安全防護)

📝 核心目標

  1. 部署一個 Cloud Function 作為後端微服務。
  2. 建立 API Gateway 作為統一入口,並將流量路由至該 Function。
  3. 透過 OpenAPI 規範 (Swagger) 設定路由規則。
  4. 使用 API Key 限制存取權限,保護後端服務。

階段一:環境準備與部署後端服務

在建立 API Gateway 之前,我們必須先有一個能接收請求的真實後端服務(這裡使用 Cloud Functions)。

# 1. 設定預設地區 (Region)
gcloud config set compute/region us-east1

# 2. 將專案 ID 與 Number 存入變數,方便後續腳本呼叫
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")

# 3. 啟用此架構所需的所有核心 API
# 包含:API Gateway 服務、Cloud Functions 服務、API 金鑰管理服務
gcloud services enable \
  apigateway.googleapis.com \
  cloudfunctions.googleapis.com \
  apikeys.googleapis.com

# 4. 下載官方範例程式碼並進入目錄
git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git
cd nodejs-docs-samples/functions/helloworld/helloworldGet

# 5. 部署 Cloud Function (名稱: helloGET)
# 設定為允許未經驗證的呼叫 (--allow-unauthenticated),因為驗證將交由前方的 API Gateway 處理
gcloud functions deploy helloGET \
  --runtime nodejs22 \
  --trigger-http \
  --allow-unauthenticated \
  --region us-east1

# 6. 測試後端服務是否部署成功
export FUNCTION_URL=$(gcloud functions describe helloGET --region us-east1 --format="value(httpsTrigger.url)")
curl -sL $FUNCTION_URL
# 預期輸出: Hello World!


階段二:建立 API Gateway (基礎路由)

API Gateway 的架構分為三個層級:API (邏輯群組) -> API Config (路由與安全規則,不可變動) -> Gateway (實際對外服務的節點)。

# 1. 產生一個隨機的 API ID (避免命名衝突)
cd ~
export API_ID="hello-world-$(cat /dev/urandom | tr -dc 'a-z' | fold -w 8 | head -n 1)"

# 2. 建立 OpenAPI 規範檔 (openapi2-functions.yaml)
# 這裡定義了 /hello 路徑,並使用 x-google-backend 擴展語法將流量導向剛才部署的 Function
cat <<EOF > openapi2-functions.yaml
swagger: '2.0'
info:
  title: ${API_ID} description
  description: Sample API on API Gateway with a Google Cloud Functions backend
  version: 1.0.0
schemes:
  - https
produces:
  - application/json
paths:
  /hello:
    get:
      summary: Greet a user
      operationId: hello
      x-google-backend:
        address: https://us-east1-${PROJECT_ID}.cloudfunctions.net/helloGET
      responses:
        '200':
          description: A successful response
          schema:
            type: string
EOF

# 3. 建立 API 邏輯資源
gcloud api-gateway apis create $API_ID \
  --display-name="Hello World API" \
  --project=$PROJECT_ID

# 4. 建立 API Config (綁定剛剛寫好的 OpenAPI yaml 檔)
# 注意:API Config 建立後即為 Read-Only,若要改規則只能建立新的 Config
gcloud api-gateway api-configs create hello-world-config \
  --api=$API_ID \
  --openapi-spec=openapi2-functions.yaml \
  --project=$PROJECT_ID \
  --display-name="Hello World Config" \
  --backend-auth-service-account=${PROJECT_NUMBER}-compute@developer.gserviceaccount.com

# 5. 建立 Gateway 實體並掛載 Config (此步驟需等待幾分鐘進行佈建)
gcloud api-gateway gateways create hello-gateway \
  --api=$API_ID \
  --api-config=hello-world-config \
  --location=us-east1 \
  --project=$PROJECT_ID \
  --display-name="Hello Gateway"

# 6. 取得 Gateway 的專屬網址並測試路由
export GATEWAY_URL=$(gcloud api-gateway gateways describe hello-gateway --location us-east1 --format json | jq -r .defaultHostname)
curl -sL https://$GATEWAY_URL/hello
# 預期輸出: Hello World!


階段三:實作 API 金鑰 (API Key) 防護

為了防止 API 被濫用,我們在 Gateway 層加上金鑰驗證。只有帶有合法 ?key=xxx 參數的請求才能通過。

# 1. 取得這組 API 專屬的 Managed Service 名稱,並允許該服務使用 API Key
export MANAGED_SERVICE=$(gcloud api-gateway apis list --format json | jq -r .[0].managedService | cut -d'/' -f6)
gcloud services enable $MANAGED_SERVICE

# 2. 建立一把專用的 API Key,並限制這把鑰匙只能存取我們的 Managed Service
gcloud services api-keys create \
  --display-name="Hello API Key" \
  --api-target=service=$MANAGED_SERVICE

# 3. 抓取這把金鑰的明碼字串並存入變數
export API_KEY=$(gcloud services api-keys get-key-string \
  $(gcloud services api-keys list --filter="displayName='Hello API Key'" --format="value(name)") \
  --format="value(keyString)")

# 4. 建立第二版 OpenAPI 規範檔 (openapi2-functions2.yaml)
# 新增了 security 與 securityDefinitions 區塊來宣告 API Key 驗證機制
cat <<EOF > openapi2-functions2.yaml
swagger: '2.0'
info:
  title: ${API_ID} description
  description: Sample API on API Gateway with a Google Cloud Functions backend
  version: 1.0.0
schemes:
  - https
produces:
  - application/json
paths:
  /hello:
    get:
      summary: Greet a user
      operationId: hello
      x-google-backend:
        address: https://us-east1-${PROJECT_ID}.cloudfunctions.net/helloGET
      security:
        - api_key: []
      responses:
        '200':
          description: A successful response
          schema:
            type: string
securityDefinitions:
  api_key:
    type: "apiKey"
    name: "key"
    in: "query"
EOF

# 5. 建立新的 API Config (使用包含了 Security 設定的第二版 yaml 檔)
gcloud api-gateway api-configs create hello-config-secure \
  --api=$API_ID \
  --openapi-spec=openapi2-functions2.yaml \
  --project=$PROJECT_ID \
  --display-name="Hello Config Secure" \
  --backend-auth-service-account=${PROJECT_NUMBER}-compute@developer.gserviceaccount.com

# 6. 更新 Gateway,將流量切換到具有防護能力的新 Config (此步驟需等待幾分鐘)
gcloud api-gateway gateways update hello-gateway \
  --api=$API_ID \
  --api-config=hello-config-secure \
  --location=us-east1 \
  --project=$PROJECT_ID


階段四:防護驗證測試

Gateway 更新完畢後,進行最終的安全測試:

# 測試 1:不帶任何身分驗證呼叫 API
curl -sL https://$GATEWAY_URL/hello
# 預期輸出:拒絕存取錯誤 (UNAUTHENTICATED: Method doesn't allow unregistered callers)

# 測試 2:在 URL 參數中帶上我們建立的 API Key
curl -sL -w "\n" "https://${GATEWAY_URL}/hello?key=${API_KEY}"
# 預期輸出:Hello World! (成功放行)

💡 核心觀念總結:

  • 解耦 (Decoupling):後端 Cloud Function 不需要寫任何驗證程式碼,驗證邏輯全交給 Gateway 處理。
  • 不可變的設定 (Immutable Configs):在 GCP 中,API Config 建立後不能修改內容。如果要更新路由或安全規則,做法永遠是「建立新的 Config」並「更新 Gateway 指向新的 Config」,這能有效避免線上服務在修改過程中發生非預期的停機。

上一篇
ui-ux , design-system , screen-specifications , interaction-patterns
下一篇
發布/訂閱:快速啟動 - 控制台
系列文
將考國際證照的應用程式變成開源27
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言