After the future removal of the classic playbook editor, your existing classic playbooks will continue to run, However, you will no longer be able to visualize or modify existing classic playbooks.
For details, see:
Data access automation API
The Automation API allows security operations teams to develop detailed and precise automation strategies. Playbooks can serve many purposes, ranging from automating minimal investigative tasks that can speed up analysis to large-scale responses to a security breach. The following APIs are supported to leverage the capabilities of data access using playbooks.
In code examples, the term None
refers to a Python None
or nulltype
and means the same as unspecified value
, value not set
, or not specifying the parameter at all. For example, Limit=None
does not set the value to be unlimited, it sets the value to the default of 2000.
collect
Use the collect API to gather information from the associated artifacts of a container or action results that you get in the action callback or through the get_action_results() API. You can also use the collect API to obtain a listing of all IP addresses or all file hashes across all artifacts by specifying the appropriate data path into the artifact JSON. Or, extract all country ISO codes from the action results of action geolocate IP and pass the collect API into the results object. You can specify either one datapath as a string for the information you want to extract from action results, or you can specify more than one datapath in a list of datapath strings.
The collect API has a suggested limit value of 2000 artifacts, which is a very large number of artifacts for a single event. Avoid use cases that rely on more than 2000 artifacts for a single event. Such large numbers of artifacts in a single event can cause performance and usability issues.
The collect API is supported from within a custom function.
phantom.collect(container, #this can be a container or an action results object datapath, scope='new', limit=100, none_if_first=False)
Parameter | Required | Description |
---|---|---|
container | Required | The container that is available to the user in on_start(), on_finish(), or any action callback. It can be a results object that you get in the action callback or through the get_action_results() API. |
datapath | Required | The path of the element in the JSON schema to access or retrieve it from associated artifacts of a container or the action results object.
The following are example datapaths for a container:
The following are example datapaths for action results:
If you specify a list of datapaths for extracting data from action results, the results are formatted as a table, where each column represents the respective datapath. If you specify a single datapath as a string, Splunk SOAR returns the data corresponding to one column. |
scope | Optional | This parameter defines if the data has to be collected from artifacts and over what range of time the data is collected. The scope parameter can be new, which implies that the information has to be collected only from new artifacts since the playbook last ran on that container. The all scope parameter implies that the information has to be collected from all of the artifacts in the container.
An active playbook runs on a container after it has been created and every time new artifacts are added to the container. You can use the |
limit | Optional | This parameter enforces the maximum number of artifacts that can be retrieved in this call. If the limit parameter is not specified, the limit is 2000. Specifying a number larger than 2000 is not recommended. For details, see the note before this table. |
none_if_first | Optional | When the collect API call is executed from a playbook for the first time on a container, even with the scope='new' argument, it collects all the artifacts since the container was created. Use this parameter to change the behavior of the collect API call executed for the first time from this playbook on a container. You can also use this parameter to specify whether the playbook collects all artifacts since the container was created, or only those artifacts added since the first time the playbook was executed on the container. Use 'True' for this parameter if you want the playbook to not get any existing artifacts the first time it is run on the container. Then, on subsequent playbook runs, it gets only the artifacts added since the first playbook run. |
collect2
The collect2 API is an extension of the phantom.collect() API. It adds the filter_artifacts
parameter, which is a list of artifacts whose values are returned. To learn more about the datapaths used in the collect2 API, see Understanding datapaths.
The collect2 API is supported from within a custom function.
phantom.collect2(container=None, action_results=None, action_name=None, datapath=None, filter_artifacts=None, tags=None, scope='new', limit=100, trace=False)
Parameter | Required? | Description |
---|---|---|
container | Required | The container dictionary object that is passed to the playbook across various functions. |
action_results | Optional, unless the action_name parameter is not provided. |
The action results passed into any callback function, or a subset of action results that are filtered from a phantom.condition() call. Results may be a mix of custom function and action results. |
action_name | Optional, unless the action_results parameter is not provided. |
The custom name specified for the action or custom function in the phantom.act() API. This parameter allows action results to be returned based on the action name or custom function name.
If a block name is supplied to the collect2 API either from the datapath or the |
datapath | Required | A list of datapaths. A datapath is the path of the element in the JSON schema to be able to access or retrieve it from associated action results, custom function results, or artifacts. For more information, see collect. |
filter_artifacts | Optional | IDs of artifacts returned from a phantom.condition() call. |
tags | Optional | A list of tags used to filter artifacts. |
scope | Optional | Scope of artifacts to retrieve. The default is new. For more information, see collect. |
limit | Optional | The maximum number of results to be returned. For more information, see collect. |
trace | Optional | Trace is a flag related to the level of logging. If trace is set to True, more logging is enabled and more detailed output is displayed in debug output. |
Although literal values are valid datapaths, the collect2 API does not interpret them as such.
This sample uses the phantom.collect2() API.
Example request
collect2( container=container, action_results=[ { 'name': 'geolocate_ip_1', 'action_results': [{ 'parameter': { 'ip': '10.0.0.1', }, }], action_name, }, { 'name': 'geolocate_ip_1', 'action_results': [{ 'parameter': { 'ip': '10.0.0.2', }, }], 'summary': {}, }, ], datapath=[ 'action_result.parameter.ip', ], )
Beginning with Splunk Phantom 4.9, if the 'summary' key does not exist for an action result object, then 'summary' will default to an empty dict, for example 'summary': {}
.
Example response
[ ['10.0.0.1'], ['10.0.0.2'], ]
collect_from_contains
The collect_from_contains API functions similarly to collect, but instead of using datapaths for the values you want, you instead provide a contains value. This action returns a flat list of all the unique values that match at least one contains in the list. The call returns None if it fails.
The collect_from_contains API is supported from within a custom function.
phantom.collect_from_contains(container=None, action_results=None, contains=None, tags=None, scope=None, filter_artifacts=None, include_params=True, limit=None, trace=False)
Parameter | Required? | Description |
---|---|---|
container | Optional, unless the action_results parameter is not provided. |
Passing this parameter searches for contains in the Common Event Format (CEF) values of that container. |
action_results | Optional, unless the container parameter is not provided. |
This parameter is an action result, like what is passed to a callback from phantom.act() as Result. Search for values matching the contains in this action result. |
contains | Required | A list of contains to filter by. |
tags | Optional | A list of tags used to further filter artifacts. |
filter_artifacts | Optional | The IDs of artifacts that were returned from a phantom.condition()call. |
include_params | Optional | If set to False, ignore values with matching contains if they are a parameter to an action. This value is only used if the action_result parameter is passed in. |
scope | Optional | Scope of artifacts to retrieve. The default is new. This parameter is only used if a container is provided. For more information, see collect. |
limit | Optional | Maximum number of artifacts to match. This value is used only if a container is provided. |
trace | Optional | Trace is a flag related to the level of logging. If trace is on (True), more logging is enabled. When set to True, more detailed output is displayed in debug output. |
This sample uses the phantom.collect_from_contains() API.
import phantom.rules as phantom def geolocate_ip(action, success, container, results, handle): # We have already created various artifacts for this event collected_ips = phantom.collect_from_contains(container=container, contains=["ip"]) # [ "8.8.8.8", "8.8.4.4", "1.1.1.1", ... ] parameters = [] for ip in collected_ips: parameters.append({ 'ip': ip }) phantom.act("geolocate ip", parameters=parameters, app={ "name": "MaxMind" }, name="geolocate_ip") return def collect_from_action_result(results): return phantom.collect_from_contains(action_results=results, contains=["url", "domain"])
get_action_results
Use the get_action_results API to retrieve the action results using the action JSON that was given in the action callback or the action run ID that was given in the action JSON. The API call get_summary() also returns one or more app run IDs that can be passed in as the optional parameter.
The get_action_results API is supported from within a custom function.
phantom.get_action_results(action=None, action_run_id = 0, app_run_id = 0, result_data=True, action_name=None, playbook_run_id=0, flatten=True)
Parameter | Required? | Description |
---|---|---|
action | Optional, unless the action_run_id and app_run_id parameters are not provided. |
Action JSON object provided in the action callback. Using this parameter provides the action results from the action that completed and triggered the callback function. |
action_run_id | Optional, unless the action and app_run_id parameters are not provided. |
The ID of the action run. Use this parameter to obtain action results from any completed action runs from the current playbook. The action_run_id parameter can be obtained from the previously noted action JSON object or by calling the phantom.get_summary() API, which enumerates all of the actions that were executed in the playbook. |
app_run_id | Optional, unless the action and action_run_id parameters are not provided. |
The ID of the app run. This parameter can be obtained by calling the phantom.get_summary() API, which enumerates all of the actions that were executed in the playbook. |
result_data | Optional | The default is True. If the user doesn't need to obtain the full action results or needs summary information, set this parameter to False. |
action_name | Optional | The unique name provided to an action execution by using the phantom.act() parameter name .
|
playbook_run_id | Optional | The playbook run ID that uniquely identifies the playbook execution instance. A default value of zero implies the current playbook execution instance. |
flatten | Optional | The default is True. An action can be executed on more than one asset and for many sets of parameters. Flattening provides a result dictionary object for each combination of asset and parameter, even if many parameters were used in a single action. Setting this variable to False generates results as provided in action callbacks or when viewing the action results in Investigation widgets. |
A single phantom.act() API call can be executed on multiple sets of parameters on more than one asset. Each instance of phantom.act() call is identified by a unique action run ID. One action execution on each asset results in a corresponding app execution, each of which is identified by a unique app run ID Parameters of an action execution on each app, on their respective assets, can be part of the same app run.
This sample uses the phantom.get_action_results() API.
import phantom.rules as phantom import json def collect_params(container, datapath, key_name): params = [] items = set(phantom.collect(container, datapath, scope='all')) for item in items: params.append({key_name:item}) return params def on_start(container): parameters = collect_params(container, 'artifacts:*.cef.sourceAddress', 'ip') phantom.act('geolocate ip', parameters=parameters, name='my_geolocate_ip') return def on_finish(container, summary): summary_json = phantom.get_summary() if 'result' in summary_json: for action_result in summary_json['result']: if 'action_run_id' in action_result: action_results = phantom.get_action_results( action_run_id=action_result['action_run_id'], result_data=False, flatten=False) phantom.debug(action_results) return
The return value of this API is a list of JSON dictionaries, a dictionary per app run which runs an instance for each asset that was used to run the action on that has the action_results parameter.
The following action_result JSON object is generated with the parameters result_data=False and flatten=False sent to the get_action_results() API in the playbook shown previously. If the parameter result_data was specified as True, the dictionaries in the action_results list must include data that has the full action result information. Setting the flatten parameter to True generates the same data but nested action_results data lists are reorganized to have a flat hierarchy with a list of higher level objects. This hierarchy is primarily for backward compatibility.
This sample uses the phantom.get_action_results() API.
[ { "asset_id": 237, "status": "success", "name": "my_geolocate_ip", "app": "MaxMind", "action_results": [ { "status": "success", "message": "Country: France", "parameter": { "ip": "2.2.2.2", "context": {...} }, "summary": { "country": "France" } }, { "status": "success", "message": "Country: Australia", "parameter": { "ip": "1.1.1.1", "context": {...} }, "summary": { "country": "Australia" } } ], "app_id": 42, "app_run_id": 1076, "asset": "maxmind", "action": "geolocate ip", "message": "'my_geolocate_ip' on asset 'maxmind': 2 actions succeeded... ", "summary": { ...}, "action_run_id": 1083 } ]
get_apps
Use the get_apps API to let the user enumerate all of the apps installed on the system for each of the actions. The API returns a flat listing of all actions and apps with matching criteria.
The get_apps API is not supported from within a custom function.
phantom.get_apps(action, asset, app_type)
All of these parameters are optional, if the user does not specify any parameter, all the configured apps in the system are retrieved.
Parameter | Description |
---|---|
action | The name of the action. Use this parameter to retrieve information about assets that support the action. For example, name the action something like "block_ip" when you retrieve information about assets that support the block IP action. |
asset | The asset name that allows users to retrieve only those apps that match the specified asset. |
app_type | This allows users to retrieve only apps that match the specified type of the app. |
This sample uses the phantom.get_apps() API.
def on_start(container): apps=[] apps = phantom.get_apps() phantom.debug(apps) apps=phantom.get_apps(action='file reputation') phantom.debug(apps) apps = phantom.get_apps(asset='my_smtp_asset') phantom.debug(apps) apps = phantom.get_apps(app_type='information') phantom.debug(apps) return
This sample shows the return value of this API, which is a list of JSON dictionaries that have the following schema.
[ { "asset_disabled": false, "product_version_match": true, "app_type": "sandbox", "product_vendor": "Cuckoo", "product_name": "Cuckoo", "app_match_product_version": ".*", "asset_name": "cuckoo", "ap_name": "Cuckoo", "action": "detonate file", "app_version": "1.2.8", "asset_product_version": "", "asset_type": "sandbox" }, ... ]
get_assets
Use the get_assets API to get a list of the assets configured on your instance. You can filter the results by action name, tags, or asset types.
The get_assets API is not supported from within a custom function.
phantom.get_assets(action=None, tags=None, types=None)
Parameter | Required | Description |
---|---|---|
action | Optional | Use this parameter to retrieve only assets that support the named action. For example, "block_ip" to retrieve a list of assets that support the block IP action. |
tags | Optional | A list of 'tags' used to retrieve assets that are tagged with the specified keyword. |
types | Optional | If included, only return apps which are one of these 'types'. |
This sample uses the phantom.get_assets() API.
def on_start(container): assets = phantom.get_assets(action='file reputation') phantom.debug(assets) assets = phantom.get_assets(tags=['my_tag']) phantom.debug(assets) assets = phantom.get_assets(types=['reputation service']) return
The sample uses filters, so the results must satisfy all specified conditions. If you provide an action and a tag, only assets that have both the action and tag will be returned. However, the tags and types can take multiple options and return any asset that satisfies one of the values in the array. For example, if you use types=["identity management", "information"]) all information assets and all identity management assets are retrieved.
The sample shows the return value of this API, which is a list of JSON dictionaries that have the following schema. This will print "Error: Failed to get assets" if no matching assets are found.
[ { "app_id": 226, "description": "", "disabled": false, "id": 107, "name": "soar_rest_api_clone_1666817446737", "tags": [], "type": "information", "version": 1 }, ]
get_container
Use the get_container API to retrieve the JSON for a container as a Python object.
The get_container API is supported from within a custom function.
json_object = phantom.get_container(container_id)
Parameter | Required? | Description |
---|---|---|
container_id | Required | The ID of the container. |
This sample uses the phantom.get_container() API.
def on_start(container): cdata = phantom.get_container(container['id']) phantom.debug('Container Data: {}'.format(cdata)) return
get_current_container_id_
Use the get_current_container_id_ API to retrieve the id of the container where the current playbook or custom function is running.
phantom.get_current_container_id_()
The get_current_container_id_ API is supported from within a custom function.
The following sample shows an example of using get_current_container_id_ for both custom functions and playbooks.
container_id = phantom.get_current_container_id_() phantom.debug(f"The current container is: {container_id}")
get_custom_function_results
Use the get_custom_function_results API to get the results of your custom function. This API returns the same structure that the callback function receives as a keyword argument.
The get_custom_function_results API is supported from within a custom function.
phantom.get_custom_function_results( custom_function_run_id=None, custom_function_name=None, trace=False )
Parameter | Required? | Description |
---|---|---|
custom_function_run_id | Optional. Provide either this parameter or the custom_function_name parameter. |
The ID of the CustomFunctionRun object in the database. This is the value returned by the custom_function API.
|
custom_function_name | Optional. Provide either this parameter or the custom_function_name parameter. |
The name of the custom function block. This name is unique for each playbook. |
get_extra_data
Use the get_extra_data API to get the extra data retrieved during an action execution. You can specify the action, action run ID, or the app run ID as a key to obtain the data.
phantom.get_extra_data(action, action_run_id, app_run_id)
The get_extra_data API is not supported from within a custom function.
Parameter | Required? | Description |
---|---|---|
action | Optional | The action JSON object provided in the action callback. Using this parameter provides the extra data from the action that completed and triggered the callback function. |
action_run_id | Optional | ID of the action run. Using this parameter obtains extra data from any completed action runs from the current playbook. The action run ID can be obtained from the previously noted action JSON object or by calling the phantom.get_summary() API, which enumerates all the actions that were executed in the playbook. |
app_run_id | Optional | ID of the app run. Get the app run ID by calling the phantom.get_summary() API which enumerates all the actions that were executed in the playbook. |
This sample uses the phantom.get_extra_data() API.
import phantom.rules as phantom import json def domain_reputation_cb(action, success, container, results, handle): if not success: return extra_data = phantom.get_extra_data(action) phantom.debug("Testing extra data: ") phantom.debug(extra_data) return def on_start(container): phantom.act('domain reputation', parameters=[{ "domain" : "bjtuangouwang.com" }], assets=["passivetotal"], callback=domain_reputation_cb) return def on_finish(container, summary): phantom.debug("Summary: " + summary) return
The following sample shows the return value of this API, which is a list of JSON dictionaries that has the action results along with extra data.
[ { "asset_id": 7, "extra_data": [ { "status": "success", "extra_data": [{...}], "parameter": {} } ], "asset": "passivetotal" } ]
get_filtered_data
Use the get_filtered_data API to retrieve the filtered data that was saved by phantom.condition(). In the phantom.condition() API, if the name was specified, the filtered data is saved under the specified key and the same key can be used to retrieve the data. This API returns a tuple of filtered action results and filtered artifacts.
The get_filtered_data API is supported from within a custom function.
phantom.get_filtered_data(name=None)
Parameter | Required? | Description |
---|---|---|
name | Required | This parameter is used to save the filtered action results and filtered artifacts. |
This sample uses the phantom.get_filtered_data() API.
import phantom.rules as phantom import json from datetime import datetime, timedelta ... def filter_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): # collect filtered artifact ids for 'if' condition 1 matched_artifacts_1, matched_results_1 = phantom.condition( container=container, action_results=results, conditions=[ ["geolocate_ip_1:action_result.data.*.country_iso_code", "!=", "UK"], ["artifact:*.cef.bytesIn", "!=", 99], ], logical_operator='or', name="filter_1:condition_1") ... def on_finish(container, summary): filtered_results, filtered_artifacts = phantom.get_filtered_data(name="filter_1:condition_1")
get_format_data
Use the get_format_data API to retrieve data saved through the phantom.format() API. If you specified the name
parameter value in the phantom.format() API, the name can be used to retrieve the data. For sample usage, see format.
The get_format_data API is supported from within a custom function.
phantom.get_format_data(name=None)
get_parent_handle
Use the get_parent_handle API to retrieve the handle that has been set in the phantom.playbook() APIin the parent playbook. This API can be called from anywhere in the child playbook.
This API works only when the parent calls the child playbook in synchronous mode. See playbook for more information on calling playbooks in synchronous mode.
The get_parent_handle API is not supported from within a custom function.
json_object = phantom.get_parent_handle()
This sample shows the parent playbook used in the phantom.get_parent_handle() API.
some_handle="some_handle from parent pb" # 'some_handle' is now passed to the child playbook through the handle parameter. playbook_run_id = phantom.playbook("local/child_pb", container=container, name="playbook_local_child_pb_1", callback=decision_1, handle=some_handle)
This sample shows the child playbook used in the phantom.get_parent_handle() API.
def on_start(container): handle_from_parent=phantom.get_parent_handle() # this call can be done from any function of the child playbook phantom.debug("handle sent by parent playbook: {}".format(handle_from_parent)) return
get_playbook_info
Use the get_playbook_info API to retrieve your current playbook information such as ID, run ID, name, repository, and parent playbook run id, and the running playbook's effective user ID.
The get_playbook_info API is supported from within a custom function.
The return value of this API is a list containing a single dictionary.
phantom.get_playbook_info()
This sample uses the phantom.get_playbook_info() API.
[{ 'parent_playbook_run_id': '0', 'name': 'test_plabook', 'run_id': '37', 'scope_artifacts': [], 'scope': 'new', 'id': '562', 'repo_name': 'local', 'effective_user_id':5 }]
get_raw_data
Use the get_raw_data API to retrieve container raw data as it exists at the source. This API allows users to access and automate on raw data in cases where there is information that was not parsed into artifacts.
The get_raw_data API is not supported from within a custom function.
phantom.get_raw_data(container)
Parameter | Required? | Description |
---|---|---|
container | Required | This is the JSON container object as available in on_start , callback, or on_finish() functions.
|
This sample uses the phantom.get_raw_data() API.
import phantom.rules as phantom import json def on_start(container): raw_data = phantom.get_raw_data(container) phantom.debug(raw_data) return def on_finish(container, summary): return
The get_raw_data API pulls raw data from the container ["data"], and is often used to store raw emails and the ticketing tools raw data from on_poll
. When pulling data, the API uses the ["data"] section of the container to do so.
This sample uses the phantom.get_raw_data() API.
phantom.debug(phantom.get_raw_data(container)) phantom.update(container, {"data": {"this": "is a test"}}) phantom.debug(phantom.get_raw_data(container)) in a custom block on a container that does not leverage container['data']. The output: Wed May 13 2020 11:08:38 GMT-0600 (Mountain Daylight Time): phantom.get_raw_data(): called for playbook run '39792' and container id: '9420' Wed May 13 2020 11:08:38 GMT-0600 (Mountain Daylight Time): {} Wed May 13 2020 11:08:39 GMT-0600 (Mountain Daylight Time): successfully updated container(id: 9420) Wed May 13 2020 11:08:39 GMT-0600 (Mountain Daylight Time): phantom.get_raw_data(): called for playbook run '39792' and container id: '9420' Wed May 13 2020 11:08:39 GMT-0600 (Mountain Daylight Time): {"this": "is a test"}
get_summary
Use the get_summary API to retrieve the summary of the playbook execution in a JSON format.
The get_summary API is not supported from within a custom function.
phantom.get_summary()
This sample uses the phantom.get_summary() API.
import phantom.rules as phantom import json def on_start(container): phantom.act('geolocate ip', parameters=[{ "ip" : "1.1.1.1" }]) return def on_finish(container, summary): summary_json = phantom.get_summary() phantom.debug(summary_json) return
This sample shows the return value of this API, which is a list of JSON representation of the playbook execution.
{ "status": "success", "message": "", "result": [ { "status": "success", "close_time": "2016-02-11T06:45:22.005343+00:00", "app_runs": [ { "asset_id": 40, "status": "success", "app": "MaxMind", "app_id": 27, "app_run_id": 224, "asset": "maxmind", "action": "geolocate ip", "summary": "Country: Australia", "parameter": "{\"ip\": \"1.1.1.1\"}", "action_run_id": 104 } ], "create_time": "2016-02-11T06:45:20.917+00:00", "action": "geolocate ip", "message": "1 action succeeded", "type": "investigate", "id": 104 } ], "playbook_run_id": 167 }
parse_errors, print_errors, parse_success, parse_results
Use these APIs to pass in the action_results directly from callback into these helper routines to access the data. See collect before using this API, as these convenience APIs have limited use cases.
The parse_errors and parse_success APIs are supported from within a custom function.
phantom.parse_errors(action_results) phantom.print_errors(action_results) phantom.parse_success(action_results) phantom.parse_results(action_results)
API | Description |
---|---|
parse_errors() | This API collects errors and returns the errors per asset and per parameter. |
print_errors() | This API dumps any errors found in the action_results parameter.
|
parse_success() | This API processes the action_results parameter and removes any records that had errors.
|
parse_results() | This API processes the action_results parameter and transforms the contents to be organized by success and failed categories.
|
set_parent_handle
Use the set_parent_handle API to set the handle from the synchronously called child playbook that is then accessed in the parent playbook through the handle parameter of the callback function. This API works only when the parent calls the child playbook in synchronous mode. See playbook for more information on calling playbooks in synchronous mode.
The last call to the set_parent_handle API overwrites the handle sent to the callback function. In a parent playbook, if there is a join block where two child playbooks called synchronously are joining to a callback, the value of handle in the callback depends on which child playbook called the set_parent_handle API last.
The set_parent_handle API is not supported from within a custom function.
phantom.set_parent_handle()
The following sample uses the phantom.set_parent_handle() child playbook.
some_handle="some_handle from child pb" phantom.set_parent_handle(some_handle)
The following sample uses the phantom.set_parent_handle() parent playbook.
def playbook_callback(..., handle=None, ...): phantom.debug("handle sent by child playbook: {}".format(handle)) return
Data management automation API | Session automation API |
This documentation applies to the following versions of Splunk® SOAR (On-premises): 6.0.0, 6.0.1, 6.0.2, 6.1.0, 6.1.1, 6.2.0, 6.2.1, 6.2.2, 6.3.0
Feedback submitted, thanks!