Esercizio - Proteggere i payload del webhook con un segreto

Completato

In questo esercizio si proteggerà il payload del webhook con un segreto e si apprenderà come verificare che i payload provengano effettivamente da GitHub usando la funzione di Azure.

Ottenere la chiave per la funzione di Azure

  1. Nella portale di Azure tornare all'app per le funzioni creata nel primo esercizio del modulo.

  2. Nel riquadro del menu a sinistra in Funzioni selezionare Funzioni. Verrà visualizzato il riquadro Funzioni relativo all'app per le funzioni.

  3. Selezionare l'elemento HttpTrigger1 creato. Viene visualizzato il riquadro HtttpTrigger1 relativo alla funzione.

  4. Nel riquadro del menu a sinistra, in Developer selezionare Codice + Test. Viene visualizzato il riquadro Codice e test per la funzione.

  5. Nel file JavaScript index.js della funzione aggiungere un riferimento alla libreria crypto-js all'inizio del file, sopra l'istruzione module.exports.

    const Crypto = require('crypto');
    
  6. Nella barra dei menu in alto selezionare Salva. Viene visualizzato il riquadro Log nella parte inferiore del riquadro.

  7. Nel riquadro del menu a sinistra, in Sviluppatore, selezionare Chiavi di funzione. Viene visualizzato il riquadro Chiavi di funzione per la funzione.

  8. Nella colonna Valore selezionare il collegamento Mostra valore.

  9. Selezionare l'icona Copia negli Appunti e salvare questa chiave per usarla nel passaggio successivo.

  10. Nel riquadro del menu a sinistra, in Developer selezionare Codice + Test. Viene visualizzato il riquadro Codice e test per la funzione.

  11. Nel blocco di codice aggiungere il codice seguente dopo l'istruzione context.log. Sostituire <chiave predefinita> con la chiave predefinita appena copiata negli Appunti:

    const hmac = Crypto.createHmac("sha1", "<default key>");
    const signature = hmac.update(JSON.stringify(req.body)).digest('hex');
    

    Questo codice calcola l'hash della chiave, usando lo stesso meccanismo di GitHub.

  12. Aggiungere un altro const anteposto a sha1= all'inizio della chiave, in modo che corrisponda al formato di x-hub-signature nell'intestazione della richiesta. Aggiungere il codice seguente alla funzione.

    const shaSignature = `sha1=${signature}`;
    
  13. Aggiungere il codice seguente per recuperare la firma GitHub dall'intestazione della richiesta:

    const gitHubSignature = req.headers['x-hub-signature'];
    
  14. Confrontare le due stringhe. Se corrispondono, elaborare la richiesta, come indicato di seguito:

    if (!shaSignature.localeCompare(gitHubSignature)) {
        // Existing code
        if (req.body.pages[0].title) {
            ...
        }
        else {
            ...
        }
    }
    
  15. Se le stringhe non corrispondono, restituire una risposta HTTP 401 (Non autorizzato), con un messaggio che indica al mittente che le firme non corrispondono.

    if (!shaSignature.localeCompare(gitHubSignature))
    {
        ...
    }
    else {
        context.res = {
            status: 401,
            body: "Signatures don't match"
        };
    }
    
    

    La funzione completata avrà l'aspetto seguente:

    const Crypto = require('crypto');
    
    module.exports = async function (context, req) {
        context.log('JavaScript HTTP trigger function processed a request.');
    
        const hmac = Crypto.createHmac("sha1", "<default key>");
        const signature = hmac.update(JSON.stringify(req.body)).digest('hex');
        const shaSignature =  `sha1=${signature}`;
        const gitHubSignature = req.headers['x-hub-signature'];
    
        if (!shaSignature.localeCompare(gitHubSignature)) {
            if (req.body.pages[0].title) {
                context.res = {
                    body: "Page is " + req.body.pages[0].title + ", Action is " + req.body.pages[0].action + ", Event Type is " + req.headers['x-github-event']
                };
            }
            else {
                context.res = {
                    status: 400,
                    body: ("Invalid payload for Wiki event")
                }
            }
        }
        else {
            context.res = {
                status: 401,
                body: "Signatures don't match"
            };
        }
    };
    
  16. Nella barra dei menu in alto selezionare Salva. Viene visualizzato il riquadro Log con un'istruzione Connected! (Connesso!).

