Skip to content

Commit

Permalink
Updated splunk python SDK from 2.0.2 to 2.1.0 as per Splunk cloud com…
Browse files Browse the repository at this point in the history
…patibility requirements
  • Loading branch information
gjanders committed Nov 24, 2024
1 parent 4cf5107 commit 152e205
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 9 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ Shannon Davis (Splunk)
Steven (malvidin on github)

# Release Notes
## 2.4.4
Updated splunk python SDK from 2.0.2 to 2.1.0 as per Splunk cloud compatibility requirements

## 2.4.3
Updated splunk python SDK from 2.0.1 to 2.0.2 as per Splunk cloud compatibility requirements

Expand Down
2 changes: 1 addition & 1 deletion bin/lib/splunklib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ def setup_logging(level, log_format=DEFAULT_LOG_FORMAT, date_format=DEFAULT_DATE
datefmt=date_format)


__version_info__ = (2, 0, 2)
__version_info__ = (2, 1, 0)
__version__ = ".".join(map(str, __version_info__))
9 changes: 8 additions & 1 deletion bin/lib/splunklib/binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ class Context:
:type scheme: "https" or "http"
:param verify: Enable (True) or disable (False) SSL verification for https connections.
:type verify: ``Boolean``
:param self_signed_certificate: Specifies if self signed certificate is used
:type self_signed_certificate: ``Boolean``
:param sharing: The sharing mode for the namespace (the default is "user").
:type sharing: "global", "system", "app", or "user"
:param owner: The owner context of the namespace (optional, the default is "None").
Expand Down Expand Up @@ -526,6 +528,7 @@ def __init__(self, handler=None, **kwargs):
self.bearerToken = kwargs.get("splunkToken", "")
self.autologin = kwargs.get("autologin", False)
self.additional_headers = kwargs.get("headers", [])
self._self_signed_certificate = kwargs.get("self_signed_certificate", True)

# Store any cookies in the self.http._cookies dict
if "cookie" in kwargs and kwargs['cookie'] not in [None, _NoAuthenticationToken]:
Expand Down Expand Up @@ -604,7 +607,11 @@ def connect(self):
"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if self.scheme == "https":
sock = ssl.wrap_socket(sock)
context = ssl.create_default_context()
context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
context.check_hostname = not self._self_signed_certificate
context.verify_mode = ssl.CERT_NONE if self._self_signed_certificate else ssl.CERT_REQUIRED
sock = context.wrap_socket(sock, server_hostname=self.host)
sock.connect((socket.gethostbyname(self.host), self.port))
return sock

Expand Down
96 changes: 95 additions & 1 deletion bin/lib/splunklib/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
PATH_JOBS = "search/jobs/"
PATH_JOBS_V2 = "search/v2/jobs/"
PATH_LOGGER = "/services/server/logger/"
PATH_MACROS = "configs/conf-macros/"
PATH_MESSAGES = "messages/"
PATH_MODULAR_INPUTS = "data/modular-inputs"
PATH_ROLES = "authorization/roles/"
Expand Down Expand Up @@ -667,6 +668,15 @@ def saved_searches(self):
"""
return SavedSearches(self)

@property
def macros(self):
"""Returns the collection of macros.
:return: A :class:`Macros` collection of :class:`Macro`
entities.
"""
return Macros(self)

@property
def settings(self):
"""Returns the configuration settings for this instance of Splunk.
Expand Down Expand Up @@ -3440,6 +3450,90 @@ def create(self, name, search, **kwargs):
return Collection.create(self, name, search=search, **kwargs)


class Macro(Entity):
"""This class represents a search macro."""
def __init__(self, service, path, **kwargs):
Entity.__init__(self, service, path, **kwargs)

@property
def args(self):
"""Returns the macro arguments.
:return: The macro arguments.
:rtype: ``string``
"""
return self._state.content.get('args', '')

@property
def definition(self):
"""Returns the macro definition.
:return: The macro definition.
:rtype: ``string``
"""
return self._state.content.get('definition', '')

@property
def errormsg(self):
"""Returns the validation error message for the macro.
:return: The validation error message for the macro.
:rtype: ``string``
"""
return self._state.content.get('errormsg', '')

@property
def iseval(self):
"""Returns the eval-based definition status of the macro.
:return: The iseval value for the macro.
:rtype: ``string``
"""
return self._state.content.get('iseval', '0')

