[IMP] runbot_merge: logging around webhook body & signature

The signature validation code seems correct, but there are validation
failure in production, increase logging around webhook requests to
try and diagnose things better:

- dump the *entire* body to the github_requests logfile
- add the received & computed signatures to the log error
This commit is contained in:
Xavier Morel 2024-02-12 10:19:53 +01:00
parent 65c303a750
commit 5d615bd733

View File

@ -96,28 +96,33 @@ class MergebotController(Controller):
secret = env['runbot_merge.repository'].search([ secret = env['runbot_merge.repository'].search([
('name', '=', repo), ('name', '=', repo),
]).project_id.secret ]).project_id.secret.strip()
if secret: if secret:
signature = 'sha256=' + hmac.new(secret.encode(), req.get_data(), hashlib.sha256).hexdigest() signature = 'sha256=' + hmac.new(secret.encode(), req.get_data(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, req.headers.get('X-Hub-Signature-256', '')): if not hmac.compare_digest(signature, req.headers.get('X-Hub-Signature-256', '')):
_logger.warning("Ignored hook %s with incorrect signature", _logger.warning(
req.headers.get('X-Github-Delivery')) "Ignored hook %s with incorrect signature: got %s expected %s",
req.headers.get('X-Github-Delivery'),
req.headers.get('X-Hub-Signature-256'),
signature,
)
return werkzeug.exceptions.Forbidden() return werkzeug.exceptions.Forbidden()
sentry_sdk.set_context('webhook', request.jsonrequest) sentry_sdk.set_context('webhook', request.jsonrequest)
return c(env, request.jsonrequest) return c(env, request.jsonrequest)
def _format(self, request): def _format(self, request):
return """<= {r.method} {r.full_path} return """{r.method} {r.full_path}
{headers} {headers}
{body} {body}
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\
""".format( """.format(
r=request, r=request,
headers='\n'.join( headers='\n'.join(
'\t%s: %s' % entry for entry in request.headers.items() '\t%s: %s' % entry for entry in request.headers.items()
), ),
body=utils.shorten(request.get_data(as_text=True).strip(), 400) body=request.get_data(as_text=True),
) )
def handle_pr(env, event): def handle_pr(env, event):