建立和啟用執行個體的服務帳戶

在執行個體上執行的應用程式,可透過服務帳戶授權並與 Google Cloud Platform API 互動。具有必要 Compute Engine 身分與存取權管理角色的服務帳戶,可讓應用程式的程式碼執行特定的 API 要求。

如要進一步瞭解服務帳戶,請參閱服務帳戶總覽。

事前準備

建立新的服務帳戶

您可以使用 Cloud IAM 來建立及設定新的服務帳戶。建立帳戶之後,請為該帳戶授予一或多個身分與存取權管理角色,然後再授權虛擬機器執行個體以該服務帳戶身分執行。

如要建立新的服務帳戶,請執行下列操作:

  1. 按照建立服務帳戶一節中的說明,建立新的服務帳戶

  2. 取得該服務帳戶的電子郵件。您需要電子郵件,才能設定執行個體以此服務帳戶身分執行。在主控台中驗證服務帳戶的電子郵件:

    1. 前往 GCP Console 的「Service Accounts」(服務帳戶) 頁面。

      前往「Service Accounts」(服務帳戶) 頁面

    2. 如果出現提示,請選取專案。
    3. 找到新的服務帳戶,並記下該服務帳戶的電子郵件。

    一般來說,服務帳戶的電子郵件源自於服務帳戶 ID,格式如下:

    [SERVICE-ACCOUNT-NAME]@[PROJECT_ID].iam.gserviceaccount.com
    
  3. 為該服務帳戶授予身分與存取權管理角色。若沒有授予任何角色,該服務帳戶將無法存取任何服務。如需完整的身分與存取權管理角色清單,請參閱身分與存取權管理說明文件中的瞭解角色主題。

  4. 接下來,設定執行個體以服務帳戶身分執行。請按照操作說明設定執行個體以服務帳戶身分執行

設定新的執行個體以服務帳戶身分執行

建立新的服務帳戶之後,即可建立新的虛擬機器執行個體,使其以該服務帳戶身分執行。如果您想要指派或變更現有執行個體的服務帳戶,請參閱變更執行個體的服務帳戶與存取權範圍一節。

您可以讓多個虛擬機器執行個體使用同一服務帳戶,但每一個虛擬機器執行個體只能有一個服務帳戶身分。如果您將同一個服務帳戶指派給多個虛擬機器執行個體,日後這個服務帳戶所發生的任何變更都會影響到所有使用這個服務帳戶的執行個體。這表示,如果您對這個服務帳戶所具備的身分與存取權管理角色,執行了任何變更,也會連帶影響使用這個服務帳戶的執行個體。舉例來說,如果移除了某個角色,那麼使用這個服務帳戶的所有執行個體也會失去該角色所授予的權限。

您可以透過 Google Cloud Platform Consolegcloud 指令列工具或直接透過 API,設定要以服務帳戶身分執行的新執行個體。

主控台

  1. 前往 GCP 主控台的「VM instances」(VM 執行個體) 頁面。

    前往 VM 執行個體頁面

  2. 按一下 [建立執行個體]
  3. 在「Create a new instance」(建立新執行個體) 頁面,填寫執行個體的屬性。
  4. 在「Identity and API access」(身分及 API 存取權) 部分,從下拉式清單中選擇您要使用的服務帳戶。
  5. 按一下 [Create] (建立) 來建立執行個體。

gcloud

如要建立新的執行個體,並使用 gcloud 指令列工具授權它以自訂服務帳戶身分執行,請提供服務帳戶電子郵件及您對該執行個體的期望存取權範圍。一般來說,您可以只設定 cloud-platform 存取權範圍。授予虛擬機器執行個體的存取權範圍,以及授予服務帳戶的身分與存取權管理角色,這二者會共同決定服務帳戶對該執行個體有多少存取權。只有存取權範圍及身分與存取權管理角色都允許執行 API 方法,服務帳戶才能執行 API 方法。

