psengine 2.0.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. psengine/__init__.py +22 -0
  2. psengine/_sdk_id.py +16 -0
  3. psengine/_version.py +14 -0
  4. psengine/analyst_notes/__init__.py +32 -0
  5. psengine/analyst_notes/constants.py +15 -0
  6. psengine/analyst_notes/errors.py +42 -0
  7. psengine/analyst_notes/helpers.py +90 -0
  8. psengine/analyst_notes/models.py +219 -0
  9. psengine/analyst_notes/note.py +149 -0
  10. psengine/analyst_notes/note_mgr.py +400 -0
  11. psengine/base_http_client.py +285 -0
  12. psengine/classic_alerts/__init__.py +24 -0
  13. psengine/classic_alerts/classic_alert.py +275 -0
  14. psengine/classic_alerts/classic_alert_mgr.py +507 -0
  15. psengine/classic_alerts/constants.py +31 -0
  16. psengine/classic_alerts/errors.py +38 -0
  17. psengine/classic_alerts/helpers.py +87 -0
  18. psengine/classic_alerts/markdown/__init__.py +13 -0
  19. psengine/classic_alerts/markdown/markdown.py +359 -0
  20. psengine/classic_alerts/models.py +141 -0
  21. psengine/collective_insights/__init__.py +29 -0
  22. psengine/collective_insights/collective_insights.py +164 -0
  23. psengine/collective_insights/constants.py +44 -0
  24. psengine/collective_insights/errors.py +18 -0
  25. psengine/collective_insights/insight.py +89 -0
  26. psengine/collective_insights/models.py +81 -0
  27. psengine/common_models.py +89 -0
  28. psengine/config/__init__.py +15 -0
  29. psengine/config/config.py +284 -0
  30. psengine/config/errors.py +18 -0
  31. psengine/constants.py +63 -0
  32. psengine/detection/__init__.py +17 -0
  33. psengine/detection/detection_mgr.py +135 -0
  34. psengine/detection/detection_rule.py +85 -0
  35. psengine/detection/errors.py +26 -0
  36. psengine/detection/helpers.py +56 -0
  37. psengine/detection/models.py +47 -0
  38. psengine/endpoints.py +98 -0
  39. psengine/enrich/__init__.py +28 -0
  40. psengine/enrich/constants.py +73 -0
  41. psengine/enrich/errors.py +26 -0
  42. psengine/enrich/lookup.py +299 -0
  43. psengine/enrich/lookup_mgr.py +341 -0
  44. psengine/enrich/models/__init__.py +13 -0
  45. psengine/enrich/models/base_enriched_entity.py +43 -0
  46. psengine/enrich/models/lookup.py +271 -0
  47. psengine/enrich/models/soar.py +138 -0
  48. psengine/enrich/soar.py +89 -0
  49. psengine/enrich/soar_mgr.py +176 -0
  50. psengine/entity_lists/__init__.py +16 -0
  51. psengine/entity_lists/constants.py +19 -0
  52. psengine/entity_lists/entity_list.py +435 -0
  53. psengine/entity_lists/entity_list_mgr.py +185 -0
  54. psengine/entity_lists/errors.py +26 -0
  55. psengine/entity_lists/models.py +87 -0
  56. psengine/entity_match/__init__.py +16 -0
  57. psengine/entity_match/entity_match.py +90 -0
  58. psengine/entity_match/entity_match_mgr.py +235 -0
  59. psengine/entity_match/errors.py +18 -0
  60. psengine/entity_match/models.py +22 -0
  61. psengine/errors.py +41 -0
  62. psengine/helpers/__init__.py +23 -0
  63. psengine/helpers/helpers.py +471 -0
  64. psengine/logger/__init__.py +15 -0
  65. psengine/logger/constants.py +39 -0
  66. psengine/logger/errors.py +18 -0
  67. psengine/logger/rf_logger.py +148 -0
  68. psengine/markdown/__init__.py +21 -0
  69. psengine/markdown/markdown.py +169 -0
  70. psengine/markdown/models.py +22 -0
  71. psengine/playbook_alerts/__init__.py +34 -0
  72. psengine/playbook_alerts/constants.py +35 -0
  73. psengine/playbook_alerts/errors.py +35 -0
  74. psengine/playbook_alerts/helpers.py +80 -0
  75. psengine/playbook_alerts/mappings.py +44 -0
  76. psengine/playbook_alerts/markdown/__init__.py +13 -0
  77. psengine/playbook_alerts/markdown/markdown.py +98 -0
  78. psengine/playbook_alerts/markdown/markdown_code_repo.py +64 -0
  79. psengine/playbook_alerts/markdown/markdown_domain_abuse.py +118 -0
  80. psengine/playbook_alerts/markdown/markdown_identity_exposure.py +158 -0
  81. psengine/playbook_alerts/models/__init__.py +36 -0
  82. psengine/playbook_alerts/models/common_models.py +18 -0
  83. psengine/playbook_alerts/models/panel_log.py +329 -0
  84. psengine/playbook_alerts/models/panel_status.py +70 -0
  85. psengine/playbook_alerts/models/pba_code_repo_leak.py +52 -0
  86. psengine/playbook_alerts/models/pba_cyber_vulnerability.py +53 -0
  87. psengine/playbook_alerts/models/pba_domain_abuse.py +139 -0
  88. psengine/playbook_alerts/models/pba_identity_exposures.py +93 -0
  89. psengine/playbook_alerts/models/pba_third_party_risk.py +103 -0
  90. psengine/playbook_alerts/models/search_endpoint.py +68 -0
  91. psengine/playbook_alerts/pa_category.py +37 -0
  92. psengine/playbook_alerts/playbook_alert_mgr.py +593 -0
  93. psengine/playbook_alerts/playbook_alerts.py +393 -0
  94. psengine/rf_client.py +430 -0
  95. psengine/risklists/__init__.py +17 -0
  96. psengine/risklists/constants.py +15 -0
  97. psengine/risklists/errors.py +20 -0
  98. psengine/risklists/models.py +65 -0
  99. psengine/risklists/risklist_mgr.py +156 -0
  100. psengine/stix2/__init__.py +21 -0
  101. psengine/stix2/base_stix_entity.py +62 -0
  102. psengine/stix2/complex_entity.py +372 -0
  103. psengine/stix2/constants.py +81 -0
  104. psengine/stix2/enriched_indicator.py +261 -0
  105. psengine/stix2/errors.py +22 -0
  106. psengine/stix2/helpers.py +68 -0
  107. psengine/stix2/rf_bundle.py +240 -0
  108. psengine/stix2/simple_entity.py +145 -0
  109. psengine/stix2/util.py +53 -0
  110. psengine-2.0.4.dist-info/METADATA +189 -0
  111. psengine-2.0.4.dist-info/RECORD +115 -0
  112. psengine-2.0.4.dist-info/WHEEL +5 -0
  113. psengine-2.0.4.dist-info/entry_points.txt +2 -0
  114. psengine-2.0.4.dist-info/licenses/LICENSE +21 -0
  115. psengine-2.0.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,70 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ import contextlib
