Files
api-wipay/FAST_API_HARDENING.md

9.3 KiB

🔒 FAST API HARDENING - IMPLEMENTASI

Status: HARDENING COMPLETED


🎯 FITUR HARDENING YANG DIIMPLEMENTASI

1. Rate Limiting

Implementasi:

  • File-based rate limiting (bisa upgrade ke Redis nanti)
  • Default: 100 requests per minute per API key
  • Configurable per API key via database
  • Response headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
  • Return 429 Too Many Requests jika limit exceeded

Location:

  • src/Helpers/RateLimitHelper.php - checkRateLimit()
  • src/Middleware/ApiKeyMiddleware.php - Rate limit check

Configuration:

-- Set custom rate limit per API key
UPDATE api_keys 
SET rate_limit_per_minute = 200, 
    rate_limit_window = 60 
WHERE id = 1;

Response Headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1705123456
Retry-After: 45

2. IP Whitelist

Implementasi:

  • IP whitelist per API key (optional)
  • Support single IP atau CIDR notation (e.g., 192.168.1.0/24)
  • Support comma-separated atau JSON array
  • Default: disabled (allow all IPs)
  • Return 403 Forbidden jika IP tidak di whitelist

Location:

  • src/Helpers/RateLimitHelper.php - checkIpWhitelist()
  • src/Middleware/ApiKeyMiddleware.php - IP whitelist check

Configuration:

-- Enable IP whitelist untuk API key
UPDATE api_keys 
SET enable_ip_whitelist = 1,
    ip_whitelist = '192.168.1.100,10.0.0.0/24,203.0.113.0/24'
WHERE id = 1;

-- Atau menggunakan JSON array
UPDATE api_keys 
SET enable_ip_whitelist = 1,
    ip_whitelist = '["192.168.1.100", "10.0.0.0/24"]'
WHERE id = 1;

Format IP Whitelist:

  • Single IP: 192.168.1.100
  • CIDR: 192.168.1.0/24
  • Comma-separated: 192.168.1.100,10.0.0.0/24
  • JSON array: ["192.168.1.100", "10.0.0.0/24"]

3. API Key Expiration

Implementasi:

  • Expiration date per API key (optional)
  • Check expiration saat validation
  • Return 401 Unauthorized jika expired
  • Default: never expires (NULL)

Location:

  • src/Helpers/RateLimitHelper.php - checkExpiration()
  • src/Middleware/ApiKeyMiddleware.php - Expiration check

Configuration:

-- Set expiration date untuk API key
UPDATE api_keys 
SET expires_at = '2025-12-31 23:59:59'
WHERE id = 1;

-- Remove expiration (never expires)
UPDATE api_keys 
SET expires_at = NULL
WHERE id = 1;

4. Request Timestamp Validation

Implementasi:

  • Optional timestamp validation untuk prevent replay attack
  • Default: disabled (log only, tidak block)
  • Max age: 5 minutes (300 seconds)
  • Header: X-Timestamp atau body timestamp

Location:

  • src/Helpers/RateLimitHelper.php - validateTimestamp()
  • src/Middleware/ApiKeyMiddleware.php - Timestamp validation

Usage:

POST /fast/check_bill
X-Client-ID: your_client_id
X-Client-Secret: your_client_secret
X-Timestamp: 1705123456

Enable Blocking: Uncomment line di ApiKeyMiddleware.php:

// Uncomment untuk block request dengan timestamp invalid
return ResponseHelper::json($handler->handle($request)->withStatus(400), 
    ['status' => 'error', 'message' => $timestampValidation['message']], 400);

📊 DATABASE SCHEMA

New Columns di api_keys Table:

ALTER TABLE api_keys 
ADD COLUMN rate_limit_per_minute INT DEFAULT 100,
ADD COLUMN rate_limit_window INT DEFAULT 60,
ADD COLUMN enable_ip_whitelist TINYINT(1) DEFAULT 0,
ADD COLUMN ip_whitelist TEXT NULL,
ADD COLUMN expires_at DATETIME NULL,
ADD COLUMN last_used_at DATETIME NULL,
ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

-- Indexes
CREATE INDEX idx_api_keys_expires_at ON api_keys(expires_at);
CREATE INDEX idx_api_keys_is_active ON api_keys(is_active);
CREATE INDEX idx_api_keys_last_used_at ON api_keys(last_used_at);

Migration Script:

php run_hardening_migration.php

Note: Script akan otomatis skip jika column/index sudah ada.


🔧 IMPLEMENTATION DETAILS

1. Rate Limiting

Storage:

  • File-based cache di storage/cache/rate_limit/
  • Format: JSON file per API key
  • Auto cleanup saat window expired

Algorithm:

  • Sliding window per API key
  • Counter reset setiap window seconds
  • Thread-safe dengan file locking

Upgrade Path:

  • Bisa upgrade ke Redis/Memcached nanti
  • Interface sudah abstract, cukup ganti storage layer

2. IP Whitelist

Validation:

  • Check exact match untuk single IP
  • Check CIDR range untuk subnet
  • Support IPv4 (IPv6 bisa ditambahkan nanti)

