Skip to content

Commit dee4853

Browse files
authored
Merge pull request #138 from splunk/pydantic2_bonus_content
Additional Pydantic2 content
2 parents dab8a06 + c2008d1 commit dee4853

31 files changed

+594
-1340
lines changed

.github/workflows/testEndToEnd.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
- name: Run contentctl init
5252
run: |
5353
cd my_splunk_content_pack
54-
poetry run contentctl init
54+
poetry run contentctl init
5555
5656
- name: Clone the AtomicRedTeam Repo
5757
run: |
@@ -73,7 +73,7 @@ jobs:
7373
if: startsWith(matrix.operating_system, 'ubuntu')
7474
run: |
7575
cd my_splunk_content_pack
76-
poetry run contentctl test
76+
poetry run contentctl test --disable-tqdm --post-test-behavior never_pause
7777
7878
- uses: actions/upload-artifact@v4
7979
with:

contentctl/actions/detection_testing/DetectionTestingManager.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,18 +154,24 @@ def create_DetectionTestingInfrastructureObjects(self):
154154
except Exception as e:
155155
raise Exception(f"Failed to pull docker container image [{self.input_dto.config.container_settings.full_image_path}]: {str(e)}")
156156

157+
already_staged_container_files = False
157158
for infrastructure in self.input_dto.config.test_instances:
158159

159160
if (isinstance(self.input_dto.config, test) and isinstance(infrastructure, Container)):
161+
# Stage the files in the apps dir so that they can be passed directly to
162+
# subsequent containers. Do this here, instead of inside each container, to
163+
# avoid duplicate downloads/moves/copies
164+
if not already_staged_container_files:
165+
self.input_dto.config.getContainerEnvironmentString(stage_file=True)
166+
already_staged_container_files = True
160167

161168
self.detectionTestingInfrastructureObjects.append(
162169
DetectionTestingInfrastructureContainer(
163170
global_config=self.input_dto.config, infrastructure=infrastructure, sync_obj=self.output_dto
164171
)
165172
)
166173

