UNPKG

secure-kit

Version:

Production-grade security + performance toolkit for backend frameworks with OWASP Top 10 compliance

127 lines 5.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FastifyAdapter = void 0; const security_1 = require("../core/security"); const performance_1 = require("../core/performance"); const config_1 = require("../core/config"); class FastifyAdapter { constructor(config) { this.config = config_1.ConfigManager.createConfig(config); this.securityManager = new security_1.SecurityManager(this.config); this.performanceManager = new performance_1.PerformanceManager(this.config); } createPlugin() { return async (fastify, _options) => { // Register main security hooks fastify.addHook('onRequest', async (request, reply) => { const startTime = Date.now(); request.startTime = startTime; // Apply security headers this.securityManager.applySecurityHeaders(reply); // CORS validation const origin = request.headers.origin; if (origin && !this.securityManager.validateCORS(origin, request.method)) { reply.status(403).send({ error: 'CORS policy violation' }); return; } // Rate limiting const clientIp = this.getClientIP(request); const rateLimitInfo = this.securityManager.checkRateLimit(clientIp); if (rateLimitInfo && rateLimitInfo.remaining === 0) { reply.header('Retry-After', rateLimitInfo.retryAfter?.toString() || '60'); reply.status(429).send({ error: 'Rate limit exceeded', retryAfter: rateLimitInfo.retryAfter, }); return; } // Apply rate limit headers if (rateLimitInfo) { reply.header('X-RateLimit-Limit', rateLimitInfo.limit.toString()); reply.header('X-RateLimit-Remaining', rateLimitInfo.remaining.toString()); reply.header('X-RateLimit-Reset', rateLimitInfo.resetTime.toISOString()); } // JWT validation (if Authorization header is present) const authHeader = request.headers.authorization; if (authHeader && authHeader.startsWith('Bearer ')) { const token = authHeader.substring(7); const jwtValidation = this.securityManager.validateJWT(token); if (!jwtValidation.valid) { reply.status(401).send({ error: jwtValidation.error }); return; } request.user = jwtValidation.payload; } }); // Performance monitoring hook fastify.addHook('onSend', async (request, reply, payload) => { const startTime = request.startTime || Date.now(); // Optimize response const optimized = this.performanceManager.optimizeResponse(payload); // Apply caching headers this.performanceManager.applyCachingHeaders(reply, optimized.data); // Record metrics const duration = Date.now() - startTime; const payloadSize = Buffer.isBuffer(optimized.data) ? optimized.data.length : JSON.stringify(optimized.data).length; this.performanceManager.recordMetrics(duration, payloadSize); return optimized.data; }); // Register security routes this.registerSecurityRoutes(fastify); }; } registerSecurityRoutes(fastify) { // CSRF token endpoint if (this.config.security?.csrf?.enabled) { fastify.get('/csrf-token', async (_request, reply) => { const token = this.securityManager.generateCSRFToken(); // Set cookie using headers for basic implementation reply.header('Set-Cookie', `csrf-token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`); return { csrfToken: token }; }); } // Security events endpoint if (this.config.logging?.enabled) { fastify.get('/security-events', async (_request, _reply) => { const events = this.securityManager.getSecurityEvents(); return { events }; }); // Performance metrics endpoint fastify.get('/performance-metrics', async (_request, _reply) => { const metrics = this.performanceManager.getMetrics(); const avgResponseTime = this.performanceManager.getAverageResponseTime(); const avgPayloadSize = this.performanceManager.getAveragePayloadSize(); const memoryUsage = this.performanceManager.getMemoryUsage(); const suggestions = this.performanceManager.getOptimizationSuggestions(); return { metrics: metrics.slice(-100), summary: { averageResponseTime: avgResponseTime, averagePayloadSize: avgPayloadSize, memoryUsage, suggestions, }, }; }); } } // Helper methods getClientIP(request) { return request.ip || request.socket.remoteAddress || 'unknown'; } // Utility methods for external use getSecurityManager() { return this.securityManager; } getPerformanceManager() { return this.performanceManager; } getConfig() { return this.config; } } exports.FastifyAdapter = FastifyAdapter; //# sourceMappingURL=fastify.js.map