1- from enum import Enum
2- from pydantic import BaseModel , computed_field , Field
1+ from __future__ import annotations
2+
33from abc import ABC
4- from typing import Set , Annotated
5- from contentctl . objects . enums import RiskSeverity
4+ from enum import Enum
5+ from typing import Annotated , Any , Set
66
7+ from pydantic import BaseModel , Field , computed_field , model_serializer
8+
9+ from contentctl .objects .enums import RiskSeverity
710
811RiskScoreValue_Type = Annotated [int , Field (ge = 1 , le = 100 )]
912
@@ -42,6 +45,7 @@ class ThreatObjectType(str, Enum):
4245 TLS_HASH = "tls_hash"
4346 URL = "url"
4447
48+ #[{"risk_object_field": "dest", "risk_object_type": "system", "risk_score": 64}, {"threat_object_field": "src_ip", "threat_object_type": "ip_address"}]
4549
4650class RiskObject (BaseModel ):
4751 field : str
@@ -51,6 +55,28 @@ class RiskObject(BaseModel):
5155 def __hash__ (self ):
5256 return hash ((self .field , self .type , self .score ))
5357
58+ def __lt__ (self , other : RiskObject ) -> bool :
59+ if (
60+ f"{ self .field } { self .type } { self .score } "
61+ < f"{ other .field } { other .type } { other .score } "
62+ ):
63+ return True
64+ return False
65+
66+ @model_serializer
67+ def serialize_risk_object (self ) -> dict [str , str | int ]:
68+ '''
69+ We define this explicitly for two reasons, even though the automatic
70+ serialization works correctly. First we want to enforce a specific
71+ field order for reasons of readability. Second, some of the fields
72+ actually have different names than they do in the object.
73+ '''
74+ return {
75+ "risk_object_field" : self .field ,
76+ "risk_object_type" : self .type ,
77+ "risk_score" : self .score
78+ }
79+
5480
5581class ThreatObject (BaseModel ):
5682 field : str
@@ -59,6 +85,24 @@ class ThreatObject(BaseModel):
5985 def __hash__ (self ):
6086 return hash ((self .field , self .type ))
6187
88+ def __lt__ (self , other : ThreatObject ) -> bool :
89+ if f"{ self .field } { self .type } " < f"{ other .field } { other .type } " :
90+ return True
91+ return False
92+
93+ @model_serializer
94+ def serialize_threat_object (self ) -> dict [str , str ]:
95+ '''
96+ We define this explicitly for two reasons, even though the automatic
97+ serialization works correctly. First we want to enforce a specific
98+ field order for reasons of readability. Second, some of the fields
99+ actually have different names than they do in the object.
100+ '''
101+ return {
102+ "threat_object_field" : self .field ,
103+ "threat_object_type" : self .type ,
104+ }
105+
62106
63107class RBAObject (BaseModel , ABC ):
64108 message : str
@@ -94,3 +138,11 @@ def severity(self) -> RiskSeverity:
94138 raise Exception (
95139 f"Error getting severity - risk_score must be between 0-100, but was actually { self .risk_score } "
96140 )
141+
142+ @model_serializer
143+ def serialize_rba (self ) -> dict [str , str | list [dict [str , str | int ]]]:
144+ return {
145+ "message" : self .message ,
146+ "risk_objects" : [obj .model_dump () for obj in sorted (self .risk_objects )],
147+ "threat_objects" : [obj .model_dump () for obj in sorted (self .threat_objects )],
148+ }
0 commit comments