refactor to remove config_files in favor of db
This commit is contained in:
@@ -19,7 +19,7 @@ from web.models import (
|
||||
ScanCertificate, ScanTLSVersion, Site, ScanSiteAssociation
|
||||
)
|
||||
from web.utils.pagination import paginate, PaginatedResult
|
||||
from web.utils.validators import validate_config_file, validate_scan_status
|
||||
from web.utils.validators import validate_scan_status
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -41,7 +41,7 @@ class ScanService:
|
||||
"""
|
||||
self.db = db_session
|
||||
|
||||
def trigger_scan(self, config_file: str = None, config_id: int = None,
|
||||
def trigger_scan(self, config_id: int,
|
||||
triggered_by: str = 'manual', schedule_id: Optional[int] = None,
|
||||
scheduler=None) -> int:
|
||||
"""
|
||||
@@ -51,8 +51,7 @@ class ScanService:
|
||||
queues the scan for background execution.
|
||||
|
||||
Args:
|
||||
config_file: Path to YAML configuration file (legacy, optional)
|
||||
config_id: Database config ID (preferred, optional)
|
||||
config_id: Database config ID
|
||||
triggered_by: Source that triggered scan (manual, scheduled, api)
|
||||
schedule_id: Optional schedule ID if triggered by schedule
|
||||
scheduler: Optional SchedulerService instance for queuing background jobs
|
||||
@@ -61,106 +60,48 @@ class ScanService:
|
||||
Scan ID of the created scan
|
||||
|
||||
Raises:
|
||||
ValueError: If config is invalid or both/neither config_file and config_id provided
|
||||
ValueError: If config is invalid
|
||||
"""
|
||||
# Validate that exactly one config source is provided
|
||||
if not (bool(config_file) ^ bool(config_id)):
|
||||
raise ValueError("Must provide exactly one of config_file or config_id")
|
||||
from web.models import ScanConfig
|
||||
|
||||
# Handle database config
|
||||
if config_id:
|
||||
from web.models import ScanConfig
|
||||
# Validate config exists
|
||||
db_config = self.db.query(ScanConfig).filter_by(id=config_id).first()
|
||||
if not db_config:
|
||||
raise ValueError(f"Config with ID {config_id} not found")
|
||||
|
||||
# Validate config exists
|
||||
db_config = self.db.query(ScanConfig).filter_by(id=config_id).first()
|
||||
if not db_config:
|
||||
raise ValueError(f"Config with ID {config_id} not found")
|
||||
# Create scan record with config_id
|
||||
scan = Scan(
|
||||
timestamp=datetime.utcnow(),
|
||||
status='running',
|
||||
config_id=config_id,
|
||||
title=db_config.title,
|
||||
triggered_by=triggered_by,
|
||||
schedule_id=schedule_id,
|
||||
created_at=datetime.utcnow()
|
||||
)
|
||||
|
||||
# Create scan record with config_id
|
||||
scan = Scan(
|
||||
timestamp=datetime.utcnow(),
|
||||
status='running',
|
||||
config_id=config_id,
|
||||
title=db_config.title,
|
||||
triggered_by=triggered_by,
|
||||
schedule_id=schedule_id,
|
||||
created_at=datetime.utcnow()
|
||||
)
|
||||
self.db.add(scan)
|
||||
self.db.commit()
|
||||
self.db.refresh(scan)
|
||||
|
||||
self.db.add(scan)
|
||||
self.db.commit()
|
||||
self.db.refresh(scan)
|
||||
logger.info(f"Scan {scan.id} triggered via {triggered_by} with config_id={config_id}")
|
||||
|
||||
logger.info(f"Scan {scan.id} triggered via {triggered_by} with config_id={config_id}")
|
||||
|
||||
# Queue background job if scheduler provided
|
||||
if scheduler:
|
||||
try:
|
||||
job_id = scheduler.queue_scan(scan.id, config_id=config_id)
|
||||
logger.info(f"Scan {scan.id} queued for background execution (job_id={job_id})")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to queue scan {scan.id}: {str(e)}")
|
||||
# Mark scan as failed if job queuing fails
|
||||
scan.status = 'failed'
|
||||
scan.error_message = f"Failed to queue background job: {str(e)}"
|
||||
self.db.commit()
|
||||
raise
|
||||
else:
|
||||
logger.warning(f"Scan {scan.id} created but not queued (no scheduler provided)")
|
||||
|
||||
return scan.id
|
||||
|
||||
# Handle legacy YAML config file
|
||||
# Queue background job if scheduler provided
|
||||
if scheduler:
|
||||
try:
|
||||
job_id = scheduler.queue_scan(scan.id, config_id=config_id)
|
||||
logger.info(f"Scan {scan.id} queued for background execution (job_id={job_id})")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to queue scan {scan.id}: {str(e)}")
|
||||
# Mark scan as failed if job queuing fails
|
||||
scan.status = 'failed'
|
||||
scan.error_message = f"Failed to queue background job: {str(e)}"
|
||||
self.db.commit()
|
||||
raise
|
||||
else:
|
||||
# Validate config file
|
||||
is_valid, error_msg = validate_config_file(config_file)
|
||||
if not is_valid:
|
||||
raise ValueError(f"Invalid config file: {error_msg}")
|
||||
logger.warning(f"Scan {scan.id} created but not queued (no scheduler provided)")
|
||||
|
||||
# Convert config_file to full path if it's just a filename
|
||||
if not config_file.startswith('/'):
|
||||
config_path = f'/app/configs/{config_file}'
|
||||
else:
|
||||
config_path = config_file
|
||||
|
||||
# Load config to get title
|
||||
import yaml
|
||||
with open(config_path, 'r') as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
# Create scan record
|
||||
scan = Scan(
|
||||
timestamp=datetime.utcnow(),
|
||||
status='running',
|
||||
config_file=config_file,
|
||||
title=config.get('title', 'Untitled Scan'),
|
||||
triggered_by=triggered_by,
|
||||
schedule_id=schedule_id,
|
||||
created_at=datetime.utcnow()
|
||||
)
|
||||
|
||||
self.db.add(scan)
|
||||
self.db.commit()
|
||||
self.db.refresh(scan)
|
||||
|
||||
logger.info(f"Scan {scan.id} triggered via {triggered_by}")
|
||||
|
||||
# Queue background job if scheduler provided
|
||||
if scheduler:
|
||||
try:
|
||||
job_id = scheduler.queue_scan(scan.id, config_file=config_file)
|
||||
logger.info(f"Scan {scan.id} queued for background execution (job_id={job_id})")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to queue scan {scan.id}: {str(e)}")
|
||||
# Mark scan as failed if job queuing fails
|
||||
scan.status = 'failed'
|
||||
scan.error_message = f"Failed to queue background job: {str(e)}"
|
||||
self.db.commit()
|
||||
raise
|
||||
else:
|
||||
logger.warning(f"Scan {scan.id} created but not queued (no scheduler provided)")
|
||||
|
||||
return scan.id
|
||||
return scan.id
|
||||
|
||||
def get_scan(self, scan_id: int) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
@@ -614,7 +555,7 @@ class ScanService:
|
||||
'duration': scan.duration,
|
||||
'status': scan.status,
|
||||
'title': scan.title,
|
||||
'config_file': scan.config_file,
|
||||
'config_id': scan.config_id,
|
||||
'json_path': scan.json_path,
|
||||
'html_path': scan.html_path,
|
||||
'zip_path': scan.zip_path,
|
||||
@@ -640,7 +581,7 @@ class ScanService:
|
||||
'duration': scan.duration,
|
||||
'status': scan.status,
|
||||
'title': scan.title,
|
||||
'config_file': scan.config_file,
|
||||
'config_id': scan.config_id,
|
||||
'triggered_by': scan.triggered_by,
|
||||
'created_at': scan.created_at.isoformat() if scan.created_at else None
|
||||
}
|
||||
@@ -783,17 +724,17 @@ class ScanService:
|
||||
return None
|
||||
|
||||
# Check if scans use the same configuration
|
||||
config1 = scan1.get('config_file', '')
|
||||
config2 = scan2.get('config_file', '')
|
||||
same_config = (config1 == config2) and (config1 != '')
|
||||
config1 = scan1.get('config_id')
|
||||
config2 = scan2.get('config_id')
|
||||
same_config = (config1 == config2) and (config1 is not None)
|
||||
|
||||
# Generate warning message if configs differ
|
||||
config_warning = None
|
||||
if not same_config:
|
||||
config_warning = (
|
||||
f"These scans use different configurations. "
|
||||
f"Scan #{scan1_id} used '{config1 or 'unknown'}' and "
|
||||
f"Scan #{scan2_id} used '{config2 or 'unknown'}'. "
|
||||
f"Scan #{scan1_id} used config_id={config1 or 'unknown'} and "
|
||||
f"Scan #{scan2_id} used config_id={config2 or 'unknown'}. "
|
||||
f"The comparison may show all changes as additions/removals if the scans "
|
||||
f"cover different IP ranges or infrastructure."
|
||||
)
|
||||
@@ -832,14 +773,14 @@ class ScanService:
|
||||
'timestamp': scan1['timestamp'],
|
||||
'title': scan1['title'],
|
||||
'status': scan1['status'],
|
||||
'config_file': config1
|
||||
'config_id': config1
|
||||
},
|
||||
'scan2': {
|
||||
'id': scan2['id'],
|
||||
'timestamp': scan2['timestamp'],
|
||||
'title': scan2['title'],
|
||||
'status': scan2['status'],
|
||||
'config_file': config2
|
||||
'config_id': config2
|
||||
},
|
||||
'same_config': same_config,
|
||||
'config_warning': config_warning,
|
||||
|
||||
Reference in New Issue
Block a user