Files
cloud-server/SECURITY.md
kappa abe052b538 feat: 코드 품질 개선 및 추천 API 구현
## 주요 변경사항

### 신규 기능
- POST /recommend: 기술 스택 기반 인스턴스 추천 API
- 아시아 리전 필터링 (Seoul, Tokyo, Osaka, Singapore)
- 매칭 점수 알고리즘 (메모리 40%, vCPU 30%, 가격 20%, 스토리지 10%)

### 보안 강화 (Security 9.0/10)
- API Key 인증 + constant-time 비교 (타이밍 공격 방어)
- Rate Limiting: KV 기반 분산 처리, fail-closed 정책
- IP Spoofing 방지 (CF-Connecting-IP만 신뢰)
- 요청 본문 10KB 제한
- CORS + 보안 헤더 (CSP, HSTS, X-Frame-Options)

### 성능 최적화 (Performance 9.0/10)
- Generator 패턴: AWS pricing 메모리 95% 감소
- D1 batch 쿼리: N+1 문제 해결
- 복합 인덱스 추가 (migrations/002)

### 코드 품질 (QA 9.0/10)
- 127개 테스트 (vitest)
- 구조화된 로깅 (민감정보 마스킹)
- 상수 중앙화 (constants.ts)
- 입력 검증 유틸리티 (utils/validation.ts)

### Vultr 연동 수정
- relay 서버 헤더: Authorization: Bearer → X-API-Key

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 11:57:35 +09:00

5.4 KiB

Security Implementation

This document describes the authentication, rate limiting, and security measures implemented in the cloud-server API.

API Key Authentication

Overview

All endpoints except /health require API key authentication via the X-API-Key header.

Implementation Details

  • Location: src/middleware/auth.ts
  • Method: Constant-time comparison using SHA-256 hashes
  • Protection: Prevents timing attacks
  • Response: 401 Unauthorized for missing or invalid keys

Usage Example

# Valid request
curl -H "X-API-Key: your-api-key-here" https://api.example.com/instances

# Missing API key
curl https://api.example.com/instances
# Response: 401 Unauthorized

Configuration

Set the API_KEY environment variable in wrangler.toml:

[vars]
API_KEY = "your-secure-api-key"

For production, use secrets instead:

wrangler secret put API_KEY

Rate Limiting

Overview

IP-based rate limiting protects against abuse and ensures fair usage.

Rate Limits by Endpoint

Endpoint Limit Window
/instances 100 requests 1 minute
/sync 10 requests 1 minute
/health No limit -

Implementation Details

  • Location: src/middleware/rateLimit.ts
  • Storage: In-memory Map (suitable for Cloudflare Workers)
  • IP Detection: Uses CF-Connecting-IP header (Cloudflare-specific)
  • Cleanup: Automatic periodic cleanup of expired entries
  • Response: 429 Too Many Requests when limit exceeded

Response Headers

When rate limited, responses include:

  • Retry-After: Seconds until rate limit resets
  • X-RateLimit-Retry-After: Same as Retry-After (for compatibility)

Rate Limit Response Example

{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Please try again later.",
  "retry_after_seconds": 45,
  "timestamp": "2024-01-21T12:00:00.000Z"
}

Security Headers

All responses include the following security headers:

X-Content-Type-Options

X-Content-Type-Options: nosniff

Prevents MIME type sniffing attacks.

X-Frame-Options

X-Frame-Options: DENY

Prevents clickjacking by blocking iframe embedding.

Strict-Transport-Security

Strict-Transport-Security: max-age=31536000

Enforces HTTPS for one year (31,536,000 seconds).

Endpoint Access Control

Public Endpoints

  • /health - No authentication required

Protected Endpoints (Require API Key)

  • /instances - Query instances
  • /sync - Trigger synchronization

Security Best Practices

API Key Management

  1. Never commit API keys to version control
  2. Use Cloudflare Secrets for production:
    wrangler secret put API_KEY
    
  3. Rotate keys regularly (recommended: every 90 days)
  4. Use different keys for development and production

Rate Limit Considerations

  1. Monitor usage to adjust limits as needed
  2. Consider user tiers for different rate limits (future enhancement)
  3. Log rate limit violations for security monitoring

Additional Recommendations

  1. Enable CORS if needed for browser clients
  2. Add request logging for audit trails
  3. Implement API versioning for backward compatibility
  4. Consider JWT tokens for more sophisticated authentication (future enhancement)

Testing Authentication and Rate Limiting

Testing Authentication

# Test missing API key (should fail)
curl -i https://api.example.com/instances

# Test invalid API key (should fail)
curl -i -H "X-API-Key: invalid-key" https://api.example.com/instances

# Test valid API key (should succeed)
curl -i -H "X-API-Key: your-api-key" https://api.example.com/instances

Testing Rate Limiting

# Send multiple requests quickly
for i in {1..150}; do
  curl -H "X-API-Key: your-api-key" https://api.example.com/instances
done
# After 100 requests, should receive 429 Too Many Requests

Testing Security Headers

curl -I https://api.example.com/health
# Should see X-Content-Type-Options, X-Frame-Options, and Strict-Transport-Security

Architecture

Request Flow

1. Request arrives
2. Check if /health endpoint → Skip to step 6
3. Authenticate API key → 401 if invalid
4. Check rate limit → 429 if exceeded
5. Route to handler
6. Add security headers
7. Return response

Middleware Components

src/middleware/
├── auth.ts        # API key authentication
├── rateLimit.ts   # IP-based rate limiting
└── index.ts       # Middleware exports

Performance Impact

Authentication

  • Overhead: ~1-2ms per request (SHA-256 hashing)
  • Optimization: Constant-time comparison prevents timing attacks

Rate Limiting

  • Overhead: <1ms per request (Map lookup)
  • Memory: ~100 bytes per unique IP
  • Cleanup: Automatic periodic cleanup (1% probability per request)

Security Headers

  • Overhead: Negligible (<0.1ms)
  • Memory: ~100 bytes per response

Future Enhancements

Potential improvements for future versions:

  1. JWT Authentication: Stateless token-based auth
  2. Role-Based Access Control: Different permissions per endpoint
  3. API Key Scoping: Limit keys to specific endpoints
  4. Rate Limit Tiers: Different limits for different users
  5. Distributed Rate Limiting: Using Cloudflare Durable Objects
  6. Request Signing: HMAC-based request verification
  7. Audit Logging: Comprehensive security event logging
  8. IP Whitelisting: Allow specific IPs to bypass rate limiting