Vai al contenuto

Webhook

Un webhook invia una richiesta POST JSON a un indirizzo esterno quando succede qualcosa su una bacheca. Si configura per bacheca (permesso board.manage) dalla bacheca o con l'API.

Eventi

Evento Quando
task.created task creata (dal Kanban, dall'API, da una riunione o da un link pubblico)
task.updated task modificata o completata da TaskWorkflow
task.moved task spostata in un altro stato; il payload ha anche from_list
task.completed task diventata done
task.deleted, task.restored task nel cestino e ripristinata
comment.created nuovo commento
ping solo per il pulsante "Prova"

Un webhook ascolta gli eventi scelti alla creazione (Webhook::events).

Consegna

  1. WebhookDispatcher trova i webhook della bacheca interessati all'evento e costruisce il payload: task (uuid, titolo, stato, priorità, avanzamento, date, stato con is_done, assegnatari), bacheca ed eventuale commento.
  2. Crea una WebhookDelivery in attesa e accoda un DeliverWebhookJob.
  3. WebhookDeliveryService::attempt() invia la richiesta con:
    • X-GesTask-Event e X-GesTask-Delivery (uuid della consegna, ripetuto anche nel corpo come delivery);
    • X-GesTask-Signature: sha256=<HMAC del corpo> se il webhook ha un segreto;
    • autenticazione Basic, se configurata;
    • timeout di 3 secondi per la connessione e 5 in tutto.
  4. Una risposta non 2xx è un fallimento. Si salvano codice, i primi 2000 caratteri della risposta, errore e durata.

Gli header X-Gestick-* del vecchio nome sono inviati ancora, duplicati, per compatibilità.

Verificare la firma

Chi riceve calcola l'HMAC SHA-256 del corpo grezzo con il segreto condiviso e lo confronta, in tempo costante, con il valore dopo sha256=.

Tentativi

  • Dopo un fallimento si riprova dopo 1 minuto, 5 minuti, 30 minuti, 2 ore e 6 ore, fino a params['webhooks']['maxAttempts'] (5).
  • php yii webhook/retry (ogni 5 minuti) riprova le consegne scadute.
  • php yii webhook/prune (ogni giorno) elimina le consegne più vecchie di retentionDays (30).
  • Dall'interfaccia si può riconsegnare a mano una consegna e inviare un ping di prova, che parte subito.

Protezione SSRF

Un webhook non deve poter raggiungere la rete interna. OutboundUrlGuard controlla l'indirizzo al salvataggio e di nuovo a ogni invio:

  • solo http e https, senza credenziali nell'URL;
  • tutti gli IP risolti devono essere pubblici: niente reti private, riservate, CGNAT, link-local, loopback, ULA o IPv4 mappati in IPv6;
  • la connessione è fissata sull'IP verificato (CURLOPT_RESOLVE), senza redirect e solo HTTP/HTTPS, così un DNS che cambia risposta non aggira il controllo.

Per un servizio interno legittimo si aggiunge il nome host a params['outboundRequests']['allowedHosts']; allowPrivateNetworks disattiva il controllo ed è da usare solo su installazioni isolate. La stessa protezione vale per le notifiche Slack e le iscrizioni Web Push.