您也可以選擇針對服務將呼叫的特定 API 方法,設定具體的存取權授權範圍。舉例來說,如要呼叫 instances.insert 方法,您必須具有 https://www.googleapis.com/auth/compute 範圍或 https://www.googleapis.com/auth/cloud-platform 範圍的相關授權,還有授予該方法存取權的身分與存取權管理角色。設定時,您可以用 compute 範圍取代 cloud-platform 範圍,這樣就會將服務呼叫方法的權限,設定在 Compute Engine 之內,其便無法在 Compute Engine 之外呼叫 API。

gcloud compute instances create [INSTANCE_NAME] \
    --service-account [SERVICE_ACCOUNT_EMAIL] \
    --scopes [SCOPES,...]

其中:

  • [SERVICE_ACCOUNT_EMAIL] 是您要使用的服務帳戶電子郵件,例如:my-sa-123@my-project-123.iam.gserviceaccount.com。如果您不知道電子郵件是哪一個,請瞭解如何取得服務帳戶電子郵件
  • [INSTANCE_NAME] 是執行個體的名稱。
  • [SCOPES] 是以逗號分隔的完整範圍 URI 清單,或在 --scopes 旗標說明中所提供的範圍別名清單。

例如:

gcloud compute instances create example-vm \
    --service-account 123-my-sa@my-project-123.iam.gserviceaccount.com \
    --scopes https://www.googleapis.com/auth/cloud-platform

如果範圍 URI 較長,gcloud 工具也會提供範圍別名取代。舉例來說,Cloud Storage 完整存取權的範圍為 https://www.googleapis.com/auth/devstorage.full_control。此範圍可以用 storage-full 別名代表。

您可以在 instances create 頁面的 --scopes 旗標說明中,查看範圍及範圍別名的清單。instances create 指令的說明中也會列出這些範圍和別名:

gcloud compute instances create --help

指定別名的方法與指定一般範圍 URI 相同。例如:

gcloud compute instances create [INSTANCE_NAME] \
    --service-account [SERVICE_ACCOUNT_EMAIL] \
    --scopes cloud-platform

API

在 API 中,建構一個標準要求來建立執行個體,但要加上 serviceAccounts 屬性。取得您的服務帳戶電子郵件,然後加上 email 屬性,還有執行個體需要的存取權範圍。一般來說,您可以只設定 cloud-platform 存取權範圍。存取權範圍,以及授予服務帳戶的身分與存取權管理角色,這二者會共同決定服務帳戶對該執行個體有多少存取權。只有存取權範圍及身分與存取權管理角色都允許執行 API 方法,服務帳戶才能執行 API 方法。

您也可以選擇針對服務將呼叫的特定 API 方法,設定具體的存取權授權範圍。舉例來說,如要呼叫 instances.insert 方法,您必須具有 https://www.googleapis.com/auth/compute 範圍或 https://www.googleapis.com/auth/cloud-platform 範圍的相關授權。設定時,您可以用 compute 範圍取代 cloud-platform 範圍,這樣就會將服務呼叫方法的權限,設定在 Compute Engine 之內,其便無法在 Compute Engine 之外呼叫 API。

POST https://compute.googleapis.com/compute/v1/projects/zones/[ZONE]/instances

{
  "machineType": "https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/machineTypes/[MACHINE_TYPE]",
  "name": "[INSTANCE_NAME]",
  "serviceAccounts": [
   {
    "email": "[SERVICE_ACCOUNT_EMAIL]",
    "scopes": ["https://www.googleapis.com/auth/cloud-platform"]
   }
  ],
  ...
}

設定執行個體以服務帳戶身分執行後,您可以透過下面幾種方式使用執行個體中的服務帳戶憑證:

使用服務帳戶憑證驗證應用程式

設定執行個體以服務帳戶身分執行後,您可以使用該服務帳戶的憑證,驗證在執行個體上執行的應用程式。

透過用戶端程式庫驗證應用程式

用戶端程式庫可以使用應用程式預設憑證向 Google API 進行驗證,然後傳送要求給這些 API。應用程式預設憑證可讓應用程式從多個來源取得憑證,方便您在本機測試應用程式,然後再將其部署至 Compute Engine 執行個體,過程中無須變更應用程式程式碼。當您在本機開發應用程式時,應用程式可以使用環境變數或 Cloud SDK 進行驗證。當應用程式在執行個體上執行時,它可以使用執行個體上已啟用的服務帳戶來進行驗證。