def update(self, definition=None, **kwargs):
"""Updates the server with any changes you've made to the current macro
along with any additional arguments you specify.
:param `definition`: The macro definition (optional).
:type definition: ``string``
:param `kwargs`: Additional arguments (optional). Available parameters are:
'disabled', 'iseval', 'validation', and 'errormsg'.
:type kwargs: ``dict``
:return: The :class:`Macro`.
"""
# Updates to a macro *require* that the definition be
# passed, so we pass the current definition if a value wasn't
# provided by the caller.
if definition is None: definition = self.content.definition
Entity.update(self, definition=definition, **kwargs)
return self

@property
def validation(self):
"""Returns the validation expression for the macro.
:return: The validation expression for the macro.
:rtype: ``string``
"""
return self._state.content.get('validation', '')


class Macros(Collection):
"""This class represents a collection of macros. Retrieve this
collection using :meth:`Service.macros`."""
def __init__(self, service):
Collection.__init__(
self, service, PATH_MACROS, item=Macro)

def create(self, name, definition, **kwargs):
""" Creates a macro.
:param name: The name for the macro.
:type name: ``string``
:param definition: The macro definition.
:type definition: ``string``
:param kwargs: Additional arguments (optional). Available parameters are:
'disabled', 'iseval', 'validation', and 'errormsg'.
:type kwargs: ``dict``
:return: The :class:`Macros` collection.
"""
return Collection.create(self, name, definition=definition, **kwargs)


class Settings(Entity):
"""This class represents configuration settings for a Splunk service.
Retrieve this collection using :meth:`Service.settings`."""
Expand Down Expand Up @@ -3905,4 +3999,4 @@ def batch_save(self, *documents):
data = json.dumps(documents)

return json.loads(
self._post('batch_save', headers=KVStoreCollectionData.JSON_HEADER, body=data).body.read().decode('utf-8'))
self._post('batch_save', headers=KVStoreCollectionData.JSON_HEADER, body=data).body.read().decode('utf-8'))
20 changes: 20 additions & 0 deletions bin/lib/splunklib/modularinput/event_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# under the License.

import sys
import traceback

from splunklib.utils import ensure_str
from .event import ET
Expand Down Expand Up @@ -66,6 +67,25 @@ def log(self, severity, message):
self._err.write(f"{severity} {message}\n")
self._err.flush()

def log_exception(self, message, exception=None, severity=None):
"""Logs messages about the exception thrown by this modular input to Splunk.
These messages will show up in Splunk's internal logs.
:param message: ``string``, message to log.
:param exception: ``Exception``, exception thrown by this modular input; if none, sys.exc_info() is used
:param severity: ``string``, severity of message, see severities defined as class constants. Default severity: ERROR
"""
if exception is not None:
tb_str = traceback.format_exception(type(exception), exception, exception.__traceback__)
else:
tb_str = traceback.format_exc()

if severity is None:
severity = EventWriter.ERROR

self._err.write(("%s %s - %s" % (severity, message, tb_str)).replace("\n", " "))
self._err.flush()

def write_xml_document(self, document):
"""Writes a string representation of an
``ElementTree`` object to the output stream.
Expand Down
7 changes: 3 additions & 4 deletions bin/lib/splunklib/modularinput/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,12 @@ def run_script(self, args, event_writer, input_stream):
event_writer.write_xml_document(root)

return 1
err_string = "ERROR Invalid arguments to modular input script:" + ' '.join(
args)
event_writer._err.write(err_string)
event_writer.log(EventWriter.ERROR, "Invalid arguments to modular input script:" + ' '.join(
args))
return 1

except Exception as e:
event_writer.log(EventWriter.ERROR, str(e))
event_writer.log_exception(str(e))
return 1

@property
Expand Down
4 changes: 2 additions & 2 deletions default/app.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ id = decrypt2

[install]
state = enabled
build = 20240914
build = 20241124

[ui]
label = DecryptCommands
Expand All @@ -12,4 +12,4 @@ is_visible = false
[launcher]
author = Gareth Anderson
description = A library of common routines to analyze malware and data exfiltration communications (based on the work of Michael Zalewski).
version = 2.4.3
version = 2.4.4

0 comments on commit 152e205

Please sign in to comment.