验证来自Google Cloud Scheduler的HTTP请求的过程是什么?文档(https://cloud.google.com/scheduler/docs/creating)提到您可以创建一个目标为任何公共HTTP终结点的作业,但没有提及服务器如何验证cron / scheduler请求。
答案 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作业时,您可以控制headers
和body
字段。您可以将自定义something
嵌入其中一个。
[更新]
以下是使用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-*
标头(通过实验找到)
@app.route('/echo_headers')
def echo_headers():
headers = {h[0]: h[1] for h in request.headers}
print(headers)
return jsonify(headers)
{
"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删除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" }.
答案 3 :(得分:0)
if request.META['HTTP_X_CLOUDSCHEDULER'] == 'true':
print("True")