GCP CloudFunction无法扮演AWS角色,调用AssumeRoleWithWebIdentity时触发AccessDenied错误
GCP CloudFunction无法扮演AWS角色,调用AssumeRoleWithWebIdentity时触发AccessDenied错误
遇到这种权限问题,大概率是AWS角色信任策略配置不匹配或者GCP侧获取身份令牌的逻辑有问题,我给你梳理几个常见的排查方向,你可以逐一验证:
1. 检查AWS IAM角色的信任策略是否正确
这是最常见的问题根源。你需要确保AWS的目标角色明确允许GCP的服务账号通过OIDC方式扮演它:
- 首先,AWS侧需要先创建GCP的OIDC身份提供商,端点是
https://accounts.google.com,并验证对应的证书指纹(GCP的OIDC证书指纹可通过官方文档确认)。 - 然后,修改该AWS角色的信任策略,添加以下类似规则(替换占位符为你的实际信息):
这里的{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::你的AWS账号ID:oidc-provider/accounts.google.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "accounts.google.com:sub": "你的GCP Cloud Function使用的服务账号邮箱" } } } ] }sub字段必须严格匹配GCP服务账号的邮箱,不能有拼写错误。
2. 验证GCP侧获取Web Identity Token的逻辑
从你贴的代码片段来看,你已经在获取服务账号邮箱,但获取ID令牌的部分可能需要调整:
- 要调用AWS的
AssumeRoleWithWebIdentity,你需要获取受众为AWS的ID令牌,代码可以这样写:import google.auth.transport.requests import google.oauth2.id_token request = google.auth.transport.requests.Request() # 这里的audience指定为AWS的官方受众地址 id_token = google.oauth2.id_token.fetch_id_token(request, "https://aws.amazon.com") - 然后用这个令牌去调用STS的接口:
确保sts_client = boto3.client('sts') response = sts_client.assume_role_with_web_identity( RoleArn="arn:aws:iam::你的AWS账号ID:role/你的目标角色名", RoleSessionName="gcp-cloud-function-s3-session", WebIdentityToken=id_token )RoleArn完全正确,并且令牌的受众和AWS信任策略的条件匹配。
3. 确认Cloud Function使用的服务账号权限
- 如果你的Cloud Function使用的是自定义服务账号,要确保它有生成ID令牌的权限(默认的App Engine默认服务账号自带这个权限,但自定义账号需要绑定
roles/iam.serviceAccountTokenCreator角色)。 - 另外,检查服务账号是否能正常访问GCP的元数据服务器(默认是允许的,除非你配置了严格的VPC限制)。
4. 排查Terraform配置的遗漏点
- 检查Terraform中是否正确指定了Cloud Function的服务账号(通过
service_account_email参数),如果没指定,会默认使用App Engine的默认服务账号,你需要确保这个账号已经被添加到AWS角色的信任策略中。 - 确认AWS侧的OIDC提供商是否已经正确创建,Terraform中如果有配置AWS资源,要确保OIDC提供商的端点和指纹正确。
5. 考虑权限传播延迟
AWS和GCP的IAM策略变更都可能有几分钟的生效延迟,如果你刚修改完策略,建议等待5-10分钟后再测试。
备注:内容来源于stack exchange,提问作者Max Trosman
相关产品推荐
相关产品推荐

