Python Playbook Tutorial for Splunk Phantom overview
Playbooks help security operations teams develop and deploy precise automation strategies. These strategies might range from generic information mining tasks to actively mitigating the impact of an ongoing incident.
Playbooks are Python scripts that execute various actions in response to an incident. As new data enters the system, enabled playbooks run on new containers in a specified order. Configure playbooks to act on containers with a specific label. For example, if the imported data has a label of incident
, the playbook is expected to run on an incident. All playbooks are independent of each other and can act on all containers. See Understanding containers in the Python Playbook API Reference for Splunk Phantom for more information on containers.
Playbooks have the following states:
Playbook state | Description |
---|---|
Active | Execute automatically when a new artifacts is added to an unresolved container. A user can also run any playbook manually. |
Safe Mode | Only execute read-only actions. For example, list vms is a read-only action, whereas block ip , which could result in changes to the state of the asset, isn't.
|
Active playbooks run in real-time as new containers are imported into the system or existing open containers are updated with new artifacts. Playbooks don't automatically run if a container is in the closed state. However, new artifacts can continue to be added to the container and users can still run actions or playbooks on them manually.
Playbook structure
Phantom playbooks are Python scripts built to run on top of the playbook API platform. Every playbook has two special functions called on_start()
and on_finish()
, which are called by the platform at the beginning and end of the playbook execution. Expand the following section to see a minimal playbook consisting of just one action:
Phantom playbook functions
import phantom.rules as phantom import json # This function gets called for all new containers or when new artifacts # are added to an existing container. def on_start(container): # container is a JSON object representing the object that this playbook # can automate on # use phantom.collect() API to get the artifacts that belong # to this container and call phantom.act(). ips = set(phantom.collect(container, 'artifact:*.cef.sourceAddress')) parameters = [] for ip in ips: parameters.append({ "ip" : ip }) if parameters: # In phantom.act(), use the optional parameter 'callback' to get # called when the action completes my_test_ips = [] my_test_ips.append('1.1.1.1') phantom.act('geolocate ip', parameters=parameters, assets=["maxmind"], handle=json.dumps(my_test_ips), callback=geolocate_ip_cb) return # this is a callback function for the action. # Evaluate the results and/or call other actions def geolocate_ip_cb(action, success, container, results, handle): # # See the documentation for 'callback' for detailed information on # these parameters # if not success: return return def on_finish(container, summary): # Summary is a user friendly representation of all action outcomes # call phantom.get_summary() to get a JSON representation of all # action results here return
Don't use globals in Phantom playbooks as their state isn't preserved in some cases. Instead, use handle
, a parameter to the phantom.act() API, to pass objects between an action and its callbacks. Alternatively, you can use the phantom.save_data and phantom.get_data APIs to save and retrieve objects.
Function | Description |
---|---|
on_start (container) |
Every time a container is ingested or updated, Phantom calls the on_start() function of all enabled playbooks. To get the artifacts of a container on which to act, a user can call the phantom.collect() API to extract the artifacts.Example container parameter from a callback { "sensitivity": "amber", "create_time": "2016-01-14 18:25:55.921199+00", "owner": "admin", "id": 7, "close_time": "", "severity": "medium", "label": "incident", "due_time": "2016-01-15 06:24:00+00", "version": "1", "current_rule_run_id": 1, "status": "open", "owner_name": "", "hash": "093d1d4d22cab1c5931bbfb1b16ce12c", "description": "this is my test incident", "tags": ["red-network"], "start_time": "2016-01-14 18:25:55.926468+00", "asset_name": "", "artifact_update_time": "2016-01-14 18:26:33.55643+00", "container_update_time": "2016-01-14 18:28:43.859814+00", "kill_chain": "", "name": "test", "ingest_app_id": "", "source_data_identifier": "48e4ab9c-2ec1-44a5-9d05-4e83bec05f87", "end_time": "", "artifact_count": 1 } |
on_finish (container, summary) |
The final method invoked after all actions run for a given container. The parameter summary presents the final outcome of the playbook execution in a human readable format. A user can call the phantom.get_summary() API to get a JSON representation of the summary of the playbook execution. |
Custom lists
Custom lists are data structures that store information that you can access through playbooks for real-time complex decision making. For example, a playbook might take different actions if an IP address is a critical server versus a test machine. To do so, it must check for the attacked IP address and its list membership.
Users can configure custom lists of test machine IP addresses, finance department endpoint IP addresses, and executives by first and last name or email address. Playbooks can then directly reference these custom lists.
Playbook versioning
Each time a user modifies and saves a playbook, its version is automatically incremented. Automation only uses the latest version of each playbook.
If a user edits a rule while a playbook is running, Phantom continues to execute the playbook in the state in which the execution started. Any changes to the later version of the playbook only apply to a new execution instance for a new incident, or an incident with new information.
Common API calls used by the Visual Playbook Editor |
This documentation applies to the following versions of Splunk® Phantom (Legacy): 4.9, 4.10, 4.10.1, 4.10.2, 4.10.3, 4.10.4, 4.10.6, 4.10.7
Feedback submitted, thanks!