using Microsoft.Extensions.Options; namespace LittleShop.Services; /// /// Validates critical configuration settings on startup to prevent security issues /// public class ConfigurationValidationService { private readonly IConfiguration _configuration; private readonly IWebHostEnvironment _environment; private readonly ILogger _logger; public ConfigurationValidationService( IConfiguration configuration, IWebHostEnvironment environment, ILogger logger) { _configuration = configuration; _environment = environment; _logger = logger; } /// /// Validates all critical configuration settings on startup /// Throws exceptions for security-critical misconfigurations /// public void ValidateConfiguration() { _logger.LogInformation("🔍 Validating application configuration..."); // JWT validation is critical in production, optional in development/testing if (_environment.IsProduction() || !string.IsNullOrEmpty(_configuration["Jwt:Key"])) { ValidateJwtConfiguration(); } else if (_environment.IsDevelopment()) { _logger.LogWarning("⚠️ JWT validation skipped in development. Configure Jwt:Key for production readiness."); } ValidateSilverPayConfiguration(); ValidateProductionSafeguards(); ValidateEnvironmentConfiguration(); _logger.LogInformation("✅ Configuration validation completed successfully"); } private void ValidateJwtConfiguration() { var jwtKey = _configuration["Jwt:Key"]; if (string.IsNullOrEmpty(jwtKey)) { throw new InvalidOperationException("🚨 CRITICAL: JWT Key not configured. Set Jwt:Key in appsettings.json"); } // Check for the old hardcoded key if (jwtKey.Contains("ThisIsASuperSecretKey")) { throw new InvalidOperationException("🚨 CRITICAL: Default JWT key detected. Generate a new secure key!"); } // Require minimum key length for security if (jwtKey.Length < 32) { throw new InvalidOperationException("🚨 CRITICAL: JWT key too short. Must be at least 32 characters."); } _logger.LogInformation("✅ JWT configuration validated"); } private void ValidateSilverPayConfiguration() { var baseUrl = _configuration["SilverPay:BaseUrl"]; var apiKey = _configuration["SilverPay:ApiKey"]; if (string.IsNullOrEmpty(baseUrl)) { throw new InvalidOperationException("🚨 CRITICAL: SilverPay BaseUrl not configured"); } if (string.IsNullOrEmpty(apiKey)) { throw new InvalidOperationException("🚨 CRITICAL: SilverPay ApiKey not configured"); } // Check for test/mock indicators in production if (_environment.IsProduction()) { if (baseUrl.Contains("localhost") || baseUrl.Contains("127.0.0.1")) { throw new InvalidOperationException("🚨 CRITICAL: SilverPay configured with localhost in production!"); } if (apiKey.Contains("test") || apiKey.Contains("mock") || apiKey.Contains("demo")) { _logger.LogWarning("⚠️ WARNING: SilverPay API key contains test/mock indicators in production"); } } _logger.LogInformation("✅ SilverPay configuration validated"); } private void ValidateProductionSafeguards() { // Ensure no mock services can be accidentally enabled var mockServiceConfig = _configuration.GetSection("SilverPay").GetChildren() .Where(x => x.Key.ToLower().Contains("mock") || x.Key.ToLower().Contains("test")) .ToList(); if (mockServiceConfig.Any()) { foreach (var config in mockServiceConfig) { _logger.LogWarning("⚠️ Found mock/test configuration: {Key} = {Value}", config.Key, config.Value); } } // In production, absolutely no mock configurations should exist if (_environment.IsProduction()) { var useMockService = _configuration.GetValue("SilverPay:UseMockService", false); if (useMockService) { throw new InvalidOperationException("🚨 CRITICAL: Mock service enabled in production! Set SilverPay:UseMockService to false"); } // Check for any configuration that might enable testing/mocking var dangerousConfigs = new[] { "Testing:Enabled", "Mock:Enabled", "Development:MockPayments", "Debug:MockServices" }; foreach (var configKey in dangerousConfigs) { if (_configuration.GetValue(configKey, false)) { throw new InvalidOperationException($"🚨 CRITICAL: Dangerous test configuration enabled in production: {configKey}"); } } } _logger.LogInformation("✅ Production safeguards validated"); } private void ValidateEnvironmentConfiguration() { // Log current environment for verification _logger.LogInformation("🌍 Environment: {Environment}", _environment.EnvironmentName); // Validate database connection var connectionString = _configuration.GetConnectionString("DefaultConnection"); if (string.IsNullOrEmpty(connectionString)) { throw new InvalidOperationException("🚨 CRITICAL: Database connection string not configured"); } // Check for development database in production if (_environment.IsProduction() && connectionString.Contains("littleshop.db")) { _logger.LogWarning("⚠️ WARNING: Using SQLite database in production. Consider PostgreSQL/SQL Server for production."); } _logger.LogInformation("✅ Environment configuration validated"); } }