Splunk® Phantom (Legacy)

Python Playbook API Reference for Splunk Phantom

This documentation does not apply to the most recent version of Splunk® Phantom (Legacy). For documentation on the most recent version, go to the latest release.

Data management automation API

Splunk Phantom's 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 response to a security breach. The following APIs are supported to leverage the capabilities of the platform using Playbooks.

get_list

phantom.get_list(list_name=None, values=None, column_index=-1, trace=False)

'Custom Lists' are lists of dictionaries to allow users to manage data that can be referenced in Phantom Playbooks. These lists are available and accessible to the user to maintain in UI Playbooks / Custom Lists.

This API allows programmatic access to these 'Custom Lists' that the users may have defined and setup. For example, users may want to define a set of user names as 'executives' or a set of IP addresses as 'test machines'. In the context of containers (events) and artifacts, if the user is a member of the 'executives' list, then the course of action may be different or the severity may have to be altered using the 'set_severity' API explained elsewhere in the docs. Similarly if the IP address on which an event has been detected is a 'test machine' there may not be any reason to act. The result of this call is the full list as defined by the user.

Parameter Required? Type Description
list_name Required str The name of the custom list to retrieve.
values Optional str A value or a list of values to search, if not included the full list will be retrieved.
column_index Optional int Used to specify a specific column to retrieve.
trace Optional bool When set to True, more detailed output will be displayed in debug output.

Here is an example of how to use the API:

import phantom.rules as phantom
import json

def on_start(container):
    #in the product in 'Playbooks / Custom Lists', define a
    # list called 'executives' and then access it here
    success, message, execs = phantom.get_list(list_name='executives')

    phantom.debug(
        'phantom.get_list results: success: {}, message: {}, execs: {}'\
        .format(success, message, execs)
    )

    return

def on_finish(container, summary):
    return

add_list

phantom.add_list(list_name=None, values=None)

Append a new row of data to the "Custom List" named by "list_name". If the list does not exist, it will be created. Values will be converted to a list of strings. On completion it returns a tuple of a success flag (bool) and any response message (str).

Parameter Required? Type Description
list_name Required str The name of the custom list to add an item to.
values Required str The values to be added, either a single value (str), or multiple (list of str).

Here is an example of how to use the API:

import phantom.rules as phantom
import json

def on_start(container):
    #in the product in 'Playbooks / Custom Lists', define a
    # list called 'executives' and then access it here
    success, message = phantom.add_list(
        list_name='executives', values=[ 'bob.jones@splunk.com' ] )

    phantom.debug(
        'phantom.add_list results: success: {}, message: {}' \
        .format(success, message)
    )

    success, message = phantom.add_list(
        list_name='executives', values=[ 'susan.smith@splunk.com' ] )

    phantom.debug(
        'phantom.add_list results: success: {}, message: {}' \
        .format(success, message)
    )

    return

def on_finish(container, summary):
    return

The above will add 2 rows to a 1-column list. First it adds Bob then it adds Susan.

remove_list

phantom.remove_list(list_name=None, empty_list=False, trace=False)

Delete a list. The list will no longer exist and not be available from the UI. When using the empty_list option, the list will still exist, but will be cleared of all values.

Parameter Required? Type Description
list_name Required str The name of the custom list to delete.
empty_list Optional bool Setting this to True will just clear out the list contents instead of completely removing the list.
trace Optional bool When set to True, more detailed output will be displayed in debug output.

For this API you will need to give the automation user permissions to delete lists.

Here is an example of how to use the API:

import phantom.rules as phantom
import json

def on_start(container):
    phantom.debug('phantom.remove_list start')

    success, message = phantom.remove_list(list_name='example')

    phantom.debug(
      'phantom.remove_list results: success: {}, message: {}'\
      .format(success, message)
    )

    return

def on_finish(container, summary):
    return

set_list

phantom.set_list(list_name=None, values=None)

This API provides the ability to replace the entire contents of a list. This API returns a tuple of a success flag (bool) and any response message (str).

