Security & Deployment Architecture
Security Architecture
Overview
Comprehensive security strategy implementing defense-in-depth principles across application, infrastructure, and operational layers.
Application Security
1. Authentication & Authorization
// lib/auth/auth-config.ts
export const authConfig = {
providers: [
// OAuth providers
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
// Email magic links
EmailProvider({
server: process.env.EMAIL_SERVER,
from: process.env.EMAIL_FROM,
})
],
session: {
strategy: 'jwt',
maxAge: 30 * 24 * 60 * 60, // 30 days
},
jwt: {
encryption: true,
secret: process.env.JWT_SECRET,
},
callbacks: {
async jwt({ token, user }) {
if (user) {
token.role = user.role
token.permissions = user.permissions
}
return token
},
async session({ session, token }) {
session.user.role = token.role
session.user.permissions = token.permissions
return session
}
}
}
2. Input Validation & Sanitization
// lib/security/validation.ts
import DOMPurify from 'isomorphic-dompurify'
import { z } from 'zod'
export class SecurityValidator {
// XSS Prevention
static sanitizeHTML(input: string): string {
return DOMPurify.sanitize(input, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
ALLOWED_ATTR: ['href', 'target', 'rel']
})
}
// SQL Injection Prevention (parameterized queries)
static sanitizeSQLParam(input: string): string {
return input.replace(/['";\\]/g, '')
}
// Path Traversal Prevention
static sanitizePath(path: string): string {
return path.replace(/\.\./g, '').replace(/^\/+/, '')
}
// CSRF Token Generation
static generateCSRFToken(): string {
return crypto.randomBytes(32).toString('hex')
}
}
// Middleware for request validation
export function validateRequest(schema: z.ZodSchema) {
return async (req: Request) => {
const body = await req.json()
const result = schema.safeParse(body)
if (!result.success) {
throw new ValidationError(result.error)
}
return result.data
}
}
3. API Security
// middleware/api-security.ts
import rateLimit from 'express-rate-limit'
import helmet from 'helmet'
// Rate Limiting Configuration
export const rateLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP',
standardHeaders: true,
legacyHeaders: false,
})
// API-specific rate limits
export const apiLimits = {
chat: rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 10, // 10 messages per minute
}),
contact: rateLimit({
windowMs: 60 * 60 * 1000, // 1 hour
max: 5, // 5 submissions per hour
}),
generate: rateLimit({
windowMs: 60 * 60 * 1000, // 1 hour
max: 20, // 20 generations per hour
})
}
// Security Headers
export const securityHeaders = {
'X-DNS-Prefetch-Control': 'on',
'X-Frame-Options': 'SAMEORIGIN',
'X-Content-Type-Options': 'nosniff',
'Referrer-Policy': 'strict-origin-when-cross-origin',
'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
'Content-Security-Policy': `
default-src 'self';
script-src 'self' 'unsafe-eval' 'unsafe-inline' https://www.googletagmanager.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https: blob:;
font-src 'self';
connect-src 'self' https://api.openai.com https://blog.leadfive138.com;
frame-ancestors 'none';
`.replace(/\s+/g, ' ').trim()
}
4. Secrets Management
// lib/security/secrets.ts
export class SecretsManager {
private static secrets = new Map<string, string>()
static async initialize() {
// Load from environment variables
const requiredSecrets = [
'OPENAI_API_KEY',
'WP_APP_PASSWORD',
'JWT_SECRET',
'ENCRYPTION_KEY'
]
for (const key of requiredSecrets) {
const value = process.env[key]
if (!value) {
throw new Error(`Missing required secret: ${key}`)
}
this.secrets.set(key, value)
}
}
static get(key: string): string {
const secret = this.secrets.get(key)
if (!secret) {
throw new Error(`Secret not found: ${key}`)
}
return secret
}
// Encrypt sensitive data at rest
static async encrypt(data: string): Promise<string> {
const key = this.get('ENCRYPTION_KEY')
const iv = crypto.randomBytes(16)
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv)
const encrypted = Buffer.concat([
cipher.update(data, 'utf8'),
cipher.final()
])
const authTag = cipher.getAuthTag()
return Buffer.concat([iv, authTag, encrypted]).toString('base64')
}
static async decrypt(encryptedData: string): Promise<string> {
const key = this.get('ENCRYPTION_KEY')
const buffer = Buffer.from(encryptedData, 'base64')
const iv = buffer.slice(0, 16)
const authTag = buffer.slice(16, 32)
const encrypted = buffer.slice(32)
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv)
decipher.setAuthTag(authTag)
return decipher.update(encrypted) + decipher.final('utf8')
}
}
Infrastructure Security
1. Network Security
# infrastructure/cloudflare-config.yaml
firewall_rules:
- name: "Block Known Bad IPs"
expression: "(ip.src in $bad_ips)"
action: "block"
- name: "Rate Limit by IP"
expression: "(http.request.uri.path contains \"/api/\")"
action: "challenge"
ratelimit:
threshold: 100
period: 60
- name: "Geo Blocking"
expression: "(ip.geoip.country in {\"XX\" \"YY\"})"
action: "block"
ddos_protection:
enabled: true
sensitivity: "high"
bot_management:
enabled: true
challenge_suspicious: true
block_definitely_automated: true
2. SSL/TLS Configuration
# SSL Configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_stapling_verify on;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
3. Container Security
# Dockerfile security best practices
FROM node:18-alpine AS base
# Run as non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# Dependencies
FROM base AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Builder
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Remove unnecessary files
RUN rm -rf .git .github .env* *.md
# Build
RUN npm run build
# Runner
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
# Copy built application
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/package.json ./
USER nextjs
EXPOSE 3000
CMD ["npm", "start"]
Security Monitoring & Incident Response
1. Security Monitoring Setup
// lib/security/monitoring.ts
export class SecurityMonitor {
private static incidents: SecurityIncident[] = []
static async logSecurityEvent(event: SecurityEvent) {
// Log to security monitoring service
await fetch(process.env.SECURITY_LOG_ENDPOINT, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SECURITY_LOG_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
timestamp: new Date().toISOString(),
event,
environment: process.env.NODE_ENV,
metadata: {
userAgent: event.userAgent,
ip: event.ip,
url: event.url
}
})
})
// Check if incident threshold reached
if (this.isIncident(event)) {
await this.createIncident(event)
}
}
static async createIncident(event: SecurityEvent) {
const incident: SecurityIncident = {
id: crypto.randomUUID(),
timestamp: new Date(),
severity: this.calculateSeverity(event),
type: event.type,
description: event.description,
status: 'open'
}
this.incidents.push(incident)
// Alert security team
await this.alertSecurityTeam(incident)
}
private static calculateSeverity(event: SecurityEvent): 'low' | 'medium' | 'high' | 'critical' {
const severityMap = {
'failed-auth': 'low',
'rate-limit': 'medium',
'sql-injection': 'high',
'xss-attempt': 'high',
'unauthorized-access': 'critical'
}
return severityMap[event.type] || 'medium'
}
}
2. Incident Response Plan
// lib/security/incident-response.ts
export class IncidentResponse {
static async handleIncident(incident: SecurityIncident) {
switch (incident.severity) {
case 'critical':
await this.criticalResponse(incident)
break
case 'high':
await this.highResponse(incident)
break
case 'medium':
await this.mediumResponse(incident)
break
case 'low':
await this.lowResponse(incident)
break
}
}
private static async criticalResponse(incident: SecurityIncident) {
// 1. Immediate containment
await this.blockSuspiciousIP(incident.sourceIP)
// 2. Alert all stakeholders
await this.alertStakeholders(incident, ['security-team', 'cto', 'devops'])
// 3. Enable enhanced monitoring
await this.enableEnhancedMonitoring()
// 4. Create incident report
await this.createIncidentReport(incident)
}
}
Deployment Architecture
Deployment Strategy
1. Multi-Environment Setup
# deployment/environments.yaml
environments:
development:
url: https://dev.leadfive138.com
branch: develop
auto_deploy: true
staging:
url: https://staging.leadfive138.com
branch: staging
auto_deploy: true
approval_required: false
production:
url: https://leadfive138.com
branch: main
auto_deploy: false
approval_required: true
rollback_enabled: true
2. CI/CD Pipeline
# .github/workflows/deploy.yml
name: Deploy Pipeline
on:
push:
branches: [main, staging, develop]
pull_request:
branches: [main]
jobs:
# Security Scanning
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Snyk Security Scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: $
- name: Run SAST Analysis
uses: github/super-linter@v4
env:
DEFAULT_BRANCH: main
GITHUB_TOKEN: $
# Build & Test
build:
needs: security
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm run test:ci
- name: Build application
run: npm run build
env:
NEXT_PUBLIC_WP_URL: $
- name: Run E2E tests
run: npm run test:e2e
# Deploy to Vercel
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: $
vercel-org-id: $
vercel-project-id: $
vercel-args: '--prod'
- name: Purge CDN Cache
run: |
curl -X POST "https://api.cloudflare.com/client/v4/zones/$/purge_cache" \
-H "Authorization: Bearer $" \
-H "Content-Type: application/json" \
--data '{"purge_everything":true}'
- name: Run Smoke Tests
run: npm run test:smoke
env:
PRODUCTION_URL: https://leadfive138.com
3. Deployment Configuration
// deployment/vercel.json
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/next"
}
],
"routes": [
{
"src": "/api/(.*)",
"headers": {
"cache-control": "no-cache, no-store, must-revalidate"
}
},
{
"src": "/(.*)",
"headers": {
"cache-control": "public, max-age=3600, s-maxage=3600"
}
}
],
"env": {
"NEXT_PUBLIC_WP_URL": "@wp_url",
"OPENAI_API_KEY": "@openai_api_key",
"WP_APP_PASSWORD": "@wp_app_password"
},
"functions": {
"app/api/ai/chat/route.ts": {
"maxDuration": 30
},
"app/api/ai/generate/route.ts": {
"maxDuration": 60
}
}
}
Blue-Green Deployment
1. Deployment Process
// scripts/blue-green-deploy.ts
export class BlueGreenDeployment {
async deploy() {
// 1. Deploy to green environment
const greenDeployment = await this.deployToGreen()
// 2. Run health checks
const healthCheck = await this.runHealthChecks(greenDeployment.url)
if (!healthCheck.passed) {
await this.rollback(greenDeployment)
throw new Error('Health checks failed')
}
// 3. Gradual traffic shift
await this.shiftTraffic([
{ percentage: 10, duration: 300 }, // 10% for 5 minutes
{ percentage: 50, duration: 600 }, // 50% for 10 minutes
{ percentage: 100, duration: 0 } // 100% permanently
])
// 4. Monitor metrics
await this.monitorDeployment()
// 5. Cleanup old deployment
await this.cleanupBlueEnvironment()
}
async rollback(deployment: Deployment) {
// Immediate rollback process
await this.shiftTraffic([{ percentage: 0, duration: 0 }])
await this.notifyTeam('Deployment rolled back', deployment)
}
}
Database Migration Strategy
1. Migration Scripts
// scripts/migrate.ts
export class DatabaseMigration {
async migrate() {
const migrations = await this.getPendingMigrations()
for (const migration of migrations) {
try {
await this.backup()
await this.runMigration(migration)
await this.verify(migration)
await this.recordMigration(migration)
} catch (error) {
await this.rollbackMigration(migration)
throw error
}
}
}
async backup() {
// Create database backup before migration
const timestamp = new Date().toISOString()
const backupName = `backup-${timestamp}.sql`
await exec(`mysqldump -h ${DB_HOST} -u ${DB_USER} -p${DB_PASS} ${DB_NAME} > ${backupName}`)
await this.uploadToS3(backupName)
}
}
Monitoring & Alerting
1. Application Monitoring
// lib/monitoring/app-monitor.ts
export class ApplicationMonitor {
static initializeMonitoring() {
// Performance monitoring
if (typeof window !== 'undefined') {
this.trackWebVitals()
this.trackUserInteractions()
this.trackErrors()
}
// Server monitoring
if (typeof window === 'undefined') {
this.trackAPIMetrics()
this.trackServerResources()
}
}
static trackWebVitals() {
// Core Web Vitals
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
this.sendMetric({
name: entry.name,
value: entry.startTime,
type: 'web-vital'
})
}
}).observe({ entryTypes: ['largest-contentful-paint', 'first-input', 'layout-shift'] })
}
}
2. Infrastructure Monitoring
# monitoring/alerts.yaml
alerts:
- name: "High Error Rate"
condition: "error_rate > 5%"
duration: "5m"
severity: "critical"
channels: ["slack", "pagerduty"]
- name: "Slow Response Time"
condition: "response_time_p95 > 3000ms"
duration: "10m"
severity: "warning"
channels: ["slack"]
- name: "Memory Usage High"
condition: "memory_usage > 85%"
duration: "5m"
severity: "warning"
channels: ["slack", "email"]
- name: "SSL Certificate Expiry"
condition: "ssl_days_remaining < 30"
severity: "warning"
channels: ["email"]
Disaster Recovery
1. Backup Strategy
# backup/strategy.yaml
backups:
database:
frequency: "daily"
retention: "30 days"
locations:
- "s3://leadfive-backups/database/"
- "glacier://leadfive-archive/database/"
files:
frequency: "weekly"
retention: "90 days"
locations:
- "s3://leadfive-backups/files/"
configurations:
frequency: "on-change"
retention: "unlimited"
locations:
- "git"
- "s3://leadfive-backups/configs/"
2. Recovery Procedures
// scripts/disaster-recovery.ts
export class DisasterRecovery {
async executeRecoveryPlan(incident: Incident) {
const plan = this.getRecoveryPlan(incident.type)
for (const step of plan.steps) {
try {
await this.executeStep(step)
await this.verifyStep(step)
await this.logProgress(step)
} catch (error) {
await this.escalate(step, error)
}
}
}
getRecoveryPlan(type: string): RecoveryPlan {
const plans = {
'data-loss': this.dataLossRecovery,
'service-outage': this.serviceOutageRecovery,
'security-breach': this.securityBreachRecovery
}
return plans[type] || this.genericRecovery
}
}
Document Version: 1.0
Date: 2025-08-05
Status: Security & Deployment Architecture