feat(security): API 키 보호, CORS 강화, Rate Limiting KV 전환
보안 개선: - API 키 하드코딩 제거 (NAMECHEAP_API_KEY_INTERNAL) - CORS 정책: * → hosting.anvil.it.com 제한 - /health 엔드포인트 DB 정보 노출 방지 - Rate Limiting 인메모리 Map → Cloudflare KV 전환 - 분산 환경 일관성 보장 - 재시작 후에도 유지 - 자동 만료 (TTL) 문서: - CLAUDE.md Security 섹션 추가 - KV Namespace 설정 가이드 추가 - 배포/마이그레이션 가이드 추가 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
39
src/index.ts
39
src/index.ts
@@ -52,8 +52,8 @@ async function handleMessage(
|
||||
const text = message.text;
|
||||
const telegramUserId = message.from.id.toString();
|
||||
|
||||
// Rate Limiting 체크
|
||||
if (!checkRateLimit(telegramUserId)) {
|
||||
// Rate Limiting 체크 (KV 기반)
|
||||
if (!(await checkRateLimit(env.RATE_LIMIT_KV, telegramUserId))) {
|
||||
await sendMessage(
|
||||
env.BOT_TOKEN,
|
||||
chatId,
|
||||
@@ -276,31 +276,12 @@ export default {
|
||||
return Response.json(result);
|
||||
}
|
||||
|
||||
// 헬스 체크
|
||||
// 헬스 체크 (공개 - 최소 정보만)
|
||||
if (url.pathname === '/health') {
|
||||
try {
|
||||
const userCount = await env.DB
|
||||
.prepare('SELECT COUNT(*) as cnt FROM users')
|
||||
.first<{ cnt: number }>();
|
||||
|
||||
const summaryCount = await env.DB
|
||||
.prepare('SELECT COUNT(*) as cnt FROM summaries')
|
||||
.first<{ cnt: number }>();
|
||||
|
||||
return Response.json({
|
||||
status: 'ok',
|
||||
timestamp: new Date().toISOString(),
|
||||
stats: {
|
||||
users: userCount?.cnt || 0,
|
||||
summaries: summaryCount?.cnt || 0,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
return Response.json({
|
||||
status: 'error',
|
||||
error: String(error),
|
||||
}, { status: 500 });
|
||||
}
|
||||
return Response.json({
|
||||
status: 'ok',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
// Deposit API - 잔액 조회 (namecheap-api 전용)
|
||||
@@ -478,9 +459,9 @@ export default {
|
||||
|
||||
// 문의 폼 API (웹사이트용)
|
||||
if (url.pathname === '/api/contact' && request.method === 'POST') {
|
||||
// CORS preflight는 OPTIONS에서 처리
|
||||
// CORS: hosting.anvil.it.com만 허용
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Origin': 'https://hosting.anvil.it.com',
|
||||
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type',
|
||||
};
|
||||
@@ -549,7 +530,7 @@ export default {
|
||||
if (url.pathname === '/api/contact' && request.method === 'OPTIONS') {
|
||||
return new Response(null, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Origin': 'https://hosting.anvil.it.com',
|
||||
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user