def template_params(self, paramsStr): """ Translate the template params if they exist from the context """ actualParams = {} if paramsStr: try: params = json.loads(paramsStr) except ValueError as e: return_error('Unable to parse templateParams: {}'.format( str(e))) # Build a simple key/value for p in params: if params[p].get('value'): actualParams[p] = params[p]['value'] elif params[p].get('key'): actualParams[p] = demisto.dt(demisto.context(), params[p]['key']) return actualParams else: return None
def configure_job(job_name: str, existing_job: Optional[Dict[str, Any]] = None) -> bool: """Configures the job in the XSOAR instance. """ instance_context = demisto.context() job_params = existing_job or {} for job in instance_context.get('ConfigurationSetup', {}).get('Jobs', []): if job.get('name') == job_name: job_params.update(job) break if not job_params: return False res = demisto.executeCommand('demisto-api-post', { 'uri': '/jobs', 'body': job_params }) if is_error(res): error_message = f'{SCRIPT_NAME} - {get_error(res)}' demisto.debug(error_message) return_error(error_message) return False return True
def main(): input_args = demisto.args() # If user did not provide a lower threshold then split is not needed. threshold = input_args.get('similarity_threshold') try: threshold = float(threshold) except ValueError as e: raise DemistoException( f'Could not use threshold: {threshold}. Error: {e}') root_context_path = 'EmailCampaign' above_threshold_context_path = f'{root_context_path}.{ABOVE_THE_THRESHOLD_ITEMS_CONTEXT_PATH}' below_threshold_context_path = f'{root_context_path}.{BELOW_THRESHOLD_ITEMS_CONTEXT_PATH}' context = demisto.get(demisto.context(), f'{above_threshold_context_path}') # If there are no incident to split if not context: return only_lower_values, only_higher_values = filter_by_threshold( context, threshold) result = [] result.append( save_to_context(only_lower_values, below_threshold_context_path, table_header='Low Similarity Incidents Result')) result.append( save_to_context(only_higher_values, above_threshold_context_path, True, table_header='High Similarity Incidents Result')) return_results(result)
def list_members_command(client: MsGraphClient, args: Dict) -> Tuple[str, Dict, Dict]: """List a group members by group id. return outputs in Demisto's format. Args: client: Client object with request args: Usually demisto.args() Returns: Outputs. """ group_id = str(args.get('group_id')) next_link = args.get('next_link') top = args.get('top') filter_ = args.get('filter') members = client.list_members(group_id, next_link, top, filter_) if not members['value']: human_readable = f'The group {group_id} has no members.' return human_readable, NO_OUTPUTS, NO_OUTPUTS members_readable, members_outputs = parse_outputs(members['value']) # get the group data from the context group_data = demisto.dt( demisto.context(), f'{INTEGRATION_CONTEXT_NAME}(val.ID === "{group_id}")') if not group_data: return_error( 'Could not find group data in the context, please run "!msgraph-groups-get-group" to retrieve group data.' ) if isinstance(group_data, list): group_data = group_data[0] if '@odata.nextLink' in members: next_link_response = members['@odata.nextLink'] group_data[ 'Members'] = members_outputs # add a field with the members to the group group_data['MembersNextLink'] = next_link_response entry_context = { f'{INTEGRATION_CONTEXT_NAME}(val.ID === obj.ID)': group_data } title = f'Group {group_id} members ' \ f'(Note that there are more results. Please use the next_link argument to see them. The value can be ' \ f'found in the context under {INTEGRATION_CONTEXT_NAME}.MembersNextLink): ' else: group_data[ 'Members'] = members_outputs # add a field with the members to the group entry_context = { f'{INTEGRATION_CONTEXT_NAME}(val.ID === obj.ID)': group_data } title = f'Group {group_id} members:' human_readable = tableToMarkdown( name=title, t=members_readable, headers=['ID', 'Display Name', 'Job Title', 'Mail'], removeNull=True) return human_readable, entry_context, members
def delete_ticket_command(client, args) -> Tuple[str, dict, dict]: """Function which deleted a specific ticket by ticket id. Args: client : Integretion client which communicates with the api. args: Users arguments of the command. Returns: human readable, context, raw response of this command. """ ticket_id = args.get('ticket_id') try: response = client.delete_ticket_request(ticket_id) except Exception as e: raise DemistoException(e) if response.get('Result') == 'Success': context = {} old_context = demisto.dt(demisto.context(), f'QuestKace.Ticket(val.ID === {ticket_id})') if old_context: if isinstance(old_context, list): old_context = old_context[0] old_context['IsDeleted'] = True context = {'QuestKace.Ticket(val.ID === obj.ID)': old_context} return f'Ticket was deleted successfully. Ticket number {ticket_id}', context, {} else: raise DemistoException('Error while deleting the ticket.')
def configure_job(job_name: str, existing_job: Optional[Dict[str, Any]] = None) -> bool: """Configures the job in the XSOAR instance. """ instance_context = demisto.context() job_params = existing_job or {} is_scheduled = job_params.get('scheduled') for job in instance_context.get('ConfigurationSetup', {}).get('Jobs', []): if job.get('name') == job_name: job_params.update(job) break if not job_params: return False if is_scheduled is False: job_params['scheduled'] = False status, res = execute_command( 'demisto-api-post', { 'uri': '/jobs', 'body': job_params }, fail_on_error=False, ) if not status: error_message = f'{SCRIPT_NAME} - {res}' demisto.debug(error_message) return False return True
def delete_group_command(client: MsGraphClient, args: Dict) -> Tuple[str, Dict, Dict]: """Delete a group by group id and return outputs in Demisto's format Args: client: Client object with request args: Usually demisto.args() Returns: Outputs. """ group_id = str(args.get('group_id')) client.delete_group(group_id) # get the group data from the context group_data = demisto.dt( demisto.context(), f'{INTEGRATION_CONTEXT_NAME}(val.ID === "{group_id}")') if isinstance(group_data, list): group_data = group_data[0] # add a field that indicates that the group was deleted group_data['Deleted'] = True # add a field with the members to the group entry_context = { f'{INTEGRATION_CONTEXT_NAME}(val.ID === obj.ID)': group_data } human_readable = f'Group: "{group_id}" was deleted successfully.' return human_readable, entry_context, NO_OUTPUTS
def policy_delete_command(client: AzureWAFClient, **args: Dict[str, str]): """ Gets a policy name and resource group (or taking instance's default) and delete the policy from the resource group. """ policy_name = str(args.get('policy_name', '')) resource_group_name = str( args.get('resource_group_name', client.resource_group_name)) # policy_path is unique and used as unique id in the product. policy_id = f'/{SUBSCRIPTION_PATH.format(client.subscription_id)}/' \ f'{RESOURCE_PATH.format(resource_group_name)}/{POLICY_PATH}/{policy_name}' status = client.delete_policy(policy_name, resource_group_name) md = "" context = None if status.status_code in [200, 202]: old_context = demisto.dt(demisto.context(), f'AzureWAF.Policy(val.id === "{policy_id}")') # updating the context with deleted policy. if old_context: if isinstance(old_context, list): old_context = old_context[0] old_context['IsDeleted'] = True context = {'AzureWAF.Policy(val.id === obj.id)': old_context} md = f"Policy {policy_name} was deleted successfully." if status.status_code == 204: md = f"Policy {policy_name} was not found." return CommandResults(outputs=context, readable_output=md)
def generate_netcraft_context_with_notes(list_of_notes_contexts): all_takedowns_entry_context = demisto.context().get("Netcraft", {}).get( "Takedown", {}) for note_context in list_of_notes_contexts: all_takedowns_entry_context = add_note_to_suitable_takedown_in_context( note_context, all_takedowns_entry_context) return all_takedowns_entry_context
def viper_upload_command(): """ Command to upload a file to Viper database """ # Get entry id, filename and filepath file_entry = demisto.args().get('EntryID') filename = demisto.getFilePath(file_entry)['name'] filepath = demisto.getFilePath(file_entry)['path'] # Send file to Viper response = viper_upload(filepath, filename, file_entry.lower()) # Update tags if necessary if response == 'add tags': curr_hash = demisto.context().get('File')[2]['SHA256'] url_fragment = "project/default/malware/{}/tag/".format(curr_hash) curr_tags = [ result['data']['tag'] for result in http_request( 'GET', url_fragment, None, None, None)['results'] ] if file_entry not in curr_tags: demisto.results("File already in Viper. Updating tags...") data = {'tag': file_entry} add_tags = http_post(url_fragment, None, data=data) else: demisto.results( "File already in Viper. Viper entry is up to date.")
def file_upload_raw(body, file_entry_id, filename_to_upload): uri = 'php/fileupload.php' if not filename_to_upload: # first priority for the file name is user's argument # second priority for the file name is the file name in the context filename_dq = demisto.dt( demisto.context(), 'File(val=val.EntryID=="' + file_entry_id + '")=val.Name') if filename_dq and filename_dq[0]: filename_to_upload = filename_dq else: # last priority for the file name is demisto's entryID filename_to_upload = file_entry_id with open(demisto.getFilePath(file_entry_id)['path'], 'rb') as file_to_upload: file_up = {'amas_filename': file_to_upload} result = http_request( uri, 'post', API_HEADERS, body, '', files=file_up, ) if not result['success']: return_error('Failed to upload sample due to: ' + result['errorMessage']) return result
def domain_delete_command(client: Client, args: dict) -> CommandResults: """ :param client: Cisco Umbrella Client for the api request. :param args: args from the user for the command. :returns (str) confirmation or error regarding deleting a domain. """ response = {} domain_name = args.get('name', '') domain_id = args.get('id', '') if not domain_name and not domain_id: raise DemistoException( 'Both domain name and domain id do not exist, Please supply one of them in order to set the domain to ' 'delete command') try: response = client.delete_domains(domain_id=domain_id, domain_name=domain_name) except Exception as e: # When deleting a domain by id and the id does not exist. if any(exp in str(e) for exp in ["Domain not in domain list", "Not Found"]): return CommandResults( readable_output= 'The domain was not found in the list, Please insert an existing domain name or id.' ) if domain_name: curr_context = demisto.dt( demisto.context(), f'UmbrellaEnforcement.Domains(val.name == "{domain_name}")') else: curr_context = demisto.dt( demisto.context(), f'UmbrellaEnforcement.Domains(val.id == "{domain_id}")') if curr_context: if isinstance(curr_context, list): curr_context = curr_context[0] curr_context['IsDeleted'] = True if response and int(response.status_code) == 204: # type: ignore message = f"{domain_name if domain_name else domain_id} domain was removed from blacklist" else: # When deleting a domain by name, if name does not exist the returned code is 200 but the response is empty. message = f"{domain_name if domain_name else domain_id} domain not in the blacklist or Error" return CommandResults(readable_output=message, outputs_prefix='UmbrellaEnforcement.Domains', outputs_key_field='id', outputs=curr_context)
def build_grid(context_path: str, keys: List[str], columns: List[str], unpack_nested_elements: bool) -> pd.DataFrame: """ Build new DateFrame from current context retrieved by DT. There are 3 cases: 1. DT returns dict - In this case we will insert it in the table as key, value in each row. 2. DT returns list - In this case each entry in the list will represent a row. 3. DT return unknown obj (str..) - return empty list. Args: context_path: DT context path. keys: Keys to be included columns: Grid columns name. unpack_nested_elements: True for unpacking nested elements, False otherwise. Returns: pd.DataFrame: New Table include data from Entry Context """ # Retrieve entry context data entry_context_data = demisto.dt(demisto.context(), context_path) # Validate entry context structure data_type = validate_entry_context(context_path, entry_context_data, keys, unpack_nested_elements) demisto.debug('context object is valid. starting to build the grid.') # Building new Grid if unpack_nested_elements: # Handle entry context as dict, with unpacking of nested elements table = pd.DataFrame( unpack_all_data_from_dict(entry_context_data, keys, columns)) table.rename(columns=dict(zip(table.columns, columns)), inplace=True) elif data_type == 'list': # Handle entry context as list of value table = pd.DataFrame(entry_context_data) table.rename(columns=dict(zip(table.columns, columns)), inplace=True) elif isinstance(entry_context_data, list): # Handle entry context as list of dicts entry_context_data = [ filter_dict(item, keys, len(columns)) for item in entry_context_data ] table = pd.DataFrame(entry_context_data) table.rename(columns=dict(zip(table.columns, columns)), inplace=True) elif isinstance(entry_context_data, dict): # Handle entry context key-value of primitive types option # If the keys arg is * it means we don't know which keys we have in the context - Will create key-value table. if keys == ['*']: entry_context_data = filter_dict(entry_context_data, keys).items() table = pd.DataFrame(entry_context_data, columns=columns[:2]) else: entry_context_data = filter_dict(entry_context_data, keys) table = pd.DataFrame([entry_context_data]) table.rename(columns=dict(zip(table.columns, columns)), inplace=True) else: table = [] return table
def get_campaign_incident_similarities() -> list: """ Gets all the campaign incident similarities. Returns: List of all the similarities. """ incidents = demisto.get(demisto.context(), "EmailCampaign.incidents") return [incident["similarity"] for incident in incidents]
def get_incident_ids() -> list: """ Gets all the campaign incident ids. Returns: List of all the ids. """ incidents = demisto.get(demisto.context(), "EmailCampaign.incidents") return [incident["id"] for incident in incidents]
def install_custom_pack(pack_id: str, skip_verify: bool, skip_validation: bool) -> Tuple[bool, str]: """Installs a custom pack in the machine. Args: pack_id (str): The ID of the pack to install. skip_verify (bool): If true will skip pack signature validation. skip_validation (bool) if true will skip all pack validations. Returns: - bool. Whether the installation of the pack was successful or not. - str. In case of failure, the error message. Notes: Assumptions: The zipped file is in the war-room, and the context includes the data related to it. """ pack_file_entry_id = '' instance_context = demisto.context() context_files = instance_context.get('File', []) if not isinstance(context_files, list): context_files = [context_files] for file_in_context in context_files: if file_in_context['Name'] == f'{pack_id}.zip': pack_file_entry_id = file_in_context['EntryID'] break uri = build_url_parameters(skip_verify=skip_verify, skip_validation=skip_validation) if pack_file_entry_id: status, res = execute_command( 'demisto-api-multipart', { 'uri': uri, 'entryID': pack_file_entry_id }, fail_on_error=False, ) if not status: error_message = f'{SCRIPT_NAME} - {res}' demisto.debug(error_message) return False, f'Issue occurred while installing the pack on the machine.\n{res}' else: error_message = 'Could not find file entry ID.' demisto.debug(f'{SCRIPT_NAME}, "{pack_id}" - {error_message}.') return False, error_message return True, ''
def get_incidents_ids_from_context() -> list: """ Gets the campaign incident ids. Returns: List of incident ids. """ relevant_incidents = demisto.get(demisto.context(), 'EmailCampaign.incidents') ids = [item.get('id') for item in relevant_incidents] if not ids: ids = [] return ids
def main(): try: incidents = get_campaign_incidents_from_context() fields_to_display = demisto.get(demisto.context(), 'EmailCampaign.fieldsToDisplay') if incidents: update_incident_with_required_keys(incidents, KEYS_FETCHED_BY_QUERY) update_empty_fields() readable_output = get_incidents_info_md(incidents, fields_to_display) else: readable_output = NO_CAMPAIGN_INCIDENTS_MSG return_results(CommandResults(readable_output=readable_output)) except Exception as err: return_error(str(err))
def get_file_details(self): cmd_res = demisto.executeCommand('getFilePath', {'id': demisto.args().get("entryID")}) file_res = cmd_res[0] if isError(file_res): file_res["Contents"] = "Error fetching entryID: " + file_res["Contents"] self.res = file_res else: # Got file path: self.file_path = file_res.get('Contents').get('path') self.file_name = file_res.get('Contents').get('name') file = demisto.dt(demisto.context(), "File(val.EntryID === '{}')".format(demisto.args().get('entryID'))) if isinstance(file, list): file = file[0] self.file_type = file.get("Type")
def get_packs_data_from_context() -> List[Dict[str, str]]: """Fetched packs' data from context and formats it to an installable object. Returns: List[Dict[str, str]]: Installable objects list. """ instance_context = demisto.context() context_packs_data = instance_context.get('ConfigurationSetup', {}).get('MarketplacePacks') return [{ 'id': pack['packid'], 'version': pack['packversion'], } for pack in context_packs_data]
def main(args): incident = demisto.incident() custom_fields = incident.get('CustomFields', {}) email_from = custom_fields.get('emailfrom') email_cc = custom_fields.get('emailcc') email_to = custom_fields.get('emailto') email_subject = custom_fields.get('emailsubject') email_html = custom_fields.get('emailhtml', '') email_html_image = custom_fields.get('emailhtmlimage') attachments = incident.get('attachment', {}) files = demisto.context().get('File', []) if not email_html_image or 'src="cid' in email_html_image: if 'src="cid' in email_html: entry_id_list = get_entry_id_list(attachments, files) html_body = create_email_html(email_html, entry_id_list) email_reply = set_email_reply(email_from, email_to, email_cc, email_subject, html_body, attachments) demisto.executeCommand( "setIncident", {'customFields': { "emailhtmlimage": email_reply }}) return_results({ 'ContentsFormat': formats['html'], 'Type': entryTypes['note'], 'Contents': email_reply, }) else: email_reply = set_email_reply(email_from, email_to, email_cc, email_subject, email_html, attachments) return_results({ 'ContentsFormat': formats['html'], 'Type': entryTypes['note'], 'Contents': email_reply }) else: return_results({ 'ContentsFormat': formats['html'], 'Type': entryTypes['note'], 'Contents': email_html_image })
def install_custom_pack(pack_id: str) -> bool: """Installs a custom pack in the machine. Args: pack_id (str): The ID of the pack to install. Returns: bool. Whether the installation of the pack was successful or not. Notes: Assumptions: The zipped file is in the war-room, and the context includes the data related to it. """ pack_file_entry_id = '' instance_context = demisto.context() context_files = instance_context.get('File', []) if not isinstance(context_files, list): context_files = [context_files] for file_in_context in context_files: if file_in_context['Name'] == f'{pack_id}.zip': pack_file_entry_id = file_in_context['EntryID'] break if pack_file_entry_id: res = demisto.executeCommand( 'demisto-api-multipart', { 'uri': '/contentpacks/installed/upload', 'entryID': pack_file_entry_id }, ) if is_error(res): error_message = f'{SCRIPT_NAME} - {get_error(res)}' demisto.debug(error_message) return False else: demisto.debug( f'{SCRIPT_NAME} - An error occurred while installing {pack_id}.') return False return True
def main(): try: args = demisto.args() # the entry_id argument can be a list of entry ids or a single entry id entry_ids = args.get('entry_id', demisto.get(demisto.context(), 'lastCompletedTaskEntries')) entry_ids = argToList(entry_ids) entries = [demisto.executeCommand('getEntry', {'id': entry_id}) for entry_id in entry_ids] error_messages = get_errors(entries) return_results(CommandResults( readable_output='\n'.join(error_messages), outputs_prefix='ErrorEntries', outputs=error_messages, raw_response=error_messages, )) except Exception as e: return_error(f'Failed to fetch errors for the given entry id(s). Problem: {str(e)}')
def template_params(): """ Translate the template params if they exist from the context """ actualParams = {} paramsStr = demisto.getArg('templateParams') if paramsStr: try: params = json.loads(paramsStr) except ValueError as e: return_error_mail_sender('Unable to parse templateParams: %s' % (str(e))) # Build a simple key/value for p in params: if params[p].get('value'): actualParams[p] = params[p]['value'] elif params[p].get('key'): actualParams[p] = demisto.dt(demisto.context(), params[p]['key']) return actualParams
def main(): fields_mapping = {} for xdr_field in XDR_INCIDENT_FIELDS: if xdr_field in demisto.args() and demisto.args().get( xdr_field) is not None: custom_field_in_demisto = demisto.args().get(xdr_field) fields_mapping[xdr_field] = custom_field_in_demisto playbook_to_run = demisto.args().get('playbook_to_run') incident_id = demisto.args().get('incident_id') first_run = demisto.args().get('first') == 'true' interval = int(demisto.args().get('interval')) xdr_incident_from_previous_run = demisto.args().get( 'xdr_incident_from_previous_run') xdr_alerts_field = demisto.args().get('xdr_alerts') xdr_file_artifacts_field = demisto.args().get('xdr_file_artifacts') xdr_network_artifacts_field = demisto.args().get('xdr_network_artifacts') verbose = demisto.args().get('verbose') == 'true' xdr_incident_markdown_field = demisto.args().get( 'xdr_incident_markdown_field') # deprecated if xdr_incident_markdown_field: # deprecated field raise ValueError( 'Deprecated xdr_incident_markdown_field argument, instead use xdr_alerts, xdr_file_artifacts, ' 'xdr_network_artifacts. For more information follow Demisto documentation.' ) previous_scheduled_task_id = demisto.get(demisto.context(), 'XDRSyncScriptTaskID') if first_run and previous_scheduled_task_id: if verbose: demisto.debug( 'Stopping previous scheduled task with ID: {}'.format( previous_scheduled_task_id)) demisto.executeCommand('StopScheduledTask', {'taskID': previous_scheduled_task_id}) demisto.setContext('XDRSyncScriptTaskID', '') xdr_incident_sync(incident_id, fields_mapping, playbook_to_run, xdr_incident_from_previous_run, first_run, interval, xdr_alerts_field, xdr_file_artifacts_field, xdr_network_artifacts_field, verbose)
def _handle_existing_outputs(anchor_hash: str, output_key: str, new_hashes_outputs: list): context = demisto.get(demisto.context(), f'{output_key}') if not context: context = [] elif not isinstance(context, list): context = [context] context = list(filter(lambda item: item.get('SourceHash') == anchor_hash, context)) if context: context = context[0].get('compared_hashes') new_hashes = [current_hash.get('hash') for current_hash in new_hashes_outputs] res = [] for item in context: if item.get('hash') not in new_hashes: res.append(item) res += new_hashes_outputs return res
def upload_file_command(): ticket_type = get_table_name(demisto.args().get('ticket_type')) ticket_id = demisto.args()['id'] file_id = demisto.args()['file_id'] file_name = demisto.args().get('file_name', demisto.dt(demisto.context(), "File(val.EntryID=='" + file_id + "').Name")) file_name = file_name[0] if isinstance(file_name, list) else file_name res = upload_file(ticket_id, file_id, file_name, ticket_type) if not res or 'result' not in res or not res['result']: return_error('Unable to retrieve response') hr = { 'Filename': res['result'].get('file_name'), 'Download link': res['result'].get('download_link'), 'System ID': res['result'].get('sys_id') } context = { 'ID': ticket_id, 'File': {} } context['File']['Filename'] = res['result'].get('file_name') context['File']['Link'] = res['result'].get('download_link') context['File']['SystemID'] = res['result'].get('sys_id') entry = { 'Type': entryTypes['note'], 'Contents': res, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('File uploaded successfully', hr), 'EntryContext': { 'ServiceNow.Ticket(val.ID===obj.ID)': context, 'Ticket(val.ID===obj.ID)': context } } return entry
def build_grid(context_path: str, keys: List[str], columns: List[str]) -> pd.DataFrame: """ Build new DateFrame from current context retrieved by DT. There is 3 cases: 1. DT returns dict (list including 1 item only)- In this case we will insert it in the table as key, value each row. 2. DT returns list - In this case each entry in the list will represent a row. 3. DT return unknown obj (str..) - return empty list. Args: context_path: DT context path. keys: Keys to be included columns: Grid columns name. Returns: pd.DataFrame: New Table include data from Entry Context """ # Retrieve entry context data entry_context_data = demisto.dt(demisto.context(), context_path) # Validate entry context structure validate_entry_context(entry_context_data, keys) # Building new Grid if len(entry_context_data) > 1: # Handle entry context list option entry_context_data = [ filter_dict(item, keys, len(columns)) for item in entry_context_data ] table = pd.DataFrame(entry_context_data) table.rename(columns=dict(zip(table.columns, columns)), inplace=True) elif len(entry_context_data) == 1 and isinstance(entry_context_data[0], dict): # Handle entry context key-vlaue option entry_context_data = filter_dict(entry_context_data[0], keys).items() table = pd.DataFrame(entry_context_data, columns=columns[:2]) else: table = [] return table
def main() -> None: ORANGE_HTML_STYLE = "color:#FF9000;font-size:250%;>" GREEN_HTML_STYLE = "color:#00CD33;font-size:275%;>" RED_HTML_STYLE = "color:#FF1744;font-size:275%;>" DIV_HTML_STYLE = "display:block;text-align:center;" try: sonar_total_hits = demisto.context()["Rubrik"]["Sonar"]["totalHits"] if not sonar_total_hits: html = f"<div style={DIV_HTML_STYLE}><h1 style={GREEN_HTML_STYLE}{str(sonar_total_hits)}</h1></div>" else: html = f"<div style={DIV_HTML_STYLE}><h1 style={RED_HTML_STYLE}{str(sonar_total_hits)}</h1></div>" except KeyError: html = f"<div style={DIV_HTML_STYLE}><h1 style={ORANGE_HTML_STYLE}No Results Found</h1></div>" demisto.results({ 'ContentsFormat': formats['html'], 'Type': entryTypes['note'], 'Contents': html })
def wait_for_key(args: Dict[str, Any]): context_key = args.get('context_key', 'None') max_iterations = 10 try: max_iterations = int(args.get('iterations', 10)) except (ValueError, TypeError): return_error('Please provide an integer value for "iterations"') demisto_context = demisto.context() itr = 0 done = False while not done and itr < max_iterations: if demisto_context.get(context_key) is not None: done = True demisto.executeCommand("Sleep", {"seconds": "1"}) itr = itr + 1 if done is False: readable_output = f'Could not find "{context_key}" after "{str(itr)}" iterations' else: readable_output = f'Found "{context_key}" after "{str(itr)}" iterations' return CommandResults(readable_output=readable_output)
def get_packs_data_from_context(): """Fetched packs' data from context and formats it to an installable object. """ instance_context = demisto.context() context_packs_data = instance_context.get('ContentData') if isinstance(context_packs_data, list): context_entries = [{ 'packid': pack['packID'], 'packversion': 'latest', } for pack in context_packs_data] else: context_entries = [{ 'packid': context_packs_data['packID'], 'packversion': 'latest', }] return_results( CommandResults( outputs_prefix='ConfigurationSetup', outputs={'MarketplacePacks': context_entries}, ))
def generate_netcraft_context_with_notes(list_of_notes_contexts): all_takedowns_entry_context = demisto.context().get("Netcraft", {}).get("Takedown", {}) for note_context in list_of_notes_contexts: all_takedowns_entry_context = add_note_to_suitable_takedown_in_context(note_context, all_takedowns_entry_context) return all_takedowns_entry_context