mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-15 18:30:39 +09:00
feat(server): add github_hmac and none webhook signing modes
Adds two new webhook trigger signing modes for external provider compatibility: - github_hmac: accepts X-Hub-Signature-256 header with HMAC-SHA256(secret, rawBody), no timestamp prefix. Compatible with GitHub, Sentry, and services following the same standard. - none: no authentication; the 24-char hex publicId in the URL acts as the shared secret. For services that cannot add auth headers. The replay window UI field is hidden when these modes are selected since neither uses timestamp-based replay protection. Closes #1892 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
eefe9f39f1
commit
cd19834fab
5 changed files with 109 additions and 15 deletions
|
|
@ -617,4 +617,72 @@ describeEmbeddedPostgres("routine service live-execution coalescing", () => {
|
|||
expect(run.status).toBe("issue_created");
|
||||
expect(run.linkedIssueId).toBeTruthy();
|
||||
});
|
||||
|
||||
it("accepts GitHub-style X-Hub-Signature-256 with github_hmac signing mode", async () => {
|
||||
const { routine, svc } = await seedFixture();
|
||||
const { trigger, secretMaterial } = await svc.createTrigger(
|
||||
routine.id,
|
||||
{
|
||||
kind: "webhook",
|
||||
signingMode: "github_hmac",
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
const payload = { action: "opened", pull_request: { number: 1 } };
|
||||
const rawBody = Buffer.from(JSON.stringify(payload));
|
||||
const signature = `sha256=${createHmac("sha256", secretMaterial!.webhookSecret)
|
||||
.update(rawBody)
|
||||
.digest("hex")}`;
|
||||
|
||||
const run = await svc.firePublicTrigger(trigger.publicId!, {
|
||||
hubSignatureHeader: signature,
|
||||
rawBody,
|
||||
payload,
|
||||
});
|
||||
|
||||
expect(run.source).toBe("webhook");
|
||||
expect(run.status).toBe("issue_created");
|
||||
});
|
||||
|
||||
it("rejects invalid signature for github_hmac signing mode", async () => {
|
||||
const { routine, svc } = await seedFixture();
|
||||
const { trigger } = await svc.createTrigger(
|
||||
routine.id,
|
||||
{
|
||||
kind: "webhook",
|
||||
signingMode: "github_hmac",
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
const rawBody = Buffer.from(JSON.stringify({ ok: true }));
|
||||
|
||||
await expect(
|
||||
svc.firePublicTrigger(trigger.publicId!, {
|
||||
hubSignatureHeader: "sha256=0000000000000000000000000000000000000000000000000000000000000000",
|
||||
rawBody,
|
||||
payload: { ok: true },
|
||||
}),
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("accepts any request with none signing mode", async () => {
|
||||
const { routine, svc } = await seedFixture();
|
||||
const { trigger } = await svc.createTrigger(
|
||||
routine.id,
|
||||
{
|
||||
kind: "webhook",
|
||||
signingMode: "none",
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
const run = await svc.firePublicTrigger(trigger.publicId!, {
|
||||
payload: { event: "error.created" },
|
||||
});
|
||||
|
||||
expect(run.source).toBe("webhook");
|
||||
expect(run.status).toBe("issue_created");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue