ic3guy / soarsdk

Object Based Splunk SOAR REST Library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

soarsdk overview

At its core, soarsdk a customer built API wrapper for the Splunk SOAR product. This tool was primarily built for use with the soar-behaviors test suite but proved invaluable for administrative tasks and larger scale projects. The goal of this project to simplify and standardize script interactions with Splunk SOAR in an object-oriented manner.

This is the initial release and we will be adding additional functionality in the coming weeks to simplify usage even further.

Authentication

Standard Authentications

from soarsdk.client import PhantomClient
# Password authentication 
phantom: PhantomClient = PhantomClient(username='username', password='password')

# Token Authentication 
phantom: PhantomClient = PhantomClient(token='token_string')

Providing an authenticated session

For larger organizations, it might be necessary to build out a custom authentication library to handle caching and different authentication schemas outside of the standard credentials or tokens. The requests.session object provided must have the appropriate CSRF token set inside the headers (example here).

from soarsdk.client import PhantomClient
from custom_module import authentication_function

soar_url, authenticated_session = authentication_function()
phantom: PhantomClient = PhantomClient(url=soar_url, session=authenticated_session)

More information will be coming soon that provide guidance on credential caching & storage.

Object Variables operations

import soarsdk 
# Object Creation
container1 = soarsdk.objects.Container()
container1.name = 'Test Container'
container1.label = 'workbench'

container1 = soarsdk.objects.Container(name='Test Container', label='workbench')
artifact1 = soarsdk.objects.Artifact(name='test_artifact_1' label='test_label')

This methodology makes it easier to adapt future functionality. By having a PhantomObject as a dictionary, it makes it simple to grab and update any information from the API pertaining to that object.

Creating Containers with Artifacts

# import soarsdk library 
from soarsdk.client import PhantomClient
from soarsdk.objects import Artifact, Container

phantom: PhantomClient = PhantomClient(username='username', password='password')

container: Container = Container(name="soarsdk Library Example", label="any_label")
artifact1: Artifact = Artifact(name="soarsdk Artifact 1", label="soarsdk 1")
artifact2: Artifact = Artifact(name="soarsdk Artifact 2", label="soarsdk 2")

container.add_artifact(artifact1, artifact2)

phantom.create_container(container=container)

Referencing an Existing Container

To download an existing container on the server, you can initialize a container object with the "id" attribute set. The method update_container_values will query the API to pull back its data, artifacts, actions, playbooks, notes, etc. This can be an expensive query to use in a loop.

from soarsdk.client import PhantomClient
from soarsdk.objects import Artifact, Container

phantom: PhantomClient = PhantomClient(username='username', password='password')

existing_container: Container = Container(id=123)

phantom.update_container_values(container)

Running Playbooks

Once you have an initialized container, there are a few different options to launch playbooks. You can define and assign the playbook to the container or provide the playbook object as a parameter.

Appending to the container

from soarsdk.client import PhantomClient
from soarsdk.objects import Container
from soarsdk.objects import Playbook
from soarsdk.exceptions import PlaybookException 

phantom: PhantomClient = PhantomClient(username='username', password='password')

existing_container: Container = Container(id=123)

phantom.update_container_values(container)

container.playbooks.append(Playbook(name="repo/playbook_name"))

phantom.run_playbooks(existing_container)

Running a Playbook as an arg

from soarsdk.client import PhantomClient
from soarsdk.objects import Container
from soarsdk.objects import Playbook
from soarsdk.exceptions import PlaybookException 

phantom: PhantomClient = PhantomClient(username='username', password='password')

existing_container: Container = Container(id=123)

phantom.update_container_values(container)

playbook_with_asset_error: Playbook = Playbook(name="repo/playbook_name")

phantom.run_playbooks(existing_container, playbook)

Handling Playbook Exceptions

By default, the soarsdk.client.PhantomClient.run_playbooks() method will monitor for python exceptions & action errors. To prevent the associated exception to be thrown, use the following try/except block.

from soarsdk.client import PhantomClient
from soarsdk.objects import Container
from soarsdk.objects import Playbook
from soarsdk.exceptions import PlaybookException 

phantom: PhantomClient = PhantomClient(username='username', password='password')

existing_container: Container = Container(id=123)

phantom.update_container_values(container)

playbook_with_asset_error: Playbook = Playbook(name="repo/playbook_name")

try:
    phantom.run_playbooks(existing_container, playbook_with_asset_error)
except PlaybookException:
    pass

Working with Prompts

Approvals for a given playbook are associated within the "Playbook" object. To define a series of prompts/approvals on a given container, create a dictionary where each key is the specific prompt_name and the value is a list of strings containing the ordered responses. Consider the following example

from soarsdk.client import PhantomClient
from soarsdk.objects import Artifact, Container

phantom: PhantomClient = PhantomClient(username='username', password='password')
artifact = Artifact(name='dummy', label='dummy')
container = Container(name='test', label='workbench', artifacts=[artifact])
phantom.create_container(container)

# let's define the prompts / approvals we need to match 
prompts = {
    'prompt_1': ['This is a standard response to an input', 'No', 'Apples'], 
    'prompt_2': ['Yes']
}
playbook = Playbook(name='soarsdk_prompts_test', prompts=prompts) 
container.add_playbooks(playbook)
phantom.run_playbooks(container=container)
                    

The playbook will launch and when an approval is found matching one configured on the Playbook object, it will answer the prompt with the pre-supplied responses. soarsdk doesn't rely on the order of the provided responses to map which answers should go where, instead, it uses the prompt_name configured on the playbook.

Differences in Objects versus the SOAR API

Playbooks vs Playbook_run

Playbooks objects are a combined abstraction of the rest/playbook (configuration object in SOAR) and the rest/playbook_run (instance of the playbook running). The main purpose of this is to simplify interactions for the testing library. The soarsdk.objects.Playbook object is primarily a representation of the playbook_run endpoint

Action vs Action_run vs App_run

The action object is also a hybrid object from this perspective. The action is primarily an action_run object with some configuration items available from the the action endpoint. When pulling down results from a playbook or action's execution, it will also add the key elements from its app_execution if present. This was mainly to simplify access without having to iterate through multiples of objects and provides a similar view the GUI in mission control.

Notes on Requests & Errors

All HTTP requests handled by the library utilize the function PhantomConnector._handle_request() which contains error handling and exception throwing based off the HTTP status code.

Development

General development

  1. Install a standard VS Code remote development environment https://code.visualstudio.com/docs/remote/containers#_installation (Note: Other docker-compatible providers can be used in place of Docker Desktop, such as Rancher Desktop)
  2. Clone this repository and open the directory in VS Code, follow the prompt to use the embedded development container configuration

Contributor Credits

Special thanks to the following contributors who've helped develop and grow this solution before its public release:

About

Object Based Splunk SOAR REST Library

License:BSD 3-Clause "New" or "Revised" License


Languages

Language:Python 99.9%Language:Dockerfile 0.1%