"""D3FEND endpoints — defensive technique listings, mappings, and import trigger.""" import logging from typing import Optional from fastapi import APIRouter, Depends, Query from sqlalchemy.orm import Session from app.database import get_db from app.dependencies.auth import get_current_user, require_role from app.models.user import User from app.services.d3fend_import_service import ( import_d3fend_techniques, import_d3fend_mappings, ) from app.services.d3fend_query_service import ( list_defensive_techniques as list_defensive_techniques_svc, list_d3fend_tactics, get_defenses_for_attack_technique, ) logger = logging.getLogger(__name__) router = APIRouter(prefix="/d3fend", tags=["d3fend"]) # --------------------------------------------------------------------------- # GET /d3fend — List all defensive techniques # --------------------------------------------------------------------------- @router.get("") def list_defensive_techniques( tactic: Optional[str] = Query(None), search: Optional[str] = Query(None), offset: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=200), db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """List all D3FEND defensive techniques with optional filters.""" return list_defensive_techniques_svc( db, tactic=tactic, search=search, offset=offset, limit=limit ) # --------------------------------------------------------------------------- # GET /d3fend/tactics — List all D3FEND tactics # --------------------------------------------------------------------------- @router.get("/tactics") def list_d3fend_tactics_endpoint( db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Return a list of all D3FEND tactics with counts.""" return list_d3fend_tactics(db) # --------------------------------------------------------------------------- # GET /d3fend/for-technique/{mitre_id} — Defenses for a technique # --------------------------------------------------------------------------- @router.get("/for-technique/{mitre_id}") def get_defenses_for_attack_technique_endpoint( mitre_id: str, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Get all D3FEND defensive techniques mapped to a given ATT&CK technique.""" return get_defenses_for_attack_technique(db, mitre_id) # --------------------------------------------------------------------------- # POST /d3fend/import — Trigger D3FEND import (admin only) # --------------------------------------------------------------------------- @router.post("/import") def trigger_d3fend_import( db: Session = Depends(get_db), current_user: User = Depends(require_role("admin")), ): """Import D3FEND techniques and ATT&CK mappings. Admin only.""" tech_result = import_d3fend_techniques(db) mapping_result = import_d3fend_mappings(db) return { "techniques": tech_result, "mappings": mapping_result, }