Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- Migration b048: evaluation_imports table (adversary, round, status, tests_created) - EvaluationImport SQLAlchemy model - attck_evaluations_service: fetch rounds from evals.mitre.org API, import per-technique detection results (Technique/Tactic/Telemetry -> detected/partially/not_detected) - All imported tests land in in_review state with lab-environment disclaimer - Idempotency guard prevents duplicate round imports - 4 new endpoints: list rounds, import specific, import latest, check-new - Weekly APScheduler cron (Mon 06:00) auto-checks and imports new rounds - SystemPage UI: rounds table, import buttons, check-new, result feedback - Disclaimer callout reminding admins these are lab results not org coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
35 lines
1.5 KiB
Python
35 lines
1.5 KiB
Python
"""SQLAlchemy model for tracking imported ATT&CK Evaluation rounds."""
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import Column, String, Integer, DateTime, Text, ForeignKey, Index
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
|
|
from app.database import Base
|
|
|
|
|
|
class EvaluationImport(Base):
|
|
"""Tracks which ATT&CK Evaluation rounds have been imported into the platform.
|
|
|
|
Each row represents one vendor+adversary combination that has been processed
|
|
and turned into Test records. Used to avoid duplicate imports and to show
|
|
the admin panel which rounds are available vs imported.
|
|
"""
|
|
__tablename__ = "evaluation_imports"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
adversary_name = Column(String, nullable=False) # "apt29", "turla"
|
|
adversary_display = Column(String, nullable=False) # "APT29", "Turla"
|
|
eval_round = Column(Integer, nullable=False) # 1, 2, 3 …
|
|
imported_at = Column(DateTime, nullable=False, default=datetime.utcnow)
|
|
imported_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
|
|
tests_created = Column(Integer, default=0)
|
|
techniques_covered = Column(Integer, default=0)
|
|
status = Column(String, default="completed") # "completed" | "failed"
|
|
notes = Column(Text, nullable=True)
|
|
|
|
__table_args__ = (
|
|
Index("ix_evaluation_imports_adversary", "adversary_name"),
|
|
Index("ix_evaluation_imports_round", "eval_round"),
|
|
)
|