为 GCP 模拟类似于 "sts assume role" 的行为,以便在本地环境中设置全局身份验证

Simulate behavior analogous to "sts assume role" for GCP for setting up a global authentication in local environment

我认为我已经走到了死胡同,但我希望得到专家的一些验证。

我这周开始学习GCP,我正在尝试实现我以前能够通过AWS云平台实现的东西。因为我对 GCP 一无所知,所以请告诉我。

问题:

在本地机器上,配置动态获取的短期凭据,用于使用 public 云 API 进行身份验证(静态密钥不在考虑之列)

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

在某种程度上,public 云平台提供的客户端 SDK 在调用 public 云平台时使用这些凭据作为默认(模拟非人类)身份 APIs.

让我们说,在我的本地机器上: 我有一个经过身份验证的 用户 A,他需要代表 ServiceAccount/Role B 调用 public 云 API .

平台:

AWS - 已解决

GCP - 未解决

AWS 解决方案

在 AWS 中,问题陈述将是: 在我的本地机器上,我被认证为用户 A,我希望我的本地 AWS 客户端 SDK 以 IAM-ROLE-B

的身份调用 AWS APIs

解决方法如下:

1 - 授权用户 A 通过用户 A 的 IAM 角色策略

对 IAM-ROLE-B 执行 sts:AssumeRole

2 - 授权用户 A 通过对用户 B

的 IAM 代入角色策略对 IAM-ROLE-B 执行 sts:AssumeRole

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

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

GCP 中的障碍

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

在我的本地机器上,我被认证为用户 A,我希望我的本地 GCP 客户端 SDK 以 SERVICE-ACCOUNT-B[= 的身份调用 GCP APIs 77=]

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

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

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

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

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

非常感谢任何解决问题的意见和想法(没有静态密钥)。

不,您在使用 gcloud、API 请求或客户端库时在 GCP 中寻找的方法不像在 AWS 中那样可行。正如您已经提到的,最好的方法是 impersonating service accounts.

您应该考虑到每次模拟服务帐户时都应该明确地这样做,因为您无法像在 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 请求时始终包含令牌,这就是您现在正在做的事情。