上次在 《GCP 的 Cloud IAM – 角色與權限控管介紹》有提到 Service Account ,這次我們從開發人員的角度,來分享在開發程式過程當中,使用 Service Account 的一些技巧和注意事項。
一、Service Account 簡介
在 GCP 各種底層運作當中,有很多會代替我們人類執行的服務,例如 Compute Engine 的虛擬機器,這些服務要動起來,就要給它們一個身份,就是 Service Account,並且要讓它們有權限存取其他服務,例如 Cloud Storage 或 BigQuery,就要在 IAM 授予角色給 Service Account。
從開發的角度來說,Service Account 就是程式專用的帳戶,代表程式本人的身份。重點是,程式是 24 小時全年無休在跑的,它操作 GCP 的次數遠遠超過我們人類,所以管理好 Service Account 很明顯是更為重要的。

資料來源:自行繪製
和人類的帳號不同的是,Service Account 是沒有密碼的,它是放在程式裡使用,典型的方法就是產生 Service Account Key,它是一個 Json 文字檔,上面記錄 Service Account 所在的 GCP 專案、Key 的 ID、Key 本身 RSA 2048 的值(可視為密碼)等等。
我們會在程式碼裡指定 Key 的存取位置,但通常我們不會把 Key 直接放在程式碼當中(太危險了),而是去外部某個安全的地方讀取到 Key,就可以去呼叫 GCP 上的各項服務。
重點就在這裡,一個 Service Account 可以生成很多 Key,而這些 Key 都被使用者下載到各處,或直接存到主機的某個地方,反而增加了帳戶被盜的風險。

資料來源:擷圖自 GCP Console
萬一權限設定太大,而 Key 又被拿走,就像你的帳戶被盜,駭客可以在你的專案環境建立大量機器做為殭屍電腦,或是挖礦,一開就是幾千幾萬台,導致你在幫駭客支付 GCP 的費用。
因此 Service Account 和 Key 務必好好保管,以免遭有心人士濫用。
二、使用 Service Account 的小技巧
以下我們依照系統開發的流程,來逐步說明使用 Service Account 的小技巧。
(一) 系統設計階段的最佳安全實務
1. 充分利用 GCP 內建的身份驗證機制
(1) 在 GCP 內部運行的資源
針對運作應用程式的服務如 Compute Engine、App Engine 和 Cloud Run,一定要為它們設定專屬的 Service Account。
首先 Service Account 在這些服務當中運作,不需要產生 Service Account Key 去跟其他 GCP 服務互動,光是這一點,就直接免除了金鑰外洩的風險。
而由於像 Compute Engine 和 App Engine 預設的 Service Account 具有 Editor 角色,權限非常大,所以才要另外設定專屬的 Service Account,並且給它們設定「最小且必要的權限」,就是所謂最小權限原則 (Principle of Least Privilege),即使該服務被盜用,也能透過權限來限制它的活動範圍,降低駭客入侵帶來的破壞。

資料來源:擷圖自 GCP Console
而且每個服務用各自的 Service Account ,可以確保每一支程式都是隔離運作的,萬一有個服務遭到入侵,也不會影響到其他服務的正常運作,避免「牽一髮而動全身」的風險。
(2) 容器化環境的解決方案
Google Kubernetes Engine (GKE) 提供 Workload Identity Federation for GKE。讓 Kubernetes 服務帳號能夠無縫地對應到 GCP 服務帳號,帶來極大便利。
透過這種方式,容器化應用程式可以直接使用 GCP 的各種服務,而不需要在系統中儲存 Service Account Key。簡化了權限管理流程,也顯著提升了系統的安全性,為開發者和維運人員提供了一個更加方便且安全的雲端運算環境。
(3) 在 GCP 外部的系統中的創新方法
同上 Workload Identity Federation 不只用於 GKE,也能讓不在 GCP 內部的系統也能輕鬆存取 GCP 資源。
這項功能讓在 AWS、Azure 或是公司自己機房的應用程式,可以使用它們原本的身份認證機制來存取 GCP 的各種服務,不需要額外管理和儲存 GCP 的 Service Account Key。
這樣的設計大幅減少了在多雲環境下管理憑證的複雜度,讓跨雲服務的整合變得更加簡單安全。
綜合以上三種解決方法,你可以看出來,就是盡量不使用到 Service Account Key,間接地減少金鑰外洩的風險。
2. 建立清晰的 Service Account 策略
(1) 了解各種身份驗證選項的優缺點
A. 從應用程式連接 GCP 各項服務
你可以設定「應用程式預設憑證」(Application Default Credentials;ADC),然後使用對應的程式語言函式庫,這是最常見的開發方式,適合大多數應用程式開發。
B. 需要使用 ID Token 的情況
ADC 主要是證明「這個應用程式有權限使用 Google Cloud 資源」,但不知道身份,ID Token:主要是證明「這個人/使用者是誰」,包含使用者身分資訊。當你需要使用者層級的身分驗證,不只是「應用程式有權限」而已。
C. 實作使用者身份驗證
當你需要讓你的應用程式的使用者能夠登入並存取 Google 服務,可以查看這份文件,裡面有不同方式的比較。
D. 在本機環境試用命令列(Command Line)工具
你可以在自己電腦上安裝 gcloud CLI,輸入驗證的指令並確認身份後,就可以輸入各種指令來操作各項 GCP 的服務和資源。
E. 在本機環境測試 API
你不需要特別準備一個寫程式的環境,你可以直接用像是 curl 的指令來呼叫 REST API。
F. 測試 GCP 官網提供的範例程式碼
你可以在本機設定 ADC 憑證,並安裝相關的客戶端函式庫( Client Library),客戶端函式庫會自動找到你的憑證,讓你能直接執行程式碼。
在 GCP 的官方文件中,已經整理好各種身分驗證的相關說明,你會發現有很多情況不一定要使用 Service Account 和 Key。
(2) 建立評估流程
為特定情境選擇最合適的身份驗證方式,可以參考這個流程,你一樣會發現,在判斷的過程當中,很多情境都不一定要用到 Service Account,真的是沒有其他辦法了,才用 Service Account。
(3) 使用機構政策 (Organization Policy)
Organization Policy 提供了管理 Service Account 和 Key 的多種政策控制如下:
- iam.disableServiceAccountCreation – 禁止在專案中創建新的 Service Account
- iam.disableServiceAccountKeyCreation – 禁止為服務帳戶創建新的 Service Account Key
- iam.disableServiceAccountKeyUpload – 禁止上傳外部生成的 Service Account Key
- iam.serviceAccountKeyExpiryHours – 強制設定 Service Account Key 到期時間
- iam.allowedPolicyMemberDomains – 限制可以被授予 IAM 角色的帳號所屬的網域,包括服務帳戶的網域。
使用機構政策做到了幾件重要的事情:它們防止人們亂建立沒人監控的服務帳戶,這樣可以避免資源使用混亂。
它們也限制 Key 的建立,並要求定期更換 Key,大幅降低了 Key 被盜用的風險。這些工具還讓管理員能清楚看到誰在用什麼服務帳戶、有什麼權限,確保公司符合各種規定。
最重要的是,這些政策幫助確保只有真正需要的服務帳戶會被建立,減少了可能被攻擊的地方。你可以根據不同部門或專案的需求,靈活設定這些規則的嚴格程度,既保障安全又不會妨礙正常工作。