本範例使用 Python 用戶端程式庫向 Cloud Storage API 進行驗證,並要求列出專案中的值區。本範例採用以下程序:

  1. 為 Cloud Storage API 取得必要的驗證憑證,並使用 build() 方法和這些憑證初始化 Cloud Storage 服務。
  2. 列出 Cloud Storage 中的值區。

您可以在有權管理 Cloud Storage 中值區的執行個體上執行本範例。


import argparse

import googleapiclient.discovery

def create_service():
    # Construct the service object for interacting with the Cloud Storage API -
    # the 'storage' service, at version 'v1'.
    # Authentication is provided by application default credentials.
    # When running locally, these are available after running
    # `gcloud auth application-default login`. When running on Compute
    # Engine, these are available from the environment.
    return googleapiclient.discovery.build('storage', 'v1')

def list_buckets(service, project_id):
    buckets = service.buckets().list(project=project_id).execute()
    return buckets

def main(project_id):
    service = create_service()
    buckets = list_buckets(service, project_id)
    print(buckets)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('project_id', help='Your Google Cloud Project ID.')

    args = parser.parse_args()

    main(args.project_id)

直接透過存取憑證驗證應用程式

對於某些應用程式,您可能需要要求 OAuth2 存取憑證並直接透過該憑證來進行驗證,而不是透過用戶端程式庫或使用 gcloudgsutil 工具來進行驗證。您有幾種方法可以取得及使用這些存取憑證來驗證應用程式。例如,您可以使用 curl 建立簡單的要求,或使用 Python 等更有彈性的程式設計語言。

cURL

如要使用 curl 要求存取憑證並傳送要求給 API,請執行下列操作:

  1. 在應用程式執行所在的執行個體,執行下列指令,透過查詢中繼資料伺服器來取得存取憑證:

    $ curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
    -H "Metadata-Flavor: Google"

    這個要求會傳回類似以下的回應:

    {
          "access_token":"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_QtAS08i85nHq39HE3C2LTrCARA",
          "expires_in":3599,
          "token_type":"Bearer"
     }
  2. 複製回應中的 access_token 屬性值,然後用它傳送要求給 API。例如,以下要求會列印出您在特定區域中的專案的執行個體清單:

    $ curl https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/instances \
    -H "Authorization":"Bearer [ACCESS_TOKEN]"
    

    其中:

    • [PROJECT_ID] 是這項要求的專案 ID。
    • [ZONE] 是列出執行個體的所在區域。
    • [ACCESS_TOKEN] 是在步驟 1 中取得的存取憑證值。

    如要進一步瞭解您可以在要求設定哪些參數,請參閱參數說明文件。

Python

本範例將示範如何在 Python 應用程式中要求 Cloud Storage API 存取憑證。本範例採用以下程序:

  1. 向中繼資料伺服器要求存取憑證。
  2. 從伺服器的回應中擷取存取憑證。
  3. 使用該存取憑證向 Cloud Storage 發出要求。
  4. 如果要求成功,指令碼會列印回應。

import argparse

import requests

METADATA_URL = 'http://metadata.google.internal/computeMetadata/v1/'
METADATA_HEADERS = {'Metadata-Flavor': 'Google'}
SERVICE_ACCOUNT = 'default'

def get_access_token():
    url = '{}instance/service-accounts/{}/token'.format(
        METADATA_URL, SERVICE_ACCOUNT)

    # Request an access token from the metadata server.
    r = requests.get(url, headers=METADATA_HEADERS)
    r.raise_for_status()

    # Extract the access token from the response.
    access_token = r.json()['access_token']

    return access_token

def list_buckets(project_id, access_token):
    url = 'https://www.googleapis.com/storage/v1/b'
    params = {
        'project': project_id
    }
    headers = {
        'Authorization': 'Bearer {}'.format(access_token)
    }

    r = requests.get(url, params=params, headers=headers)
    r.raise_for_status()

    return r.json()