15
+ from datetime import datetime
16
+ from typing import Optional, Union
17
+
18
+ from pydantic import model_validator
19
+
20
+ from ...common_models import RFBaseModel
21
+ from ..models.common_models import ResolvedEntity
22
+
23
+
24
+ class Organisation(RFBaseModel):
25
+ organisation_id: str
26
+ organisation_name: str
27
+
28
+
29
+ class OwnerOrganisationDetails(RFBaseModel):
30
+ organisations: list[Organisation]
31
+ enterprise_id: str
32
+ enterprise_name: str
33
+
34
+
35
+ class PanelStatus(RFBaseModel):
36
+ status: str
37
+ priority: str
38
+ reopen: Optional[str] = None
39
+ assignee_name: Optional[str] = None
40
+ assignee_id: Optional[str] = None
41
+ created: datetime
42
+ updated: datetime
43
+ case_rule_id: Optional[str] = None
44
+ case_rule_label: Optional[str] = None
45
+ creator_name: Optional[str] = None
46
+ creator_id: Optional[str] = None
47
+ owner_organisation_details: Optional[OwnerOrganisationDetails] = None
48
+ entity_id: Optional[str] = None
49
+ entity_name: Optional[str] = None
50
+ actions_taken: list[str]
51
+ targets: Optional[list[Union[ResolvedEntity, str]]] = []
52
+
53
+ @model_validator(mode='before')
54
+ @classmethod
55
+ def rm_deprecated(cls, data):
56
+ """Remove deprecated fields."""
57
+ for key in ('owner_id', 'owner_name', 'organisation_id', 'organisation_name'):
58
+ with contextlib.suppress(KeyError):
59
+ del data[key]
60
+ return data
61
+
62
+
63
+ class PanelAction(RFBaseModel):
64
+ action: Optional[str] = None
65
+ updated: Optional[datetime] = None
66
+ assignee_name: Optional[str] = None
67
+ assignee_id: Optional[str] = None
68
+ status: Optional[str] = None
69
+ description: Optional[str] = None
70
+ link: Optional[str] = None
@@ -0,0 +1,52 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ from datetime import datetime
15
+ from typing import Optional
16
+
17
+ from pydantic import Field, HttpUrl
18
+
19
+ from ...common_models import RFBaseModel
20
+ from ..models.common_models import ResolvedEntity
21
+ from ..models.panel_status import PanelStatus
22
+
23
+
24
+ class CodeRepoPanelStatus(PanelStatus):
25
+ risk_score: Optional[int] = None
26
+ entity_criticality: Optional[str] = None
27
+ targets: Optional[list[ResolvedEntity]] = []
28
+
29
+
30
+ class Repository(RFBaseModel):
31
+ id_: str = Field(alias='id', default=None)
32
+ name: Optional[str] = None
33
+ owner: Optional[ResolvedEntity] = None
34
+
35
+
36
+ class Assessment(RFBaseModel):
37
+ id_: str = Field(alias='id')
38
+ title: Optional[str] = None
39
+ value: Optional[str] = None
40
+
41
+
42
+ class Evidence(RFBaseModel):
43
+ assessments: list[Assessment]
44
+ targets: list[ResolvedEntity]
45
+ url: Optional[HttpUrl] = None
46
+ content: str
47
+ published: datetime
48
+
49
+
50
+ class CodeRepoEvidencePanel(RFBaseModel):
51
+ repository: Optional[Repository] = Field(default_factory=Repository)
52
+ evidence: Optional[list[Evidence]] = []
@@ -0,0 +1,53 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ from datetime import datetime
15
+ from typing import Optional
16
+
17
+ from pydantic import Field
18
+
19
+ from ...common_models import RFBaseModel
20
+ from ..models.common_models import ResolvedEntity
21
+ from ..models.panel_status import PanelStatus
22
+
23
+
24
+ class CyberVulnerabilityPanelStatus(PanelStatus):
25
+ risk_score: Optional[int] = None
26
+ entity_criticality: Optional[str] = None
27
+ targets: Optional[list[ResolvedEntity]] = []
28
+ lifecycle_stage: Optional[str] = None
29
+
30
+
31
+ class VulnerabilityRiskRules(RFBaseModel):
32
+ rule: str
33
+ description: str
34
+
35
+
36
+ class VulnerabilitySummary(RFBaseModel):
37
+ targets: Optional[list[ResolvedEntity]] = []
38
+ lifecycle_stage: Optional[str] = None
39
+ risk_rules: Optional[list[VulnerabilityRiskRules]] = []
40
+
41
+
42
+ class InsiktNote(RFBaseModel):
43
+ id_: str = Field(alias='id')
44
+ title: str
45
+ published: datetime
46
+ topic: str
47
+ fragment: str
48
+
49
+
50
+ class CyberVulnerabilityEvidencePanel(RFBaseModel):
51
+ summary: Optional[VulnerabilitySummary] = Field(default_factory=VulnerabilitySummary)
52
+ affected_products: Optional[list[ResolvedEntity]] = []
53
+ insikt_notes: Optional[list[InsiktNote]] = []
@@ -0,0 +1,139 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ from datetime import datetime
15
+ from typing import Optional, Union
16
+
17
+ from pydantic import Field
18
+
19
+ from ...common_models import IdNameType, RFBaseModel
20
+ from ..models.panel_status import PanelStatus
21
+
22
+
23
+ class Context(RFBaseModel):
24
+ context: str
25
+
26
+
27
+ class DomainAbusePanelStatus(PanelStatus):
28
+ entity_criticality: Optional[str] = None
29
+ risk_score: Optional[int] = None
30
+ context_list: Optional[list[Context]] = []
31
+ targets: Optional[list[str]] = []
32
+
33
+
34
+ class ResolvedRecord(RFBaseModel):
35
+ entity: Optional[str] = None
36
+ record: Optional[str] = None
37
+ risk_score: Optional[int] = None
38
+ criticality: Optional[str] = None
39
+ record_type: Optional[str] = None
40
+ context_list: Optional[list[Context]] = []
41
+
42
+
43
+ class Reregistration(RFBaseModel):
44
+ registrar: Optional[str] = None
45
+ registrar_name: Optional[str] = None
46
+ expiration: Optional[datetime] = None
47
+
48
+
49
+ class MentionedEntity(RFBaseModel):
50
+ entity: Optional[IdNameType] = Field(default_factory=IdNameType)
51
+ reference: str
52
+ fragment: str
53
+
54
+
55
+ class MentionedKeyword(RFBaseModel):
56
+ entity: Optional[IdNameType] = Field(default_factory=IdNameType)
57
+ reference: str
58
+ fragment: str
59
+ keyword: str
60
+
61
+
62
+ class ScreenshotMention(RFBaseModel):
63
+ url: Optional[str] = None
64
+ screenshot: Optional[str] = None
65
+ document: Optional[str] = None
66
+ analyzed: Optional[str] = None
67
+ mentioned_entities: Optional[list[MentionedEntity]] = []
68
+ mentioned_custom_keywords: Optional[list[MentionedKeyword]] = []
69
+
70
+
71
+ class KeywordInDomain(RFBaseModel):
72
+ word: Optional[str] = None
73
+ domain: Optional[str] = None
74
+
75
+
76
+ class Keywords(RFBaseModel):
77
+ security_keywords_in_domain_name: Optional[list[KeywordInDomain]] = []
78
+ payment_keywords_in_domain_name: Optional[list[KeywordInDomain]] = []
79
+
80
+
81
+ class Screenshot(RFBaseModel):
82
+ description: str
83
+ image_id: str
84
+ created: datetime
85
+ tag: Optional[str] = None
86
+
87
+
88
+ class DomainAbuseEvidenceSummary(RFBaseModel):
89
+ explanation: Optional[str] = None
90
+ resolved_record_list: Optional[list[ResolvedRecord]] = []
91
+ screenshots: Optional[list[Screenshot]] = []
92
+ reregistration: Optional[Reregistration] = Field(default_factory=Reregistration)
93
+ screenshot_mentions: Optional[list[ScreenshotMention]] = []
94
+ keywords_in_domain_name: Optional[Keywords] = Field(default_factory=Keywords)
95
+
96
+
97
+ class DomainAbuseEvidenceDns(RFBaseModel):
98
+ ip_list: Optional[list[ResolvedRecord]] = []
99
+ mx_list: Optional[list[ResolvedRecord]] = []
100
+ ns_list: Optional[list[ResolvedRecord]] = []
101
+
102
+
103
+ class ValueServer(RFBaseModel):
104
+ status: Optional[str] = None
105
+ registrar_name: Optional[str] = Field(alias='registrarName', default=None)
106
+ private_registration: Optional[bool] = Field(alias='privateRegistration', default=None)
107
+ name_servers: Optional[list[str]] = Field(alias='nameServers', default=[])
108
+ contact_email: Optional[str] = Field(alias='contactEmail', default=None)
109
+ created_date: Optional[datetime] = Field(alias='createdDate', default=None)
110
+ updated_date: Optional[datetime] = Field(alias='updatedDate', default=None)
111
+ expires_date: Optional[datetime] = Field(alias='expiresDate', default=None)
112
+
113
+
114
+ class ValueLocation(RFBaseModel):
115
+ type_: str = Field(alias='type', default=None)
116
+ telephone: Optional[str] = None
117
+ street1: Optional[str] = None
118
+ state: Optional[str] = None
119
+ postal_code: Optional[str] = Field(alias='postalCode', default=None)
120
+ organization: Optional[str] = None
121
+ name: Optional[str] = None
122
+ fax: Optional[str] = None
123
+ email: Optional[str] = None
124
+ country_code: Optional[str] = Field(alias='countryCode', default=None)
125
+ country: Optional[str] = None
126
+ city: Optional[str] = None
127
+
128
+
129
+ class WhoisAttribute(RFBaseModel):
130
+ provider: str
131
+ entity: str
132
+ attribute: str
133
+ value: Union[ValueServer, ValueLocation]
134
+ added: datetime = None
135
+ removed: Optional[datetime] = None
136
+
137
+
138
+ class DomainAbuseEvidenceWhois(RFBaseModel):
139
+ body: Optional[list[WhoisAttribute]] = []
@@ -0,0 +1,93 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ from datetime import datetime
15
+ from typing import Optional
16
+
17
+ from pydantic import Field, IPvAnyAddress
18
+
19
+ from ...common_models import RFBaseModel
20
+ from ..models.common_models import ResolvedEntity
21
+ from ..models.panel_status import PanelStatus
22
+
23
+
24
+ class Assessment(RFBaseModel):
25
+ name: str
26
+ criticality: str
27
+
28
+
29
+ class PasswordDetails(RFBaseModel):
30
+ properties: Optional[list[str]] = []
31
+ rank: Optional[list[str]] = []
32
+ clear_text_value: Optional[str] = None
33
+ clear_text_hint: Optional[str] = None
34
+
35
+
36
+ class PasswordHash(RFBaseModel):
37
+ algorithm: str
38
+ hash_: Optional[str] = Field(alias='hash', default=None)
39
+ hash_prefix: Optional[str] = None
40
+
41
+
42
+ class ExposedSecret(RFBaseModel):
43
+ type_: str = Field(alias='type', default=None)
44
+ effectively_clear: Optional[bool] = None
45
+ hashes: Optional[list[PasswordHash]] = []
46
+ details: Optional[PasswordDetails] = Field(default_factory=PasswordDetails)
47
+
48
+
49
+ class Dump(RFBaseModel):
50
+ name: Optional[str] = None
51
+ description: Optional[str] = None
52
+
53
+
54
+ class MalwareFamily(RFBaseModel):
55
+ id_: str = Field(alias='id', default=None)
56
+ name: Optional[str] = None
57
+
58
+
59
+ class Infrastructure(RFBaseModel):
60
+ ip: Optional[IPvAnyAddress] = None
61
+
62
+
63
+ class Technology(RFBaseModel):
64
+ name: str
65
+ id_: Optional[str] = Field(alias='id', default=None)
66
+ category: Optional[str] = None
67
+
68
+
69
+ class CompromisedHost(RFBaseModel):
70
+ exfiltration_date: Optional[datetime] = None
71
+ os: Optional[str] = None
72
+ os_username: Optional[str] = None
73
+ malware_file: Optional[str] = None
74
+ timezone: Optional[str] = None
75
+ computer_name: Optional[str] = None
76
+ uac: Optional[str] = None
77
+ antivirus: Optional[list[str]] = []
78
+
79
+
80
+ class IdentityPanelStatus(PanelStatus):
81
+ targets: Optional[list[ResolvedEntity]] = []
82
+
83
+
84
+ class IdentityEvidencePanel(RFBaseModel):
85
+ assessments: Optional[list[Assessment]] = []
86
+ subject: Optional[str] = None
87
+ exposed_secret: Optional[ExposedSecret] = Field(default_factory=ExposedSecret)
88
+ dump: Optional[Dump] = Field(default_factory=Dump)
89
+ authorization_url: Optional[str] = None
90
+ compromised_host: Optional[CompromisedHost] = Field(default_factory=CompromisedHost)
91
+ malware_family: Optional[MalwareFamily] = Field(default_factory=MalwareFamily)
92
+ infrastructure: Optional[Infrastructure] = Field(default_factory=Infrastructure)
93
+ technologies: Optional[list[Technology]] = []
@@ -0,0 +1,103 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ from datetime import datetime
15
+ from typing import Optional
16
+
17
+ from pydantic import Field, model_validator
18
+
19
+ from ...common_models import RFBaseModel
20
+ from ..models.common_models import ResolvedEntity
21
+ from ..models.panel_status import PanelStatus
22
+
23
+
24
+ class TPRPanelStatus(PanelStatus):
25
+ risk_score: Optional[int] = None
26
+ entity_criticality: Optional[str] = None
27
+ targets: Optional[list[ResolvedEntity]] = []
28
+
29
+
30
+ class InsiktNote(RFBaseModel):
31
+ id_: str = Field(alias='id')
32
+ title: Optional[str] = None
33
+ published: Optional[datetime] = None
34
+ topic: Optional[str] = None
35
+ fragment: Optional[str] = None
36
+
37
+
38
+ class ObservedNetworkTraffic(RFBaseModel):
39
+ recent_timestamp: datetime
40
+ malware_family: Optional[str] = None
41
+ client_ip_address: Optional[str] = None
42
+ malware_ip_address: Optional[str] = None
43
+
44
+
45
+ class SummaryString(RFBaseModel):
46
+ data: list
47
+ summary: str
48
+
49
+
50
+ class Reference(RFBaseModel):
51
+ title: Optional[str] = None
52
+ fragment: Optional[str] = None
53
+ published: datetime
54
+ document_url: Optional[str] = None
55
+ source: Optional[str] = None
56
+
57
+
58
+ class IpRule(RFBaseModel):
59
+ name: str
60
+ criticality: int
61
+ number_of_ip_addresses: int
62
+
63
+
64
+ class CyberTrend(RFBaseModel):
65
+ date: datetime
66
+ criticality: int
67
+ number_of_references: int
68
+
69
+
70
+ class Evidence(RFBaseModel):
71
+ summary: str
72
+ type_: str = Field(alias='type')
73
+ data: list
74
+
75
+ @model_validator(mode='after')
76
+ @classmethod
77
+ def check_data_type(cls, evidence: 'Evidence'):
78
+ """Check if evidence type is supported and validate it."""
79
+ type_mapping = {
80
+ 'ip_rule': IpRule,
81
+ 'cyber_trend': CyberTrend,
82
+ 'insikt_note': InsiktNote,
83
+ 'reference': Reference,
84
+ 'hosts_communication': ObservedNetworkTraffic,
85
+ 'summary_string': SummaryString,
86
+ }
87
+ evidence.data = [
88
+ model.model_validate(obj)
89
+ for obj in evidence.data
90
+ if (model := type_mapping.get(evidence.type_))
91
+ ]
92
+ return evidence
93
+
94
+
95
+ class Assessment(RFBaseModel):
96
+ risk_rule: str
97
+ level: int
98
+ added: datetime
99
+ evidence: Evidence
100
+
101
+
102
+ class TPREvidencePanel(RFBaseModel):
103
+ assessments: Optional[list[Assessment]] = []
@@ -0,0 +1,68 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ import contextlib
15
+ from datetime import datetime
16
+ from typing import Optional
17
+
18
+ from pydantic import Field, model_validator
19
+
20
+ from ...common_models import RFBaseModel
21
+ from ..models.panel_status import OwnerOrganisationDetails
22
+
23
+
24
+ class DatetimeRange(RFBaseModel):
25
+ from_: Optional[datetime] = Field(alias='from', default=None)
26
+ until: Optional[datetime] = None
27
+
28
+
29
+ class SearchStatus(RFBaseModel):
30
+ status_code: str
31
+ status_message: str
32
+
33
+
34
+ class SearchData(RFBaseModel):
35
+ playbook_alert_id: str
36
+ status: str
37
+ priority: str
38
+ reopen: Optional[str] = None
39
+ created: datetime
40
+ updated: datetime
41
+ category: str
42
+ title: str
43
+ assignee_name: Optional[str] = None
44
+ assignee_id: Optional[str] = None
45
+ owner_organisation_details: Optional[OwnerOrganisationDetails] = None
46
+ actions_taken: list[str]
47
+
48
+ @model_validator(mode='before')
49
+ @classmethod
50
+ def rm_deprecated(cls, data):
51
+ """Remove deprecated fields."""
52
+ for key in ('owner_id', 'owner_name', 'organisation_id', 'organisation_name'):
53
+ with contextlib.suppress(KeyError):
54
+ del data[key]
55
+ return data
56
+
57
+
58
+ class SearchCounts(RFBaseModel):
59
+ returned: int
60
+ total: int
61
+
62
+
63
+ class SearchResponse(RFBaseModel):
64
+ """Model for payload received by /search endpoint."""
65
+
66
+ status: SearchStatus
67
+ data: list[SearchData]
68
+ counts: SearchCounts
@@ -0,0 +1,37 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ from enum import Enum
15
+
16
+
17
+ class PACategory(Enum):
18
+ """Playbook Alert categories as Enum."""
19
+
20
+ def __str__(self):
21
+ """String representation of the enum value."""
22
+ return str(self.value)
23
+
24
+ def lower(self):
25
+ """Return the lower case version of the enum value.
26
+
27
+ Returns:
28
+ str: lower case version of the enum value
29
+ """
30
+ return self.value.lower()
31
+
32
+ DOMAIN_ABUSE = 'domain_abuse'
33
+ CYBER_VULNERABILITY = 'cyber_vulnerability'
34
+ THIRD_PARTY_RISK = 'third_party_risk'
35
+ CODE_REPO_LEAKAGE = 'code_repo_leakage'
36
+ IDENTITY_NOVEL_EXPOSURES = 'identity_novel_exposures'
37
+ UNMAPPED_ALERT = 'unmapped_alert'