使用事件网格事件架构的终结点验证

Webhook 是从 Azure 事件网格接收事件的多种方式之一。 当新事件准备就绪时,事件网格服务会向已配置的终结点 POST HTTP 请求,并在请求正文中包含该事件信息。

与众多支持 Webhook 的其他服务一样,事件网格需要你证明对 Webhook 的所有权,然后才能开始向该终结点传送事件。 此要求可防止恶意用户用大量事件淹没你的终结点。

通过事件网格事件验证终结点

如果使用以下 Azure 服务中的任何一项,Azure 基础结构将自动进行此验证:

如果使用其他任何类型的终结点(例如基于 HTTP 触发器的 Azure 函数),终结点代码需要参与事件网格的验证握手。 事件网格支持通过两种方式来验证订阅。

  • 同步握手:在创建事件订阅时,事件网格会将一个订阅验证事件发送到终结点。 此事件的架构与任何其他事件网格事件类似。 此事件的数据部分包括一个 validationCode 属性。 你的应用程序会确认验证请求是否针对预期的事件订阅,并在响应中同步返回验证码。 所有事件网格版本都支持此握手机制。

  • 异步握手:在某些情况下,无法在响应中同步返回 validationCode。 例如,如果使用非 Microsoft 服务(如 ZapierIFTTT),则无法以编程方式使用验证码进行响应。

    事件网格支持手动验证握手。 如果你在创建事件订阅时使用的 SDK 或工具使用了 API 版本 2018-05-01-preview 或更高版本,则事件网格将在订阅验证事件的数据部分中发送 validationUrl 属性。 若要完成握手,请在事件数据中找到该 URL 并向其发送一个 GET 请求。 你可以使用 REST 客户端或 Web 浏览器。

    提供的 URL 的有效期为 10 分钟。 在该时间内,事件订阅的预配状态为 AwaitingManualAction。 如果在 10 分钟内未完成手动验证,则配置状态被设为 Failed。 你将必须在开始手动验证之前重新创建事件订阅。

    此身份验证机制还要求 Webhook 终结点返回 HTTP 状态代码 200,这样它就知道验证事件的 POST 已被接受,然后它就可以进入手动验证模式。 换句话说,如果终结点返回 200,但没有同步返回验证响应,则模式将转换为手动验证模式。 如果在 10 分钟内验证 URL 收到一个 GET 请求,则将验证握手视为成功。

注意

不支持使用自签名证书进行验证。 请改为使用商业证书颁发机构 (CA) 颁发的签名证书。

验证详细信息

  • 在创建/更新事件订阅时,事件网格会将一个订阅验证事件发送到目标终结点。
  • 事件包含标头值 aeg-event-type: SubscriptionValidation
  • 事件正文具有与其他事件网格事件相同的架构。
  • 事件的 eventType 属性为 Microsoft.EventGrid.SubscriptionValidationEvent
  • 该事件的 data 属性包括一个 validationCode 属性,其中含有随机生成的字符串。 例如,validationCode: acb13…
  • 事件数据还包括 validationUrl 属性,其中包含用于手动验证订阅的 URL。
  • 该数组仅包含验证事件。 你回显验证代码后,事件网格会以单独的请求发送其他事件。
  • 事件网格数据平面 SDK 包含对应订阅验证事件数据和订阅验证响应的类。

以下示例显示了 SubscriptionValidationEvent 示例:

[
  {
    "id": "2d1781af-3a4c-4d7c-bd0c-e34b19da4e66",
    "topic": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "subject": "",
    "data": {
      "validationCode": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6",
      "validationUrl": "https://rp-chinanorth2.eventgrid.azure.cn:553/eventsubscriptions/myeventsub/validate?id=0000000000-0000-0000-0000-00000000000000&t=2022-10-28T04:23:35.1981776Z&apiVersion=2018-05-01-preview&token=1A1A1A1A"
    },
    "eventType": "Microsoft.EventGrid.SubscriptionValidationEvent",
    "eventTime": "2022-10-28T04:23:35.1981776Z",
    "metadataVersion": "1",
    "dataVersion": "1"
  }
]

为证明终结点所有权,请在 validationResponse 属性中回显验证代码,如下例所示:

{
  "validationResponse": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6"
}

执行下列步骤之一:

  • 你必须返回 HTTP 200 OK 响应状态代码。 HTTP 202 Accepted 未被识别为有效的事件网格订阅验证响应。 必须在 30 秒内完成 HTTP 请求。 如果未在 30 秒内完成操作,那么操作将被取消,并在 5 秒后重试。 如果所有尝试都失败,则会将其视为验证握手错误。

    应用程序已准备好处理并返回验证代码,这表明你创建了事件订阅并预期接收该事件。 假设不支持握手验证,而黑客知道了应用程序 URL。 黑客可以使用应用程序的 URL 创建主题和事件订阅,并通过发送大量事件开始对应用程序执行 DoS 攻击。 握手验证可防止发生这种情况。

    假设已在应用中实现了验证,因为你创建了自己的事件订阅。 即使黑客使用应用 URL 创建事件订阅,验证请求事件的正确实现也会检查请求中的 aeg-subscription-name 标头,以确定它是你识别的事件订阅。

    即使在正确的握手实现之后,黑客也可以通过复制看似来自事件网格的请求来淹没应用程序 (它已验证事件订阅) 。 若要防止这一点,必须使用 Microsoft Entra 身份验证保护 Webhook。 有关详细信息,请参阅将事件传送到 Microsoft Entra 保护的终结点

  • 另外,还可以通过将 GET 请求发送到验证 URL 来手动验证订阅。 事件订阅将一直处于挂起状态,直到得到验证。 验证 URL 使用端口 553。 如果防火墙规则阻止端口 553,则需要更新规则才能成功进行手动握手。

    在订阅验证事件的验证中,如果确定它不是预期事件的事件订阅,则不会返回 200 响应或根本不返回响应。 因此,验证将失败。

有关处理订阅验证握手的示例,请参阅 C# 示例

请参阅以下文章,了解如何排查事件订阅验证问题:排查事件订阅验证问题