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:
87
CLAUDE.md
87
CLAUDE.md
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user