跨/同项目GCP Pub/Sub推送Cloud Run遇403权限问题求助
问题分析与解决方案
核心原因
Pub/Sub向Cloud Run推送消息时,发起请求的身份是Pub/Sub专属服务账号(格式为service-<PROJECT_NUMBER>@gcp-sa-pubsub.iam.gserviceaccount.com),而非Cloud Run关联的服务账号。你之前错误地将权限授予了Cloud Run的服务账号,这是导致403的关键。
一、跨项目场景(项目A主题→项目B订阅+Cloud Run)配置步骤
- 项目B(Cloud Run所在项目):给项目A的Pub/Sub服务账号授予
roles/run.invoker权限,允许它调用Cloud Run服务。- 项目A的Pub/Sub服务账号格式:
service-<项目A的PROJECT_NUMBER>@gcp-sa-pubsub.iam.gserviceaccount.com
- 项目A的Pub/Sub服务账号格式:
- 项目A(主题所在项目):给项目B订阅使用的服务账号(若订阅指定了自定义服务账号)授予
roles/pubsub.subscriber权限,确保订阅能拉取主题消息。 - 订阅的推送配置无需额外指定服务账号(默认使用Pub/Sub自身服务账号)。
二、同项目场景(结合你的Terraform代码)修正
你的代码存在两个关键错误:
- 重复定义
google_project_iam_member.pubsub_editor资源,会导致Terraform覆盖或报错; - 权限授予对象错误,应该给Pub/Sub服务账号而非Cloud Run服务账号添加
run.invoker权限。
修正后的Terraform代码
resource "google_service_account" "cloud_run_service_account" { account_id = "testss" } # 按需保留:若Cloud Run需要主动操作Pub/Sub,给它加对应权限 resource "google_project_iam_member" "pubsub_editor_for_cr_sa" { project = "testproject" role = "roles/pubsub.editor" member = "serviceAccount:${google_service_account.cloud_run_service_account.email}" } resource "google_project_iam_member" "pubsub_subscriber_for_cr_sa" { project = "testproject" role = "roles/pubsub.subscriber" member = "serviceAccount:${google_service_account.cloud_run_service_account.email}" } # 获取当前项目编号,用于拼接Pub/Sub服务账号 data "google_project" "current" { project_id = "testproject" } # 关键:给Pub/Sub服务账号授予Cloud Run调用权限 resource "google_cloud_run_service_iam_member" "pubsub_invoker" { service = google_cloud_run_service.test_cr.name location = google_cloud_run_service.test_cr.location role = "roles/run.invoker" member = "serviceAccount:service-${data.google_project.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com" } resource "google_pubsub_topic" "test_topic" { name = "test_topic" } resource "google_pubsub_subscription" "test_sub" { name = "test_sub" topic = google_pubsub_topic.test_topic.id push_config { push_endpoint = google_cloud_run_service.test_cr.status[0].url } } resource "google_cloud_run_service" "test_cr" { name = "test_cr" location = var.location template { spec { service_account_name = google_service_account.cloud_run_service_account.email containers { image = "gcr.io..." } } } traffic { percent = 100 latest_revision = true } }
验证步骤
- 确认Pub/Sub服务账号格式正确:在GCP控制台IAM页面搜索
gcp-sa-pubsub即可找到对应账号; - 检查Cloud Run的IAM权限:确保Pub/Sub服务账号已拥有
roles/run.invoker权限; - 查看Cloud Run日志详情:403日志会显示请求身份,确认是否为Pub/Sub服务账号,以此验证权限配置是否生效。
内容的提问来源于stack exchange,提问作者jereczq22
相关产品推荐
相关产品推荐

