Перейти до вмісту
На сайт

Перевірка вхідних вебхуків

Будь-хто, хто дізнався ingress-адресу джерела, може надсилати на неї запити. Перевірка звіряє кожен запит із секретом, яким підписує провайдер, і відхиляє все, що не збігається, ще до того, як щось буде збережено.

verificationMode Що перевіряється
NONE Нічого. Усе, що надійшло на адресу, Railhook зберігає й пересилає. Вмикайте цей режим лише на час підключення провайдера.
PROVIDER Власна схема провайдера, яку визначає providerType. Вона є в кожного типу провайдера, крім GENERIC.
HMAC_GENERIC HMAC-SHA256-підпис у заголовку, який ви вкажете. Саме так перевіряють провайдера GENERIC.

На запит, що не пройшов перевірку, Railhook відповідає 401 і не зберігає його.

GET /api/v1/incoming-providers повертає провайдерів, яких перевіряє запущений Railhook, і заголовок, у якому підписує кожен. Провайдера, якого немає в списку, можна додати одним класом; як саме, описано в CONTRIBUTING.md.

providerType Заголовок, що перевіряється Як
GITHUB X-Hub-Signature-256 sha256=, а за ним HMAC-SHA256 необробленого тіла в hex.
GITLAB X-Gitlab-Token Заголовок має дорівнювати секрету. GitLab надсилає токен, а не підпис.
STRIPE Stripe-Signature t=…,v1=…: HMAC-SHA256 від <t>.<необроблене тіло> у hex. t має відрізнятися від поточного часу не більш ніж на 300 секунд. Під час ротації секрету Stripe надсилає по одному v1 на кожен секрет; запит проходить перевірку, якщо збігається будь-який із них.
SHOPIFY X-Shopify-Hmac-SHA256 HMAC-SHA256 необробленого тіла в Base64.
SLACK X-Slack-Signature, X-Slack-Request-Timestamp v0=, а за ним HMAC-SHA256 від v0:<timestamp>:<необроблене тіло> у hex. Мітка часу має відрізнятися від поточного часу не більш ніж на 300 секунд.
TWILIO X-Twilio-Signature HMAC-SHA1 в Base64, ключ — Auth Token. Для запитів у форматі form-encoded підписано URL, а за ним усі параметри, відсортовані за назвою; для інших запитів — лише URL, а параметр рядка запиту bodySHA256 має відповідати тілу.

| SQUARE | x-square-hmacsha256-signature | HMAC-SHA256 у Base64 від адреси сповіщення, за якою одразу йде необроблене тіло, без жодного роздільника. | | ADYEN | hmacsignature або жодного | HMAC-SHA256 у Base64, ключ — декодовані байти hex-ключа HMAC. Стандартний платіжний вебхук не має заголовка взагалі: кожен елемент сповіщення підписує вісім власних полів, з’єднаних двокрапками, і кладе результат у additionalData.hmacSignature. Вебхуки Management і Balance Platform підписують необроблене тіло й передають підпис у заголовку. Railhook приймає обидві схеми, тож одне джерело впорається з будь-якою. | | SENDGRID | X-Twilio-Email-Event-Webhook-Signature, X-Twilio-Email-Event-Webhook-Timestamp | ECDSA над SHA-256 від мітки часу, за якою йде необроблене тіло; перевіряється відкритим ключем SendGrid. Це не HMAC. | | HUBSPOT | X-HubSpot-Signature-v3, X-HubSpot-Request-Timestamp | HMAC-SHA256 у Base64 від методу запиту, повної адреси, необробленого тіла й мітки часу — саме в такому порядку, ключ — client secret застосунку. Мітка часу має відрізнятися від поточного часу не більш ніж на 300 секунд. Підтримано лише v3: v1 і v2 не прив’язують запит до жодного моменту. |

Для будь-якого провайдера секрет указують у полі hmacSecret джерела: секрет підпису вебхуків, секретний токен (Secret token) GitLab, Auth Token Twilio, Signature Key у Square, ключ HMAC Adyen у вигляді того самого шістнадцяткового рядка, який показує Customer Area, або client secret застосунку HubSpot.

Налаштування провайдера

Section titled “Налаштування провайдера”
  1. Створіть джерело з verificationMode: PROVIDER, потрібним providerType і секретом провайдера:

    Terminal window
    curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-sources" \
    -H "X-API-Key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name":"GitHub","providerType":"GITHUB","verificationMode":"PROVIDER","hmacSecret":"'"$GITHUB_WEBHOOK_SECRET"'"}'
  2. Вставте ingressUrl джерела в налаштування вебхуків провайдера з тим самим секретом.

  3. Надішліть тестовий вебхук із боку провайдера. Він з’явиться в розділі «Отримані»; якщо підпис не збігся, Railhook відповість 401 і вебхука там не буде.

Для провайдера без готового пресету використовуйте HMAC_GENERIC:

Поле Типово Значення
hmacHeaderName X-Signature Заголовок із підписом.
hmacSignaturePrefix немає Префікс, який Railhook відкидає перед порівнянням, наприклад sha256=.
hmacSecret Спільний секрет.

Railhook приймає заголовок у двох форматах:

Формат Що підписано Захист від повторного використання
t=<unix-ms>,v1=<hex>, власний формат Railhook <t>.<необроблене тіло> t має відрізнятися від поточного часу не більш ніж на 300 секунд.
Лише hex-дайджест Лише необроблене тіло Сам підпис не захищає: той самий запит проходитиме перевірку, доки діє секрет.
Terminal window
curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-sources" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Acme","providerType":"GENERIC","verificationMode":"HMAC_GENERIC","hmacHeaderName":"X-Acme-Signature","hmacSignaturePrefix":"sha256=","hmacSecret":"'"$ACME_SECRET"'"}'

Повторне використання підписів

Section titled “Повторне використання підписів”

Railhook пам’ятає перевірений підпис протягом певного вікна й відхиляє з 401 другий запит із тим самим підписом у межах цього вікна. Для провайдерів, у підписі яких є мітка часу, це відсікає дублікати. Для голого hex-дайджесту це єдиний захист від того, що перехоплений запит надішлють ще раз.

Запит з ідентифікатором події провайдера, яку Railhook уже зберіг, — це повторне надсилання, а не повторне використання підпису: він однаково має пройти перевірку, після чого Railhook відповідає 202 зі збереженою подією. Див. повторні надсилання від провайдера.

Змінна Типово
WEBHOOK_INGRESS_REPLAY_WINDOW_MINUTES 5