首页 > 解决方案 > 为 GCP 模拟类似于“sts 承担角色”的行为,以在本地环境中设置全局身份验证

问题描述

我相信我已经走到了死胡同,但我想得到专家的一些验证。

这周我开始学习 GCP,我正在努力实现以前使用 AWS 云平台能够实现的目标。请告诉我,因为我对 GCP 一无所知。

问题:

在本地机器上,配置动态获取的、短暂的凭据以使用公共云 API 进行身份验证(静态密钥是不可能的)

当经过身份验证的人类用户(GCP:IAM 用户,AWS:IAM 用户)冒充非人类身份(GCP:IAM 服务帐户,AWS:IAM 角色)时,

公共云平台提供的客户端 SDK 在调用公共云平台 API 时使用这些凭据作为默认(模拟的非人类)身份。

假设在我的本地机器上:我有一个经过身份验证的用户 A,他需要代表ServiceAccount/Role B调用公共云 API 。

平台:

AWS - 已解决

GCP - 未解决

AWS 解决方案

在 AWS 中,问题陈述将是:在我作为用户 A 进行身份验证的本地机器上,我希望我的本地 AWS 客户端 SDK 以 IAM-ROLE-B 的身份调用 AWS API

解决方案如下:

1 - 通过用户 A 的 IAM 角色策略授权用户 A 对 IAM-ROLE-B 执行 sts:AssumeRole

2 - 授权用户 A 执行 sts:AssumeRole 对 IAM-ROLE-B 通过用户 B 上的 IAM 承担角色策略

3 - 例如,使用 aws cli 对 AWS STS API 进行 AssumeRole 操作调用。这将返回我:访问密钥 ID 和 b。秘密访问密钥

4 - 在 ~/.aws/.creds 文件中设置这些,所有 SDK 默认使用这些凭据

GCP 中的障碍

当我尝试为 GCP 模拟相同的行为时,就会出现问题。

在我作为用户 A 进行身份验证的本地计算机上,我希望我的本地 GCP 客户端 SDK 以 SERVICE-ACCOUNT-B 的身份调用 GCP API

由于我需要动态的短期凭据,因此我不能使用静态且太不安全的服务帐户密钥文件,我们知道不使用它的充分理由。

我知道的唯一其他选择是通过projects.serviceAccounts.generateAccessToken “模拟”服务帐户(代表 SERVICE-ACCOUNT-B 进行调用) 。根据我的 AWS 类比,我在步骤 3 中收到访问密钥 ID 和访问密钥秘密 ,我可以全局设置(供客户端 SDK 使用)。

在 GCP 的情况下,projects.serviceAccounts.generateAccessToken 调用给了我一个 AccessToken,它基本上是代表 SERVICE-ACCOUNT-B 进行调用的短期身份验证。

虽然我可以将此访问令牌注入到我打算对未来调用 GCP 发出的请求中,但有没有办法将其全局设置为由 GCP 客户端 SDK 自动获取,我不必修改我的代码库并注入这个在我的代码中以某种方式标记?

回想一下我是一个完全的 GCP 新手这一事实,我是否在思考正确的方向?还是我完全弄乱了 GCP 身份验证概念并在解决问题的方法中走错了路?

非常感谢任何解决问题的输入和想法(没有静态键)。

标签: amazon-web-servicesgoogle-cloud-platformamazon-iamgoogle-cloud-iam

解决方案


不,您在使用 API 请求或客户端库时在 GCP 中寻找的方法gcloud不可能像在 AWS 中那样。正如您已经提到的,最好的方法是模拟服务帐户

您应该考虑每次模拟服务帐户时都应该明确地进行,因为您无法像在 AWS 中那样存储凭证,例如:

gcloud compute instances create sample_vm --zone=us-central1-a \
  --machine-type=n1-standard-1 --image=centos-8-v20200811 \
  --image-family centos-8 --image-project=centos-cloud  \
  --impersonate-service-account=impersonated@project_id.iam.gserviceaccount.com

或者在使用客户端库时:

from google.cloud import storage
from google.auth import impersonated_credentials
import google.auth

target_scopes=[ 'https://www.googleapis.com/auth/devstorage.read_only' ]

my_credentials, project = google.auth.default()

impersonated_credentials = impersonated_credentials.Credentials(
    source_credentials=my_credentials,
    target_principal='impersonate@project.iam.gserviceaccount.com',
    target_scopes=target_scopes,
    lifetime=60)

client = storage.Client(credentials=impersonated_credentials)
blobs = client.list_blobs('bucket_name')
for blob in blobs:
    print(blob.name) 

最后,您应该在执行 API 请求时始终包含令牌,这就是您现在正在执行的操作。


推荐阅读