AWS Lambda借助GCP工作负载身份联盟发送Gmail遇前置检查失败问题
解决AWS Lambda通过GCP工作负载身份联盟模拟Workspace用户发邮件的
Precondition check failed错误 核心问题背景
你切换到工作负载身份联盟后,基础的跨云身份信任已配置成功(能访问共享Drive),但域范围委派的权限链路和用户模拟的凭证生成逻辑没有同步适配联盟模式,这是导致报错的核心原因。
步骤1:确认服务账号的域范围委派配置
- 登录Google Workspace Admin控制台,进入安全 > API控制 > 域范围委派
- 找到目标GCP服务账号对应的条目,确保已添加以下作用域:
https://www.googleapis.com/auth/gmail.send- 其他业务需要的作用域(如Drive相关)
- 确认该服务账号已被授权模拟
no-reply@my_org.com这个Workspace用户(此配置之前用密钥时应该已存在,需确认未被修改)
步骤2:给工作负载身份池身份添加服务账号模拟权限
- 登录GCP控制台,进入IAM & Admin > 工作负载身份联盟
- 找到你的身份池和对应AWS身份提供商
- 定位到映射AWS Lambda执行角色的GCP身份(格式类似:
principal://iam.googleapis.com/projects/[PROJECT_ID]/locations/global/workloadIdentityPools/[POOL_ID]/subject/[AWS_ROLE_ARN]) - 给该身份绑定roles/iam.serviceAccountTokenCreator角色,授权对象为你要模拟的GCP服务账号
- 这个权限是跨云身份生成服务账号访问令牌的前提,也是实现用户模拟的关键
步骤3:调整代码中的凭证生成逻辑
外部账号凭证直接调用with_subject()无法正确传递用户模拟参数,需要通过iamcredentials API显式生成带subject的访问令牌:
from google.oauth2 import service_account from googleapiclient.discovery import build import os from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials scope_list = [ "https://www.googleapis.com/auth/gmail.send", "https://www.googleapis.com/auth/drive.readonly" ] # 原工作负载身份联盟配置 config = { "type": "external_account", "audience": os.getenv('GOOGLE_WORKLOADIDENTITY_AUDIENCE'), "subject_token_type": "urn:ietf:params:aws:token-type:aws4_request", "token_url": "https://sts.googleapis.com/v1/token", "credential_source": { "environment_id": "aws1", "region_url": "http://169.254.169.254/latest/meta-data/placement/availability-zone", "url": "http://169.254.169.254/latest/meta-data/iam/security-credentials", "regional_cred_verification_url": "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15" }, "service_account_impersonation_url": f"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/{os.getenv('GOOGLE_WORKLOADIDENTITY_SERVICEACCOUNT')}:generateAccessToken", } # 获取基础跨云身份凭证 base_credentials = service_account.Credentials.from_info(config, scopes=scope_list) base_credentials.refresh(Request()) # 调用IAM凭证API生成带用户模拟的访问令牌 iam_creds_service = build('iamcredentials', 'v1', credentials=base_credentials) token_response = iam_creds_service.projects().serviceAccounts().generateAccessToken( name=f"projects/-/serviceAccounts/{os.getenv('GOOGLE_WORKLOADIDENTITY_SERVICEACCOUNT')}", body={ "scope": scope_list, "subject": "no-reply@my_org.com" } ).execute() # 构造最终可用的凭证 impersonated_credentials = Credentials( token=token_response['accessToken'], expiry=token_response['expireTime'], scopes=scope_list ) # 初始化Gmail服务并发送邮件 service = build("gmail", "v1", credentials=impersonated_credentials) service.users().messages().send( userId="no-reply@my_org.com", body=create_message ).execute()
关键验证项
- 确认AWS Lambda执行角色ARN已正确映射到GCP身份池的身份提供商
- 检查GCP服务账号的IAM绑定,确保跨云身份确实拥有
roles/iam.serviceAccountTokenCreator权限 - 确认Workspace Admin控制台中,域范围委派的作用域无遗漏,服务账号的客户端ID已正确注册
内容的提问来源于stack exchange,提问作者SHolzhauer
相关产品推荐
相关产品推荐

