Skip to content

Commit 619a53e

Browse files
committed
feat: init commit, new function to retrieve stanzas based on rest
1 parent 6c06546 commit 619a53e

File tree

5 files changed

+152
-97
lines changed

5 files changed

+152
-97
lines changed

solnlib/credentials.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ def get_session_key(
373373
validate_scheme_host_port(scheme, host, port)
374374

375375
if any([scheme is None, host is None, port is None]):
376-
scheme, host, port = get_splunkd_access_info()
376+
scheme, host, port = get_splunkd_access_info(use_btool=True)
377377

378378
uri = "{scheme}://{host}:{port}/{endpoint}".format(
379379
scheme=scheme, host=host, port=port, endpoint="services/auth/login"

solnlib/modular_input/event_writer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,13 @@ def __init__(
233233
scheme, host, hec_port = utils.extract_http_scheme_host_port(hec_uri)
234234
else:
235235
if not all([scheme, host, port]):
236-
scheme, host, port = get_splunkd_access_info()
236+
scheme, host, port = get_splunkd_access_info(session_key=self._session_key)
237237
hec_port, hec_token = self._get_hec_config(
238238
hec_input_name, session_key, scheme, host, port, **context
239239
)
240240

241241
if global_settings_schema:
242-
scheme = get_scheme_from_hec_settings()
242+
scheme = get_scheme_from_hec_settings(session_key=self._session_key)
243243

244244
if not context.get("pool_connections"):
245245
context["pool_connections"] = 10

solnlib/server_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def __init__(
7878
"""
7979
is_localhost = False
8080
if not all([scheme, host, port]) and os.environ.get("SPLUNK_HOME"):
81-
scheme, host, port = get_splunkd_access_info()
81+
scheme, host, port = get_splunkd_access_info(session_key=session_key)
8282
is_localhost = (
8383
host == "localhost" or host == "127.0.0.1" or host in ("::1", "[::1]")
8484
)

solnlib/splunk_rest_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ def __init__(
221221
"""
222222
# Only do splunkd URI discovery in SPLUNK env (SPLUNK_HOME is set).
223223
if not all([scheme, host, port]) and os.environ.get("SPLUNK_HOME"):
224-
scheme, host, port = get_splunkd_access_info()
224+
scheme, host, port = get_splunkd_access_info(session_key=session_key)
225225
if os.environ.get("SPLUNK_HOME") is None:
226226
if not all([scheme, host, port]):
227227
raise ValueError(

solnlib/splunkenv.py

Lines changed: 147 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@
2020
import os.path as op
2121
import socket
2222
import subprocess
23+
import json
2324
from configparser import ConfigParser
2425
from io import StringIO
2526
from typing import List, Optional, Tuple, Union
2627

28+
from splunk.clilib.bundle_paths import make_splunkhome_path as msp
29+
from splunk.rest import simpleRequest
30+
from splunk import getSessionKey
31+
2732
from .utils import is_true
2833

2934
__all__ = [
@@ -36,6 +41,7 @@
3641
"get_conf_key_value",
3742
"get_conf_stanza",
3843
"get_conf_stanzas",
44+
"_get_conf_stanzas_from_splunk_api",
3945
]
4046

4147
ETC_LEAF = "etc"
@@ -54,46 +60,6 @@
5460
]
5561

5662

57-
def _splunk_home():
58-
return os.path.normpath(os.environ["SPLUNK_HOME"])
59-
60-
61-
def _splunk_etc():
62-
try:
63-
result = os.environ["SPLUNK_ETC"]
64-
except KeyError:
65-
result = op.join(_splunk_home(), ETC_LEAF)
66-
67-
return os.path.normpath(result)
68-
69-
70-
def _get_shared_storage() -> Optional[str]:
71-
"""Get splunk shared storage name.
72-
73-
Returns:
74-
Splunk shared storage name.
75-
"""
76-
77-
try:
78-
state = get_conf_key_value("server", "pooling", "state", APP_SYSTEM)
79-
storage = get_conf_key_value("server", "pooling", "storage", APP_SYSTEM)
80-
except KeyError:
81-
state = "disabled"
82-
storage = None
83-
84-
if state == "enabled" and storage:
85-
return storage
86-
87-
return None
88-
89-
90-
# Verify path prefix and return true if both paths have drives
91-
def _verify_path_prefix(path, start):
92-
path_drive = os.path.splitdrive(path)[0]
93-
start_drive = os.path.splitdrive(start)[0]
94-
return len(path_drive) == len(start_drive)
95-
96-
9763
def make_splunkhome_path(parts: Union[List, Tuple]) -> str:
9864
"""Construct absolute path by $SPLUNK_HOME and `parts`.
9965
@@ -111,53 +77,29 @@ def make_splunkhome_path(parts: Union[List, Tuple]) -> str:
11177
Raises:
11278
ValueError: Escape from intended parent directories.
11379
"""
80+
return msp(parts)
11481

115-
relpath = os.path.normpath(os.path.join(*parts))
116-
117-
basepath = None
118-
shared_storage = _get_shared_storage()
119-
if shared_storage:
120-
for candidate in on_shared_storage:
121-
# SPL-100508 On windows if the path is missing the drive letter,
122-
# construct fullpath manually and call relpath
123-
if os.name == "nt" and not _verify_path_prefix(relpath, candidate):
124-
break
125-
126-
if os.path.relpath(relpath, candidate)[0:2] != "..":
127-
basepath = shared_storage
128-
break
129-
130-
if basepath is None:
131-
etc_with_trailing_sep = os.path.join(ETC_LEAF, "")
132-
if relpath == ETC_LEAF or relpath.startswith(etc_with_trailing_sep):
133-
# Redirect $SPLUNK_HOME/etc to $SPLUNK_ETC.
134-
basepath = _splunk_etc()
135-
# Remove leading etc (and path separator, if present). Note: when
136-
# emitting $SPLUNK_ETC exactly, with no additional path parts, we
137-
# set <relpath> to the empty string.
138-
relpath = relpath[4:]
139-
else:
140-
basepath = _splunk_home()
141-
142-
fullpath = os.path.normpath(os.path.join(basepath, relpath))
143-
144-
# Check that we haven't escaped from intended parent directories.
145-
if os.path.relpath(fullpath, basepath)[0:2] == "..":
146-
raise ValueError(
147-
f'Illegal escape from parent directory "{basepath}": {fullpath}'
148-
)
149-
return fullpath
15082

151-
152-
def get_splunk_host_info() -> Tuple:
83+
def get_splunk_host_info(
84+
use_btool: Optional[bool] = False,
85+
session_key: Optional[str] = None
86+
) -> Tuple:
15387
"""Get splunk host info.
15488
15589
Returns:
15690
Tuple of (server_name, host_name).
15791
"""
15892

159-
server_name = get_conf_key_value("server", "general", "serverName", APP_SYSTEM)
93+
server_name = get_conf_key_value(
94+
"server",
95+
"general",
96+
"serverName",
97+
use_btool=use_btool,
98+
session_key=session_key,
99+
app_name=APP_SYSTEM
100+
)
160101
host_name = socket.gethostname()
102+
161103
return server_name, host_name
162104

163105

@@ -175,21 +117,37 @@ def get_splunk_bin() -> str:
175117
return make_splunkhome_path(("bin", splunk_bin))
176118

177119

178-
def get_splunkd_access_info() -> Tuple[str, str, int]:
120+
def get_splunkd_access_info(
121+
use_btool: Optional[bool] = False,
122+
session_key: Optional[str] = None
123+
) -> Tuple[str, str, int]:
179124
"""Get splunkd server access info.
180125
181126
Returns:
182127
Tuple of (scheme, host, port).
183128
"""
129+
enable_splunkd_ssl = get_conf_key_value(
130+
"server",
131+
"sslConfig",
132+
"enableSplunkdSSL",
133+
use_btool=use_btool,
134+
session_key=session_key,
135+
app_name=APP_SYSTEM
136+
)
184137

185-
if is_true(
186-
get_conf_key_value("server", "sslConfig", "enableSplunkdSSL", APP_SYSTEM)
187-
):
138+
if is_true(enable_splunkd_ssl):
188139
scheme = "https"
189140
else:
190141
scheme = "http"
191142

192-
host_port = get_conf_key_value("web", "settings", "mgmtHostPort", APP_SYSTEM)
143+
host_port = get_conf_key_value(
144+
"web",
145+
"settings",
146+
"mgmtHostPort",
147+
use_btool=use_btool,
148+
session_key=session_key,
149+
app_name=APP_SYSTEM
150+
)
193151
host_port = host_port.strip()
194152
host_port_split_parts = host_port.split(":")
195153
host = ":".join(host_port_split_parts[:-1])
@@ -203,14 +161,24 @@ def get_splunkd_access_info() -> Tuple[str, str, int]:
203161
return scheme, host, port
204162

205163

206-
def get_scheme_from_hec_settings() -> str:
164+
def get_scheme_from_hec_settings(
165+
use_btool: Optional[bool] = False,
166+
session_key: Optional[str] = None
167+
) -> str:
207168
"""Get scheme from HEC global settings.
208169
209170
Returns:
210171
scheme (str)
211172
"""
212173
try:
213-
ssl_enabled = get_conf_key_value("inputs", "http", "enableSSL", APP_HEC)
174+
ssl_enabled = get_conf_key_value(
175+
"inputs",
176+
"http",
177+
"enableSSL",
178+
use_btool=use_btool,
179+
session_key=session_key,
180+
app_name=APP_HEC
181+
)
214182
except KeyError:
215183
raise KeyError(
216184
"Cannot get enableSSL setting form conf: 'inputs' and stanza: '[http]'. "
@@ -237,20 +205,29 @@ def get_splunkd_uri() -> str:
237205
if os.environ.get("SPLUNKD_URI"):
238206
return os.environ["SPLUNKD_URI"]
239207

240-
scheme, host, port = get_splunkd_access_info()
208+
scheme, host, port = get_splunkd_access_info(use_btool=True)
241209
return f"{scheme}://{host}:{port}"
242210

243211

244212
def get_conf_key_value(
245-
conf_name: str, stanza: str, key: str, app_name: Optional[str] = None
213+
conf_name: str,
214+
stanza: str,
215+
key: str,
216+
use_btool: Optional[bool] = False,
217+
app_name: Optional[str] = None,
218+
session_key: Optional[str] = None,
219+
user: Optional[str] = "nobody"
246220
) -> Union[str, List, dict]:
247221
"""Get value of `key` of `stanza` in `conf_name`.
248222
249223
Arguments:
250224
conf_name: Config file.
251225
stanza: Stanza name.
252226
key: Key name.
227+
use_btool: If True, stanzas will be retrieved using cmd btool... otherwise using splunk API. Optional.
253228
app_name: Application name. Optional.
229+
session_key: If not provided solnlib will try to get it from splunk.getSessionKey(). Optional.
230+
user: used for set user context in API call. Optional.
254231
255232
Returns:
256233
Config value.
@@ -259,18 +236,43 @@ def get_conf_key_value(
259236
KeyError: If `stanza` or `key` doesn't exist.
260237
"""
261238

262-
stanzas = get_conf_stanzas(conf_name, app_name)
263-
return stanzas[stanza][key]
239+
if use_btool:
240+
stanzas = get_conf_stanzas(conf_name, app_name)
241+
return stanzas[stanza][key]
242+
243+
if not app_name:
244+
raise KeyError("app name must be specified if use_btool is True")
245+
246+
stanzas = _get_conf_stanzas_from_splunk_api(
247+
conf_name,
248+
app_name,
249+
session_key=session_key,
250+
user=user,
251+
stanza=stanza
252+
)
253+
254+
stanza = stanzas.get("entry")[0].get("content")
255+
requested_key = stanza[key]
256+
return requested_key
264257

265258

266259
def get_conf_stanza(
267-
conf_name: str, stanza: str, app_name: Optional[str] = None
260+
conf_name: str,
261+
stanza: str,
262+
use_btool: Optional[bool] = False,
263+
app_name: Optional[str] = None,
264+
session_key: Optional[str] = None,
265+
user: Optional[str] = "nobody"
268266
) -> dict:
269267
"""Get `stanza` in `conf_name`.
270268
271269
Arguments:
272270
conf_name: Config file.
273271
stanza: Stanza name.
272+
use_btool: If True, stanzas will be retrieved using cmd btool... otherwise using splunk API. Optional.
273+
app_name: Application name. Optional.
274+
session_key: If not provided solnlib will try to get it from splunk.getSessionKey(). Optional.
275+
user: used for set user context in API call. Optional.
274276
app_name: Application name. Optional.
275277
276278
Returns:
@@ -280,8 +282,23 @@ def get_conf_stanza(
280282
KeyError: If stanza doesn't exist.
281283
"""
282284

283-
stanzas = get_conf_stanzas(conf_name, app_name)
284-
return stanzas[stanza]
285+
if use_btool:
286+
stanzas = get_conf_stanzas(conf_name, app_name)
287+
return stanzas[stanza] # uncomment after tests
288+
289+
if not app_name:
290+
raise KeyError("app name must be specified if use_btool is True")
291+
292+
stanzas = _get_conf_stanzas_from_splunk_api(
293+
conf_name,
294+
app_name,
295+
session_key=session_key,
296+
user=user,
297+
stanza=stanza
298+
)
299+
300+
stanza = stanzas.get("entry")[0].get("content")
301+
return stanza
285302

286303

287304
def get_conf_stanzas(conf_name: str, app_name: Optional[str] = None) -> dict:
@@ -330,3 +347,41 @@ def get_conf_stanzas(conf_name: str, app_name: Optional[str] = None) -> dict:
330347
for section in parser.sections():
331348
out[section] = {item[0]: item[1] for item in parser.items(section, raw=True)}
332349
return out
350+
351+
352+
def _get_conf_stanzas_from_splunk_api(
353+
conf_name: str,
354+
app_name: str,
355+
session_key: Optional[str] = None,
356+
user: Optional[str] = "nobody",
357+
stanza: Optional[str] = None,
358+
) -> dict:
359+
"""Get stanzas of `conf_name` using splunk API:
360+
/servicesNS/{user}/{app_name}/configs/conf-{conf_name}/{stanza}
361+
362+
Arguments:
363+
conf_name: Config file.
364+
app_name: Application name.
365+
session_key: Session key. Optional.
366+
user: Username. Optional.
367+
stanza: Stanza name. Optional.
368+
369+
Returns:
370+
json response.
371+
"""
372+
373+
url = f"/servicesNS/{user}/{app_name}/configs/conf-{conf_name}"
374+
375+
if stanza:
376+
url = url + "/" + stanza
377+
378+
if not session_key:
379+
session_key = getSessionKey()
380+
381+
server_response, server_content = simpleRequest(
382+
url, sessionKey=session_key, getargs={"output_mode": "json"}, logme=True
383+
)
384+
385+
result = json.loads(server_content.decode())
386+
387+
return result

0 commit comments

Comments
 (0)