错误:匿名调用者没有 storage.objects.get 访问 Google Cloud Storage 对象的权限
Posted
技术标签:
【中文标题】错误:匿名调用者没有 storage.objects.get 访问 Google Cloud Storage 对象的权限【英文标题】:Error: Anonymous caller does not have storage.objects.get access to the Google Cloud Storage object 【发布时间】:2020-09-23 11:23:59 【问题描述】:我正在尝试在 firebase 中关注 Image resizer tutorial。我尝试用普通的 NodeJS 语法重写代码,并从其他来源借鉴了一些想法。下面附上我在 index.js
中的最终代码const functions = require('firebase-functions')
const Storage = require('@google-cloud/storage');
const projectId = "REDACTED INFO"
let gcs = new Storage (
projectId
);
const os = require('os');
const path = require('path');
const sharp = require('sharp');
const fs = require('fs-extra');
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
exports.onFileChange = functions.storage.object().onFinalize(async object =>
const bucket = gcs.bucket(object.bucket);
const filePath = object.name;
const fileName = filePath.split('/').pop();
const bucketDir = path.dirname(filePath);
const workingDir = path.join(os.tmpdir(), 'thumbs');
// const tmpFilePath = path.join(workingDir, 'source.png');
const tmpFilePath = path.join(workingDir, fileName);
//const tmpFilePath = path.join(os.tmpdir(), path.basename(filePath));
if (fileName.includes('thumb@') || !object.contentType.includes('image'))
console.log('exiting function');
return false;
// 1. Ensure thumbnail dir exists
await fs.ensureDir(workingDir);
// 2. Download Source File
await bucket.file(filePath).download(
destination: tmpFilePath
);
// 3. Resize the images and define an array of upload promises
const sizes = [64, 128, 256];
const uploadPromises = sizes.map(async size =>
const thumbName = `thumb@$size_$fileName`;
const thumbPath = path.join(workingDir, thumbName);
// Resize source image
await sharp(tmpFilePath)
.resize(size, size)
.toFile(thumbPath);
// Upload to GCS
return bucket.upload(thumbPath,
destination: path.join(bucketDir, thumbName)
);
);
// 4. Run the upload operations
await Promise.all(uploadPromises);
// 5. Cleanup remove the tmp/thumbs from the filesystem
return fs.remove(workingDir);
);
exports.onFileDelete = functions.storage.object().onDelete(event =>
console.log(event);
console.log('We deleted a file, exit...')
return;
);
但是,当我尝试上传图片时,我在 firebase 控制台日志中不断收到这些错误和警告。
Error: Anonymous caller does not have storage.objects.get access to the Google Cloud Storage object.
at new ApiError (/srv/node_modules/@google-cloud/common/build/src/util.js:59:15)
at Util.parseHttpRespMessage (/srv/node_modules/@google-cloud/common/build/src/util.js:161:41)
at Util.handleResp (/srv/node_modules/@google-cloud/common/build/src/util.js:135:76)
at Duplexify.requestStream.on.on.res (/srv/node_modules/@google-cloud/storage/build/src/file.js:823:31)
at emitOne (events.js:116:13)
at Duplexify.emit (events.js:211:7)
at emitOne (events.js:116:13)
at DestroyableTransform.emit (events.js:211:7)
at onResponse (/srv/node_modules/retry-request/index.js:200:19)
at PassThrough.<anonymous> (/srv/node_modules/retry-request/index.js:152:11)
和
MetadataLookupWarning: received unexpected error = URL is not defined code = UNKNOWN
有谁知道我错过了哪些步骤?如果需要更多信息,请通知我。谢谢。
【问题讨论】:
【参考方案1】:Try this:
import * as admin from "firebase-admin";
admin.initializeApp(functions.config().firebase);
const gcs = admin.storage();
【讨论】:
工作,让我也使用了@google-cloud/storage
【参考方案2】:
以下是我为初始化客户端 API/SDK 和管理 API/SDK 而编写的一些函数
我将在此处包括整个内容,但对于此问题而言,重要的部分是:
const serviceAccount = getJsonFromFile(`$rootDirname/service-account-file.json`)
const adminConfig = appConfig.firebase.options
adminConfig.credential = admin.credential.cert(serviceAccount)
adminApp = admin.initializeApp(adminConfig)
生成服务帐号 JSON 文件的说明为here
以下是将其置于上下文中的其余代码:
// noinspection ES6CheckImport
import connectStorageEmulator, getStorage from 'firebase/storage'
import initializeApp from 'firebase/app'
import admin from 'firebase-admin'
import appConfig from '../app-config.js'
import axiosAsyncAwait from './axios-utils.js'
import axios from 'axios'
import rootDirname from './root-dirname.js'
import getJsonFromFile from './get-json-from-file.js'
let app
let adminApp
let storage
const areEmulatorsRunning = async () =>
const emulatorFunctionsPort = appConfig.firebase.emulatorPorts.functions
// noinspection HttpUrlsUsage
const pingUrl = `http://$appConfig.domain:$emulatorFunctionsPort/$appConfig.firebase.options.projectId/us-central1/ping`
const ping = await axiosAsyncAwait(axios.get(pingUrl))
const emulatorsRunning = ping.success
return emulatorsRunning
export const getFirebaseApp = async (emulate = true) =>
if (app == null)
app = initializeApp(appConfig.firebase.options)
storage = getStorage(app)
const useEmulators = emulate && await areEmulatorsRunning()
if (useEmulators)
console.log('using emulators (client API)')
process.env.PUBSUB_PROJECT_ID = appConfig.firebase.options.projectId
process.env.PUBSUB_EMULATOR_HOST = `$appConfig.domain:$appConfig.firebase.emulatorPorts.pubsub`
connectStorageEmulator(storage, appConfig.domain, appConfig.firebase.emulatorPorts.storage)
else
console.log('using real (client API)')
process.env.GOOGLE_APPLICATION_CREDENTIALS = `$rootDirname/service-account-file.json` // pubsub authentication
return app, storage
export const getFirebaseAdminApp = async (emulate = true) =>
if (adminApp == null)
const serviceAccount = getJsonFromFile(`$rootDirname/service-account-file.json`)
const adminConfig = appConfig.firebase.options
adminConfig.credential = admin.credential.cert(serviceAccount)
adminApp = admin.initializeApp(adminConfig)
const useEmulators = emulate && await areEmulatorsRunning()
if (useEmulators)
console.log('using emulators (admin API)')
process.env.PUBSUB_PROJECT_ID = appConfig.firebase.options.projectId
process.env.PUBSUB_EMULATOR_HOST = `$appConfig.domain:$appConfig.firebase.emulatorPorts.pubsub`
process.env.FIREBASE_STORAGE_EMULATOR_HOST = `$appConfig.domain:$appConfig.firebase.emulatorPorts.storage`
else
console.log('using real (admin API)')
return adminApp, storage: null
【讨论】:
以上是关于错误:匿名调用者没有 storage.objects.get 访问 Google Cloud Storage 对象的权限的主要内容,如果未能解决你的问题,请参考以下文章
调用 GMAIL API 时出现间歇性错误 - “调用者没有权限”
错误: (gcloud.beta.functions.deploy) ... message=[调用者没有权限]