调用Cloud Tasks触发Firebase云函数时出现PERMISSION_DENIED权限错误
Cloud Tasks触发云函数时出现403权限拒绝问题
问题描述
我要实现一个Cloud Tasks任务逻辑:当Firestore中名为“temp”的条目创建后,60秒内调用云函数将其删除。目前队列创建、任务入队均正常,其他已部署的云函数也无权限问题,但队列中的任务触发时抛出以下错误:
PERMISSION_DENIED(7): HTTP status code 403
任务队列状态截图:
GCP IAM策略截图:
相关代码
创建任务的云函数
exports.createJob = functions.firestore .document("users/{userId}/jobs/{jobId}") .onCreate(async (snap) => { const job = snap.data(); /* eslint-disable */ const token = "drTHilFCSjBLAHBLAHBLAHy5zr84zqNTSjzmewMy7jyeLTAca7ag"; /* eslint-enable */ const name = job.name; const rate = job.ratePerHour; if (name == "temp") { functions.logger.log("name is temp"); const project = JSON.parse(process.env.FIREBASE_CONFIG!).projectId; const location = "us-central1"; const queue = "firestore-delTempJob"; const tasksClient = new CloudTasksClient(); const queuePath: string = tasksClient.queuePath(project, location, queue); const url = `https://${location}-${project}.cloudfunctions.net/firestoreTtlCallback`; const docPath = snap.ref.path; functions.logger.log("docpath is -- " + docPath); const deletePayload: ExpirationTaskPayload = {docPath}; const task = { httpRequest: { httpMethod: "POST", url, body: Buffer.from(JSON.stringify(deletePayload)).toString("base64"), headers: { "Content-Type": "application/json", }, }, scheduleTime: { seconds: 60, }, }; try { await tasksClient.createTask({parent: queuePath, task}); } catch (error) { functions.logger.error("delete request task creation failed:", error); } } });
任务回调云函数
interface ExpirationTaskPayload { docPath: string } export const firestoreTtlCallback = functions.https.onRequest(async (req, res) => { const payload = req.body as ExpirationTaskPayload; try { await admin.firestore().doc(payload.docPath).delete(); res.send(200); } catch (error) { functions.logger.error(error); res.status(500).send(error); } });
排查与解决建议
1. 修正任务执行时间配置
原代码中scheduleTime.seconds: 60是错误的,该字段需要传入Unix时间戳(从1970年1月1日开始的秒数),直接写60会导致任务立即过期。改为当前时间加60秒:
scheduleTime: { seconds: Math.floor(Date.now() / 1000) + 60, },
2. 配置Cloud Tasks调用云函数的身份验证
如果云函数开启了「需要身份验证」,需要给Cloud Tasks的服务账号添加调用权限,同时在任务中配置OIDC令牌:
- 在IAM控制台,找到项目默认的App Engine服务账号(
[项目ID]@appspot.gserviceaccount.com),添加Cloud Functions Invoker角色。 - 修改任务配置,添加
oidcToken字段:
const task = { httpRequest: { httpMethod: "POST", url, body: Buffer.from(JSON.stringify(deletePayload)).toString("base64"), headers: { "Content-Type": "application/json", }, oidcToken: { serviceAccountEmail: `${project}@appspot.gserviceaccount.com`, }, }, scheduleTime: { seconds: Math.floor(Date.now() / 1000) + 60, }, };
3. 检查云函数的访问权限设置
进入云函数控制台,找到firestoreTtlCallback函数:
- 若为测试环境,可临时开启「允许未经身份验证的调用」(在「触发器」标签页设置)。
- 生产环境建议保持「需要身份验证」,通过上述IAM角色授权的方式让Cloud Tasks调用。
4. 验证云函数URL正确性
确认url变量拼接的地址与云函数实际部署的地址完全一致,包括区域、项目ID和函数名称。
内容的提问来源于stack exchange,提问作者youcantgetridofmestackoverflow
相关产品推荐
相关产品推荐