Parameter Required? Type Description
list_name Required str The name of the custom list to modify.
values Required list of lists The values to set.

Here is an example of how to use the API:

import phantom.rules as phantom
import json

def on_start(container):
    #in the product in 'Playbooks / Custom Lists', define a
    # list called 'example' with two rows. Creates the list if it does not exist.
    success, message = phantom.set_list(
        list_name='example',
        values=[ ['a', 'list', 'of', 'values'], ['second', 'row'] ])
    phantom.debug(
      'phantom.set_list results: success: {}, message: {}'\
      .format(success, message)
    )
    return

def on_finish(container, summary):
    return

check_list

phantom.check_list(list_name=None, value=None, case_sensitive=False, substring=False)

This API allows users to check whether a value is in a custom list or does not appear in any column. The default behavior (case_sensitive=False) is case insensitive and to search complete strings (substring=False). It returns a tuple of a success flag (bool), any response message, and the number of matching rows in the custom list (int).

Parameter Required? Type Description
list_name Required string The name of the custom list to search through.
value Required string The value that should be searched.
case_sensitive Optional boolean Default behavior is case insensitive but can be changed with this option.
substring Optional boolean Default behavior is complete string match, but can be changed with this option.

Example:

import phantom.rules as phantom

def on_start(container):
    phantom.debug('phantom.check_list start')

    success, message, matched_row_count = \
        phantom.check_list(list_name='Example List', value='Example Value')

    phantom.debug(
      'phantom.check_list results: success: {}, message: {}, matched_row_count: {}'\
      .format(success, message, matched_row_count)
    )

    return

def on_finish(container, summary):
    return

delete_from_list

phantom.delete_from_list(list_name=None, value=None, column=None, remove_all=False, remove_row=False)

This API provides the ability to remove rows from a list that contain a specific value. This API returns a tuple of a success flag (bool) and any response message (str).

Parameter Required? Type Description
list_name Required str The name of the custom list to modify.
value Required str Will replace cells containing the value with None.
column Optional positive int Zero based index, only check for value in this column.
remove_all Optional boolean If True, replace all occurrences of value with None. Otherwise the API will fail if multiple are found.
remove_row Optional boolean If True, remove the full row where an occurrence of value was found.

Here is an example of how to use the API:

import phantom.rules as phantom
import json

def on_start(container):
    #in the product in 'Playbooks / Custom Lists', define a
    # list called 'example' with two rows. Creates the list if it does not exist.
    success, message = phantom.delete_from_list(
        list_name='example',
        value='deleteme')
    phantom.debug(
      'phantom.delete_from_list results: success: {}, message: {}'\
      .format(success, message)
    )
    return

def on_finish(container, summary):
    return

NOTE: It is not possible to delete all rows from the list, and phantom.delete_from_list commands that attempt to do so will result in an error. At least one row must be present in the list.


get_run_data

phantom.get_run_data(key=None)

This API returns the data value saved for the specified 'key' via the phantom.save_run_data() method. If 'key' is not specified, this API returns data for all the keys as a string object.

Sample result data if a key is not specified when calling get_run_data:

{
   "specified_key_on_save_run_data_call" : {
      "auto_" : true,
      "data_" : "specified value on save run data call with key provided"
   },
   "ef106ce1-301d-490d-9b96-d16b7e3a1a85" : {
      "auto_" : true,
      "data_" : "specified value on save run data call without key provided"
   }
}

save_run_data

phantom.save_run_data(value=None, key=None, auto=True)

This API saves the 'value' in a 'key' only in the context of the playbook run/execution. 'key' and 'value' are string objects. This data is automatically deleted when the playbook execution completes unless the 'auto' parameter is set to False.

get_object

phantom.get_object(key=None, clear_data=False, container_id=None, playbook_name=None, repo_name=None)

This API retrieves data that was saved via the save_object API.

NOTE: Please see the save_object() API for sample playbook and usage of this API.

