Splunk® SOAR (Cloud)

Python Playbook Tutorial for Splunk SOAR (Cloud)

Acrobat logo Download manual as PDF


The Splunk SOAR Automation Broker documentation has moved. See Set Up and Manage the Splunk SOAR Automation Broker.
Acrobat logo Download topic as PDF

Tutorial: Chain a series of actions in

This topic demonstrates how to execute a series of actions to bind together many security operations tasks into a single playbook in . You execute a series of actions by incorporating new actions into the callback of another action.

You don't need to use callbacks to run multiple actions in parallel if those actions have no interdependency. Instead, invoke multiple act() commands sequentially. However, if one action depends on the results of another action, the second action must be called from within the first action's callback.

Prerequisites

Before completing this tutorial, review the following topics to learn about callbacks and extracting data from a container:

Parse results

The results of an action are passed to the callback as the fourth parameter. The results contain an array of results that you can access as a JSON structure. You can run a single action on multiple assets, in which case a result exists for each asset.

More than one parameter might have been provided to the action, meaning there is an additional array of results with one result for each parameter. In that case, the result structure can be three levels deep. If you intend to parse results in your own code, you must iterate through all assets and all parameters to access them.

For example, a simple action that calls disable user with a single user produces the following results:

import phantom.rules as phantom
import json

def disable_user_cb(action, success, container, results, handle):

    phantom.debug(results)
    
    if not success:
        return

    return


def on_start(incident):

    users = [{ "username" : "jason_malware" }]
    
    phantom.act('disable user', parameters=users, assets=["domainctrl1"], callback=disable_user_cb)

    return
[
{
    'status': 'success',
    'action_results': [
        {
            'status': 'success',
            'data': [ ],
            'message': 'Userstatechanged',
            'parameter': {
                'username': 'jason_malware'
            },
            'summary': { }
        }
    ],
    'asset': 'domainctrl1',
    'summary': {
        'total_objects': 1,
        'total_objects_successful': 1
    }
}
]

Calling this same Action on two users, with one invalid user name, produces an array of results:

import phantom.rules as phantom
import json

def disable_user_cb(action, success, container, results, handle):

    phantom.debug(results)
    
    if not success:
        return

    return


def on_start(incident):

    users = [{ "username" : "jason_malware" },
             { "username" : "fred_malware" }]
    
    phantom.act('disable user', parameters=users, assets=["domainctrl1"], callback=disable_user_cb)

    return
{
    'status': 'success',
    'action_results': [
        {
            'status': 'success',
            'data': [ ],
            'message': 'Userstatesameasrequired',
            'parameter': {
                'username': 'jason_malware'
            },
            'summary': { }
        },
        {
            'status': 'failed',
            'data': [ ],
            'message': 'SearchonADforUserDNfailed',
            'parameter': {
                'username': 'fred_malware'
            },
            'summary': { }
        }
    ],
    'asset': 'domainctrl1',
    'summary': {
        'total_objects': 2,
        'total_objects_successful': 1
    }
}

Chain actions

If any an Action on any one Asset with any single parameter succeeds, then the overall Action is considered to have succeeded. Individual portions of that Action may have, however, failed. If we want to now operate on the results of the disable user call, we can iterate through the result structure and look for successful results, calling enable user on each disabled user:

import phantom.rules as phantom
import json

def enable_user_cb(action, success, container, results, handle):

    if not success:
        return

    for result in results:
        for user in result['action_results']:
            if 'status' in user and user['status'] == 'success':
                phantom.debug(user['parameter']['username'] + ' re-enabled')
    
def disable_user_cb(action, success, container, results, handle):

    if not success:
        return

    for result in results:
        for user in result['action_results']:
            if 'status' in user and user['status'] == 'success':
                phantom.debug(user['parameter']['username'] + ' disabled')
                phantom.act('enable user', parameters=[{ "username" : user['parameter']['username'] }], assets=["domainctrl1"], callback=enable_user_cb)
        
    return


