如何使用身份验证从 Cloud Scheduler 调用 Cloud Function

Nat*_*uer 12 python authentication google-cloud-functions google-cloud-scheduler

我到处寻找,似乎人们要么使用 pubsub、应用程序引擎 http 或没有身份验证的 http。没有太多人展示他们通过身份验证访问函数的工作,使用 oidc 令牌来访问谷歌函数。

我签出:无法从 GCP 调度程序调用谷歌云功能,但似乎没有任何工作。

我遵循的文档:https : //cloud.google.com/scheduler/docs/http-target-auth#using-gcloud_1

  1. 创建了一个新的服务帐户
  2. 设置角色(云调度程序服务代理/云函数服务代理/云调度程序管理员/云函数调用者......甚至尝试过所有者!)
  3. 已部署的 google 函数不允许公开(未经身份验证的)访问(一个简单的 helloworld 函数)
  4. 在云调度程序上设置 cron 作业以使用此配置每分钟针对新部署的功能运行:
    • url = helloworld 函数
    • oidc-token
    • 新创建的服务帐户
    • 观众设置为你好世界功能网址

云调度程序日志的结果:

Expand all | Collapse all{
 httpRequest: {
 }
 insertId: "ibboa4fg7l1s9"  
 jsonPayload: {
  @type: "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished"   
  jobName: "projects/project/locations/region/jobs/tester"   
  status: "PERMISSION_DENIED"   
  targetType: "HTTP"   
  url: "https://region-project.cloudfunctions.net/tester"   
 }
 logName: "projects/project/logs/cloudscheduler.googleapis.com%2Fexecutions"  
 receiveTimestamp: "2020-04-15T17:50:14.287689800Z"  
 resource: {…}  
 severity: "ERROR"  
 timestamp: "2020-04-15T17:50:14.287689800Z" 
Run Code Online (Sandbox Code Playgroud)

我看到一个解决方案,显示有人创建了一个新项目来开始工作,还有其他解决方案吗?

感谢提供的任何帮助。

更新

新的 Google 功能 - 在中央运行(与我的应用引擎应用相同)

新服务帐户 - 具有所有者角色

新计划任务 - 信息

新建计划任务 - 状态

新建计划任务 - 日志

实际修复

如果您缺少 cloudcheduler 服务帐户(例如:service-1231231231412@gcp-sa-cloudscheduler.iam.gserviceaccount.com)Http auth 任务将不起作用。为了解决这个问题,我不得不禁用 api 并重新启用,它给了我服务帐户,我没有使用这个服务帐户,但是,这是我这样做后唯一的变化因素,使其工作。

Voy*_*Voy 8

我想我应该扩展 Nebulastic 的答案,因为我刚刚发现有一些边缘情况他们的答案并不完整。

创建云函数

# Create cloud function
gcloud functions deploy my_function \
  --entry-point=my_entrypoint \
  --runtime=python37 \
  --trigger-http \
  --region=europe-west1 \
  --project=${PROJECT_ID}
Run Code Online (Sandbox Code Playgroud)

您可能想要更改字段,例如entry-pointruntimetrigger请参阅Cloud Functions 部署文档了解更多信息。

创建云调度程序作业:

# Deploy scheduler
gcloud scheduler jobs create http my_job \
  --schedule="every 60 minutes" \
  --uri="https://europe-west1-${PROJECT_ID}.cloudfunctions.net/my_function/" \
  --http-method=POST \
  --oidc-service-account-email="${SERVICE_ACCOUNT_EMAIL}" \
  --oidc-token-audience="https://europe-west1-${PROJECT_ID}.cloudfunctions.net/my_function" \
  --project=${PROJECT_ID}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅云计划文档。

请注意,任何服务帐户都可以用于 OIDC 身份验证,而不仅仅是为项目创建的默认帐户。

此外,您不需要gcloud functions add-iam-policy-binding像 Nebulastic 的答案中建议的那样进行调用,而是可以将Cloud Functions Invoker角色设置为传递到的服务帐户--oidc-service-account-email(请参阅有关添加角色的文档)。这样,此类服务帐户将有权调用任何云功能,而无需在每次部署时授予此类权限。这并不是说 Nebulastic 建议的方法不正确,您也可以这样做。

您可以通过在 Cloud Functions 列表 -> 权限选项卡 -> 角色子选项卡 -> 打开 Cloud Functions Invoker 行中单击其名称来验证哪些服务帐户有权调用该函数。

功能权限


现在来说说边缘情况:

入口 - 仅允许内部流量

尽管文档有建议,将函数的入口设置设置为“仅允许内部流量”并不包含 Cloud Scheduler 的流量,并且会导致 PERMISSION_DENIED 错误。GCP 开发人员已经意识到这一点,并且可能会在未来得到修复。目前,请使用“允许所有流量”(或者--ingress-settings=all如果使用 gcloud 进行部署)。

入口设置

URL参数和OIDC认证

如果您的 Cloud Schedule 作业使用 OIDC 身份验证,并且您的函数需要URL 参数形式的参数- 例如。...my_function?key=value- 那么您必须确保 OIDC Audience包含 URL 参数。仅在 URL 字段中指定 URL 参数,但如果它们出现在 Audience 字段中,请求将返回 403 UNAUTHENTICATED。请注意,如果您未手动指定 OIDC 受众,OIDC 受众会自动填写 URL 副本。这是 GCP 开发人员了解的另一个问题,并且可能正在修复或更新文档。

tldr:不要将 URL 参数放入 OIDC 受众 URL 中 - 仅在 URL 字段中:

  --uri="https://europe-west1-${PROJECT_ID}.cloudfunctions.net/my_function?key=value" \
  --oidc-token-audience="https://europe-west1-${PROJECT_ID}.cloudfunctions.net/my_function" \
Run Code Online (Sandbox Code Playgroud)

JSON 参数和 Content-Type

如果您选择使用 Cloud Scheduler 作业调用带有 JSON 参数的函数 - 例如。{"key": "value"}正文字段中 - 那么您将需要:

  • 在函数中手动解析 JSON - 例如Flask 的 get_json将无法工作,除非您使用force=True.

  • gcloud scheduler jobs create使用而不是从控制台创建函数,并确保通过添加以下标志来指定 Content-Type 标头:--headers Content-Type=application/json

Cloud Scheduler API 在 2019 年 3 月 19 日之前启用

启用 Cloud Scheduler API 时,会自动设置授予此角色的 Cloud Scheduler 服务帐户,除非您在 2019 年 3 月 19 日之前启用它,在这种情况下,您必须手动添加该角色。

这似乎是作者问题中列出的问题背后的原因。请参阅文档了解更多信息。造成问题的原因如下:

Cloud Scheduler 本身必须有一个自己的服务帐户,该帐户已授予 Cloud Scheduler 服务代理角色。这样它就可以代表您的客户服务帐户生成标头令牌,以对您的目标进行身份验证。


资料来源:刚刚花了一周的时间与他们的一位支持代理一起解决了所有这些问题 - 向帮助发现所有这些怪癖的 Jason 大声喊叫。他们正在解决这些问题,但我想我应该把这些信息留在这里,直到(如果有的话)这些问题得到解决。


Neb*_*tic 7

这些是您必须采取的确切步骤。确保不要跳过第二步,它会在服务帐户上设置调用者权限,以便调度程序能够使用该服务帐户的 OIDC 信息调用 HTTP Cloud Function。注意:为简单起见,我在这里选择默认服务帐户,但是,为此目的创建一个具有较少权限的单独服务帐户是明智的。

# Create cloud function
gcloud functions deploy my_function \
  --entry-point=my_entrypoint \
  --runtime=python37 \
  --trigger-http \
  --region=europe-west1 \
  --project=${PROJECT_ID}

# Set invoke permissions
gcloud functions add-iam-policy-binding my_function \
  --region=europe-west1 \
  --member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
  --role="roles/cloudfunctions.invoker" \
  --project=${PROJECT_ID}

# Deploy scheduler
gcloud scheduler jobs create http my_job \
  --schedule="every 60 minutes" \
  --uri="https://europe-west1-${PROJECT_ID}.cloudfunctions.net/my_function/" \
  --http-method=POST \
  --oidc-service-account-email="${PROJECT_ID}@appspot.gserviceaccount.com" \
  --oidc-token-audience="https://europe-west1-${PROJECT_ID}.cloudfunctions.net/my_function" \
  --project=${PROJECT_ID}
Run Code Online (Sandbox Code Playgroud)