Splunk® Phantom (Legacy)

Build Playbooks with the Visual Editor

Add custom code to your Splunk Phantom Playbook with the legacy custom function block

Legacy custom function blocks are the custom functions that were introduced in Splunk Phantom version 4.2 and are supported for playbooks which use those blocks. A newer implementation was released in Splunk Phantom version 4.9 and should be used instead. For information on converting legacy custom functions to the current custom function implementation, see Convert legacy custom functions to new custom functions.

Add custom Python code to a Custom Function block. Custom functions enable you to expand the kinds of processing performed in a playbook, such as adding custom input parameters and output variables. To use a legacy custom function block, you must have Edit Code permissions, which can be configured in Administration > User Management > Roles and Permissions. For more information on the Edit Code permission, see Add a role to Splunk Phantom in the Administer Splunk Phantom manual.

Settings

Follow these steps to configure the settings for a Legacy Custom Function block:

  1. Click Settings.
  2. Select Info or Advanced.
Setting Description
Info Configure settings for this Legacy Custom Function block.
  • Custom Name: The name for this legacy custom function block. This name is visible in the playbook editor and also in Splunk Phantom wherever details about this action are visible. Functions, parameters, and output variables can all have custom names using the following characters:
    • A-Z
    • a-z
    • 0-9
    • Underscores
  • Description: The Description field shows up as a code comment above the block definition.
  • Notes: The Notes field contents appear when you hover over the Note icon in the action block.

Setting or changing a custom name changes that custom name in all data paths that use it, including generated and custom code.

Advanced setting Description
Join Settings You can configure Join settings when you have two blocks with callbacks both calling the same downstream block. Block types with callbacks are Action and Prompt. Configure Join settings from the downstream block. Click the required checkbox if the action in the upstream block must be completed before this downstream block is run.
Artifact Scope Select a value from the drop-down menu. The setting determines which artifacts are processed when the playbook block runs.
  • Default matches the scope of the playbook.
  • New Artifacts processes only the artifacts that were defined since the block was last run.
  • All Artifacts includes all artifacts when the playbook block runs.

Click the </> icon to open the Python Playbook Editor to add your custom code:

This screen image shows a custom block on the VPE. The main elements are Input and Output parameters, which are described in the sections immediately following this image.

Input parameters

Input parameters represent a data path. You can set a data path from any valid blocks upstream, artifact data, and container data.

To create or remove an input parameter, perform the following steps:

  1. Click the + icon to add an input parameter. The index of parameters starts at zero.
  2. Type a name to set the name for or rename the input parameter.
  3. Click the > icon to set the properties for the input parameter.

You can delete the input parameter by clicking the x icon.

Output variables

Output variables are usable as inputs in other downstream blocks, such as Action, API, Filter, Decision, Format, Prompt, or other Custom Function blocks. The name of an output variable becomes <block_name>__<variable_name> in the auto-generated section of the playbook code. Give your output variables clear and meaningful names in your custom code.

Follow these steps to create or remove an output variable:

  1. Click the + icon to add an output variable.
  2. Type a name to set the name for, or rename the output variable.
  3. Click the x icon to delete an output variable.

See the following example of a custom function:

def format_login(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None):
phantom.debug('format_login() called')
results_data_1 = phantom.collect2(container=container, datapath=['get_login_history:action_result.data.*.output'], action_results=results)
results_item_1_0 = [item[0] for item in results_data_1]
    
format_login__login_table = None
    
################################################################################
## Custom Code Start
################################################################################
    
# format the output into Jira's markup language for rendering a table
format_login__login_table = "|| output of '/usr/bin/last -a' ||\n"
last_lines = results_item_1_0[0].split('\n')
for line in last_lines:
    format_login__login_table += "| {} |\n".format(line)
        
phantom.debug("table of logins for jira:")
phantom.debug(format_login__login_table)
    
################################################################################
## Custom Code End
################################################################################
    
phantom.save_run_data(key='format_login:login_table', value=json.dumps(format_login__login_table))
enrich_ticket_1(container=container)
    
return    

Custom function example for processing multiple artifacts to build a parameter list

def DBSearch(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None):
    phantom.debug('SearchDB() called')
    name_value = container.get('name', None)
    container_data = phantom.collect2(container=container, datapath=['artifact:*.cef.message', 'artifact:*.cef.startTime', 'artifact:*.id'])
    container_item_0 = [item[0] for item in container_data]
    container_item_1 = [item[1] for item in container_data]

    ################################################################################
    ## Custom Code Start
    ################################################################################

    # Write your custom code here...
    customernamestr = name_value
    parameters = []

    # Loop over the container data structure (a list of lists, with each inner list of length three)
    for messagestr, start_time, artifact_id in container_data:
        startdatestr = start_time.split(' ')[0]
        starttimestr = start_time.split(' ')[1]

        # Build the SQL
        if 'groupName:' in messagestr:
            hostgroupstr = messagestr.split('/')[0].replace('groupName:', '')
            hoststr = messagestr.split('/')[1].split(':')[1]
            sqlstr = "select COUNT(*) as cnt from schedule where customer = '"+ customernamestr +"' and startdate <= '"+ startdatetimestr +"' and enddate >= '"+ startdatetimestr +"' and ("
            for group in hostgroupstr.split('/'):
                sqlstr = sqlstr + "kyoten like '%"+ group +"%' or reason like '%"+ group +"%' or "
            sqlstr = sqlstr + "kyoten like '%"+ hoststr +"%' or reason like '%"+ hoststr +"%')"
            
        else:
            hoststr = messagestr.split(':')[0]
            sqlstr = "select COUNT(*) as cnt from schedule where customer = '"+ customernamestr +"' and  (kyoten like '%"+ hoststr +"%' or reason like '%"+ hoststr +"%') and startdate <= '"+ startdatetimestr +"' and enddate >= '"+ startdatetimestr +"'"

        # Update the parameter list
        # There should be one parameter per item in the container_data variable
        # There should be one item in the container_data variable per artifact
        # Thus, there should be one parameter per artifact
        parameters.append({
            'query': sqlstr,
            'format_vars': "",
            'no_commit': False,
        })

    phantom.act("run query", parameters=parameters, assets=['mysql'], callback=filter_2, name="SearchDB")

    ################################################################################
    ## Custom Code End
    ################################################################################
    filter_2(container=container)

    return

Last modified on 20 May, 2021
Add custom code to your Splunk Phantom playbook with the custom function block   Determine your Splunk Phantom playbook flow

This documentation applies to the following versions of Splunk® Phantom (Legacy): 4.10.4, 4.10.6, 4.10.7


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