Parameter Required? Description
key Required The key specified in the save_object() API used when saving data.
clear_data Optional If set True, clears the data after fetching. Defaults to False.
container_id Optional, unless playbook_name is not specified. Can also be specified with a playbook_name. The container id specified when the data was saved.
playbook_name Optional, unless container_id is not specified. Can also be specified with a container_id The playbook name as specified when the data was saved.
repo_name Optional The repo name as specified when saving the data in the save_object API call

The key parameter supports Postgres LIKE patterns. If pattern does not contain percent signs or underscores, then the pattern only represents the string itself; in that case LIKE acts like the equals operator. An underscore (_) in pattern stands for (matches) any single character; a percent sign (%) matches any sequence of zero or more characters.

The return value is a list of dictionaries where each dictionary has search criteria and the value for the specified combination of parameters.

Sample result data:

[
    {
        "composite_key": {
            "container_id": <>,
            "playbook_name": <>,
            "key": <>
        },
        "value": {<>
        }
    }
]

save_object

 phantom.save_object(key=None, value=None, container_id=None,
                    auto_delete=False, playbook_name=None,
                    repo_name=None)

This API allows you to save data by key and/or container_id and/or playbook name, to be retrieved when executing playbooks on containers. Users can save a key and value pair along with the context of container id and/or playbook name.

NOTE: Only JSON compliant objects, dictionaries, lists, strings and numbers are supported as objects that can be saved and retrieved.

Parameter Required? Description
key Required Specify to save and retrieve data by this unique key.
value Required The data to be saved. This is expected to be a Python dictionary object.
container_id Optional, unless a playbook_name is not specified. This is the container_id as a context to the data being saved. Must be provided if auto_delete is True.
auto_delete Optional Defaults to False. If set True, the data will be deleted when the container is closed. The clear_object can be used to delete the data. If set True, container_id must be provided.
playbook_name Optional, unless a container_id is not provided. The playbook name which is also saved as context to the data.
repo_name Optional It is recommended to specify the repo_name when a playbook name is provided, since a particular playbook may exist in more than one repo.

Sample playbook:

import phantom.rules as phantom
import json
from datetime import datetime, timedelta

