contentctl 5.6.0__tar.gz → 5.6.2__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.6.0 → contentctl-5.6.2}/PKG-INFO +18 -16
- {contentctl-5.6.0 → contentctl-5.6.2}/README.md +4 -2
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/GitService.py +7 -5
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructure.py +1 -1
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/enrichments/cve_enrichment.py +19 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/abstract_security_content_objects/detection_abstract.py +1 -1
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/base_test.py +1 -1
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/base_test_result.py +2 -2
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/data_source.py +5 -5
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/drilldown.py +2 -2
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/lookup.py +3 -3
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/mitre_attack_enrichment.py +4 -4
- {contentctl-5.6.0 → contentctl-5.6.2}/pyproject.toml +21 -19
- {contentctl-5.6.0 → contentctl-5.6.2}/LICENSE.md +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/__init__.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/build.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/deploy_acs.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/DetectionTestingManager.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/generate_detection_coverage_badge.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructureContainer.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructureServer.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/progress_bar.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/views/DetectionTestingView.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/views/DetectionTestingViewCLI.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/views/DetectionTestingViewFile.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/detection_testing/views/DetectionTestingViewWeb.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/doc_gen.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/initialize.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/inspect.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/new_content.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/release_notes.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/reporting.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/test.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/actions/validate.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/api.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/contentctl.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/enrichments/attack_enrichment.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/enrichments/splunk_app_enrichment.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/helper/link_validator.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/helper/logger.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/helper/splunk_app.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/helper/utils.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/input/director.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/input/new_content_questions.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/input/yml_reader.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/abstract_security_content_objects/security_content_object_abstract.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/alert_action.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/annotated_types.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/atomic.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/base_security_event.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/baseline.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/baseline_tags.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/config.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/constants.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/content_versioning_service.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/correlation_search.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/dashboard.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/deployment.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/deployment_email.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/deployment_notable.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/deployment_phantom.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/deployment_rba.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/deployment_scheduling.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/deployment_slack.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/detection.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/detection_metadata.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/detection_stanza.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/detection_tags.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/enums.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/errors.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/integration_test.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/integration_test_result.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/investigation.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/investigation_tags.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/macro.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/manual_test.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/manual_test_result.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/notable_action.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/notable_event.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/playbook.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/playbook_tags.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/rba.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/removed_security_content_object.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/risk_analysis_action.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/risk_event.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/risk_object.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/savedsearches_conf.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/security_content_object.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/story.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/story_tags.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/test_attack_data.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/test_group.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/threat_object.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/throttling.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/unit_test.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/unit_test_baseline.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/objects/unit_test_result.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/api_json_output.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/attack_nav_output.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/attack_nav_writer.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/conf_output.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/conf_writer.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/doc_md_output.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/jinja_writer.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/json_writer.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/runtime_csv_writer.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/svg_output.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/analyticstories_detections.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/analyticstories_investigations.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/analyticstories_stories.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/app.conf.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/app.manifest.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/collections.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/content-version.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/detection_count.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/detection_coverage.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/doc_detection_page.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/doc_detections.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/doc_navigation.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/doc_navigation_pages.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/doc_playbooks.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/doc_playbooks_page.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/doc_stories.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/doc_story_page.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/es_investigations_investigations.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/es_investigations_stories.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/header.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/macros.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/panel.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/savedsearches_baselines.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/savedsearches_detections.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/savedsearches_fbds.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/savedsearches_investigations.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/server.conf.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/transforms.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/workflow_actions.j2 +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/yml_writer.py +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/README.md +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_default.yml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/README/essoc_story_detail.txt +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/README/essoc_summary.txt +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/README/essoc_usage_dashboard.txt +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/README.md +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/default/analytic_stories.conf +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/default/commands.conf +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/default/data/ui/nav/default.xml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/default/data/ui/views/escu_summary.xml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/default/data/ui/views/feedback.xml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/default/use_case_library.conf +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/lookups/mitre_enrichment.csv +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/metadata/default.meta +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/static/appIcon.png +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/static/appIconAlt.png +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/static/appIconAlt_2x.png +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/static/appIcon_2x.png +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/data_sources/sysmon_eventid_1.yml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/datamodels_cim.conf +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/datamodels_custom.conf +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/deployments/escu_default_configuration_anomaly.yml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/deployments/escu_default_configuration_baseline.yml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/deployments/escu_default_configuration_correlation.yml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/deployments/escu_default_configuration_hunting.yml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/deployments/escu_default_configuration_ttp.yml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/detections/application/.gitkeep +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/detections/cloud/.gitkeep +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/detections/network/.gitkeep +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/detections/web/.gitkeep +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/macros/security_content_ctime.yml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/macros/security_content_summariesonly.yml +0 -0
- {contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/stories/cobalt_strike.yml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: contentctl
|
|
3
|
-
Version: 5.6.
|
|
3
|
+
Version: 5.6.2
|
|
4
4
|
Summary: Splunk Content Control Tool
|
|
5
5
|
License: Apache 2.0
|
|
6
6
|
License-File: LICENSE.md
|
|
@@ -12,32 +12,34 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
-
Requires-Dist: Jinja2 (>=3.1.
|
|
16
|
-
Requires-Dist: PyYAML (>=6.0.
|
|
15
|
+
Requires-Dist: Jinja2 (>=3.1.6,<4.0.0)
|
|
16
|
+
Requires-Dist: PyYAML (>=6.0.3,<7.0.0)
|
|
17
17
|
Requires-Dist: attackcti (>=0.5.4,<0.6)
|
|
18
18
|
Requires-Dist: bottle (>=0.12.25,<0.14.0)
|
|
19
|
-
Requires-Dist: docker (>=7.
|
|
20
|
-
Requires-Dist: gitpython (>=3.1.
|
|
19
|
+
Requires-Dist: docker (>=7.2.0,<8.0.0)
|
|
20
|
+
Requires-Dist: gitpython (>=3.1.62,<4.0.0)
|
|
21
21
|
Requires-Dist: pycvesearch (>=1.2,<2.0)
|
|
22
22
|
Requires-Dist: pydantic (>=2.9.2,<2.10.0)
|
|
23
|
-
Requires-Dist: pygit2 (>=1.
|
|
24
|
-
Requires-Dist: questionary (>=2.
|
|
25
|
-
Requires-Dist: requests (>=2.
|
|
26
|
-
Requires-Dist: rich (>=
|
|
23
|
+
Requires-Dist: pygit2 (>=1.20.1,<2.0.0)
|
|
24
|
+
Requires-Dist: questionary (>=2.1.1,<3.0.0)
|
|
25
|
+
Requires-Dist: requests (>=2.34.2)
|
|
26
|
+
Requires-Dist: rich (>=15.0.0,<16.0.0)
|
|
27
27
|
Requires-Dist: semantic-version (>=2.10.0,<3.0.0)
|
|
28
|
-
Requires-Dist: setuptools (
|
|
29
|
-
Requires-Dist: splunk-sdk (>=2.
|
|
30
|
-
Requires-Dist: tqdm (>=4.
|
|
31
|
-
Requires-Dist: tyro (>=0.
|
|
32
|
-
Requires-Dist: xmltodict (>=0.
|
|
28
|
+
Requires-Dist: setuptools (>=83.0.0,<84)
|
|
29
|
+
Requires-Dist: splunk-sdk (>=2.1.1,<3.0.0)
|
|
30
|
+
Requires-Dist: tqdm (>=4.70.1,<5.0.0)
|
|
31
|
+
Requires-Dist: tyro (>=1.0.16,<2.0.0)
|
|
32
|
+
Requires-Dist: xmltodict (>=1.0.4,<2.0.0)
|
|
33
33
|
Description-Content-Type: text/markdown
|
|
34
34
|
|
|
35
35
|
# contentctl
|
|
36
|
+
> ## The Future of contentctl
|
|
37
|
+
> We are shifting future investment from contentctl to Detection Studio as we work to bring this functionality into Splunk as an officially supported capability. This repository will remain publicly available for reference, but we are no longer accepting new pull requests or feature requests. Going forward, continued use of contentctl may require customer-managed customization to support specific environments and requirements.
|
|
38
|
+
|
|
36
39
|
<p align="center">
|
|
37
40
|
<img src="https://raw.githubusercontent.com/splunk/contentctl/refs/heads/main/docs/contentctl_logo_white.png" title="In case you're wondering, it's a capybara" alt="the logo for the contentctl project, which depicts a doodled 4 legged animal that is supposed to represent a capybara, with the name of the project below it" width="250" height="250"></p>
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
> Looking to migrate from an earlier release to the new contentctl v5+ ? Check out our migration guide [here](docs/contentctl_v5_migration_guide.md).
|
|
42
|
+
|
|
41
43
|
|
|
42
44
|
## What is contentctl?
|
|
43
45
|
`contentctl` is a tool developed by the Splunk Threat Research Team to help with managing the content living in [splunk/security_content](https://github.com/splunk/security_content) and producing the Enterprise Security Content Update app for Splunk. While its development is largely driven by STRT's needs, it has been somewhat genericized and can be used by customers and partners to package their own content. Simply put, `contentctl` is the workhorse that packages detections, macros, lookups, dashboards into a Splunk app that you can use, and that understands the YAML structure and project layout we've selected to keep development clean.
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# contentctl
|
|
2
|
+
> ## The Future of contentctl
|
|
3
|
+
> We are shifting future investment from contentctl to Detection Studio as we work to bring this functionality into Splunk as an officially supported capability. This repository will remain publicly available for reference, but we are no longer accepting new pull requests or feature requests. Going forward, continued use of contentctl may require customer-managed customization to support specific environments and requirements.
|
|
4
|
+
|
|
2
5
|
<p align="center">
|
|
3
6
|
<img src="https://raw.githubusercontent.com/splunk/contentctl/refs/heads/main/docs/contentctl_logo_white.png" title="In case you're wondering, it's a capybara" alt="the logo for the contentctl project, which depicts a doodled 4 legged animal that is supposed to represent a capybara, with the name of the project below it" width="250" height="250"></p>
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
> Looking to migrate from an earlier release to the new contentctl v5+ ? Check out our migration guide [here](docs/contentctl_v5_migration_guide.md).
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
## What is contentctl?
|
|
9
11
|
`contentctl` is a tool developed by the Splunk Threat Research Team to help with managing the content living in [splunk/security_content](https://github.com/splunk/security_content) and producing the Enterprise Security Content Update app for Splunk. While its development is largely driven by STRT's needs, it has been somewhat genericized and can be used by customers and partners to package their own content. Simply put, `contentctl` is the workhorse that packages detections, macros, lookups, dashboards into a Splunk app that you can use, and that understands the YAML structure and project layout we've selected to keep development clean.
|
|
@@ -147,11 +147,13 @@ class GitService(BaseModel):
|
|
|
147
147
|
# Filter to find the Lookup Object the references this CSV
|
|
148
148
|
matched = list(
|
|
149
149
|
filter(
|
|
150
|
-
lambda x:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
150
|
+
lambda x: (
|
|
151
|
+
isinstance(x, CSVLookup)
|
|
152
|
+
and not isinstance(
|
|
153
|
+
x, RuntimeCSV
|
|
154
|
+
) # RuntimeCSV is not used directly by any content
|
|
155
|
+
and x.filename == decoded_path
|
|
156
|
+
),
|
|
155
157
|
self.director.lookups,
|
|
156
158
|
)
|
|
157
159
|
)
|
|
@@ -149,7 +149,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
|
|
|
149
149
|
|
|
150
150
|
# Init the list of setup functions we always need
|
|
151
151
|
primary_setup_functions: list[
|
|
152
|
-
tuple[Callable[[],
|
|
152
|
+
tuple[Callable[[], client.Service | None], str]
|
|
153
153
|
] = [
|
|
154
154
|
(self.start, "Starting"),
|
|
155
155
|
(self.get_conn, "Waiting for App Installation"),
|
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import sys
|
|
4
|
+
import types
|
|
3
5
|
from decimal import Decimal
|
|
4
6
|
from typing import TYPE_CHECKING, Annotated, Union
|
|
5
7
|
|
|
8
|
+
try:
|
|
9
|
+
import pkg_resources # noqa: F401
|
|
10
|
+
except ModuleNotFoundError:
|
|
11
|
+
# setuptools >= 82 no longer ships pkg_resources. pycvesearch (unmaintained,
|
|
12
|
+
# no newer release available) still does `import pkg_resources` just to read
|
|
13
|
+
# its own version for a User-Agent header. Stub out the single attribute it
|
|
14
|
+
# needs so the import succeeds, rather than pinning setuptools to a version
|
|
15
|
+
# with a known vulnerability.
|
|
16
|
+
def _get_distribution(name: str) -> types.SimpleNamespace:
|
|
17
|
+
from importlib.metadata import version
|
|
18
|
+
|
|
19
|
+
return types.SimpleNamespace(version=version(name))
|
|
20
|
+
|
|
21
|
+
_pkg_resources_shim = types.ModuleType("pkg_resources")
|
|
22
|
+
_pkg_resources_shim.get_distribution = _get_distribution # type: ignore[attr-defined]
|
|
23
|
+
sys.modules["pkg_resources"] = _pkg_resources_shim
|
|
24
|
+
|
|
6
25
|
from pycvesearch import CVESearch
|
|
7
26
|
from pydantic import BaseModel, ConfigDict, Field, computed_field
|
|
8
27
|
|
|
@@ -117,7 +117,7 @@ class Detection_Abstract(SecurityContentObject):
|
|
|
117
117
|
f"Error getting severity - risk_score must be between 0-100, but was actually {self.risk_score}"
|
|
118
118
|
)
|
|
119
119
|
|
|
120
|
-
explanation:
|
|
120
|
+
explanation: str | None = Field(
|
|
121
121
|
default=None,
|
|
122
122
|
exclude=True, # Don't serialize this value when dumping the object
|
|
123
123
|
description="Provide an explanation to be included "
|
|
@@ -38,7 +38,7 @@ class BaseTestResult(BaseModel):
|
|
|
38
38
|
"""
|
|
39
39
|
|
|
40
40
|
# Message for the result
|
|
41
|
-
message: Union[
|
|
41
|
+
message: Union[str, None] = None
|
|
42
42
|
|
|
43
43
|
# Any exception that was raised (may be None)
|
|
44
44
|
exception: Union[Exception, None] = None
|
|
@@ -53,7 +53,7 @@ class BaseTestResult(BaseModel):
|
|
|
53
53
|
job_content: Union[Record, None] = None
|
|
54
54
|
|
|
55
55
|
# The Splunk endpoint URL
|
|
56
|
-
sid_link: Union[
|
|
56
|
+
sid_link: Union[str, None] = None
|
|
57
57
|
|
|
58
58
|
# Needed to allow for embedding of Exceptions in the model
|
|
59
59
|
model_config = ConfigDict(validate_assignment=True, arbitrary_types_allowed=True)
|
|
@@ -19,14 +19,14 @@ class DataSource(SecurityContentObject):
|
|
|
19
19
|
source: str = Field(...)
|
|
20
20
|
sourcetype: str = Field(...)
|
|
21
21
|
separator: Optional[str] = None
|
|
22
|
-
separator_value:
|
|
22
|
+
separator_value: str | None = None
|
|
23
23
|
configuration: Optional[str] = None
|
|
24
24
|
supported_TA: list[TA] = []
|
|
25
|
-
fields:
|
|
26
|
-
field_mappings:
|
|
25
|
+
fields: list | None = None
|
|
26
|
+
field_mappings: list | None = None
|
|
27
27
|
mitre_components: list[str] = []
|
|
28
|
-
convert_to_log_source:
|
|
29
|
-
example_log:
|
|
28
|
+
convert_to_log_source: list | None = None
|
|
29
|
+
example_log: str | None = None
|
|
30
30
|
output_fields: list[str] = []
|
|
31
31
|
status: ContentStatus = ContentStatus.production
|
|
32
32
|
|
|
@@ -22,14 +22,14 @@ class Drilldown(BaseModel):
|
|
|
22
22
|
description="The text of a drilldown search. This must be valid SPL.",
|
|
23
23
|
min_length=1,
|
|
24
24
|
)
|
|
25
|
-
earliest_offset:
|
|
25
|
+
earliest_offset: str | None = Field(
|
|
26
26
|
...,
|
|
27
27
|
description="Earliest offset time for the drilldown search. "
|
|
28
28
|
f"The most common value for this field is '{EARLIEST_OFFSET}', "
|
|
29
29
|
"but it is NOT the default value and must be supplied explicitly.",
|
|
30
30
|
min_length=1,
|
|
31
31
|
)
|
|
32
|
-
latest_offset:
|
|
32
|
+
latest_offset: str | None = Field(
|
|
33
33
|
...,
|
|
34
34
|
description="Latest offset time for the driolldown search. "
|
|
35
35
|
f"The most common value for this field is '{LATEST_OFFSET}', "
|
|
@@ -100,11 +100,11 @@ class Lookup(SecurityContentObject, abc.ABC):
|
|
|
100
100
|
match_type: list[Annotated[str, Field(pattern=r"(^WILDCARD|CIDR)\(.+\)$")]] = Field(
|
|
101
101
|
default=[]
|
|
102
102
|
)
|
|
103
|
-
min_matches:
|
|
104
|
-
max_matches:
|
|
103
|
+
min_matches: NonNegativeInt | None = Field(default=None)
|
|
104
|
+
max_matches: Annotated[NonNegativeInt, Field(ge=1, le=1000)] | None = Field(
|
|
105
105
|
default=None
|
|
106
106
|
)
|
|
107
|
-
case_sensitive_match:
|
|
107
|
+
case_sensitive_match: bool | None = Field(default=None)
|
|
108
108
|
status: ContentStatus = ContentStatus.production
|
|
109
109
|
|
|
110
110
|
@field_validator("status", mode="after")
|
|
@@ -41,9 +41,9 @@ class AttackGroupType(StrEnum):
|
|
|
41
41
|
class MitreExternalReference(BaseModel):
|
|
42
42
|
model_config = ConfigDict(extra="forbid")
|
|
43
43
|
source_name: str
|
|
44
|
-
external_id:
|
|
45
|
-
url:
|
|
46
|
-
description:
|
|
44
|
+
external_id: str | None = None
|
|
45
|
+
url: HttpUrl | None = None
|
|
46
|
+
description: str | None = None
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
class MitreAttackGroup(BaseModel):
|
|
@@ -58,7 +58,7 @@ class MitreAttackGroup(BaseModel):
|
|
|
58
58
|
group_id: str
|
|
59
59
|
id: str
|
|
60
60
|
matrix: list[AttackGroupMatrix]
|
|
61
|
-
mitre_attack_spec_version:
|
|
61
|
+
mitre_attack_spec_version: str | None
|
|
62
62
|
mitre_version: str
|
|
63
63
|
# assume that if the deprecated field is not present, then the group is not deprecated
|
|
64
64
|
mitre_deprecated: bool
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "contentctl"
|
|
3
3
|
|
|
4
|
-
version = "5.6.
|
|
4
|
+
version = "5.6.2"
|
|
5
5
|
|
|
6
6
|
description = "Splunk Content Control Tool"
|
|
7
7
|
authors = ["STRT <research@splunk.com>"]
|
|
@@ -14,31 +14,33 @@ contentctl = 'contentctl.contentctl:main'
|
|
|
14
14
|
[tool.poetry.dependencies]
|
|
15
15
|
|
|
16
16
|
python = "^3.11,<3.14"
|
|
17
|
+
# Pinned to 2.9.2. Newer pydantic versions (tested through 2.13.5) fail to
|
|
18
|
+
# resolve the forward reference from Story to Detection, raising
|
|
19
|
+
# "`Story` is not fully defined; you should define `Detection`, then call
|
|
20
|
+
# `Story.model_rebuild()`." during `contentctl validate`/`build`.
|
|
17
21
|
pydantic = "~2.9.2"
|
|
18
|
-
PyYAML = "^6.0.
|
|
19
|
-
requests = ">=2.
|
|
22
|
+
PyYAML = "^6.0.3"
|
|
23
|
+
requests = ">=2.34.2"
|
|
20
24
|
pycvesearch = "^1.2"
|
|
21
|
-
xmltodict = "
|
|
25
|
+
xmltodict = "^1.0.4"
|
|
26
|
+
# attackcti 0.6.x requires pydantic>=2.12.5, which conflicts with our
|
|
27
|
+
# pydantic pin above, so this stays capped below 0.6.
|
|
22
28
|
attackcti = ">=0.5.4,<0.6"
|
|
23
|
-
Jinja2 = "^3.1.
|
|
24
|
-
questionary = "^2.
|
|
25
|
-
docker = "^7.
|
|
26
|
-
splunk-sdk = "^2.
|
|
29
|
+
Jinja2 = "^3.1.6"
|
|
30
|
+
questionary = "^2.1.1"
|
|
31
|
+
docker = "^7.2.0"
|
|
32
|
+
splunk-sdk = "^2.1.1"
|
|
27
33
|
semantic-version = "^2.10.0"
|
|
28
34
|
bottle = ">=0.12.25,<0.14.0"
|
|
29
|
-
tqdm = "^4.
|
|
30
|
-
pygit2 = "^1.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
tyro = "^0.9.2,<0.9.23"
|
|
36
|
-
gitpython = "^3.1.43"
|
|
37
|
-
setuptools = "<81"
|
|
38
|
-
rich = "^14.0.0"
|
|
35
|
+
tqdm = "^4.70.1"
|
|
36
|
+
pygit2 = "^1.20.1"
|
|
37
|
+
tyro = "^1.0.16"
|
|
38
|
+
gitpython = "^3.1.62"
|
|
39
|
+
setuptools = ">=83.0.0,<84"
|
|
40
|
+
rich = "^15.0.0"
|
|
39
41
|
|
|
40
42
|
[tool.poetry.group.dev.dependencies]
|
|
41
|
-
ruff = "^0.
|
|
43
|
+
ruff = "^0.16.8"
|
|
42
44
|
|
|
43
45
|
[build-system]
|
|
44
46
|
requires = ["poetry-core>=1.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
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/analyticstories_detections.j2
RENAMED
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/analyticstories_investigations.j2
RENAMED
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/analyticstories_stories.j2
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
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/es_investigations_stories.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/savedsearches_baselines.j2
RENAMED
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/savedsearches_detections.j2
RENAMED
|
File without changes
|
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/output/templates/savedsearches_investigations.j2
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
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/README/essoc_summary.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/default/commands.conf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/lookups/mitre_enrichment.csv
RENAMED
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/metadata/default.meta
RENAMED
|
File without changes
|
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/static/appIconAlt.png
RENAMED
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/static/appIconAlt_2x.png
RENAMED
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/app_template/static/appIcon_2x.png
RENAMED
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/data_sources/sysmon_eventid_1.yml
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
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/macros/security_content_ctime.yml
RENAMED
|
File without changes
|
{contentctl-5.6.0 → contentctl-5.6.2}/contentctl/templates/macros/security_content_summariesonly.yml
RENAMED
|
File without changes
|
|
File without changes
|