psengine 2.8.2__tar.gz → 2.8.4__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.8.2 → psengine-2.8.4}/PKG-INFO +3 -2
- {psengine-2.8.2 → psengine-2.8.4}/psengine/analyst_notes/markdown.py +1 -2
- {psengine-2.8.2 → psengine-2.8.4}/psengine/classic_alerts/markdown/markdown.py +1 -1
- {psengine-2.8.2 → psengine-2.8.4}/psengine/markdown/markdown.py +2 -2
- psengine-2.8.4/psengine/markdown/markdown_strings.py +163 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown.py +1 -2
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_code_repo.py +1 -2
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_cyber_vulnerability.py +1 -2
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_domain_abuse.py +1 -2
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_geopolitics_facility.py +1 -2
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_identity_exposure.py +1 -2
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_malware_report.py +1 -2
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_third_party_risk.py +1 -2
- {psengine-2.8.2 → psengine-2.8.4}/pyproject.toml +5 -3
- {psengine-2.8.2 → psengine-2.8.4}/README.md +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/_sdk_id.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/analyst_notes/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/analyst_notes/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/analyst_notes/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/analyst_notes/helpers.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/analyst_notes/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/analyst_notes/note.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/analyst_notes/note_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/asi/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/asi/asi.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/asi/asi_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/asi/client.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/asi/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/asi/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/asi/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/base_http_client.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/classic_alerts/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/classic_alerts/classic_alert.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/classic_alerts/classic_alert_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/classic_alerts/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/classic_alerts/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/classic_alerts/helpers.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/classic_alerts/markdown/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/classic_alerts/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/collective_insights/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/collective_insights/collective_insights.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/collective_insights/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/collective_insights/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/collective_insights/insight.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/collective_insights/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/common_models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/config/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/config/config.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/config/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/detection/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/detection/detection_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/detection/detection_rule.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/detection/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/detection/helpers.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/detection/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/endpoints.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/lookup.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/lookup_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/models/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/models/base_enriched_entity.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/models/lookup.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/models/soar.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/soar.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/enrich/soar_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_lists/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_lists/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_lists/entity_list.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_lists/entity_list_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_lists/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_lists/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_match/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_match/entity_match.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_match/entity_match_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_match/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/entity_match/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/fusion/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/fusion/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/fusion/fusion_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/fusion/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/helpers/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/helpers/helpers.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/identity/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/identity/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/identity/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/identity/identity.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/identity/identity_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/identity/models/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/identity/models/common_models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/identity/models/detections.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/identity/models/incident_report.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/identity/models/lookup.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/links/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/links/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/links/links.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/links/links_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/links/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/logger/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/logger/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/logger/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/logger/rf_logger.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/malware_intel/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/malware_intel/auto_sigma_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/malware_intel/auto_yara_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/malware_intel/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/malware_intel/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/malware_intel/helpers.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/malware_intel/malware_intel.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/malware_intel/malware_intel_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/malware_intel/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/markdown/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/markdown/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/helpers.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/mappings.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/common_models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/panel_log.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/panel_status.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/pba_code_repo_leak.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/pba_cyber_vulnerability.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/pba_domain_abuse.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/pba_geopolitics_facility.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/pba_identity_exposures.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/pba_malware_report.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/pba_third_party_risk.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/search_endpoint.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/pa_category.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/playbook_alert_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/playbook_alerts.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/py.typed +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/rf_client.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/risk_history/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/risk_history/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/risk_history/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/risk_history/risk_history_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/risklists/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/risklists/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/risklists/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/risklists/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/risklists/risklist_mgr.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/stix2/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/stix2/base_stix_entity.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/stix2/complex_entity.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/stix2/constants.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/stix2/enriched_indicator.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/stix2/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/stix2/helpers.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/stix2/rf_bundle.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/stix2/simple_entity.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/stix2/util.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/threat_maps/__init__.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/threat_maps/errors.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/threat_maps/models.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/threat_maps/threat_map.py +0 -0
- {psengine-2.8.2 → psengine-2.8.4}/psengine/threat_maps/threat_map_mgr.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: psengine
|
|
3
|
-
Version: 2.8.
|
|
3
|
+
Version: 2.8.4
|
|
4
4
|
Summary: psengine is a simple, yet elegant, library for rapid development of integrations with Recorded Future.
|
|
5
5
|
Keywords: API,Recorded Future,Cyber Security Engineering,Threat Intelligence
|
|
6
6
|
Author: Moise Medici, Patrick Kinsella, Ernest Bartosevic
|
|
@@ -18,13 +18,14 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
19
|
Requires-Dist: typing-extensions>=4.8.0
|
|
20
20
|
Requires-Dist: requests>=2.33.1
|
|
21
|
+
Requires-Dist: urllib3>=2.7.0
|
|
22
|
+
Requires-Dist: idna>=3.15
|
|
21
23
|
Requires-Dist: jsonpath-ng>=1.5.3,<=1.8.0
|
|
22
24
|
Requires-Dist: stix2~=3.0.2
|
|
23
25
|
Requires-Dist: python-dateutil>=2.7.0
|
|
24
26
|
Requires-Dist: more-itertools>=9.0.0,<=11.0.2
|
|
25
27
|
Requires-Dist: pydantic>=2.7,<3.0.0
|
|
26
28
|
Requires-Dist: pydantic-settings[toml]>=2.14.2,<2.15.0
|
|
27
|
-
Requires-Dist: markdown-strings==3.4.0
|
|
28
29
|
Requires-Python: >=3.10, <3.15
|
|
29
30
|
Project-URL: Homepage, https://recordedfuture-professionalservices.github.io/psengine/latest/
|
|
30
31
|
Project-URL: Changelog, https://recordedfuture-professionalservices.github.io/psengine/latest/CHANGELOG/
|
|
@@ -16,11 +16,10 @@ from collections import defaultdict
|
|
|
16
16
|
from itertools import chain
|
|
17
17
|
from typing import TYPE_CHECKING
|
|
18
18
|
|
|
19
|
-
from markdown_strings import bold, unordered_list
|
|
20
|
-
|
|
21
19
|
from ..constants import TIMESTAMP_STR
|
|
22
20
|
from ..endpoints import EP_ANALYST_NOTE_LOOKUP
|
|
23
21
|
from ..markdown.markdown import MarkdownMaker, divider, html_collapsible
|
|
22
|
+
from ..markdown.markdown_strings import bold, unordered_list
|
|
24
23
|
|
|
25
24
|
if TYPE_CHECKING:
|
|
26
25
|
from ..analyst_notes import AnalystNote
|
|
@@ -15,7 +15,7 @@ import re
|
|
|
15
15
|
from itertools import chain
|
|
16
16
|
from typing import TYPE_CHECKING
|
|
17
17
|
|
|
18
|
-
from markdown_strings import blockquote, bold, esc_format, link
|
|
18
|
+
from ...markdown.markdown_strings import blockquote, bold, esc_format, link
|
|
19
19
|
|
|
20
20
|
if TYPE_CHECKING:
|
|
21
21
|
from ...classic_alerts.classic_alert import ClassicAlert
|
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
import html
|
|
15
15
|
from typing import Annotated
|
|
16
16
|
|
|
17
|
-
import markdown_strings
|
|
18
|
-
from markdown_strings import header
|
|
19
17
|
from pydantic import validate_call
|
|
20
18
|
from typing_extensions import Doc
|
|
21
19
|
|
|
20
|
+
from . import markdown_strings
|
|
21
|
+
from .markdown_strings import header
|
|
22
22
|
from .models import Section
|
|
23
23
|
|
|
24
24
|
TITLE_HEADER_LEVEL = 2
|
|
@@ -0,0 +1,163 @@
|
|
|
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
|
+
|
|
15
|
+
def esc_format(text, esc):
|
|
16
|
+
"""Return text with markdown formatting characters escaped."""
|
|
17
|
+
if esc:
|
|
18
|
+
return str(text).replace('_', r'\_').replace('*', r'\*').replace('`', r'\`')
|
|
19
|
+
return text
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def header(header_text, header_level, style='atx', esc=True):
|
|
23
|
+
"""Return a header of the specified level and style."""
|
|
24
|
+
if not isinstance(header_level, int):
|
|
25
|
+
raise TypeError('header_level must be int')
|
|
26
|
+
if not isinstance(header_text, str):
|
|
27
|
+
raise TypeError('header_text must be str')
|
|
28
|
+
if style == 'atx':
|
|
29
|
+
if not 1 <= header_level <= 6:
|
|
30
|
+
raise ValueError(f'Invalid level {header_level} for atx')
|
|
31
|
+
return f'{"#" * header_level} {esc_format(header_text, esc)}'
|
|
32
|
+
if style == 'setext':
|
|
33
|
+
if not 0 < header_level < 3:
|
|
34
|
+
raise ValueError(f'Invalid level {header_level} for setext')
|
|
35
|
+
header_character = '=' if header_level == 1 else '-'
|
|
36
|
+
header_string = (header_character * 3) + header_character * (len(header_text) - 3)
|
|
37
|
+
return f'{esc_format(header_text, esc)}\n{header_string}'
|
|
38
|
+
raise ValueError(f"Invalid style {style} (choose 'atx' or 'setext')")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def italics(text, esc=True):
|
|
42
|
+
"""Return italics formatted text."""
|
|
43
|
+
return f'_{esc_format(text, esc)}_'
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def bold(text, esc=True):
|
|
47
|
+
"""Return bold formatted text."""
|
|
48
|
+
return f'**{esc_format(text, esc)}**'
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def inline_code(text):
|
|
52
|
+
"""Return formatted inline code."""
|
|
53
|
+
return f'`{str(text)}`'
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def code_block(text, language=''):
|
|
57
|
+
"""Return a code block, fenced if a language is specified."""
|
|
58
|
+
if language:
|
|
59
|
+
return f'```{language}\n{text}\n```'
|
|
60
|
+
return '\n'.join([f' {item}' for item in text.split('\n')])
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def link(text, link_url, esc=True):
|
|
64
|
+
"""Return an inline link."""
|
|
65
|
+
return f'[{esc_format(text, esc)}]({link_url})'
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def image(alt_text, link_url, title='', esc=True):
|
|
69
|
+
"""Return an inline image."""
|
|
70
|
+
image_string = f''
|
|
71
|
+
if title:
|
|
72
|
+
image_string += f' "{esc_format(title, esc)}"'
|
|
73
|
+
return image_string
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def unordered_list(text_list, esc=True):
|
|
77
|
+
"""Return an unordered list from a list."""
|
|
78
|
+
return '\n'.join([f'- {esc_format(item, esc)}' for item in text_list])
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def ordered_list(text_list, esc=True):
|
|
82
|
+
"""Return an ordered list from a list."""
|
|
83
|
+
ordered_list = []
|
|
84
|
+
for number, item in enumerate(text_list):
|
|
85
|
+
ordered_list.append(
|
|
86
|
+
f'{(f"{esc_format(number + 1, esc)}.").ljust(3)} {esc_format(item, esc)}'
|
|
87
|
+
)
|
|
88
|
+
return '\n'.join(ordered_list)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def blockquote(text, esc=True):
|
|
92
|
+
"""Return a blockquote."""
|
|
93
|
+
return '\n'.join([f'> {esc_format(item, esc)}' for item in text.split('\n')])
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def horizontal_rule(length=79, style='_'):
|
|
97
|
+
"""Return a horizontal rule of the specified length and style."""
|
|
98
|
+
if style not in ('_', '*'):
|
|
99
|
+
raise ValueError("Invalid style (choose '_' or '*')")
|
|
100
|
+
if length < 3:
|
|
101
|
+
raise ValueError('Length must be >= 3')
|
|
102
|
+
return style * length
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def strikethrough(text, esc=True):
|
|
106
|
+
"""Return text with strike-through formatting."""
|
|
107
|
+
return f'~{esc_format(text, esc)}~'
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def task_list(task_list, esc=True):
|
|
111
|
+
"""Return a task list from a 2-dimensional list of (text, completed) pairs."""
|
|
112
|
+
tasks = []
|
|
113
|
+
for item, completed in task_list:
|
|
114
|
+
tasks.append(f'- [{"X" if completed else " "}] {esc_format(item, esc)}')
|
|
115
|
+
return '\n'.join(tasks)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def table_row(text_list, pad=None, esc=True):
|
|
119
|
+
"""Return a single table row, optionally padded."""
|
|
120
|
+
if pad is None:
|
|
121
|
+
pad = [0] * len(text_list)
|
|
122
|
+
row = '|'
|
|
123
|
+
for column_number in range(len(text_list)):
|
|
124
|
+
padding = pad[column_number] + 1
|
|
125
|
+
row += (' ' + esc_format(text_list[column_number], esc)).ljust(padding) + ' |'
|
|
126
|
+
return row
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def table_delimiter_row(number_of_columns, column_lengths=None):
|
|
130
|
+
"""Return a delimiter row for use in a table."""
|
|
131
|
+
if column_lengths is None:
|
|
132
|
+
column_lengths = [0] * number_of_columns
|
|
133
|
+
if number_of_columns != len(column_lengths):
|
|
134
|
+
raise ValueError('number_of_columns must be the number of columns in column_lengths')
|
|
135
|
+
delimiter_row = [
|
|
136
|
+
'---' + '-' * (column_lengths[column_number] - 3)
|
|
137
|
+
for column_number in range(number_of_columns)
|
|
138
|
+
]
|
|
139
|
+
return table_row(delimiter_row)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def table(table_list):
|
|
143
|
+
"""Return a formatted table generated from a 2-dimensional list of columns."""
|
|
144
|
+
number_of_columns = len(table_list)
|
|
145
|
+
number_of_rows_in_column = [len(column) for column in table_list]
|
|
146
|
+
string_list = [[str(cell) for cell in column] for column in table_list]
|
|
147
|
+
column_lengths = [len(max(column, key=len)) for column in string_list]
|
|
148
|
+
table = []
|
|
149
|
+
|
|
150
|
+
row_list = [column[0] for column in string_list]
|
|
151
|
+
table.append(table_row(row_list, pad=column_lengths))
|
|
152
|
+
|
|
153
|
+
table.append(table_delimiter_row(len(column_lengths), column_lengths=column_lengths))
|
|
154
|
+
|
|
155
|
+
for row in range(1, max(number_of_rows_in_column)):
|
|
156
|
+
row_list = []
|
|
157
|
+
for column_number in range(number_of_columns):
|
|
158
|
+
if number_of_rows_in_column[column_number] > row:
|
|
159
|
+
row_list.append(string_list[column_number][row])
|
|
160
|
+
else:
|
|
161
|
+
row_list.append('')
|
|
162
|
+
table.append(table_row(row_list, pad=column_lengths))
|
|
163
|
+
return '\n'.join(table)
|
|
@@ -11,12 +11,11 @@
|
|
|
11
11
|
# accessed from any third party API. #
|
|
12
12
|
##############################################################################################
|
|
13
13
|
|
|
14
|
-
from markdown_strings import bold, link
|
|
15
|
-
|
|
16
14
|
from ...constants import TIMESTAMP_STR, TRUNCATE_COMMENT
|
|
17
15
|
from ...markdown import (
|
|
18
16
|
MarkdownMaker,
|
|
19
17
|
)
|
|
18
|
+
from ...markdown.markdown_strings import bold, link
|
|
20
19
|
from ..pa_category import PACategory
|
|
21
20
|
from .markdown_code_repo import _code_repo_markdown
|
|
22
21
|
from .markdown_cyber_vulnerability import _cyber_vulnerability_markdown
|
|
@@ -14,10 +14,9 @@
|
|
|
14
14
|
from collections import defaultdict
|
|
15
15
|
from typing import TYPE_CHECKING
|
|
16
16
|
|
|
17
|
-
from markdown_strings import blockquote, bold
|
|
18
|
-
|
|
19
17
|
from ...constants import TIMESTAMP_STR
|
|
20
18
|
from ...markdown import MarkdownMaker, clean_text, divider, html_textarea
|
|
19
|
+
from ...markdown.markdown_strings import blockquote, bold
|
|
21
20
|
|
|
22
21
|
if TYPE_CHECKING:
|
|
23
22
|
from ...playbook_alerts.playbook_alerts import PBA_CodeRepoLeakage
|
{psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_cyber_vulnerability.py
RENAMED
|
@@ -14,14 +14,13 @@
|
|
|
14
14
|
import itertools
|
|
15
15
|
from typing import TYPE_CHECKING
|
|
16
16
|
|
|
17
|
-
from markdown_strings import bold, unordered_list
|
|
18
|
-
|
|
19
17
|
from ...analyst_notes import AnalystNote
|
|
20
18
|
from ...analyst_notes.markdown import _cleanup_insikt_note_text
|
|
21
19
|
from ...constants import TIMESTAMP_STR
|
|
22
20
|
from ...enrich.lookup import CVSS, CVSSV3, EnrichmentData
|
|
23
21
|
from ...markdown import MarkdownMaker
|
|
24
22
|
from ...markdown.markdown import divider, header, html_collapsible
|
|
23
|
+
from ...markdown.markdown_strings import bold, unordered_list
|
|
25
24
|
|
|
26
25
|
if TYPE_CHECKING:
|
|
27
26
|
from ...playbook_alerts.playbook_alerts import PBA_CyberVulnerability
|
{psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_domain_abuse.py
RENAMED
|
@@ -14,12 +14,11 @@
|
|
|
14
14
|
import base64
|
|
15
15
|
from typing import TYPE_CHECKING
|
|
16
16
|
|
|
17
|
-
from markdown_strings import bold
|
|
18
|
-
|
|
19
17
|
from ...constants import TIMESTAMP_STR
|
|
20
18
|
from ...helpers import FormattingHelpers
|
|
21
19
|
from ...markdown import MarkdownMaker
|
|
22
20
|
from ...markdown.markdown import divider, table_from_rows
|
|
21
|
+
from ...markdown.markdown_strings import bold
|
|
23
22
|
from ..models.pba_domain_abuse import ValueServer
|
|
24
23
|
|
|
25
24
|
if TYPE_CHECKING:
|
{psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_geopolitics_facility.py
RENAMED
|
@@ -15,9 +15,8 @@ import base64
|
|
|
15
15
|
from datetime import datetime
|
|
16
16
|
from typing import TYPE_CHECKING
|
|
17
17
|
|
|
18
|
-
from markdown_strings import bold, link
|
|
19
|
-
|
|
20
18
|
from ...markdown import MarkdownMaker, divider
|
|
19
|
+
from ...markdown.markdown_strings import bold, link
|
|
21
20
|
|
|
22
21
|
if TYPE_CHECKING:
|
|
23
22
|
from ...playbook_alerts.playbook_alerts import PBA_GeopoliticsFacility
|
{psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_identity_exposure.py
RENAMED
|
@@ -13,11 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
from typing import TYPE_CHECKING
|
|
15
15
|
|
|
16
|
-
from markdown_strings import bold, unordered_list
|
|
17
|
-
|
|
18
16
|
from ...constants import TIMESTAMP_STR
|
|
19
17
|
from ...markdown import MarkdownMaker
|
|
20
18
|
from ...markdown.markdown import divider
|
|
19
|
+
from ...markdown.markdown_strings import bold, unordered_list
|
|
21
20
|
|
|
22
21
|
if TYPE_CHECKING:
|
|
23
22
|
from ...playbook_alerts.playbook_alerts import PBA_IdentityNovelExposure
|
{psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_malware_report.py
RENAMED
|
@@ -13,10 +13,9 @@
|
|
|
13
13
|
|
|
14
14
|
from typing import TYPE_CHECKING
|
|
15
15
|
|
|
16
|
-
from markdown_strings import bold, header
|
|
17
|
-
|
|
18
16
|
from ...markdown import MarkdownMaker, divider
|
|
19
17
|
from ...markdown.markdown import html_collapsible
|
|
18
|
+
from ...markdown.markdown_strings import bold, header
|
|
20
19
|
|
|
21
20
|
if TYPE_CHECKING:
|
|
22
21
|
from ...playbook_alerts.playbook_alerts import PBA_MalwareReport
|
{psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/markdown/markdown_third_party_risk.py
RENAMED
|
@@ -15,14 +15,13 @@ import itertools
|
|
|
15
15
|
from dataclasses import dataclass
|
|
16
16
|
from typing import TYPE_CHECKING
|
|
17
17
|
|
|
18
|
-
from markdown_strings import bold, unordered_list
|
|
19
|
-
|
|
20
18
|
from ...analyst_notes import AnalystNote
|
|
21
19
|
from ...analyst_notes.markdown import _cleanup_insikt_note_text
|
|
22
20
|
from ...constants import TIMESTAMP_STR
|
|
23
21
|
from ...enrich import EnrichedIP, EnrichmentData, SOAREnrichOut
|
|
24
22
|
from ...markdown import MarkdownMaker
|
|
25
23
|
from ...markdown.markdown import divider, header, html_collapsible
|
|
24
|
+
from ...markdown.markdown_strings import bold, unordered_list
|
|
26
25
|
from ..models.pba_third_party_risk import TPRAssessment
|
|
27
26
|
|
|
28
27
|
if TYPE_CHECKING:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "psengine"
|
|
3
|
-
version = "2.8.
|
|
3
|
+
version = "2.8.4"
|
|
4
4
|
readme = "README.md"
|
|
5
5
|
license = "MIT"
|
|
6
6
|
requires-python = ">=3.10, <3.15"
|
|
@@ -29,13 +29,14 @@ classifiers=[
|
|
|
29
29
|
dependencies = [
|
|
30
30
|
"typing_extensions >= 4.8.0",
|
|
31
31
|
"requests>=2.33.1",
|
|
32
|
+
"urllib3>=2.7.0",
|
|
33
|
+
"idna>=3.15",
|
|
32
34
|
"jsonpath_ng>=1.5.3, <=1.8.0",
|
|
33
35
|
"stix2~=3.0.2",
|
|
34
36
|
"python-dateutil>=2.7.0",
|
|
35
37
|
"more-itertools>=9.0.0, <=11.0.2",
|
|
36
38
|
"pydantic>=2.7, <3.0.0",
|
|
37
39
|
"pydantic-settings[toml]>=2.14.2,<2.15.0",
|
|
38
|
-
"markdown-strings==3.4.0"
|
|
39
40
|
]
|
|
40
41
|
|
|
41
42
|
|
|
@@ -61,11 +62,12 @@ docs = [
|
|
|
61
62
|
"mike>=2.1.4,<2.3.0",
|
|
62
63
|
"mkdocs~=1.6.1",
|
|
63
64
|
"mkdocs-material>=9.7.6,<9.8.0",
|
|
64
|
-
"mkdocstrings[python]>=0.
|
|
65
|
+
"mkdocstrings[python]>=1.0.4",
|
|
65
66
|
"griffe-typingdoc>=0.2.8,<0.4.0",
|
|
66
67
|
"mkdocs-codeinclude-plugin~=0.2.1",
|
|
67
68
|
"markdown-include~=0.8.1",
|
|
68
69
|
"mkdocs-exclude~=1.0.2",
|
|
70
|
+
"pymdown-extensions~=10.21.3",
|
|
69
71
|
|
|
70
72
|
# Tools for examples
|
|
71
73
|
"rich==15.0.0",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/pba_cyber_vulnerability.py
RENAMED
|
File without changes
|
|
File without changes
|
{psengine-2.8.2 → psengine-2.8.4}/psengine/playbook_alerts/models/pba_geopolitics_facility.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|