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.
- psengine/__init__.py +22 -0
- psengine/_sdk_id.py +16 -0
- psengine/_version.py +14 -0
- psengine/analyst_notes/__init__.py +32 -0
- psengine/analyst_notes/constants.py +15 -0
- psengine/analyst_notes/errors.py +42 -0
- psengine/analyst_notes/helpers.py +90 -0
- psengine/analyst_notes/models.py +219 -0
- psengine/analyst_notes/note.py +149 -0
- psengine/analyst_notes/note_mgr.py +400 -0
- psengine/base_http_client.py +285 -0
- psengine/classic_alerts/__init__.py +24 -0
- psengine/classic_alerts/classic_alert.py +275 -0
- psengine/classic_alerts/classic_alert_mgr.py +507 -0
- psengine/classic_alerts/constants.py +31 -0
- psengine/classic_alerts/errors.py +38 -0
- psengine/classic_alerts/helpers.py +87 -0
- psengine/classic_alerts/markdown/__init__.py +13 -0
- psengine/classic_alerts/markdown/markdown.py +359 -0
- psengine/classic_alerts/models.py +141 -0
- psengine/collective_insights/__init__.py +29 -0
- psengine/collective_insights/collective_insights.py +164 -0
- psengine/collective_insights/constants.py +44 -0
- psengine/collective_insights/errors.py +18 -0
- psengine/collective_insights/insight.py +89 -0
- psengine/collective_insights/models.py +81 -0
- psengine/common_models.py +89 -0
- psengine/config/__init__.py +15 -0
- psengine/config/config.py +284 -0
- psengine/config/errors.py +18 -0
- psengine/constants.py +63 -0
- psengine/detection/__init__.py +17 -0
- psengine/detection/detection_mgr.py +135 -0
- psengine/detection/detection_rule.py +85 -0
- psengine/detection/errors.py +26 -0
- psengine/detection/helpers.py +56 -0
- psengine/detection/models.py +47 -0
- psengine/endpoints.py +98 -0
- psengine/enrich/__init__.py +28 -0
- psengine/enrich/constants.py +73 -0
- psengine/enrich/errors.py +26 -0
- psengine/enrich/lookup.py +299 -0
- psengine/enrich/lookup_mgr.py +341 -0
- psengine/enrich/models/__init__.py +13 -0
- psengine/enrich/models/base_enriched_entity.py +43 -0
- psengine/enrich/models/lookup.py +271 -0
- psengine/enrich/models/soar.py +138 -0
- psengine/enrich/soar.py +89 -0
- psengine/enrich/soar_mgr.py +176 -0
- psengine/entity_lists/__init__.py +16 -0
- psengine/entity_lists/constants.py +19 -0
- psengine/entity_lists/entity_list.py +435 -0
- psengine/entity_lists/entity_list_mgr.py +185 -0
- psengine/entity_lists/errors.py +26 -0
- psengine/entity_lists/models.py +87 -0
- psengine/entity_match/__init__.py +16 -0
- psengine/entity_match/entity_match.py +90 -0
- psengine/entity_match/entity_match_mgr.py +235 -0
- psengine/entity_match/errors.py +18 -0
- psengine/entity_match/models.py +22 -0
- psengine/errors.py +41 -0
- psengine/helpers/__init__.py +23 -0
- psengine/helpers/helpers.py +471 -0
- psengine/logger/__init__.py +15 -0
- psengine/logger/constants.py +39 -0
- psengine/logger/errors.py +18 -0
- psengine/logger/rf_logger.py +148 -0
- psengine/markdown/__init__.py +21 -0
- psengine/markdown/markdown.py +169 -0
- psengine/markdown/models.py +22 -0
- psengine/playbook_alerts/__init__.py +34 -0
- psengine/playbook_alerts/constants.py +35 -0
- psengine/playbook_alerts/errors.py +35 -0
- psengine/playbook_alerts/helpers.py +80 -0
- psengine/playbook_alerts/mappings.py +44 -0
- psengine/playbook_alerts/markdown/__init__.py +13 -0
- psengine/playbook_alerts/markdown/markdown.py +98 -0
- psengine/playbook_alerts/markdown/markdown_code_repo.py +64 -0
- psengine/playbook_alerts/markdown/markdown_domain_abuse.py +118 -0
- psengine/playbook_alerts/markdown/markdown_identity_exposure.py +158 -0
- psengine/playbook_alerts/models/__init__.py +36 -0
- psengine/playbook_alerts/models/common_models.py +18 -0
- psengine/playbook_alerts/models/panel_log.py +329 -0
- psengine/playbook_alerts/models/panel_status.py +70 -0
- psengine/playbook_alerts/models/pba_code_repo_leak.py +52 -0
- psengine/playbook_alerts/models/pba_cyber_vulnerability.py +53 -0
- psengine/playbook_alerts/models/pba_domain_abuse.py +139 -0
- psengine/playbook_alerts/models/pba_identity_exposures.py +93 -0
- psengine/playbook_alerts/models/pba_third_party_risk.py +103 -0
- psengine/playbook_alerts/models/search_endpoint.py +68 -0
- psengine/playbook_alerts/pa_category.py +37 -0
- psengine/playbook_alerts/playbook_alert_mgr.py +593 -0
- psengine/playbook_alerts/playbook_alerts.py +393 -0
- psengine/rf_client.py +430 -0
- psengine/risklists/__init__.py +17 -0
- psengine/risklists/constants.py +15 -0
- psengine/risklists/errors.py +20 -0
- psengine/risklists/models.py +65 -0
- psengine/risklists/risklist_mgr.py +156 -0
- psengine/stix2/__init__.py +21 -0
- psengine/stix2/base_stix_entity.py +62 -0
- psengine/stix2/complex_entity.py +372 -0
- psengine/stix2/constants.py +81 -0
- psengine/stix2/enriched_indicator.py +261 -0
- psengine/stix2/errors.py +22 -0
- psengine/stix2/helpers.py +68 -0
- psengine/stix2/rf_bundle.py +240 -0
- psengine/stix2/simple_entity.py +145 -0
- psengine/stix2/util.py +53 -0
- psengine-2.0.4.dist-info/METADATA +189 -0
- psengine-2.0.4.dist-info/RECORD +115 -0
- psengine-2.0.4.dist-info/WHEEL +5 -0
- psengine-2.0.4.dist-info/entry_points.txt +2 -0
- psengine-2.0.4.dist-info/licenses/LICENSE +21 -0
- 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'
|