Performance:

  • Cached di memory per request
  • No database query jika disabled

3. API Key Expiration

Validation:

  • Check saat API key validation
  • Compare dengan current timestamp
  • Log expired attempts

4. Request Timestamp

Validation:

  • Optional (tidak block by default)
  • Max age: 5 minutes
  • Prevent replay attack

🛡️ SECURITY FLOW

Request → ApiKeyMiddleware
    ↓
1. Extract X-Client-ID & X-Client-Secret
    ↓
2. Validate API Key (database)
    ↓
3. ✅ Check Expiration (if column exists)
    ↓
4. ✅ Check IP Whitelist (if enabled)
    ↓
5. ✅ Check Rate Limit (always enabled)
    ↓
6. ✅ Validate Timestamp (optional, log only)
    ↓
7. Attach API Key to Request
    ↓
8. Add Rate Limit Headers to Response
    ↓
Response

📝 USAGE EXAMPLES

Example 1: Basic API Call (No Hardening Config)

POST /fast/check_bill
X-Client-ID: ABC_1234567890_abcdef
X-Client-Secret: 64_char_hex_string

Response:
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1705123456

Example 2: Rate Limit Exceeded

POST /fast/check_bill
X-Client-ID: ABC_1234567890_abcdef
X-Client-Secret: 64_char_hex_string

Response:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705123456
Retry-After: 45

{
    "status": "error",
    "message": "Rate limit exceeded. Please try again later.",
    "retry_after": 45
}

Example 3: IP Not Whitelisted

POST /fast/check_bill
X-Client-ID: ABC_1234567890_abcdef
X-Client-Secret: 64_char_hex_string
IP: 192.168.1.200 (not in whitelist)

Response:
HTTP/1.1 403 Forbidden

{
    "status": "error",
    "message": "IP address not allowed"
}

Example 4: API Key Expired

POST /fast/check_bill
X-Client-ID: ABC_1234567890_abcdef
X-Client-Secret: 64_char_hex_string

Response:
HTTP/1.1 401 Unauthorized

{
    "status": "error",
    "message": "API key has expired"
}

⚙️ CONFIGURATION

Environment Variables (Optional):

# Rate Limiting (defaults)
RATE_LIMIT_DEFAULT=100
RATE_LIMIT_WINDOW=60

# Timestamp Validation (defaults)
TIMESTAMP_MAX_AGE=300

Database Configuration:

-- Set custom rate limit
UPDATE api_keys 
SET rate_limit_per_minute = 200,
    rate_limit_window = 60
WHERE id = 1;

-- Enable IP whitelist
UPDATE api_keys 
SET enable_ip_whitelist = 1,
    ip_whitelist = '192.168.1.100,10.0.0.0/24'
WHERE id = 1;

-- Set expiration
UPDATE api_keys 
SET expires_at = '2025-12-31 23:59:59'
WHERE id = 1;

🔍 MONITORING & LOGGING

API Logs:

Semua hardening events di-log ke api_logs table:

-- View rate limit events
SELECT * FROM api_logs 
WHERE status = 'rate_limited' 
ORDER BY created_at DESC;

-- View IP blocked events
SELECT * FROM api_logs 
WHERE status = 'ip_blocked' 
ORDER BY created_at DESC;

-- View expired API keys
SELECT * FROM api_logs 
WHERE status = 'expired' 
ORDER BY created_at DESC;

Rate Limit Cache Files:

# View rate limit cache
ls -la storage/cache/rate_limit/

# Clear rate limit cache (emergency)
rm -rf storage/cache/rate_limit/*

BACKWARD COMPATIBILITY

Semua hardening features adalah backward compatible:

  1. Rate Limiting - Always enabled, default 100 req/min
  2. IP Whitelist - Default disabled (allow all IPs)
  3. Expiration - Default never expires (NULL)
  4. Timestamp - Optional, tidak block by default

Jika column belum ada di database:

  • Hardening features akan skip gracefully
  • Error di-log tapi request tetap di-allow (fail open)
  • Tidak ada breaking changes untuk existing API keys

🚀 UPGRADE PATH

Future Enhancements:

  1. Redis/Memcached untuk Rate Limiting

    • Ganti file-based cache dengan Redis
    • Better performance untuk high traffic
  2. Advanced Rate Limiting

    • Per-endpoint rate limiting
    • Burst protection
    • Adaptive rate limiting
  3. Request Signature (HMAC)

    • HMAC SHA256 signature validation
    • Prevent request tampering
    • Replay attack protection
  4. API Key Rotation

    • Automatic key rotation
    • Grace period untuk old keys
    • Notification sebelum expiration

📋 CHECKLIST

  • Rate Limiting implemented
  • IP Whitelist implemented
  • API Key Expiration implemented
  • Request Timestamp validation implemented
  • Database migration script created
  • Backward compatible (fail open)
  • Error handling & logging
  • Response headers added
  • Documentation created

Status: HARDENING COMPLETED

Level Security: ENHANCED (dari basic ke hardened)

Production Ready: YES (backward compatible)