contentctl 4.4.7__py3-none-any.whl → 5.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- contentctl/__init__.py +1 -1
- contentctl/actions/build.py +102 -57
- contentctl/actions/deploy_acs.py +29 -24
- contentctl/actions/detection_testing/DetectionTestingManager.py +66 -42
- contentctl/actions/detection_testing/GitService.py +134 -76
- contentctl/actions/detection_testing/generate_detection_coverage_badge.py +48 -30
- contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructure.py +192 -147
- contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructureContainer.py +45 -32
- contentctl/actions/detection_testing/progress_bar.py +9 -6
- contentctl/actions/detection_testing/views/DetectionTestingView.py +16 -19
- contentctl/actions/detection_testing/views/DetectionTestingViewCLI.py +1 -5
- contentctl/actions/detection_testing/views/DetectionTestingViewFile.py +2 -2
- contentctl/actions/detection_testing/views/DetectionTestingViewWeb.py +1 -4
- contentctl/actions/doc_gen.py +9 -5
- contentctl/actions/initialize.py +45 -33
- contentctl/actions/inspect.py +118 -61
- contentctl/actions/new_content.py +155 -108
- contentctl/actions/release_notes.py +276 -146
- contentctl/actions/reporting.py +23 -19
- contentctl/actions/test.py +33 -28
- contentctl/actions/validate.py +55 -34
- contentctl/api.py +54 -45
- contentctl/contentctl.py +124 -90
- contentctl/enrichments/attack_enrichment.py +112 -72
- contentctl/enrichments/cve_enrichment.py +34 -28
- contentctl/enrichments/splunk_app_enrichment.py +38 -36
- contentctl/helper/link_validator.py +101 -78
- contentctl/helper/splunk_app.py +69 -41
- contentctl/helper/utils.py +58 -53
- contentctl/input/director.py +68 -36
- contentctl/input/new_content_questions.py +27 -35
- contentctl/input/yml_reader.py +28 -18
- contentctl/objects/abstract_security_content_objects/detection_abstract.py +303 -259
- contentctl/objects/abstract_security_content_objects/security_content_object_abstract.py +115 -52
- contentctl/objects/alert_action.py +10 -9
- contentctl/objects/annotated_types.py +1 -1
- contentctl/objects/atomic.py +65 -54
- contentctl/objects/base_test.py +5 -3
- contentctl/objects/base_test_result.py +19 -11
- contentctl/objects/baseline.py +62 -30
- contentctl/objects/baseline_tags.py +30 -24
- contentctl/objects/config.py +790 -597
- contentctl/objects/constants.py +33 -56
- contentctl/objects/correlation_search.py +150 -136
- contentctl/objects/dashboard.py +55 -41
- contentctl/objects/data_source.py +16 -17
- contentctl/objects/deployment.py +43 -44
- contentctl/objects/deployment_email.py +3 -2
- contentctl/objects/deployment_notable.py +4 -2
- contentctl/objects/deployment_phantom.py +7 -6
- contentctl/objects/deployment_rba.py +3 -2
- contentctl/objects/deployment_scheduling.py +3 -2
- contentctl/objects/deployment_slack.py +3 -2
- contentctl/objects/detection.py +5 -2
- contentctl/objects/detection_metadata.py +1 -0
- contentctl/objects/detection_stanza.py +7 -2
- contentctl/objects/detection_tags.py +58 -103
- contentctl/objects/drilldown.py +66 -34
- contentctl/objects/enums.py +81 -100
- contentctl/objects/errors.py +16 -24
- contentctl/objects/integration_test.py +3 -3
- contentctl/objects/integration_test_result.py +1 -0
- contentctl/objects/investigation.py +59 -36
- contentctl/objects/investigation_tags.py +30 -19
- contentctl/objects/lookup.py +304 -101
- contentctl/objects/macro.py +55 -39
- contentctl/objects/manual_test.py +3 -3
- contentctl/objects/manual_test_result.py +1 -0
- contentctl/objects/mitre_attack_enrichment.py +17 -16
- contentctl/objects/notable_action.py +2 -1
- contentctl/objects/notable_event.py +1 -3
- contentctl/objects/playbook.py +37 -35
- contentctl/objects/playbook_tags.py +23 -13
- contentctl/objects/rba.py +96 -0
- contentctl/objects/risk_analysis_action.py +15 -11
- contentctl/objects/risk_event.py +110 -160
- contentctl/objects/risk_object.py +1 -0
- contentctl/objects/savedsearches_conf.py +9 -7
- contentctl/objects/security_content_object.py +5 -2
- contentctl/objects/story.py +54 -49
- contentctl/objects/story_tags.py +56 -45
- contentctl/objects/test_attack_data.py +2 -1
- contentctl/objects/test_group.py +5 -2
- contentctl/objects/threat_object.py +1 -0
- contentctl/objects/throttling.py +27 -18
- contentctl/objects/unit_test.py +3 -4
- contentctl/objects/unit_test_baseline.py +5 -5
- contentctl/objects/unit_test_result.py +6 -6
- contentctl/output/api_json_output.py +233 -220
- contentctl/output/attack_nav_output.py +21 -21
- contentctl/output/attack_nav_writer.py +29 -37
- contentctl/output/conf_output.py +235 -172
- contentctl/output/conf_writer.py +201 -125
- contentctl/output/data_source_writer.py +38 -26
- contentctl/output/doc_md_output.py +53 -27
- contentctl/output/jinja_writer.py +19 -15
- contentctl/output/json_writer.py +21 -11
- contentctl/output/svg_output.py +56 -38
- contentctl/output/templates/analyticstories_detections.j2 +2 -2
- contentctl/output/templates/analyticstories_stories.j2 +1 -1
- contentctl/output/templates/collections.j2 +1 -1
- contentctl/output/templates/doc_detections.j2 +0 -5
- contentctl/output/templates/es_investigations_investigations.j2 +1 -1
- contentctl/output/templates/es_investigations_stories.j2 +1 -1
- contentctl/output/templates/savedsearches_baselines.j2 +2 -2
- contentctl/output/templates/savedsearches_detections.j2 +10 -11
- contentctl/output/templates/savedsearches_investigations.j2 +2 -2
- contentctl/output/templates/transforms.j2 +6 -8
- contentctl/output/yml_writer.py +29 -20
- contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml +16 -34
- contentctl/templates/stories/cobalt_strike.yml +1 -0
- {contentctl-4.4.7.dist-info → contentctl-5.0.0.dist-info}/METADATA +5 -4
- contentctl-5.0.0.dist-info/RECORD +168 -0
- {contentctl-4.4.7.dist-info → contentctl-5.0.0.dist-info}/WHEEL +1 -1
- contentctl/actions/initialize_old.py +0 -245
- contentctl/objects/event_source.py +0 -11
- contentctl/objects/observable.py +0 -37
- contentctl/output/detection_writer.py +0 -28
- contentctl/output/new_content_yml_output.py +0 -56
- contentctl/output/yml_output.py +0 -66
- contentctl-4.4.7.dist-info/RECORD +0 -173
- {contentctl-4.4.7.dist-info → contentctl-5.0.0.dist-info}/LICENSE.md +0 -0
- {contentctl-4.4.7.dist-info → contentctl-5.0.0.dist-info}/entry_points.txt +0 -0
contentctl/objects/constants.py
CHANGED
|
@@ -15,7 +15,7 @@ ATTACK_TACTICS_KILLCHAIN_MAPPING = {
|
|
|
15
15
|
"Collection": "Exploitation",
|
|
16
16
|
"Command And Control": "Command and Control",
|
|
17
17
|
"Exfiltration": "Actions on Objectives",
|
|
18
|
-
"Impact": "Actions on Objectives"
|
|
18
|
+
"Impact": "Actions on Objectives",
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
SES_CONTEXT_MAPPING = {
|
|
@@ -65,7 +65,7 @@ SES_CONTEXT_MAPPING = {
|
|
|
65
65
|
"Other:Policy Violation": 82,
|
|
66
66
|
"Other:Threat Intelligence": 83,
|
|
67
67
|
"Other:Flight Risk": 84,
|
|
68
|
-
"Other:Removable Storage": 85
|
|
68
|
+
"Other:Removable Storage": 85,
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
SES_KILL_CHAIN_MAPPINGS = {
|
|
@@ -76,47 +76,9 @@ SES_KILL_CHAIN_MAPPINGS = {
|
|
|
76
76
|
"Exploitation": 4,
|
|
77
77
|
"Installation": 5,
|
|
78
78
|
"Command and Control": 6,
|
|
79
|
-
"Actions on Objectives": 7
|
|
79
|
+
"Actions on Objectives": 7,
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
SES_OBSERVABLE_ROLE_MAPPING = {
|
|
83
|
-
"Other": -1,
|
|
84
|
-
"Unknown": 0,
|
|
85
|
-
"Actor": 1,
|
|
86
|
-
"Target": 2,
|
|
87
|
-
"Attacker": 3,
|
|
88
|
-
"Victim": 4,
|
|
89
|
-
"Parent Process": 5,
|
|
90
|
-
"Child Process": 6,
|
|
91
|
-
"Known Bad": 7,
|
|
92
|
-
"Data Loss": 8,
|
|
93
|
-
"Observer": 9
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
SES_OBSERVABLE_TYPE_MAPPING = {
|
|
97
|
-
"Unknown": 0,
|
|
98
|
-
"Hostname": 1,
|
|
99
|
-
"IP Address": 2,
|
|
100
|
-
"MAC Address": 3,
|
|
101
|
-
"User Name": 4,
|
|
102
|
-
"Email Address": 5,
|
|
103
|
-
"URL String": 6,
|
|
104
|
-
"File Name": 7,
|
|
105
|
-
"File Hash": 8,
|
|
106
|
-
"Process Name": 9,
|
|
107
|
-
"Resource UID": 10,
|
|
108
|
-
"Endpoint": 20,
|
|
109
|
-
"User": 21,
|
|
110
|
-
"Email": 22,
|
|
111
|
-
"Uniform Resource Locator": 23,
|
|
112
|
-
"File": 24,
|
|
113
|
-
"Process": 25,
|
|
114
|
-
"Geo Location": 26,
|
|
115
|
-
"Container": 27,
|
|
116
|
-
"Registry Key": 28,
|
|
117
|
-
"Registry Value": 29,
|
|
118
|
-
"Other": 99
|
|
119
|
-
}
|
|
120
82
|
|
|
121
83
|
SES_ATTACK_TACTICS_ID_MAPPING = {
|
|
122
84
|
"Reconnaissance": "TA0043",
|
|
@@ -132,24 +94,20 @@ SES_ATTACK_TACTICS_ID_MAPPING = {
|
|
|
132
94
|
"Collection": "TA0009",
|
|
133
95
|
"Command_and_Control": "TA0011",
|
|
134
96
|
"Exfiltration": "TA0010",
|
|
135
|
-
"Impact": "TA0040"
|
|
97
|
+
"Impact": "TA0040",
|
|
136
98
|
}
|
|
137
99
|
|
|
138
|
-
RBA_OBSERVABLE_ROLE_MAPPING = {
|
|
139
|
-
"Attacker": 0,
|
|
140
|
-
"Victim": 1
|
|
141
|
-
}
|
|
142
100
|
|
|
143
101
|
# The relative path to the directory where any apps/packages will be downloaded
|
|
144
102
|
DOWNLOADS_DIRECTORY = "downloads"
|
|
145
103
|
|
|
146
104
|
# Maximum length of the name field for a search.
|
|
147
|
-
# This number is derived from a limitation that exists in
|
|
105
|
+
# This number is derived from a limitation that exists in
|
|
148
106
|
# ESCU where a search cannot be edited, due to validation
|
|
149
107
|
# errors, if its name is longer than 99 characters.
|
|
150
108
|
# When an saved search is cloned in Enterprise Security User Interface,
|
|
151
|
-
# it is wrapped in the following:
|
|
152
|
-
# {Detection.tags.security_domain
|
|
109
|
+
# it is wrapped in the following:
|
|
110
|
+
# {Detection.tags.security_domain} - {SEARCH_STANZA_NAME} - Rule
|
|
153
111
|
# Similarly, when we generate the search stanza name in contentctl, it
|
|
154
112
|
# is app.label - detection.name - Rule
|
|
155
113
|
# However, in product the search name is:
|
|
@@ -157,16 +115,35 @@ DOWNLOADS_DIRECTORY = "downloads"
|
|
|
157
115
|
# or in ESCU:
|
|
158
116
|
# ESCU - {detection.name} - Rule,
|
|
159
117
|
# this gives us a maximum length below.
|
|
160
|
-
# When an ESCU search is cloned, it will
|
|
118
|
+
# When an ESCU search is cloned, it will
|
|
161
119
|
# have a full name like (the following is NOT a typo):
|
|
162
120
|
# Endpoint - ESCU - Name of Search From YML File - Rule - Rule
|
|
163
121
|
# The math below accounts for all these caveats
|
|
164
122
|
ES_MAX_STANZA_LENGTH = 99
|
|
165
|
-
CONTENTCTL_DETECTION_STANZA_NAME_FORMAT_TEMPLATE =
|
|
123
|
+
CONTENTCTL_DETECTION_STANZA_NAME_FORMAT_TEMPLATE = (
|
|
124
|
+
"{app_label} - {detection_name} - Rule"
|
|
125
|
+
)
|
|
166
126
|
CONTENTCTL_BASELINE_STANZA_NAME_FORMAT_TEMPLATE = "{app_label} - {detection_name}"
|
|
167
|
-
CONTENTCTL_RESPONSE_TASK_NAME_FORMAT_TEMPLATE =
|
|
127
|
+
CONTENTCTL_RESPONSE_TASK_NAME_FORMAT_TEMPLATE = (
|
|
128
|
+
"{app_label} - {detection_name} - Response Task"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
ES_SEARCH_STANZA_NAME_FORMAT_AFTER_CLONING_IN_PRODUCT_TEMPLATE = (
|
|
132
|
+
"{security_domain_value} - {search_name} - Rule"
|
|
133
|
+
)
|
|
134
|
+
SECURITY_DOMAIN_MAX_LENGTH = max(
|
|
135
|
+
[len(SecurityDomain[value]) for value in SecurityDomain._member_map_]
|
|
136
|
+
)
|
|
137
|
+
CONTENTCTL_MAX_STANZA_LENGTH = ES_MAX_STANZA_LENGTH - len(
|
|
138
|
+
ES_SEARCH_STANZA_NAME_FORMAT_AFTER_CLONING_IN_PRODUCT_TEMPLATE.format(
|
|
139
|
+
security_domain_value="X" * SECURITY_DOMAIN_MAX_LENGTH, search_name=""
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
CONTENTCTL_MAX_SEARCH_NAME_LENGTH = CONTENTCTL_MAX_STANZA_LENGTH - len(
|
|
143
|
+
CONTENTCTL_DETECTION_STANZA_NAME_FORMAT_TEMPLATE.format(
|
|
144
|
+
app_label="ESCU", detection_name=""
|
|
145
|
+
)
|
|
146
|
+
)
|
|
168
147
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
CONTENTCTL_MAX_STANZA_LENGTH = ES_MAX_STANZA_LENGTH - len(ES_SEARCH_STANZA_NAME_FORMAT_AFTER_CLONING_IN_PRODUCT_TEMPLATE.format(security_domain_value="X"*SECURITY_DOMAIN_MAX_LENGTH,search_name=""))
|
|
172
|
-
CONTENTCTL_MAX_SEARCH_NAME_LENGTH = CONTENTCTL_MAX_STANZA_LENGTH - len(CONTENTCTL_DETECTION_STANZA_NAME_FORMAT_TEMPLATE.format(app_label="ESCU", detection_name=""))
|
|
148
|
+
DEPRECATED_TEMPLATE = "**WARNING**, this {content_type} has been marked **DEPRECATED** by the Splunk Threat Research Team. This means that it will no longer be maintained or supported. If you have any questions feel free to email us at: research@splunk.com. {description}"
|
|
149
|
+
EXPERIMENTAL_TEMPLATE = "**WARNING**, this {content_type} is marked **EXPERIMENTAL** by the Splunk Threat Research Team. This means that the {content_type} has been manually tested but we do not have the associated attack data to perform automated testing or cannot share this attack dataset due to its sensitive nature. If you have any questions feel free to email us at: research@splunk.com. {description}"
|