""" Configuration management for VPN Access Server. Handles loading database credentials and system constants from environment variables and configuration files with secure defaults. """ import os from typing import Optional from dataclasses import dataclass @dataclass class DatabaseConfig: """Database connection configuration.""" host: str port: int database: str username: str password: str charset: str = 'utf8mb4' autocommit: bool = False pool_size: int = 5 max_overflow: int = 10 @dataclass class ServerConfig: """VPN Access Server configuration.""" log_level: str = 'INFO' log_file: Optional[str] = '/var/log/openvpn/access-server.log' default_session_limit: int = 28800 # 8 hours in seconds max_session_limit: int = 86400 # 24 hours in seconds timezone: str = 'UTC' @dataclass class EmailConfig: """Email service configuration.""" smtp_host: str smtp_port: int smtp_username: str smtp_password: str smtp_use_tls: bool from_email: str from_name: str @dataclass class EmailConfig: """Email service configuration.""" smtp_host: str smtp_port: int smtp_username: str smtp_password: str smtp_use_tls: bool from_email: str from_name: str class Config: """Main configuration loader for VPN Access Server.""" def __init__(self): self.database = self._load_database_config() self.server = self._load_server_config() self.email = self._load_email_config() def _load_database_config(self) -> DatabaseConfig: """Load database configuration from environment variables.""" return DatabaseConfig( host=os.getenv('DB_HOST', 'localhost'), port=int(os.getenv('DB_PORT', '3306')), database=os.getenv('DB_NAME', 'vpn_access'), username=os.getenv('DB_USER', 'vpn_user'), password=os.getenv('DB_PASSWORD', ''), charset=os.getenv('DB_CHARSET', 'utf8mb4'), autocommit=os.getenv('DB_AUTOCOMMIT', 'false').lower() == 'true', pool_size=int(os.getenv('DB_POOL_SIZE', '5')), max_overflow=int(os.getenv('DB_MAX_OVERFLOW', '10')) ) def _load_server_config(self) -> ServerConfig: """Load server configuration from environment variables.""" return ServerConfig( log_level=os.getenv('LOG_LEVEL', 'INFO').upper(), log_file=os.getenv('LOG_FILE', '/var/log/openvpn/access-server.log'), default_session_limit=int(os.getenv('DEFAULT_SESSION_LIMIT', '28800')), max_session_limit=int(os.getenv('MAX_SESSION_LIMIT', '86400')), timezone=os.getenv('TIMEZONE', 'UTC') ) def _load_email_config(self) -> EmailConfig: """Load email configuration from environment variables.""" return EmailConfig( smtp_host=os.getenv('SMTP_HOST', 'smtp.gmail.com'), smtp_port=int(os.getenv('SMTP_PORT', '587')), smtp_username=os.getenv('SMTP_USERNAME', ''), smtp_password=os.getenv('SMTP_PASSWORD', ''), smtp_use_tls=os.getenv('SMTP_USE_TLS', 'true').lower() == 'true', from_email=os.getenv('SMTP_FROM_EMAIL', 'noreply@yourcompany.com'), from_name=os.getenv('SMTP_FROM_NAME', 'VPN Access Server') ) def validate(self) -> bool: """Validate configuration values.""" errors = [] # Validate database config if not self.database.password: errors.append("DB_PASSWORD is required") if self.database.port < 1 or self.database.port > 65535: errors.append("DB_PORT must be between 1 and 65535") # Validate server config if self.server.log_level not in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']: errors.append("LOG_LEVEL must be one of: DEBUG, INFO, WARNING, ERROR, CRITICAL") if self.server.default_session_limit > self.server.max_session_limit: errors.append("DEFAULT_SESSION_LIMIT cannot exceed MAX_SESSION_LIMIT") # Validate email config if not self.email.smtp_username: errors.append("SMTP_USERNAME is required for email functionality") if not self.email.smtp_password: errors.append("SMTP_PASSWORD is required for email functionality") if self.email.smtp_port < 1 or self.email.smtp_port > 65535: errors.append("SMTP_PORT must be between 1 and 65535") if errors: for error in errors: print(f"Configuration Error: {error}") return False return True # Global configuration instance config = Config()