Skip to content

Commit f6619d9

Browse files
committed
refactor: 미들웨어로 수정
1 parent 2fe688c commit f6619d9

File tree

4 files changed

+30
-36
lines changed

4 files changed

+30
-36
lines changed

src/controllers/webhook.controller.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { NextFunction, Request, RequestHandler, Response } from 'express';
22
import { EmptyResponseDto, SentryWebhookData } from '@/types';
33
import logger from '@/configs/logger.config';
44
import { sendSlackMessage } from '@/modules/slack/slack.notifier';
5-
import { verifySignature } from '@/utils/verify.util';
65

76
export class WebhookController {
87
private readonly STATUS_EMOJI = {
@@ -17,8 +16,7 @@ export class WebhookController {
1716
next: NextFunction,
1817
): Promise<void> => {
1918
try {
20-
// 시그니처 검증 과정 추가
21-
if (req.body?.action !== "created" || !verifySignature(req)) {
19+
if (req.body?.action !== "created") {
2220
const response = new EmptyResponseDto(true, 'Sentry 웹훅 처리에 실패했습니다', {}, null);
2321
res.status(400).json(response);
2422
return;

src/middlewares/auth.middleware.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import logger from '@/configs/logger.config';
44
import pool from '@/configs/db.config';
55
import { DBError, InvalidTokenError } from '@/exception';
66
import { VelogJWTPayload, User } from '@/types';
7+
import crypto from "crypto";
78

89
/**
910
* 요청에서 토큰을 추출하는 함수
@@ -66,10 +67,36 @@ const verifyBearerTokens = () => {
6667
};
6768
};
6869

70+
/**
71+
* Sentry 웹훅 요청의 시그니처 헤더를 검증합니다.
72+
* HMAC SHA256과 Sentry의 Client Secret를 사용하여 요청 본문을 해시화하고,
73+
* Sentry에서 제공하는 시그니처 헤더와 비교하여 요청의 무결성을 확인합니다.
74+
* @param {Request} request - Express 요청 객체
75+
* @returns {boolean} 헤더가 유효하면 true, 그렇지 않으면 false
76+
*/
77+
function verifySignature(request: Request, res: Response, next: NextFunction) {
78+
try {
79+
if(!process.env.SENTRY_CLIENT_SECRET) throw new Error("SENTRY_CLIENT_SECRET가 env에 없습니다");
80+
const hmac = crypto.createHmac("sha256", process.env.SENTRY_CLIENT_SECRET);
81+
hmac.update(JSON.stringify(request.body), "utf8");
82+
const digest = hmac.digest("hex");
83+
84+
if(digest !== request.headers["sentry-hook-signature"]) {
85+
throw new Error("유효하지 않은 시그니처 헤더입니다.");
86+
}
87+
next();
88+
} catch (error) {
89+
logger.error('시그니처 검증 중 오류가 발생하였습니다. : ', error);
90+
next(error);
91+
}
92+
93+
}
94+
6995
/**
7096
* 사용자 인증을 위한 미들웨어 모음
7197
* @property {Function} verify
7298
*/
7399
export const authMiddleware = {
74100
verify: verifyBearerTokens(),
101+
verifySignature,
75102
};

src/routes/webhook.router.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import express, { Router } from 'express';
22
import { WebhookController } from '@/controllers/webhook.controller';
3+
import { authMiddleware } from '@/middlewares/auth.middleware';
34

45
const router: Router = express.Router();
56

@@ -47,6 +48,6 @@ const webhookController = new WebhookController();
4748
* 500:
4849
* description: 서버 오류
4950
*/
50-
router.post('/webhook/sentry', webhookController.handleSentryWebhook);
51+
router.post('/webhook/sentry', authMiddleware.verifySignature, webhookController.handleSentryWebhook);
5152

5253
export default router;

src/utils/verify.util.ts

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)