验证来自Google Cloud Scheduler的HTTP请求

时间:2018-11-06 22:50:57

标签: cron google-cloud-platform scheduler google-cloud-scheduler

验证来自Google Cloud Scheduler的HTTP请求的过程是什么?文档(https://cloud.google.com/scheduler/docs/creating)提到您可以创建一个目标为任何公共HTTP终结点的作业,但没有提及服务器如何验证cron / scheduler请求。

4 个答案:

答案 0 :(得分:3)

[2019年5月28日更新]

Google Cloud Scheduler现在具有两个命令行选项:

--oidc-service-account-email=<service_account_email>
--oidc-token-audience=<service_endpoint_being_called>

这些选项将额外的标头添加到Cloud Scheduler发出的请求中:

 Authorization: Bearer ID_TOKEN

您可以在端点代码中处理ID_TOKEN以验证谁在呼叫您的端点。

例如,您可以发出HTTP请求以解码ID令牌:

https://oauth2.googleapis.com/tokeninfo?id_token=ID_TOKEN

这将返回如下JSON:

{
  "aud": "https://cloudtask-abcdefabcdef-uc.a.run.app",
  "azp": "0123456789077420983142",
  "email": "cloudtask@development.iam.gserviceaccount.com",
  "email_verified": "true",
  "exp": "1559029789",
  "iat": "1559026189",
  "iss": "https://accounts.google.com",
  "sub": "012345678901234567892",
  "alg": "RS256",
  "kid": "0123456789012345678901234567890123456789c3",
  "typ": "JWT"
}

然后,您可以检查服务帐户电子邮件是否与您授权Cloud Scheduler使用的电子邮件匹配,并且令牌尚未过期。

[结束更新]

您需要亲自验证请求。

Google Cloud Scheduler包含多个Google特定的标头,例如User-Agent: Google-Cloud-Scheduler。请参阅下面的文档链接。

但是,任何人都可以伪造HTTP标头。您需要创建一个自定义something,您可以将其包含为HTTP标头或知道如何进行验证的HTTP正文中的内容。使用签名的JWT是安全的,并且易于创建和验证。

创建Google Cloud Scheduler作业时,您可以控制headersbody字段。您可以将自定义something嵌入其中一个。

Scheduler Jobs

[更新]

以下是使用gcloud的示例(Windows命令行),以便您可以设置HTTP标头和正文。此示例在每个触发器上调用“云函数”,以显示如何包括APIKEY。 Google控制台还没有此级别的支持。

gcloud beta scheduler ^
--project production ^
jobs create http myfunction ^
--time-zone "America/Los_Angeles" ^
--schedule="0 0 * * 0" ^
--uri="https://us-central1-production.cloudfunctions.net/myfunction" ^
--description="Job Description" ^
--headers="{ \"Authorization\": \"APIKEY=AUTHKEY\", \"Content-Type\": \"application/json\" }" ^
--http-method="POST" ^
--message-body="{\"to\":\"/topics/allDevices\",\"priority\":\"low\",\"data\":{\"success\":\"ok\"}}"

答案 1 :(得分:1)

简短回答

如果您将应用托管在Google Cloud中,只需检查标题X-Appengine-Queuename是否等于__scheduler。但是,这是未记录的行为,有关更多信息,请参阅下文。

此外,如果可能,请使用Pub / Sub而不是HTTP请求,因为Pub / Sub是内部发送的(因此隐式验证了来源)。


实验

我发现here时,Google剥离了某些标头 1 的请求,但不是全部 2 。让我们看看是否有Cloud Scheduler的标头。

1 例如您无法发送任何X-Google-*标头(通过实验找到,但here's some info about it

2 例如您可以发送X-Appengine-*标头(通过实验找到)

实验中使用的Flask应用程序:

@app.route('/echo_headers')
def echo_headers():
    headers = {h[0]: h[1] for h in request.headers}
    print(headers)
    return jsonify(headers)

Cloud Scheduler发送的请求标头

{
  "Host": []
  "X-Forwarded-For": "0.1.0.2, 169.254.1.1",
  "X-Forwarded-Proto": "http",
  "User-Agent": "AppEngine-Google; (+http://code.google.com/appengine)",
  "X-Appengine-Queuename": "__scheduler",
  "X-Appengine-Taskname": [private]
  "X-Appengine-Taskretrycount": "1",
  "X-Appengine-Taskexecutioncount": "0",
  "X-Appengine-Tasketa": [private]
  "X-Appengine-Taskpreviousresponse": "0",
  "X-Appengine-Taskretryreason": "",
  "X-Appengine-Country": "ZZ",
  "X-Cloud-Trace-Context": [private]
  "X-Appengine-Https": "off",
  "X-Appengine-User-Ip": [private]
  "X-Appengine-Api-Ticket": [private]
  "X-Appengine-Request-Log-Id": [private]
  "X-Appengine-Default-Version-Hostname": [private]
}

证明标题X-Appengine-Queuename已被GAE删除

enter image description here

限制

Google SLA和折旧政策很可能不支持此方法,因为未记录该方法。另外,我不确定在请求源位于Google Cloud内时是否无法伪造标头(可能是在外层剥离了标头)。我已经在GAE中使用某个应用进行了测试,对于其他部署选项,结果可能会有所不同。简而言之,使用后果自负。

答案 2 :(得分:0)

这个标题应该有效:

<块引用>

映射(键:字符串,值:字符串)

HTTP 请求标头。

此映射包含标题字段名称和值。标题可以是 在创建作业时设置。

Cloud Scheduler 将一些标头设置为默认值:

User-Agent:默认情况下,此标头为“AppEngine-Google; (+http://code.google.com/appengine)”。这个标题可以修改,但是 Cloud Scheduler 将附加“AppEngine-Google; (+http://code.google.com/appengine)”到修改后的用户代理。 X-CloudScheduler:此标头将设置为 true。 X-CloudScheduler-JobName:此标头将包含作业名称。 X-CloudScheduler-ScheduleTime:对于中指定的 Cloud Scheduler 作业 unix-cron 格式,此标头将包含作业计划时间 RFC3339 UTC“祖鲁语”格式。如果作业有正文,则 Cloud Scheduler 设置以下标题:

Content-Type:默认情况下,Content-Type 标头设置为 “应用程序/八位字节流”。默认值可以被显式覆盖 作业时将 Content-Type 设置为特定的媒体类型 创建。例如,Content-Type 可以设置为“application/json”。 内容长度:这是由 Cloud Scheduler 计算的。这个值是 仅输出。它无法更改。以下标题仅输出。 它们不能被设置或覆盖:

X-Google-:仅供 Google 内部使用。 X-AppEngine-:对于 Google 限内部使用。此外,一些 App Engine 标头,其中包含 作业特定的信息也会发送给作业处理程序。

一个包含“键”:值对列表的对象。示例:{“名称”: "扳手", "质量": "1.3kg", "count": "3" }.

https://cloud.google.com/scheduler/docs/reference/rest/v1/projects.locations.jobs#appenginehttptarget

答案 3 :(得分:0)

if request.META['HTTP_X_CLOUDSCHEDULER'] == 'true':
   print("True")