Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Github Webhooks secret with AWS API Gateway

I am trying to have a Github Webhook launch an AWS Lambda I have. The best way I can figure out how to do that is to use AWS API Gateway, the issue is security.

Github Webhooks will only send a secret with the POST call.

I can't find any way to have AWS API Gateway to verify this signature. Or where I can add this functionality.

I assume I can write an AWS Lambda Authorizer. But this is a lot of code in different places, starting to see the need for serverless framework.

Any easier setup within AWS I do not know about for this?

like image 632
Kyle Calica-St Avatar asked Sep 26 '19 00:09

Kyle Calica-St


2 Answers

Came here because I was trying to integrate a Github webhook with AWS lambda and ran into the same problem as the OP. At the time of writing I believe the best solution is to include verification code in the main lambda, as others have suggested.

On the AWS Computer Blog from September 2017:

Enhanced request authorizer Lambda functions receive an event object that is similar to proxy integrations. It contains all of the information about a request, excluding the body.

Source: Using Enhanced Request Authorizers in Amazon API Gateway (amazon.com)

You can't perform HMAC as recommended by Github, because AWS authorizer lambdas don't give you access to the body of the HTTP request, which you need in order to compare digests.

This is a shame, because HMAC seems to be a pretty standard way of securing an endpoint that responds to a webhook. See for example this blog post, Webhooks do’s and dont’s: what we learned after integrating +100 APIs (restful.io). Twitter and Stripe do something similar:

  • Securing webhooks (twitter.com)
  • Checking Webhook Signatures(stripe.com)

To make the approach described above work, if you're using API Gateway you'll need to make sure that the header that contains the hash signature is forwarded as part of the event argument to the lambda. To do that, follow these instructions: How do I pass custom headers through Amazon API Gateway to an AWS Lambda function using custom Lambda integration for further processing? (amazon.com)

like image 113
Oscar Barlow Avatar answered Sep 19 '22 14:09

Oscar Barlow


I couldn't find a way to do this with API Gateway. I validated within the LAMBDA using (Python).

High level overview : Calculate HMAC signature with GITHUB_SECRET then compare to the signature passed from Github.

You can obviously simplify, intentionally verbose for readability. There may be better ways, but I couldn't find one.

Make sure your Webhook is configured for application/json. Hopefully this helps someone else.

import logging
import json
import hmac
import hashlib
import re
from urllib.parse import unquote

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

GITHUB_SECRET = 'SECRET FROM GITHUB CONSOLE'


def lambda_handler(event, context):
    logger.info("Lambda execution starting up...")

    incoming_signature = re.sub(r'^sha1=', '', event['headers']['X-Hub-Signature'])
    incoming_payload = unquote(re.sub(r'^payload=', '', event['body']))
    calculated_signature = calculate_signature(GITHUB_SECRET, incoming_payload.encode('utf-8'))

    if incoming_signature != calculated_signature:
        logger.error('Unauthorized attempt')
        return {
            'statusCode': 403,
            'body': json.dumps('Forbidden')
        }

    logger.info('Request successfully authorized')

    # do stuff in Lambda

    return {
        'statusCode': 200,
        'body': json.dumps(f'Work in progress')
    }


def calculate_signature(github_signature, githhub_payload):
    signature_bytes = bytes(github_signature, 'utf-8')
    digest = hmac.new(key=signature_bytes, msg=githhub_payload, digestmod=hashlib.sha1)
    signature = digest.hexdigest()
    return signature
like image 38
Justin Daines Avatar answered Sep 22 '22 14:09

Justin Daines