Ejercicio: Protección de las cargas de webhook con un secreto
En este ejercicio, protegerá la carga de webhook con un secreto y aprenderá a validar que las cargas de GitHub son realmente de GitHub mediante una función de Azure Functions.
Obtención de la clave para la función de Azure
En Azure Portal, vaya a la aplicación de funciones que ha creado antes.
En el panel Aplicación de Funciones, seleccione su Aplicación de Funciones bajo Functions en el panel central.
Seleccione la instancia de HttpTrigger1 que ha creado. Aparecerá el panel HtttpTrigger1 de la función.
En el panel de menús izquierdo, en Desarrollador, seleccione Código y prueba. Aparece el panel Código y prueba para la función.
En el index.js archivo JavaScript de la función, agregue una referencia a la biblioteca crypto-js al principio del archivo, encima de la
module.exports
instrucción .const Crypto = require('crypto');
En la barra de menús superior, seleccione Guardar. El panel Registros aparece en la parte inferior del panel.
En el panel de menús de la izquierda, en Programador, seleccione Claves de función. Aparece el panel Claves de función para la función.
En la columna Valor , seleccione el vínculo Mostrar valor .
Seleccione el icono Copiar en el Portapapeles y guarde esta clave para usarla en el paso siguiente.
En el panel de menús izquierdo, en Desarrollador, seleccione Código y prueba. Aparece el panel Código y prueba para la función.
En el bloque de código, después de la instrucción
context.log
, agregue el código siguiente. Reemplace <la clave> predeterminada por la clave predeterminada que acaba de copiar en el Portapapeles:const hmac = Crypto.createHmac("sha1", "<default key>"); const signature = hmac.update(JSON.stringify(req.body)).digest('hex');
Este código calcula el hash de la clave utilizando el mismo mecanismo que GitHub.
Agregue otro
const
que anteceda asha1=
al principio de la clave, para que coincida con el formato dex-hub-signature
en el encabezado de solicitud. Agregue el siguiente código a la función.const shaSignature = `sha1=${signature}`;
Agregue el código siguiente para recuperar la firma de GitHub del encabezado de solicitud:
const gitHubSignature = req.headers['x-hub-signature'];
Compare las dos cadenas. Si coinciden, procese la solicitud del modo siguiente:
if (!shaSignature.localeCompare(gitHubSignature)) { // Existing code if (req.body.pages[0].title) { ... } else { ... } }
Si las cadenas no coinciden, se devuelve una respuesta HTTP 401 (no autorizado), con un mensaje que indica al emisor que las firmas no coinciden.
if (!shaSignature.localeCompare(gitHubSignature)) { ... } else { context.res = { status: 401, body: "Signatures don't match" }; }
Este es el aspecto que debería tener la función completada:
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" }; } };
En la barra de menús superior, seleccione Guardar. El panel Registros aparece con una instrucción Connected! .
Actualización del secreto del webhook
Cambie a la cuenta de GitHub en el portal de GitHub.
Seleccione el repositorio.
En la barra de menús superior, seleccione Configuración. Aparece el panel Configuración .
En la barra lateral, seleccione Webhooks. Aparece el panel Webhooks .
Seleccione Editar junto al webhook.
En el cuadro de texto Secreto , escriba la clave predeterminada de la función que guardó anteriormente en este ejercicio.
Desplácese hacia abajo hasta la parte inferior de la página y seleccione Actualizar webhook. Aparece el panel Webhooks/Administrar webhooks .
Prueba del webhook y la función de Azure
Seleccione la pestaña Entregas recientes .
Seleccione la entrada de entrega más reciente (superior) seleccionando el botón de puntos suspensivos (...).
Seleccione Volver a entregar. En el cuadro de diálogo ¿Volver a entregar la carga? que aparece, seleccione Sí, volver a entregar esta carga.
Esta acción simula que edita de nuevo la página de wiki.
Seleccione la entrada de entrega más reciente (superior) seleccionando el botón de puntos suspensivos (...).
En la sección Encabezados, verá
x-hub-signature
. También verá que el código de respuesta es 200, lo que indica que la solicitud se procesó correctamente.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>
Prueba de una firma no válida
En el portal de GitHub, en la página webhooks, seleccione el botón Editar del webhook.
En el cuadro Secreto , seleccione Cambiar secreto.
Escriba una cadena aleatoria, desplácese hacia abajo y seleccione Actualizar webhook.
La clave utilizada por el webhook ya no debe coincidir con lo esperado por la función de Azure.
Seleccione la pestaña Entregas recientes .
Seleccione la entrada de entrega más reciente (superior) seleccionando el botón de puntos suspensivos (...).
Seleccione Volver a entregar y, en el cuadro de diálogo Carga útil para volver a entregar que aparece, seleccione Sí, vuelva a enviar esta carga útil.
Esta vez, verá que el código de respuesta es 401, lo que indica que la solicitud no se ha autorizado.
Seleccione la entrada de entrega más reciente (superior) (redelivery) por medio del botón de puntos suspensivos (...).
Seleccione la pestaña Respuesta y, en la sección Cuerpo , compruebe que aparece el mensaje "Las firmas no coinciden".