contentctl 4.4.7__py3-none-any.whl → 5.0.0a2__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.
Files changed (70) hide show
  1. contentctl/actions/build.py +39 -27
  2. contentctl/actions/detection_testing/DetectionTestingManager.py +0 -1
  3. contentctl/actions/detection_testing/GitService.py +132 -72
  4. contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructure.py +32 -26
  5. contentctl/actions/detection_testing/progress_bar.py +6 -6
  6. contentctl/actions/detection_testing/views/DetectionTestingView.py +4 -4
  7. contentctl/actions/new_content.py +98 -81
  8. contentctl/actions/test.py +4 -5
  9. contentctl/actions/validate.py +2 -1
  10. contentctl/contentctl.py +114 -80
  11. contentctl/helper/utils.py +0 -14
  12. contentctl/input/director.py +5 -5
  13. contentctl/input/new_content_questions.py +2 -2
  14. contentctl/input/yml_reader.py +11 -6
  15. contentctl/objects/abstract_security_content_objects/detection_abstract.py +228 -120
  16. contentctl/objects/abstract_security_content_objects/security_content_object_abstract.py +5 -7
  17. contentctl/objects/alert_action.py +2 -1
  18. contentctl/objects/atomic.py +1 -0
  19. contentctl/objects/base_test.py +4 -3
  20. contentctl/objects/base_test_result.py +3 -3
  21. contentctl/objects/baseline.py +26 -6
  22. contentctl/objects/baseline_tags.py +2 -3
  23. contentctl/objects/config.py +789 -596
  24. contentctl/objects/constants.py +4 -1
  25. contentctl/objects/correlation_search.py +89 -95
  26. contentctl/objects/data_source.py +5 -6
  27. contentctl/objects/deployment.py +2 -10
  28. contentctl/objects/deployment_email.py +2 -1
  29. contentctl/objects/deployment_notable.py +2 -1
  30. contentctl/objects/deployment_phantom.py +2 -1
  31. contentctl/objects/deployment_rba.py +2 -1
  32. contentctl/objects/deployment_scheduling.py +2 -1
  33. contentctl/objects/deployment_slack.py +2 -1
  34. contentctl/objects/detection_tags.py +7 -42
  35. contentctl/objects/drilldown.py +1 -0
  36. contentctl/objects/enums.py +21 -58
  37. contentctl/objects/investigation.py +6 -5
  38. contentctl/objects/investigation_tags.py +2 -3
  39. contentctl/objects/lookup.py +145 -63
  40. contentctl/objects/macro.py +2 -3
  41. contentctl/objects/mitre_attack_enrichment.py +2 -2
  42. contentctl/objects/observable.py +3 -1
  43. contentctl/objects/playbook_tags.py +5 -1
  44. contentctl/objects/rba.py +90 -0
  45. contentctl/objects/risk_event.py +87 -144
  46. contentctl/objects/story_tags.py +1 -2
  47. contentctl/objects/test_attack_data.py +2 -1
  48. contentctl/objects/unit_test_baseline.py +2 -1
  49. contentctl/output/api_json_output.py +233 -220
  50. contentctl/output/conf_output.py +51 -44
  51. contentctl/output/conf_writer.py +201 -125
  52. contentctl/output/data_source_writer.py +0 -1
  53. contentctl/output/json_writer.py +2 -4
  54. contentctl/output/svg_output.py +1 -1
  55. contentctl/output/templates/analyticstories_detections.j2 +1 -1
  56. contentctl/output/templates/collections.j2 +1 -1
  57. contentctl/output/templates/doc_detections.j2 +0 -5
  58. contentctl/output/templates/savedsearches_detections.j2 +8 -3
  59. contentctl/output/templates/transforms.j2 +4 -4
  60. contentctl/output/yml_writer.py +15 -0
  61. contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml +16 -34
  62. {contentctl-4.4.7.dist-info → contentctl-5.0.0a2.dist-info}/METADATA +5 -4
  63. {contentctl-4.4.7.dist-info → contentctl-5.0.0a2.dist-info}/RECORD +66 -69
  64. {contentctl-4.4.7.dist-info → contentctl-5.0.0a2.dist-info}/WHEEL +1 -1
  65. contentctl/objects/event_source.py +0 -11
  66. contentctl/output/detection_writer.py +0 -28
  67. contentctl/output/new_content_yml_output.py +0 -56
  68. contentctl/output/yml_output.py +0 -66
  69. {contentctl-4.4.7.dist-info → contentctl-5.0.0a2.dist-info}/LICENSE.md +0 -0
  70. {contentctl-4.4.7.dist-info → contentctl-5.0.0a2.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  from typing import Union, Any
2
- from enum import Enum
2
+ from enum import StrEnum
3
3
 
4
4
  from pydantic import ConfigDict, BaseModel
5
5
  from splunklib.data import Record # type: ignore
@@ -10,7 +10,7 @@ from contentctl.helper.utils import Utils
10
10
  # TODO (#267): Align test reporting more closely w/ status enums (as it relates to "untested")
11
11
  # TODO (PEX-432): add status "UNSET" so that we can make sure the result is always of this enum
12
12
  # type; remove mypy ignores associated w/ these typing issues once we do
13
- class TestResultStatus(str, Enum):
13
+ class TestResultStatus(StrEnum):
14
14
  """Enum for test status (e.g. pass/fail)"""
15
15
  # Test failed (detection did NOT fire appropriately)
16
16
  FAIL = "fail"
@@ -113,7 +113,7 @@ class BaseTestResult(BaseModel):
113
113
  # Exceptions and enums cannot be serialized, so convert to str
114
114
  if isinstance(getattr(self, field), Exception):
115
115
  summary_dict[field] = str(getattr(self, field))
116
- elif isinstance(getattr(self, field), Enum):
116
+ elif isinstance(getattr(self, field), StrEnum):
117
117
  summary_dict[field] = str(getattr(self, field))
118
118
  else:
119
119
  summary_dict[field] = getattr(self, field)
@@ -1,7 +1,10 @@
1
1
 
2
2
  from __future__ import annotations
3
- from typing import Annotated, Optional, List,Any
4
- from pydantic import field_validator, ValidationInfo, Field, model_serializer
3
+ from typing import Annotated, List,Any, TYPE_CHECKING
4
+ if TYPE_CHECKING:
5
+ from contentctl.input.director import DirectorOutputDto
6
+
7
+ from pydantic import field_validator, ValidationInfo, Field, model_serializer, computed_field
5
8
  from contentctl.objects.deployment import Deployment
6
9
  from contentctl.objects.security_content_object import SecurityContentObject
7
10
  from contentctl.objects.enums import DataModel
@@ -9,21 +12,34 @@ from contentctl.objects.baseline_tags import BaselineTags
9
12
 
10
13
  from contentctl.objects.config import CustomApp
11
14
 
12
-
15
+ from contentctl.objects.lookup import Lookup
13
16
  from contentctl.objects.constants import CONTENTCTL_MAX_SEARCH_NAME_LENGTH,CONTENTCTL_BASELINE_STANZA_NAME_FORMAT_TEMPLATE
14
17
 
15
18
  class Baseline(SecurityContentObject):
16
19
  name:str = Field(...,max_length=CONTENTCTL_MAX_SEARCH_NAME_LENGTH)
17
20
  type: Annotated[str,Field(pattern="^Baseline$")] = Field(...)
18
- datamodel: Optional[List[DataModel]] = None
19
21
  search: str = Field(..., min_length=4)
20
22
  how_to_implement: str = Field(..., min_length=4)
21
23
  known_false_positives: str = Field(..., min_length=4)
22
24
  tags: BaselineTags = Field(...)
23
-
25
+ lookups: list[Lookup] = Field([], validate_default=True)
24
26
  # enrichment
25
27
  deployment: Deployment = Field({})
26
-
28
+
29
+
30
+ @field_validator('lookups', mode="before")
31
+ @classmethod
32
+ def getBaselineLookups(cls, v:list[str], info:ValidationInfo) -> list[Lookup]:
33
+ '''
34
+ This function has been copied and renamed from the Detection_Abstract class
35
+ '''
36
+ director:DirectorOutputDto = info.context.get("output_dto",None)
37
+ search: str | None = info.data.get("search",None)
38
+ if search is None:
39
+ raise ValueError("Search was None - is this file missing the search field?")
40
+
41
+ lookups = Lookup.get_lookups(search, director)
42
+ return lookups
27
43
 
28
44
  def get_conf_stanza_name(self, app:CustomApp)->str:
29
45
  stanza_name = CONTENTCTL_BASELINE_STANZA_NAME_FORMAT_TEMPLATE.format(app_label=app.label, detection_name=self.name)
@@ -34,6 +50,10 @@ class Baseline(SecurityContentObject):
34
50
  def getDeployment(cls, v:Any, info:ValidationInfo)->Deployment:
35
51
  return Deployment.getDeployment(v,info)
36
52
 
53
+ @computed_field
54
+ @property
55
+ def datamodel(self) -> List[DataModel]:
56
+ return [dm for dm in DataModel if dm in self.search]
37
57
 
38
58
  @model_serializer
39
59
  def serialize_model(self):
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from pydantic import BaseModel, Field, field_validator, ValidationInfo, model_serializer
2
+ from pydantic import BaseModel, Field, field_validator, ValidationInfo, model_serializer, ConfigDict
3
3
  from typing import List, Any, Union
4
4
 
5
5
  from contentctl.objects.story import Story
@@ -12,12 +12,12 @@ from contentctl.objects.enums import SecurityDomain
12
12
 
13
13
 
14
14
  class BaselineTags(BaseModel):
15
+ model_config = ConfigDict(extra="forbid")
15
16
  analytic_story: list[Story] = Field(...)
16
17
  #deployment: Deployment = Field('SET_IN_GET_DEPLOYMENT_FUNCTION')
17
18
  # TODO (#223): can we remove str from the possible types here?
18
19
  detections: List[Union[Detection,str]] = Field(...)
19
20
  product: List[SecurityContentProductName] = Field(...,min_length=1)
20
- required_fields: List[str] = Field(...,min_length=1)
21
21
  security_domain: SecurityDomain = Field(...)
22
22
 
23
23
 
@@ -33,7 +33,6 @@ class BaselineTags(BaseModel):
33
33
  "analytic_story": [story.name for story in self.analytic_story],
34
34
  "detections": [detection.name for detection in self.detections if isinstance(detection,Detection)],
35
35
  "product": self.product,
36
- "required_fields":self.required_fields,
37
36
  "security_domain":self.security_domain,
38
37
  "deployments": None
39
38
  }