feat: Phase 4 - MITRE ATT&CK sync and scheduled job (T-018, T-019)
- Add MITRE sync service via TAXII 2.0 with GitHub fallback - Upsert attack-pattern objects into techniques table (691 techniques) - Detect name/description changes and flag review_required on re-sync - Add APScheduler background job running every 24h - Add POST /system/sync-mitre endpoint (admin only) - Add GET /system/scheduler-status endpoint (admin only) - Configure logging for scheduler and sync visibility - Update README with new endpoints and project structure
This commit is contained in:
58
backend/app/routers/system.py
Normal file
58
backend/app/routers/system.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""System-level endpoints (admin only).
|
||||
|
||||
Provides manual triggers for background operations such as the MITRE
|
||||
ATT&CK synchronisation, and scheduler health introspection.
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.database import get_db
|
||||
from app.dependencies.auth import require_role
|
||||
from app.models.user import User
|
||||
from app.services.mitre_sync_service import sync_mitre
|
||||
from app.jobs.mitre_sync_job import scheduler
|
||||
|
||||
router = APIRouter(prefix="/system", tags=["system"])
|
||||
|
||||
|
||||
@router.post("/sync-mitre")
|
||||
def trigger_mitre_sync(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(require_role("admin")),
|
||||
):
|
||||
"""Manually trigger a MITRE ATT&CK synchronisation.
|
||||
|
||||
**Requires** the ``admin`` role.
|
||||
|
||||
Returns a JSON object with the sync summary including the count of
|
||||
new and updated techniques.
|
||||
"""
|
||||
summary = sync_mitre(db)
|
||||
return {
|
||||
"message": "MITRE sync completed",
|
||||
"new": summary["created"],
|
||||
"updated": summary["updated"],
|
||||
}
|
||||
|
||||
|
||||
@router.get("/scheduler-status")
|
||||
def scheduler_status(
|
||||
current_user: User = Depends(require_role("admin")),
|
||||
):
|
||||
"""Return the current state of the background scheduler.
|
||||
|
||||
**Requires** the ``admin`` role.
|
||||
"""
|
||||
jobs = scheduler.get_jobs()
|
||||
return {
|
||||
"running": scheduler.running,
|
||||
"jobs": [
|
||||
{
|
||||
"id": job.id,
|
||||
"name": job.name,
|
||||
"next_run_time": str(job.next_run_time) if job.next_run_time else None,
|
||||
}
|
||||
for job in jobs
|
||||
],
|
||||
}
|
||||
Reference in New Issue
Block a user