Exercício – Proteger conteúdos do webhook com um segredo

Concluído

Neste exercício, você protegerá o conteúdo do webhook com um segredo e aprenderá a validar se os conteúdos são realmente do GitHub usando a Função do Azure.

Obter a chave para a sua Função do Azure

  1. No portal do Azure, retorne para seu Aplicativo de Funções criado no primeiro exercício do módulo.

  2. No painel de menu esquerdo, em Functions, selecione Functions. O painel Funções aparece para o seu aplicativo de funções.

  3. Selecione o HttpTrigger1 que você criou. O painel HtttpTrigger1 é exibido para a sua função.

  4. No painel de menu esquerdo, em Desenvolvedor, selecione Código + Teste. O painel Codificar + Testar é exibido para sua função.

  5. No arquivo JavaScript index.js da função, adicione uma referência à biblioteca crypto-js no início do arquivo, acima da instrução module.exports.

    const Crypto = require('crypto');
    
  6. Na barra de menus superior, selecione Salvar. O painel Logs é exibido na parte inferior do painel.

  7. No painel de menu esquerdo, em Desenvolvedor, selecione Chaves de Função. O painel Chaves de Função é exibido para a sua função.

  8. Na coluna Valor, selecione o link Mostrar valor.

  9. Selecione o ícone Copiar para área de transferência e salve essa chave para uso na próxima etapa.

  10. No painel de menu esquerdo, em Desenvolvedor, selecione Código + Teste. O painel Codificar + Testar é exibido para sua função.

  11. No bloco de código, após a instrução context.log, adicione o código a seguir. Substitua <chave padrão> pela chave padrão que você acabou de copiar na área de transferência:

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

    Esse código calcula o hash da chave usando o mesmo mecanismo que o GitHub.

  12. Adicione outro const que precede sha1= ao início da chave para que corresponda ao formato do x-hub-signature no cabeçalho da solicitação. Adicione o seguinte código à sua função.

    const shaSignature = `sha1=${signature}`;
    
  13. Adicione o seguinte código para recuperar a assinatura do GitHub do cabeçalho da solicitação:

    const gitHubSignature = req.headers['x-hub-signature'];
    
  14. Compare as duas cadeias de caracteres. Se elas corresponderem, processe a solicitação da seguinte maneira:

    if (!shaSignature.localeCompare(gitHubSignature)) {
        // Existing code
        if (req.body.pages[0].title) {
            ...
        }
        else {
            ...
        }
    }
    
  15. Se as cadeias de caracteres não corresponderem, retorne uma resposta HTTP 401 (Não Autorizado), com uma mensagem informando o remetente de que as assinaturas não correspondem.

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

    A função concluída deve ter esta aparência:

    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. Na barra de menus superior, selecione Salvar. O painel Logs é exibido mostrando a instrução Conectado.

Atualizar o segredo do webhook

  1. Alterne para sua conta do GitHub no portal do GitHub.

  2. Selecione seu repositório.

  3. Na barra de menus superior, selecione Configurações. O painel Configurações é exibido.

  4. Na barra lateral, escolha Webhooks. O painel Webhooks é exibido.

  5. Selecione Edit (Editar) ao lado de seu webhook.

  6. Na caixa de texto Segredo, insira a chave padrão de sua função que você salvou anteriormente neste exercício.

  7. Role para a parte inferior da página e selecione Atualizar webhook. O painel Webhooks/Gerenciar webhooks é exibido.

Teste o webhook e a Função do Azure

  1. Selecione a guia Entregas Recentes.

  2. Selecione a entrada de entrega mais recente (superior) selecionando o botão de reticências ().

  3. Selecione Redeliver (Entregar Novamente). Na caixa de diálogo Entregar o conteúdo novamente? que aparece, selecione Sim, entregar novamente esse conteúdo.

    Essa ação simula que você está editando sua página Wiki novamente.

  4. Selecione a entrada de entrega mais recente (superior) selecionando o botão de reticências ().

  5. Na seção Cabeçalhos, você verá o x-hub-signature. Você também verá que o código de resposta é 200, indicando que a solicitação foi processada com êxito.

    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>
    

Testar uma assinatura inválida

  1. No portal do GitHub, na página webhooks, selecione a guia Configurações.

  2. Na caixa de teste Segredo, selecione Alterar Segredo.

  3. Insira uma cadeia de caracteres aleatória, role para baixo e selecione Update webhook (Atualizar webhook).

    A chave usada pelo webhook não deve mais corresponder ao esperado pela função do Azure.

  4. Selecione a guia Entregas Recentes.

  5. Selecione a entrada de entrega mais recente (superior) selecionando o botão de reticências ().

  6. Selecione Entregar novamente e, na caixa de diálogo Entregar o conteúdo novamente? que aparece, selecione Sim, entregar novamente esse conteúdo.

  7. Neste momento, você verá que o código de resposta é 401, que indica que a solicitação não foi autorizada.

  8. Selecione a entrada de entrega (re-entrega) mais recente (superior) selecionando o respectivo botão de reticências ().

  9. Selecione a guia Resposta e, na seção Corpo, verifique se a mensagem "As assinaturas não correspondem" aparece.