GKE中Workload Identity配置下自定义ServiceAccount凭证获取异常
问题解决:GKE自定义ServiceAccount无法通过Application Default Credentials获取
问题背景
在使用Workload Identity配置的GKE集群中,自定义KSA已绑定到GCP服务账号,但代码调用GoogleCredentials.getApplicationDefault()时,返回的是GKE默认的ComputeEngineCredentials,而非自定义服务账号的ServiceAccountCredentials,导致Gmail API调用出现权限问题。临时通过加载SA密钥文件的方式可以正常工作,但希望使用Workload Identity的无密钥方式。
排查与解决方案
1. 确认Workload Identity绑定及权限配置
- 补全GCP服务账号的IAM角色:
你的Terraform模块中roles参数为空,导致GCP服务账号未获得Gmail API所需权限。需要为对应的GCP SA绑定roles/gmail.reader角色(匹配GMAIL_READONLYscope),修改Terraform配置:module "highpass-services-gke-workload-identity" { source = "terraform-google-modules/kubernetes-engine/google//modules/workload-identity" name = "${var.project_services}-ksa" namespace = "default" project_id = var.project roles = ["roles/gmail.reader"] # 添加Gmail只读权限角色 gcp_sa_display_name = "Develop Services GKE - SA/KSA" } - 验证KSA与GCP SA的绑定关系:
确保KSA邮箱(格式为default.my-develop-services-ksa@<GKE_PROJECT_ID>.iam.gserviceaccount.com)已被授予roles/iam.workloadIdentityUser角色,绑定到目标GCP SA。通过GCP CLI验证:
输出中需包含该KSA邮箱作为gcloud iam service-accounts get-iam-policy my-develop-services-ksa@<PROJECT_ID>.iam.gserviceaccount.comroles/iam.workloadIdentityUser的成员。
2. 验证Pod的凭证获取路径
进入运行中的Pod,检查元数据服务器返回的服务账号信息:
kubectl exec -it <POD_NAME> -- curl http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email -H "Metadata-Flavor: Google"
- 若返回自定义GCP SA的邮箱,说明Workload Identity已生效;若返回默认Compute Engine SA邮箱,需重新检查Terraform配置是否执行到位,或GKE集群是否已启用Workload Identity。
- 同时确认Pod未设置
GOOGLE_APPLICATION_CREDENTIALS环境变量,该变量会覆盖Workload Identity的凭证获取逻辑。
3. 配置域范围委派
因代码使用createDelegated(user)进行用户身份委派,需完成两项配置:
- 在GCP控制台的IAM -> 服务账号页面,找到目标SA并编辑,勾选"启用域范围委派"。
- 在Google Admin Console中,为该GCP SA配置API客户端访问权限,添加
https://www.googleapis.com/auth/gmail.readonly的scope,并授权给对应域内的用户。
4. 代码保持默认逻辑
确保代码未强制指定凭证来源,保持getApplicationDefault()的默认逻辑即可,配置正确后会自动获取自定义SA的凭证:
final List<String> SCOPES = List.of(GmailScopes.GMAIL_READONLY); GoogleCredentials delegatedCredentials = GoogleCredentials.getApplicationDefault() .createScoped(SCOPES) .createDelegated(user); return new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, new HttpCredentialsAdapter(delegatedCredentials)).setApplicationName("Gmail-App").build();
内容的提问来源于stack exchange,提问作者anz
相关产品推荐
相关产品推荐

