两个Firestore项目:一个有效,一个失败,并显示“错误:7 PERMISSION_DENIED:缺少权限或权限不足”。

时间:2020-06-04 22:50:27

标签: node.js google-cloud-firestore

TLDR:一个凭证有效,而另一个凭证无效吗?

我有2个针对Cloud Firestore的Google Cloud项目。一种用于生产,一种用于开发。

注意:我不使用Firebase,仅使用Firestore。

项目1(产品)::使用生产凭据,部署到GAE(Google App Engine)的代码可以很好地访问Firestore。 GAE和Firestore共享同一个项目。

项目2(dev):我的本地代码可以使用开发凭据(我已指定为开发沙箱的项目)访问Firestore

现在是问题所在:

错误:7 PERMISSION_DENIED:缺少权限或权限不足。

那是我运行以下代码时遇到的错误。

// script.js
//
// In my local environment (my laptop), I want to run a script that queries my
// "Production Firestore" and do some analysis.


const Firestore = require('@google-cloud/firestore');
const prodProjectKey = require('./keys/prod.json')

const db = new Firestore({
  credentials: {
    client_email: prodProjectKey.client_email,
    private_key: prodProjectKey.private_key,
  },
})

;(async () => {
  const doc = await db.collection('users').doc('123').get()
})()

现在,对我来说并不奇怪,如果我更改凭据以使用开发凭据,一切正常。

// To be super clear, the following works
// (the only difference is using dev.json instead of prod.json)

const devProjectKey = require('./keys/dev.json')
const db = new Firestore({
  credentials: {
    client_email: devProjectKey.client_email,
    private_key: devProjectKey.private_key,
  },
})
;(async () => {
  const doc = await db.collection('users').doc('123').get()
})()

据我所知,这些键之间的唯一区别是项目ID。我遵循相同的步骤来创建它们: Google Cloud Console->服务帐户->创建服务帐户->分配项目所有者角色->创建密钥->下载密钥

关于SO的其他问题,我也指向“数据库规则”,但是

  1. 这些答案似乎仅适用于Firebase用户(我仅适用于Firestore用户)
  2. 似乎没有解释为什么我的prod和dev项目的行为方式不同

2 个答案:

答案 0 :(得分:1)

继续尝试,我终于找到了解决方法。

正确:

const db = new Firestore({
  projectId: 'myproject',
  keyFilename: '/absolute/path/to/prodProjectKey.json',
})

错误:

const db = new Firestore({
  credentials: {
    client_email: prodProjectKey.client_email,
    private_key: prodProjectKey.private_key,
  },
})

我应该注意,遇到任何相同问题的人都可以在Google Cloud上运行“错误”代码。只有在本地运行时,才会弹出PERMISSION_DENIED错误。

回想一下,当您查看prodProjectKey.json的内容时,我认为原因很明显:

{
  "type": "service_account",
  "project_id": "xxxx",
  "private_key_id": "xxxx",
  "private_key": "-----BEGIN PRIVATE KEY-----xxxxxx\n-----END PRIVATE KEY-----\n",
  "client_email": "xxxx@xxx.iam.gserviceaccount.com",
  "client_id": "xxxx",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "xxx"
}

当您在Google Cloud上运行时提供client_email和private_key时,Google Cloud可以从服务器环境中推断其他重要参数,例如project_id。当它在本地运行时,不能。

答案 1 :(得分:0)

您所描述的行为实际上是预期的和正确的。您无法使用其他项目中的密钥,因为该密钥是根据与之相关的每个服务帐户和projectId生成的,您可以查看此documentation上的示例以获取更多详细信息。

根据firebase规则,您无法在Cloud Console上对其进行编辑,但是您也可以使用Firebase CLI通过版本控制进行部署,在此documentation上有一个方法。

注意:作为Cloud Console用户,您可以访问Firebase Console而无需支付额外费用,因此,我不明白为什么要编辑规则对您的项目造成问题通过那里。另外,如果您选择使用Firebase CLI,如先前共享的文档所述:

使用Firebase CLI部署安全规则时,在项目目录中定义的规则将覆盖Firebase控制台中的所有现有规则。因此,如果您选择使用Firebase控制台定义或编辑安全规则,请确保还更新在项目目录中定义的规则。

希望这会有所帮助。

相关问题