6

我正在尝试让 Github Webhook 启动我拥有的 AWS Lambda。我能弄清楚如何做到这一点的最好方法是使用 AWS API Gateway,问题是安全性。

Github Webhooks 只会通过 POST 调用发送一个秘密。

我找不到任何方法让 AWS API Gateway 验证此签名。或者我可以在哪里添加此功能。

我假设我可以编写一个AWS Lambda Authorizer。但这是在不同地方的大量代码,开始看到对serverless框架的需求。

我不知道在 AWS 中有什么更简单的设置吗?

4

2 回答 2

5

来到这里是因为我试图将 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 做了类似的事情:

为了使上述方法有效,如果您使用的是 API Gateway,您需要确保将包含哈希签名的标头作为event参数的一部分转发给 lambda。为此,请按照以下说明操作:如何使用自定义 Lambda 集成将自定义标头通过 Amazon API Gateway 传递到 AWS Lambda 函数以进行进一步处理?(亚马逊网站)

于 2019-11-08T14:07:31.773 回答
4

我找不到使用 API Gateway 执行此操作的方法。我使用(Python)在 LAMBDA 中进行了验证。

高级概述:使用 GITHUB_SECRET 计算 HMAC 签名,然后与从 Github 传递的签名进行比较。

您显然可以简化,故意冗长以提高可读性。可能有更好的方法,但我找不到。

确保为 application/json 配置了 Webhook。希望这对其他人有帮助。

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
于 2019-09-30T19:37:49.800 回答