Node.js 使用工作负载标识从GKE向Google Cloud Firestore进行身份验证

Node.js 使用工作负载标识从GKE向Google Cloud Firestore进行身份验证,node.js,kubernetes,google-cloud-firestore,google-kubernetes-engine,google-iam,Node.js,Kubernetes,Google Cloud Firestore,Google Kubernetes Engine,Google Iam,我正在尝试编写一个简单的后端来访问我的Google Cloud Firestore,它位于Google Kubernetes引擎中。在我的本地计算机上,我使用以下代码对Firestore进行身份验证,详细内容见谷歌文档 if(process.env.NODE_env!=“生产”){ const result=require('dotenv').config() //这里有额外的错误处理 } 这将提取GOOGLE\u APPLICATION\u CREDENTIALS环境变量,并用我的GOOGL

我正在尝试编写一个简单的后端来访问我的Google Cloud Firestore,它位于Google Kubernetes引擎中。在我的本地计算机上,我使用以下代码对Firestore进行身份验证,详细内容见谷歌文档

if(process.env.NODE_env!=“生产”){
const result=require('dotenv').config()
//这里有额外的错误处理
}
这将提取GOOGLE\u APPLICATION\u CREDENTIALS环境变量,并用我的
GOOGLE APPLICATION credentals.json
填充它,我是通过使用
的“云数据存储用户”
角色创建服务帐户而获得的

因此,在本地,我的代码运行良好。我可以到达我的火炉店,做我需要做的一切。然而,一旦我部署到GKE,问题就出现了

我按照此步骤为集群设置了工作负载标识,我创建了一个部署,并通过运行以下命令验证了所有POD都使用了正确的IAM服务帐户:

kubectl exec -it POD_NAME -c CONTAINER_NAME -n NAMESPACE sh
> gcloud auth list
我从文档中得到的印象是,只要上述情况属实,我的服务将进行身份验证。我真的不知道为什么,但我的Firestore()实例的行为似乎没有访问Firestore所需的凭据

如果有帮助,下面是我对实例的声明和实现:

const firestore=new firestore()
const server=新服务器({
schema:schema,
数据源:()=>{
返回{
userDatasource:新的userDatasource(firestore)
}
}
})
更新:

在一次绝望中,我决定拆除一切,重建它。在一步一步地完成所有事情之后,我似乎遇到了一个bug,或者(更有可能)我第一次做了一些轻微的错误。我现在可以连接到我的后端服务然而,我现在得到一个不同的错误。在发送任何请求时(我使用的是GraphQL,但本质上是任何REST调用),我都会得到404

检查日志会产生以下结果:

“从插件获取元数据失败,错误为:无法刷新访问令牌:尝试检索计算引擎内置服务帐户的accesstoken时返回未找到错误。”。这可能是因为计算引擎实例没有指定任何权限范围:无法刷新访问令牌:响应状态代码不成功。请求失败,状态代码为404'


对这个问题的粗略搜索似乎不会返回任何与我试图实现的目标相关的内容,因此我回到了起点。

将结束这个问题

以防万一有人无意中发现了,这是给我做的

1.)我重新按照上面Google文档链接中的步骤操作,这解决了我的POD无法启动的问题

2.)至于我的更新,我重新创建了集群,并授予它云数据源权限。我假设权限与工作负载标识所需的功能是分开的。我错了


我希望这对某人有所帮助。

我认为你最初的假设是正确的!如果仍然必须指定作用域,则工作负载标识无法正常工作。在您链接的Workload文章中,没有使用作用域

我一直在努力解决同一个问题,并确定了三种方法来获得pod中的身份验证凭据


1。工作负载标识(基本上是上面的工作负载标识文章,添加了一些部署详细信息)

此方法是首选方法,因为它允许仅向集群中的每个pod部署授予其所需的权限

创建集群(注意:未定义作用域或服务帐户)

然后创建k8sServiceAccount、分配角色和注释

gcloud container clusters get-credentials {cluster-name}

kubectl create serviceaccount --namespace default {k8sServiceAccount}

gcloud iam service-accounts add-iam-policy-binding \
  --member serviceAccount:{projectID}.svc.id.goog[default/{k8sServiceAccount}] \
  --role roles/iam.workloadIdentityUser \
  {googleServiceAccount}

kubectl annotate serviceaccount \
  --namespace default \
  {k8sServiceAccount} \
  iam.gke.io/gcp-service-account={googleServiceAccount}
然后我创建部署,并设置k8sServiceAccount。 (设置服务帐户是我缺少的部分)

然后以8080为目标曝光

kubectl expose deployment {deployment-name}  --name={service-name} --type=LoadBalancer --port 80 --target-port 8080
googleServiceAccount需要分配适当的IAM角色(见下文)


2。群集服务帐户

此方法不是首选方法,因为集群中的所有VM和POD都将具有基于定义的服务帐户的权限

使用分配的服务帐户创建群集

gcloud beta container clusters create [cluster-name] \
 --release-channel regular \
 --service-account {googleServiceAccount}
googleServiceAccount需要分配适当的IAM角色(见下文)

然后按上述方式部署和公开,但不设置k8sServiceAccount


3。范围

此方法不是首选方法,因为集群中的所有VM和POD都具有基于定义的作用域的权限

创建具有指定范围的集群(firestore只需要“云平台”,实时数据库也需要“userinfo.email”)

然后按上述方式部署和公开,但不设置k8sServiceAccount


前两种方法需要一个分配了相应IAM角色的Google服务帐户。以下是我分配给一些Firebase产品的角色:

  • FireStore:云数据存储用户(数据存储)
  • 实时数据库:Firebase实时数据库管理员(Firebase产品)
  • 存储:存储对象管理员(云存储)

感谢您的深入回复,它比谷歌文档更有帮助。我还没有尝试过这一点,因为这个项目将我带向了一个不同的方向,但当我重新考虑它时,如果它起作用的话,我会让它成为公认的答案:)。谢谢谢谢你,这很有帮助。我在workload identity中有一个场景,其中两个KSA绑定到两个不同的google SA,如何使我的部署使用这两个KSA的如下命令一次只设置一个服务帐户。kubectl set-serviceaccount部署{deployment name}{k8sServiceAccount}非常感谢您提供的任何帮助您是否正在创建一个需要两组
kubectl expose deployment {deployment-name}  --name={service-name} --type=LoadBalancer --port 80 --target-port 8080
gcloud beta container clusters create [cluster-name] \
 --release-channel regular \
 --service-account {googleServiceAccount}
gcloud beta container clusters create $2 \
  --release-channel regular \
  --scopes https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email