def return_involved_incidents_entry(incidents_df, indicators_df, fields_to_display): incidents_df['Id'] = incidents_df['id'].apply(lambda x: "[%s](#/Details/%s)" % (x, x)) incidents_df = incidents_df.sort_values('created', ascending=False).reset_index(drop=True) incidents_df['created_dt'] = incidents_df['created'].apply(lambda x: dateutil.parser.parse(x)) # type: ignore incidents_df['Created'] = incidents_df['created_dt'].apply(lambda x: x.strftime("%B %d, %Y")) incidents_df['similarity'] = incidents_df['similarity'].fillna(1) incidents_df['similarity'] = incidents_df['similarity'].apply(lambda x: '{:.1f}%'.format(x * 100)) current_incident_id = demisto.incident()['id'] incidents_df['DBot Score'] = incidents_df['id'].apply(lambda id_: get_reputation(id_, indicators_df)) # add a mark at current incident, at its similarity cell incidents_df['similarity'] = incidents_df.apply( lambda x: '{} (current)'.format(x['similarity']) if x['id'] == current_incident_id else x['similarity'], axis=1) incidents_df['status'] = incidents_df['status'].apply(lambda x: STATUS_DICT[x] if x in STATUS_DICT else '') incidents_df.rename({ 'name': 'Name', FROM_FIELD: 'Email From', 'similarity': 'Similarity to Current Incident', 'status': 'Status'}, axis=1, inplace=True) incidents_headers = ['Id', 'Created', 'Name', 'Status', 'Email From', 'DBot Score', 'Similarity to Current Incident'] if fields_to_display is not None: fields_to_display = [f for f in fields_to_display if f in incidents_df.columns] incidents_df[fields_to_display] = incidents_df[fields_to_display].fillna('') fields_to_display = [f for f in fields_to_display if len(get_non_na_empty_values(incidents_df, f)) > 0] incidents_headers += fields_to_display hr = '\n\n' + tableToMarkdown('Involved Incidents', incidents_df[incidents_headers].to_dict(orient='records'), headers=incidents_headers) return_outputs_custom(hr, tag='incidents')
def main(): incident = demisto.incident() custom_fields = incident.get('CustomFields', {}) identity_results_str = custom_fields.get('identitytable', {}) identity_results = json.loads(identity_results_str) if not identity_results: return CommandResults() if isinstance(identity_results, list): events_arr = [] for event in identity_results: events_arr.append(event) markdown = tableToMarkdown("", events_arr, headers=events_arr[0].keys()) else: markdown = tableToMarkdown("", identity_results) return { 'ContentsFormat': formats['markdown'], 'Type': entryTypes['note'], 'Contents': markdown }
def main(): incident = demisto.incident() if not incident: raise ValueError( "Error - demisto.incident() expected to return current incident " "from context but returned None") custom_fields = incident.get('CustomFields', {}) identity_results_str = custom_fields.get('identitytable', {}) is_successful = custom_fields.get('successfulidentityenrichment', '') if is_successful == 'false': return CommandResults(readable_output='Identity enrichment failed.') identity_results = json.loads(identity_results_str) if not identity_results: return CommandResults( readable_output='No users were found in the notable.') if isinstance(identity_results, list): events_arr = [] for event in identity_results: events_arr.append(event) markdown = tableToMarkdown("", events_arr, headers=events_arr[0].keys()) else: markdown = tableToMarkdown("", identity_results) return { 'ContentsFormat': formats['markdown'], 'Type': entryTypes['note'], 'Contents': markdown }
def main(): try: incident = demisto.incident() custom_fields = incident.get('CustomFields', {}) fetched = custom_fields.get('numberoffetchedevents', 0) # define which incident field to use total = custom_fields.get('numberofeventsinoffense', 0) # define which incident field to use if fetched == 0: message = 'The offense contains Events but non were fetched. ' \ 'Event fetching can be configured in the integration instance settings.' else: message = 'Events details on this page are based on the fetched events.' html = HTML_TEMPLATE.format(fetched=fetched, total=total, message=message) return { 'ContentsFormat': 'html', 'Type': entryTypes['note'], 'Contents': html } except Exception as exp: return_error('could not parse QRadar offense', error=exp)
def main(): current_incident_id = demisto.args().get('incidentID') if current_incident_id is None: incident = demisto.incident() current_incident_id = incident['id'] related_incidents_ids = demisto.args().get('relatedIncidentsIDs', []) if type(related_incidents_ids) is not list: related_incidents_ids = related_incidents_ids.split(",") related_incidents_ids = [x for x in related_incidents_ids if x] indicators = demisto.args().get('indicators', []) if len(indicators) and len(related_incidents_ids) == 0: return_error("No related incidents or indicators specified") canvas, connections = generate_canvas(current_incident_id, related_incidents_ids, indicators) override = demisto.args().get('overrideUserCanvas') == 'true' res = demisto.executeCommand( 'drawCanvas', { 'canvas': canvas, 'canvasLinks': connections, 'id': current_incident_id, 'overrideUserCanvas': override }) if res is None: return_error("Unexpected error") elif is_error(res): return_error(get_error(res)) else: hr = "### Check the incidents and indicators layout on the [canvas](#/Canvas/{0})".format( current_incident_id) return_outputs(hr)
def create_context_for_campaign_details(campaign_found=False, incidents_df=None): if not campaign_found: return { 'isCampaignFound': campaign_found, } else: incident_id = demisto.incident()['id'] incidents_df['recipients'] = incidents_df.apply( lambda row: get_recipients(row), axis=1) incidents_df['recipientsdomain'] = incidents_df.apply( lambda row: extract_domain_from_recipients(row), axis=1) context_keys = [ 'id', 'similarity', FROM_FIELD, FROM_DOMAIN_FIELD, 'recipients', 'recipientsdomain' ] incident_df = incidents_df[ context_keys] # lgtm [py/hash-unhashable-value] incident_df = incident_df[incident_df['id'] != incident_id] incident_df.rename({FROM_DOMAIN_FIELD: 'emailfromdomain'}, axis=1, inplace=True) incidents_context = incident_df.fillna(1).to_dict(orient='records') return { 'isCampaignFound': campaign_found, 'involvedIncidentsCount': len(incidents_df) if incidents_df is not None else 0, 'incidents': incidents_context }
def get_incident_owners(incident_ids) -> list: """ Gets the campaign incident owners by their ids. Args: incident_ids: All the campaign incident ids. Returns: List of the incident owners. """ res = demisto.executeCommand( 'GetIncidentsByQuery', {'query': "id:({})".format(' '.join(incident_ids))}) if isError(res): return_error( f'Error occurred while trying to get incidents by query: {get_error(res)}' ) incidents_from_query = json.loads(res[0]['Contents']) incident_owners = set( [incident['owner'] for incident in incidents_from_query]) incident_owners.add( demisto.incident()["owner"]) # Add the campaign incident owner incident_owners_res = list(filter(lambda x: x, incident_owners)) return incident_owners_res
def create_context_for_campaign_details(campaign_found=False, incidents_df=None, additional_context_fields: list = None): if not campaign_found: return { 'isCampaignFound': campaign_found, } else: incident_id = demisto.incident()['id'] incidents_df['recipients'] = incidents_df.apply(lambda row: get_recipients(row), axis=1) incidents_df['recipientsdomain'] = incidents_df.apply(lambda row: extract_domain_from_recipients(row), axis=1) context_keys = {'id', 'similarity', FROM_FIELD, FROM_DOMAIN_FIELD, 'recipients', 'recipientsdomain'} invalid_context_keys = set() if additional_context_fields is not None: for key in additional_context_fields: if key in incidents_df.columns: context_keys.add(key) else: invalid_context_keys.add(key) if invalid_context_keys: return_warning(INVALID_KEY_WARNING.format(fields=invalid_context_keys)) incident_df = incidents_df[context_keys] # lgtm [py/hash-unhashable-value] if not SELF_IN_CONTEXT: incident_df = incident_df[incident_df['id'] != incident_id] incident_df.rename({FROM_DOMAIN_FIELD: 'emailfromdomain'}, axis=1, inplace=True) incidents_context = incident_df.fillna(1).to_dict(orient='records') return { 'isCampaignFound': campaign_found, 'involvedIncidentsCount': len(incidents_df) if incidents_df is not None else 0, INCIDENTS_CONTEXT_TD: incidents_context }
def merge_contexts(self, current_incident_data: dict, campaign_data: dict) -> dict: """ This will update the existing incident's campaign data with the rest of the campaign data, according to the following logic: If we have a new campaign, copy the all current incident's campaign context to campaign. If we have an existing campaign - if the current incident is new, add the new incident to the campaign. Also, update other campaign incident's similarity to match the new one. """ if not campaign_data: demisto.debug( "Creating new Campaign with the current incident data.") return current_incident_data if self.is_incident_new_in_campaign(demisto.incident()["id"], campaign_data): demisto.debug( "Adding current incident as new incident to Campaign.") self.add_current_incident_to_campaign(current_incident_data, campaign_data) self.update_similarity_to_last_incident( current_incident_data.get('incidents', [])) return campaign_data else: demisto.debug("Current incident already exists in Campaign.") return campaign_data
def main(): args = demisto.args() command_args = {'alert_status': None, 'alert_id': None, 'aggregate_alert_id': None} incident = demisto.incident() alert_status = args['new'] alert_status = alert_status.lower().replace(' ', '_') command_args['alert_status'] = alert_status labels = incident.get('labels', []) for label in labels: if label.get('type') == 'id': command_args['alert_id'] = label.get('value') if label.get('type') == 'aggregate_alert_id': command_args['aggregate_alert_id'] = label.get('value') demisto.info( "Update status: alert id - {}, aggregate_alert_id - {}, new status - {}".format( command_args.get('alert_id', ''), command_args.get('aggregate_alert_id', ''), alert_status)) res = demisto.executeCommand("cybersixgill-update-alert-status", command_args) if isError(res[0]): return_error('Failed to update Actionable alert status - {}'.format(res[0]['Contents'])) else: demisto.results("Actionable Alert Status Updated successfully.")
def main(): try: incident = demisto.incident() custom_fields = incident.get('CustomFields', {}) last_mirror_in_time = custom_fields.get('lastmirroredintime', None) message = custom_fields.get('incomingmirrorerror', '') if message == '': status = 'Not Started' elif message == 'Mirroring events has reached events limit in this incident.': status = 'Completed and Stopped' elif message == 'All available events in the offense were mirrored.': status = 'Completed' elif message == 'In queue.': status = 'In Progress' else: status = 'Failure' html = HTML_TEMPLATE.format(status=status, message=message, last_mirror_in_time=last_mirror_in_time) return { 'ContentsFormat': 'html', 'Type': entryTypes['note'], 'Contents': html } except Exception as exp: return_error('could not parse QRadar offense', error=exp)
def perform_add_to_campaign(ids, action): demisto.debug('starting add to campaign') campaign_id = demisto.incident()['id'] campaign_incident_context = demisto.executeCommand('getContext', {'id': campaign_id}) demisto.debug(f'got incident context: {campaign_incident_context}') if isError(campaign_incident_context): return_error(COMMAND_ERROR_MSG.format(action=action, ids=','.join(ids), error=get_error(campaign_incident_context))) incident_context = demisto.dt(campaign_incident_context, 'Contents.context.EmailCampaign.incidents') if isinstance(incident_context, dict) or isinstance(incident_context, str): incident_context = [incident_context] for incident_id in ids: search_path = f'Contents.context.EmailCampaign.LowerSimilarityIncidents(val.id=={incident_id})' similar_incident_data = demisto.dt(campaign_incident_context, search_path) if similar_incident_data: similar_incident_data = similar_incident_data[0] _add_campaign_to_incident(incident_id, campaign_id) # Add the incident to context under "incidents": incident_context.append(similar_incident_data) _remove_incident_from_lower_similarity_context(campaign_incident_context, ids) res = demisto.executeCommand('SetByIncidentId', {'key': 'EmailCampaign.incidents', 'value': incident_context}) if is_error(res): return_error('Failed to change current context. Error details:\n{}'.format(get_error(res))) return COMMAND_SUCCESS.format(action=action, ids=','.join(ids))
def main(): try: incident = demisto.incident() magnitude = incident.get('CustomFields', {}).get( 'magnitudeoffense', 0) # define which incident field to use if 8 <= magnitude <= 10: magnitude = str(magnitude) html = "<h1 style='color:#D13C3C;text-align:center;'>" + magnitude + "</h1>" elif 4 <= magnitude <= 7: magnitude = str(magnitude) html = "<h1 style='color:#D17D00;text-align:center;'>" + magnitude + "</h1>" else: magnitude = str(magnitude) html = "<h1 style='color:#1DB846;text-align:center;'>" + magnitude + "</h1>" return { 'ContentsFormat': formats['html'], 'Type': entryTypes['note'], 'Contents': html } except Exception as exp: return_error('could not parse QRadar assets', error=exp)
def main(): try: incident = demisto.incident() assets = incident.get('CustomFields', {}).get('assettable', {}) if not assets: return '' if not isinstance(assets, dict): assets = json.loads(assets) if not isinstance(assets, list): assets = [assets] for asset in assets: if "interfaces" in asset: if isinstance(asset["interfaces"], str): asset["interfaces"] = json.loads(asset["interfaces"]) # using yaml to prettify the output of the field asset["interfaces"] = yaml.dump(asset["interfaces"]) markdown = tableToMarkdown("Asset Table", assets) return { 'ContentsFormat': formats['markdown'], 'Type': entryTypes['note'], 'Contents': markdown } except Exception as exp: return_error('could not parse QRadar assets', error=exp)
def rubrik_radar_analysis_status_command(client: Client, args: Dict[str, Any]) -> CommandResults: incident = demisto.incident().get("CustomFields") # activitySeriesId is an optional value for the command. When not set, # look up the value in the incident custom fields activitySeriesId = args.get('activitySeriesId', None) if not activitySeriesId: try: activitySeriesId = incident.get("rubrikpolarisactivityseriesid") except AttributeError as e: # if still not found return an error message about it being # required return_error( message="The activitySeriesId value is required. Either manually provide or run this " "command in a 'Rubrik Radar Anomaly' incident where it will automatically looked " "up using the incident context.", error=e) operation_name = f"{OPERATION_NAME_PREFIX}AnomalyEventSeriesDetailsQuery" query = """query %s($activitySeriesId: UUID!, $clusterUuid: UUID!) { activitySeries(activitySeriesId: $activitySeriesId, clusterUuid: $clusterUuid) { activityConnection { nodes { id message time } } progress lastUpdated lastActivityStatus } } """ % operation_name variables = { "clusterUuid": incident.get("rubrikpolariscdmclusterid"), "activitySeriesId": activitySeriesId } radar_update_events = client.gql_query(operation_name, query, variables, False) context = { "ClusterID": incident.get("rubrikpolariscdmclusterid"), "ActivitySeriesId": activitySeriesId, "Message": radar_update_events["data"]["activitySeries"]["activityConnection"]["nodes"] } if radar_update_events["data"]["activitySeries"]["lastActivityStatus"] == "Success": context["EventComplete"] = "True" else: context["EventComplete"] = "False" return CommandResults( outputs_prefix='Rubrik.Radar', outputs_key_field='ActivitySeriesId', outputs=context )
def get_pcap() -> Dict[str, Any]: alert_id = demisto.incident()['CustomFields'].get('alertid') if not alert_id: return_error( 'Forescout EyeInspect alert ID is missing inside the incident.') return demisto.executeCommand('forescout-ei-alert-pcap-get', {'alert_id': alert_id})
def associate_to_current_incident(indicators: List[Dict[str, str]]): incident_id = demisto.incident()['id'] execute_command( 'associateIndicatorsToIncident', { 'incidentId': incident_id, 'indicatorsValues': list(map(lambda x: x['value'], indicators)) } )
def set_incident_owners(incident_ids, action, user_name): incident_ids.append(demisto.incident()["id"]) for incident_id in incident_ids: res = demisto.executeCommand("setIncident", {"id": incident_id, "owner": user_name}) if isError(res): return_error(COMMAND_ERROR_MSG.format(action=action, ids=','.join(incident_ids), error=get_error(res)))
def evidence_dynamic_section(args: Dict[str, Any]) -> CommandResults: incident = demisto.incident() custom_fields = incident.get('CustomFields', {}) latest_evidence = custom_fields.get('expanselatestevidence', None) if latest_evidence is None: latest_evidence = "*No Latest Evidence*\n" else: latest_evidence = convert_to_markdown(json.loads(latest_evidence)) return CommandResults(readable_output=latest_evidence)
def main(args): incident = demisto.incident() account_name = incident.get('account') account_name = f"acc_{account_name}/" if account_name != "" else "" is_widget = argToBoolean(args.get('isWidget', True)) if is_widget is True: workers = demisto.executeCommand( "demisto-api-get", {"uri": f"{account_name}workers/status"})[0]['Contents'] if not workers['response']['ProcessInfo']: table = [{'Details': '-', 'Duration': '-', 'StartedAt': '-'}] else: table = workers['response']['ProcessInfo'] nano_to_secs(table) format_time(table) format_details(table) md = tableToMarkdown('Workers Status', table, headers=[ 'InvestigationID', 'PlaybookName', 'TaskID', 'TaskName', 'StartTime', 'Duration' ]) dmst_entry = { 'Type': entryTypes['note'], 'Contents': md, 'ContentsFormat': formats['markdown'], 'HumanReadable': md, 'ReadableContentsFormat': formats['markdown'], 'EntryContext': { 'workers': table } } return dmst_entry else: workers = demisto.executeCommand( "demisto-api-get", {"uri": "/workers/status"})[0]['Contents'] demisto.executeCommand( "setIncident", { 'healthcheckworkerstotal': workers['response']['Total'], 'healthcheckworkersbusy': workers['response']['Busy'] }) add_actions = analyze_data(workers['response']) results = CommandResults(readable_output="HealthCheckWorkers Done", outputs_prefix="HealthCheck.ActionableItems", outputs=add_actions) return results
def main(): 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') attachments = incident.get('attachment', []) email_latest_message = custom_fields.get('emaillatestmessage') try: email_related_incident_code = email_subject.split('<')[1].split('>')[0] email_original_subject = email_subject.split('<')[-1].split('>')[1] email_related_incident = get_email_related_incident_id( email_related_incident_code, email_original_subject) update_latest_message_field(email_related_incident, email_latest_message) query = f"id:{email_related_incident}" incident_details = get_incident_by_query(query)[0] check_incident_status(incident_details, email_related_incident) get_attachments_using_instance(email_related_incident, incident.get('labels')) # Adding a 5 seconds sleep in order to wait for all the attachments to get uploaded to the server. time.sleep(5) files = get_incident_related_files(email_related_incident) 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, html_body, attachments) add_entries(email_reply, email_related_incident) # False - to not create new incident demisto.results(False) except (IndexError, ValueError, DemistoException) as e: demisto.executeCommand( 'setIncident', { 'id': incident.get('id'), 'customFields': { 'emailgeneratedcode': get_unique_code() } }) # True - For creating new incident demisto.results(True) if type(e).__name__ == 'IndexError': demisto.debug( 'No related incident was found. A new incident was created.') else: demisto.debug(f"A new incident was created. Reason: \n {e}")
def refresh_issue_assets_command(args: Dict[str, Any]) -> CommandResults: incident = demisto.incident() custom_fields = incident.get('CustomFields', {}) assets = custom_fields.get('expanseasset', []) for asset in assets: asset_type = asset.get('assettype') asset_key = asset.get('assetkey') if asset_type == 'Domain': new_asset = demisto.executeCommand('expanse-get-domain', {"domain": asset_key}) elif asset_type == 'IpRange': new_asset = demisto.executeCommand('expanse-get-iprange', { "id": asset_key, "include": "annotations" }) elif asset_type == 'Certificate': new_asset = demisto.executeCommand('expanse-get-certificate', {"md5_hash": asset_key}) elif asset_type == 'CloudResource': new_asset = demisto.executeCommand('expanse-get-cloud-resource', {"id": asset_key}) else: # Unknown asset type, ignore. continue if isinstance(new_asset, list): for na in new_asset: if isinstance(na, dict) and 'Contents' in na: contents = na.get('Contents') break if not contents: continue if isinstance(contents, list): if len(contents) == 0: continue contents = contents[0] if not isinstance(contents, dict): continue if (annotations := contents.get('annotations', None)) and isinstance( annotations, dict): if (tags := annotations.get('tags', None)) and isinstance( tags, list) and len(tags) > 0: asset['tags'] = '\n'.join(t['name'] for t in tags if 'name' in t)
def extract_feedback_information(): feedback_field = get_value_from_context(key="Arcanna.FeedbackField") if type(feedback_field) == list and len(feedback_field) > 0: feedback_field = feedback_field[0] if not feedback_field: raise Exception("Failed to get value for Arcanna closing field") # Get Values from incident feedback_field_value = demisto.incident().get(feedback_field, None) if not feedback_field_value: # if closing field value is Empty try to get it from Args as a fallback feedback_field_value = demisto.args().get(feedback_field, None) return feedback_field, feedback_field_value
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 get_duration_html(): try: incident_id = demisto.incident().get('id', {}) context = demisto.executeCommand("getContext", {'id': incident_id}) first_date = demisto.get(context[0]['Contents']['context'], "EmailCampaign.firstIncidentDate") if not first_date: raise FieldNotFound() if isinstance(first_date, list): first_date = first_date[-1] now = datetime.now().replace(tzinfo=utc) parsed_first_date: datetime = dateutil.parser.isoparse( first_date).replace(tzinfo=utc) diff = now - parsed_first_date return f""" <table> <tr> <th style="font-size: 25px;">🕙</th> <th style="font-size: 30px;">{diff.days}</th> <th style="font-size: 30px;">:</th> <th style="font-size: 30px;">{(diff.seconds // 3600) % 24}</th> <th style="font-size: 30px;">:</th> <th style="font-size: 30px;">{(diff.seconds // 60) % 60}</th> </tr> <tr> <td style="font-size: 15px; text-align: center"></td> <td style="font-size: 15px; text-align: center">Days</td> <td style="font-size: 15px; text-align: center"></td> <td style="font-size: 15px; text-align: center">Hours</td> <td style="font-size: 15px; text-align: center"></td> <td style="font-size: 15px; text-align: center">Minutes</td> </tr> </table> """ except FieldNotFound: return '<div style="text-align: center;">Duration is not available.</div>' except Exception as e: demisto.error(traceback.format_exc()) return_error(f"Error calculating duration\n{str(e)}")
def get_duration_html(): try: incident_id = demisto.incident().get('id', {}) context = demisto.executeCommand("getContext", {'id': incident_id}) first_date = demisto.get(context[0]['Contents']['context'], "EmailCampaign.firstIncidentDate") if not first_date: raise FieldNotFound() if isinstance(first_date, list): first_date = first_date[-1] now = datetime.now().replace(tzinfo=utc) parsed_first_date: datetime = dateutil.parser.isoparse( first_date).replace(tzinfo=utc) diff = now - parsed_first_date return f""" <div class="demisto-duration vertical-strech"> <div class="duration-widget"> <div class="grid-container"> <div class="duration-icon"><i class="wait icon home"></i></div> <div class="days-number">{diff.days}</div> <div class="colon center aligned">:</div> <div class="hours-number">{(diff.seconds // 3600) % 24}</div> <div class="colon-2 center aligned">:</div> <div class="one column wide minutes-number">{(diff.seconds // 60) % 60}</div> <div class="days-label time-unit title-h5 opacity-description">DAYS</div> <div class="hours-label time-unit title-h5 opacity-description">HOURS</div> <div class="minutes-label time-unit title-h5 opacity-description">MIN</div> </div> </div> </div> """ except FieldNotFound: return_error( "Can't find firstIncidentDate in context, please run FindEmailCampaign" ) except Exception as e: demisto.error(traceback.format_exc()) return_error(f"Error calculating duration\n{str(e)}")
def main(): try: incident = demisto.incident() events = incident.get('CustomFields', {}).get('events', {}) if not events: return CommandResults() title = f'Offense Events (Showing first {MAX_EVENTS})' if isinstance(events, list): events_arr = [] for event in events: events_arr.append(json.loads(event)) markdown = tableToMarkdown(title, events_arr[:MAX_EVENTS], headers=events_arr[0].keys()) else: markdown = tableToMarkdown(title, json.loads(events)[:MAX_EVENTS]) return CommandResults(readable_output=markdown) except Exception as exp: return_error('could not parse QRadar events', error=exp)
def get_current_table(grid_id: str) -> pd.DataFrame: """ Get current Data from the grid Args: grid_id: Grid ID to retrieve data from. Returns: DataFrame: Existing grid data. """ custom_fields = demisto.incident().get("CustomFields", {}) if grid_id not in custom_fields: raise ValueError( f"The following grid id was not found: {grid_id}. Please make sure you entered the correct " f"incident type with the \"Machine name\" as it appears in the incident field editor in " f"Settings->Advanced ->Fields (Incident). Also make sure that this value appears in the " f"incident Context Data under incident - if not then please consult with support." ) current_table: Optional[List[dict]] = custom_fields.get(grid_id) return pd.DataFrame(current_table)
def main(): incident = demisto.incident() incident_id = incident.get('id') email_threads = fetch_email_threads(incident_id) if email_threads: thread_summary_rows = format_threads(email_threads) else: return_results({ 'ContentsFormat': EntryFormat.HTML, 'Type': EntryType.NOTE, 'Contents': no_entries_message }) return None demisto.results({ 'ContentsFormat': EntryFormat.TABLE, 'Type': EntryType.NOTE, 'Contents': thread_summary_rows, 'HumanReadable': thread_summary_rows })
def main(): 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') attachments = incident.get('attachment', []) email_latest_message = custom_fields.get('emaillatestmessage') try: email_related_incident = email_subject.split('#')[1].split()[0] update_latest_message_field(email_related_incident, email_latest_message) query = f"id:{email_related_incident}" incident_details = get_incident_by_query(query) check_incident_status(incident_details, email_related_incident) get_attachments_using_instance(email_related_incident, incident.get('labels')) # Adding a 5 seconds sleep in order to wait for all the attachments to get uploaded to the server. time.sleep(5) files = get_incident_related_files(email_related_incident) 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, html_body, attachments) add_entries(email_reply, email_related_incident) # False - to not create new incident demisto.results(False) except (IndexError, ValueError, DemistoException) as e: # True - For creating new incident demisto.results(True) return_error( f"The PreprocessEmail script has encountered an error:\n {e} \nA new incidents was created." )