def main(project_id):
    access_token = get_access_token()
    buckets = list_buckets(project_id, access_token)
    print(buckets)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('project_id', help='Your Google Cloud project ID.')

    args = parser.parse_args()

    main(args.project_id)

存取憑證會在短時間內失效。中繼資料伺服器會快取存取憑證,直到存取憑證離到期日剩下 60 秒時才停止。您可以要求新的憑證,其時間與次數不限,但是您的應用程式必須具有有效的存取憑證,才能成功呼叫 API。

使用服務帳戶的執行個體上的驗證工具

某些應用程式可能會使用來自 gcloudgsutil 工具的指令,這些指令會預設包含在多數的 Compute Engine 映像檔中。這些工具會自動識別執行個體的服務帳戶及授予服務帳戶的相關權限。具體來說,如果您已為服務帳戶授予正確的角色,就可以使用來自執行個體的 gcloudgsutil 工具,而無須使用 gcloud auth login

這個服務帳戶的識別作業會自動啟動,並且只適用於執行個體包含的 gcloudgsutil 工具。如果您建立了新的工具或新增了自訂工具,那麼必須使用用戶端程式庫或透過直接在應用程式中使用存取憑證來授權應用程式。

為了讓自動識別服務帳戶的功能發揮效用,請為服務帳戶授予適當的身分與存取權管理角色,並設定執行個體以服務帳戶身分執行。舉例來說,如果您為服務帳戶授予 roles/storage.objectAdmin 角色,gsutil 工具就能自動管理及存取 Cloud Storage 物件。

同樣地,如果為服務帳戶啟用了 roles/compute.instanceAdmin.v1gcloud compute 工具就能自動管理執行個體。

變更執行個體的服務帳戶與存取權範圍

如果您想以不同的身分執行 VM,或是確定執行個體需要不同的一組範圍才能呼叫所需的 API 時,可以變更現有執行個體的服務帳戶及存取範圍。舉例來說,您可以變更存取權範圍來授予新 API 的存取權,或者變更執行個體,使其以您建立的服務帳戶身分 (而不是 Compute Engine 預設服務帳戶的身分) 執行。

如要變更執行個體的服務帳戶與存取權範圍,您必須暫時停止執行個體。如果要停止執行個體,請參閱停止執行個體說明文件。變更服務帳戶或存取權範圍之後,請記得重新啟動執行個體。請使用下列其中一種方法,變更已停止之執行個體的服務帳戶或存取權範圍。

主控台

  1. 前往 Compute Engine 的「VM instances」(VM 執行個體) 頁面。

    前往「VM Instances」(VM 執行個體) 頁面

  2. 按一下您要更新服務帳戶的執行個體。
  3. 如果執行個體未處於停止狀態,請按一下 [Stop] (停止) 按鈕。等待執行個體完全停止。
  4. 接下來,按一下 [Edit] (編輯) 按鈕。
  5. 向下捲動到「Service Account」(服務帳戶) 區段。
  6. 從下拉式選單中,選取所要的服務帳戶。
  7. 如要變更範圍,請在「Access Scopes」(存取權範圍) 區段中,設定符合需求的適當範圍。最佳做法是,只指定 VM 執行個體所需要的存取權範圍。如果不確定該如何設定適當的存取權範圍,請選擇 [Allow full access to all Cloud APIs] (允許所有 Cloud API 的完整存取權),然後再透過設定身分與存取權管理角色來限制存取權。
  8. 按一下 [Save] (儲存) 按鈕儲存變更。

gcloud

使用 instances set-service-account 指令,並提供執行個體名稱、服務帳戶電子郵件和期望的範圍。您也可以移除執行個體的服務帳戶和存取權範圍,藉此有效防止執行個體存取任何 Google Cloud Platform 服務:

gcloud compute instances set-service-account [INSTANCE_NAME] \
   [--service-account [SERVICE_ACCOUNT_EMAIL] | --no-service-account] \
   [--no-scopes | --scopes [SCOPES,...]]