def on_start(container):
    phantom.debug('on_start() called {}'.format(container))

    pb_info = phantom.get_playbook_info()
    phantom.debug(pb_info)
    if not pb_info:
        return

    playbook_name = pb_info[0].get('name', None)
    container_id = container['id']


    # SAVE data with key, container id and Playbook name
    phantom.save_object(key="key1", value={'value':'key 1 data for
        container and playbook'}, auto_delete=True, container_id = container_id,
        playbook_name=playbook_name)

    phantom.save_object(key="key2", value={'value':'key 2 data for
        container and playbook'}, auto_delete=True, container_id = container_id,
        playbook_name=playbook_name)

    # SAVE data with key, container id but NO Playbook name
    phantom.save_object(key="key1", value={'value':'key 1 data for
        only container and NO playbook'}, auto_delete=True,
        container_id = container_id)

    # SAVE data with key, Playbook name and NO container id
    phantom.save_object(key="key1", value={'value':'key 1 data for
        only playbook and not container'}, auto_delete=False,
        playbook_name=playbook_name)


    my_key = "key1"
    data = phantom.get_object(key=my_key,
            container_id = container_id, playbook_name=playbook_name)

    phantom.debug("get by key, container_id and playbook name:
        {} records found".format(len(data)))
    phantom.debug(data)

    data = phantom.get_object(key=my_key, container_id = container_id)

    phantom.debug("get by key, and container_id and
        NO playbook name: {} records found".format(len(data)))
    phantom.debug(data)

    data = phantom.get_object(key=my_key,
        playbook_name=playbook_name)

    phantom.debug("get by key, and playbook name and no container id:
        {} records found".format(len(data)))
    phantom.debug(data)

    data = phantom.get_object(key=my_key, playbook_name="%%")

    phantom.debug("get by key, and ALL playbook name and
        no container id: {} records found".format(len(data)))
    phantom.debug(data)

    data = phantom.get_object(key="%%",
        container_id = container_id)

    phantom.debug("get for ALL key, and container_id and
        no playbook name: {} records found".format(len(data)))
    phantom.debug(data)

    data = phantom.get_object(key="%%", container_id = container_id,
        playbook_name=playbook_name)

    phantom.debug("get for ALL key, and container_id and playbook name:
        {} records found".format(len(data)))
    phantom.debug(data)

    # TESTING CLEAR API

    data = phantom.get_object(key="key1", container_id = container_id,
        playbook_name=playbook_name)
    phantom.debug("BEFORE clear ... get for key1, and container_id and playbook
        name: {} records found".format(len(data)))
    phantom.debug(data)

    phantom.clear_object(key="key1", container_id = container_id,
        playbook_name=playbook_name)

    data = phantom.get_object(key="key1", container_id = container_id,
        playbook_name=playbook_name)

    phantom.debug("AFTER clear ... get for key1, and container_id and playbook
        name: {} records found".format(len(data)))
    phantom.debug(data)


    return

def on_finish(container, summary):
    phantom.debug('on_finish() called')
    return

The output of the above playbook in debugger shows the following results:

Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): Starting playbook 'local/automation_data' (id: 112, version: 35) on 'incident'(id: 10) with playbook run id: 72
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): calling on_start() on incident 'CryptoLocker Ransomware Infection (new, SLA breached) (192.168.1.41)'(id: 10).
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): on_start() called {'sensitivity': 'amber', 'create_time': '2017-03-23 03:54:12.981519+00', 'owner': 'bob.tailor@splunk.com', 'id': 10, 'close_time': '', 'severity': 'high', 'label': 'incident', 'due_time': '2017-03-18 21:34:47.217516+00', 'version': '1', 'current_rule_run_id': 72, 'status': 'new', 'owner_name': '', 'hash': 'f407a85b849baecdb34d27da1e1431dc', 'description': 'CryptoLocker has been detected on finance system 192.168.1.41 running on ESXi server 192.168.1.40', 'tags': [], 'start_time': '2014-09-04 14:40:33+00', 'asset_name': 'qradar_entr', 'artifact_update_time': '2017-03-23 03:54:15.990076+00', 'container_update_time': '', 'kill_chain': '', 'name': 'CryptoLocker Ransomware Infection (new, SLA breached) (192.168.1.41)', 'ingest_app_id': '', 'source_data_identifier': '45', 'end_time': '', 'artifact_count': 2}
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT):
[
    {
        "parent_playbook_run_id": "0",
        "name": "automation_data",
        "run_id": "72",
        "scope_artifacts": [],
        "scope": "new",
        "id": "112",
        "repo_name": "local"
    }
]
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): save_object() called:key=key1,auto_delete=True,container_id=10,playbook_name=automation_data,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): save_object() called:key=key2,auto_delete=True,container_id=10,playbook_name=automation_data,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): save_object() called:key=key1,auto_delete=True,container_id=10,playbook_name=None,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): save_object() called:key=key1,auto_delete=False,container_id=None,playbook_name=automation_data,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get_object() called:key=key1, clear_data=False,container_id=10,playbook_name=automation_data,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get by key, container_id and playbook name: 1 records found
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT):
[
    {
        "composite_key": {
            "container_id": 10,
            "playbook_name": "automation_data",
            "key": "key1"
        },
        "value": {
            "value": "key 1 data for container and playbook"
        }
    }
]
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get_object() called:key=key1, clear_data=False,container_id=10,playbook_name=None,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get by key, and container_id and NO playbook name: 1 records found
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT):
[
    {
        "composite_key": {
            "container_id": 10,
            "playbook_name": "",
            "key": "key1"
        },
        "value": {
            "value": "key 1 data for only container and NO playbook"
        }
    }
]
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get_object() called:key=key1, clear_data=False,container_id=None,playbook_name=automation_data,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get by key, and playbook name and no container id: 1 records found
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT):
[
    {
        "composite_key": {
            "container_id": 0,
            "playbook_name": "automation_data",
            "key": "key1"
        },
        "value": {
            "value": "key 1 data for only playbook and not container"
        }
    }
]
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get_object() called:key=key1, clear_data=False,container_id=None,playbook_name=%%,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get by key, and ALL playbook name and no container id: 1 records found
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT):
[
    {
        "composite_key": {
            "container_id": 0,
            "playbook_name": "automation_data",
            "key": "key1"
        },
        "value": {
            "value": "key 1 data for only playbook and not container"
        }
    }
]
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get_object() called:key=%%, clear_data=False,container_id=10,playbook_name=None,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get for ALL key, and container_id and no playbook name: 1 records found
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT):
[
    {
        "composite_key": {
            "container_id": 10,
            "playbook_name": "",
            "key": "key1"
        },
        "value": {
            "value": "key 1 data for only container and NO playbook"
        }
    }
]
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get_object() called:key=%%, clear_data=False,container_id=10,playbook_name=automation_data,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get for ALL key, and container_id and playbook name: 2 records found
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT):
[
    {
        "composite_key": {
            "container_id": 10,
            "playbook_name": "automation_data",
            "key": "key2"
        },
        "value": {
            "value": "key 2 data for container and playbook"
        }
    },
    {
        "composite_key": {
            "container_id": 10,
            "playbook_name": "automation_data",
            "key": "key1"
        },
        "value": {
            "value": "key 1 data for container and playbook"
        }
    }
]
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get_object() called:key=key1, clear_data=False,container_id=10,playbook_name=automation_data,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): BEFORE clear ... get for key1, and container_id and playbook name: 1 records found
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT):
[
    {
        "composite_key": {
            "container_id": 10,
            "playbook_name": "automation_data",
            "key": "key1"
        },
        "value": {
            "value": "key 1 data for container and playbook"
        }
    }
]
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): clear_object() called:key=key1,container_id=10,playbook_name=automation_data,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): get_object() called:key=key1, clear_data=False,container_id=10,playbook_name=automation_data,repo_name=None
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): AFTER clear ... get for key1, and container_id and playbook name: 0 records found
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT):
[]

Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): No actions were executed
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT):

