NodeJS 无法从GCP Scheduler调用Google Cloud Function

shyt4zoc  于 2023-06-05  发布在  Node.js
关注(0)|答案(5)|浏览(180)

我一直在尝试从GCP调度程序调用GCP函数(--runtime nodejs8 --trigger-http),这两个函数都位于同一个项目中。我只能让它工作,如果我通过将allUsers成员添加到函数权限中来授予未经身份验证的访问权限,并向其应用Cloud Functions-Invoker角色。但是,当我只使用调度程序的服务帐户作为Cloud Functions-Invoker时,我会得到一个PERMISSION DENIED错误。
我创建了一个hello world示例,以详细展示我的设置是什么样子的。
1.我创建了一个服务帐户:
gcloud iam service-accounts create scheduler --display-name="Task Schedule Runner"
1.设置角色:

svc_policy.json:
{
    "bindings": [
      {
        "members": [
          "serviceAccount:scheduler@mwsdata-1544225920485.iam.gserviceaccount.com"
        ],
        "role": "roles/cloudscheduler.serviceAgent"
      }    
    ]
  }

gcloud iam service-accounts set-iam-policy scheduler@mwsdata-1544225920485.iam.gserviceaccount.com svc_policy.json  -q

1.部署云函数:
gcloud functions deploy helloworld --runtime nodejs8 --trigger-http --entry-point=helloWorld
1.将服务帐户作为成员添加到函数中:
gcloud functions add-iam-policy-binding helloworld --member serviceAccount:scheduler@mwsdata-1544225920485.iam.gserviceaccount.com --role roles/cloudfunctions.invoker
1.创建计划程序作业:
gcloud beta scheduler jobs create http test-job --schedule "5 * * * *" --http-method=GET --uri=https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld --oidc-service-account-email=scheduler@mwsdata-1544225920485.iam.gserviceaccount.com --oidc-token-audience=https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld
日志:权限被拒绝

{
 httpRequest: {
 }
 insertId: "1ny5xuxf69w0ck"  
 jsonPayload: {
  @type: "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished"   
  jobName: "projects/mwsdata-1544225920485/locations/europe-west1/jobs/test-job"   
  status: "PERMISSION_DENIED"   
  targetType: "HTTP"   
  url: "https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld"   
 }
 logName: "projects/mwsdata-1544225920485/logs/cloudscheduler.googleapis.com%2Fexecutions"  
 receiveTimestamp: "2020-02-04T22:05:05.248707989Z"  
 resource: {
  labels: {
   job_id: "test-job"    
   location: "europe-west1"    
   project_id: "mwsdata-1544225920485"    
  }
  type: "cloud_scheduler_job"   
 }
 severity: "ERROR"  
 timestamp: "2020-02-04T22:05:05.248707989Z"  
}

更新

以下是相应的设置。
计划程序服务帐户

gcloud iam service-accounts get-iam-policy scheduler@mwsdata-1544225920485.iam.gserviceaccount.com

bindings:
- members:
  - serviceAccount:scheduler@mwsdata-1544225920485.iam.gserviceaccount.com
  role: roles/cloudscheduler.serviceAgent
etag: BwWdxuiGNv4=
version: 1

职能部门的IAM政策:

gcloud functions get-iam-policy helloworld    
bindings:
- members:
  - serviceAccount:scheduler@mwsdata-1544225920485.iam.gserviceaccount.com
  role: roles/cloudfunctions.invoker
etag: BwWdxyDGOAY=
version: 1

功能描述

gcloud functions describe helloworld
availableMemoryMb: 256
entryPoint: helloWorld
httpsTrigger:
  url: https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld
ingressSettings: ALLOW_ALL
labels:
  deployment-tool: cli-gcloud
name: projects/mwsdata-1544225920485/locations/us-central1/functions/helloworld
runtime: nodejs8
serviceAccountEmail: mwsdata-1544225920485@appspot.gserviceaccount.com
sourceUploadUrl: https://storage.googleapis.com/gcf-upload-us-central1-671641e6-3f1b-41a1-9ac1-558224a1638a/b4a0e407-69b9-4f3d-a00d-7543ac33e013.zip?GoogleAccessId=service-617967399269@gcf-admin-robot.iam.gserviceaccount.com&Expires=1580854835&Signature=S605ODVtOpnU4LIoRT2MnU4OQN3PqhpR0u2CjgcpRcZZUXstQ5kC%2F1rT6Lv2SusvUpBrCcU34Og2hK1QZ3dOPluzhq9cXEvg5MX1MMDyC5Y%2F7KGTibnV4ztFwrVMlZNTj5N%2FzTQn8a65T%2FwPBNUJWK0KrIUue3GemOQZ4l4fCf9v4a9h6MMjetLPCTLQ1BkyFUHrVnO312YDjSC3Ck7Le8OiXb7a%2BwXjTDtbawR20NZWfgCCVvL6iM9mDZSaVAYDzZ6l07eXHXPZfrEGgkn7vXN2ovMF%2BNGvwHvTx7pmur1yQaLM4vRRprjsnErU%2F3p4JO3tlbbFEf%2B69Wd9dyIKVA%3D%3D
status: ACTIVE
timeout: 60s
updateTime: '2020-02-04T21:51:15Z'
versionId: '1'

