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:
kappa
2026-01-19 15:20:14 +09:00
parent 6d4fd7f22f
commit 4eb5bbd3d3
11 changed files with 1277 additions and 66 deletions

View File

@@ -82,12 +82,22 @@ npm run chat
npm run chat "날씨 알려줘"
```
**KV Namespace 생성 (최초 1회):**
```bash
# Rate Limiting용 KV Namespace 생성
wrangler kv:namespace create RATE_LIMIT_KV
# 출력된 id를 wrangler.toml의 [[kv_namespaces]] 섹션에 입력
```
**Secrets 설정:**
```bash
wrangler secret put BOT_TOKEN # Telegram Bot Token
wrangler secret put WEBHOOK_SECRET # Webhook 검증용
wrangler secret put OPENAI_API_KEY # OpenAI API 키
wrangler secret put NAMECHEAP_API_KEY # namecheap-api 래퍼 인증 키
wrangler secret put NAMECHEAP_API_KEY_INTERNAL # Namecheap API 키 (내부용)
wrangler secret put BRAVE_API_KEY # Brave Search API 키
wrangler secret put DEPOSIT_API_SECRET # Deposit API 인증 키
```
**Webhook 설정:**
@@ -176,6 +186,7 @@ curl https://telegram-summary-bot.kappa-d8e.workers.dev/webhook-info
| **AI가 도구 호출 안 함** | 키워드 미인식 | 시스템 프롬프트 + 도구 description에 키워드 추가 |
| **예치금 최소 금액 제한** | Agent 프롬프트 문제 | Deposit Agent 프롬프트 수정 (OpenAI API) |
| **다른 사용자 응답 없음** | DB 작업 try-catch 누락 | `index.ts:handleMessage` 전체 try-catch 적용 (2026-01 수정) |
| **CORS 오류 (웹사이트 문의)** | 허용된 Origin 아님 | `hosting.anvil.it.com`만 허용됨 |
### 디버깅 명령어
```bash
@@ -188,6 +199,68 @@ wrangler d1 execute telegram-conversations --command "SELECT * FROM users LIMIT
---
## Security
### Endpoint Security
**공개 엔드포인트:**
| 엔드포인트 | 보안 수준 | 설명 |
|-----------|----------|------|
| `/health` | 최소 정보만 | status, timestamp만 반환 (DB 정보 미노출) |
| `/webhook-info` | BOT_TOKEN 필요 | Telegram Webhook 상태 조회 |
| `/setup-webhook` | BOT_TOKEN + WEBHOOK_SECRET 필요 | Webhook 설정 |
**인증 필요 엔드포인트:**
| 엔드포인트 | 인증 방식 | 권한 |
|-----------|----------|------|
| `/webhook` | Telegram Secret Token | Telegram만 호출 가능 |
| `/api/deposit/*` | X-API-Key 헤더 | namecheap-api 전용 |
| `/api/test` | WEBHOOK_SECRET | 테스트 전용 |
| `/api/contact` | CORS | hosting.anvil.it.com만 |
**CORS 정책:**
```typescript
// 문의 폼 API (POST /api/contact)
'Access-Control-Allow-Origin': 'https://hosting.anvil.it.com' // 특정 도메인만 허용
'Access-Control-Allow-Methods': 'POST, OPTIONS'
'Access-Control-Allow-Headers': 'Content-Type'
```
**Rate Limiting (Cloudflare KV 기반):**
- 사용자별 메시지 제한 (30 requests / 60초)
- KV Namespace: `RATE_LIMIT_KV` (`wrangler.toml`)
- 인스턴스 간 공유, 재시작 후 유지
- 자동 만료 (TTL), 분산 환경 일관성 보장
- 과도한 요청 시 경고 메시지 + 차단
### Health Check 정책
**이전 (보안 취약):**
```json
{
"status": "ok",
"timestamp": "...",
"stats": {
"users": 123, // DB 테이블 정보 노출
"summaries": 456 // 민감한 통계 노출
}
}
```
**현재 (보안 강화):**
```json
{
"status": "ok",
"timestamp": "2026-01-19T12:34:56.789Z" // 최소 정보만
}
```
**상세 정보 필요 시:**
- 별도 인증된 Admin 엔드포인트 추가 검토 (미구현)
- 또는 Cloudflare Dashboard의 Analytics 활용
---
## Architecture
**Message Flow:**
@@ -214,7 +287,7 @@ Telegram Webhook → Security Validation → Command/Message Router
| `openai-service.ts` | AI 응답 + Function Calling | `generateResponse()`, `executeFunctionCall()` |
| `summary-service.ts` | 프로필 시스템 | `updateSummary()`, `getConversationContext()` |
| `deposit-agent.ts` | 예치금 함수 (코드 직접 처리) | `executeDepositFunction()` |
| `security.ts` | Webhook 보안 | `validateWebhook()`, `checkRateLimit()` |
| `security.ts` | Webhook 보안, Rate Limiting (KV) | `validateWebhook()`, `checkRateLimit()` |
| `commands.ts` | 봇 명령어 | `handleCommand()` |
| `telegram.ts` | Telegram API | `sendMessage()`, `sendTypingAction()` |
@@ -393,6 +466,18 @@ case 'new_tool':
| `BRAVE_API_KEY` | - | Brave Search API 키 (wrangler secret) |
| `DEPOSIT_API_SECRET` | - | Deposit API 인증 키 (namecheap-api용, wrangler secret) |
**KV Namespaces:**
| Binding | 설명 | 생성 명령 |
|---------|------|----------|
| `RATE_LIMIT_KV` | Rate Limiting 저장소 | `wrangler kv:namespace create RATE_LIMIT_KV` |
**Bindings:**
| Binding | 타입 | 용도 |
|---------|------|------|
| `DB` | D1 Database | 사용자/메시지/예치금 데이터 |
| `AI` | Workers AI | OpenAI 폴백용 |
| `RATE_LIMIT_KV` | KV Namespace | 사용자별 Rate Limiting (30 req/60s) |
---
## External Integrations