其中:

  • [SERVICE_ACCOUNT_EMAIL] 是您要使用的服務帳戶電子郵件,例如:my-sa-123@my-project-123.iam.gserviceaccount.com
  • [INSTANCE_NAME] 是執行個體的名稱。
  • [SCOPES] 是以逗號分隔的完整範圍 URI 清單,或在 --scopes 旗標的說明中提供的範圍別名清單。如要移除執行個體的所有範圍,請改用 --no-scopes 旗標。

舉例來說,下列指令會將服務帳戶 my-sa-123@my-project-123.iam.gserviceaccount.com 指派給一個名稱為 example-instance 的執行個體,並在該執行個體上設定相關存取權範圍,以允許對 Compute Engine 進行讀寫,以及對 Cloud Storage 進行唯讀:

gcloud compute instances set-service-account example-instance \
   --service-account my-sa-123@my-project-123.iam.gserviceaccount.com \
   --scopes compute-rw,storage-ro

API

透過 API 向 setServiceAccount 方法發出 POST 要求。

https://compute.googleapis.com/compute/v1/projects[PROJECT_ID]/zones/[ZONE]/instances/[INSTANCE_NAME]/setServiceAccount

其中:

  • [PROJECT_ID] 是這項要求的專案 ID。
  • [ZONE] 是這個執行個體所屬的區域。
  • [INSTANCE_NAME] 是執行個體的名稱。

在要求主體中,提供服務帳戶的電子郵件地址,及執行個體需要的範圍 URI

{
  "email": "[SERVICE_ACCOUNT_EMAIL]",
  "scopes": [
    "[SCOPE_URI]",
    "[SCOPE_URI]",
    ...
  ]
}

例如,下列要求使用了服務帳戶電子郵件 my-sa-123@my-project-123.iam.gserviceaccount.com 並設定了 Cloud Storage 和 BigQuery 範圍:

{
  "email": "my-sa-123@my-project-123.iam.gserviceaccount.com",
  "scopes": [
    "https://www.googleapis.com/auth/bigquery",
    "https://www.googleapis.com/auth/devstorage.read_only"
  ]
}

取得服務帳戶電子郵件

為了識別服務帳戶,您需要服務帳戶電子郵件。請透過下列其中一個方法,取得服務帳戶電子郵件:

主控台

  1. 前往 GCP Console 的「Service Accounts」(服務帳戶) 頁面。

    前往「Service Accounts」(服務帳戶) 頁面

  2. 如果出現提示,請選取專案。「Service Accounts」(服務帳戶) 頁面會列出專案的所有服務帳戶及其電子郵件。

gcloud

使用本機電腦的 gcloud compute instances describe 指令:

gcloud compute instances describe [INSTANCE_NAME] --format json
{
      ...
      "serviceAccounts":[
         {
            "email":"123845678986-compute@developer.gserviceaccount.com",
            "scopes":[
               "https://www.googleapis.com/auth/devstorage.full_control"
            ]
         }
      ]
      ...
   }

如果執行個體未使用服務帳戶,您會收到不含 serviceAccounts 屬性的回應。

中繼資料伺服器

直接從執行個體查詢中繼資料伺服器。向 http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/ 發出要求:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/" \
-H "Metadata-Flavor: Google"

如果您在建立執行個體時啟用了一或多個服務帳戶,這個curl 指令會傳回類似以下的輸出:

123845678986-compute@developer.gserviceaccount.com/
default/

如果執行個體沒有使用任何服務帳戶,您會收到沒有內容的回應。

API

對 Service Accounts API 發出要求

使用 Compute Engine 預設服務帳戶

如果您熟悉 Compute Engine 預設服務帳戶,並且想使用預設服務帳戶提供的憑證,而不想建立新的服務帳戶,那麼您可以為預設服務帳戶授予身分與存取權管理角色。

根據預設,所有的 Compute Engine 執行個體都能以預設服務帳戶身分執行。如果您在使用 gcloud 指令列工具或 GCP Console 建立執行個體時省略了任何服務帳戶規格,系統就會將預設服務帳戶指派給執行個體。

