Open pyth0n1c opened 2 weeks ago
There might be one more bug before it works. I currently have a problem with the "infer app path" part of the ansible task inside docker-splunk. I'm not sure what the fix is yet, I'm investigating. I'll post a screenshot tomorrow when I get back on my work computer, if you have an idea.
Here is the error:
Found the bug, will include the patch soon
Here is the patch. Sorry again for the manual work, after this PR I'll probably be able to contribute back normally to upstream.
This fixes the error mentioned in the last comment, as well as adds a proper "wait for app installation" that actually checks for app installation instead of assuming that apps are installed once you get a connection to the splunk API (which is not the case).
From cc6c63fe160bb9f76c740a371be3f4ca5af4c3b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=89milio=20Gonzalez?= <little.moon6016@fastmail.com>
Date: Tue, 5 Nov 2024 20:41:59 -0500
Subject: =?UTF-8?q?Fix=20du=20setup=20initial=20+=20t=C3=A9l=C3=A9chargeme?=
=?UTF-8?q?nt=20depuis=20splunkbase.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../DetectionTestingInfrastructure.py | 44 +++++++++++++++++--
...DetectionTestingInfrastructureContainer.py | 5 +++
contentctl/objects/config.py | 6 +--
3 files changed, 48 insertions(+), 7 deletions(-)
diff --git a/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructure.py b/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructure.py
index d443ea2..8bb1f1e 100644
--- a/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructure.py
+++ b/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructure.py
@@ -1,3 +1,4 @@
+import logging
import time
import uuid
import abc
@@ -17,12 +18,13 @@ from pydantic import ConfigDict, BaseModel, PrivateAttr, Field, dataclasses
import requests # type: ignore
import splunklib.client as client # type: ignore
from splunklib.binding import HTTPError # type: ignore
+from splunklib.client import Service
from splunklib.results import JSONResultsReader, Message # type: ignore
import splunklib.results
from urllib3 import disable_warnings
import urllib.parse
-from contentctl.objects.config import test_common, Infrastructure
+from contentctl.objects.config import test_common, Infrastructure, ENTERPRISE_SECURITY_UID
from contentctl.objects.enums import PostTestBehavior, AnalyticsType
from contentctl.objects.detection import Detection
from contentctl.objects.base_test import BaseTest
@@ -42,6 +44,12 @@ from contentctl.actions.detection_testing.progress_bar import (
TestingStates
)
+LOG = logging.getLogger(__name__)
+LOG.setLevel(logging.DEBUG)
+handler = logging.StreamHandler()
+handler.setLevel(logging.DEBUG)
+LOG.addHandler(handler)
+
class SetupTestGroupResults(BaseModel):
exception: Union[Exception, None] = None
@@ -107,6 +115,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
def __init__(self, **data):
super().__init__(**data)
+ self._conn: Optional[Service] = None
# TODO: why not use @abstractmethod
def start(self):
@@ -138,7 +147,8 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
try:
for func, msg in [
(self.start, "Starting"),
- (self.get_conn, "Waiting for App Installation"),
+ (self.get_conn, "Getting initial connection"),
+ (self.wait_for_app_installation, "Waiting for App Installation"),
(self.configure_conf_file_datamodels, "Configuring Datamodels"),
(self.create_replay_index, f"Create index '{self.sync_obj.replay_index}'"),
(self.get_all_indexes, "Getting all indexes from server"),
@@ -210,6 +220,29 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
except Exception as e:
raise (Exception(f"Failure getting indexes: {str(e)}"))
+ def wait_for_app_installation(self):
+ config_apps = self.global_config.apps
+ installed_config_apps = []
+ while len(installed_config_apps) < len(config_apps):
+ try:
+ # Get apps installed in the Splunk instance
+ splunk_instance_apps = self.get_conn().apps.list()
+
+ # Try to find all the apps we want to be installed (config_apps)
+ installed_config_apps = []
+ for config_app in config_apps:
+ for splunk_instance_app in splunk_instance_apps:
+ if config_app.appid == splunk_instance_app.name:
+ # For Enterprise Security, we need to make sure the app is also configured.
+ if config_app.uid == ENTERPRISE_SECURITY_UID and splunk_instance_app.content.get('configured') != '1':
+ continue
+ installed_config_apps.append(config_app.appid)
+ LOG.debug("Apps in the Splunk instance: " + str(list(map(lambda x: x.name, splunk_instance_apps))))
+ LOG.debug(f"apps in contentctl package found in Splunk instance: {installed_config_apps}")
+ except Exception as e:
+ LOG.exception(e)
+ time.sleep(5)
+
def get_conn(self) -> client.Service:
try:
if not self._conn:
@@ -218,9 +251,11 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
# continue trying to re-establish a connection until after
# the server has restarted
self.connect_to_api()
- except Exception:
+ except Exception as e:
# there was some issue getting the connection. Try again just once
+ LOG.exception(e)
self.connect_to_api()
+
return self._conn
def check_for_teardown(self):
@@ -295,7 +330,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
):
try:
# Set which roles should be configured. For Enterprise Security/Integration Testing,
- # we must add some extra foles.
+ # we must add some extra roles.
if self.global_config.enable_integration_testing:
roles = imported_roles + enterprise_security_roles
else:
@@ -334,6 +369,7 @@ class DetectionTestingInfrastructure(BaseModel, abc.ABC):
self.check_for_teardown()
time.sleep(1)
try:
_ = self.get_conn().get(
f"configs/conf-{conf_file_name}", app=app_name
)
diff --git a/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructureContainer.py b/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructureContainer.py
index f588703..37326f9 100644
--- a/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructureContainer.py
+++ b/contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructureContainer.py
@@ -1,3 +1,5 @@
+import time
+
from contentctl.actions.detection_testing.infrastructures.DetectionTestingInfrastructure import (
DetectionTestingInfrastructure,
)
@@ -25,6 +27,9 @@ class DetectionTestingInfrastructureContainer(DetectionTestingInfrastructure):
self.container = self.make_container()
self.container.start()
+ # There might be a small delay between the starting of the container and the binding of the ports for splunk.
+ # To avoid a "connection refused" error, wait a little bit before finishing the method call.
+ time.sleep(20)
def finish(self):
if self.container is not None:
diff --git a/contentctl/objects/config.py b/contentctl/objects/config.py
index 4228ba9..1931c15 100644
--- a/contentctl/objects/config.py
+++ b/contentctl/objects/config.py
@@ -31,7 +31,8 @@ from contentctl.helper.splunk_app import SplunkApp
ENTERPRISE_SECURITY_UID = 263
COMMON_INFORMATION_MODEL_UID = 1621
-SPLUNKBASE_URL = "https://splunkbase.splunk.com/app/{uid}/release/{version}/download"
+SPLUNKBASE_BASE_URL = "https://splunkbase.splunk.com"
+SPLUNKBASE_URL = SPLUNKBASE_BASE_URL + "/app/{uid}/release/{version}/download"
# TODO (#266): disable the use_enum_values configuration
@@ -836,7 +837,6 @@ class test(test_common):
def __init__(self, **kwargs):
if "SPLUNKBASE_USERNAME" in os.environ:
- breakpoint()
kwargs['splunk_api_username'] = os.environ["SPLUNKBASE_USERNAME"]
if "SPLUNKBASE_PASSWORD" in os.environ:
kwargs['splunk_api_password'] = os.environ["SPLUNKBASE_PASSWORD"]
@@ -886,7 +886,7 @@ class test(test_common):
container_paths = []
for path in paths:
- if path.startswith(SPLUNKBASE_URL):
+ if path.startswith(SPLUNKBASE_BASE_URL):
container_paths.append(path)
else:
container_paths.append((self.getContainerAppDir()/pathlib.Path(path).name).as_posix())
--
2.34.1
This PR should be closed and is replaced by #327
This larger PR aggregates a number of great changes courtesy @Res260 . These updates fix broken logic to allow Apps to be downloaded from Splunkbase at
contentctl test
runtime