Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

RFC: Dual webhook signatures for migrating signature schemes

オープン
#1,068 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
機能追加
明瞭さ
おおむね明確
活発さ
活発
技術スタック
go

調査の方向性

Start by reviewing the RFC’s proposed compat signature configuration and migration flows, then examine the existing default webhook signature behavior; the issue does not name implementation files or tests. The first scope is default webhook mode, with a migration guide also required. Done means the RFC’s open naming and design questions are resolved and the proposed behavior and scope are agreed.

索引モデルが issue の本文から書いたものです。

説明

Summary

Let a deployment send two webhook signature formats on the same request for a transition period. Operators can then move to Outpost from a webhook system they built themselves or from another provider, or change signature schemes, without breaking receivers' verification code.

Motivation

A receiver's verification code is coupled to the signature format: header names, signed content, encoding, key derivation. Two cases change that format for existing receivers:

  1. Changing the scheme of a running deployment, e.g. moving from a custom template to a different one, or renaming headers.
  2. Moving to Outpost from a previous webhook system, self-built or another provider. Receivers verify that system's headers. Outpost sends its own.

Today both are hard cutovers. Every receiver has to deploy new verification code at the moment the operator flips the config.

Approach

Add a second, optional set of webhook signature config. If it is set, Outpost signs each request twice and sends both sets of headers: the primary signature as today, plus the second one built from the alternative config. If it isn't set, nothing changes.

The second set takes the same options as the primary signature (header name, content template, header template, encoding, algorithm). When configured, it applies to every webhook destination in the deployment, until the operator removes the config.

Naming

The second config set needs a name. Options:

  • DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_HEADER_NAME
  • DESTINATIONS_WEBHOOK_LEGACY_SIGNATURE_HEADER_NAME
  • DESTINATIONS_WEBHOOK_ALT_SIGNATURE_HEADER_NAME
  • DESTINATIONS_WEBHOOK_SIGNATURE_HEADER_NAME_COMPAT (suffix form)
  • DESTINATIONS_WEBHOOK_SIGNATURE_HEADER_NAME_1 (numbered)

The rest of this RFC uses COMPAT as a prefix group (destinations.webhook.compat.* in YAML). The mechanism doesn't depend on the term, and feedback on it is welcome.

Proposal

The second signature set is called the compat signature below.

Operator config
Key Description
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_HEADER_NAME Name of the compat signature header. Setting it enables the feature.
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_CONTENT_TEMPLATE Same semantics as SIGNATURE_CONTENT_TEMPLATE
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_HEADER_TEMPLATE Same semantics as SIGNATURE_HEADER_TEMPLATE
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_ENCODING hex | base64
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_ALGORITHM e.g. hmac-sha256
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_SECRET_ENCODING How the HMAC key is derived from the stored secret: raw (default) | base64 | hex
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_SECRET_PREFIX Prefix stripped from the secret before decoding, e.g. whsec_
DESTINATIONS_WEBHOOK_COMPAT_HEADERS Comma-separated name=template pairs (same shape as OTEL_EXPORTER_OTLP_HEADERS, \, for a literal comma), for companion headers the other scheme requires (ID, timestamp). A plain map in YAML config.

Both signatures use the same destination secret (including previous_secret during rotation) and the same timestamp. Receivers keep their existing secret.

Two of these options are new capabilities:

  • Secret encoding/prefix. The default mode uses the secret string as the HMAC key. Other schemes base64-decode it after a prefix. Without this, one secret can't serve both schemes. For symmetry, the same two options are added to the primary signature (DESTINATIONS_WEBHOOK_SIGNATURE_SECRET_ENCODING / _SECRET_PREFIX).
  • Compat headers. If the previous signature covered values sent in other headers (an event ID, a timestamp in a different format), receivers read those headers to verify it. Compat headers reproduce them under the names and formats receivers expect. Templates receive the same fields as the signature content template, minus the body.
Example: compat signature in Standard Webhooks format
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_HEADER_NAME=webhook-signature
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_CONTENT_TEMPLATE={{.EventID}}.{{.Timestamp.Unix}}.{{.Body}}
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_HEADER_TEMPLATE=v1,{{index .Signatures 0}}{{range slice .Signatures 1}} v1,{{.}}{{end}}
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_ENCODING=base64
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_SECRET_ENCODING=base64
DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_SECRET_PREFIX=whsec_
DESTINATIONS_WEBHOOK_COMPAT_HEADERS=webhook-id={{.EventID}},webhook-timestamp={{.Timestamp.Unix}}

Migration flows

Changing the signature scheme of a running deployment

  1. Copy the current signature settings to the COMPAT_* keys.
  2. Set the new primary scheme. Every request now carries both.
  3. Announce a sunset date. Receivers switch verification.
  4. At sunset, remove the COMPAT_* keys.

Moving to Outpost from a previous webhook system

  1. Set COMPAT_* to the previous scheme.
  2. Create a destination per existing endpoint with its current secret.
  3. Every request carries both signatures until the operator removes the compat config.

Not in scope

Two additions came up during review and are left out until there is a need for them:

  • Limiting which destinations receive it, by a creation cutoff timestamp or a per-destination setting. Open as a follow-up if feedback asks for it.
  • A sunset timestamp that stops the compat signature automatically. Removing the config does the same.

Scope

  • default webhook mode first (#1069). Follow-up (#1072): fold standard mode into the default provider as a preset (fixed templates, base64 encoding, whsec_ secret decoding, fixed header names, whsec_ format enforced on create). Compat then works in both modes with no extra code, and the secret-encoding option lets standard accept existing secrets during a default → standard migration, which its strict validation blocks today.
  • A compat header name that matches a primary header (signature or system headers) is rejected at boot. Compat headers override a destination's custom_headers with the same name.
  • Templates are validated at startup, same as the primary ones.
  • Docs: a "Migrating webhook signatures" guide covering both flows.

Alternatives considered

  • List of N named schemes. Needs structured config, and migrating from more than one scheme at a time isn't a real case. A single slot can grow into a list later.
主要言語
Go
スター
1.1k
フォーク
70
平均マージ
1日 18時間
マージ済み PR(30日)
56

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

hookdeck/outpost のほかの issue

hookdeck/outpost の issue をすべて見る

似ている issue

Go の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。