瞭解服務帳戶

背景

服務帳戶是特殊的 Google 帳戶類型,主要用於代表需要驗證且必須取得授權才能存取 Google API 資料的非人類使用者。

服務帳戶通常用於以下情況:

  • 在虛擬機器 (VM) 上執行工作負載。
  • 在呼叫 Google API 的內部部署工作站或資料中心上執行工作負載。
  • 執行未附加至人類使用者生命週期的工作負載。

您的應用程式以服務帳戶的身分呼叫 Google API,如此一來使用者即不會直接參與其中。

管理服務帳戶

當您確定需要服務帳戶時,可以試問自己以下問題,有助於瞭解您對服務帳戶的使用方式:

  • 服務帳戶可以存取什麼資源?
  • 服務帳戶需要什麼權限?
  • 取得服務帳戶身分的程式碼要在哪裡執行:Google Cloud Platform 或是內部部署?

請利用以下的流程圖找到上述問題的答案:

服務帳戶流程圖

請注意,服務帳戶既可以視為資源,又可以視為身分

將服務帳戶視為身分時,您可以將角色授予服務帳戶,來允許其存取資源 (例如專案)。

將服務帳戶視為資源時,您可以將角色授予其他使用者,以便其存取或管理該服務帳戶。

將存取權授予服務帳戶

向服務帳戶授予對資源的存取權,與向任何其他身分授予存取權類似。舉例來說,如果您在 Google Compute Engine 上執行應用程式,且希望應用程式「只」具備在 Google Cloud Storage 中建立物件的權限。您可以為應用程式建立服務帳戶,然後授予 Storage 物件建立者角色。下列圖表說明了本範例:

服務帳戶流程圖

瞭解將角色授予服務帳戶

模擬服務帳戶

模擬服務帳戶存取 Google API 的方法有三種:

  • 使用 RSA 私密金鑰進行驗證
  • 使用 Cloud IAM 政策進行授權
  • 在 GCP 服務上部署工作

使用 RSA 私密金鑰進行驗證

所有的服務帳戶都有一組定期輪替的 GCP 代管金鑰,而私密金鑰一律以信託的形式儲存,永遠無法直接存取。

使用者自行管理的金鑰組也可以手動建立。GCP 會產生私密/公開金鑰,並儲存公開金鑰,將私密金鑰提供給使用者。依建立日算起,金鑰組效期為 10 年,金鑰組從服務帳戶中刪除後,就無法用於向 Google 進行身分驗證。

使用 Cloud IAM 政策進行授權

所有的服務帳戶都有 Cloud IAM 政策,用於授予服務帳戶的存取權。有些權限會根據使用者的憑證,允許使用者模擬或成為服務帳戶。

在 GCP 上部署工作

有些 GCP 服務,如 Compute Engine、App Engine 或 Cloud Functions 等,會允許您部署以服務帳戶身分執行的工作 (例如 VM 或函式)。

若要透過此方式部署工作,就必須將所需服務的必要權限授予服務帳戶,還要將服務帳戶的 iam.serviceAccounts.actAs 權限授予使用者帳戶。「服務帳戶使用者」角色也具有此權限,GCP 服務還必須維護服務帳戶上的 Cloud IAM 權限,但系統通常會自動為您執行。

範例

使用服務帳戶執行 VM

假設您有長時間執行的工作,而您的員工擁有啟動工作的權限,但是您不希望當最後一位啟動工作的員工離開公司後,工作遭到終止。

解決這個問題的方法是建立一個服務帳戶來啟動及停止工作。透過以下步驟進行即可完成:

  1. 建立服務帳戶

  2. 將服務帳戶的「服務帳戶使用者」(roles/iam.serviceAccountUser) 角色授予需要工作啟動權限的員工。在本情境中,會將服務帳戶視為資源。

  3. 向同一群員工授予 Compute 執行個體管理員 (roles/compute.instanceAdmin.v1) 角色。

  4. 現在,員工可以建立執行服務帳戶的 Compute Engine 執行個體,與執行個體連結,並使用服務帳戶啟動工作。例如:

    gcloud compute instances create my-instance --scopes=cloud-platform \
    --service-account=my-service-account@test9q.iam.gserviceaccount.com \
    --zone=us-central1-a
    

