def on_finish(email, summary): setupkey = 'setup_data' + str(email['current_rule_run_id']) collectkey = 'collect_data' + str(email['current_rule_run_id']) email_to, email_from, smtp_asset = phantom.get_data(setupkey, clear_data=True) container_url = phantom.get_base_url() + 'container/' + str(email['id']) # calling get_summary to find out if we actually had anything we acted on getsummary = phantom.get_summary() #phantom.debug('Get summary: {}'.format(getsummary)) # if len(getsummary['result']) > 0: # we have processed at least one item in on_start collected_results, collected_vault_items, container_owner = phantom.get_data(collectkey, clear_data=True) # finalize the vault item info and add to email for vaultid in collected_vault_items.keys(): vaultinfo = phantom.get_vault_item_info(vaultid) for app_run_id, datavalues in collected_results.iteritems(): #phantom.debug('iterate collected results: \napprunid: {}\n\ndatavals: {}'.format(app_run_id, datavalues)) if datavalues['detonate_summary']['target'] == vaultid: collected_results[app_run_id]['vault_info'] = vaultinfo if len(collected_results) < (len(getsummary['result'])-2): # subtracting actions that arent counted as detonations collected_results['message'] = "Unexpected: Collected Results: {} is less than actions run: {}".format(len(collected_results), (len(getsummary['result'])-2)) # send summary email email_subject = "Results: Ingest file detonatation" email_body = '\nPhantom Container ID: {} - Owner: {}\nURL: {}\nReturned results by app_run_id:\n{}'.format(email['id'], container_owner, container_url, pprint.pformat(collected_results, indent=4)) phantom.act('send email', parameters=[{ "from" : email_from, "to" : email_to, "subject" : email_subject, "body" : email_body }], assets=[smtp_asset], callback=send_email_cb) phantom.debug("Summary: " + pprint.pformat(summary, indent=4)) else: # no artifacts run on phantom.debug('No artifacts, sending abort email.') email_subject = "Results: No artifacts to run, aborting" email_body = '\nPhantom Container ID: {}\nURL: {} \nSummary:\n{}'.format(email['id'],container_url,summary) phantom.act('send email', parameters=[{ "from" : email_from, "to" : email_to, "subject" : email_subject, "body" : email_body }], assets=[smtp_asset], callback=send_email_cb) return
def on_finish(container, summary): phantom.debug('on_finish() called') # This function is called after all actions are completed. # summary of all the action and/or all detals of actions # can be collected here. # 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) qa_overall_result = phantom.get_data(key=keyfile, clear_data=False) qa_overall_result['message'] = qa_overall_result['message'] + '\n\n' + summary # # if qa_overall_result['qa_fail_count'] == 0: if expected_pass_count == qa_overall_result['qa_pass_count']: qa_overall_result['overall_result'] = 'Pass' # set final pass/fail result in on_finish phantom.debug( 'Overall Qa result: {} - Pass: {} - Fail: {} \nMessage: {}'.format(qa_overall_result['overall_result'], qa_overall_result['qa_pass_count'], qa_overall_result['qa_fail_count'], qa_overall_result['message'], )) phantom.save_data(qa_overall_result, key=keyfile) return
def Format_End_Marker(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('Format_End_Marker() called') playbook_info = phantom.get_playbook_info() guid = phantom.get_data(playbook_info[0]['id'], clear_data=False) phantom.debug(guid) template = "eventcreate /id 999 /D \"ended test for {0} guid=%s\" /T INFORMATION /L application" % guid # parameter list for template variable replacement parameters = [ "Run_Start_Marker:action_result.parameter.ip_hostname", ] phantom.format(container=container, template=template, parameters=parameters, name="Format_End_Marker") Run_End_Marker(container=container) return
def Format_Start_Marker(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('format_1() called') playbook_info = phantom.get_playbook_info() guid = phantom.get_data(playbook_info[0]['id'], clear_data=False) template = "eventcreate /id 999 /D \"started test on {0} guid=%s\" /T INFORMATION /L application" % guid # parameter list for template variable replacement parameters = ["artifact:*.cef.destinationAddress"] phantom.format(container=container, template=template, parameters=parameters, name="Format_Start_Marker") Run_Start_Marker(container=container) return
def pin_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): import random phantom.debug('pin_1() called') # collect data for 'pin_to_hud_6' call dest_ip_artifacts = filter( lambda x: x[0], phantom.collect2(container=container, datapath=['artifact:*.cef.destinationAddress'])) sorc_ip_artifacts = filter( lambda x: x[0], phantom.collect2(container=container, datapath=['artifact:*.cef.sourceAddress'])) styles = set(["white", "red", "purple"]) pin_name = pin_name_mangle("pin_1", container) pin_id = phantom.get_data(pin_name) if not pin_id: ret_val, message, pin_id = phantom.pin( container=container, message="Affected IPs", data=str(len(dest_ip_artifacts) + len(sorc_ip_artifacts)), pin_type="card_medium", pin_style="white") phantom.debug("new pin_1") else: style = random.sample(styles, 1)[0] phantom.debug(style) ret_val, message = phantom.update_pin( pin_id, message="Affected IPs", data=str(len(dest_ip_artifacts) + len(sorc_ip_artifacts)), pin_style=style) if ret_val: phantom.save_data(pin_id, pin_name) # set container properties for: update_data = {} phantom.update(container, update_data) return
def pin_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): import random phantom.debug('pin_2() called') # collect data for 'pin_to_hud_6' call dest_username = filter( lambda x: x[0], phantom.collect2(container=container, datapath=['artifact:*.cef.destinationUserName'])) sorc_username = filter( lambda x: x[0], phantom.collect2(container=container, datapath=['artifact:*.cef.sourceUserName'])) styles = set(["white", "red", "purple"]) pin_name = pin_name_mangle("pin_2", container) pin_id = phantom.get_data(pin_name) if not pin_id: ret_val, message, pin_id = phantom.pin( container=container, message="Affected Users", data=str(len(dest_username) + len(sorc_username)), pin_type="card_medium", pin_style="purple") phantom.debug("new pin_2") else: # Delete and remake this one, for the sake of demonstration ret_val, message = phantom.delete_pin(pin_id) ret_val, message, pin_id = phantom.pin( container=container, message="Affected Users", data=str(len(dest_username) + len(sorc_username)), pin_type="card_medium", pin_style=random.sample(styles, 1)[0]) if ret_val: phantom.save_data(pin_id, pin_name) # set container properties for: update_data = {} phantom.update(container, update_data) return
def _save_data(qa_pass_count=0, qa_fail_count=0, qa_overall_result="Fail", message="", init=False, offset=0): if init: if message == "": message = 'At on_start' qa_overall_result = {'qa_pass_count': 0, 'qa_fail_count': 0, 'overall_result': 'Fail', 'message': message} phantom.save_data(qa_overall_result, key=keyfile) else: with padlock: qa_overall_result = phantom.get_data(key=keyfile, clear_data=False) if len(message) > 0: message = "{}():{}> {}".format(inspect.stack()[1 + offset][3], inspect.stack()[1 + offset][2], message) phantom.debug(message) qa_overall_result['message'] += "\n" + message qa_overall_result['qa_pass_count'] += qa_pass_count qa_overall_result['qa_fail_count'] += qa_fail_count phantom.save_data(qa_overall_result, key=keyfile)
def pin_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): import random phantom.debug('pin_3() called') # collect data for 'pin_to_hud_6' call dest_domain = filter( lambda x: x[0], phantom.collect2(container=container, datapath=['artifact:*.cef.destinationDnsDomain'])) pin_name = pin_name_mangle("pin_3", container) try: most_rcnt_domain = dest_domain[0][0] except: pass else: pin_id = phantom.get_data(pin_name) if not pin_id: ret_val, message, pin_id = phantom.pin( container=container, message="Most Recent Domain", data=most_rcnt_domain, pin_type="card_medium", pin_style="red") phantom.debug("new pin_3") else: ret_val, message = phantom.update_pin(pin_id, message="Most Recent Domain", data=most_rcnt_domain, pin_type="card_medium", pin_style="red") if ret_val: phantom.save_data(pin_id, pin_name) # set container properties for: update_data = {} phantom.update(container, update_data) return
def detonate_file_cb(action, success, email, results, handle): collectkey = 'collect_data' + str(email['current_rule_run_id']) if not success: phantom.debug("Error running detonate action.\n{}".format(json.dumps(results))) return # grab just the results url from the threatgrid return data, perhaps send the entire results dict # later as an email attachment? #result_url = results[0]['action_results'][0]['summary']['results_url'] # get the app run ID, and use it as a key to the dictionary we build with results app_run_id = results[0]['app_run_id'] collected_results, collected_vault_items, container_owner = phantom.get_data(collectkey, clear_data=False) collected_results[app_run_id] = dict() collected_results[app_run_id]['asset'] = results[0]['asset'] collected_results[app_run_id]['message'] = results[0]['message'] collected_results[app_run_id]['summary'] = results[0]['summary'] collected_results[app_run_id]['detonate_summary'] = results[0]['action_results'][0]['summary'] phantom.save_data([collected_results, collected_vault_items, container_owner], key=collectkey) return
def quarantine_device_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): # collect data for 'quarantine_device_1' call container_data = phantom.get_data("rkitdata", clear_data=True) parameters = [] # build parameters list for 'quarantine_device_1' call for container_item in container_data: if container_item[0]: parameters.append({ 'ip_hostname': container_item[0], # context (artifact id) is added to associate results with the artifact 'context': { 'artifact_id': container_item[1] }, }) if parameters: phantom.act("quarantine device", parameters=parameters, assets=['carbonblack'], callback=get_system_info_1, name="quarantine_device_1") else: phantom.error( "'quarantine_device_1' will not be executed due to lack of parameters" ) return
def generic_cb(action_name, status, incident, results, handle): phantom.debug('Action '+action_name+ (' SUCCEEDED' if status else ' FAILED')) my_data = phantom.get_data(handle) return
def pin_4(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('pin_4() called') artifacts = phantom.collect(container=container, datapath='artifacts:*', scope='all') artifacts = sorted(artifacts, key=lambda x: x['update_time'], reverse=True) ioc_count = 0 most_recent_ioc = None ioc_types = set() for artifact in artifacts: for key, value in artifact['cef'].iteritems(): value = str(value) ret, ioc_type = is_ioc(value) if ret: if most_recent_ioc is None: most_recent_ioc = value ioc_count += 1 ioc_types.add(ioc_type) pin4_name = pin_name_mangle("pin_4", container) pin5_name = pin_name_mangle("pin_5", container) pin6_name = pin_name_mangle("pin_6", container) pin_id_ioc_cnt = phantom.get_data(pin4_name) pin_id_ioc_rct = phantom.get_data(pin5_name) pin_id_ioc_type = phantom.get_data(pin6_name) if not pin_id_ioc_cnt: ret_val, message, pin_id_ioc_cnt = phantom.pin(container=container, message="IOC Count", data=str(ioc_count), pin_type="card_medium", pin_style="white") else: ret_val, message = phantom.update_pin(pin_id_ioc_cnt, message="IOC Count", data=str(ioc_count), pin_type="card_medium", pin_style="red") if ret_val: phantom.save_data(pin_id_ioc_cnt, pin4_name) if ioc_count: if not pin_id_ioc_rct: ret_val, message, pin_id_ioc_rct = phantom.pin( container=container, message="Most Recent IOC", data=most_recent_ioc, pin_type="card_medium", pin_style="purple") else: ret_val, message = phantom.update_pin(pin_id_ioc_rct, message="Most Recent IOC", data=most_recent_ioc, pin_type="card_medium", pin_style="purple") if ret_val: phantom.save_data(pin_id_ioc_rct, pin5_name) if not pin_id_ioc_type: ret_val, message, pin_id_ioc_type = phantom.pin( container=container, message="IOC Types", data=", ".join(ioc_types)) else: ret_val, message = phantom.update_pin(pin_id_ioc_type, message="IOC Types", data=", ".join(ioc_types)) if ret_val: phantom.save_data(pin_id_ioc_type, pin6_name) return
def generic_cb(action_name, status, incident, results, handle): phantom.debug('Action ' + action_name + (' SUCCEEDED' if status else ' FAILED')) my_data = phantom.get_data(handle) return