167-
elif isinstance(infrastructure, Infrastructure):
168-
174+
elif (isinstance(self.input_dto.config, test_servers) and isinstance(infrastructure, Infrastructure)):
169175
self.detectionTestingInfrastructureObjects.append(
170176
DetectionTestingInfrastructureServer(
171177
global_config=self.input_dto.config, infrastructure=infrastructure, sync_obj=self.output_dto

contentctl/actions/detection_testing/GitService.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from contentctl.objects.lookup import Lookup
1515
from contentctl.objects.detection import Detection
1616
from contentctl.objects.security_content_object import SecurityContentObject
17-
from contentctl.objects.config import test, All, Changes, Selected
17+
from contentctl.objects.config import test_common, All, Changes, Selected
1818

1919
# Logger
2020
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
@@ -28,7 +28,7 @@
2828

2929
class GitService(BaseModel):
3030
director: DirectorOutputDto
31-
config: test
31+
config: test_common
3232
gitHash: Optional[str] = None
3333

3434
def getHash(self)->str:

contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructure.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from urllib3 import disable_warnings
2424
import urllib.parse
2525

26-
from contentctl.objects.config import test, test_servers, test_common, Infrastructure
26+
from contentctl.objects.config import test_common, Infrastructure
2727
from contentctl.objects.enums import PostTestBehavior, AnalyticsType
2828
from contentctl.objects.detection import Detection
2929
from contentctl.objects.base_test import BaseTest
@@ -32,7 +32,6 @@
3232
from contentctl.objects.unit_test_attack_data import UnitTestAttackData
3333
from contentctl.objects.unit_test_result import UnitTestResult
3434
from contentctl.objects.integration_test_result import IntegrationTestResult
35-
#from contentctl.objects.test_config import TestConfig, Infrastructure
3635
from contentctl.objects.test_group import TestGroup
3736
from contentctl.objects.base_test_result import TestResultStatus
3837
from contentctl.objects.correlation_search import CorrelationSearch, PbarData
@@ -79,7 +78,7 @@ class DetectionTestingManagerOutputDto():
7978

8079
class DetectionTestingInfrastructure(BaseModel, abc.ABC):
8180
# thread: threading.Thread = threading.Thread()
82-
global_config: Union[test,test_servers]
81+
global_config: test_common
8382
infrastructure: Infrastructure
8483
sync_obj: DetectionTestingManagerOutputDto
8584
hec_token: str = ""
@@ -396,7 +395,7 @@ def execute(self):
396395
try:
397396
self.test_detection(detection)
398397
except ContainerStoppedException:
399-
self.pbar.write(f"Stopped container [{self.get_name()}]")
398+
self.pbar.write(f"Warning - container was stopped when trying to execute detection [{self.get_name()}]")
400399
self.finish()
401400
return
402401
except Exception as e:
@@ -1357,7 +1356,7 @@ def status(self):
13571356
pass
13581357

13591358
def finish(self):
1360-
self.pbar.bar_format = f"Stopped container [{self.get_name()}]"
1359+
self.pbar.bar_format = f"Finished running tests on instance: [{self.get_name()}]"
13611360
self.pbar.update()
13621361
self.pbar.close()
13631362

contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructureContainer.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66
import docker.models.containers
77
import docker
88
import docker.types
9-
from contentctl.objects.test_config import (
10-
CONTAINER_APP_DIR,
11-
LOCAL_APP_DIR,
12-
)
139

1410

1511
class DetectionTestingInfrastructureContainer(DetectionTestingInfrastructure):
@@ -78,8 +74,8 @@ def make_container(self) -> docker.models.resource.Model:
7874

7975
mounts = [
8076
docker.types.Mount(
81-
source=str(LOCAL_APP_DIR.absolute()),
82-
target=str(CONTAINER_APP_DIR.absolute()),
77+
source=str(self.global_config.getLocalAppDir()),
78+
target=str(self.global_config.getContainerAppDir()),
8379
type="bind",
8480
read_only=True,
8581
)
@@ -88,7 +84,9 @@ def make_container(self) -> docker.models.resource.Model:
8884
environment = {}
8985
environment["SPLUNK_START_ARGS"] = "--accept-license"
9086
environment["SPLUNK_PASSWORD"] = self.infrastructure.splunk_app_password
91-
environment["SPLUNK_APPS_URL"] = self.global_config.getContainerEnvironmentString(stage_file=True)
87+
# Files have already been staged by the time that we call this. Files must only be staged
88+
# once, not staged by every container
89+
environment["SPLUNK_APPS_URL"] = self.global_config.getContainerEnvironmentString(stage_file=False)
9290
if (
9391
self.global_config.splunk_api_username is not None
9492
and self.global_config.splunk_api_password is not None
@@ -119,6 +117,18 @@ def emit_docker_run_equivalent():
119117
detach=True,
120118
platform="linux/amd64"
121119
)
120+
121+
if self.global_config.enterpriseSecurityInApps():
122+
#ES sets up https, so make sure it is included in the link
123+
address = f"https://{self.infrastructure.instance_address}:{self.infrastructure.web_ui_port}"
124+
else:
125+
address = f"http://{self.infrastructure.instance_address}:{self.infrastructure.web_ui_port}"
126+
print(f"\nStarted container with the following information:\n"
127+
f"\tname : [{self.get_name()}]\n"
128+
f"\taddress : [{address}]\n"
129+
f"\tusername: [{self.infrastructure.splunk_app_username}]\n"
130+
f"\tpassword: [{self.infrastructure.splunk_app_password}]\n"
131+
)
122132

123133
return container
124134

@@ -140,6 +150,8 @@ def removeContainer(self, removeVolumes: bool = True, forceRemove: bool = True):
140150
# container was found, so now we try to remove it
141151
# v also removes volumes linked to the container
142152
container.remove(v=removeVolumes, force=forceRemove)
153+
print(f"container [{self.get_name()}] successfully removed")
154+
143155
# remove it even if it is running. remove volumes as well
144156
# No need to print that the container has been removed, it is expected behavior
145157

contentctl/actions/detection_testing/views/DetectionTestingView.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
from pydantic import BaseModel
55

6-
from contentctl.objects.test_config import TestConfig
7-
from contentctl.objects.config import test
6+
from contentctl.objects.config import test_common
87

98
from contentctl.actions.detection_testing.infrastructures.DetectionTestingInfrastructure import (
109
DetectionTestingManagerOutputDto,
@@ -14,7 +13,7 @@
1413

1514

1615
class DetectionTestingView(BaseModel, abc.ABC):
17-
config: test
16+
config: test_common
1817
sync_obj: DetectionTestingManagerOutputDto
1918

2019
interval: float = 10

contentctl/actions/detection_testing/views/DetectionTestingViewFile.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
from pydantic import BaseModel
2-
import abc
3-
from typing import Callable
4-
from contentctl.objects.test_config import TestConfig
5-
from contentctl.actions.detection_testing.infrastructures.DetectionTestingInfrastructure import (
6-
DetectionTestingManagerOutputDto,
7-
)
8-
91
from contentctl.actions.detection_testing.views.DetectionTestingView import (
102
DetectionTestingView,
113
)

contentctl/actions/initialize.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def execute(self, config: test) -> None:
3434
source_directory = pathlib.Path(os.path.dirname(__file__))/templateDir
3535
target_directory = config.path/targetDir
3636
#Throw an exception if the target exists
37-
shutil.copytree(source_directory, targetDir, dirs_exist_ok=False)
37+
shutil.copytree(source_directory, target_directory, dirs_exist_ok=False)
3838

3939
#Create the config file as well
4040
shutil.copyfile(pathlib.Path(os.path.dirname(__file__))/'../templates/README','README')

0 commit comments

Comments
 (0)