將身分與存取權管理角色指派給預設服務帳戶之前,請注意以下幾點:

  • 為預設服務帳戶授予身分與存取權管理角色的動作,會使所有以預設服務帳戶身分執行的執行個體受到影響。舉例來說,如果您為預設服務帳戶授予了 roles/storage.objectAdmin 角色,那麼以預設服務帳戶 (帳戶具有必要存取權範圍) 身分執行的所有執行個體,也會獲得 roles/storage.objectAdmin 角色所授予的權限。同理,如果您藉由省略特定角色來限制存取權,這也會影響所有以預設服務帳戶身分執行的執行個體。

  • 您必須撤銷服務帳戶的專案編輯者權限。根據預設,系統會將預設服務帳戶新增為專案的專案編輯者。如果要使用身分與存取權管理角色,您必須撤銷專案編輯者權限。

如果您不確定是否要為預設服務帳戶授予身分與存取權管理角色,請改為建立新的服務帳戶

請按照下列操作說明,為預設服務帳戶授予身分與存取權管理角色:

  1. 前往 GCP Console 的「IAM」頁面。

    前往「IAM」頁面

  2. 如果出現提示,請選取專案。
  3. 找出名稱為「Compute Engine Default Service Account」(Compute Engine 預設服務帳戶) 的服務帳戶。
  4. 在「Role」(角色) 欄中,展開 Compute Engine 預設服務帳戶的下拉式選單。
  5. 移除「編輯者」存取權並儲存變更。
  6. 接下來,為服務帳戶授予身分與存取權管理角色

所有目前以預設服務帳戶身分執行的虛擬機器執行個體,現在都可以根據您授予該帳戶的身分與存取權管理角色,存取其他的 Google Cloud Platform API。

如果您想要設定新的執行個體以預設服務帳戶身分執行,請按照下列操作說明:

主控台

  1. 前往 GCP 主控台的「VM instances」(VM 執行個體) 頁面。

    前往 VM 執行個體頁面

  2. 按一下 [建立執行個體]
  3. 在「Create a new instance」(建立新執行個體) 頁面,填寫執行個體的屬性。
  4. 在「Identity and API Access」(身分及 API 存取權) 部分,從下拉式清單中選擇 [Compute Engine Default Service Account] (Compute Engine 預設服務帳戶)。
  5. 按一下 [Create] (建立) 來建立執行個體。

gcloud

如要使用預設服務帳戶建立新的執行個體,並授予其所有 Google Cloud Platform 服務的完整存取權,請執行下列操作:

gcloud compute instances create [INSTANCE_NAME] \
     --scopes cloud-platform

API

在 API 中,建構一個標準要求來建立執行個體,但要加上 serviceAccounts 屬性。取得預設服務帳戶 ID,並將其加入做為服務帳戶的 email。接著,在 scopes 屬性中設定一或多個範圍。

POST https://compute.googleapis.com/compute/v1/projects/zones/[ZONE]/instances

{
  "machineType": "https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/machineTypes/[MACHINE_TYPE]",
  "name": "[INSTANCE_NAME]",
  "serviceAccounts": [
   {
    "email": "[DEFAULT_SERVICE_ACCOUNT_EMAIL]",
    "scopes": ["https://www.googleapis.com/auth/cloud-platform"]
   }
  ],
  ...
}

最佳做法

一般來說,Google 建議所有需要呼叫 Google API 的執行個體,都應該以具有該執行個體執行其工作所需的最低權限的服務帳戶身分來執行。在實務上,這指的是,您必須按照下列程序,設定執行個體的服務帳戶:

  1. 建立新的服務帳戶,而不使用 Compute Engine 預設服務帳戶。
  2. 只針對該服務帳戶需要的資源,授予相關的身分與存取權管理角色。
  3. 設定執行個體以該服務帳戶身分執行。
  4. https://www.googleapis.com/auth/cloud-platform 範圍授予執行個體,允許對所有 Google Cloud API 的完整存取權,使執行個體的身分與存取權管理權限完全由服務帳戶的身分與存取權管理角色決定。

請避免授予超過需要的存取權,並定期檢查服務帳戶權限,以確保合乎時宜。

後續步驟

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

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

這個網頁
Compute Engine 說明文件