Firebase Cloud Functions 部署失败 - 服务代理的 IAM 角色

问题描述 投票:0回答:1

我在部署 Firebase Cloud Functions 时遇到问题。该项目具有三个功能:

http
onSchedule
onObjectFinalized
http
onSchedule
函数部署成功,但我在部署
onObjectFinalized
函数时遇到错误。

我收到的完整错误消息是:

$ npm run deploy:prod

> [email protected] deploy:prod      
> npm run changeToProd && firebase deploy


> [email protected] 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:[email protected] --role=roles/iam.serviceAccountTokenCreator`
i  functions: `gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:[email protected] --role=roles/run.invoker`
i  functions: `gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:[email protected] --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 Storage = require("@google-cloud/storage")
// const {tmpdir} = require("os")
const path = require("path")
const sharp = require("sharp")
// const fs = require("fs-extra")

// const gsc = Storage()

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!");
  });

我的角色是

Cloud Functions Admin
Editor
部署脚本如下:

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 google-cloud-functions google-cloud-iam
1个回答
-3
投票

我遇到了完全相同的问题,我通过从 GCP 手动创建函数成功解决了这个问题。

此错误的一个可能来源可能是我有一个来自第一代云功能的“App Engine”服务帐户,具有

[email protected]
ID 成员,但我没有也无法为第二代功能创建默认成员 ID这是
[email protected]
,如云函数 docs 中所述。

因此,我将这些 IAM 角色赋予了默认的第一代服务帐户

[email protected]
我已经拥有:

  • 角色/run.invoker
  • 角色/firebasestorage.serviceAgent

在手动创建 coud 函数时,我输入了此服务帐户作为触发器:

[email protected]

此外,为了获取 GCP Cloud Function 中的日志,我不知道为什么,但我必须创建一个具有此角色的 Google Storage Service Agent

service-PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com

  • 角色/pubsub.publisher

执行此操作的命令与上面帖子中描述的部署失败后终端中指示的命令相同:

gcloud projects add-iam-policy-binding PROJECT_NAME --member=serviceAccount:service-PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com --role=roles/pubsub.editor

之后,部署和功能就如魔法般发挥作用。我希望它会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.