diff --git a/.env.example b/.env.example index ae3ccd6a..c3b41639 100644 --- a/.env.example +++ b/.env.example @@ -31,6 +31,12 @@ DB_POOL_MAX=20 DB_CONNECTION_TIMEOUT=5000 DB_IDLE_TIMEOUT=30000 +# Database SSL Configuration (Required in production) +# Path to CA certificate file for TLS verification +# In production, this must be set to enable secure certificate validation +# Example: /etc/ssl/certs/ca-bundle.crt or /path/to/ca.pem +DB_SSL_CA= + # SMS Integration (#448) # Provider selection: twilio | sns | vonage (default: twilio) SMS_PROVIDER=twilio diff --git a/src/lib/db/pool.ts b/src/lib/db/pool.ts index f1fc9dd8..dfa312fc 100644 --- a/src/lib/db/pool.ts +++ b/src/lib/db/pool.ts @@ -13,12 +13,38 @@ import { retryWithBackoff } from '@/utils/errorUtils'; * - Query queueing during reconnect windows */ +/** + * Validate DB_SSL_CA is provided in production + */ +function validateSSLConfig(): void { + if (process.env.NODE_ENV === 'production' && !process.env.DB_SSL_CA) { + throw new Error( + 'DB_SSL_CA environment variable is required in production. ' + + 'This should contain the path to your CA certificate file.', + ); + } +} + +// Validate on module load +validateSSLConfig(); + +const getSSLConfig = () => { + if (process.env.NODE_ENV === 'production') { + return { + rejectUnauthorized: true, + ca: process.env.DB_SSL_CA, + }; + } + // Allow unverified certificates in development + return false; +}; + const DB_CONFIG: PoolConfig = { connectionString: process.env.DATABASE_URL, max: parseInt(process.env.DB_POOL_MAX || '20', 10), connectionTimeoutMillis: parseInt(process.env.DB_CONNECTION_TIMEOUT || '5000', 10), idleTimeoutMillis: parseInt(process.env.DB_IDLE_TIMEOUT || '30000', 10), - ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false, + ssl: getSSLConfig(), }; type CircuitState = 'CLOSED' | 'OPEN';