Una vez que tu servidor se configure para recibir cargas útiles, éste escuchará a cualquiera de ellas que se envíe a la terminal que configuraste. Por razones de seguridad, probablemente quieras limitar las solicitudes a aquellas que vengan de GitHub. Hay algunas formas de solucionar esto, por ejemplo, podrías decidir el permitir las solicitudes que vengan de la dirección IP de GitHub, pero una manera mucho más fácil es configurar un token secreto y validar la información.
Las API de REST de los webhooks te permiten administrar webhooks de repositorio, organización y aplicación.. También puedes utilizar la API de REST para cambiar la configuración del webhook. Por ejemplo, puedes modificar la URL de la carga útil, el tipo de contenido, la verificación de SSL, y el secreto. Para obtener más información, consulta:
- API de REST para los webhooks de los repositorios
- API de REST de webhooks de organización
- GitHub App API de REST de Webhooks
Configurar tu token secreto
Necesitarás configurar tu token secreto en dos lugares: GitHub y tu servidor.
Para configurar tu token en GitHub:
- Navega al repositorio en donde configuraste tu webhook.
- Llena la caja de texto del secreto. Utiliza una secuencia aleatoria con entropía alta (por ejemplo, tomando la salida de
ruby -rsecurerandom -e 'puts SecureRandom.hex(20)'
en la terminal). - Da clic en Actualizar Webhook.
Después, configura una variable de ambiente en tu servidor, la cual almacene este token. Por lo general, esto es tan simple como el ejecutar:
$ export SECRET_TOKEN=your_token
¡Jamás preprogrames el token en tu app!
Validar cargas útiles de GitHub
Cuando se configura tu token secreto, GitHub Enterprise Server lo utiliza para crear una firma de hash con cada carga útil. Esta firma de hash se incluye con los encabezados de cada solicitud como X-Hub-Signature-256
.
Nota: Para tener compatibilidad en versiones anteriores, también incluimos el encabezado X-Hub-Signature
que se genera utilizando la función de hash SHA-1. De ser posible, te recomendamos que utilices el encabezado de X-Hub-Signature-256
para mejorar la seguridad. El ejemplo siguiente demuestra cómo utilizar el encabezado X-Hub-Signature-256
.
Por ejemplo, si tienes un servidor básico que escucha a los webhooks, puede configurarse de forma similar a esto:
require 'sinatra'
require 'json'
post '/payload' do
request.body.rewind
push = JSON.parse(request.body.read)
"I got some JSON: #{push.inspect}"
end
La intención es calcular un hash utilizando tu SECRET_TOKEN
, y asegurarse de que el resultado empate con el hash de GitHub Enterprise Server. GitHub Enterprise Server utiliza un resumen hexadecimal de HMAC para calcular el hash, así que podrías reconfigurar tu servidor para que se viera así:
post '/payload' do
request.body.rewind
payload_body = request.body.read
verify_signature(payload_body)
push = JSON.parse(payload_body)
"I got some JSON: #{push.inspect}"
end
def verify_signature(payload_body)
signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), ENV['SECRET_TOKEN'], payload_body)
return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE_256'])
end
Nota: Las cargas útiles de los webhooks pueden contener caracteres en unicode. Si tu implementación de idioma y servidor especifican un cifrado de caracteres, asegúrate de que estés manejando la carga útil como UTF-8.
Tus implementaciones de lenguaje y de servidor pueden diferir de esta muestra de código. Sin embargo, hay varias cosas muy importantes que destacar:
-
Sin importar qué implementación utilices, la firma de hash comenzará con
sha256=
, utilizando la llave de tu token secreto y el cuerpo de tu carga útil. -
No se recomienda utilizar un simple operador de
==
. Un método como el desecure_compare
lleva a cabo una secuencia de comparación de "tiempo constante" que ayuda a mitigar algunos ataques de temporalidad en contra de las operaciones de igualdad habituales.