資料來源:擷圖自 GCP Console
(二) 開發與測試階段技巧
1. 使用專屬的 Service Account 提高可觀察性
為每個應用程式建立獨立的服務帳戶,並分配最小權限。
你甚至可以在不同環境的應用程式中,都使用不同的服務帳號,讓環境的隔離做得更為徹底,就不會發生一台機器中毒,然後感染整個環境的狀況。
另外一個好處是,當你查看稽核記錄( (Audited Logs)時,可以通過「principalEmail」欄位追蹤到每一個 Service Account 到底訪問過哪些資源,或是操作過哪些 API,確保他們沒有濫用權限,或訪問不該訪問的地方,大為提高了 Troubleshooting 的效率。
這樣做有幾個重要好處,首先它能幫助您清楚區分不同應用程式的活動,讓監控和管理變得更加簡單。
此外,還能幫助你進行更精確的權限控制,讓每個服務只擁有它所需的最小權限,從而減少安全風險。如果一個服務帳戶被入侵,受影響的範圍也會被限制在該服務的權限內,不會危及整個系統。
2. 安全地建立與傳送金鑰
(1) 使用命令列工具創建金鑰的技巧
在 GCP 中建議使用命令列工具來提高安全性,就是下達 gcloud 指令,直接將 Key 檔案寫入指定的位置:
gcloud iam service-accounts keys create
這種方法的好處是,系統會自動設置適當的檔案權限,提高了金鑰的安全性。這比手動下載金鑰檔案更安全可靠,也減少了人為錯誤的可能性,像是 Key 到處亂放、甚至被盜取的情況。
(2) 在團隊間安全傳送憑證的新方法
傳統上,我們是直接把 JSON 金鑰檔案通過電子郵件、聊天工具(如 Line 或Slack)或雲端硬碟分享等方式將檔案傳送給別人。
這樣會增加了洩露的風險,同一個金鑰檔案可能同時存在多個地方,甚至大家傳來傳去,過程中複製越多份,存放的地方越多,越有可能被有心人士取得。
萬一金鑰被盜,你也沒有辦法追蹤到底是誰手上的那一個金鑰被盜。這樣的話,管理員只能直接停用這個金鑰,這樣也會導致要使用同一個金鑰的人全部都不能用,相關的程式全部都停止運作,你必須重新建立金鑰,然後再次發送給各位,非常麻煩。
你可以採用一種創新的自簽證書方法,這比傳統方式更安全。
具體做法是:首先在需要使用 Service Account 的目標主機上創建 RSA 2048 位的金鑰對和自簽證書。
建立私鑰:
openssl genrsa -out private-key.pem 2048
使用私鑰創建公鑰證書請求:
openssl req -new -key private-key.pem -out cert-request.csr
根據系統提示來填寫國家名稱、城市、公司名稱、單位名稱、服務名稱和電子郵件地址。
生成自簽證書(有效期 365 天):
openssl x509 -req -days 365 -in cert-request.csr -signkey private-key.pem -out public-cert.pem
開發人員只需要傳遞公開的證書檔案(public-cert.pem)給 GCP 管理員,這部分無需保密,可以透過一般的溝通管道分享。
然後,管理員將這個公開證書上傳並綁定到對應的 Service Account:
gcloud iam service-accounts keys upload public-cert.pem –iam-account=my-service-account@project-id.iam.gserviceaccount.com
運作流程如下圖:

資料來源:自行繪製
這種方法的最大優點是完全不需要傳遞私鑰,因為私鑰始終保留在原始機器上,大幅降低了憑證洩露的風險,同時保證了開發人員和主機能夠安全地使用 Service Account。
到這裡你可能會想到一個問題,上面提到的原始機器,不就是 Compute Engine 的虛擬機器嗎?Compute Engine 在呼叫 GCP 服務時,本來就不需要使用 Service Account Key 啊,這樣做有什麼意義嗎?不是多此一舉?
對的, Compute Engine 本來就不用 Service Account Key,這個自簽證書的機制主要是針對「外部環境」設計的,例如:
- 本機開發環境:開發人員在自己的電腦上進行開發時需要存取 GCP 資源
- 其他雲端平台的機器:例如在 AWS、Azure 或阿里雲上運行但需要存取 GCP 服務的應用
- 自有機房中的主機:公司內部數據中心的機器需要與 GCP 服務整合
- CI/CD 管道:在 Jenkins、GitHub Actions 等持續整合 (Continuous Integration) 環境中需要存取 GCP
- 第三方服務:需要整合到 GCP 的外部 SaaS 解決方案
(3) 善用過期時間設置
前面提到的 Organizatino Policy,設定的是「所有 Service Account Key」統一的有效時間,而每一個 Service Account Key 本身,都可以單獨設定到期時間。
前者會設定長一點,例如三個月或六個月,做為所有 Key 的最低要求,後者則是會視情況設定較短的到期時間,可能只有 7~30 天,因為它的掌控程度較高,萬一到期再建立新的 Key 就好了。
我們可以為開發和測試環境的 Service Account Key 設定合理的過期時間,自動讓不再需要的 Key 失效,減少後續管理工作,即使金鑰被有心人士取得,它也失去了作用。
(三) 部署與生產環境技巧
1. 優化 Service Account Key 的存儲方式
(1) 硬體安全解決方案
使用硬體安全模組(Hardware Security Module;HSM)或可信平台模組(Trusted Platform Module;TPM)來管理您的金鑰可以大幅提升安全性。
A. 硬體安全模組
關於 HSM,你可以購買專用的設備,價格為幾千到幾萬元不等,然後將此設備連接到伺服器上(不一定是 GCP 的虛擬機器)。 HSM 設備通常會提供的管理工具,使用跟上述類似的方法建立 RSA 金鑰對和公開的自簽證書,再上傳到 GCP 綁定 Service Account Key。
程式要準備呼叫 GCP 的 API 時,會先呼叫 HSM 廠商提供的 API,發送資料跟 HSM 索取簽名,簽名就是要向 GCP 證明這個 Request 是合法的,簽名結果再返回程式,程式再將原始資料和簽名結果一起發送到 Google Cloud API。

資料來源:自行繪製
其實,你不一定要額外購買 HSM 設備,Cloud Key Management Service (Cloud KMS) 也有 HSM 的功能,這是一種由 Google 管理的硬體安全模組服務,符合 FIPS 140-2 Level 3 安全標準,這樣你就不需要購買實體 HSM 設備。

資料來源:自行繪製
GCP 使用之前儲存的公鑰,來驗證簽名是否真的由對應的私鑰生成。只有當簽名驗證成功時,GCP 才會認為這是來自授權 Service Account 的合法請求。
這樣做有幾個好處:
- 即使有人攔截了請求和簽名,也無法使用這些資訊生成新的有效請求,就是駭客無法產生新的並且合法的 Request 來呼叫 GCP 的 API。
- 只有 HSM 中的私鑰才能生成 GCP 可以驗證的有效簽名,是一個唯一可以信任的來源。
- 主機和應用程式不一定都要在 GCP 內,但如果都在 GCP 內部,必定更為安全。
- 每個請求的簽名都是獨特的,防止重放攻擊(Replay Attack),指的是駭客使用一模一樣的資料去操作 GCP。
B. 可信任平台模組 (TPM)
大多數電腦(特別是 2016 年後製造的)通常已內建 TPM 2.0 晶片在主機板上。如果沒有內建 TPM,你就要購買一個 TPM 模組並安裝到主機板上。
這些模組通常是小型電路板,可以插入主機板上專門的 TPM 插槽。然後在 Linux 上,使用 tpm2-tools 工具集來產生金鑰。
以 Debian 為例,您可以安裝 tpm2-tools 後執行:
ls /dev/tpm*
如果顯示 /dev/tpm0 或 /dev/tpmrm0,通常表示系統已識別到 TPM 設備:

資料來源:擷圖自 4sysops
安裝 tpm2-tools 的相關指令如下(不同作業系統版本,指令可能會有所不同):
更新套件列表:
sudo apt update
安裝 TPM2 工具和資源庫:
sudo apt install tpm2-tools tpm2-abrmd libtss2-dev
安裝後重啟電腦,進入 BIOS/UEFI 設定,尋找 「Security」或「Advanced」選項,啟用 「TPM」,然後重啟電腦。

資料來源:擷圖自 MSI 網站
接下來建立「主要金鑰」(Primary Key),它是 TPM 中所有其他金鑰的根源。
tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctx
然後使用之前創建的主要金鑰來創建一個子金鑰對:
tpm2_create -C primary.ctx -u key.pub -r key.priv
將金鑰載入 TPM:
tpm2_load -C primary.ctx -u rsa.pub -r rsa.priv -c rsa.ctx
將公鑰轉換為 PEM 格式(是 GCP 可接受的格式):
tpm2_readpublic -c rsa.ctx -o rsa.pem -f pem
使用 OpenSSL 指令創建自簽名證書:
openssl req -new -x509 -key tpmkey -out cert.pem
接下來就可以將 rsa_cert.pem 上傳到 GCP Service Account。
最後程式在運作時,就可以使用以下指令,對要簽名的資料(例如 data.txt)來執行「簽名」:
tpm2_sign -c rsa.ctx -g sha256 -o signature.bin data.txt
另外注意程式需要能夠呼叫 TPM 指令,這需要使用 tpm2-tss 等程式庫進行開發。而且電腦必須保持開機狀態才能使用這些金鑰,因為私鑰無法從 TPM 中導出。

資料來源:自行繪製
這樣一來,應用程式只需要使用 HSM/TPM 提供的簽名 API,而不必直接接觸私鑰。這種方法提供了硬體層級的安全保障,有效防止金鑰被複製或提取,大幅降低了資安風險。
(2) 軟體金鑰庫的實用技巧
如果你要使用軟體金鑰庫來儲存 GCP Service Account Key,在 GCP 中可以使用 Secret Manager 來儲存,以下是幾個具體的實作方法:
A. 設定精細的存取控制
- 為 Secret Manager 的使用者,設定最小 IAM 角色權限。
- 建立 Secret,然後把 Service Account 放在 Secret 裡面。
- 為不同團隊或服務建立專用的存取群組,例如讓開發團隊只能存取開發環境的 Secret。

資料來源:擷圖自 GCP Console
- 為不同環境創建不同的 Key,例如 service-account-key-dev 和 service-account-key-prod,然後為每個 Key 設定不同的存取權限,你也可以或使用不同專案隔離環境,每個專案中有各自的 Secret Manager 和 Key。
B. 詳細記錄所有使用情況:
為了追蹤每個 Key 在 Secret Manager 被存取的狀況,你可以啟用 Cloud Audit Logs 來追蹤,因為根據預設,Secret 的存取是不會主動記錄的。你要去稽核記錄把它打開:

資料來源:擷圖自 GCP Console
我們可以故意測試一下,在 Secret Manager 建立一個 Secret 之後,再用 gcloud 指令去讀取它。

資料來源:擷圖自 GCP Console
你看到我執行了兩次讀取 Secret 的指令,因為當我第一次執行完後,出了「Hello」這個值,但我還沒馬上截圖,結果「Hello」這個值就消失了,所以我又再執行了一次,並且馬上截圖,可見 Secret 即使透過 gcloud 指令操作,也會顧及安全性,只顯示幾秒鐘。
接著就可以在 Cloud Logging 的「已稽核的資源」看到 Secret 被存取的時間和操作人員。

資料來源:擷圖自 GCP Console
因為稽核記錄的儲存是有期限的,如果想要長期保存 Secret 的存取記錄,你可以設定 Log Export 到 BigQuery 或 Cloud Storage。
另外,你也可以針對 Secret 的存取記錄,建立 Log-Based Metric 監控指標,這樣就可以把 Secret 的存取次數畫在儀表板上,如果有存取異常,例如某個 Secret 平均一分鐘大概存取 5 次,突然變成 500 次,很明顯就是異常,就可以再設定快訊,來及時通知管理員。
C. 加再一層 Cloud KMS 確保主金鑰的安全
你可以在建立 Secret 時,選擇 CMEK (Customer-Managed Encryption Keys) 功能,使用 Cloud KMS 來的金鑰來加密你建立的 Secret,這樣你的金鑰,除了要有 Secret Manager 的權限角色,又同時要有 KMS 的權限角色,才能夠存取到 Secret 裡的金鑰,等於是雙重保護。
你還可以定期輪換加密金鑰,建議每 90 天一次。這樣除了你的 Service Account Key 能夠定期輪換,KMS 的 Key 也定期輪換,這樣能讓金鑰被竊取所造成的風險降到最低。
D. 實施防止未授權存取的機制
VPC Service Control 是 GCP 中最嚴格的安全功能,能夠限制哪些 API,只能從哪裡進來存取,以及資料只能輸出到哪裡。 例如你可以設定 Service Controls 限制只有公司網路才能存取 Secret Manager。
即使 Secret Manager 是軟體功能,但是當它與其他 GCP 安全功能結合使用時,還是可以在各種資安功能互相搭配之下,給予完善的保護,有效降低憑證洩漏的風險。
2. 高效追蹤 Service Account 使用情況
你可以使用 Cloud Logging 設定查詢語法,來識別過去 90 天是否有未使用的 Service Account。
在 Cloud Monitoring 中設置監控金鑰身份驗證事件指標,然後針對指標設定快訊,例如某一個 Service Account 每天不會用來呼叫某 API 超過 1000次,若超過就發出快訊通知。這能幫助您了解 Service Account 的使用模式和頻率,從而識別異常行為。
每個 Service Account 都有一個「指標」分頁,可以快速查看基本用量資訊,你可以直接從這裡找到要監控的指標,然後設定快訊,就不用去 Metrics Explorer 大海撈針尋找指標。

資料來源:擷圖自 GCP Console
3. 外部整合的最佳實務建議
(1) 安全使用外部來源的憑證
當您需要從外部來源取得 Service Account Key 時,建立一個嚴謹的驗證流程非常重要。首先,您應該確保憑證的來源是可信的,例如大家統一都從 Secret Manager 取得 Key,而非透過 Line 或 Email 來傳送,避免使用來歷不明的金鑰檔案。
因為駭客雖然沒那麼容易偽造 Key,但 Key 被駭客取得後,修改其中某些欄位(如重新導向或添加惡意程式碼)但保留核心加密部分,都有可能對你的系統或 GCP 環境造成破壞。
所以每次收到或使用 Service Account Key 檔案時,都應該檢查其 JSON 格式中的 “type” 欄位值是否確實為 “service_account”,並且確認 Service Account 的電子郵件是否具有正當的權限,再確認這個 Key 是否能夠從 GCP 獲取令牌。這些檢查步驟都能幫助您確認您使用的是正確的憑證類型,而非其他類型的金鑰或偽造的檔案。
(2) 全網域授權的高效方法
GCP 提供了一種更安全、更簡潔的方式來進行服務授權,不需要使用傳統的 Service Account 金鑰。這種方法利用 signJwt API,可以為全網域提供高效的授權機制。
什麼是 signJwt?
想像你需要寄一封非常重要的信,你想確保收信人知道這封信確實是你寄的,而且信的內容沒有被人竄改。在數位世界中,signJwt 就像是一種特殊的「數位簽名」服務,幫你在重要文件上蓋上無法偽造的印章。
首先使用 Service Account 或 Workload Identity Federation 進行身份驗證。就像在公司大樓,你不用自己帶鑰匙,而是在前台登記後由保全確認你的身分。這樣可以避免直接管理和存儲敏感的金鑰文件。
然後建立一個 JSON Web Token (JWT) 做為「數位通行證」,它包含實際的資訊,例如誰可以讀取特定資料、這個權限何時過期等,這個 JWT 將作為授權請求的基礎。
接著把這封「未簽名」的 JWT 內容送到 Google 的 signJwt 服務,說:「請幫我在這份文件上簽名。」
Google 會確認你有權請求這項簽名服務,使用只有 Google 知道的特殊私鑰,再依據你信件的內容產生一個獨特的數學計算結果(簽名),然後把這個簽名附在你的信件上,形成一個完整的已簽名 JWT。
最後把它送給 Google 的授權服務,換取一個臨時的「存取令牌」,其他 Google 服務看到這個令牌時,會使用 Google 的公鑰驗證簽名。如果簽名有效,且內容顯示你有權限,服務就會允許存取。

資料來源:自行繪製
這種方法減少了安全風險,因為你不需要下載、發佈或管理 Service Account Key 的檔案。同時簡化了授權流程,使整個過程更加高效和易於維護。對於需要在多個服務或整個網域中進行授權的場景,這是一個特別有價值的解決方案。
你可能會擔心,看起來流程很長,會不會來回很花時間或吃效能?
其實 GCP 的這些服務都經過高度優化,大部分步驟在 GCP 的基礎設施上執行得非常快速。而且這個流程只有在第一次次建立連接或每次令牌過期時才需要執行。
存取令牌一旦獲取,通常可以使用幾個小時(典型設定為 1 小時),不需要每次請求都重新執行整個流程。整個步驟加起來通常只需數百毫秒完成,所以在實際執行時,效能影響是很有限的,卻因此提升很高的安全性。
(四) 維護與治理技巧
1. 金鑰輪替的最佳策略
(1) 制定有效的輪替計劃
如上述提到,就像定期更換家中門鎖一樣,即使目前沒有安全問題,定期的更新也能防範潛在威脅。建議每隔 90 天進行一次金鑰輪替,這樣即使某個金鑰被洩露,其可用時間也會受到限制。在實際操作中,可以通過 GCP 控制台或使用 gcloud 指令來創建新金鑰並廢棄舊金鑰。
為了減少人為錯誤並確保輪替流程的一致性,建立自動化的金鑰輪替機制非常重要。您可以利用 Cloud Functions 配合 Cloud Scheduler 來定期觸發金鑰輪替流程,或者使用 CI/CD Pipeline 來管理這一過程。自動化不只是輪替,還能將新的金鑰自動部署到相關服務,減少服務中斷或人為操作錯誤。
對於儲存在 HSM 中的高敏感度金鑰,需要制定更嚴格的輪替策略。這些金鑰通常用於加密重要資料或簽署關鍵交易,因此建議為 HSM 金鑰設定更短的輪替周期,例如 30~60 天。
(2) 高效管理未使用的金鑰
如前面提到,你可以用 Cloud Logging 設定查詢語法,來識別過去 90 天是否有未使用的 Service Account,並且設定 Cloud Monitoring 監控指標, 顯示各金鑰的使用頻率,幫助您快速發現那些閒置的金鑰。
這個動作最好建立成一個 SOP,每月或每季度對所有 Service Account Key 進行全面審查。你可以使用標籤系統來標記不同狀態的金鑰,如「活躍」、「待觀察」或「待刪除」。同時,確保審查結果有明確的記錄和後續行動,避免重複工作或遺漏重要金鑰。
在移除未使用的金鑰時,不要急於刪除,而是先將其停用。停用後,觀察一段時間(通常為 7~14 天),確保沒有任何系統依賴這些金鑰。等到確認都沒問題,再執行刪除操作。這種「先停用再刪除」的方法能夠減少因誤刪而導致的系統中斷。
2. 機構層級(Organization Level)的管理建議
(1) 有效利用機構政策
管理員應在機構層級設定預設的限制條件,同時也為特殊需求的設定例外政策。例如「iam.disableServiceAccountKeyCreation」,預設禁止所有專案建立 Service Account 金鑰,但為開發環境或特定整合需求的專案設置例外。
還有透過條件表達式,如「resource.name.startsWith(“projects/dev-“)」,可以僅允許名稱以「dev-」開頭的開發專案建立金鑰,實現更靈活的控制機制,確保安全政策既嚴謹又不妨礙業務運作。
(2) 角色與權限的最佳配置
盡量避免使用過於寬鬆的 Editor 角色,而改用更精細的預定義角色(Predefined Roles)。例如為負責 CI/CD 的 Service Account 分配「Cloud Build Service Agent」和「Storage Object Viewer」角色,共允許只能執行部署工作和讀取必要的物件。
對於需要監控資源的 Service Account,可以建立包含「monitoring.timeSeries.list」和「logging.logEntries.list」等極小權限的自訂角色,而不是授予權限範圍過大的「Monitoring Viewer」角色,避免意外刪除資源或未授權訪問敏感資料等問題。
三、使用 Service Account 的注意事項
前面提到的各項技巧,有些需要時間慢慢建立,如果要立刻可以執行的方法,可以遵守以下防範的各項動作:
(一) 防範憑證外洩
1. 避免將金鑰保存在臨時位置,例如電腦桌面、共用電腦或共享的網路資料夾。
2. 不要在用戶間直接傳遞 Service Account 金鑰文件,例如存在 Line 群組、Email 或雲端硬碟。
3. 防止將金鑰提交到原始碼儲存庫,例如 GitHub 或 GitLab。
4. 不要將金鑰嵌入程序的二進位檔,如果有人獲取了你的二進位檔,他們可能能夠提取出這些金鑰,而且當你需要更新金鑰時,你必須重新編譯整個程式,不安全也很麻煩。
5. 前面雖然提到使用 Secret Manager 來儲存 Key,但能夠不使用 Service Account Key,就盡量不使用,建議還是使用 Workload Identity Federation、HSM、TPM 或自簽證書的方法。
(二) 防範安全配置問題
你需要特別小心處理那些安全認證文件。這些 X.509 證書檔案(就是那種帶有 .pem 或 .crt 副檔名的檔案),它可能會包含比你想像的更多資訊。
首先,請確保你不要在這些證書中放入敏感資訊。例如,不要在裡面寫你公司的內部系統名稱、伺服器位置或其他機密資料。
其次,當你填寫證書的「Subject」(主體)欄位時,請使用一般性的名稱,像是「GCP服務帳戶」或「應用程式認證」,而不是具體的系統名稱如「公司財務系統主機」。
另外,證書中有些是選填欄位,像是地址、城市、郵遞區號等,建議你不要填寫這些資訊。因為如果駭客取得了這些證書,他們可以利用這些地點資訊來猜測你的實體伺服器位置,或是用來發動更具針對性的釣魚攻擊。
(三) 防範權限提升風險
因為如果金鑰被不當取得,駭客可能利用這些憑證來進行各種破壞。尤其是 Editor 角色可能帶來的安全隱患,它的權限實在是太大,若被濫用可能造成嚴重損害,建議採用最小權限原則,只授予必要的權限,前面提了很多次,但還是再問一次,你真的有確實遵守嗎?
其次,應避免在檔案系統(本機電腦、VM 的某個目錄)中直接存儲金鑰,因為這樣很容易被其他人拿到或在系統備份過程中洩露。真的要用,建議使用 Secret Manager 來安全存儲這些敏感憑證。
最後,在虛擬化環境(如容器或虛擬機)中使用 Service Account 金鑰時,要防止底層安全問題,因為底層主機被入侵的話,可能導致所有虛擬環境的金鑰都被洩露。在這種情況下,可考慮使用臨時憑證或 Workload Identity,來減少金鑰洩露的風險。
四、同場加映:防止呼叫 API 爆量的方法
GCP 提供了豐富的 API 服務,幾乎所有 GCP 的功能,都是以 API 的形式在運作,讓開發人員可以透過程式來自動化存取各種雲端資源。但如果沒有加以控制,API 可能被過度呼叫,導致成本急劇上升,甚至造成服務異常。
(一) API 爆量的發生情境
這種問題通常發生在以下幾種情境:
1. 開發或測試環境未設限
開發人員可能在測試時,沒有把程式碼寫得完善,不慎觸發大量 API 請求。
2. 系統錯誤或程式 Bug
例如無限迴圈 (For Loop)或非預期的重試機制,導致 API 被頻繁呼叫。
3. 流量暴增
突然的流量高峰,例如 DDoS 攻擊或用戶激增,可能導致 API 配額迅速耗盡。
4. 惡意濫用
如果 API 沒有適當的身份驗證與授權控制,可能會被未授權用戶濫用,如上述 Service Account Key 被盜用,如果這個 Key 具有建立虛擬機器的權限,就會被任意建立大量主機,執行挖礦或作為殭屍電腦,是上述情境中最危險的情況。
(二) 限制 GCP API 呼叫的方法
1. 設定消費預算警報
GCP Cloud Billing 允許設定預算警報,一旦 API 費用達到特定閾值,系統會自動發送通知,提醒使用者注意 API 開銷。像我自己是真的把預算警報用到「極致」,不要說超過 50 美金要通知,我只要每超過 1 美金都要收到通知。

資料來源:擷圖自 GCP Console
但是 GCP 預算警報要隔一天才知道,在正常使用的情況下,GCP 的費用不會超出太多。但如果是被駭客入侵或攻擊,當你看到警報時,可能已經產生一百萬的 GCP 費用了,所以這是緩不濟急的,請再搭配下面提到的方法。
2. 加強 Service Account 權限控制
像前面提到最基本的要求,就是為 Service Account 設置最小權限原則,限制各個 Service Account 只能呼叫特定的 API 和服務,甚至不同環境都用不同的 Service Account,讓它無法隨意呼叫 GCP 的 API。
3. 設定 API 配額限制
在 GCP 上呼叫 API 有多種方式,包括使用 Service Account 和 API Key,API Key 是一種相對簡單的認證方式,它只是一個字串,例如「AIzaSy………M-O1pNg」。
API Key 主要用於特定 API 的存取控制,你可以設定這個 Key 只能呼叫 Compute Engine API,其他 API 都不能呼叫。有些服務能夠限制 API 請求配額,可以有效確保 API 的呼叫次數,尤其是可以限制一天之內或一分鐘之內的次數上限,甚至能區分每個使用者的呼叫上限。
這可以確保萬一 API Key 被駭客取得,呼叫次數也能限制在某個次數範圍之內。

資料來源:擷圖自 GCP Console
4. 設定資源配額
除了像 API 可以限制呼叫次數,在 GCP IAM 裡管理的則是資源配額,例如專案內可以建立的 VM 數量、vCPU 核心數、儲存容量等各種資源可被開啟的數量上限。
我個人認為這是更重要的,因為假如駭客盜取你的帳號,或是 Service Account Key,他可以直接在你的 GCP 專案內任意開啟機器,要注意他不是一台一台手動開機器,他是用程式自動化的技術,在每個 Region 把你的機器「開好開滿」,直接開到配額上限。
以 N1 的 vCPU 來說,如果你是以個人信用卡使用 GCP,每個 Region 初期只能用到 24 vCPU,隨著使用時間越長,配額會自動調高。
但是你的專案帳單如果直接綁定在代理商,系統會判定你是等級較高的用戶,你在每個 Region 能使用的 vCPU 就會提高不少,萬一被駭,就會變成每個 Region 的主機、CPU 甚至 GPU,全部開滿。
只要 1~2 天的時間,就可以在一個專案內,開「幾萬台」機器,隔天就會收到「百萬」等級的帳單,等你收到帳單警示已經來不及了。這是確實有發生過的情況,絕非杜撰,這就回到你的 Service Account Key 務必保管好,甚至使用其他驗證方式。

資料來源:擷圖自 GCP Console
難道沒有其他解決辧法嗎?有的,就是減少配額,建議針對每個型號,例如 N1、N2 的 vCPU,而且每個 Region 都要減少。如果你沒有在用 GPU,就直接把每個 GPU 配額改成 0。

資料來源:擷圖自 GCP Console
你可能會想,駭客進來也可以提高配額啊?這點不用擔心,減少配額可以改完當下就生效,但是如果要增加配額超過預設值,Google 那邊至少需要兩天的時間人工審核,還要填寫聯絡方式包含電話號碼,所以駭客不會去做的。
5. 設定各個服務的運作上限
(1) Compute Engine 的配額限制
如前段提到的例子,你可以通過配額限制來控制資源使用。
(2) Google App Engine 必須要調整 app.yaml
很多人都不知道,App Engine 預設沒有設定上限,代表它會無限擴充,重點是,很多人都一直以為他的 App Engine 只有一台機器在跑,直到看到帳單才發現原來它在某個尖峰時間,曾經擴充過多台主機。
你必須要在 app.yaml 設定 Autoscale 的上限數量,才不會一直擴充下去。

資料來源:擷圖自 GCP Console
(3) Cloud Run 或 Cloud Run Function
執行個體預設的 Autoscale 數量是 0 到 100,記得把它改成你能接受的上限,例如 5 個。

資料來源:擷圖自 GCP Console
(4) 設定 BigQuery 每天查詢上限
要注意,原本 BigQuery 的預設查詢配額,也是「無上限」的,如果你的資料太多又沒整理,或是不小心有程式一直自動查詢大量資料,也會造成非常大的費用。你可以設定 BigQuery 每天的查詢限制,也能設定每天+每個使用者的查詢限制。

資料來源:擷圖自 GCP Console
6. 節流機制 (Throttling)
(1) Cloud Armor 節流(Rate Limit)
對於外部流量,Cloud Armor 可以設定節流機制,例如每分鐘不能存取超過 1,000 次,超過即停止服務。但要注意,你要先知道你的服務平時的流量,以及假日或活動期間的流量,以免低估流量,反而把真正的用戶阻擋在外面。

資料來源:擷圖自 GCP Console
(2) 本地節流機制
這裡指的就是你自己開發的應用程式,直接實作 API 請求節流的邏輯,那你就可以彈性地設定各種不同時間間隔,例如每秒不能超過 100 次,每分鐘不能超過 1000 次,每小時不能超過 10,000 次等等。這也是要注意,不要錯估流量。
另一方面,如果程式發生錯誤,例如當 API 回應 429 時,必須要重新存取(Retry),或是被外部呼叫,你可以使用指數退避 (Exponential Backoff) 策略處理重試,自動延遲並逐步增加重試間隔,例如當發生第一次錯誤,休息兩秒,第二次,休息四秒,第三次,休息八秒…等,不要讓程式在出錯時還一直不斷存取,減少無謂資源的消耗。
7. 設定各種指標的監控
Cloud Monitoring 可以監控很多指標,不只監控 API 呼叫次數,你也可以監控例如用戶發出的 Request 數量,或是主機每秒送出的流量大小,並且限制例每分送出超過 10 MB,就發出流量警告,讓你在異常流量發生的當下,就能夠立即發現並阻擋。

資料來源:擷圖自 GCP Console
五、結論
成功管理 Service Account 需要綜合考慮安全性、方便性和維護成本。通過上述的小技巧,你可以在系統開發過程的各個階段,有效並安全地使用 Service Account。
要記住的是,不是「Service Account 怎麼用」或「Service Account Key 怎麼保管」。因為你「不一定要用 Service Account」,選擇合適的身份驗證方法是最重要的第一步。
你可以優先考慮 GCP 的內建驗證機制,只在非用不可的時候,才使用 Service Account 和 Key,並依照最佳實務來管理。這樣不僅可以降低維護成本,還能大幅提高系統的整體安全性。
另外,各種機制也是需要不少時間規劃流程和制度,以及各部門之間互相配合,遵守規範,這也需要主管大力支持並提供充份的資源,才能有效實施。
六、常見問題
(一) 如何檢查 Service Account 是否有過度授權?
1. GCP 提供 IAM 建議 (IAM Recommender)
可以分析 Service Account 的使用情況,找出是否擁有過多權限。
步驟:
(1) 前往 GCP Console,打開 IAM & Admin > IAM。
(2) 找到 Service Account,查看「建議的角色」(Recommended roles) 欄位。
(3) 如果 GCP 建議降低權限,請根據建議調整角色。

資料來源:擷圖自 GCP Console
2. 使用 IAM Policy Analyzer 進行分析
你可以在 IAM & Admin > Policy Analyzer 中輸入 Service Account 的電子郵件。查看該帳戶擁有哪些權限,並確認是否有不必要的存取權限,操作方式和上述差不多。

資料來源:擷圖自 GCP Console
(二) 如何刪除未使用的 Service Account?
可參考以下步驟:
1. 列出所有 Service Account 並找出未使用的帳戶:
gcloud iam service-accounts list –format=”table(email, disabled)”
可以顯示所有 Service Account 和目前的使用狀態 (是否已停用)。
(2) 停用 Service Account
如果確認某個 Service Account 一直都沒有在用,可先停用:
gcloud iam service-accounts disable service-account@your-project.iam.gserviceaccount.com
這樣可以避免影響現有服務,若發現問題仍可重新啟用。
(3) 刪除 Service Account
停用後,如果確定不再需要,可刪除:
gcloud iam service-accounts delete service-account@your-project.iam.gserviceaccount.com
⚠ 注意:刪除後不可恢復,請確保已經沒有任何應用程式在使用該帳戶。
(三) Service Account 金鑰遺失該怎麼辦?
如果 Service Account 金鑰遺失,應立即執行以下步驟,以確保系統安全:
1. 列出現有的 Service Account 金鑰
gcloud iam service-accounts keys list –iam-account=service-account@your-project.iam.gserviceaccount.com
這會顯示所有金鑰的 KEY_ID,你可以確認哪個金鑰可能遺失。
2. 立即刪除遺失的金鑰
如果確定某個金鑰已洩露,請使用以下命令刪除:
gcloud iam service-accounts keys delete YOUR_KEY_ID –iam-account=service-account@your-project.iam.gserviceaccount.com
刪除之後,即使駭客手上擁有你的金鑰檔案,也是無法發運任何作用的。
⚠ 注意:一旦刪除,任何使用該金鑰的應用程式都將失去存取權限,請確保已經準備好替代方案。
3. 生成新的 Service Account 金鑰
如果仍需使用金鑰(不推薦),可以產生新的金鑰:
gcloud iam service-accounts keys create new-key.json –iam-account=service-account@your-project.iam.gserviceaccount.com
(四) 我可以將 Service Account Key 存放在 GitHub 嗎?
不建議這樣做,因為這可能導致憑證洩漏,應該使用 Secret Manager 來管理。
(五) 如何檢測 Service Account Key 是否外洩?
你可以透過 Cloud Audit Logs 來查詢這個 Service Account Key 異常存取行為,你可以參考這份文件來操作。
(六) Service Account Key 有效期多久?
預設情況下都是永久的,開發人員應該手動輪替金鑰。
(七) 有哪些更安全的替代方案?
Workload Identity Federation 和 OAuth 2.0 是更安全的選擇,能不用 Service Account Key 就盡量不要用。
另一個方法是產生 RSA 2048 金鑰對,透過 HSM 模組、Cloud KMS 或 TPM 方法,在私鑰完全不需要對外分享的情況下,讓應用程式還是可以操作 GCP 的 API。
(八) 如何讓 CI/CD 流程更加安全?
可以使用 Workload Identity Federation,避免直接存放 Service Account Key。
(九) 如何避免因資安事件發生,而造成大量的帳單費用?
- 設定預算警示
- 設定 API 配額
- 設定減少資源配額,例如 CPU 和 GPU
- 設定 Service Account 和 Key 的監控和快訊
- 設定流量和資源使用量的監控和快訊
- 限縮服務本的的自動擴充上限
- 設定應用程式的存取次數
本文同時刊登於: