Migrate from file-based configs to database with per-IP site configuration

Major architectural changes:
   - Replace YAML config files with database-stored ScanConfig model
   - Remove CIDR block support in favor of individual IP addresses per site
   - Each IP now has its own expected_ping, expected_tcp_ports, expected_udp_ports
   - AlertRule now uses config_id FK instead of config_file string

   API changes:
   - POST /api/scans now requires config_id instead of config_file
   - Alert rules API uses config_id with validation
   - All config dropdowns fetch from /api/configs dynamically

   Template updates:
   - scans.html, dashboard.html, alert_rules.html load configs via API
   - Display format: Config Title (X sites) in dropdowns
   - Removed Jinja2 config_files loops

   Migrations:
   - 008: Expand CIDRs to individual IPs with per-IP port configs
   - 009: Remove CIDR-related columns
   - 010: Add config_id to alert_rules, remove config_file
This commit is contained in:
2025-11-19 19:40:34 -06:00
parent 034f146fa1
commit 0ec338e252
21 changed files with 2004 additions and 686 deletions

View File

@@ -35,20 +35,7 @@ def dashboard():
Returns:
Rendered dashboard template
"""
import os
# Get list of available config files
configs_dir = '/app/configs'
config_files = []
try:
if os.path.exists(configs_dir):
config_files = [f for f in os.listdir(configs_dir) if f.endswith(('.yaml', '.yml'))]
config_files.sort()
except Exception as e:
logger.error(f"Error listing config files: {e}")
return render_template('dashboard.html', config_files=config_files)
return render_template('dashboard.html')
@bp.route('/scans')
@@ -60,20 +47,7 @@ def scans():
Returns:
Rendered scans list template
"""
import os
# Get list of available config files
configs_dir = '/app/configs'
config_files = []
try:
if os.path.exists(configs_dir):
config_files = [f for f in os.listdir(configs_dir) if f.endswith(('.yaml', '.yml'))]
config_files.sort()
except Exception as e:
logger.error(f"Error listing config files: {e}")
return render_template('scans.html', config_files=config_files)
return render_template('scans.html')
@bp.route('/scans/<int:scan_id>')
@@ -299,7 +273,6 @@ def alert_rules():
Returns:
Rendered alert rules template
"""
import os
from flask import current_app
from web.models import AlertRule
@@ -317,19 +290,7 @@ def alert_rules():
if rules is None:
rules = []
# Get list of available config files
configs_dir = '/app/configs'
config_files = []
try:
if os.path.exists(configs_dir):
config_files = [f for f in os.listdir(configs_dir) if f.endswith(('.yaml', '.yml'))]
config_files.sort()
except Exception as e:
logger.error(f"Error listing config files: {e}")
return render_template(
'alert_rules.html',
rules=rules,
config_files=config_files
rules=rules
)