165 lines
5.6 KiB
Python
165 lines
5.6 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import time
|
|
import logging
|
|
from datetime import datetime, timedelta
|
|
from cve_handler import CVEHandler
|
|
import config
|
|
|
|
logging.basicConfig(
|
|
level=config.LOG_LEVEL,
|
|
format=config.LOG_FORMAT
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def incremental_update():
|
|
|
|
logger.info("=" * 80)
|
|
logger.info(f"Starting incremental update at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
logger.info("=" * 80)
|
|
|
|
try:
|
|
handler = CVEHandler()
|
|
days_back = getattr(config, 'SCHEDULER_UPDATE_DAYS', 7)
|
|
|
|
updated_count = 0
|
|
failed_count = 0
|
|
total_new_cves = 0
|
|
|
|
for vendor in config.VENDORS:
|
|
if not vendor.get('use_cpe'):
|
|
logger.debug(f"Skipping {vendor['name']} (CPE disabled)")
|
|
continue
|
|
|
|
try:
|
|
logger.info(f"Updating {vendor['name']}...")
|
|
|
|
new_cves = handler.fetch_cve_from_nvd(
|
|
keywords=vendor.get('keywords', []),
|
|
vendor_config=vendor,
|
|
days_back=days_back
|
|
)
|
|
|
|
if new_cves:
|
|
handler.save_cves_to_cache(new_cves, vendor['code'])
|
|
logger.info(f" ✓ {vendor['name']}: Added {len(new_cves)} new CVEs")
|
|
total_new_cves += len(new_cves)
|
|
updated_count += 1
|
|
else:
|
|
logger.info(f" ✓ {vendor['name']}: No new CVEs")
|
|
updated_count += 1
|
|
|
|
except Exception as e:
|
|
logger.error(f" ✗ {vendor['name']}: {e}")
|
|
failed_count += 1
|
|
|
|
logger.info("=" * 80)
|
|
logger.info(f"✓ Incremental update completed")
|
|
logger.info(f" Vendors updated: {updated_count}")
|
|
logger.info(f" Vendors failed: {failed_count}")
|
|
logger.info(f" New CVEs added: {total_new_cves}")
|
|
logger.info("=" * 80)
|
|
|
|
return updated_count, failed_count
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Incremental update failed: {e}", exc_info=True)
|
|
return 0, len(config.VENDORS)
|
|
|
|
|
|
def initial_full_scan():
|
|
|
|
logger.info("=" * 80)
|
|
logger.info("INITIAL FULL SCAN")
|
|
logger.info("=" * 80)
|
|
logger.info(f"This will scan {config.INITIAL_LOOKBACK_DAYS} days back for all vendors")
|
|
|
|
try:
|
|
from cve_handler import update_all_vendors
|
|
updated, failed = update_all_vendors(force=True)
|
|
|
|
logger.info("=" * 80)
|
|
logger.info(f"✓ Initial scan completed: {updated} updated, {failed} failed")
|
|
logger.info("=" * 80)
|
|
|
|
return updated, failed
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Initial scan failed: {e}", exc_info=True)
|
|
return 0, len(config.VENDORS)
|
|
|
|
|
|
def run_scheduler():
|
|
logger.info("=" * 80)
|
|
logger.info("CVE Monitor Scheduler Starting")
|
|
logger.info("=" * 80)
|
|
|
|
update_interval_hours = config.UPDATE_INTERVAL_HOURS
|
|
scheduler_update_days = getattr(config, 'SCHEDULER_UPDATE_DAYS', 7)
|
|
|
|
logger.info(f"Configuration:")
|
|
logger.info(f" Update interval: {update_interval_hours} hours")
|
|
logger.info(f" Incremental lookback: {scheduler_update_days} days")
|
|
logger.info(f" Initial lookback: {config.INITIAL_LOOKBACK_DAYS} days")
|
|
logger.info(f" Auto-update enabled: {config.ENABLE_AUTO_UPDATE}")
|
|
|
|
if config.ENABLE_AUTO_UPDATE:
|
|
logger.info("\nChecking database status...")
|
|
|
|
try:
|
|
handler = CVEHandler()
|
|
|
|
with handler.get_db_connection() as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute("SELECT COUNT(*) FROM cve_cache")
|
|
total_cves = cursor.fetchone()[0]
|
|
|
|
if total_cves == 0:
|
|
logger.info(f" Database is EMPTY")
|
|
logger.info(f"Starting initial full scan ({config.INITIAL_LOOKBACK_DAYS} days)...")
|
|
logger.info(f"This may take 30-60 minutes depending on API rate limits\n")
|
|
|
|
initial_full_scan()
|
|
|
|
else:
|
|
logger.info(f"✓ Database has {total_cves} CVEs")
|
|
logger.info(f"Skipping initial scan, starting incremental updates\n")
|
|
logger.info("Performing startup incremental update...")
|
|
incremental_update()
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error checking database: {e}", exc_info=True)
|
|
|
|
logger.info(f"\nWaiting 2 minutes before starting scheduled updates...")
|
|
time.sleep(120)
|
|
|
|
while True:
|
|
if config.ENABLE_AUTO_UPDATE:
|
|
try:
|
|
updated, failed = incremental_update()
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error in scheduled update: {e}", exc_info=True)
|
|
else:
|
|
logger.debug("Auto-update is disabled, skipping")
|
|
|
|
sleep_seconds = update_interval_hours * 3600
|
|
next_update = datetime.now() + timedelta(seconds=sleep_seconds)
|
|
|
|
logger.info(f"\n{'=' * 80}")
|
|
logger.info(f"Next incremental update at: {next_update.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
logger.info(f"Sleeping for {update_interval_hours} hours...")
|
|
logger.info(f"{'=' * 80}\n")
|
|
|
|
time.sleep(sleep_seconds)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
run_scheduler()
|
|
except KeyboardInterrupt:
|
|
logger.info("\n\nScheduler stopped by user")
|
|
except Exception as e:
|
|
logger.error(f"Scheduler crashed: {e}", exc_info=True)
|