Exercice : Sécuriser des charges utiles de webhook avec un secret

Effectué

Dans cet exercice, vous protégez votre charge utile webhook avec un secret et apprenez à valider que les charges utiles proviennent réellement de GitHub à l’aide de votre fonction Azure.

Obtenir une clé pour votre fonction Azure

  1. Dans le portail Microsoft Azure, retournez à l’application de fonction que vous avez créée dans le premier exercice de ce module.

  2. Dans le volet du menu de gauche, sous Fonctions, sélectionnez Fonctions. Le volet Fonctions s’affiche pour votre application de fonction.

  3. Sélectionnez la fonction HttpTrigger1 que vous avez créée. Le volet HttpTrigger1 s’affiche pour votre fonction.

  4. Dans le volet du menu de gauche, sélectionnez Code + test sous Développeur. Le volet Code + Test s’affiche pour votre fonction.

  5. Dans le fichier JavaScript index.js de votre fonction, ajoutez une référence à la bibliothèque crypto-js au début du fichier, au-dessus de l’instruction module.exports.

    const Crypto = require('crypto');
    
  6. Dans la barre de menus supérieure, sélectionnez Enregistrer. Le volet Journaux s’affiche en bas du volet.

  7. Dans le volet du menu de gauche, sous Développeur, sélectionnezClés de fonction. Le volet Clés de fonction s’affiche pour votre fonction.

  8. Sous la colonne Valeur, sélectionnez le lien Afficher la valeur.

  9. Sélectionnez l’icône Copier dans le presse-papiers, puis enregistrez cette clé pour l’utiliser à l’étape suivante.

  10. Dans le volet du menu de gauche, sélectionnez Code + test sous Développeur. Le volet Code + Test s’affiche pour votre fonction.

  11. Dans le bloc de code, après l’instruction context.log, ajoutez le code suivant. Remplacez <default key> par la clé par défaut que vous avez copiée dans le Presse-papiers :

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

    Ce code calcule le hachage de la clé, en utilisant le même mécanisme que GitHub.

  12. Ajoutez un autre const devant sha1= au début de la clé, pour qu’il corresponde au format de x-hub-signature dans l’en-tête de requête. Ajoutez le code suivant à votre fonction.

    const shaSignature = `sha1=${signature}`;
    
  13. Ajoutez le code suivant pour récupérer la signature GitHub à partir de l’en-tête de requête :

    const gitHubSignature = req.headers['x-hub-signature'];
    
  14. Comparez les deux chaînes. Si elles sont identiques, traitez la requête de la façon suivante :

    if (!shaSignature.localeCompare(gitHubSignature)) {
        // Existing code
        if (req.body.pages[0].title) {
            ...
        }
        else {
            ...
        }
    }
    
  15. Si elles ne sont pas identiques, retournez une réponse HTTP 401 (non autorisé), avec un message indiquant à l’expéditeur que les signatures ne sont pas les mêmes.

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

    Une fois terminée, la fonction doit ressembler à ceci :

    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. Dans la barre de menus supérieure, sélectionnez Enregistrer. Le volet Journaux apparaît avec l’indication Vous êtes connecté !

Mettre à jour le secret du webhook

  1. Basculez vers votre compte GitHub à partir du portail GitHub.

  2. Sélectionnez votre dépôt.

  3. Dans la barre de menus supérieure, sélectionnez Paramètres. Le volet Paramètres s’affiche.

  4. Dans la barre latérale , sélectionnez Webhooks. Le volet Webhooks s’affiche.

  5. Sélectionnez Edit (Modifier) à côté de votre webhook.

  6. Dans la zone de texte Secret, entrez la clé par défaut de votre fonction que vous avez enregistrée précédemment dans cet exercice.

  7. Faites défiler l’affichage jusqu’au bas de la page, puis sélectionnez Mettre à jour le webhook. Le volet Webhooks/Manage webhooks (Webhooks/Gérer les webhooks) s’affiche.

Tester le webhook et la fonction Azure

  1. Sélectionnez l’onglet Recent Deliveries (Livraisons récentes).

  2. Sélectionnez l’entrée de la dernière livraison (en haut) en sélectionnant le bouton de sélection (...).

  3. Sélectionnez Redeliver (Relivrer). Dans la boîte de dialogue Redeliver payload? (Relivrer la charge utile ?) qui s’affiche, sélectionnez Yes, redeliver this payload (Oui, relivrer cette charge utile).

    Cette action simule une nouvelle modification de votre page Wiki.

  4. Sélectionnez l’entrée de la dernière livraison (en haut) en sélectionnant le bouton de sélection (...).

  5. Dans la section Headers (En-têtes), vous voyez x-hub-signature. Vous verrez également le code de réponse 200, qui indique que la requête a bien été traitée.

    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>
    

Tester une signature non valide

  1. Dans le portail GitHub, sur la page des webhooks, sélectionnez l’onglet Settings (Paramètres).

  2. Dans la zone de texte Secret, sélectionnez Change Secret (Modifier le secret).

  3. Saisissez une chaîne aléatoire, faites défiler vers le bas, puis sélectionnez Update webhook (Mettre à jour le webhook).

    La clé utilisée par le webhook ne doit plus correspondre à celle attendue par la fonction Azure.

  4. Sélectionnez l’onglet Recent Deliveries (Livraisons récentes).

  5. Sélectionnez l’entrée de la dernière livraison (en haut) en sélectionnant le bouton de sélection (...).

  6. Sélectionnez Redeliver (Relivrer), puis dans la boîte de dialogue Redeliver payload (Relivrer la charge utile) qui s’affiche, sélectionnez Yes, redeliver this payload (Oui, relivrer cette charge utile).

  7. Cette fois-ci, vous verrez le code de réponse 401, qui indique que la requête n’est pas autorisée.

  8. Sélectionnez l’entrée de la dernière livraison (en haut) (redelivery (nouvelle livraison)) en sélectionnant son bouton de sélection (...).

  9. Sélectionnez l’onglet Response (Réponse), puis dans la section Body, vérifiez que le message « Signatures don’t match » (Les signatures ne correspondent pas) s’affiche.