我正在尝试让Github Webhook启动我拥有的AWS Lambda。 我弄清楚如何做到这一点的最好方法是使用 AWS API 网关,问题是安全性。
Github Webhooks 只会通过 POST 调用发送一个秘密。
我找不到任何方法让 AWS API 网关来验证此签名。 或者我可以在哪里添加此功能。
我假设我可以编写一个 AWS Lambda 授权方。 但这是不同地方的大量代码,开始看到对serverless
框架的需求。
我不知道在AWS中有什么更简单的设置吗?
来到这里是因为我试图将 Github webhook 与 AWS lambda 集成,并遇到了与 OP 相同的问题。在撰写本文时,我认为最好的解决方案是在主 lambda 中包含验证码,正如其他人所建议的那样。
在 2017 年 9 月的 AWS 计算机博客上:
增强型请求授权方 Lambda 函数接收类似于代理集成的事件对象。它包含有关请求的所有信息,不包括正文。
来源:在 Amazon API Gateway 中使用增强型请求授权方 (amazon.com(
您无法按照 Github 的建议执行 HMAC,因为 AWS 授权方 lambda 不会授予您访问 HTTP 请求正文的权限,而您需要该正文来比较摘要。
这是一种耻辱,因为HMAC似乎是保护响应Webhook的端点的一种非常标准的方法。例如,请参阅这篇博客文章,Webhooks 该做和不该做:我们在集成 +100 API 后学到了什么 (restful.io(。Twitter和Stripe做了类似的事情:
- 保护网络钩子 (twitter.com(
- 检查网络钩子签名(stripe.com(
要使上述方法正常工作,如果您使用的是 API 网关,则需要确保包含哈希签名的标头作为event
参数的一部分转发到 lambda。为此,请按照以下说明操作:如何使用自定义 Lambda 集成通过 Amazon API 网关将自定义标头传递到 AWS Lambda 函数以进行进一步处理?(amazon.com(
我找不到使用 API 网关执行此操作的方法。 我使用(Python(在LAMBDA中进行了验证。
高级概述:使用GITHUB_SECRET计算HMAC签名,然后与从Github传递的签名进行比较。
您可以明显简化,故意冗长以提高可读性。可能有更好的方法,但我找不到。
确保您的 Webhook 已配置为应用程序/json。 希望这对其他人有所帮助。
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