將資料遷移到 GCP

假設您使用其他的雲端供應商服務處理部分資料,而想要將處理後的資料轉移到 Google Cloud Platform,可以藉由外部雲端服務虛擬機器中的服務帳戶,將資料推送到 Google Cloud Platform。如要進行這項作業,您必須在建立服務帳戶時,建立並下載服務帳戶金鑰,然後透過外部程序使用金鑰來呼叫 Cloud Platform API。

追蹤服務帳戶

隨著時間過去,您會建立越來越多的服務帳戶,可能會導致您不記得服務帳戶的用途。

查看服務帳戶的顯示名稱是個不錯的方法,可以取得更多服務帳戶的相關資訊,像是帳戶用途或是帳戶聯絡人等。對於新服務帳戶,您可以在建立帳戶時填入顯示名稱。對於現有的服務帳務,則可透過 serviceAccounts.update() 方法修改顯示名稱。

刪除和重新建立服務帳戶

刪除服務帳戶,然後建立具有相同名稱的新服務帳戶是可行的。如果您重複使用刪除的服務帳戶名稱,可能會導致非預期的行為。

服務帳戶刪除後,其角色繫節並不會立即刪除。如果您建立一個與最近刪除的服務帳戶同名的新服務帳戶,則舊的繫結可能仍然存在;但是,即使兩個帳戶具有相同的電子郵件地址,它們也不會應用於新的服務帳戶。這種行為的發生,是因為服務帳戶在建立時,便會在 Cloud IAM 中被指定一個唯一識別碼。在內部,所有都使用這些識別碼授予角色繫結,而非服務帳戶的電子郵件地址。因此,已刪除的服務帳戶存在的任何角色繫結,都不適用於使用相同電子郵件地址的新服務帳戶。

為避免混淆,我們建議使用唯一的服務帳戶名稱。如果無法做到這一點,您可以透過以下方式為新服務帳戶授予角色:

  1. 明確刪除將該角色授予舊服務帳戶的所有繫結。
  2. 將這些角色重新授予新服務帳戶。

在重新添加角色繫結之前,必須先刪除角色繫結。若僅只是再次授予角色,只會將角色授予至舊的已刪除服務帳戶而失敗,且不會發出通知。

服務帳戶的權限

本節說明以下幾種常見情境中,會將權限授予服務帳戶或具有模擬服務帳戶權限的使用者帳戶:

向服務帳戶授予最低權限

請只為服務帳戶授予達成作業目標所需的最低權限。如要進一步瞭解,請參閱將角色授予特定資源的服務帳戶一節。

向使用者授予服務帳戶的存取權時,請記住,使用者將能夠存取服務帳戶可存取的所有資源。因此,設定服務帳戶的權限時請務必小心,嚴加管控能以 (或模擬) 服務帳戶身分進行動作的小組成員。

如果使用者的 Cloud IAM 角色能更新 App Engine 和 Compute Engine 執行個體 (例如 App Engine DeployerCompute 執行個體管理員),將能以執行這些執行個體所用的服務帳戶,有效地執行程式碼,並且對於服務帳戶可以存取的所有資源,也能間接取得這些資源的存取權限。同樣地,Compute Engine 執行個體的 SSH 存取權可能也會提供以執行個體執行程式碼的能力。

常見情境的服務帳戶權限

服務帳戶可以在多種不同的情境下使用,每個帳戶都需要特定的權限。本節將說明常見情境以及所需的權限。

啟動長時間執行的工作

權限:

  • iam.serviceAccounts.actAs

角色:

  • roles/editor (編輯者)
  • roles/iam.serviceAccountUser (服務帳戶使用者)

使用者 (或服務) 可以將服務帳戶繫結到長時間執行的工作服務。以下是幾個例子:

  • Compute Engine VM
  • App Engine 應用程式
  • Cloud Functions 函式
  • Cloud Dataflow 工作

