psengine 2.4.2__tar.gz → 2.5.0__tar.gz
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-2.4.2 → psengine-2.5.0}/PKG-INFO +4 -3
- {psengine-2.4.2 → psengine-2.5.0}/README.md +1 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/__init__.py +0 -1
- {psengine-2.4.2 → psengine-2.5.0}/psengine/_sdk_id.py +2 -2
- psengine-2.5.0/psengine/asi/__init__.py +29 -0
- psengine-2.5.0/psengine/asi/asi.py +290 -0
- psengine-2.5.0/psengine/asi/asi_mgr.py +861 -0
- psengine-2.5.0/psengine/asi/client.py +288 -0
- psengine-2.5.0/psengine/asi/constants.py +46 -0
- psengine-2.5.0/psengine/asi/errors.py +34 -0
- psengine-2.5.0/psengine/asi/models.py +345 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/config/config.py +3 -1
- {psengine-2.4.2 → psengine-2.5.0}/psengine/constants.py +3 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/endpoints.py +12 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/constants.py +0 -2
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/markdown/markdown.py +1 -1
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/common_models.py +6 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/panel_status.py +2 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/pba_geopolitics_facility.py +2 -2
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/search_endpoint.py +2 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/playbook_alert_mgr.py +6 -4
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/playbook_alerts.py +1 -1
- {psengine-2.4.2 → psengine-2.5.0}/psengine.egg-info/PKG-INFO +4 -3
- {psengine-2.4.2 → psengine-2.5.0}/psengine.egg-info/SOURCES.txt +7 -1
- {psengine-2.4.2 → psengine-2.5.0}/pyproject.toml +4 -3
- psengine-2.4.2/psengine/_version.py +0 -14
- {psengine-2.4.2 → psengine-2.5.0}/LICENSE +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/analyst_notes/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/analyst_notes/constants.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/analyst_notes/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/analyst_notes/helpers.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/analyst_notes/markdown.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/analyst_notes/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/analyst_notes/note.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/analyst_notes/note_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/base_http_client.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/classic_alerts/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/classic_alerts/classic_alert.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/classic_alerts/classic_alert_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/classic_alerts/constants.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/classic_alerts/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/classic_alerts/helpers.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/classic_alerts/markdown/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/classic_alerts/markdown/markdown.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/classic_alerts/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/collective_insights/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/collective_insights/collective_insights.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/collective_insights/constants.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/collective_insights/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/collective_insights/insight.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/collective_insights/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/common_models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/config/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/config/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/detection/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/detection/detection_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/detection/detection_rule.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/detection/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/detection/helpers.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/detection/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/constants.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/lookup.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/lookup_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/models/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/models/base_enriched_entity.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/models/lookup.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/models/soar.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/soar.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/enrich/soar_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_lists/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_lists/constants.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_lists/entity_list.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_lists/entity_list_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_lists/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_lists/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_match/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_match/entity_match.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_match/entity_match_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_match/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/entity_match/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/fusion/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/fusion/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/fusion/fusion_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/fusion/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/helpers/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/helpers/helpers.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/identity/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/identity/constants.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/identity/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/identity/identity.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/identity/identity_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/identity/models/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/identity/models/common_models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/identity/models/detections.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/identity/models/incident_report.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/identity/models/lookup.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/logger/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/logger/constants.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/logger/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/logger/rf_logger.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/malware_intel/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/malware_intel/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/malware_intel/malware_intel.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/malware_intel/malware_intel_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/malware_intel/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/markdown/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/markdown/markdown.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/markdown/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/helpers.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/mappings.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/markdown/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/markdown/markdown_code_repo.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/markdown/markdown_cyber_vulnerability.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/markdown/markdown_domain_abuse.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/markdown/markdown_geopolitics_facility.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/markdown/markdown_identity_exposure.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/markdown/markdown_malware_report.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/markdown/markdown_third_party_risk.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/panel_log.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/pba_code_repo_leak.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/pba_cyber_vulnerability.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/pba_domain_abuse.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/pba_identity_exposures.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/pba_malware_report.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/models/pba_third_party_risk.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/playbook_alerts/pa_category.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/py.typed +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/rf_client.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/risk_history/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/risk_history/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/risk_history/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/risk_history/risk_history_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/risklists/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/risklists/constants.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/risklists/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/risklists/models.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/risklists/risklist_mgr.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/stix2/__init__.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/stix2/base_stix_entity.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/stix2/complex_entity.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/stix2/constants.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/stix2/enriched_indicator.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/stix2/errors.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/stix2/helpers.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/stix2/rf_bundle.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/stix2/simple_entity.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine/stix2/util.py +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine.egg-info/dependency_links.txt +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine.egg-info/requires.txt +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/psengine.egg-info/top_level.txt +0 -0
- {psengine-2.4.2 → psengine-2.5.0}/setup.cfg +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: psengine
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: psengine is a simple, yet elegant, library for rapid development of integrations with Recorded Future.
|
|
5
5
|
Author-email: Moise Medici <moise.medici@recordedfuture.com>, Patrick Kinsella <patrick.kinsella@recordedfuture.com>, Ernest Bartosevic <ernest.bartosevic@recordedfuture.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.
|
|
8
|
-
Project-URL: Changelog, https://recordedfuture-professionalservices.github.io/psengine/CHANGELOG/
|
|
7
|
+
Project-URL: Homepage, https://recordedfuture-professionalservices.github.io/psengine/latest/
|
|
8
|
+
Project-URL: Changelog, https://recordedfuture-professionalservices.github.io/psengine/latest/CHANGELOG/
|
|
9
9
|
Keywords: API,Recorded Future,Cyber Security Engineering,Threat Intelligence
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Programming Language :: Python
|
|
@@ -87,6 +87,7 @@ PSEngine is ready for the demands of building robust and reliable integrations.
|
|
|
87
87
|
It can easily interact with the following Recorded Future datasets:
|
|
88
88
|
|
|
89
89
|
- Analyst Notes
|
|
90
|
+
- Attack Surface Intelligence
|
|
90
91
|
- Collective Insights
|
|
91
92
|
- Classic & Playbook Alerts
|
|
92
93
|
- Detection Rules
|
|
@@ -30,6 +30,7 @@ PSEngine is ready for the demands of building robust and reliable integrations.
|
|
|
30
30
|
It can easily interact with the following Recorded Future datasets:
|
|
31
31
|
|
|
32
32
|
- Analyst Notes
|
|
33
|
+
- Attack Surface Intelligence
|
|
33
34
|
- Collective Insights
|
|
34
35
|
- Classic & Playbook Alerts
|
|
35
36
|
- Detection Rules
|
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
# accessed from any third party API. #
|
|
12
12
|
##############################################################################################
|
|
13
13
|
|
|
14
|
-
from .
|
|
14
|
+
from importlib.metadata import version
|
|
15
15
|
|
|
16
|
-
SDK_ID = f'psengine-py/{
|
|
16
|
+
SDK_ID = f'psengine-py/{version("psengine")}'
|
|
@@ -0,0 +1,29 @@
|
|
|
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 .asi import (
|
|
15
|
+
Asset,
|
|
16
|
+
AssetExposuresOut,
|
|
17
|
+
AssetResponse,
|
|
18
|
+
AssetWithExposureSearch,
|
|
19
|
+
ExposureSearchOut,
|
|
20
|
+
ProjectListOut,
|
|
21
|
+
)
|
|
22
|
+
from .asi_mgr import AttackSurfaceMgr
|
|
23
|
+
from .errors import (
|
|
24
|
+
ASIExposureSearchError,
|
|
25
|
+
ASIFetchAssetError,
|
|
26
|
+
ASIFetchExposureError,
|
|
27
|
+
ASIFetchProjectsError,
|
|
28
|
+
ASISearchAssetsError,
|
|
29
|
+
)
|
|
@@ -0,0 +1,290 @@
|
|
|
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 import (
|
|
21
|
+
ApiMeta,
|
|
22
|
+
AssetExposure,
|
|
23
|
+
AssetWithExposure,
|
|
24
|
+
CertificateInstance,
|
|
25
|
+
DefensiveControl,
|
|
26
|
+
DNSRecord,
|
|
27
|
+
Exposure,
|
|
28
|
+
ExposureSignature,
|
|
29
|
+
ScannedIP,
|
|
30
|
+
WHOISRecord,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AssetWithExposureSearch(RFBaseModel):
|
|
35
|
+
"""Validate data received from the `/projects/{project_id}/exposures/{signature_id}`
|
|
36
|
+
endpoint.
|
|
37
|
+
|
|
38
|
+
This class supports hashing, equality comparison, greater-than comparison, and string
|
|
39
|
+
representation of `AssetWithExposureSearch` instances.
|
|
40
|
+
|
|
41
|
+
Hashing:
|
|
42
|
+
Returns a hash value based on the exposure signature `id`.
|
|
43
|
+
|
|
44
|
+
Equality:
|
|
45
|
+
Checks equality between two `AssetWithExposureSearch` instances based on the exposure
|
|
46
|
+
signature `id`.
|
|
47
|
+
|
|
48
|
+
Greater-than Comparison:
|
|
49
|
+
Defines a greater-than comparison between two `AssetWithExposureSearch` instances based on
|
|
50
|
+
the signature severity and `id`.
|
|
51
|
+
|
|
52
|
+
String Representation:
|
|
53
|
+
Returns a string representation of the `AssetWithExposureSearch` instance including the
|
|
54
|
+
signature name, `id`, and severity.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
>>> print(asset_with_exposure)
|
|
58
|
+
Name: Exposed Service, Id: exp-123, Severity: critical
|
|
59
|
+
```
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
asset_exposures: Optional[list[AssetWithExposure]] = []
|
|
63
|
+
signature: ExposureSignature
|
|
64
|
+
meta: Optional[ApiMeta] = None
|
|
65
|
+
|
|
66
|
+
def __str__(self) -> str:
|
|
67
|
+
msg = 'Name: {}, Id: {}, Severity: {}'
|
|
68
|
+
return msg.format(
|
|
69
|
+
self.signature.name,
|
|
70
|
+
self.signature.id_,
|
|
71
|
+
self.signature.severity.value,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def __hash__(self) -> int:
|
|
75
|
+
return hash(self.signature.id_)
|
|
76
|
+
|
|
77
|
+
def __eq__(self, other: 'AssetWithExposureSearch'):
|
|
78
|
+
return self.signature.id_ == other.signature.id_
|
|
79
|
+
|
|
80
|
+
def __gt__(self, other: 'AssetWithExposureSearch'):
|
|
81
|
+
return (self.signature.severity.value, self.signature.id_) > (
|
|
82
|
+
other.signature.severity.value,
|
|
83
|
+
other.signature.id_,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class ExposureSearch(RFBaseModel):
|
|
88
|
+
"""Validate data received from the `/projects/{project_id}/exposures` endpoint.
|
|
89
|
+
|
|
90
|
+
This class supports hashing, equality comparison, greater-than comparison, and string
|
|
91
|
+
representation of `ExposureSearch` instances.
|
|
92
|
+
|
|
93
|
+
Hashing:
|
|
94
|
+
Returns a hash value based on the exposure signature `id`.
|
|
95
|
+
|
|
96
|
+
Equality:
|
|
97
|
+
Checks equality between two `ExposureSearch` instances based on the exposure signature
|
|
98
|
+
`id`.
|
|
99
|
+
|
|
100
|
+
Greater-than Comparison:
|
|
101
|
+
Defines a greater-than comparison between two `ExposureSearch` instances based on the
|
|
102
|
+
signature severity, asset count, and `id`.
|
|
103
|
+
|
|
104
|
+
String Representation:
|
|
105
|
+
Returns a string representation of the `ExposureSearch` instance including the signature
|
|
106
|
+
name, `id`, severity, and asset count.
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
>>> print(exposure)
|
|
110
|
+
Name: Exposed Service, Id: exp-123, Severity: critical, Asset Count: 42
|
|
111
|
+
```
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
asset_count: int
|
|
115
|
+
asset_exposures: Optional[list[AssetExposure]] = []
|
|
116
|
+
signature: ExposureSignature
|
|
117
|
+
|
|
118
|
+
def __str__(self) -> str:
|
|
119
|
+
msg = 'Name: {}, Id: {}, Severity: {}, Asset Count: {}'
|
|
120
|
+
return msg.format(
|
|
121
|
+
self.signature.name,
|
|
122
|
+
self.signature.id_,
|
|
123
|
+
self.signature.severity.value,
|
|
124
|
+
self.asset_count,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def __hash__(self) -> int:
|
|
128
|
+
return hash(self.signature.id_)
|
|
129
|
+
|
|
130
|
+
def __eq__(self, other: 'ExposureSearch'):
|
|
131
|
+
return self.signature.id_ == other.signature.id_
|
|
132
|
+
|
|
133
|
+
def __gt__(self, other: 'ExposureSearch'):
|
|
134
|
+
return (self.signature.severity.value, self.asset_count, self.signature.id_) > (
|
|
135
|
+
other.signature.severity.value,
|
|
136
|
+
other.asset_count,
|
|
137
|
+
other.signature.id_,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class ExposureSearchOut(RFBaseModel):
|
|
142
|
+
"""Validate data received from the `/projects/{project_id}/exposures` endpoint."""
|
|
143
|
+
|
|
144
|
+
data: list[ExposureSearch]
|
|
145
|
+
meta: ApiMeta
|
|
146
|
+
|
|
147
|
+
def __str__(self) -> str:
|
|
148
|
+
return '\n'.join(str(c) for c in sorted(self.data))
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class Asset(RFBaseModel):
|
|
152
|
+
"""Validate data received from the `/projects/{project_id}/assets`,
|
|
153
|
+
`/projects/{project_id}/assets/{asset_id}`,
|
|
154
|
+
`/projects/{project_id}/assets/{asset_id}/exposures`, and
|
|
155
|
+
`/projects/{project_id}/assets/_search` endpoints.
|
|
156
|
+
|
|
157
|
+
This class supports hashing, equality comparison, greater-than comparison, and string
|
|
158
|
+
representation of `Asset` instances.
|
|
159
|
+
|
|
160
|
+
Hashing:
|
|
161
|
+
Returns a hash value based on the asset `id_` and `project_id`.
|
|
162
|
+
|
|
163
|
+
Equality:
|
|
164
|
+
Checks equality between two `Asset` instances based on the asset `id_` and `project_id`.
|
|
165
|
+
|
|
166
|
+
Greater-than Comparison:
|
|
167
|
+
Defines a greater-than comparison between two `Asset` instances based on the exposure
|
|
168
|
+
score and `id_`.
|
|
169
|
+
|
|
170
|
+
String Representation:
|
|
171
|
+
Returns a string representation of the `Asset` instance including the name, type, and
|
|
172
|
+
exposure score.
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
>>> print(asset)
|
|
176
|
+
Name: example.com, Type: domain, Exposure Score: 85
|
|
177
|
+
```
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
project_id: str
|
|
181
|
+
id_: str = Field(alias='id')
|
|
182
|
+
name: str
|
|
183
|
+
type_: str = Field(alias='type')
|
|
184
|
+
discovered_at: Optional[datetime]
|
|
185
|
+
added_to_project_at: datetime
|
|
186
|
+
last_scanned_at: Optional[datetime] = None
|
|
187
|
+
apex_domain: Optional[str] = None
|
|
188
|
+
exposure_score: Optional[int] = None
|
|
189
|
+
is_static_asset: Optional[bool] = False
|
|
190
|
+
custom_tags: Optional[list[str]] = None
|
|
191
|
+
resolved_ips: Optional[list[str]] = None
|
|
192
|
+
dns_records: Optional[list[DNSRecord]] = None
|
|
193
|
+
whois: Optional[WHOISRecord] = None
|
|
194
|
+
certificates: Optional[list[CertificateInstance]] = None
|
|
195
|
+
defenses: Optional[list[DefensiveControl]] = None
|
|
196
|
+
exposures: Optional[list[Exposure]] = None
|
|
197
|
+
scanned_ips: Optional[list[ScannedIP]] = None
|
|
198
|
+
|
|
199
|
+
def __str__(self) -> str:
|
|
200
|
+
msg = 'Name: {}, Type: {}, Exposure Score: {}'
|
|
201
|
+
return msg.format(self.name, self.type_, self.exposure_score or 'N/A')
|
|
202
|
+
|
|
203
|
+
def __hash__(self) -> int:
|
|
204
|
+
return hash((self.id_, self.project_id))
|
|
205
|
+
|
|
206
|
+
def __eq__(self, other: 'Asset'):
|
|
207
|
+
return (self.id_, self.project_id) == (other.id_, other.project_id)
|
|
208
|
+
|
|
209
|
+
def __gt__(self, other: 'Asset'):
|
|
210
|
+
return (self.exposure_score or 0, self.id_) > (other.exposure_score or 0, other.id_)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class AssetResponse(RFBaseModel):
|
|
214
|
+
"""Validate data received from the `/projects/{project_id}/assets` and
|
|
215
|
+
`/projects/{project_id}/assets/_search` endpoints.
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
data: list[Asset]
|
|
219
|
+
meta: ApiMeta
|
|
220
|
+
|
|
221
|
+
def __str__(self) -> str:
|
|
222
|
+
return '\n'.join(str(c) for c in sorted(self.data, reverse=True))
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class Project(RFBaseModel):
|
|
226
|
+
"""Validate data received from the `/projects` endpoint.
|
|
227
|
+
|
|
228
|
+
This class supports hashing, equality comparison, greater-than comparison, and string
|
|
229
|
+
representation of `Project` instances.
|
|
230
|
+
|
|
231
|
+
Hashing:
|
|
232
|
+
Returns a hash value based on the project `id`.
|
|
233
|
+
|
|
234
|
+
Equality:
|
|
235
|
+
Checks equality between two `Project` instances based on the project `id`.
|
|
236
|
+
|
|
237
|
+
Greater-than Comparison:
|
|
238
|
+
Defines a greater-than comparison between two `Project` instances based on the project
|
|
239
|
+
title.
|
|
240
|
+
|
|
241
|
+
String Representation:
|
|
242
|
+
Returns a string representation of the `Project` instance including the title, `id`, and
|
|
243
|
+
whether scanning is enabled.
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
>>> print(project)
|
|
247
|
+
Name: Example Project, Id: 123e4567-e89b-12d3-a456-426614174000, Enabled: True
|
|
248
|
+
```
|
|
249
|
+
"""
|
|
250
|
+
|
|
251
|
+
id_: str = Field(alias='id')
|
|
252
|
+
title: str
|
|
253
|
+
scanning_enabled: Optional[bool] = None
|
|
254
|
+
last_scanned_at: Optional[datetime] = None
|
|
255
|
+
inserted_at: Optional[datetime] = None
|
|
256
|
+
max_exposure_score: Optional[int] = None
|
|
257
|
+
|
|
258
|
+
def __str__(self) -> str:
|
|
259
|
+
msg = 'Name: {}, Id: {}, Enabled: {}'
|
|
260
|
+
return msg.format(
|
|
261
|
+
self.title,
|
|
262
|
+
self.id_,
|
|
263
|
+
self.scanning_enabled or 'False',
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
def __hash__(self) -> int:
|
|
267
|
+
return hash(self.id_)
|
|
268
|
+
|
|
269
|
+
def __eq__(self, other: 'Project'):
|
|
270
|
+
return self.id_ == other.id_
|
|
271
|
+
|
|
272
|
+
def __gt__(self, other: 'Project'):
|
|
273
|
+
return self.title > other.title
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class ProjectListOut(RFBaseModel):
|
|
277
|
+
"""Validate data received from the `/projects` endpoint."""
|
|
278
|
+
|
|
279
|
+
data: list[Project]
|
|
280
|
+
meta: ApiMeta
|
|
281
|
+
|
|
282
|
+
def __str__(self) -> str:
|
|
283
|
+
return '\n'.join(str(c) for c in sorted(self.data))
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
class AssetExposuresOut(RFBaseModel):
|
|
287
|
+
"""Validate data received from the `/projects/{project_id}/assets/{asset_id}/exposures`."""
|
|
288
|
+
|
|
289
|
+
data: list[AssetWithExposure]
|
|
290
|
+
meta: ApiMeta
|