Aggiornare il segreto del webhook

  1. Passare al proprio account GitHub nel portale GitHub.

  2. Selezionare il repository.

  3. Nella barra dei menu in alto selezionare Settings (Impostazioni). Viene visualizzato il riquadro Impostazioni.

  4. Nella barra laterale selezionare Webhooks. Viene visualizzato il riquadro Webhook.

  5. Selezionare Edit (Modifica) accanto al webhook.

  6. Nella casella di testo Secret (Segreto) immettere la chiave predefinita della funzione salvata in precedenza in questo esercizio.

  7. Scorrere fino alla parte inferiore della pagina e selezionare Update webhook (Aggiorna webhook). Viene visualizzato il riquadro Webhooks/Manage webhooks (Webhook/Gestisci webhook).

Testare il webhook e la funzione di Azure

  1. Selezionare la scheda Recent Deliveries (Recapiti recenti).

  2. Selezionare la voce del recapito (in alto) più recente selezionando il pulsante con i puntini di sospensione (...).

  3. Selezionare Redeliver (Recapita nuovamente). Nella finestra di dialogo Recapitare nuovamente il payload? visualizzata, selezionare Sì, recapita nuovamente questo payload.

    Questa azione simula di nuovo la modifica della pagina Wiki.

  4. Selezionare la voce del recapito (in alto) più recente selezionando il pulsante con i puntini di sospensione (...).

  5. Nella sezione Headers (Intestazioni) verrà visualizzato x-hub-signature. Si noterà anche che il codice di risposta è 200, che indica che la richiesta è stata elaborata correttamente.

    Request URL: https://testwh123456.azurewebsites.net/api/HttpTrigger1?code=aUjXIpqdJ0ZHPQuB0SzFegxGJu0nAXmsQBnmkCpJ6RYxleRaoxJ8cQ%3D%3D
    Request method: POST
    content-type: application/json
    Expect:
    User-Agent: GitHub-Hookshot/16496cb
    X-GitHub-Delivery: ce122460-6aae-11e9-99d4-de6a298a424a
    X-GitHub-Event: gollum
    X-Hub-Signature: sha1=<hash of default key>
    

Testare una firma non valida

  1. Nella pagina dei webhook del portale di GitHub selezionare la scheda Impostazioni.

  2. Nella casella di testo Secret (Segreto) selezionare Change Secret (Cambia segreto).

  3. Immettere una stringa casuale, scorrere verso il basso e quindi selezionare Update webhook (Aggiorna webhook).

    La chiave usata dal webhook non deve più corrispondere a quella prevista dalla funzione di Azure.

  4. Selezionare la scheda Recent Deliveries (Recapiti recenti).

  5. Selezionare la voce del recapito (in alto) più recente selezionando il pulsante con i puntini di sospensione (...).

  6. Selezionare Redeliver (Recapita nuovamente) e nella finestra di dialogo Redeliver payload? (Recapitare nuovamente il payload?) visualizzata, selezionare Yes, redeliver this payload (Sì, recapita nuovamente questo payload).

  7. Questa volta si noterà che il codice di risposta è 401, che indica che la richiesta non è stata autorizzata.

  8. Selezionare la voce del recapito (in alto) (redelivery) più recente selezionando il pulsante con i puntini di sospensione (...).

  9. Selezionare la scheda Response (Risposta) e nella sezione Body (Corpo) verificare che il messaggio relativo alla mancata corrispondenza delle firme venga visualizzato.