Firebase Cloud Functions Firestore 触发器产生:错误:7 PERMISSION_DENIED:缺少权限或权限不足

Posted

技术标签:

【中文标题】Firebase Cloud Functions Firestore 触发器产生:错误:7 PERMISSION_DENIED:缺少权限或权限不足【英文标题】:Firebase Cloud Functions Firestore Trigger produces: Error: 7 PERMISSION_DENIED: Missing or insufficient permissions 【发布时间】:2019-01-21 20:18:47 【问题描述】:

当我的一个文档已使用触发器更新时,我正在尝试使用 Firebase 云函数来更新我的 Firestore 数据库中的文档。触发器被调用并且工作正常,但是当我使用 firebase 管理实例获取我想要更新的另一个文档时,我收到以下错误。

Error: 7 PERMISSION_DENIED: Missing or insufficient permissions.
    at Object.exports.createStatusError (/user_code/node_modules/firebase-admin/node_modules/grpc/src/common.js:87:15)
    at ClientReadableStream._emitStatusIfDone (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client.js:235:26)
    at ClientReadableStream._receiveStatus (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client.js:213:8)
    at Object.onReceiveStatus (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:1256:15)
    at InterceptingListener._callNext (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:564:42)
    at InterceptingListener.onReceiveStatus (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:614:8)
    at /user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:1019:24

功能代码:

import * as functions from "firebase-functions";
import * as admin from "firebase-admin";

admin.initializeApp();
const settings =  timestampsInSnapshots: true ;
admin.firestore().settings(settings);

export const onDocUpdate = functions.firestore
  .document("documents/documentId")
  .onUpdate((snapshot, context) => 
    console.log("onDocUpdate called ", context.params.documentId);
    const document = snapshot.after.data();
    console.log("Document: ", document);
    if (document.screw) 
      console.log("Document screw exists. ", document.screw);
      const docRef = admin
        .firestore()
        .collection("screws")
        .doc(document.screw);
      return docRef
        .get()
        .then(doc => 
          if (doc.exists) 
            console.log("Screw for document exists.");
           else 
            console.error(
              "Screw for document not found! ",
              document.screw
            );
          
        )
        .catch(error => 
          // Here I get the permission error :(
          console.error(
            "Screw for document doc load error!! ",
            error
          );
        );
     else 
      console.error("Document is not bound to a screw! ", document.id);
    
    return null;
  );

package.json


  "name": "functions",
  "scripts": 
    "lint": "tslint --project tsconfig.json",
    "build": "tsc",
    "serve": "npm run build && firebase serve --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  ,
  "main": "lib/index.js",
  "dependencies": 
    "@google-cloud/firestore": "^0.16.0",
    "firebase-admin": "^6.0.0",
    "firebase-functions": "^2.0.4",
    "protobufjs": "^6.8.8"
  ,
  "devDependencies": 
    "tslint": "~5.8.0",
    "typescript": "~2.8.3"
  ,
  "private": true

我认为这与管理员实例的权限有关,但不知道错误可能是什么,我只是按照 youtube 上的文档和 firebase 视频中的步骤进行操作。

我的帐户仍处于免费计划中,并且我在日志中收到一条通知,我应该配置结算帐户,但如果正确理解文档,我应该能够访问 Google Cloud Platform 中的服务等读取同一数据库中的其他节点应该不是问题。

我已经在 *** 上发现了两个类似的问题,但没有找到解决方案。也许其他人同时也遇到了这个问题并且能够解决它?

PERMISSION_DENIED Firestore CloudFunction TypeScript 和 Firebase error writing to Firestore via a Function: "7 PERMISSION_DENIED: Missing or insufficient permissions"

更新 1: 新的 timestampsInSnapshots 设置存在另一个问题。这已得到修复,上面的代码已更新。主要问题权限被拒绝仍然存在。

更新 2:关于下面@RonRoyston 的回答。这是一个云函数,它使用 firebase-admin 包中的 Admin SDK 来读取节点。因此,它不应受 Firestore 安全规则的影响。在@DougStevenson 提到的一个链接问题上已经有一个comment。基于Admin SDK documentation,通过调用 admin.initializeApp() 来初始化它应该足够了,但不幸的是在我的情况下它不是。我没有读到在使用 Cloud Functions 时需要在服务帐户或安全规则中应用任何特殊 IAM 设置的地方,因此我没有触及任何这些设置。

干杯, 拉尔斯

【问题讨论】:

您的 Firestore 规则不允许读取或写入。查看您的 firestore.rules 文件。 @RonRoyston 感谢您的回复,但这是一个使用 firebase-admin 的云功能,它不应受 Firestore 安全规则的影响。请参阅我在问题中的完整答案(更新 2)。它还包含@DougStevenson 提到的链接。 在我使用 firebase serve --only 函数的情况下,我可以读取 firestore 集合。但是,在将 firebase 功能部署到云时,我会收到权限错误。这让我相信每个谈论 Firestore 规则的人都会让每个使用 admin.firestore() 的人走上死胡同。 【参考方案1】:

我的解决方案是设置serviceAccount,检查以下代码sn-p:

var admin = require("firebase-admin");

var serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp(
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://your-database-url.firebaseio.com"
);

您可以在以下位置生成 serviceAccountKey: Firebase 仪表板 -> 项目设置 -> 服务帐户标签

希望对你有帮助!

【讨论】:

在这里工作得很好。非常感谢!【参考方案2】:

一个对我有用的解决方案:

我在 Firebase 项目之间切换,我想在其中模拟 Cloud Function 并在 Firestore 中查看生产结果(我已经让 Cloud Function 在项目的生产 Firestore 中创建数据(例如“project-dev”) 通过云功能在 Firestore 中创建新文档时,即使我正在为新项目(“项目沙盒”)使用下载的 serviceAccount 凭据,权限被拒绝错误仍然发生
let serviceAccount = require('../credentials-sb.json');
admin.initializeApp(
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://<project>-sandbox.firebaseio.com"
);
我注意到我还没有为我的新项目运行firebase use 命令,也没有将它添加到.firebaserc。我正在“使用”一个项目,而不是凭证文件需要的项目(例如:Firebase CLI 设置为使用“project-dev”,我还没有为我的新“project-sandbox”运行firebase use 命令) 在我运行firebase use project-sandbox 之后,我运行npm run shell 并从模拟器执行我的功能,一切正常。模拟器在“project-sandbox”中的运行与“project-dev”一样。

我只能假设这是由于设置了一个 project-id 环境变量,该环境变量要么是在运行 admin.initializeApp() 时从环境中感知到的,要么我可以像这样手动设置(参见上面 @Seb 的评论):

let serviceAccount = require('../credentials-sb.json');
admin.initializeApp(
    project-id: '<project>-sandbox'
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://inkling-sandbox.firebaseio.com"
);

我希望这会有所帮助!如果有请告诉我。

【讨论】:

【参考方案3】:

我有同样的问题。和nvitius 一样,我通过更改权限解决了这个问题。

创建函数时,默认服务帐户显示为&lt;project-name&gt;@appspot.gserviceaccount.com

您可以通过点击Environment variables, networking, timeouts and more 链接来查看:

然后您可以验证或将帐户更改为`App Engine默认服务帐户':

之后,我去IAM验证了这个服务账号的权限。

但 IAM 没有列出/添加此服务帐户。

所以我添加它>>添加>>新成员。开始输入项目的 ID,服务帐户应该会在下拉列表中弹出。

然后我给了它以下权限:

项目 >> 编辑器(可能已经有) 数据存储 >> 云数据存储所有者 存储 >> 存储管理

希望这会有所帮助。

【讨论】:

这是正确答案,由于某种原因,默认服务帐户没有出现在我的 IAM 中,我已将其添加回来,但它不起作用:) 我花了很长时间才找到这个答案。 Compute Engine 帐户是默认帐户,尽管它似乎具有相同的角色,但它不适用于 Firestore。在创建集群时更改服务帐户就可以了。【参考方案4】:

我在使用 Cloud Functions 时遇到了同样的问题。删除/重新部署该功能并没有解决我的问题。事实证明,在配置我的项目时,没有添加默认服务帐户的 IAM 角色。我必须在 IAM 管理面板中为&lt;project-name&gt;@appspot.gserviceaccount.com 添加一个Editor 角色。

【讨论】:

我能够以类似的方式解决这个问题,但有一些不同。我对这个问题的回答中的详细信息。【参考方案5】:

我遇到了同样的错误,但在任何地方都没有找到解决方案,所以如果它可以帮助某人,我会在此处发布...

我们使用 2 个 firebase 项目(DEV、PROD)并在两者上部署相同的功能。当您在中指定错误的 projectId 时,也会出现 PERMISSION_DENIED :

admin.initializeApp(projectId: 'your_project_id');

【讨论】:

天哪,你的传奇。我花了很长时间才弄清楚。 这对我来说也是如此,尴尬...您可以为您的项目ID使用环境变量:firebase.google.com/docs/functions/config-env【参考方案6】:

我终于让它工作了。我没有更改任何 Firestore 安全规则,也没有更改任何 IAM 内容。我删除了在 us-central1 上运行的功能。再次创建了相同的 Cloud Function 项目,复制了我现有的代码,但这次我将它部署到 europe-west1,它开箱即用。

我假设在第一次部署到 us-central1 时可能会出现问题,之后即使我多次删除并重新部署该功能,我的项目仍会出现错误。不确定到底发生了什么,因为没有显示明显的错误。也许了解内部工作流程的 Firebase 团队中的某个人可以告诉我们是否会发生这样的事情,如果会,如何处理。

目前上述步骤解决了我的问题。

【讨论】:

天哪。得到同样的错误。刚刚删除并重新部署了功能,即使使用默认的 us-central1 loc,它也终于可以工作了

以上是关于Firebase Cloud Functions Firestore 触发器产生:错误:7 PERMISSION_DENIED:缺少权限或权限不足的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 中为 Firebase 使用 Cloud Functions

Cloud Functions for Firebase 超时

Firebase Cloud Functions https.onCall 完成状态码:204

Cloud Functions for Firebase onWrite 超时

Easy Firebase Cloud Functions 组织

在 Firebase Cloud Functions 中创建 PDF