在這種情況下,必須同時授予使用者部署作業的權限 (隨服務而異) 和模擬服務帳戶的權限 (透過服務帳戶上的 iam.serviceAccounts.actAs 授予)。請注意,授予 iam.serviceAccounts.actAs 權限本身並不允許模擬服務帳戶。

在服務帳戶授予 iam.serviceAccounts.actAs 權限後,使用者即可啟動以服務帳戶身分執行的長時間執行工作。工作啟動後,該使用者就不再需要使用服務帳戶的存取權。即使該使用者失去存取權,工作仍會繼續執行。工作服務會繼續在服務帳戶上使用自己的權限,來維持以使用該服務帳戶身分執行工作。

請注意,有時您必須具備 iam.serviceAccounts.actAs 權限,才能變更長時間執行的工作 (例如在 Compute Engine VM 上設定執行個體中繼資料)。

如要進一步瞭解這個流程,請參閱 Compute Engine 說明文件中的建立和啟用執行個體的服務帳戶

直接模擬服務帳戶

權限:

  • iam.serviceAccounts.getAccessToken
  • iam.serviceAccounts.signBlob
  • iam.serviceAccounts.signJwt
  • iam.serviceAccounts.implicitDelegation

角色:

  • roles/iam.serviceAccountTokenCreator (服務帳戶憑證建立者)

被授予所需權限後,使用者 (或服務) 就可以在幾種常見情境下直接模擬 (或主張擁有) 服務帳戶的身分。

首先,使用者可以使用 iam.serviceAccounts.getAccessToken 權限並呼叫 generateAccessToken() 方法來獲得服務帳戶的短期憑證。藉由使用短期憑證,使用者可以向 GCP 發出指令,並且可以存取該服務帳戶可存取的所有資源。例如,這個流程允許使用者使用 gcloud --impersonate-service-account 標記模擬服務帳戶,無須使用下載的外部服務帳戶金鑰。

其次,使用者可以使用 iam.serviceAccounts.signBlob 權限並呼叫 signBlob()signJwt() 方法,來獲得服務帳戶的 Google 代管私密金鑰所簽署的構件。Google 代管私密金鑰一律以信託的形式儲存,絕不會直接公開。signBlob() 允許簽署任意酬載 (例如 Cloud Storage 簽署的網址),而 signJwt() 只允許簽署格式正確的 JWT。

最後,使用者可以模擬 (或主張擁有) 該服務帳戶,無須取得該服務帳戶的憑證。這是進階用途,且只有使用 generateAccessToken() 方法的程式存取權支援此用途。在至少有 3 個服務帳戶 (名稱分別為「A」、「B」和「C」 的情境中):如果將「B」iam.serviceAccounts.implicitDelegation 權限授予服務帳戶「A」,並將「C」iam.serviceAccounts.getAccessToken權限授予「B」,則服務帳戶「A」就可以取得服務帳戶「C」的存取憑證,

產生 OpenID Connect (OIDC) ID 憑證

權限:

  • iam.serviceAccounts.getOpenIdToken

角色:

  • roles/iam.serviceAccountTokenCreator (服務帳戶憑證建立者)

使用者 (或服務) 可以使用 iam.serviceAccounts.getOpenIdToken 權限產生由 Google OIDC 供應商 (accounts.google.com) 簽署、與 OpenID Connect (OIDC) 相容的 JWT 憑證,來代表服務帳戶的身分。

大多數的 Google API 都不會直接接受這些憑證,除非貴機構部署額外的身分聯盟來授予 Google 存取權。但這有幾個例外,譬如 Cloud Identity-Aware Proxy 允許使用者執行依據 OIDC 存取使用者執行的應用程式。

產生外部私密金鑰

權限:

  • iam.serviceAccountKeys.create

角色:

  • roles/editor (編輯者)
  • roles/iam.serviceAccountAdmin (服務帳戶管理員)