def on_start(incident):

    users = [{ "username" : "jason_malware" },
             { "username" : "fred_malware" }]
    
    phantom.act('disable user', parameters=users, assets=["domainctrl1"], callback=disable_user_cb)

    return
2015-03-21T00:29:59.131000:  Processing incident: '4' [2a76c74c-5713-11e4-8a26-9b99986c1e2a]
2015-03-21T00:29:59.137000:  act(): Action 'disable user' shall be executed on assets: domainctrl1
2015-03-21T00:29:59.137000:  act(): action details: [disable user] parameters: [[{"username": "jason_malware"}, {"username": "fred_malware"}]] assets: [domainctrl1] callback function: [disable_user_cb] and NO user specified for reviewing params
2015-03-21T00:29:59.167000:  act(): No action parameter review or asset approval requests generated.
2015-03-21T00:29:59.168000: Starting action 'disable user' on asset '6c9c1b21-c259-4382-88ce-957cf6bb7a8e'
2015-03-21T00:29:59.189000: running: The connector 'LDAP App' started successfully. Execution parameters sent.
2015-03-21T00:29:59.340000: running: Loaded action execution configuration
2015-03-21T00:29:59.367000: running: Ldap module initialized
2015-03-21T00:29:59.541000: running: Got Base DN =  'DC=corp,DC=contoso,DC=com'
2015-03-21T00:29:59.542000: running: Connecting to 10.10.0.42...
2015-03-21T00:29:59.628000: running: Got User Base DN CN=Jason Malware,CN=Users,DC=corp,DC=contoso,DC=com
2015-03-21T00:29:59.674000: running: Disabling user
2015-03-21T00:29:59.729000: running: Ldap module initialized
2015-03-21T00:29:59.883000: running: Got Base DN =  'DC=corp,DC=contoso,DC=com'
2015-03-21T00:29:59.884000: running: Connecting to 10.10.0.42...
2015-03-21T00:29:59.973000: success: 1 of 2 actions succeeded
2015-03-21T00:29:59.991000: Command 'disable user' success. 1 of 2 actions succeeded
2015-03-21T00:29:59.996000:  calling action callback function: disable_user_cb
2015-03-21T00:30:00.814000: jason_malware disabled
2015-03-21T00:30:00.823000:  act(): Action 'enable user' shall be executed on assets: domainctrl1
2015-03-21T00:30:00.824000:  act(): action details: [enable user] parameters: [[{"username": "jason_malware"}]] assets: [domainctrl1] callback function: [enable_user_cb] and NO user specified for reviewing params
2015-03-21T00:30:00.854000:  act(): No action parameter review or asset approval requests generated.
2015-03-21T00:30:00.855000: Starting action 'enable user' on asset '6c9c1b21-c259-4382-88ce-957cf6bb7a8e'
2015-03-21T00:30:00.871000: running: The connector 'LDAP App' started successfully. Execution parameters sent.
2015-03-21T00:30:01.014000: running: Loaded action execution configuration
2015-03-21T00:30:01.037000: running: Ldap module initialized
2015-03-21T00:30:01.222000: running: Got Base DN =  'DC=corp,DC=contoso,DC=com'
2015-03-21T00:30:01.224000: running: Connecting to 10.10.0.42...
2015-03-21T00:30:01.328000: running: Got User Base DN CN=Jason Malware,CN=Users,DC=corp,DC=contoso,DC=com
2015-03-21T00:30:01.396000: running: Enabling user
2015-03-21T00:30:01.441000: success: 1 of 1 action succeeded
2015-03-21T00:30:01.468000: Command 'enable user' success. 1 of 1 action succeeded
2015-03-21T00:30:01.473000:  calling action callback function: enable_user_cb
2015-03-21T00:30:02.383000: jason_malware re-enabled
 *** The Rule has completed. Result: success *** 
Last modified on 03 September, 2021
PREVIOUS
Tutorial: Specify parameters in
  NEXT
Develop, test, and deploy playbooks in

This documentation applies to the following versions of Splunk® SOAR (Cloud): current


Was this documentation topic helpful?


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