contentctl 5.5.6__tar.gz → 5.5.8__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.
- {contentctl-5.5.6 → contentctl-5.5.8}/PKG-INFO +3 -3
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/deploy_acs.py +5 -3
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/DetectionTestingManager.py +3 -3
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/GitService.py +4 -4
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/generate_detection_coverage_badge.py +3 -3
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructure.py +15 -17
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructureContainer.py +9 -8
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/progress_bar.py +2 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/views/DetectionTestingViewCLI.py +4 -3
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/views/DetectionTestingViewFile.py +4 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/views/DetectionTestingViewWeb.py +7 -7
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/doc_gen.py +1 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/release_notes.py +2 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/reporting.py +3 -3
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/test.py +2 -3
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/validate.py +1 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/api.py +7 -6
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/contentctl.py +1 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/enrichments/attack_enrichment.py +1 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/enrichments/cve_enrichment.py +9 -6
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/enrichments/splunk_app_enrichment.py +5 -4
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/helper/link_validator.py +7 -7
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/helper/splunk_app.py +6 -6
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/helper/utils.py +8 -8
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/input/director.py +3 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/input/new_content_questions.py +1 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/input/yml_reader.py +2 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/abstract_security_content_objects/detection_abstract.py +1 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/alert_action.py +4 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/atomic.py +8 -5
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/base_test_result.py +2 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/baseline_tags.py +7 -6
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/config.py +5 -5
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/correlation_search.py +156 -139
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/dashboard.py +1 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/deployment_email.py +1 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/deployment_notable.py +3 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/deployment_phantom.py +1 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/deployment_rba.py +1 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/deployment_scheduling.py +1 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/deployment_slack.py +1 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/investigation_tags.py +6 -3
- contentctl-5.5.8/contentctl/objects/playbook_tags.py +297 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/story_tags.py +1 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/throttling.py +2 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/unit_test_baseline.py +2 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/unit_test_result.py +4 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/conf_output.py +2 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/conf_writer.py +5 -5
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/doc_md_output.py +0 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/jinja_writer.py +1 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/json_writer.py +1 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/yml_writer.py +3 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/pyproject.toml +33 -33
- contentctl-5.5.6/contentctl/objects/playbook_tags.py +0 -60
- {contentctl-5.5.6 → contentctl-5.5.8}/LICENSE.md +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/README.md +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/__init__.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/build.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructureServer.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/detection_testing/views/DetectionTestingView.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/initialize.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/inspect.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/actions/new_content.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/helper/logger.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/abstract_security_content_objects/security_content_object_abstract.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/annotated_types.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/base_security_event.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/base_test.py +1 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/baseline.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/constants.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/content_versioning_service.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/data_source.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/deployment.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/detection.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/detection_metadata.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/detection_stanza.py +1 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/detection_tags.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/drilldown.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/enums.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/errors.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/integration_test.py +2 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/integration_test_result.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/investigation.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/lookup.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/macro.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/manual_test.py +2 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/manual_test_result.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/mitre_attack_enrichment.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/notable_action.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/notable_event.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/playbook.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/rba.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/removed_security_content_object.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/risk_analysis_action.py +1 -1
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/risk_event.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/risk_object.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/savedsearches_conf.py +3 -3
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/security_content_object.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/story.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/test_attack_data.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/test_group.py +2 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/threat_object.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/objects/unit_test.py +2 -2
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/api_json_output.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/attack_nav_output.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/attack_nav_writer.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/runtime_csv_writer.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/svg_output.py +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/analyticstories_detections.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/analyticstories_investigations.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/analyticstories_stories.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/app.conf.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/app.manifest.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/collections.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/content-version.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/detection_count.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/detection_coverage.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/doc_detection_page.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/doc_detections.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/doc_navigation.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/doc_navigation_pages.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/doc_playbooks.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/doc_playbooks_page.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/doc_stories.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/doc_story_page.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/es_investigations_investigations.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/es_investigations_stories.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/header.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/macros.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/panel.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/savedsearches_baselines.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/savedsearches_detections.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/savedsearches_investigations.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/server.conf.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/transforms.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/output/templates/workflow_actions.j2 +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/README.md +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_default.yml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/README/essoc_story_detail.txt +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/README/essoc_summary.txt +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/README/essoc_usage_dashboard.txt +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/README.md +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/default/analytic_stories.conf +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/default/commands.conf +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/default/data/ui/nav/default.xml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/default/data/ui/views/escu_summary.xml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/default/data/ui/views/feedback.xml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/default/use_case_library.conf +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/lookups/mitre_enrichment.csv +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/metadata/default.meta +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/static/appIcon.png +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/static/appIconAlt.png +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/static/appIconAlt_2x.png +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/app_template/static/appIcon_2x.png +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/data_sources/sysmon_eventid_1.yml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/datamodels_cim.conf +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/datamodels_custom.conf +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/deployments/escu_default_configuration_anomaly.yml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/deployments/escu_default_configuration_baseline.yml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/deployments/escu_default_configuration_correlation.yml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/deployments/escu_default_configuration_hunting.yml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/deployments/escu_default_configuration_ttp.yml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/detections/application/.gitkeep +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/detections/cloud/.gitkeep +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/detections/network/.gitkeep +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/detections/web/.gitkeep +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/macros/security_content_ctime.yml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/macros/security_content_summariesonly.yml +0 -0
- {contentctl-5.5.6 → contentctl-5.5.8}/contentctl/templates/stories/cobalt_strike.yml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: contentctl
|
|
3
|
-
Version: 5.5.
|
|
3
|
+
Version: 5.5.8
|
|
4
4
|
Summary: Splunk Content Control Tool
|
|
5
5
|
License: Apache 2.0
|
|
6
6
|
Author: STRT
|
|
@@ -21,10 +21,10 @@ Requires-Dist: pycvesearch (>=1.2,<2.0)
|
|
|
21
21
|
Requires-Dist: pydantic (>=2.9.2,<2.10.0)
|
|
22
22
|
Requires-Dist: pygit2 (>=1.15.1,<2.0.0)
|
|
23
23
|
Requires-Dist: questionary (>=2.0.1,<3.0.0)
|
|
24
|
-
Requires-Dist: requests (>=2.32.
|
|
24
|
+
Requires-Dist: requests (>=2.32.4)
|
|
25
25
|
Requires-Dist: rich (>=14.0.0,<15.0.0)
|
|
26
26
|
Requires-Dist: semantic-version (>=2.10.0,<3.0.0)
|
|
27
|
-
Requires-Dist: setuptools (>=
|
|
27
|
+
Requires-Dist: setuptools (>=80.9.0)
|
|
28
28
|
Requires-Dist: splunk-sdk (>=2.0.2,<3.0.0)
|
|
29
29
|
Requires-Dist: tqdm (>=4.66.5,<5.0.0)
|
|
30
30
|
Requires-Dist: tyro (>=0.9.2,<0.9.23)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
from contentctl.objects.config import deploy_acs, StackType
|
|
2
|
-
from requests import post
|
|
3
1
|
import pprint
|
|
4
2
|
|
|
3
|
+
from requests import post
|
|
4
|
+
|
|
5
|
+
from contentctl.objects.config import StackType, deploy_acs
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
class Deploy:
|
|
7
9
|
def execute(self, config: deploy_acs, appinspect_token: str) -> None:
|
|
@@ -33,7 +35,7 @@ class Deploy:
|
|
|
33
35
|
raise Exception(f"Unsupported stack type: '{config.stack_type}'")
|
|
34
36
|
except Exception as e:
|
|
35
37
|
raise Exception(
|
|
36
|
-
f"Error installing to stack '{config.splunk_cloud_stack}' (stack_type='{config.stack_type}') via ACS:\n{
|
|
38
|
+
f"Error installing to stack '{config.splunk_cloud_stack}' (stack_type='{config.stack_type}') via ACS:\n{e!s}"
|
|
37
39
|
)
|
|
38
40
|
|
|
39
41
|
try:
|
|
@@ -162,10 +162,10 @@ class DetectionTestingManager(BaseModel):
|
|
|
162
162
|
print()
|
|
163
163
|
print(f"[{error_type}]:")
|
|
164
164
|
for error in errors[error_type]:
|
|
165
|
-
print(f"\t❌ {
|
|
165
|
+
print(f"\t❌ {error!s}")
|
|
166
166
|
if isinstance(error, ExceptionGroup):
|
|
167
167
|
for suberror in error.exceptions: # type: ignore
|
|
168
|
-
print(f"\t\t❌ {
|
|
168
|
+
print(f"\t\t❌ {suberror!s}") # type: ignore
|
|
169
169
|
print()
|
|
170
170
|
|
|
171
171
|
return self.output_dto
|
|
@@ -208,7 +208,7 @@ class DetectionTestingManager(BaseModel):
|
|
|
208
208
|
except Exception as e:
|
|
209
209
|
raise Exception(
|
|
210
210
|
"Failed to pull docker container image "
|
|
211
|
-
f"[{self.input_dto.config.container_settings.full_image_path}]: {
|
|
211
|
+
f"[{self.input_dto.config.container_settings.full_image_path}]: {e!s}"
|
|
212
212
|
)
|
|
213
213
|
|
|
214
214
|
already_staged_container_files = False
|
|
@@ -99,7 +99,7 @@ class GitService(BaseModel):
|
|
|
99
99
|
updated_detections.add(detectionObject)
|
|
100
100
|
else:
|
|
101
101
|
raise Exception(
|
|
102
|
-
f"Error getting detection object for file {
|
|
102
|
+
f"Error getting detection object for file {decoded_path!s}"
|
|
103
103
|
)
|
|
104
104
|
|
|
105
105
|
elif (
|
|
@@ -111,7 +111,7 @@ class GitService(BaseModel):
|
|
|
111
111
|
updated_macros.add(macroObject)
|
|
112
112
|
else:
|
|
113
113
|
raise Exception(
|
|
114
|
-
f"Error getting macro object for file {
|
|
114
|
+
f"Error getting macro object for file {decoded_path!s}"
|
|
115
115
|
)
|
|
116
116
|
|
|
117
117
|
elif (
|
|
@@ -125,7 +125,7 @@ class GitService(BaseModel):
|
|
|
125
125
|
updated_datasources.add(datasourceObject)
|
|
126
126
|
else:
|
|
127
127
|
raise Exception(
|
|
128
|
-
f"Error getting data source object for file {
|
|
128
|
+
f"Error getting data source object for file {decoded_path!s}"
|
|
129
129
|
)
|
|
130
130
|
|
|
131
131
|
elif decoded_path.is_relative_to(self.config.path / "lookups"):
|
|
@@ -172,7 +172,7 @@ class GitService(BaseModel):
|
|
|
172
172
|
|
|
173
173
|
else:
|
|
174
174
|
raise Exception(
|
|
175
|
-
f"Detected a changed file in the lookups/ directory '{
|
|
175
|
+
f"Detected a changed file in the lookups/ directory '{decoded_path!s}'.\n"
|
|
176
176
|
"Only files ending in .csv, .yml, or .mlmodel are supported in this "
|
|
177
177
|
"directory. This file must be removed from the lookups/ directory."
|
|
178
178
|
)
|
|
@@ -47,13 +47,13 @@ parser.add_argument(
|
|
|
47
47
|
try:
|
|
48
48
|
results = parser.parse_args()
|
|
49
49
|
except Exception as e:
|
|
50
|
-
print(f"Error parsing arguments: {
|
|
50
|
+
print(f"Error parsing arguments: {e!s}")
|
|
51
51
|
exit(1)
|
|
52
52
|
|
|
53
53
|
try:
|
|
54
54
|
summary_info = json.loads(results.input_summary_file.read())
|
|
55
55
|
except Exception as e:
|
|
56
|
-
print(f"Error loading {results.input_summary_file.name} JSON file: {
|
|
56
|
+
print(f"Error loading {results.input_summary_file.name} JSON file: {e!s}")
|
|
57
57
|
sys.exit(1)
|
|
58
58
|
|
|
59
59
|
if "summary" not in summary_info:
|
|
@@ -75,7 +75,7 @@ try:
|
|
|
75
75
|
RAW_BADGE_SVG.format(results.badge_string, "{:2.1f}%".format(pass_percent))
|
|
76
76
|
)
|
|
77
77
|
except Exception as e:
|
|
78
|
-
print(f"Error generating badge: {
|
|
78
|
+
print(f"Error generating badge: {e!s}")
|
|
79
79
|
sys.exit(1)
|
|
80
80
|
|
|
81
81
|
|
|
@@ -197,7 +197,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
197
197
|
self.check_for_teardown()
|
|
198
198
|
|
|
199
199
|
except Exception as e:
|
|
200
|
-
msg = f"[{self.get_name()}]: {
|
|
200
|
+
msg = f"[{self.get_name()}]: {e!s}"
|
|
201
201
|
self.finish()
|
|
202
202
|
if isinstance(e, ExceptionGroup):
|
|
203
203
|
raise ExceptionGroup(msg, e.exceptions) from e # type: ignore
|
|
@@ -310,7 +310,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
310
310
|
return
|
|
311
311
|
|
|
312
312
|
except Exception as e:
|
|
313
|
-
raise (Exception(f"Failure creating HEC Endpoint: {
|
|
313
|
+
raise (Exception(f"Failure creating HEC Endpoint: {e!s}"))
|
|
314
314
|
|
|
315
315
|
def get_all_indexes(self) -> None:
|
|
316
316
|
"""
|
|
@@ -327,7 +327,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
327
327
|
# Retrieve all available indexes on the splunk instance
|
|
328
328
|
self.all_indexes_on_server = indexes
|
|
329
329
|
except Exception as e:
|
|
330
|
-
raise (Exception(f"Failure getting indexes: {
|
|
330
|
+
raise (Exception(f"Failure getting indexes: {e!s}"))
|
|
331
331
|
|
|
332
332
|
def get_conn(self) -> client.Service:
|
|
333
333
|
try:
|
|
@@ -382,7 +382,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
382
382
|
pass
|
|
383
383
|
except Exception as e:
|
|
384
384
|
self.pbar.write(
|
|
385
|
-
f"Error getting API connection (not quitting) '{type(e).__name__}': {
|
|
385
|
+
f"Error getting API connection (not quitting) '{type(e).__name__}': {e!s}"
|
|
386
386
|
)
|
|
387
387
|
|
|
388
388
|
for _ in range(sleep_seconds):
|
|
@@ -402,7 +402,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
402
402
|
pass
|
|
403
403
|
else:
|
|
404
404
|
raise Exception(
|
|
405
|
-
f"Error creating index {self.sync_obj.replay_index} - {
|
|
405
|
+
f"Error creating index {self.sync_obj.replay_index} - {e!s}"
|
|
406
406
|
)
|
|
407
407
|
|
|
408
408
|
def configure_imported_roles(
|
|
@@ -426,7 +426,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
426
426
|
)
|
|
427
427
|
return
|
|
428
428
|
except Exception as e:
|
|
429
|
-
msg = f"Error configuring roles: {
|
|
429
|
+
msg = f"Error configuring roles: {e!s}"
|
|
430
430
|
self.pbar.write(msg)
|
|
431
431
|
raise Exception(msg) from e
|
|
432
432
|
|
|
@@ -436,7 +436,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
436
436
|
self.get_conn().post(endpoint, value=";".join(self.all_indexes_on_server))
|
|
437
437
|
except Exception as e:
|
|
438
438
|
self.pbar.write(
|
|
439
|
-
f"Error configuring deleteIndexesAllowed with '{self.all_indexes_on_server}': [{
|
|
439
|
+
f"Error configuring deleteIndexesAllowed with '{self.all_indexes_on_server}': [{e!s}]"
|
|
440
440
|
)
|
|
441
441
|
|
|
442
442
|
def wait_for_conf_file(self, app_name: str, conf_file_name: str):
|
|
@@ -474,12 +474,12 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
474
474
|
parser.read(custom_acceleration_datamodels)
|
|
475
475
|
if len(parser.keys()) > 1:
|
|
476
476
|
self.pbar.write(
|
|
477
|
-
f"Read {len(parser) - 1} custom datamodels from {
|
|
477
|
+
f"Read {len(parser) - 1} custom datamodels from {custom_acceleration_datamodels!s}!"
|
|
478
478
|
)
|
|
479
479
|
|
|
480
480
|
if not cim_acceleration_datamodels.is_file():
|
|
481
481
|
self.pbar.write(
|
|
482
|
-
f"******************************\nDATAMODEL ACCELERATION FILE {
|
|
482
|
+
f"******************************\nDATAMODEL ACCELERATION FILE {cim_acceleration_datamodels!s} NOT "
|
|
483
483
|
"FOUND. CIM DATAMODELS NOT ACCELERATED\n******************************\n"
|
|
484
484
|
)
|
|
485
485
|
else:
|
|
@@ -499,7 +499,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
499
499
|
|
|
500
500
|
except Exception as e:
|
|
501
501
|
self.pbar.write(
|
|
502
|
-
f"Error creating the conf Datamodel {datamodel_name} key/value {name}/{value}: {
|
|
502
|
+
f"Error creating the conf Datamodel {datamodel_name} key/value {name}/{value}: {e!s}"
|
|
503
503
|
)
|
|
504
504
|
|
|
505
505
|
def execute(self):
|
|
@@ -528,9 +528,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
528
528
|
self.finish()
|
|
529
529
|
return
|
|
530
530
|
except Exception as e:
|
|
531
|
-
self.pbar.write(
|
|
532
|
-
f"Error testing detection: {type(e).__name__}: {str(e)}"
|
|
533
|
-
)
|
|
531
|
+
self.pbar.write(f"Error testing detection: {type(e).__name__}: {e!s}")
|
|
534
532
|
raise e
|
|
535
533
|
finally:
|
|
536
534
|
self.sync_obj.outputQueue.append(detection)
|
|
@@ -1365,7 +1363,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
1365
1363
|
except Exception as e:
|
|
1366
1364
|
raise (
|
|
1367
1365
|
Exception(
|
|
1368
|
-
f"Trouble deleting data using the search {splunk_search}: {
|
|
1366
|
+
f"Trouble deleting data using the search {splunk_search}: {e!s}"
|
|
1369
1367
|
)
|
|
1370
1368
|
)
|
|
1371
1369
|
|
|
@@ -1440,7 +1438,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
1440
1438
|
except Exception as e:
|
|
1441
1439
|
raise (
|
|
1442
1440
|
Exception(
|
|
1443
|
-
f"Could not download attack data file [{attack_data_file.data}]:{
|
|
1441
|
+
f"Could not download attack data file [{attack_data_file.data}]:{e!s}"
|
|
1444
1442
|
)
|
|
1445
1443
|
)
|
|
1446
1444
|
|
|
@@ -1514,7 +1512,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
1514
1512
|
except Exception as e:
|
|
1515
1513
|
raise (
|
|
1516
1514
|
Exception(
|
|
1517
|
-
f"There was an exception sending attack_data to HEC: {
|
|
1515
|
+
f"There was an exception sending attack_data to HEC: {e!s}"
|
|
1518
1516
|
)
|
|
1519
1517
|
)
|
|
1520
1518
|
|
|
@@ -1558,7 +1556,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
1558
1556
|
)
|
|
1559
1557
|
)
|
|
1560
1558
|
except Exception as e:
|
|
1561
|
-
raise (Exception(f"There was an exception in the post: {
|
|
1559
|
+
raise (Exception(f"There was an exception in the post: {e!s}"))
|
|
1562
1560
|
|
|
1563
1561
|
def status(self):
|
|
1564
1562
|
pass
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import docker
|
|
2
|
+
import docker.models.containers
|
|
3
|
+
import docker.models.resource
|
|
4
|
+
import docker.types
|
|
5
|
+
|
|
1
6
|
from contentctl.actions.detection_testing.infrastructures.DetectionTestingInfrastructure import (
|
|
2
7
|
DetectionTestingInfrastructure,
|
|
3
8
|
)
|
|
4
9
|
from contentctl.objects.config import test
|
|
5
|
-
import docker.models.resource
|
|
6
|
-
import docker.models.containers
|
|
7
|
-
import docker
|
|
8
|
-
import docker.types
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class DetectionTestingInfrastructureContainer(DetectionTestingInfrastructure):
|
|
@@ -34,7 +35,7 @@ class DetectionTestingInfrastructureContainer(DetectionTestingInfrastructure):
|
|
|
34
35
|
self.removeContainer()
|
|
35
36
|
pass
|
|
36
37
|
except Exception as e:
|
|
37
|
-
raise (Exception(f"Error removing container: {
|
|
38
|
+
raise (Exception(f"Error removing container: {e!s}"))
|
|
38
39
|
super().finish()
|
|
39
40
|
|
|
40
41
|
def get_name(self) -> str:
|
|
@@ -46,7 +47,7 @@ class DetectionTestingInfrastructureContainer(DetectionTestingInfrastructure):
|
|
|
46
47
|
|
|
47
48
|
return c
|
|
48
49
|
except Exception as e:
|
|
49
|
-
raise (Exception(f"Failed to get docker client: {
|
|
50
|
+
raise (Exception(f"Failed to get docker client: {e!s}"))
|
|
50
51
|
|
|
51
52
|
def check_for_teardown(self):
|
|
52
53
|
try:
|
|
@@ -56,7 +57,7 @@ class DetectionTestingInfrastructureContainer(DetectionTestingInfrastructure):
|
|
|
56
57
|
except Exception as e:
|
|
57
58
|
if self.sync_obj.terminate is not True:
|
|
58
59
|
self.pbar.write(
|
|
59
|
-
f"Error: could not get container [{self.get_name()}]: {
|
|
60
|
+
f"Error: could not get container [{self.get_name()}]: {e!s}"
|
|
60
61
|
)
|
|
61
62
|
self.sync_obj.terminate = True
|
|
62
63
|
else:
|
|
@@ -175,6 +176,6 @@ class DetectionTestingInfrastructureContainer(DetectionTestingInfrastructure):
|
|
|
175
176
|
except Exception as e:
|
|
176
177
|
raise (
|
|
177
178
|
Exception(
|
|
178
|
-
f"Could not remove Docker Container [{self.get_name()}]: {
|
|
179
|
+
f"Could not remove Docker Container [{self.get_name()}]: {e!s}"
|
|
179
180
|
)
|
|
180
181
|
)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
import tqdm
|
|
4
|
+
|
|
1
5
|
from contentctl.actions.detection_testing.views.DetectionTestingView import (
|
|
2
6
|
DetectionTestingView,
|
|
3
7
|
)
|
|
4
8
|
|
|
5
|
-
import time
|
|
6
|
-
import tqdm
|
|
7
|
-
|
|
8
9
|
|
|
9
10
|
class DetectionTestingViewCLI(DetectionTestingView, arbitrary_types_allowed=True):
|
|
10
11
|
pbar: tqdm.tqdm = None
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import webbrowser
|
|
1
2
|
from threading import Thread
|
|
3
|
+
from wsgiref.simple_server import WSGIRequestHandler, make_server
|
|
2
4
|
|
|
3
|
-
from bottle import template, Bottle, ServerAdapter
|
|
4
|
-
from wsgiref.simple_server import make_server, WSGIRequestHandler
|
|
5
5
|
import jinja2
|
|
6
|
-
import
|
|
6
|
+
from bottle import Bottle, ServerAdapter, template
|
|
7
7
|
from pydantic import ConfigDict
|
|
8
8
|
|
|
9
9
|
from contentctl.actions.detection_testing.views.DetectionTestingView import (
|
|
@@ -39,8 +39,8 @@ $(document).ready(function () {
|
|
|
39
39
|
{% for containerName, data in currentTestingQueue.items() %}
|
|
40
40
|
<tr>
|
|
41
41
|
<td>{{ containerName }}</td>
|
|
42
|
-
<td>{{ data["name"] }}</td>
|
|
43
|
-
<td>{{ data["search"] }}</td>
|
|
42
|
+
<td>{{ data["name"] }}</td>
|
|
43
|
+
<td>{{ data["search"] }}</td>
|
|
44
44
|
</tr>
|
|
45
45
|
{% endfor %}
|
|
46
46
|
</tbody>
|
|
@@ -69,7 +69,7 @@ $(document).ready(function () {
|
|
|
69
69
|
{% else %}
|
|
70
70
|
<td style="font-weight: bold;background-color: #ff9999"><b>False</b></td>
|
|
71
71
|
{% endif %}
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
</tr>
|
|
74
74
|
{% endfor %}
|
|
75
75
|
{% endfor %}
|
|
@@ -118,7 +118,7 @@ class DetectionTestingViewWeb(DetectionTestingView):
|
|
|
118
118
|
try:
|
|
119
119
|
webbrowser.open(f"http://{self.server.host}:{DEFAULT_WEB_UI_PORT}")
|
|
120
120
|
except Exception as e:
|
|
121
|
-
print(f"Could not open webbrowser for status page: {
|
|
121
|
+
print(f"Could not open webbrowser for status page: {e!s}")
|
|
122
122
|
|
|
123
123
|
def stop(self):
|
|
124
124
|
if self.server.server is None:
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
|
-
|
|
3
2
|
from dataclasses import dataclass
|
|
4
3
|
|
|
5
|
-
from contentctl.input.director import
|
|
4
|
+
from contentctl.input.director import Director, DirectorInputDto, DirectorOutputDto
|
|
6
5
|
from contentctl.output.doc_md_output import DocMdOutput
|
|
7
6
|
|
|
8
7
|
|
|
@@ -46,7 +46,7 @@ class ReleaseNotes:
|
|
|
46
46
|
file_path
|
|
47
47
|
).replace(str(repo_path), "")
|
|
48
48
|
playbook_link = playbook_link.replace(
|
|
49
|
-
"
|
|
49
|
+
"yml", "/"
|
|
50
50
|
).lower()
|
|
51
51
|
updates.append(
|
|
52
52
|
"- "
|
|
@@ -155,7 +155,7 @@ class ReleaseNotes:
|
|
|
155
155
|
|
|
156
156
|
except yaml.YAMLError as exc:
|
|
157
157
|
raise Exception(
|
|
158
|
-
f"Error parsing YAML file for release_notes {file_path}: {
|
|
158
|
+
f"Error parsing YAML file for release_notes {file_path}: {exc!s}"
|
|
159
159
|
)
|
|
160
160
|
else:
|
|
161
161
|
warnings.append(
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
|
|
3
3
|
from contentctl.input.director import DirectorOutputDto
|
|
4
|
-
from contentctl.output.svg_output import SvgOutput
|
|
5
|
-
from contentctl.output.attack_nav_output import AttackNavOutput
|
|
6
4
|
from contentctl.objects.config import report
|
|
5
|
+
from contentctl.output.attack_nav_output import AttackNavOutput
|
|
6
|
+
from contentctl.output.svg_output import SvgOutput
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
@dataclass(frozen=True)
|
|
@@ -24,7 +24,7 @@ class Reporting:
|
|
|
24
24
|
)
|
|
25
25
|
else:
|
|
26
26
|
raise Exception(
|
|
27
|
-
f"Error writing reporting : '{input_dto.config.getReportingPath()}': {
|
|
27
|
+
f"Error writing reporting : '{input_dto.config.getReportingPath()}': {e!s}"
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
print("Creating GitHub Badges...")
|
|
@@ -18,9 +18,8 @@ from contentctl.actions.detection_testing.views.DetectionTestingViewFile import
|
|
|
18
18
|
from contentctl.actions.detection_testing.views.DetectionTestingViewWeb import (
|
|
19
19
|
DetectionTestingViewWeb,
|
|
20
20
|
)
|
|
21
|
-
from contentctl.objects.config import Changes, Selected
|
|
21
|
+
from contentctl.objects.config import Changes, Selected, test_servers
|
|
22
22
|
from contentctl.objects.config import test as test_
|
|
23
|
-
from contentctl.objects.config import test_servers
|
|
24
23
|
from contentctl.objects.detection import Detection
|
|
25
24
|
from contentctl.objects.integration_test import IntegrationTest
|
|
26
25
|
|
|
@@ -151,5 +150,5 @@ class Test:
|
|
|
151
150
|
return summary.get("success", False)
|
|
152
151
|
|
|
153
152
|
except Exception as e:
|
|
154
|
-
print(f"Error determining if whole test was successful: {
|
|
153
|
+
print(f"Error determining if whole test was successful: {e!s}")
|
|
155
154
|
return False
|
|
@@ -118,7 +118,7 @@ class Validate:
|
|
|
118
118
|
)
|
|
119
119
|
except Exception as e:
|
|
120
120
|
errors.append(
|
|
121
|
-
f"Error processing checking version of TA {supported_TA.name}: {
|
|
121
|
+
f"Error processing checking version of TA {supported_TA.name}: {e!s}"
|
|
122
122
|
)
|
|
123
123
|
|
|
124
124
|
if len(errors) > 0:
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Any,
|
|
2
|
+
from typing import Any, Type, Union
|
|
3
|
+
|
|
4
|
+
from contentctl.input.director import DirectorOutputDto
|
|
3
5
|
from contentctl.input.yml_reader import YmlReader
|
|
4
|
-
from contentctl.objects.config import
|
|
6
|
+
from contentctl.objects.config import test, test_common, test_servers
|
|
5
7
|
from contentctl.objects.security_content_object import SecurityContentObject
|
|
6
|
-
from contentctl.input.director import DirectorOutputDto
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
def config_from_file(
|
|
@@ -36,7 +37,7 @@ def config_from_file(
|
|
|
36
37
|
|
|
37
38
|
except Exception as e:
|
|
38
39
|
raise Exception(
|
|
39
|
-
f"Failed to load contentctl configuration from file '{path}': {
|
|
40
|
+
f"Failed to load contentctl configuration from file '{path}': {e!s}"
|
|
40
41
|
)
|
|
41
42
|
|
|
42
43
|
# Apply settings that have been overridden from the ones in the file
|
|
@@ -45,7 +46,7 @@ def config_from_file(
|
|
|
45
46
|
except Exception as e:
|
|
46
47
|
raise Exception(
|
|
47
48
|
f"Failed updating dictionary of values read from file '{path}'"
|
|
48
|
-
f" with the dictionary of arguments passed: {
|
|
49
|
+
f" with the dictionary of arguments passed: {e!s}"
|
|
49
50
|
)
|
|
50
51
|
|
|
51
52
|
# The function below will throw its own descriptive exception if it fails
|
|
@@ -78,7 +79,7 @@ def config_from_dict(
|
|
|
78
79
|
try:
|
|
79
80
|
test_object = configType.model_validate(config)
|
|
80
81
|
except Exception as e:
|
|
81
|
-
raise Exception(f"Failed to load contentctl configuration from dict:\n{
|
|
82
|
+
raise Exception(f"Failed to load contentctl configuration from dict:\n{e!s}")
|
|
82
83
|
|
|
83
84
|
return test_object
|
|
84
85
|
|
|
@@ -206,7 +206,7 @@ def main():
|
|
|
206
206
|
config_obj = YmlReader().load_file(configFile, add_fields=False)
|
|
207
207
|
t = test.model_validate(config_obj)
|
|
208
208
|
except Exception as e:
|
|
209
|
-
print(f"Error validating 'contentctl.yml':\n{
|
|
209
|
+
print(f"Error validating 'contentctl.yml':\n{e!s}")
|
|
210
210
|
sys.exit(1)
|
|
211
211
|
|
|
212
212
|
# For ease of generating the constructor, we want to allow construction
|
|
@@ -183,7 +183,7 @@ class AttackEnrichment(BaseModel):
|
|
|
183
183
|
)
|
|
184
184
|
|
|
185
185
|
except Exception as err:
|
|
186
|
-
raise Exception(f"Error getting MITRE Enrichment: {
|
|
186
|
+
raise Exception(f"Error getting MITRE Enrichment: {err!s}")
|
|
187
187
|
|
|
188
188
|
print("Done!")
|
|
189
189
|
return attack_lookup
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Annotated, Union, TYPE_CHECKING
|
|
4
|
-
from pydantic import ConfigDict, BaseModel, Field, computed_field
|
|
2
|
+
|
|
5
3
|
from decimal import Decimal
|
|
4
|
+
from typing import TYPE_CHECKING, Annotated, Union
|
|
5
|
+
|
|
6
|
+
from pycvesearch import CVESearch
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field, computed_field
|
|
8
|
+
|
|
6
9
|
from contentctl.objects.annotated_types import CVE_TYPE
|
|
7
10
|
|
|
8
11
|
if TYPE_CHECKING:
|
|
@@ -46,7 +49,7 @@ class CveEnrichment(BaseModel):
|
|
|
46
49
|
return CveEnrichment(use_enrichment=True, cve_api_obj=cve_api_obj)
|
|
47
50
|
except Exception as e:
|
|
48
51
|
raise Exception(
|
|
49
|
-
f"Error setting CVE_SEARCH API to: {CVESSEARCH_API_URL}: {
|
|
52
|
+
f"Error setting CVE_SEARCH API to: {CVESSEARCH_API_URL}: {e!s}"
|
|
50
53
|
)
|
|
51
54
|
|
|
52
55
|
return CveEnrichment(use_enrichment=False, cve_api_obj=None)
|
|
@@ -57,14 +60,14 @@ class CveEnrichment(BaseModel):
|
|
|
57
60
|
if not self.use_enrichment:
|
|
58
61
|
return CveEnrichmentObj(
|
|
59
62
|
id=cve_id,
|
|
60
|
-
cvss=Decimal(5.0),
|
|
63
|
+
cvss=Decimal("5.0"),
|
|
61
64
|
summary="SUMMARY NOT AVAILABLE! ONLY THE LINK WILL BE USED AT THIS TIME",
|
|
62
65
|
)
|
|
63
66
|
else:
|
|
64
67
|
print("WARNING - Dynamic enrichment not supported at this time.")
|
|
65
68
|
return CveEnrichmentObj(
|
|
66
69
|
id=cve_id,
|
|
67
|
-
cvss=Decimal(5.0),
|
|
70
|
+
cvss=Decimal("5.0"),
|
|
68
71
|
summary="SUMMARY NOT AVAILABLE! ONLY THE LINK WILL BE USED AT THIS TIME",
|
|
69
72
|
)
|
|
70
73
|
# Depending on needs, we may add dynamic enrichment functionality back to the tool
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
import xmltodict
|
|
3
1
|
import functools
|
|
4
|
-
import shelve
|
|
5
2
|
import os
|
|
3
|
+
import shelve
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
import xmltodict
|
|
6
7
|
|
|
7
8
|
SPLUNKBASE_API_URL = "https://apps.splunk.com/api/apps/entriesbyid/"
|
|
8
9
|
|
|
@@ -75,7 +76,7 @@ class SplunkAppEnrichment:
|
|
|
75
76
|
splunk_app_enriched["url"] = ""
|
|
76
77
|
except Exception as e:
|
|
77
78
|
print(
|
|
78
|
-
f"There was an unknown error enriching the Splunk TA [{splunk_ta}]: {
|
|
79
|
+
f"There was an unknown error enriching the Splunk TA [{splunk_ta}]: {e!s}"
|
|
79
80
|
)
|
|
80
81
|
splunk_app_enriched["name"] = splunk_ta
|
|
81
82
|
splunk_app_enriched["url"] = ""
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
from pydantic import BaseModel, model_validator
|
|
2
|
-
from typing import Union, Callable, Any
|
|
3
|
-
import requests
|
|
4
|
-
import urllib3
|
|
5
|
-
import urllib3.exceptions
|
|
6
|
-
import time
|
|
7
1
|
import abc
|
|
8
|
-
|
|
9
2
|
import os
|
|
10
3
|
import shelve
|
|
4
|
+
import time
|
|
5
|
+
from typing import Any, Callable, Union
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
import urllib3
|
|
9
|
+
import urllib3.exceptions
|
|
10
|
+
from pydantic import BaseModel, model_validator
|
|
11
11
|
|
|
12
12
|
DEFAULT_USER_AGENT_STRING = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36"
|
|
13
13
|
ALLOWED_HTTP_CODES = [200]
|