计划程序作业描述

gcloud scheduler jobs describe test-job
attemptDeadline: 180s
httpTarget:
  headers:
    User-Agent: Google-Cloud-Scheduler
  httpMethod: GET
  oidcToken:
    audience: https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld
    serviceAccountEmail: scheduler@mwsdata-1544225920485.iam.gserviceaccount.com
  uri: https://us-central1-mwsdata-1544225920485.cloudfunctions.net/helloworld
lastAttemptTime: '2020-02-05T09:05:00.054111Z'
name: projects/mwsdata-1544225920485/locations/europe-west1/jobs/test-job
retryConfig:
  maxBackoffDuration: 3600s
  maxDoublings: 16
  maxRetryDuration: 0s
  minBackoffDuration: 5s
schedule: 5 * * * *
scheduleTime: '2020-02-05T10:05:00.085854Z'
state: ENABLED
status:
  code: 7
timeZone: Etc/UTC
userUpdateTime: '2020-02-04T22:02:31Z'
rlcwz9us

rlcwz9us1#

以下是我遵循的步骤,以使Cloud Scheduler触发一个HTTP触发的Cloud Function,该函数不允许未经身份验证的调用:
1.创建一个服务帐户,其格式为[SA-NAME]@[PROJECT-ID]. iam.gserviceaccount.com。
1.将服务帐户[SA-NAME]@[PROJECT-ID]. iam.gserviceaccount.com添加为a project member,并将以下角色添加到服务帐户:云函数调用器和Cloud Scheduler Admin

  1. Deploy an HTTP triggered Cloud Function,不允许公共(未经身份验证)访问(如果您使用的是UI,只需取消选中“允许未经身份验证的调用”复选框),并且使用了最近创建的服务帐户[SA-NAME]@[PROJECT-ID]。iam.gserviceaccount.com,位于服务帐户字段(单击“更多”并查找“服务帐户”字段,默认情况下,它应该被设置为App Engine默认服务帐户),并注意云功能的URL。
    1.通过从Cloud Shell发出以下命令,创建具有身份验证的Cloud Scheduler作业:gcloud scheduler jobs create http [JOB-NAME] --schedule="* * * * *" --uri=[CLOUD-FUNCTIONS-URL] --oidc-service-account-email=[SA-NAME]@[PROJECT-ID].iam.gserviceaccount.com
    在您的特定情况下,您将为Cloud Functions保留默认的App Engine服务帐户。将其更改为您在前面步骤中指定的服务帐户。
afdcj2ne

afdcj2ne2#

@Marko我经历了同样的问题,似乎重新启用(禁用/启用)调度程序API做了修复。这就是为什么创建一个新项目是有意义的,因为这样做可能会获得一个调度程序服务帐户。因此,如果你的项目没有从google创建的调度服务帐户,做这个技巧会给予你一个。虽然您不需要将此特定服务帐户分配给任何任务,但它必须可用。你可以在这里看到我的工作:如何通过身份验证从Cloud Scheduler调用Cloud Function

ncecgwcz

ncecgwcz3#

我也遇到过类似的问题。
在我们的案例中,我们在很久以前就启用了Cloud Scheduler。
根据文档,如果您在*2019年3月19日 * 之前启用了Cloud Scheduler API,则需要手动将Cloud Scheduler Service Agent角色添加到您的Cloud Scheduler服务帐户中。
因此,我们必须创建一个新的服务帐户,如下所示:
希望这能帮助到其他人。

bq3bfh9z

bq3bfh9z4#

本教程帮助我调用了一个程序员函数,但在创建服务帐户后创建程序时出现了问题,最后消除了程序员并重新执行。
Google Cloud Scheduler - Calling Cloud Function

8xiog9wr

8xiog9wr5#

问题可能是关于第一代云函数的,但也许我的努力会帮助那些正在尝试第二代CF的人。
经过相当的斗争与此,我设法设置适当的权限,以第二代云功能。
有几件事我从一开始就没有意识到:

  • 在创建第二代功能时,GCP也在创建连接到该功能的Cloud Run服务
  • 所有的http触发器请求都来自Cloud Run服务
  • CloudRunSA是CloudFunction的实际调用者(至少在我测试时似乎是这样)
  • Cloud Run服务的名称基于Cloud Function名称生成,并且在大多数情况下是相同的(当CF名称中使用下划线时,将用破折号my_cf_function => my-cf-function替换)

所以我做了什么来使它工作:

#!/bin/bash

set -e

SA_NAME="my-cf-sa"
PROJECT="my-project-id"
REGION="europe-west1"
SA_EMAIL="${SA_NAME}@${PROJECT}.iam.gserviceaccount.com"
IAM_MEMBER="serviceAccount:${SA_EMAIL}"
CLOUD_FUNCTION_NAME="my-http-function"
SCHEDULER_JOB_NAME="my-cf-job"

# Create SA to use with function

gcloud iam service-accounts create $SA_NAME \
--description="My CF SA" \
--display-name="My CF SA" \
--project=$PROJECT

# Deploy function with created SA

gcloud functions deploy $CLOUD_FUNCTION_NAME \
--gen2 \
--runtime=python311 \
--source=. \
--entry-point=my_http_function \
--trigger-http \
--service-account=$SA_EMAIL \
--run-service-account=$SA_EMAIL \
--no-allow-unauthenticated \
--region=$REGION \
--project=$PROJECT

# COMMAND BELOW DOES NOT WORK even though it is in documentation here https://cloud.google.com/scheduler/docs/http-target-auth
#
# Generate this error:
#
# ERROR: (gcloud.functions.add-iam-policy-binding) ResponseError: status=[400], code=[Ok], message=[Invalid argument: 'An invalid argument was specified. Please check the fields and try again.']
#
# Bug report for this: https://issuetracker.google.com/issues/284853816
#
# gcloud functions add-iam-policy-binding $CLOUD_FUNCTION_NAME --member=$IAM_MEMBER --role=roles/run.invoker --gen2 --region=$REGION --project=$PROJECT

# Add roles/cloudfunctions.invoker to allow SA to invoke function run
#
# After running this command it will ask you if you want to also add iam for Cloud Run service connected to CF.
#
#
#     WARNING: The role [roles/cloudfunctions.invoker] was successfully bound to member [serviceAccount:my-cf-sa@my-project-id.iam.gserviceaccount.com]
#     but this does not grant the member permission to invoke 2nd gen function [my-http-function]. Instead, the role [roles/run.invoker] must be
#     granted on the underlying Cloud Run service. This can be done by running the `gcloud functions add-invoker-policy-binding` command.
#
#     Would you like to run this command and additionally grant [serviceAccount:my-cf-sa@my-project-id.iam.gserviceaccount.com] permission to invoke function [my-http-function] (Y/n)?
#
# If you choose YES you don't need to manually run iam binding command for Cloud Run service.
# I choose NO and did this in two steps so I could replicate all this in terraform later on

gcloud functions add-iam-policy-binding $CLOUD_FUNCTION_NAME \
--member=$IAM_MEMBER \
--role=roles/cloudfunctions.invoker \
--gen2 \
--region=$REGION \
--project=$PROJECT

# Add roles/run.invoker to allow SA invoke Cloud Run service that is connected to function
#
# Only needed if you choose NO in previous command

gcloud run services add-iam-policy-binding $CLOUD_FUNCTION_NAME \
--member=$IAM_MEMBER \
--role=roles/run.invoker \
--region=$REGION \
--project=$PROJECT

# Create Scheduler job with OIDC auth set to use SA

gcloud scheduler jobs create http $SCHEDULER_JOB_NAME \
--schedule="0 */6 * * *" \
--uri="$(gcloud functions describe $CLOUD_FUNCTION_NAME --gen2 --project=$PROJECT --region=$REGION --format="value(serviceConfig.uri)")" \
--http-method=GET \
--oidc-service-account-email=$SA_EMAIL \
--location=$REGION \
--project=$PROJECT

在实际运行作业之前,您需要等待几分钟,因为IAM权限可能需要一些时间才能传播到所有位置。
在此之后,我手动运行作业:

gcloud scheduler jobs run $SCHEDULER_JOB_NAME --location=$REGION --project=$PROJECT

我查了日志

gcloud logging read "resource.type=\"cloud_scheduler_job\" AND resource.labels.job_id=\"$SCHEDULER_JOB_NAME\" AND resource.labels.location=\"$REGION\"" --project=$PROJECT --limit 1

而我从CF得到了200美元

---
httpRequest:
  status: 200
insertId: gde4phfur06nd
jsonPayload:
  '@type': type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished
  jobName: projects/my-project-id/locations/europe-west1/jobs/my-cf-job
  targetType: HTTP
  url: <FUNCTION_URL>
logName: projects/my-project-id/logs/cloudscheduler.googleapis.com%2Fexecutions
receiveTimestamp: '2023-06-03T16:40:28.454858025Z'
resource:
  labels:
    job_id: my-cf-job
    location: europe-west1
    project_id: my-project-id
  type: cloud_scheduler_job
severity: INFO
timestamp: '2023-06-03T16:40:28.454858025Z'

相关问题