From 1a5ee9930df81d8cc18cdf517e077fe7950ba79e Mon Sep 17 00:00:00 2001 From: Yevhen Date: Tue, 18 Mar 2025 11:38:47 -0400 Subject: [PATCH 1/2] fix: Splunk metadata parsing logic: config stanzas must be loaded from the system app (#432) Method get_conf_stanzas internally calls `$SPLUNK_HOME/bin/splunk cmd btool server list` This command leads to accumulated output. It reads server.conf files from all apps. Such behaviour may lead to invalid results, if an app has different (not supported) format in the conf file. I suggest to change login and read configs only from the system app: `$SPLUNK_HOME/bin/splunk cmd btool server list --app=system` --- solnlib/splunkenv.py | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/solnlib/splunkenv.py b/solnlib/splunkenv.py index cda53970..d27ef882 100644 --- a/solnlib/splunkenv.py +++ b/solnlib/splunkenv.py @@ -39,6 +39,8 @@ ] ETC_LEAF = "etc" +APP_SYSTEM = "system" +APP_HEC = "splunk_httpinput" # See validateSearchHeadPooling() in src/libbundle/ConfSettings.cpp on_shared_storage = [ @@ -73,8 +75,8 @@ def _get_shared_storage() -> Optional[str]: """ try: - state = get_conf_key_value("server", "pooling", "state") - storage = get_conf_key_value("server", "pooling", "storage") + state = get_conf_key_value("server", "pooling", "state", APP_SYSTEM) + storage = get_conf_key_value("server", "pooling", "storage", APP_SYSTEM) except KeyError: state = "disabled" storage = None @@ -154,7 +156,7 @@ def get_splunk_host_info() -> Tuple: Tuple of (server_name, host_name). """ - server_name = get_conf_key_value("server", "general", "serverName") + server_name = get_conf_key_value("server", "general", "serverName", APP_SYSTEM) host_name = socket.gethostname() return server_name, host_name @@ -180,12 +182,14 @@ def get_splunkd_access_info() -> Tuple[str, str, int]: Tuple of (scheme, host, port). """ - if is_true(get_conf_key_value("server", "sslConfig", "enableSplunkdSSL")): + if is_true( + get_conf_key_value("server", "sslConfig", "enableSplunkdSSL", APP_SYSTEM) + ): scheme = "https" else: scheme = "http" - host_port = get_conf_key_value("web", "settings", "mgmtHostPort") + host_port = get_conf_key_value("web", "settings", "mgmtHostPort", APP_SYSTEM) host_port = host_port.strip() host_port_split_parts = host_port.split(":") host = ":".join(host_port_split_parts[:-1]) @@ -206,7 +210,7 @@ def get_scheme_from_hec_settings() -> str: scheme (str) """ try: - ssl_enabled = get_conf_key_value("inputs", "http", "enableSSL") + ssl_enabled = get_conf_key_value("inputs", "http", "enableSSL", APP_HEC) except KeyError: raise KeyError( "Cannot get enableSSL setting form conf: 'inputs' and stanza: '[http]'. " @@ -237,13 +241,16 @@ def get_splunkd_uri() -> str: return f"{scheme}://{host}:{port}" -def get_conf_key_value(conf_name: str, stanza: str, key: str) -> Union[str, List, dict]: +def get_conf_key_value( + conf_name: str, stanza: str, key: str, app_name: Optional[str] = None +) -> Union[str, List, dict]: """Get value of `key` of `stanza` in `conf_name`. Arguments: conf_name: Config file. stanza: Stanza name. key: Key name. + app_name: Application name. Optional. Returns: Config value. @@ -252,16 +259,19 @@ def get_conf_key_value(conf_name: str, stanza: str, key: str) -> Union[str, List KeyError: If `stanza` or `key` doesn't exist. """ - stanzas = get_conf_stanzas(conf_name) + stanzas = get_conf_stanzas(conf_name, app_name) return stanzas[stanza][key] -def get_conf_stanza(conf_name: str, stanza: str) -> dict: +def get_conf_stanza( + conf_name: str, stanza: str, app_name: Optional[str] = None +) -> dict: """Get `stanza` in `conf_name`. Arguments: conf_name: Config file. stanza: Stanza name. + app_name: Application name. Optional. Returns: Config stanza. @@ -270,15 +280,16 @@ def get_conf_stanza(conf_name: str, stanza: str) -> dict: KeyError: If stanza doesn't exist. """ - stanzas = get_conf_stanzas(conf_name) + stanzas = get_conf_stanzas(conf_name, app_name) return stanzas[stanza] -def get_conf_stanzas(conf_name: str) -> dict: +def get_conf_stanzas(conf_name: str, app_name: Optional[str] = None) -> dict: """Get stanzas of `conf_name` Arguments: conf_name: Config file. + app_name: Application name. Optional. Returns: Config stanzas. @@ -299,6 +310,10 @@ def get_conf_stanzas(conf_name: str) -> dict: conf_name, "list", ] + + if app_name: + btool_cli.append(f"--app={app_name}") + p = subprocess.Popen( # nosemgrep: python.lang.security.audit.dangerous-subprocess-use.dangerous-subprocess-use btool_cli, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) From d335d1f8bf173f90f5af906c4ea69eea4ade5ab0 Mon Sep 17 00:00:00 2001 From: srv-rr-github-token <94607705+srv-rr-github-token@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:44:55 +0000 Subject: [PATCH 2/2] chore(release): 6.2.1-beta.1 ## [6.2.1-beta.1](https://github.com/splunk/addonfactory-solutions-library-python/compare/v6.2.0...v6.2.1-beta.1) (2025-03-18) ### Bug Fixes * Splunk metadata parsing logic: config stanzas must be loaded from the system app ([#432](https://github.com/splunk/addonfactory-solutions-library-python/issues/432)) ([1a5ee99](https://github.com/splunk/addonfactory-solutions-library-python/commit/1a5ee9930df81d8cc18cdf517e077fe7950ba79e)) --- pyproject.toml | 2 +- solnlib/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 953c5eb2..297f5969 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ [tool.poetry] name = "solnlib" -version = "6.2.0" +version = "6.2.1-beta.1" description = "The Splunk Software Development Kit for Splunk Solutions" authors = ["Splunk "] license = "Apache-2.0" diff --git a/solnlib/__init__.py b/solnlib/__init__.py index 0eb4240f..b4b42c82 100644 --- a/solnlib/__init__.py +++ b/solnlib/__init__.py @@ -56,4 +56,4 @@ "utils", ] -__version__ = "6.2.0" +__version__ = "6.2.1-beta.1"