Подтвердите HTTP-запрос от Google Cloud Scheduler - PullRequest
0 голосов
/ 07 ноября 2018

Каков процесс проверки HTTP-запроса от планировщика Google Cloud? В документах (https://cloud.google.com/scheduler/docs/creating) указано, что вы можете создать задание с целью любой общедоступной конечной точки HTTP, но не упоминается, как сервер проверяет запрос cron / планировщика.

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Краткий ответ

Если ваше приложение размещено в Google Cloud, просто проверьте, равен ли заголовок X-Appengine-Queuename __scheduler. Однако это недокументированное поведение, дополнительную информацию читайте ниже.

Кроме того, если возможно, используйте Pub / Sub вместо HTTP-запросов, так как Pub / Sub отправляется изнутри (поэтому имеет неявно проверенное происхождение).


Эксперимент

Как я обнаружил здесь , Google удаляет запросы определенных заголовков 1 , но не всех 2 . Давайте выясним, есть ли такие заголовки для Cloud Scheduler.

1 Например. вы не можете отправить X-Google-* заголовки (найдены экспериментально, но вот некоторая информация об этом )

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)

Заголовки запроса отправлены 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, поскольку он не задокументирован. Кроме того, я не уверен, что заголовок не может быть подделан, когда источник запроса находится в Google Cloud (возможно, они удалены на внешнем уровне). Я протестировал с приложением в GAE, результаты могут отличаться или не отличаться для других вариантов развертывания. Короче, используйте на свой страх и риск.

0 голосов
/ 07 ноября 2018

[Обновление от 28 мая 2019 г.]

Планировщик Google Cloud теперь имеет две опции командной строки:

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

Эти опции добавляют дополнительный заголовок к запросу, который делает Cloud Scheduler:

 Authorization: Bearer ID_TOKEN

Вы можете обработать ID_TOKEN внутри кода конечной точки, чтобы проверить, кто вызывает вашу конечную точку.

Например, вы можете сделать HTTP-запрос для декодирования идентификатора токена:

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, вы можете управлять полями headers и body. Вы можете встроить свой пользовательский something в любой из них.

Планировщик заданий

[Update]

Вот пример (командная строка Windows), использующий gcloud, чтобы вы могли установить заголовки HTTP и тело. В этом примере вызывается функция Cloud для каждого триггера, показывающая, как включить 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\"}}"
...