# 🔒 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:** ```sql -- 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:** ```sql -- 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:** ```sql -- 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:** ```http 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`: ```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:** ```sql 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:** ```bash 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)** ```http 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** ```http 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** ```http 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** ```http 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):** ```env # Rate Limiting (defaults) RATE_LIMIT_DEFAULT=100 RATE_LIMIT_WINDOW=60 # Timestamp Validation (defaults) TIMESTAMP_MAX_AGE=300 ``` ### **Database Configuration:** ```sql -- 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: ```sql -- 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:** ```bash # 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)