使用 Google Cloud Platform 原生工作负载身份访问 AWS 安全博客
使用 Google Cloud Platform 原生工作负载身份访问 AWS
作者:Simran Singh 和 Rashmi Iyer,发表于 2023年12月22日分类:中级 (200)、多云、安全、身份与合规、技术如何做
永久链接评论 分享
关键要点
本文展示如何通过 Google Cloud Platform (GCP) 的身份令牌,安全地在 AWS 中获取临时凭证。介绍了相关的访问控制和认证流程的最佳实践。包含了用于设置的具体步骤,以及对重要步骤的额外说明。组织在进行云迁移和业务转型时,往往需要在混合或多云环境中管理 IT 操作。这使得保障工作负载、应用程序和数据的安全,以及有效处理身份和权限变得更加复杂。本文将教你如何在 AWS 账户中使用 AWS 身份与访问管理 (IAM) 角色,安全地为运行在 GCP 上的应用程序颁发临时凭证。

安全领域中的访问控制
随着多云环境的扩大,跨不同提供商的访问控制管理变得更具挑战性。通过从一开始就实施适当的访问控制,可以有效扩展云操作,而不影响安全性。当你在多个云提供商之间部署应用时,应当在这两个云环境中实施统一一致的身份验证和授权机制,以维护安全且具成本效益的环境。接下来,我们将探讨如何在 AWS 和托管在 GCP 的工作负载之间实现这些目标,如图 1 所示。
猎豹加速器pc版准备工作
按照以下准备工作进行操作:
在 GCP 中创建一个服务账户。GCP 中的资源通过服务账户进行 API 调用。在创建 GCP 资源如计算引擎实例时,会自动创建一个默认服务账户。尽管可以使用该默认服务账户,但我们推荐你创建一个用户管理的服务账户,以便在 GCP 内控制其权限。详细了解服务账户的最佳实践,请参考 Google 文档中的服务账户最佳实践。本帖中我们将使用 GCP 虚拟机 (VM) 实例进行演示。有关如何将服务账户附加到其他 GCP 资源的信息,请参见将服务账户附加到资源。
在 GCP 中创建一个虚拟机实例,并附加在步骤 1 中创建的服务账户。GCP 中的资源存储其元数据在元数据服务器上,你可以从服务器请求实例的身份令牌。稍后将在认证流程中使用此身份令牌。
在步骤 2 中创建的 GCP VM 上安装 AWS 命令行工具 (AWS CLI)。
安装jq和curl。
GCP VM 身份认证流程
获取在 GCP 上运行的工作负载的临时 AWS 凭证是一个多步骤过程。在此流程中,你将使用 GCP 计算引擎元数据服务器中的身份令牌,通过调用AssumeRoleWithWebIdentity API 来请求 AWS 临时凭证。此流程为你的应用程序提供了更大的灵活性,以请求已配置足够信任策略的 IAM 角色的凭证,且应用程序必须知道该 IAM 角色的相应 Amazon 资源名称 (ARN)。
在 AWS 上定义 IAM 角色
由于 AWS 已经支持开放ID连接 (OIDC) 联合身份认证,因此可以使用在步骤 2 中提到的 GCP 提供的 OIDC 令牌,而无需在你的 AWS 账户中创建单独的 OIDC 提供者。要创建用于 OIDC 联合身份认证的 IAM 角色,请按照 为 Web 身份或开放ID连接联合创建角色中的步骤操作。使用没有条件的 OIDC 验证者可能会过于宽松。为确保只有预期的身份提供者能够假设此角色,你需要在此 IAM 角色的信任策略中提供一个 StringEquals 条件。将条件键accountsgooglecomaud、accountsgooglecomoaud和accountsgooglecomsub添加到角色的信任策略中,如下所示:
json{ Version 20121017 Statement [ { Effect Allow Principal {Federated accountsgooglecom} Action stsAssumeRoleWithWebIdentity Condition { StringEquals { accountsgooglecomaud ltazpvaluegt accountsgooglecomoaud ltaudvaluegt accountsgooglecomsub ltsubvaluegt } } } ]}
确保将 ltplaceholder valuesgt 替换为来自Google ID 令牌的值。为服务账户颁发的 ID 令牌中,有 azp (AUTHORIZEDPARTY) 字段设置,因此条件键与 Google ID 令牌字段的对应关系如下:
accountsgooglecomoaud 条件键匹配 Google ID 令牌中的 aud (AUDIENCE) 字段。accountsgooglecomaud 条件键匹配 Google ID 令牌中的 azp (AUTHORIZEDPARTY) 字段。accountsgooglecomsub 条件键匹配 Google ID 令牌中的 sub (SUBJECT) 字段。有关 Google aud 和 azp 字段的更多信息,请参考 Google Identity Platform OpenID Connect指南。
认证流程
本场景的认证流程如图 2 所示。
该认证流程包括以下步骤:
在 AWS 上,你可以通过配置配置文件中的 credentialprocess 设置源外部凭证。有关语法和操作系统要求,请参阅使用外部进程源凭证。在此帖中,我们在配置文件中创建了一个自定义配置文件 TeamAS3ReadOnlyAccess,如下所示:
ini[profile TeamAS3ReadOnlyAccess]credentialprocess = /opt/bin/credentialssh
若要使用不同设置,可以创建并引用其他配置文件。
指定 credentialprocess 将调用的程序或脚本。本文中,credentialprocess 调用脚本 /opt/bin/credentialssh,其代码如下。确保将 lt111122223333gt 替换为您自己的账户 ID。
bash
!/bin/bash
AUDIENCE=devawsaccountteamaROLEARN=arnawsiamlt111122223333gtrole/RoleForAccessFromGCPTeamA
jwttoken=(curl sH MetadataFlavor Google http//metadata/computeMetadata/v1/instance/serviceaccounts/default/identityaudience={AUDIENCE}ampformat=fullamplicenses=FALSE)
jwtsub=(jq R split() [1] @base64d fromjson ltltlt jwttoken jq r sub)
credentials=(aws sts assumerolewithwebidentity rolearn ROLEARN rolesessionname jwtsub webidentitytoken jwttoken jq Credentials jq Version=1)
echo credentials
脚本执行以下步骤:
1 [Google 生成一个新的唯一实例身份令牌](https//cloudgooglecom/compute/docs/instances/verifyinginstanceidentity#requestsignature),格式为 JSON Web Token (JWT)。 bash jwttoken=(curl sH MetadataFlavor Google http//metadata/computeMetadata/v1/instance/serviceaccounts/default/identityaudience={AUDIENCE}ampformat=fullamplicenses=FALSE) 此[令牌的有效负载](https//cloudgooglecom/compute/docs/instances/verifyinginstanceidentity#tokenformat)包括有关实例的多个详细信息和受众 URI,如下所示。 json { iss [TOKENISSUER] iat [ISSUEDTIME] exp [EXPIREDTIME] aud [AUDIENCE] sub [SUBJECT] azp [AUTHORIZEDPARTY] google { computeengine { projectid [PROJECTID] projectnumber [PROJECTNUMBER] zone [ZONE] instanceid [INSTANCEID] instancename [INSTANCENAME] instancecreationtimestamp [CREATIONTIMESTAMP] instanceconfidentiality [INSTANCECONFIDENTIALITY] licenseid [ [LICENSE1] [LICENSEN] ] } } } IAM 信任策略使用 JWT 令牌中的 aud (AUDIENCE)、azp (AUTHORIZEDPARTY) 和 sub (SUBJECT) 值,以确保在 AWS 中定义的 IAM 角色只能由预期的 GCP 服务账户假设。2 脚本调用 AssumeRoleWithWebIdentity API,传递前一步的身份令牌并指定要假设的 IAM 角色。脚本使用身份的主题声称作为会话名称,这有助于对这个 AssumeRoleWithWebIdentity API 调用进行审计或取证操作。[AWS 验证令牌的真实性](https//docsawsamazoncom/IAM/latest/UserGuide/idcredentialstemprequesthtml#apiassumerolewithwebidentity)后返回临时凭证。此外,您可以通过使用[获取实例身份令牌](https//cloudgooglecom/compute/docs/instances/verifyinginstanceidentity#requestsignature)中描述的流程验证令牌。 脚本将临时凭证作为 JSON 输出返回给 credentialprocess;我们使用 jq 解析输出为所需的 JSON 格式。bashjwtsub=(jq R split() [1] @base64d fromjson ltltlt jwttoken jq r sub)credentials=(aws sts assumerolewithwebidentity rolearn ROLEARN rolesessionname jwtsub webidentitytoken jwttoken jq Credentials jq Version=1)echo credentials以下是由 credentialprocess 脚本返回的临时凭证示例:json{ Version 1 AccessKeyId AKIAIOSFODNN7EXAMPLE SecretAccessKey wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY SessionToken FwoGZXIvYXdzEBUaDOSY1zJwXi29/reyLSASRJwSogY/Kx7NomtkCoSJyipWuu6sbDIwFEYtZqg9knuQQyJa9fP68/LCv4jH/efuo1WbMpjh4RZpbVCOQx/zggZTyk2H5sFvpVRUoCO4dc7eqftMhdKtcq67vAUljmcDkC9l0Fei5tJBvVpQ7jzsYeduX/5VM6uReJaSMeOXnIJnQZce6PI3GBiLfaX7Co4o216oS8yLNusTK1rrrwrY2g5e3Zuh1oXp/Q8niFy2FSLN62QHfniDWGO8rCEV9ZnZX0xc4ZN68wBc1N24wKgTxfCjamcCnBjJYHI2rEtJdkE6bRQc2WAUtccsQk5u83vWaeSpB9ycE/dzfXurqcjCP0urAp4k9aFZFsRIGfLAI1cOABX6CzF30qrcEBnEXAMPLESESSIONTOKEN== Expiration 20230831T044530Z}请注意,AWS SDK 在调用 credentialprocess 时会将返回的 AWS 凭证存储在内存中。AWS SDK 会跟踪凭证的过期时间,并通过凭证过程生成新的 AWS 会话凭证。相比之下,AWS CLI 不会缓存外部进程凭证;相反,AWS CLI 会在每次 CLI 请求时调用 credentialprocess,这会创建一个新的角色会话,并可能在运行命令时导致轻微延迟。
在 AWS CLI 中测试访问
配置好 credentialprocess 的配置文件后,通过运行以下命令验证你的设置。
bashaws sts getcalleridentity profile TeamAS3ReadOnlyAccess
输出将类似于以下内容。
json{ UserId AIDACKCEVSQ6C2EXAMPLE[Identity subject claim] Account 111122223333 Arn arnawsiam111122223333role/RoleForAccessFromGCPTeamA[Identity subject claim]}
Amazon CloudTrail 记录了 AssumeRoleWithWebIdentity API 调用,如图 3 所示。该日志捕获了身份令牌中的受众以及正在假设的 IAM 角色。它还捕获带有身份主题声称的会话名称,这有助于简化对这个 AssumeRoleWithWebIdentity API 调用的审计或取证操作。
在 AWS SDK 中测试访问
下一步是在 AWS SDK 中测试访问。以下 Python 程序示例展示了如何引用配置的用于凭证进程的自定义配置文件。
pythonimport boto3
session = boto3Session(profilename=TeamAS3ReadOnlyAccess)client = sessionclient(s3)
response = clientlistbuckets()for bucket in response[Buckets] print(bucket[Name])
在运行此程序前,请先运行pip install boto3。创建一个附加有 AmazonS3ReadOnlyAccess 策略的 IAM 角色。该程序打印你的 AWS 账户中现有 S3 存储桶的名称。例如,如果你的 AWS 账户中有两个 S3 存储桶,名为 DOCEXAMPLEBUCKET1 和 DOCEXAMPLEBUCKET2,则上述程序的输出如下所示:
bashDOCEXAMPLEBUCKET1DOCEXAMPLEBUCKET2
如果你没有现有的 S3 存储桶,请在运行上述程序之前创建一个 S3 存储桶。
listbucket API 调用也记录在 CloudTrail 中,捕获了调用应用程序的身份和来源,如图 4 所示。
 创建聊天助手,可以处理图像和文本。使用 Retrieval Augmented Generation (RAG) 策略,提高聊天机器人的响应准确性...