Cybersecurity-Projects/PROJECTS/intermediate/siem-dashboard/backend/app/schemas/rule.py

106 lines
2.6 KiB
Python

"""
©AngelaMos | 2026
rule.py
"""
from typing import Any, Literal
from pydantic import BaseModel, Field, model_validator
from app.config import settings
from app.models.CorrelationRule import RuleType
from app.models.LogEvent import Severity
class ThresholdConditions(BaseModel):
"""
Conditions for threshold-based correlation rules
"""
event_filter: dict[str, str]
threshold: int = Field(ge=1)
window_seconds: int = Field(ge=1)
group_by: str
class SequenceStep(BaseModel):
"""
A single step in a sequence correlation rule
"""
event_filter: dict[str, str]
count: int = Field(default=1, ge=1)
class SequenceConditions(BaseModel):
"""
Conditions for sequence-based correlation rules
"""
steps: list[SequenceStep] = Field(min_length=2)
window_seconds: int = Field(ge=1)
group_by: str
class AggregationConditions(BaseModel):
"""
Conditions for aggregation-based correlation rules
"""
event_filter: dict[str, str]
aggregation: Literal["count_distinct"]
aggregation_field: str
threshold: int = Field(ge=1)
window_seconds: int = Field(ge=1)
group_by: str
CONDITION_SCHEMAS: dict[RuleType, type[BaseModel]] = {
RuleType.THRESHOLD: ThresholdConditions,
RuleType.SEQUENCE: SequenceConditions,
RuleType.AGGREGATION: AggregationConditions,
}
class RuleCreateRequest(BaseModel):
"""
Schema for creating a new correlation rule
"""
name: str = Field(min_length=1)
description: str = ""
rule_type: RuleType
conditions: dict[str, Any]
severity: Severity
enabled: bool = True
mitre_tactic: str | None = None
mitre_technique: str | None = None
@model_validator(mode="after")
def validate_conditions(self) -> RuleCreateRequest:
"""
Validate conditions dict matches the expected structure for rule_type
"""
schema = CONDITION_SCHEMAS[self.rule_type]
schema.model_validate(self.conditions)
return self
class RuleUpdateRequest(BaseModel):
"""
Schema for updating an existing correlation rule
"""
name: str | None = None
description: str | None = None
conditions: dict[str, Any] | None = None
severity: Severity | None = None
enabled: bool | None = None
mitre_tactic: str | None = None
mitre_technique: str | None = None
class RuleTestRequest(BaseModel):
"""
Schema for testing a rule against historical events
"""
hours: int = Field(
default=settings.TIMELINE_DEFAULT_HOURS,
ge=1,
le=settings.RULE_TEST_MAX_HOURS,
)