Google 从云函数生成签名 url 时存储权限错误

Google storage permissions error while generating signed url from cloud function

我正在尝试使用 Firebase 云函数为存储在存储桶中的文件创建签名下载 URL。在我的本地机器上使用下面的代码片段,我能够访问云存储并生成这些 URL。

/* eslint-disable indent */
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const serviceAccount = require("./test-serviceAccount.json");

admin.initializeApp();
const storage = admin.storage();
const bucket = storage.bucket();

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
}, "firestore");

export const getFile = functions.https.onRequest(async (request, response) => {
  const [files] = await bucket.getFiles();
  const fileNames: string[] = [];
  files.forEach(async (file) => {
    console.log(file.name);
    const url = await file.getSignedUrl(
      {
        version: "v2",
        action: "read",
        expires: Date.now() + 1000 * 60 * 60 * 24,
      }
    );
    fileNames.push(String(url));
    if (files.indexOf(file) === files.length - 1) {
      response.send(JSON.stringify(fileNames));
    }
  });
});

然而,在部署到 Cloud Functions 之后,当我调用该函数时出现错误:

Error: could not handle the request

并且功能控制台中记录了以下消息:

Error: The caller does not have permission
    at Gaxios._request (/workspace/node_modules/gaxios/build/src/gaxios.js:129:23)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async Compute.requestAsync (/workspace/node_modules/google-auth-library/build/src/auth/oauth2client.js:368:18)
    at async GoogleAuth.signBlob (/workspace/node_modules/google-auth-library/build/src/auth/googleauth.js:655:21)
    at async sign (/workspace/node_modules/@google-cloud/storage/build/src/signer.js:97:35) 

我试过使用和不使用 .json 服务帐户密钥并确保服务帐户具有权限(它目前具有服务帐户令牌创建者、存储管理员和编辑者角色) .

我也看了this issue关于python存储SDK的问题,不过好像已经解决了。该问题中提到的解决方法(使用 .json 服务帐户令牌)也没有解决权限错误。

使用 Firebase 支持后 - 以下是对我有用的方法:

import { initializeApp, applicationDefault } from 'firebase-admin/app';

initializeApp({
 credential: applicationDefault(),
 projectId: '<FIREBASE_PROJECT_ID>',
});

在 init 调用中指定 projectId 似乎已经解决了问题。