使用服务账号向 Google Cloud API 验证工作负载身份验证


本页面介绍如何使用服务账号使在虚拟机 (VM) 实例上运行的应用向 Google Cloud API 进行身份验证并授予对资源的访问权限。

如需使用服务账号进行身份验证,您必须先确保虚拟机已配置为使用服务账号。为此,请完成以下步骤之一:

准备工作

  • 查看服务账号概览
  • 如果您尚未设置身份验证,请进行设置。身份验证是通过其进行身份验证以访问 Google Cloud 服务和 API 的过程。如需从本地开发环境运行代码或示例,您可以按如下方式向 Compute Engine 进行身份验证。

    如需在本地开发环境中使用本页面上的 Python 示例,请安装并初始化 gcloud CLI,然后使用您的用户凭据设置应用默认凭据。

    1. Install the Google Cloud CLI.
    2. To initialize the gcloud CLI, run the following command:

      gcloud init
    3. If you're using a local shell, then create local authentication credentials for your user account:

      gcloud auth application-default login

      You don't need to do this if you're using Cloud Shell.

    如需了解详情,请参阅 Set up authentication for a local development environment

概览

将虚拟机实例设置为使用服务账号运行后,在虚拟机实例上运行的应用可以使用以下方法之一进行身份验证:

使用服务账号凭据对应用进行身份验证

在将实例设置为以服务账号的身份运行后,您可以使用服务账号凭据对实例上运行的应用进行身份验证。

使用客户端库对应用进行身份验证

客户端库可以使用应用默认凭据在 Google API 中进行身份验证,并向这些 API 发送请求。应用默认凭据允许应用自动从多个源获取凭据,因此您可以在本地测试应用,然后将其部署到 Compute Engine 实例,而无需更改应用代码。

如需了解如何设置应用默认凭据,请参阅向应用默认凭据提供凭据

此示例使用 Python 客户端库进行身份验证,并向 Cloud Storage API 发出请求以列出项目中的存储桶。该示例采用以下过程:

  1. 获取 Cloud Storage API 所需的必要身份验证凭据,并使用 build() 方法和凭据初始化 Cloud Storage 服务。
  2. 列出 Cloud Storage 中的存储桶。

您可以在有权管理 Cloud Storage 中的存储分区的实例上运行此示例。

import argparse
from typing import List

from google.cloud import storage


def create_client() -> storage.Client:
    """
    Construct a client object for the Storage API using the
    application default credentials.

    Returns:
        Storage API client object.
    """
    # 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 storage.Client()


def list_buckets(client: storage.Client, project_id: str) -> List[storage.Bucket]:
    """
    Retrieve bucket list of a project using provided client object.


    Args:
        client: Storage API client object.
        project_id: name of the project to list buckets from.

    Returns:
        List of Buckets found in the project.
    """
    buckets = client.list_buckets()
    return list(buckets)


def main(project_id: str) -> None:
    client = create_client()
    buckets = list_buckets(client, 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 访问令牌,Compute Engine 允许您从其元数据服务器获取访问令牌,以便在应用中使用。

在获取并使用这些访问令牌对应用进行身份验证时,有几种方法可供选择。例如,您可以使用 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"
     }

    对于 API 请求,您需要添加 access_token 值,而不是整个响应。如果您已安装 jq 命令行 JSON 处理器,则可以使用以下命令从响应中提取访问令牌值:

    $ ACCESS_TOKEN=`curl \
    "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
    -H "Metadata-Flavor: Google" | jq -r '.access_token'`
    
  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:您在上一步中获得的访问令牌值。

    如需了解可在请求中设置的参数,请参阅系统参数文档。

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() -> str:
    """
    Retrieves access token from the metadata server.

    Returns:
        The access token.
    """
    url = f"{METADATA_URL}instance/service-accounts/{SERVICE_ACCOUNT}/token"

    # 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: str, access_token: str) -> dict:
    """
    Calls Storage API to retrieve a list of buckets.

    Args:
        project_id: name of the project to list buckets from.
        access_token: access token to authenticate with.

    Returns:
        Response from the API.
    """
    url = "https://www.googleapis.com/storage/v1/b"
    params = {"project": project_id}
    headers = {"Authorization": f"Bearer {access_token}"}

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

    return r.json()


def main(project_id: str) -> None:
    """
    Retrieves access token from metadata server and uses it to list
    buckets in a project.

    Args:
        project_id: name of the project to list buckets from.
    """
    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)

访问令牌会在短时间后过期。元数据服务器会缓存访问令牌,直到离到期时间还有 5 分钟。如果无法缓存令牌,则每秒查询次数超过 50 次的请求可能会受到速率限制。您的应用必须具有有效的访问令牌,其 API 调用才能成功。

使用服务账号在实例上对工具进行身份验证

某些应用可以使用 gcloud CLI 中的命令,大多数 Compute Engine 映像中都会默认附带 gcloud CLI。gcloud CLI 会自动识别实例的服务账号和向服务账号授予的相关权限。具体来说,如果您向服务账号授予正确的角色,则可以使用实例中的 gcloud CLI,而无需使用 gcloud auth login

这种服务账号识别会自动发生,且仅适用于实例附带的 gcloud CLI。如果您要创建新工具或添加自定义工具,则必须使用客户端库直接在应用中使用访问令牌对应用进行授权。

如需利用服务账号自动识别功能,请向服务账号授予相应 IAM 角色,并将服务账号关联到实例。例如,如果您授予服务账号 roles/storage.objectAdmin 角色,则 gcloud CLI 可以自动管理和访问 Cloud Storage 对象。

同样,如果为该服务账号启用 roles/compute.instanceAdmin.v1,则 gcloud compute 工具可自动管理实例。

后续步骤

自行试用

如果您是 Google Cloud 新手,请创建一个账号来评估 Compute Engine 在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。

免费试用 Compute Engine