Skip to content

Commit

Permalink
Add security token auth and credential loading from msticpyconfig.yam…
Browse files Browse the repository at this point in the history
…l to SplunkUploader (microsoft#731)

* splunkToken auth and credentials loading from msticpyconfig.yaml

* parameter name replaced from splunkToken to bearer_token

* modify just lints

* a few fix for pytest result.

---------

Co-authored-by: Ian Hellen <[email protected]>
  • Loading branch information
Tatsuya-hasegawa and ianhelle authored Dec 15, 2023
1 parent 471bb1b commit 3b192cb
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ repos:
entry: python -m tools.create_reqs_all
pass_filenames: False
language: python
types: [python]
types: [python]
10 changes: 5 additions & 5 deletions docs/source/data_acquisition/SplunkProvider.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ Parameter Description
host (string) The host name (the default is 'localhost').
username (string) The Splunk account username, which is used to authenticate the Splunk instance.
password (string) The password for the Splunk account.
splunkToken (string) The Authorization Bearer Token <JWT> created in the Splunk.
bearer_token (string) The Authorization Bearer Token <JWT> created in the Splunk.
=========== ===========================================================================================================================

The username and password are needed for user account authentication.
On the other hand, splunkToken is needed for Token authentication.
The user auth method has a priority to token auth method if both username and splunkToken are set.
On the other hand, bearer_token is needed for Token authentication.
The user auth method has a priority to token auth method if both username and bearer_token are set.


Optional configuration parameters:
Expand Down Expand Up @@ -136,7 +136,7 @@ On the other hand, you can use the authentification token to connect.
- host = "localhost" (Splunk server FQDN hostname to connect, for locally
installed splunk, you can specify localhost)
- port = "8089" (Splunk REST API)
- splunkToken = "<Authorization Bearer Token>" (token can be used instead of username/password)
- bearer_token = "<Authorization Bearer Token>" (token can be used instead of username/password)


Once you have details, you can specify it in ``msticpyconfig.yaml`` as
Expand Down Expand Up @@ -165,7 +165,7 @@ OR

.. code:: ipython3
qry_prov.connect(host=<hostname>, splunkToken=<token_string>)
qry_prov.connect(host=<hostname>, bearer_token=<token_string>)
Listing available queries
Expand Down
8 changes: 8 additions & 0 deletions docs/source/data_acquisition/UploadData.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Instantiating the Splunk uploader
The first step in uploading data is to instantiate an uploader for the location we wish to upload data to.
For Splunk there are three parameters that need to be passed at this stage, the Splunk host name, a username,
and a password. You can also pass a parameter for ``port``, by default this value is 8089.
In addition, The security auth token of ``bearer_token`` can be also passed instead of username and password as same as Splunk QueryProvider.

.. code:: ipython3
Expand All @@ -89,6 +90,13 @@ and a password. You can also pass a parameter for ``port``, by default this valu
You can also set a ``debug`` flag when instantiating which will provide additional progress messages during an upload process.

On the other hand, You can use the stored credentials in msticpyconfig.yaml to SplunkUploader.

.. code:: ipython3
from msticpy.data.uploaders.splunk_uploader import SplunkUploader
spup = SplunkUploader()
*Note: Due to the way Splunk API's work the time taken to upload a file to Splunk can be significantly longer than
with Log Analytics.*

Expand Down
11 changes: 9 additions & 2 deletions msticpy/data/drivers/splunk_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@
"username": "(string) The Splunk account username, which is used to "
+ "authenticate the Splunk instance.",
"password": "(string) The password for the Splunk account.",
"splunkToken": "(string) The Authorization Bearer Token <JWT> created in the Splunk.",
"bearer_token": "(string) The Authorization Bearer Token <JWT> created in the Splunk."
+ " (Named as 'splunkToken' in Splunk Python SDK)",
}


Expand Down Expand Up @@ -123,6 +124,11 @@ def connect(self, connection_str: Optional[str] = None, **kwargs):
arg_dict = {
key: val for key, val in cs_dict.items() if key in SPLUNK_CONNECT_ARGS
}

# Replace to Splunk python sdk's parameter name of sp_client.connect()
if arg_dict.get("bearer_token"):
arg_dict["splunkToken"] = arg_dict.pop("bearer_token")

try:
self.service = sp_client.connect(**arg_dict)
except AuthenticationError as err:
Expand Down Expand Up @@ -179,7 +185,7 @@ def _get_connect_args(
if "username" in cs_dict:
self._required_params = ["host", "username", "password"]
else:
self._required_params = ["host", "splunkToken"]
self._required_params = ["host", "bearer_token"]

missing_args = set(self._required_params) - cs_dict.keys()
if missing_args:
Expand All @@ -191,6 +197,7 @@ def _get_connect_args(
*[f"{arg}: {desc}" for arg, desc in SPLUNK_CONNECT_ARGS.items()],
title="no Splunk connection parameters",
)

return cs_dict

def query(
Expand Down
42 changes: 31 additions & 11 deletions msticpy/data/uploaders/splunk_uploader.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# license information.
# --------------------------------------------------------------------------
"""Splunk Uploader class."""
import logging
from pathlib import Path
from typing import Any, Optional

Expand All @@ -17,19 +18,22 @@
from .uploader_base import UploaderBase

__version__ = VERSION
__author__ = "Pete Bryan"
__author__ = "Pete Bryan, Tatsuya Hasegawa"

logger = logging.getLogger(__name__)


class SplunkUploader(UploaderBase):
"""Uploader class for Splunk."""

def __init__(self, username: str, host: str, password: str, **kwargs):
def __init__(self, **kwargs):
"""Initialize a Splunk Uploader instance."""
super().__init__()
self._kwargs = kwargs
self.workspace = host
self.workspace_secret = password
self.user = username
self.host = kwargs.get("host")
self.password = kwargs.get("password")
self.username = kwargs.get("username")
self.bearer_token = kwargs.get("bearer_token")
self.driver = SplunkDriver()
self.port = kwargs.get("port", 8089)
self._debug = kwargs.get("debug", False)
Expand All @@ -40,12 +44,28 @@ def __init__(self, username: str, host: str, password: str, **kwargs):

def connect(self):
"""Connect to Splunk host."""
self.driver.connect(
host=self.workspace,
username=self.user,
password=self.workspace_secret,
port=self.port,
)
if self._kwargs:
if self.username:
self.driver.connect(
host=self.host,
username=self.username,
password=self.password,
port=self.port,
)
elif self.bearer_token:
self.driver.connect(
host=self.host,
bearer_token=self.bearer_token,
port=self.port,
)
else:
logger.info("username/bearer_token are missing.")
logger.info("Credential loading from config file.")
self.driver.connect()
else:
logger.info("Credential loading from config file.")
self.driver.connect()

self.connected = True

def _post_data(
Expand Down

0 comments on commit 3b192cb

Please sign in to comment.