Verify HTTP request from Google Cloud Scheduler

混江龙づ霸主 提交于 2019-11-27 18:53:41

问题


What's the process for verifying the HTTP request from Google Cloud scheduler? The docs (https://cloud.google.com/scheduler/docs/creating) mention you can create a job with a target of any publicly available HTTP endpoint but do not mention how the server verifies the cron/scheduler request.


回答1:


[Update May 28, 2019]

Google Cloud Scheduler now has two command line options:

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

These options add an additional header to the request that Cloud Scheduler makes:

 Authorization: Bearer ID_TOKEN

You can process the ID_TOKEN inside your endpoint code to verify who is calling your endpoint.

For example, you can make an HTTP request to decode the ID Token:

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

This will return JSON like this:

{
  "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"
}

Then you can check that the service account email matches the one that you authorized Cloud Scheduler to use and that the token has not expired.

[End Update]

You will need to verify the request yourself.

Google Cloud Scheduler includes several Google specific headers such as User-Agent: Google-Cloud-Scheduler. Refer to the documentation link below.

However, anyone can forge HTTP headers. You need to create a custom something that you include as an HTTP Header or in the HTTP body that you know how to verify. Using a signed JWT would be secure and easy to create and verify.

When you create a Google Cloud Scheduler Job you have some control over the headers and body fields. You can embed your custom something in either one.

Scheduler Jobs

[Update]

Here is an example (Windows command line) using gcloud so that you can set HTTP headers and the body. This example calls Cloud Functions on each trigger showing how to include an APIKEY. The Google Console does not have this level of support yet.

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\"}}"



回答2:


Short answer

If you host your app in Google Cloud, just check if header X-Appengine-Queuename equals __scheduler. However, this is undocumented behaviour, for more information read below.

Furthermore, if possible use Pub/Sub instead of HTTP requests, as Pub/Sub is internally sent (therefore of implicitly verified origin).


Experiment

As I've found here, Google strips requests of certain headers1, but not all2. Let's find if there are such headers for Cloud Scheduler.

1 E.g. you can't send any X-Google-* headers (found experimentally, read more)

2 E.g. you can send X-Appengine-* headers (found experimentally)

Flask app used in the experiment:

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

Request headers sent by 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]
}

Proof that header X-Appengine-Queuename is stripped by GAE

Limitations

This method is most likely not supported by Google SLAs and Depreciation policies, since it's not documented. Also, I'm not sure if header cannot forged when the request source is within Google Cloud (maybe they're stripped at the outside layer). I've tested with an app in GAE, results may or may not vary for other deployment options. In short, use at your own risk.



来源:https://stackoverflow.com/questions/53181297/verify-http-request-from-google-cloud-scheduler

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!