Firebase Cloud Functions部署失败:服务代理IAM角色权限问题
Firebase Cloud Functions部署问题:onObjectFinalized函数部署失败
问题概述
项目包含http、onSchedule、onObjectFinalized三个函数,其中http与onSchedule可成功部署,但onObjectFinalized函数部署失败。本人拥有Cloud Functions Admin和Editor角色,已查阅官方文档与技术论坛未找到有效方案。
完整错误信息
$ npm run deploy:prod > cloud-functions@1.0.0 deploy:prod > npm run changeToProd && firebase deploy > cloud-functions@1.0.0 changeToProd > firebase use prod Now using alias prod (zipshot-prod) === Deploying to 'zipshot-prod'... i deploying functions, hosting i functions: preparing codebase default for deployment i functions: ensuring required API cloudfunctions.googleapis.com is enabled... i functions: ensuring required API cloudbuild.googleapis.com is enabled... i artifactregistry: ensuring required API artifactregistry.googleapis.com is enabled... + functions: required API cloudfunctions.googleapis.com is enabled + artifactregistry: required API artifactregistry.googleapis.com is enabled + functions: required API cloudbuild.googleapis.com is enabled i functions: Loading and analyzing source code for codebase default to determine what to deploy Serving at port 8581 {"severity":"WARNING","message":"params.PROJECT_ID.value() invoked during function deployment, instead of during runtime."} {"severity":"WARNING","message":"This is usually a mistake. In configs, use Params directly without calling .value()."} {"severity":"WARNING","message":"example: { memory: memoryParam } not { memory: memoryParam.value() }"} i functions: preparing functions directory for uploading... i functions: packaged F:\\project\\chrome_ext\\zipshot\\cloud-functions\\functions (109.47 KB) for uploading i functions: ensuring required API cloudscheduler.googleapis.com is enabled... + functions: required API cloudscheduler.googleapis.com is enabled i functions: ensuring required API run.googleapis.com is enabled... i functions: ensuring required API eventarc.googleapis.com is enabled... i functions: ensuring required API pubsub.googleapis.com is enabled... i functions: ensuring required API storage.googleapis.com is enabled... + functions: required API run.googleapis.com is enabled + functions: required API storage.googleapis.com is enabled + functions: required API pubsub.googleapis.com is enabled + functions: required API eventarc.googleapis.com is enabled i functions: generating the service identity for pubsub.googleapis.com... i functions: generating the service identity for eventarc.googleapis.com... i functions: Failed to verify the project has the correct IAM bindings for a successful deployment. i functions: You can either re-run `firebase deploy` as a project owner or manually run the following set of `gcloud` commands: i functions: `gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:service-1090842465135@gs-project-accounts.iam.gserviceaccount.com --role=roles/pubsub.publisher` i functions: `gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:service-1090842465135@gcp-sa-pubsub.iam.gserviceaccount.com --role=roles/iam.serviceAccountTokenCreator` i functions: `gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:1090842465135-compute@developer.gserviceaccount.com --role=roles/run.invoker` i functions: `gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:1090842465135-compute@developer.gserviceaccount.com --role=roles/eventarc.eventReceiver` Error: We failed to modify the IAM policy for the project. The functions deployment requires specific roles to be granted to service agents, otherwise the deployment will fail.
index.js核心代码片段
const {onRequest} = require("firebase-functions/v2/https"); const {onObjectFinalized} = require("firebase-functions/v2/storage"); const {getStorage} = require("firebase-admin/storage"); const {onSchedule} = require("firebase-functions/v2/scheduler"); const {initializeApp} = require("firebase-admin/app"); const logger = require("firebase-functions/logger"); const path = require("path") const sharp = require("sharp") initializeApp(); const app = require("./app.js"); const {projectID} = require("firebase-functions/params") exports.apiv2 = onRequest({minInstances: 2}, app) // currently running after every 10 mins exports.callUploadAfterEveryXmin = onSchedule("*/10 * * * *", async() => { ... }) /** * When an image is uploaded in the Storage bucket, * generate a preview image automatically using sharp. * This code creates a 600x300 preview image for the * image saved in a temporary directory, then uploads * it back to Cloud Storage. */ exports.generatePreviewImg = onObjectFinalized(async (event) => { const fileBucket = event.data.bucket; // Storage bucket containing the file. const filePath = event.data.name; // File path in the bucket. const contentType = event.data.contentType; // File content type. // Exit if this is triggered on a file that is not an image. if (!contentType.startsWith("image/")) { return logger.log("This is not an image."); } // Exit if the image is already a preview image. const fileName = path.basename(filePath); if (fileName.startsWith("preview_")) { return logger.log("Already a Preview Image."); } // Download file into memory from bucket. const bucket = getStorage().bucket(fileBucket); const downloadResponse = await bucket.file(filePath).download(); const imageBuffer = downloadResponse[0]; logger.log("Image downloaded!"); // Generate a preview image using sharp. const previewBuffer = await sharp(imageBuffer).resize({ width: 600, height: 300, withoutEnlargement: true, }).toBuffer(); logger.log("preview image created"); // Prefix 'preview_' to file name. const thumbFileName = `preview_${fileName}`; const thumbFilePath = path.join(path.dirname(filePath), thumbFileName); // Upload the preview image. const metadata = {contentType: contentType}; await bucket.file(thumbFilePath).save(previewBuffer, { metadata: metadata, }); return logger.log("Preview image uploaded!"); });
部署配置信息
package.json
"scripts": { "deploy:prod": "npm run changeToProd && firebase deploy", "changeToProd": "firebase use prod" }
.firebaserc
{ "projects": { "default": "dummy-dev", "dev": "dummy-dev", "prod": "dummy-prod" } }
解决方案
核心原因
Firebase CLI尝试自动配置触发onObjectFinalized所需的IAM权限时失败,因为Cloud Functions Admin和Editor角色没有项目级IAM策略修改权限,无法为相关服务账号添加必要角色。
解决步骤
手动配置IAM权限:执行错误提示中的4条gcloud命令,给对应服务账号添加角色:
gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:service-1090842465135@gs-project-accounts.iam.gserviceaccount.com --role=roles/pubsub.publisher gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:service-1090842465135@gcp-sa-pubsub.iam.gserviceaccount.com --role=roles/iam.serviceAccountTokenCreator gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:1090842465135-compute@developer.gserviceaccount.com --role=roles/run.invoker gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:1090842465135-compute@developer.gserviceaccount.com --role=roles/eventarc.eventReceiver执行前确保已通过
gcloud auth login登录有权限修改项目IAM的账号。使用项目所有者账号重新部署:切换到项目所有者权限的账号,重新运行
npm run deploy:prod,Firebase CLI会自动完成IAM配置。
额外修复:部署警告处理
部署时出现的params.PROJECT_ID.value()警告,需检查代码中是否在部署阶段调用了projectID.value(),正确做法是直接使用projectID参数(如函数配置项),不要在部署时调用.value()方法,避免该警告。
内容的提问来源于stack exchange,提问作者ATOM
相关产品推荐
相关产品推荐

