Firebase 部署 permission denied

firebase deploy 报权限错——IAM / 登录账号 / 项目对应。

你在本地或 CI 上跑 firebase deploy,报:

Error: HTTP Error: 403, The caller does not have permission
Error: Request to https://firebase.googleapis.com/... had HTTP Error: 403

或者更直白:

Error: Failed to authenticate, have you run firebase login?

排查的关键不在 firebase deploy 命令本身,而在背后这串身份链:你的本地 Google 账号 → 当前项目映射 → 那个账号在 GCP IAM 里的角色。任一环节断了,就 permission denied。

常见原因

按命中率从高到低:

1. 登的是个人 Google 账号,但项目在公司账号下

最高频。你 firebase login 时随手用了 personal@gmail.com,但要 deploy 的项目在 you@company.com 的 GCP organization 下,personal 账号根本没访问权限。

如何判断firebase login:list 看当前账号 email,对照 GCP console 里项目在哪个 org / account。

2. 账号在项目里没 Firebase Hosting Admin 角色

账号能”看见”项目但没 deploy 权限。常见于公司新人——SRE 加了 Viewer 但忘了加 Deploy。

如何判断GCP IAM → 选项目 → 找你的 email → 看 roles 列表。

3. .firebaserc 项目 ID 写错

{
  "projects": {
    "default": "my-project-prod"  // 真实 ID 是 my-project-prod-x9q
  }
}

CLI 试图 deploy 一个不存在或你没权限的项目。

如何判断firebase projects:list 看你能访问哪些项目,对照 .firebaserc 里的 ID。

4. CI 用了过期 / 错的 service account key

CI 用 GOOGLE_APPLICATION_CREDENTIALSFIREBASE_TOKEN 认证。Key 文件被删 / rotate / 权限被撤掉都会失败。

如何判断:CI 日志报 401/403,本地 deploy 同一个项目正常。

5. 需要 enable 的 API 没启用

Cloud Build API / Cloud Functions API / Cloud Run API 没开。Firebase CLI 首次会提示,但 CI 上没人点确认。

如何判断:错误含 “API has not been used” 或 “is disabled”。

6. Org policy 阻止个人账号 deploy

某些 GCP org 设了 “External members not allowed”,gmail.com 账号即使被 invite 也不能 deploy。

如何判断:错误含 “principalType is not allowed by the organization policy”。

最短修复路径

Step 1:自检身份链

# 1. 当前账号
firebase login:list

# 2. 当前能访问的项目
firebase projects:list

# 3. 当前 .firebaserc 的 default 项目
cat .firebaserc

# 4. 当前部署的目标项目
firebase use   # 显示 active project

四个输出对照:账号 → 项目列表里能看到 → .firebaserc 里的 ID 在列表里 → use 选的是正确的。

Step 2:登对账号

firebase logout
firebase login   # 浏览器选公司账号
firebase login:list  # 确认 email 是公司的

如果你需要在多账号间切换,可以用 --account flag:

firebase deploy --account=you@company.com --project=my-prod

Step 3:让 admin 加 IAM 角色

要 deploy Firebase Hosting + Functions 至少需要:

- Firebase Hosting Admin     (roles/firebasehosting.admin)
- Cloud Functions Admin      (roles/cloudfunctions.admin)
- Service Account User       (roles/iam.serviceAccountUser)
- Firebase Admin             (roles/firebase.admin)  # 简单粗暴

让 admin 在 IAM → 选项目 → Grant Access → 加你的 email + 上述角色。

Step 4:修 .firebaserc

firebase use --add  # 交互式选项目
# 或手动改:
{
  "projects": {
    "default": "my-project-prod-x9q",
    "staging": "my-project-staging-a3p"
  }
}
firebase use staging  # 切到 staging
firebase deploy --only hosting

Step 5:CI 用 service account

不要在 CI 用 firebase login 个人账号。生成 service account:

# 1. 在 GCP IAM → Service Accounts → Create
# 2. 给 SA 加上述 IAM 角色
# 3. 下载 JSON key

# CI(GitHub Actions 示例)
env:
  GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GCP_SA_KEY }}
steps:
  - run: |
      echo "${GOOGLE_APPLICATION_CREDENTIALS}" > /tmp/sa.json
      export GOOGLE_APPLICATION_CREDENTIALS=/tmp/sa.json
      firebase deploy --project my-project-prod --non-interactive

或用 FIREBASE_TOKEN(旧方式):

firebase login:ci  # 生成 token,存进 CI secret
firebase deploy --token "$FIREBASE_TOKEN"

Step 6:启用必要的 API

gcloud services enable \
  firebase.googleapis.com \
  cloudfunctions.googleapis.com \
  cloudbuild.googleapis.com \
  artifactregistry.googleapis.com \
  --project=my-project-prod

或一次去 API Library 全部 enable。

预防建议

  • 新成员入职就在 wiki 写明”deploy Firebase 需要这些 IAM 角色”
  • 个人项目用个人 Google 账号,工作项目用工作账号——别混用,浏览器 profile 隔离
  • .firebaserc 提交到 git,每个项目 ID 加注释(哪个环境)
  • CI 一律用 service account,永远不要用个人账号 token
  • service account key 每 90 天 rotate 一次,写进运维 calendar
  • firebase use staging --reload 而不是手动改 .firebaserc,命令式更可重现
  • deploy 前 dry-run:firebase deploy --only hosting --dry-run 看会改什么

相关阅读

标签: #后端 #排查 #排查 #Firebase