""" 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' class Config: """Main configuration loader for VPN Access Server.""" def __init__(self): self.database = self._load_database_config() self.server = self._load_server_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 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") if errors: for error in errors: print(f"Configuration Error: {error}") return False return True # Global configuration instance config = Config()