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?
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:
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)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With