本页面介绍如何使用服务帐号启用在虚拟机 (VM) 实例上运行的应用,以向 Google Cloud API 进行身份验证并授予对资源的访问权限。
如需详细了解 Compute Engine 如何使用服务帐号,请参阅服务帐号概览。
准备工作
- 如果您要使用本指南中的命令行示例,请执行以下操作:
- 安装或更新到 Google Cloud CLI 的最新版本。
- 设置默认区域和可用区。
- 如果您要使用本指南中的 API 示例,请设置 API 访问权限。
- 阅读服务帐号概览。
创建新的服务帐号
您可以使用 IAM 创建并设置新的服务帐号。创建帐号后,为该帐号授予一个或多个 IAM 角色,然后授权虚拟机实例以该服务帐号的身份运行。
控制台
要创建新的服务帐号,请执行以下操作:
按照创建服务帐号中所述创建新的服务帐号。
获取服务帐号的电子邮件地址。您需要使用该电子邮件地址将实例设置为以此服务帐号的身份运行。在控制台中验证服务帐号的电子邮件地址:
转到服务帐号页面。
如果出现提示,请选择项目。
查找您的新服务帐号并记下服务帐号电子邮件地址。
通常,服务帐号的电子邮件地址来源于服务帐号 ID,格式如下:
[SERVICE-ACCOUNT-NAME]@[PROJECT_ID].iam.gserviceaccount.com
向服务帐号授予 IAM 角色。如果您不授予任何角色,则服务帐号将无权访问任何服务。如需查看 IAM 角色的完整列表,请参阅 IAM 文档中的了解角色部分。
然后将实例设置为以服务帐号的身份运行。按照以下说明将实例设置为以服务帐号的身份运行。
Terraform
如需创建服务帐号,您可以使用 google_service_account
资源。
请务必替换 account_id
和 display_name
属性的占位值。
如需了解如何应用或移除 Terraform 配置,请参阅基本 Terraform 命令。
将新实例设置为以服务帐号的身份运行
创建新的服务帐号之后,您可以创建以该服务帐号的身份运行的新虚拟机实例。如果服务帐号与实例位于不同的项目中,则您必须为不同项目中的资源配置服务帐号。
如果要为现有实例分配或更改服务帐号,请参阅更改实例的服务帐号和访问范围。
您可以允许多个虚拟机实例使用同一个服务帐号,但一个虚拟机实例只能具有一个服务帐号身份。如果将同一服务帐号分配给多个虚拟机实例,则您对该服务帐号所做的任何后续更改都将影响使用该服务帐号的实例。这包括您对授予服务帐号的 IAM 角色所做的任何更改。例如,如果删除一个角色,则使用该服务帐号的所有实例都将失去该角色授予的权限。
通常,您可以只设置 cloud-platform
访问权限范围以允许访问大多数 Cloud API,然后仅向服务帐号授予相关 IAM 角色。授予虚拟机实例的访问权限范围与授予服务帐号的 IAM 角色共同决定了服务帐号对该实例具有的访问权限大小。仅当访问权限范围和 IAM 角色两者都允许时,服务帐号才能执行 API 方法。
或者,您可以选择设置特定范围,允许访问服务将调用的特定 API 方法。例如,如需调用 instances.insert
方法,需要获得 https://www.googleapis.com/auth/compute
范围或 https://www.googleapis.com/auth/cloud-platform
范围的授权以及授予对该方法的访问权限的 IAM 角色。您可以设置 compute
范围来代替 cloud-platform
范围,这将授予服务在 Compute Engine 中调用方法的访问权限,但并未授予服务在 Compute Engine 之外调用 API 方法的访问权限。
您可以通过 Google Cloud 控制台、Google Cloud CLI 或直接通过 API 将新实例设置为以服务帐号的身份运行。
控制台
转到创建实例页面。
指定虚拟机详情。
在身份和 API 访问权限部分,从下拉列表中选择要使用的服务帐号。
继续虚拟机创建过程。
gcloud
如需使用 Google Cloud CLI 创建新实例并授权该实例以自定义服务帐号的身份运行,请提供服务帐号电子邮件地址和该实例所需的访问权限范围。
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]
是--scopes
标志说明中提供的以英文逗号分隔的完整范围 URI 或范围别名。
例如:
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
gcloud CLI 还提供范围别名来代替较长的范围 URI。例如,对 Cloud Storage 的完整访问权限的范围是 https://www.googleapis.com/auth/devstorage.full_control
。此范围的别名是 storage-full
。
您可以在 --scopes
标志说明中的 instances create
页面上查看范围和范围别名的列表。instances create
命令帮助还列出了以下范围和别名:
gcloud compute instances create --help
按照与指定普通范围 URI 相同的方式指定别名。例如:
gcloud compute instances create [INSTANCE_NAME] \
--service-account [SERVICE_ACCOUNT_EMAIL] \
--scopes cloud-platform
Terraform
如需将新实例设置为以服务帐号的身份运行,您可以使用 google_compute_instance
资源。
API
在 API 中,构建一个标准请求来创建实例,但同时添加 serviceAccounts
属性。获取您的服务帐号电子邮件地址,并将其添加为 email
属性,此外还要添加实例所需的访问权限范围。
POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/instances { "machineType": "https://www.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"] } ], ... }
在将实例设置为以服务帐号的身份运行后,在实例上运行的应用可以使用以下方法之一进行身份验证:
- 对于大多数应用,请选择以下任一项:
- 对于需要 OAuth2 访问令牌的应用,请直接从元数据服务器请求和使用访问令牌
使用服务帐号凭据对应用进行身份验证
在将实例设置为以服务帐号的身份运行后,您可以使用服务帐号凭据对实例上运行的应用进行身份验证。
使用客户端库对应用进行身份验证
客户端库可以使用应用默认凭据在 Google API 中进行身份验证,并向这些 API 发送请求。应用默认凭据允许应用自动从多个源获取凭据,因此您可以在本地测试应用,然后将其部署到 Compute Engine 实例,而无需更改应用代码。
如需了解如何设置应用默认凭据,请参阅向应用默认凭据提供凭据。
此示例使用 Python 客户端库进行身份验证,并向 Cloud Storage API 发出请求以列出项目中的存储桶。该示例采用以下过程:
- 获取 Cloud Storage API 所需的必要身份验证凭据,并使用
build()
方法和凭据初始化 Cloud Storage 服务。 - 列出 Cloud Storage 中的存储分区。
您可以在有权管理 Cloud Storage 中的存储分区的实例上运行此示例。
直接使用访问令牌对应用进行身份验证
对于大多数应用,您可以使用应用默认凭据进行身份验证,该凭据会为您查找凭据和管理令牌。不过,如果您的应用要求您提供 OAuth2 访问令牌,Compute Engine 允许您从其元数据服务器获取访问令牌,以便在应用中使用。
在获取并使用这些访问令牌对应用进行身份验证时,有几种方法可供选择。例如,您可以使用 curl
创建简单请求,或使用 Python 之类的编程语言实现更大的灵活性。
cURL
如需使用 curl
请求访问令牌并向 API 发送请求,请执行以下操作:
在应用运行的实例上,通过运行以下命令在元数据服务器中查询访问令牌:
$ 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'`
从响应中复制
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。该示例采用以下过程:
- 从元数据服务器请求访问令牌。
- 从服务器响应中提取访问令牌。
- 使用访问令牌向 Cloud Storage 发出请求。
- 如果请求成功,脚本将输出响应内容。
访问令牌会在短时间后过期。元数据服务器会缓存访问令牌,直到离到期时间还有 5 分钟。您可以根据需要随时请求新令牌,但应用必须具有有效的访问令牌,其 API 调用才能成功。
使用服务帐号在实例上对工具进行身份验证
某些应用可能使用 gcloud
和 gsutil
工具中的命令,大多数 Compute Engine 映像中都会默认附带这些工具。这些工具会自动识别实例的服务帐号和授予服务帐号的相关权限。具体来说,如果您向服务帐号授予正确的角色,则可以使用实例中的 gcloud
和 gsutil
工具,而无需使用 gcloud auth login
。
这种服务帐号识别会自动发生,且仅适用于实例随附的 gcloud
和 gsutil
工具。如果您要创建新工具或添加自定义工具,则必须使用客户端库或直接在应用中使用访问令牌对应用进行授权。
如需利用自动服务帐号识别功能,请向服务帐号授予相应 IAM 角色,并将实例设置为以服务帐号的身份运行。例如,如果您授予服务帐号 roles/storage.objectAdmin
角色,则 gsutil
工具可以自动管理和访问 Google Cloud Storage 对象。
同样,如果为该服务帐号启用 roles/compute.instanceAdmin.v1
,则 gcloud compute
工具可自动管理实例。
更改实例的服务帐号和访问权限范围
如果您想要以不同身份运行虚拟机,或者确定实例需要另一组范围来调用所需的 API,则可以更改现有实例的服务帐号和访问范围。例如,您可以更改访问权限范围以授予对新 API 的访问权限,移除服务帐号和访问权限范围以阻止虚拟机访问任何 Google Cloud 服务,也可以更改虚拟机,使其以您创建的服务帐号(而不是 Compute Engine 默认服务帐号)的身份运行。但是,Google 建议您使用精细的 IAM 政策(而不是依赖于访问权限范围)来控制服务帐号的资源访问权限。
如需更改实例的服务帐号和访问权限范围,您必须暂时停止该实例。如需停止实例,请阅读有关停止实例的文档。 更改服务帐号或访问权限范围后,请记得重启实例。使用以下一种方法更改已停止实例的服务帐号或访问范围。
控制台
转到虚拟机实例页面。
点击要为其更改服务帐号的虚拟机实例名称。
如果实例未停止,请点击停止。等待实例停止。
然后,点击修改。
向下滚动到服务帐号部分。
从下拉列表中,选择要分配给实例的服务帐号。
- 如果您选择默认服务帐号,则可以在 Google Cloud 控制台中修改其访问权限范围。
- 如需更改范围,请在访问权限范围部分中,选择针对每个 API 设置访问权限,并根据需要设置适当的范围。
- 如果您不确定要设置的正确访问权限范围,请选择允许所有 Cloud API 的全面访问权限,然后确保通过设置服务帐号的 IAM 角色来限制访问权限。
- 如果您选择其他服务帐号,则虚拟机的访问权限范围默认为
cloud-platform
范围。您可以使用 gcloud CLI 或 Compute Engine API 修改范围。 - 如需详细了解如何设置访问权限范围,请参阅最佳做法。
- 如果您选择默认服务帐号,则可以在 Google Cloud 控制台中修改其访问权限范围。
点击保存以保存更改。
gcloud
使用 instances set-service-account
命令并提供实例名称、服务帐号电子邮件地址和所需的范围。如需详细了解如何设置访问权限范围,请参阅最佳做法。
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]
是--scopes
标志说明中提供的以英文逗号分隔的完整范围 URI 或范围别名。如果要移除实例的所有范围,请改为使用--no-scopes
标志。
例如,以下命令将服务帐号 my-sa-123@my-project-123.iam.gserviceaccount.com
分配给名为 example-instance 的实例,并对该实例设置访问权限范围,以允许对 Compute Engine 进行读写访问,同时允许对 Google 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"
]
}
获取服务帐号电子邮件地址
为了识别服务帐号,您需要服务帐号电子邮件。通过以下任一种方式获取服务帐号电子邮件:
控制台
转到服务帐号页面。
如果出现提示,请选择项目。该服务帐号页面列出了项目的所有服务帐号及其电子邮件地址。
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
使用 Compute Engine 默认服务帐号
如果您熟悉 Compute Engine 默认服务帐号,并希望使用默认服务帐号提供的凭据而不是创建新服务帐号,则可以将 IAM 角色授予默认服务帐号。
默认情况下,所有 Compute Engine 实例均可以默认服务帐号的身份运行。如果您使用 Google Cloud CLI 或 Google Cloud 控制台创建实例,并忽略所有服务帐号规范,系统会将默认服务帐号分配给实例。
在将 IAM 角色分配给默认服务帐号之前,请注意:
向默认服务帐号授予 IAM 角色会影响以默认服务帐号的身份运行的所有实例。例如,如果您向默认服务帐号授予
roles/storage.objectAdmin
角色,则具有所需访问权限范围且以默认服务帐号的身份运行的所有实例都将具有roles/storage.objectAdmin
角色授予的权限。同样,如果通过省略某些角色来限制访问,则会影响以默认服务帐号的身份运行的所有实例。必须撤消服务帐号的项目 Editor 权限。默认情况下,默认服务帐号会作为项目 Editor 添加到项目中。 如需使用 IAM 角色,您必须撤消项目 Editor 权限。
如果您不确定如何向默认服务帐号授予 IAM 角色,请改为创建新服务帐号。
按照以下说明向默认服务帐号授予 IAM 角色:
在 Google Cloud 控制台中,转到 IAM 页面。
如果出现提示,请选择项目。
查找名为 Compute Engine 默认服务帐号的服务帐号。
在角色列中,展开下拉菜单找到“Compute Engine 默认服务帐号”。
移除编辑者访问权限并保存更改。
然后向服务帐号授予 IAM 角色。
当前以默认服务帐号身份运行的任何虚拟机实例现在都可以根据您授予该帐号的 IAM 角色访问其他 Google Cloud API。
如果要将新实例设置为以默认服务帐号身份运行,请按照以下说明操作:
控制台
转到创建实例页面。
指定虚拟机详情。
在身份和 API 访问权限部分中,从服务帐号下拉列表中选择 Compute Engine 默认服务帐号。
继续虚拟机创建过程。
gcloud
如需创建新实例并授予其使用默认服务帐号对所有 Google Cloud 服务的完整访问权限,请执行以下操作:
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://www.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 的虚拟机实例应以服务帐号的身份运行,该虚拟机具有执行其作业所需的最低权限。
按照以下说明为您的虚拟机配置服务帐号:
- 创建新的服务帐号,而不是使用 Compute Engine 默认服务帐号。
- 仅针对所需的资源,将 IAM 角色授予该服务帐号。
- 将虚拟机配置为以您创建的新服务帐号的身份运行。
- 向虚拟机授予
https://www.googleapis.com/auth/cloud-platform
范围,以允许访问大多数 Google Cloud API,从而使虚拟机的 IAM 权限完全由您向虚拟机的服务帐号授予的 IAM 角色决定。服务帐号只能执行访问权限范围和服务帐号的特定 IAM 角色所允许的 API 方法。
限制服务帐号的权限并定期检查服务帐号权限以确保其始终能满足需求。
请谨慎删除服务帐号。在删除之前,请确保您的关键应用不再使用该服务帐号。如果您不确定某个服务帐号是否正在使用,我们建议您停用该服务帐号,而不是将其删除。已停用的服务帐号可以在需要时重新启用。
缓解您的服务帐号的安全风险。如需了解详情,请参阅使用服务帐号的最佳实践。
后续步骤
- 详细了解服务帐号。
- 详细了解 Compute Engine IAM 角色。
- 详细了解使用服务帐号的最佳实践。
自行试用
如果您是 Google Cloud 新手,请创建一个帐号来评估 Compute Engine 在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
免费试用 Compute Engine