使用者或服務可以產生外部私密金鑰內容 (RSA),以便可以用來直接以服務帳戶身分向 Google 進行驗證。這個金鑰內容之後可與應用程式預設憑證 (ADC) 程式庫或與 gcloud auth activate-service-account 指令搭配使用。任何人只要能存取這個金鑰內容,就擁有服務帳戶可存取之所有資源的完整存取權限。這類的私密金鑰內容應視為最高風險的內容來處置,而且這個內容存在越久就越不安全。所以,為維持高度安全性,請務必輪替私密金鑰內容。

管理服務帳戶金鑰

服務帳戶金鑰有兩種類型:

  • GCP 代管的金鑰。這些金鑰是由 Cloud Platform 服務 (例如 App Engine 與 Compute Engine) 使用。金鑰無法下載,且會自動輪替用於簽署最多兩個星期。輪替處理是隨機的;新金鑰的使用會隨著金鑰生命週期的演進逐漸增加或減少。我們建議將服務帳戶的公開金鑰組快取儲存最多 24 小時,以確保您隨時可以存取目前的金鑰組。

  • 使用者代管的金鑰。使用者可以建立、下載及管理這些金鑰。依建立日算起,金鑰效期為 10 年,若從服務帳戶中刪除,就無法成功驗證。

對於使用者代管的金鑰,您必須確保已設置相關程序以符合金鑰管理需求,如下所示:

  • 金鑰儲存
  • 金鑰發佈
  • 金鑰撤銷
  • 金鑰輪替
  • 保護金鑰避免未經授權的使用者存取
  • 金鑰復原

任何人只要有權存取服務帳戶的有效私密金鑰,就可以透過該服務帳戶存取資源。請注意,金鑰的服務帳戶存取權 (以及服務帳戶有權存取的資料) 生命週期與下載金鑰之使用者的生命週期無關。

我們一律不建議開發人員將金鑰簽入來源程式碼,或是把金鑰留在工作站的下載目錄中。

為加強金鑰的安全性,請遵循以下操作說明:

搭配使用服務帳戶與 Compute Engine

Compute Engine 執行個體必須做為服務帳戶執行,才能存取其他的 Cloud Platform 資源。請考慮以下事項,以確保 Compute Engine 執行個體的安全性:

  • 您可以在同一個專案中,用不同服務帳戶建立 VM。如要在建立 VM 後變更服務帳戶,請使用 instances.setServiceAccount 方法。

  • 您可以向服務帳戶授予 IAM 角色,藉此定義服務帳戶的存取權限。在多數情況下,您不再需要依靠範圍。這讓您得以修改 VM 服務帳戶的權限,不必重新建立執行個體。

  • 由於執行個體必須依靠服務帳戶才能存取 Cloud Platform 資源,因此請避免刪除運作中執行個體仍在使用的服務帳戶。如果您刪除這種服務帳戶,執行個體可能會發生作業錯誤。

最佳做法

  • 限制可透過服務帳戶執行動作的使用者。如果使用者具有服務帳戶的服務帳戶使用者角色,就能間接存取服務帳戶有權存取的所有資源。因此,將 serviceAccountUser 角色授予使用者時,請務必小心謹慎。

  • 只為服務帳戶授予達成作業目標所需的最低權限。如要進一步瞭解,請參閱將角色授予特定資源的服務帳戶一節。

  • 為各項服務建立的服務帳戶,只具備服務本身需要的權限。

  • 利用服務帳戶的顯示名稱來追蹤服務帳戶。建立服務帳戶時,可將服務帳戶的用途填入顯示名稱。

  • 為您的服務帳戶制訂命名慣例。

  • 執行相關程序以自動輪替由使用者代管的服務帳戶金鑰。

  • 利用 IAM service account API 執行金鑰輪替作業。

  • 透過 serviceAccount.keys.list() 方法或主控台的記錄檢視器頁面來稽核服務帳戶。

  • 除非您希望這些應用程式無法存取服務帳戶,否則請勿透過在 App Engine 或 Compute Engine 上執行執行個體來刪除使用中的服務帳戶。

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Cloud IAM 說明文件