diff --git a/apps/api/src/routes/github/index.ts b/apps/api/src/routes/github/index.ts index 2dda59f6a..7e28c530b 100644 --- a/apps/api/src/routes/github/index.ts +++ b/apps/api/src/routes/github/index.ts @@ -1,16 +1,19 @@ import type { WorkflowRunEvent } from "@octokit/webhooks-types"; import type { Request, Response } from "express"; import { env } from "@/config.js"; -import { asyncHandler } from "@/types/api.js"; import { Webhooks } from "@octokit/webhooks"; -import { Router } from "express"; +import express, { Router } from "express"; import { logger } from "@ctrlplane/logger"; import { handleWorkflowRunEvent } from "./workflow_run.js"; export const createGithubRouter = (): Router => - Router().post("/webhook", asyncHandler(handleWebhookRequest)); + Router().post( + "/webhook", + express.raw({ type: "application/json" }), + handleWebhookRequest, + ); const getGithubWebhooksObject = (): Webhooks => { const secret = env.GITHUB_WEBHOOK_SECRET; @@ -18,27 +21,29 @@ const getGithubWebhooksObject = (): Webhooks => { return new Webhooks({ secret }); }; -const verifyRequest = async (req: Request): Promise => { +const verifyRequest = async ( + body: Buffer, + signature: string, +): Promise => { const webhooks = getGithubWebhooksObject(); - const signature = req.headers["x-hub-signature-256"]?.toString(); - if (signature == null) return false; - - const { body } = req; - const json = JSON.stringify(body); - return webhooks.verify(json, signature); + return webhooks.verify(body.toString("utf8"), signature); }; const handleWebhookRequest = async (req: Request, res: Response) => { try { - const isVerified = await verifyRequest(req); - if (!isVerified) { + const signature = req.headers["x-hub-signature-256"]?.toString(); + if ( + signature == null || + !(await verifyRequest(req.body as Buffer, signature)) + ) { res.status(401).json({ message: "Unauthorized" }); return; } + const payload = JSON.parse((req.body as Buffer).toString("utf8")); const eventType = req.headers["x-github-event"]?.toString(); if (eventType === "workflow_run") - await handleWorkflowRunEvent(req.body as WorkflowRunEvent); + await handleWorkflowRunEvent(payload as WorkflowRunEvent); res.status(200).json({ message: "OK" }); } catch (error: unknown) { diff --git a/apps/api/src/server.ts b/apps/api/src/server.ts index 6003c7eb2..7b3514744 100644 --- a/apps/api/src/server.ts +++ b/apps/api/src/server.ts @@ -63,7 +63,16 @@ const app = express() .use(cors({ credentials: true })) .use(helmet()) .use(express.urlencoded({ extended: true, limit: "100mb" })) - .use(express.json({ limit: "100mb" })) + .use((req, res, next) => { + if ( + req.path.startsWith("/api/github/webhook") || + req.path.startsWith("/api/tfe/webhook") + ) { + next(); + return; + } + express.json({ limit: "100mb" })(req, res, next); + }) .use(cookieParser()) .use(loggerMiddleware)