无法从 GCP 调度程序调用 Google Cloud Function

Posted

技术标签:

【中文标题】无法从 GCP 调度程序调用 Google Cloud Function【英文标题】:Cannot invoke Google Cloud Function from GCP Scheduler 【发布时间】:2020-05-20 03:57:40 【问题描述】:

我一直在尝试从 GCP 调度程序调用 GCP 函数 (--runtime nodejs8 --trigger-http),这两个函数都位于同一个项目中。如果我通过将allUsers 成员添加到函数权限并应用Cloud Functions-Invoker 角色来授予未经身份验证的访问权限,我只能使其工作。但是,当我仅将调度程序的服务帐户用作Cloud Functions-Invoker 时,会出现 PERMISSION DENIED 错误。

我创建了一个 hello world 示例,详细展示了我的设置是什么样的。

    我设置了一个服务帐号:

gcloud iam service-accounts create scheduler --display-name="Task Schedule Runner"

    设置角色:
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
    部署云功能:

gcloud functions deploy helloworld --runtime nodejs8 --trigger-http --entry-point=helloWorld

    将服务帐号作为成员添加到函数中:

gcloud functions add-iam-policy-binding helloworld --member serviceAccount:scheduler@mwsdata-1544225920485.iam.gserviceaccount.com --role roles/cloudfunctions.invoker

    创建调度程序作业:

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'

【问题讨论】:

cloud.google.com/functions/docs/securing/authenticating 我都做到了。 GCP 提供的唯一官方教程只涉及 scheduler -> PubSub -> Cloud Functions。或者这是要走的路?我无法想象.. 您做错了与文档不符的事情。首先,不要修改代理服务帐户 - 撤消任何更改。其次,您需要为服务帐户和 Functions 服务本身分配正确的角色。使用这两项的详细信息编辑您的问题。不说你尝试了什么,展示一下此时究竟配置了什么。 @JohnHanley 我添加了请求的详细信息 请显示设置的内容,而不是您尝试执行的操作。使用gcloud 命令读取分配。在您的问题中显示命令和结果。 【参考方案1】:

以下是我使 Cloud Scheduler 触发不允许未经身份验证的调用的 HTTP 触发的 Cloud Functions 的步骤:

    Create a service account,格式如下 [SA-NAME]@[PROJECT-ID].iam.gserviceaccount.com。 将服务帐户 [SA-NAME]@[PROJECT-ID].iam.gserviceaccount.com 添加为 a project member 并将以下角色添加到服务帐户:Cloud Functions Invoker 和 Cloud Scheduler Admin。 Deploy an HTTP triggered Cloud Function 不允许公共(未经身份验证)访问(如果您使用 UI,只需取消选中允许未经身份验证的调用复选框)并且使用最近创建的服务帐户 [SA-NAME]@[PROJECT-ID].iam服务帐户字段上的 .gserviceaccount.com(单击更多并查找服务帐户字段,默认情况下应设置为 App Engine 默认服务帐户)并注意 Cloud Function 的 URL。 Create a Cloud Scheduler job with authentication 通过从 Cloud Shell 发出以下命令: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 服务帐户。将其更改为您在前面步骤中指定的创建的服务帐户。

【讨论】:

我也尝试了所有这些,但没有成功。然后我创建了一个新项目,在那里部署了所有东西,并且一切都按预期工作(事实上,每一个设置,我们在这篇文章中都讨论过)。我不知道,为什么它以前没有工作。也许在更高级别上有一些限制,阻止了工作访问该功能..我不知道.. 但根据您上次的编辑,Function Description: 部分指出 App Engine 的默认服务帐户 serviceAccountEmail: mwsdata-1544225920485@appspot.gserviceaccount.com 在您的 Cloud Function 上用作运行时服务帐户,您需要使用 @987654331 @服务帐户创建云功能时指定在我的帖子的第 3 步。尽管如此,我真的很高兴你能在一个新项目上工作! @DanielOcando 您提供的解决方案在我的情况下效果很好。我正在从云调度程序触发经过身份验证的云功能。 @DanielOcando 您提供的解决方案适用于“从云调度程序触发云功能”场景。我还有另一种情况,我想从另一个经过身份验证的云功能触发经过身份验证的云功能。更多信息可以参考:***.com/questions/61055972/…【参考方案2】:

@Marko 我遇到了同样的问题,似乎重新启用(禁用/启用)调度程序 API 进行了修复。这就是为什么创建一个新项目是有意义的,因为您可能通过这样做获得了一个调度程序服务帐户。因此,如果您的项目没有从 google 创建的调度程序服务帐户,那么执行此技巧将为您提供一个。尽管您不需要将此特定服务帐户分配给您的任何任务,但它必须可用。你可以在这里看到我的作品:How to invoke Cloud Function from Cloud Scheduler with Authentication

【讨论】:

我仍然创建了一个明确的服务帐户,但是禁用并重新启用 api 然后重新创建我的计划(使用我的明确服务帐户)最终解决了问题。感谢您的提示。 很高兴它有帮助! @马特伯恩 浪费了大量时间试图为我的服务帐户查找缺少的权限/角色。无法相信“关闭再打开”毕竟是解决方案。 你成功了!干得好,当时对我来说是一个令人沮丧的错误。 @GurupadMamadapur 现在我们知道罪魁祸首:cloud.google.com/scheduler/docs/… 查看 Vitalii Kyrychenko 的回答。【参考方案3】:

根据 GCP 的最新更新,新功能需要手动更新以进行身份​​验证。

我们需要给用户allusers添加云函数Invoker权限。

请参考 https://cloud.google.com/functions/docs/securing/managing-access-iam#allowing_unauthenticated_function_invocation

【讨论】:

【参考方案4】:

本教程帮我调用了一个programmer函数,但是在创建service account后在创建程序的时候出现了问题,最后去掉了programmer,又做了一遍。

Google Cloud Scheduler - Calling Cloud Function

【讨论】:

【参考方案5】:

我也有类似的问题。

在我们的例子中,我们很久以前就启用了 Cloud Scheduler。

根据the docs,如果您启用Cloud Scheduler API之前 2019年3月19日,您需要手动将Cloud Scheduler Service Agent角色添加到您的Cloud Scheduler服务帐号。

所以我们必须创建一个类似于 service-[project-number]@gcp-sa-cloudscheduler.iam.gserviceaccount.com 的新服务帐户

希望这对其他人有帮助。

【讨论】:

看起来这也适用于 Pub/Sub 触发器,而文档适用于 HTTP 我还必须将“Cloud Scheduler Service Agent”角色添加到调度程序调用我的函数的服务帐户。

以上是关于无法从 GCP 调度程序调用 Google Cloud Function的主要内容,如果未能解决你的问题,请参考以下文章

如何调用使用 GCP 身份验证的 REST 服务?

有关如何从 Google Cloud Platform 调用外部网络服务的任何信息?

GCP - 无法在 Cloud Run 中使用 Google Secret Manager (@google-cloud/secret-manager)

k8s无法在GCP上调度本地ssd卷

从存储桶复制 GCP 文件失败,无法访问元数据服务

Google Secret Manager:不要通过 Spring Boot 从中获得价值