Skip to main content
Publicamos actualizaciones para la documentación con frecuencia y es posible que aún se esté traduciendo esta página. Para obtener la información más reciente, consulta la documentación en inglés.

Securing your webhooks (Protección de sus webhooks)

Asegúrate de que tu servidor está recibiendo únicamente las solicitudes de GitHub esperadas por razones de seguridad.

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.

Puedes usar la API de REST para administrar repositorios, organizaciones y webhooks de aplicaciones. Puedes enumerar las entregas de webhook para un webhook, o bien obtener y volver a entregar una entrega individual para un webhook, que se puede integrar en una aplicación o servicio externos. También puedes usar la API 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 más información, consulte:

Configurar tu token secreto

Necesitarás configurar tu token secreto en dos lugares: GitHub y tu servidor.

Para configurar tu token en GitHub:

  1. Desplácese hasta el repositorio donde está configurando el webhook.

  2. En el nombre del repositorio, haz clic en Configuración. Si no puedes ver la pestaña "Configuración", selecciona el menú desplegable y, a continuación, haz clic en Configuración.

    Captura de pantalla de un encabezado de repositorio en el que se muestran las pestañas. La pestaña "Configuración" está resaltada con un contorno naranja oscuro.

  3. En la barra lateral de la izquierda, haz clic en Webhooks.

  4. Junto al webhook, haz clic en Editar.

  5. En el campo "Secreto", escribe una cadena aleatoria con entropía elevada. Puedes generar una cadena con ruby -rsecurerandom -e 'puts SecureRandom.hex(20)' en el terminal, por ejemplo.

  6. Haga clic en Update Webhook (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

Nunca codifique de forma rígida el token en la aplicación.

Validación de las cargas de GitHub

Cuando se configura tu token secreto, GitHub Enterprise Cloud 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 la compatibilidad con versiones anteriores, también se incluye el encabezado x-hub-signature que se genera mediante la función de hash SHA-1. Si es posible, se recomienda usar el encabezado x-hub-signature-256 para mejorar la seguridad. En los ejemplos siguientes se muestra cómo usar el encabezado x-hub-signature-256.

Debes calcular un hash mediante tu SECRET_TOKEN y asegurarte de que el resultado coincide con el hash de GitHub Enterprise Cloud. GitHub Enterprise Cloud usa un código hash hexadecimal HMAC para calcular el hash.

Nota: Las cargas de webhook pueden contener caracteres 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.

Las implementaciones de lenguaje y servidor pueden diferir de los ejemplos siguientes. Sin embargo, hay varias cosas muy importantes que destacar:

  • Con independencia de la implementación que use, la firma de hash comienza con sha256= y se utiliza la clave del token secreto y el cuerpo de la carga.

  • ==No se recomiendausar un operador sin formato. Un método como secure_compare realiza una comparación de cadenas de "tiempo constante", lo que ayuda a mitigar determinados ataques de tiempo contra operadores de igualdad convencionales.

Ejemplo de Ruby

Por ejemplo, puedes definir la siguiente función verify_signature:

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

Después, puedes llamarla cuando recibas una carga de webhook:

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

Ejemplo de Python

Por ejemplo, puedes definir la siguiente función verify_signature y llamarla cuando recibas una carga de webhook:

import hashlib
import hmac
def verify_signature(payload_body, secret_token, signature_header):
    """Verify that the payload was sent from GitHub by validating SHA256.
    
    Raise and return 403 if not authorized.
    
    Args:
        payload_body: original request body to verify (request.body())
        secret_token: GitHub app webhook token (WEBHOOK_SECRET)
        signature_header: header received from GitHub (x-hub-signature-256)
    """
    if not signature_header:
        raise HTTPException(status_code=403, detail="x-hub-signature-256 header is missing!")
    hash_object = hmac.new(secret_token.encode('utf-8'), msg=payload_body, digestmod=hashlib.sha256)
    expected_signature = "sha256=" + hash_object.hexdigest()
    if not hmac.compare_digest(expected_signature, signature_header):
        raise HTTPException(status_code=403, detail="Request signatures didn't match!")