【问题标题】:Two Firestore projects: one works, one fails with "Error: 7 PERMISSION_DENIED: Missing or insufficient permissions."两个 Firestore 项目:一个有效,一个失败,并显示“错误:7 PERMISSION_DENIED:缺少权限或权限不足”。
【发布时间】:2020-09-24 01:48:11
【问题描述】:

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

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

注意:我不使用 firebase,只使用 firestore。

项目 1(产品):我部署到 GAE(Google App Engine)的代码能够使用生产凭据正常访问 Firestore。 GAE 和 Firestore 共享同一个项目。

项目 2(开发):我的本地代码能够使用开发凭据访问 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 项目表现不同

【问题讨论】:

    标签: node.js google-cloud-firestore


    【解决方案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。当它在本地运行时,它不能。

    【讨论】:

      【解决方案2】:

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

      根据 firebase 规则,您无法在 Cloud Console 上编辑它们,但您也可以使用 Firebase CLI 进行版本控制部署,documentation 上有一个操作方法。

      注意:作为 Cloud Console 用户,您无需支付额外费用即可访问 Firebase Console,因此如果您想修改规则,我不明白为什么这会对您的项目造成问题通过那里。此外,如果您选择使用 Firebase CLI,如之前共享的文档中所述:

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

      希望这会有所帮助。

      【讨论】:

      • 感谢@ralemos 的回答,但我认为您的回答不适用于这里。 1)我不使用 Firebase 和 2)我没有使用来自不同项目的密钥。当我指定一个密钥时,Firestore 会隐式地对适当的项目进行身份验证(我假设是从 client_email 派生的)
      • 您仍然可以将 Firebase CLI 用于 firebase 规则。我不明白你是如何创建密钥的,你能澄清一下吗?
      • 这是我创建密钥的分步操作:Google Cloud Console -> 服务帐户 -> 创建服务帐户 -> 分配项目所有者角色 -> 创建密钥 -> 下载密钥。我对每个键执行一次。需要明确的是,我在创建第二个密钥时切换项目。
      • 如果您确实切换项目,答案确实适用,因为密钥是根据每个服务帐户生成的,该帐户绑定到每个单独的项目。检查是否确实如此的一种方法是检查密钥文件中的private_key_idprivate_key 字段是否与另一个字段不同。
      猜你喜欢
      • 2019-01-06
      • 2020-09-06
      • 2019-01-21
      • 2020-09-25
      • 2020-09-01
      • 2019-05-05
      • 2018-04-25
      • 2020-05-20
      相关资源
      最近更新 更多