Playbook 'automation_data' (playbook id: 112) executed (playbook run id: 72) on incident 'CryptoLocker Ransomware Infection (new, SLA breached) (192.168.1.41)'(container id: 10).
   Playbook execution status is 'success'
	Total actions executed: 0

Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): on_finish() called
Fri Mar 24 2017 07:13:08 GMT-0700 (PDT): {"message":"No actions were executed","playbook_run_id":72,"result":[],"status":"success"}

WARNING: If auto_delete is False or no container id is provided or container is NOT closed, the data will not be deleted and can waste space.

clear_object

phantom.clear_object(key=None, container_id=None, playbook_name=None, repo_name=None)

This is an API that allows you to delete data saved via the save_object() API.

Parameter Required? Description
key Required The key parameter that was used in save_object() API
container_id Optional, unless playbook_name is not provided. Can also be use together with a playbook_name. The same container_id parameter that was used in save_object() API.
playbook_name Optional, unless playbook_name is not provided. Can also be use together with a playbook_name. The same playbook_name parameter that was used in save_object() API.
repo_name Optional The same repo_name parameter that was used in save_object() API.

The container_id and playbook_name parameters support Postgres LIKE patterns. If pattern does not contain percent signs or underscores, then the pattern only represents the string itself; in that case LIKE acts like the equals operator. An underscore (_) in pattern stands for (matches) any single character; a percent sign (%) matches any sequence of zero or more characters.

Last modified on 21 January, 2021
Container automation API   Data access automation API

This documentation applies to the following versions of Splunk® Phantom (Legacy): 4.8


Was this topic useful?







You must be logged into splunk.com in order to post comments. Log in now.

Please try to keep this discussion focused on the content covered in this documentation topic. If you have a more general question about Splunk functionality or are experiencing a difficulty with Splunk, consider posting a question to Splunkbase Answers.

0 out of 1000 Characters