def list_attachments_command(): user_id = demisto.args().get('user_id') message_id = demisto.args().get('message_id') folder_id = demisto.args().get('folder_id') raw_response = list_attachments(user_id, message_id, folder_id) attachments = raw_response.get('value') if attachments: attachment_list = [{ 'ID': attachment.get('id'), 'Name': attachment.get('name'), 'Type': attachment.get('contentType') } for attachment in attachments] attachment_entry = {'ID': message_id, 'Attachment': attachment_list, 'UserID': user_id} entry_context = {'MSGraphMailAttachment(val.ID === obj.ID)': attachment_entry} # Build human readable file_names = [attachment.get('Name') for attachment in attachment_list if isinstance( attachment, dict) and attachment.get('Name')] human_readable = tableToMarkdown( f'Total of {len(attachment_list)} attachments found in message {message_id} from user {user_id}', {'File names': file_names} ) return_outputs(human_readable, entry_context, raw_response) else: human_readable = f'### No attachments found in message {message_id}' return_outputs(human_readable, dict(), raw_response)
def main(): LIST_NAME = demisto.args()['listName'] TO_ZIP = (demisto.args()['zipFile'] == 'true') entry_id = demisto.args()['entryId'] res = demisto.getFilePath(entry_id) if not res: return_error("Entry {} not found".format(entry_id)) file_path = res['path'] file_base64 = get_file_data(file_path, TO_ZIP) res = demisto.executeCommand("createList", {"listName": LIST_NAME, "listData": file_base64}) if isError(res): return res return { 'Contents': file_base64, 'ContentsFormat': formats['text'], 'HumanReadable': tableToMarkdown('Success store file in list', { 'File Entry ID': entry_id, 'List Name': LIST_NAME, 'Size': len(file_base64) }), 'HumanReadableFormat': formats['markdown'], }
def delete_tags(): """ The command deletes tags for the specified endpoint. demisto parameter: (string) endpoint_id The unique ID of the endpoint demisto parameter: (array) body The tags to delete from the endpoint """ endpoint_id = demisto.args().get('endpoint_id') body = argToList(demisto.args().get('tags')) response = delete_tags_request(endpoint_id, body) response = endpoint_tags_request(endpoint_id) response = { 'tags': response, 'Id': endpoint_id } context = { 'CounterTack.Endpoint(val.Id && val.Id === obj.Id)': createContext(response, keyTransform=underscoreToCamelCase) } entry = { 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown( 'Endpoint tags were deleted successfully', response), 'EntryContext': context } demisto.results(entry)
def add_entries_command(): resource_id = demisto.args().get('resourceId') entries = demisto.args().get('entries') query_path = 'www/manager-service/services/ActiveListService/' if not isinstance(entries, dict): try: entries = json.loads(entries) except ValueError as ex: demisto.debug(str(ex)) return_error('Entries must be in JSON format. Must be array of objects.') if not all([entry.keys() == entries[0].keys() for entry in entries[1:]]): return_error('All entries must have the same fields') columns = ''.join(COLUMN(column) for column in entries[0]) # the fields in the entryList matrix are the columns entry_list = BODY(columns + ''.join(ENTRY_LIST(''.join(ENTRY(v) for v in en.values())) for en in entries)) body = REQ_SOAP_BODY(function='addEntries', auth_token=AUTH_TOKEN, resource_id=resource_id, entryList=entry_list) res = send_request(query_path, body=body) if not res.ok: demisto.debug(res.text) return_error("Failed to add entries. Please make sure to enter Active List resource ID" "\nResource ID: {}\nStatus Code: {}\nRequest Body: {}\nResponse: {}".format(resource_id, res.status_code, body, res.text)) demisto.results("Success")
def rasterize_image(): global return_code, error_message res = demisto.getFilePath(demisto.args()['EntryID']) with open(res['path'], 'r') as f: data = f.read() b64 = base64.b64encode(data) html = '<img src="data:image/png;base64, ' + b64 + '">' return_code = 0 friendly_name = 'image.png' f = open('htmlImage.html', 'w') f.write('<html style="background:white;"><body>' + html + '</body></html>') f.close() command = ['phantomjs', '/usr/local/bin/rasterize.js', 'htmlImage.html', friendly_name] if demisto.get(demisto.args(), 'width') and demisto.get(demisto.args(), 'height'): command.append(demisto.get(demisto.args(), 'width') + '*' + demisto.get(demisto.args(), 'height')) try: error_message = subprocess.check_output(command) except Exception as e: return_code = -1 error_message = e.message if return_code == 0: file = file_result_existing_file(friendly_name) file['Type'] = entryTypes['image'] demisto.results(file) else: demisto.results({'ContentsFormat': 'text', 'Type': entryTypes['error'], 'Contents': 'PhantomJS returned - ' + error_message})
def add_behavior_tags(): """ Add specific tags to specified behavior demisto parameter: (string) behavior_id The unique ID of the behavior demisto parameter: (Array) Body. The tags to add to the behavior. seperate the tags with comma """ behaviour_id = demisto.args().get('behaviour_id') body = argToList(demisto.args().get('tags')) response = behaviour_add_tags_request(behaviour_id, body) behavior_tags = get_behavior_request(behaviour_id) response = { 'tags': behavior_tags.get('tags'), 'Id': behaviour_id } context = { 'CounterTack.Behavior(val.Id && val.Id === obj.Id)': createContext(response, keyTransform=underscoreToCamelCase) } entry = { 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('Behavior tags were added successfully', response), 'EntryContext': context } demisto.results(entry)
def get_security_events_command(): ids = demisto.args().get('ids') last_date_range = demisto.args().get('lastDateRange') ids = argToList(str(ids) if isinstance(ids, int) else ids) raw_events = get_security_events(ids, last_date_range) if raw_events: events = [] contents = decode_arcsight_output(raw_events) for raw_event in contents: event = { 'Event ID': raw_event.get('eventId'), 'Time': timestamp_to_datestring(raw_event.get('endTime'), '%Y-%m-%d, %H:%M:%S'), 'Source Address': decode_ip(demisto.get(raw_event, 'source.address')), 'Destination Address': decode_ip(demisto.get(raw_event, 'destination.address')), 'Name': raw_event.get('name'), 'Source Port': demisto.get(raw_event, 'source.port'), 'Base Event IDs': raw_event.get('baseEventIds') } events.append(event) human_readable = tableToMarkdown('Security Event: {}'.format(','.join(map(str, ids))), events, removeNull=True) outputs = {'ArcSightESM.SecurityEvents(val.eventId===obj.eventId)': contents} return_outputs(readable_output=human_readable, outputs=outputs, raw_response=contents) else: demisto.results('No events were found')
def update_policy_command(): """ Command to update an existing policy in Symantec MC :return: An entry with the policy data """ uuid = demisto.args()['uuid'] name = demisto.args().get('name') description = demisto.args().get('description') reference_id = demisto.args().get('reference_id') replace_variables = demisto.args().get('replace_variables') content: dict = {} context: dict = {} policy = update_policy_request(uuid, name, description, reference_id, replace_variables) if policy: content = { 'UUID': policy.get('uuid'), 'Name': policy.get('name'), 'ContentType': policy.get('contentType'), 'Author': policy.get('author') } context['SymantecMC.Policy(val.UUID && val.UUID === obj.UUID)'] = createContext(content, removeNull=True) headers = ['UUID', 'Name', 'ContentType', 'Author'] return_outputs(tableToMarkdown('Policy updated successfully', content, removeNull=True, headers=headers, headerTransform=pascalToSpace), context, policy)
def whitelist_ip_command(): """ Whitelist an IP address in Canary Tools """ ip = demisto.args().get('ip') port = demisto.args().get('port') res = whitelist_ip(ip, port) if not port: port = 'Any' result_status = res.get('result') if result_status == 'success': context = { 'Address': str(ip), 'Port': str(port), 'Whitelisted': 'True' } context = createContext(context, removeNull=True) contents = res human_readable = 'The IP address {}:{} was added to the Whitelist'.format(ip, port) outputs = { 'CanaryTools.IP(val.Address && val.Address===obj.Address && val.Port && val.Port===obj.Port)': context} return_outputs(readable_output=human_readable, outputs=outputs, raw_response=contents) elif result_status == 'failure': return_outputs(readable_output=res.get('message'), outputs={}, raw_response=res) elif result_status == 'error': return_error(res.get('message'))
def check_whitelist_command(): """ Check if a given IP address is whitelisted in Canary Tools """ ip = demisto.args().get('ip') port = demisto.args().get('port') res = check_whitelist(ip, port) if not port: port = 'Any' context = { 'Address': str(ip), 'Port': str(port), 'Whitelisted': str(res.get('is_ip_whitelisted')) } contents = res context = createContext(context, removeNull=True) outputs = {'CanaryTools.IP(val.Address && val.Address===obj.Address && val.Port && val.Port===obj.Port)': context} if res.get('is_ip_whitelisted'): human_readable = 'The IP address {}:{} is Whitelisted'.format(ip, port) else: human_readable = 'The IP address {}:{} is not Whitelisted'.format(ip, port) return_outputs(readable_output=human_readable, outputs=outputs, raw_response=contents)
def update_ticket_command(): custom_fields = split_fields(demisto.args().get('custom_fields')) template = demisto.args().get('template') ticket_type = get_table_name(demisto.args().get('ticket_type')) ticket_id = demisto.args()['id'] if template: template = get_template(template) fields = get_ticket_fields(template, ticket_type) res = update(ticket_type, ticket_id, fields, custom_fields) if not res or 'result' not in res: return_error('Unable to retrieve response') hr = get_ticket_human_readable(res['result'], ticket_type) context = get_ticket_context(res['result'], ticket_type) entry = { 'Type': entryTypes['note'], 'Contents': res, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('ServiceNow ticket updated successfully\nTicket type: ' + ticket_type, hr, removeNull=True), 'EntryContext': { 'ServiceNow.Ticket(val.ID===obj.ID)': context } } return entry
def create_record_command(): table_name = demisto.args()['table_name'] fields = demisto.args().get('fields') custom_fields = demisto.args().get('custom_fields') if fields: fields = split_fields(fields) if custom_fields: custom_fields = split_fields(custom_fields) res = create(table_name, fields, custom_fields) if not res or 'result' not in res: return 'Could not retrieve record' result = res['result'] mapped_record = {DEFAULT_RECORD_FIELDS[k]: result[k] for k in DEFAULT_RECORD_FIELDS if k in result} entry = { 'Type': entryTypes['note'], 'Contents': res, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('ServiceNow record created successfully', mapped_record, removeNull=True), 'EntryContext': { 'ServiceNow.Record(val.ID===obj.ID)': createContext(mapped_record) } } return entry
def add_comment_command(): ticket_id = demisto.args()['id'] key = 'comments' if demisto.args().get('post-as-comment', 'false').lower() == 'true' else 'work_notes' text = demisto.args()['comment'] ticket_type = get_table_name(demisto.args().get('ticket_type')) res = add_comment(ticket_id, ticket_type, key, text) if not res or 'result' not in res: return_error('Unable to retrieve response') headers = ['System ID', 'Number', 'Impact', 'Urgency', 'Severity', 'Priority', 'State', 'Created On', 'Created By', 'Active', 'Close Notes', 'Close Code', 'Description', 'Opened At', 'Due Date', 'Resolved By', 'Resolved At', 'SLA Due', 'Short Description', 'Additional Comments'] hr = get_ticket_human_readable(res['result'], ticket_type) entry = { 'Type': entryTypes['note'], 'Contents': res, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('Comment successfully added to ServiceNow ticket', hr, headers=headers, removeNull=True) } return entry
def get_case_event_ids_command(): case_id = demisto.args().get('caseId') with_correlated_events = demisto.args().get('withCorrelatedEvents') == 'true' query_path = 'www/manager-service/rest/CaseService/getCaseEventIDs' params = { 'authToken': AUTH_TOKEN, 'caseId': case_id } res = send_request(query_path, params=params, method='get') if not res.ok: demisto.debug(res.text) return_error("Failed to get Event IDs with:\nStatus Code: {}\nResponse: {}".format(res.status_code, res.text)) res_json = res.json() if 'cas.getCaseEventIDsResponse' in res_json and 'cas.return' in res_json.get('cas.getCaseEventIDsResponse'): event_ids = res_json.get('cas.getCaseEventIDsResponse').get('cas.return') if not isinstance(event_ids, list): event_ids = [event_ids] if with_correlated_events: event_ids = get_correlated_events_ids(event_ids) contents = decode_arcsight_output(res_json) human_readable = tableToMarkdown(name='', headers='Case {} Event IDs'.format(case_id), t=event_ids, removeNull=True) outputs = {'ArcSightESM.CaseEvents': event_ids} return_outputs(readable_output=human_readable, outputs=outputs, raw_response=contents) else: demisto.results('No result returned')
def add_policy_content_command(): """ Command to add content to an existing policy in Symantec MC :return: An entry indicating whether the addition was successful """ uuid = demisto.args().get('uuid') name = demisto.args().get('name') content_type = demisto.args()['content_type'] change_description = demisto.args()['change_description'] schema_version = demisto.args().get('schema_version') ips = argToList(demisto.args().get('ip', [])) urls = argToList(demisto.args().get('url', [])) categories = argToList(demisto.args().get('category', [])) enabled = demisto.args().get('enabled') description = demisto.args().get('description') verify_policy_content(content_type, ips, categories, urls) uuid = get_policy_uuid(uuid, name) if content_type == IP_LIST_TYPE: add_policy_content_request(uuid, content_type, change_description, schema_version, ips=ips, enabled=enabled, description=description) elif content_type == URL_LIST_TYPE: add_policy_content_request(uuid, content_type, change_description, schema_version, urls=urls, enabled=enabled, description=description) elif content_type == CATEGORY_LIST_TYPE: add_policy_content_request(uuid, content_type, change_description, schema_version, categories=categories) return_outputs('Successfully added content to the policy', {}, {})
def get_attachment_command(): message_id = demisto.args().get('message_id') user_id = demisto.args().get('user_id') folder_id = demisto.args().get('folder_id') attachment_id = demisto.args().get('attachment_id') raw_response = get_attachment(message_id, user_id, folder_id=folder_id, attachment_id=attachment_id) entry_context = file_result_creator(raw_response) demisto.results(entry_context)
def add_alert(apply_all, disabled, name, notify_snmp, refire_interval, severity, alert_type, object_type, protocols, field_name, stat_name, units, interval_length, operand, operator, field_name2, field_op, param, param2, alert_id=None): data = { "apply_all": apply_all, "disabled": disabled, "name": name, "notify_snmp": notify_snmp, "refire_interval": int(refire_interval), "severity": int(severity), "type": alert_type } if alert_type == 'detection': data['object_type'] = object_type data['protocols'] = [str(protocols)] elif alert_type == 'threshold': data['field_name'] = field_name data['stat_name'] = stat_name data['units'] = units data['interval_length'] = int(interval_length) data['operand'] = operand data['operator'] = operator if demisto.args().get('field_name2'): data['field_name2'] = field_name2 if demisto.args().get('field_op'): data['field_op'] = field_op if demisto.args().get('param'): data['param'] = param if demisto.args().get('param2'): data['param2'] = param2 if alert_id: method = 'PATCH' url_suffix = 'alerts/{alert_id}'.format(alert_id=alert_id) else: method = 'POST' url_suffix = 'alerts' data = json.dumps(data) try: res = requests.request( method, BASE_URL + url_suffix, verify=USE_SSL, data=data, headers=HEADERS ) except requests.exceptions.RequestException: # This is the correct syntax return_error('Failed to connect to - {url} - Please check the URL'.format(url=BASE_URL)) # Handle error responses gracefully if res.status_code == 204: return demisto.results('Successful Modification') if res.status_code == 400: resp = res.json() return_error('Error in request format - {message}'.format(message=resp['error_message'])) if res.status_code == 201: return demisto.results('Alert successfully added') elif res.status_code not in {200, 204, 201}: return_error('Error in API call to ExtraHop {code} - {reason}'.format(code=res.status_code, reason=res.reason)) return res
def get_entries_command(): resource_id = demisto.args().get('resourceId') entry_filter = demisto.args().get('entryFilter') query_path = 'www/manager-service/services/ActiveListService/' body = REQ_SOAP_BODY(function='getEntries', auth_token=AUTH_TOKEN, resource_id=resource_id, entryList=None) res = send_request(query_path, body=body) if not res.ok: demisto.debug(res.text) return_error("Failed to get entries:\nResource ID: {}\nStatus Code: {}\nRequest Body: {}\nResponse: {}".format( resource_id, res.status_code, body, res.text)) res_json = json.loads(xml2json(res.text)) raw_entries = demisto.get(res_json, 'Envelope.Body.getEntriesResponse.return') # retrieve columns cols = demisto.get(raw_entries, 'columns') if cols: hr_columns = tableToMarkdown(name='', headers=['Columns'], t=cols, removeNull=True) if cols else 'Active list has no columns' contents = cols return_outputs(readable_output=hr_columns, outputs={}, raw_response=contents) if 'entryList' in raw_entries: entry_list = raw_entries['entryList'] if isinstance(raw_entries['entryList'], list) else [ raw_entries['entryList']] entry_list = [d['entry'] for d in entry_list if 'entry' in d] keys = raw_entries.get('columns') entries = [dict(zip(keys, values)) for values in entry_list] # if the user wants only entries that contain certain 'field:value' sets (filters) # e.g., "name:myName,eventId:0,:ValueInUnknownField" # if the key is empty, search in every key filtered = entries if entry_filter: for f in entry_filter.split(','): k, v = f.split(':') filtered = [entry for entry in filtered if ((entry.get(k) == v) if k else (v in entry.values()))] contents = decode_arcsight_output(filtered) ActiveListContext = { 'ResourceID': resource_id, 'Entries': contents, } outputs = { 'ArcSightESM.ActiveList.{id}'.format(id=resource_id): contents, 'ArcSightESM.ActiveList(val.ResourceID===obj.ResourceID)': ActiveListContext } human_readable = tableToMarkdown(name='Active List entries: {}'.format(resource_id), t=filtered, removeNull=True) return_outputs(readable_output=human_readable, outputs=outputs, raw_response=contents) else: demisto.results('Active List has no entries')
def delete_policy_command(): """ Command to delete an existing policy in Symantec MC :return: An entry indicating whether the deletion was successful """ uuid = demisto.args()['uuid'] force = demisto.args().get('force') delete_policy_request(uuid, force) return_outputs('Policy deleted successfully', {}, {})
def delete_user(): # can acually delete any object... success = conn.delete(demisto.args().get('user-dn')) if not success: raise Exception('Failed to delete user') demisto_entry = { 'ContentsFormat': formats['text'], 'Type': entryTypes['note'], 'Contents': "Deleted object with dn {}".format(demisto.args().get('user-dn')) } demisto.results(demisto_entry)
def wildfire_file_command(): inputs = file_args_handler(demisto.args().get('file'), demisto.args().get('md5'), demisto.args().get('sha256')) for element in inputs: if sha1Regex.match(element): demisto.results({ 'Type': 11, 'Contents': 'WildFire file hash reputation supports only MD5, SHA256 hashes', 'ContentsFormat': formats['text'] }) else: file_hash, report, file_info = wildfire_get_report(element) create_report(file_hash, report, file_info, 'xml', False)
def urlscan_submit_url(): submission_dict = {} if demisto.args().get('public') == 'public': submission_dict['public'] = 'on' submission_dict['url'] = demisto.args().get('url') sub_json = json.dumps(submission_dict) wait = int(demisto.args().get('wait', 5)) retries = int(demisto.args().get('retries', 0)) r = http_request('POST', 'scan/', sub_json, wait, retries) uuid = r['uuid'] return uuid
def kill_process(): """ Terminates all instances of the process identified in the command. Processes can be identified by the PID or process name. demisto parameter: (string) endpoint_id The unique ID of the endpoint demisto parameter: (string) process_id The ID of the process to terminate demisto parameter: (string) process_name The name of the process to terminate """ endpoint_id = demisto.args().get('endpoint_id') pid = demisto.args().get('process_id') name = demisto.args().get('process_name') if not pid and not name: return_error('Please provide either process_id or process_name') body = { 'type': 'kill_process', 'pid': pid, 'name': name } response = kill_process_request(endpoint_id, body) data = { 'Id': response.get('id'), 'User Name': response.get('username'), 'Request Time': response.get('request_time'), 'Endpoint ID': response.get('endpoint_ids'), 'Command Name': response.get('command_name'), 'Status': response.get('status'), } context = { 'CounterTack.Endpoint(val.Id && val.Id === obj.Id)': createContext(response, keyTransform=underscoreToCamelCase, removeNull=True) } entry = { 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown( 'The process has been terminated', data, removeNull=True), 'EntryContext': context } demisto.results(entry)
def rasterize_email_command(): html = demisto.args()['htmlBody'] friendly_name = 'email.png' if demisto.get(demisto.args(), 'type') == 'pdf': friendly_name = 'email.pdf' rasterize_email_request(html, friendly_name) if return_code == 0: file = file_result_existing_file(friendly_name) file['Type'] = entryTypes['image'] demisto.results(file) else: demisto.results({'ContentsFormat': 'text', 'Type': entryTypes['error'], 'Contents': 'PhantomJS returned - ' + error_message})
def query_groups_command(): table_name = 'sys_user_group' group_id = demisto.args().get('group_id') group_name = demisto.args().get('group_name') group_query = demisto.args().get('query', {}) offset = demisto.args().get('offset', DEFAULTS['offset']) limit = demisto.args().get('limit', DEFAULTS['limit']) if group_id: res = get(table_name, group_id) else: if group_name: group_query = 'name=' + group_name res = query(table_name, limit, offset, group_query) if not res or 'result' not in res: return 'No groups found' groups = res['result'] if not isinstance(groups, list): groups = [groups] if len(groups) == 0: return 'No groups found' headers = ['ID', 'Description', 'Name', 'Active', 'Manager', 'Updated'] mapped_groups = [{ 'ID': group.get('sys_id'), 'Description': group.get('description'), 'Name': group.get('name'), 'Active': group.get('active'), 'Manager': group.get('manager', {}).get('value') if isinstance(group.get('manager'), dict) else group.get('manager'), 'Updated': group.get('sys_updated_on'), } for group in groups] entry = { 'Type': entryTypes['note'], 'Contents': res, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('ServiceNow Groups', mapped_groups, headers=headers, removeNull=True, headerTransform=pascalToSpace), 'EntryContext': { 'ServiceNow.Group(val.ID===obj.ID)': createContext(mapped_groups, removeNull=True), } } return entry
def predict_phishing_words(model_name, model_store_type, email_subject, email_body): model_data = get_model_data(model_name, model_store_type) model = demisto_ml.decode_model(model_data) text = "%s %s" % (email_subject, email_body) res = demisto.executeCommand('WordTokenizerNLP', {'value': text, 'hashWordWithSeed': demisto.args().get('hashSeed')}) if is_error(res[0]): return_error(res[0]['Contents']) tokenized_text_result = res[0]['Contents'] input_text = tokenized_text_result['hashedTokenizedText'] if tokenized_text_result.get('hashedTokenizedText') else \ tokenized_text_result['tokenizedText'] filtered_text, filtered_text_number_of_words = demisto_ml.filter_model_words(input_text, model) if filtered_text_number_of_words == 0: return_error("The model does not contains any of the input text words") explain_result = demisto_ml.explain_model_words(model, input_text, float(demisto.args().get('labelProbabilityThreshold', 0)), float(demisto.args().get('wordThreshold', 0)), int(demisto.args()['topWordsLimit'])) if tokenized_text_result.get('hashedTokenizedText'): hash_word_to_plain = dict( zip(tokenized_text_result['hashedTokenizedText'].split(" "), tokenized_text_result['tokenizedText'].split(" "))) explain_result['PositiveWords'] = map(lambda x: hash_word_to_plain[x], explain_result['PositiveWords']) explain_result['NegativeWords'] = map(lambda x: hash_word_to_plain[x], explain_result['NegativeWords']) explain_result['OriginalText'] = tokenized_text_result['originalText'] explain_result['TextTokensHighlighted'] = tokenized_text_result['tokenizedText'] res = demisto.executeCommand('HighlightWords', {'text': tokenized_text_result['tokenizedText'], 'terms': ",".join(explain_result['PositiveWords'])}) res = res[0] if not is_error(res): highlighted_text_markdown = res['Contents'] explain_result['TextTokensHighlighted'] = highlighted_text_markdown return { 'Type': entryTypes['note'], 'Contents': explain_result, 'ContentsFormat': formats['json'], 'HumanReadable': tableToMarkdown('DBot Predict Phihsing Words', explain_result, headers=['TextTokensHighlighted', 'Label', 'Probability', 'PositiveWords', 'NegativeWords'], removeNull=True), 'HumanReadableFormat': formats['markdown'], 'EntryContext': { 'DBotPredictPhishingWords': explain_result } }
def query_users_command(): table_name = 'sys_user' user_id = demisto.args().get('user_id') user_name = demisto.args().get('user_name') user_query = demisto.args().get('query', {}) offset = demisto.args().get('offset', DEFAULTS['offset']) limit = demisto.args().get('limit', DEFAULTS['limit']) if user_id: res = get(table_name, user_id) else: if user_name: user_query = 'user_name=' + user_name res = query(table_name, limit, offset, user_query) if not res or 'result' not in res: return 'No users found' users = res['result'] if not isinstance(users, list): users = [users] if len(users) == 0: return 'No users found' headers = ['ID', 'Name', 'UserName', 'Email', 'Created', 'Updated'] mapped_users = [{ 'ID': user.get('sys_id'), 'Name': '{} {}'.format(user.get('first_name', ''), user.get('last_name', '')).rstrip(), 'UserName': user.get('user_name'), 'Email': user.get('email'), 'Created': user.get('sys_created_on'), 'Updated': user.get('sys_updated_on'), } for user in users] entry = { 'Type': entryTypes['note'], 'Contents': res, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('ServiceNow Users', mapped_users, headers=headers, removeNull=True, headerTransform=pascalToSpace), 'EntryContext': { 'ServiceNow.User(val.ID===obj.ID)': createContext(mapped_users, removeNull=True), } } return entry
def get_record_command(): table_name = demisto.args()['table_name'] record_id = demisto.args()['id'] fields = demisto.args().get('fields') res = get(table_name, record_id) if not res or 'result' not in res: return 'Cannot find record' if isinstance(res['result'], list): if len(res['result']) == 0: return 'Cannot find record' record = res['result'][0] else: record = res['result'] entry = { 'Type': entryTypes['note'], 'Contents': res, 'ContentsFormat': formats['json'] } if fields: fields = argToList(fields) if 'sys_id' not in fields: # ID is added by default fields.append('sys_id') # filter the record for the required fields record = dict(filter(lambda kv_pair: kv_pair[0] in fields, record.items())) for k, v in record.iteritems(): if isinstance(v, dict): # For objects that refer to a record in the database, take their value(system ID). record[k] = v.get('value', record[k]) record['ID'] = record.pop('sys_id') entry['ReadableContentsFormat'] = formats['markdown'] entry['HumanReadable'] = tableToMarkdown('ServiceNow record', record, removeNull=True) entry['EntryContext'] = { 'ServiceNow.Record(val.ID===obj.ID)': createContext(record) } else: mapped_record = {DEFAULT_RECORD_FIELDS[k]: record[k] for k in DEFAULT_RECORD_FIELDS if k in record} entry['ReadableContentsFormat'] = formats['markdown'] entry['HumanReadable'] = tableToMarkdown('ServiceNow record' + record_id, mapped_record, removeNull=True) entry['EntryContext'] = { 'ServiceNow.Record(val.ID===obj.ID)': createContext(mapped_record) } return entry
def delete_ticket_command(): ticket_id = demisto.args()['id'] ticket_type = get_table_name(demisto.args().get('ticket_type')) res = delete(ticket_type, ticket_id) entry = { 'Type': entryTypes['note'], 'Contents': res, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['text'], 'HumanReadable': 'Ticket with ID ' + ticket_id + ' was successfully deleted.' } return entry
def delete_record_command(): record_id = demisto.args()['id'] table_name = demisto.args().get('table_name') res = delete(table_name, record_id) entry = { 'Type': entryTypes['note'], 'Contents': res, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['text'], 'HumanReadable': 'Record with ID ' + record_id + ' was successfully deleted.' } return entry
import glob import os import re import errno import shutil from typing import List # error class for shell errors class ShellException(Exception): pass try: ROOT_PATH = os.getcwd() MAX_IMAGES = int(demisto.args().get('maxImages', 20)) except OSError: return_error( "The script failed to access the current working directory. This might happen if your docker isn't " "set up correctly. Please contact customer support") except ValueError: return_error( "Value provided for maxImages is of the wrong type. Please provide an integer for maxImages" ) EMAIL_REGXEX = "[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_.]+" # Documentation claims png is enough for pdftohtml, but through testing we found jpg can be generated as well IMG_FORMATS = ['jpg', 'jpeg', 'png', 'gif'] def mark_suspicious(suspicious_reason, entry_id):
break demisto.setLastRun( {"time": tmp_last_fetch if tmp_last_fetch else last_fetch}) return incidents """EXECUTION BLOCK""" try: if demisto.command() == 'test-module': result = test_function() elif demisto.command() == 'fetch-incidents': incidents = fetch_incidents(demisto.getLastRun()) demisto.incidents(incidents) elif demisto.command() == 'aws-access-analyzer-list-analyzers': list_analyzers_command(demisto.args()) elif demisto.command() == 'aws-access-analyzer-list-analyzed-resource': list_analyzed_resource_command(demisto.args()) elif demisto.command() == 'aws-access-analyzer-list-findings': list_findings_command(demisto.args()) elif demisto.command() == 'aws-access-analyzer-get-analyzed-resource': get_analyzed_resource_command(demisto.args()) elif demisto.command() == 'aws-access-analyzer-get-finding': get_finding_command(demisto.args()) elif demisto.command() == 'aws-access-analyzer-start-resource-scan': start_resource_scan_command(demisto.args()) elif demisto.command() == 'aws-access-analyzer-update-findings': update_findings_command(demisto.args()) except Exception as e: return_error(
def search_by_file_hash_command(): ''' Queries Cortex Logging according to a pre-set query ''' args = demisto.args() start_time = args.get('startTime') end_time = args.get('endTime') value = args.get('logsAmount') time_range = args.get('timeRange') time_value = args.get('rangeValue') filehash = args.get('SHA256') if (time_range): if (time_value): service_end_date = datetime.now() service_start_date = get_start_time(time_range, int(time_value)) else: raise Exception( 'Please enter timeRange and timeValue, or startTime and endTime' ) else: # parses user input to datetime object service_start_date = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S") service_end_date = datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S") # transforms datetime object to epoch time service_start_date_epoch = int(service_start_date.strftime("%s")) service_end_date_epoch = int(service_end_date.strftime("%s")) api_query = "SELECT * FROM panw.threat WHERE filedigest='" + filehash + "' LIMIT " + value query_data = { "query": api_query, "startTime": service_start_date_epoch, "endTime": service_end_date_epoch, } response = query_loggings(query_data) try: result = response.json()['result'] pages = result['esResult']['hits']['hits'] table_name = result['esQuery']['table'][0].split('.')[1] except ValueError: raise Exception('Failed to parse the response from Cortex') output = [] for page in pages: row_contents = page.get('_source') row_contents['id'] = page.get('_id') row_contents['score'] = page.get('_score') transformed_row = transform_row_keys(row_contents) output.append(transformed_row) screened_results = results_screener('threat', output) entry = { 'Type': entryTypes['note'], 'Contents': output, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('Logs ' + table_name + ' table', screened_results), 'EntryContext': { 'Cortex.Logging(val.id==obj.id)': output } } return entry
def create_token_command(): role_name = demisto.args().get('role_name') policies = argToList(demisto.args().get('policies', [])) meta = demisto.args().get('meta') no_parent = demisto.args().get('no_parent') no_default_policy = demisto.args().get('no_default_policy') renewable = demisto.args().get('renewable') ttl = demisto.args().get('ttl') explicit_max_ttl = demisto.args().get('explicit_max_ttl') display_name = demisto.args().get('display_name') num_uses = demisto.args().get('num_uses') period = demisto.args().get('period') res = create_token(role_name, policies, meta, no_parent, no_default_policy, renewable, ttl, explicit_max_ttl, display_name, num_uses, period) if not res or 'auth' not in res: return_error('Could not get authentication token') auth = res['auth'] mapped_auth = { 'Token': auth.get('client_token'), 'Policy': auth.get('policies'), 'LeaseDuration': auth.get('lease_duration') } demisto.results({ 'Type': entryTypes['note'], 'Contents': res, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('Token successfully created', mapped_auth, removeNull=True), 'EntryContext': { 'HashiCorp.Auth(val.Token===obj.Token)': createContext(mapped_auth, removeNull=True) } })
def main(): try: # in order to support compression of the file compression = zipfile.ZIP_DEFLATED except Exception: compression = zipfile.ZIP_STORED zipName = None filePath = None password = None fileEntryID = demisto.args().get('entryID') if 'zipName' in demisto.args().keys(): zipName = escape_illegal_characters_in_file_name(demisto.args().get('zipName')) + '.zip' if 'password' in demisto.args().keys(): password = demisto.args().get('password') if not fileEntryID: return_error('You must set an entryID when using the zip script') res = demisto.executeCommand('getFilePath', {'id': fileEntryID}) if res[0]['Type'] == entryTypes['error']: return_error( 'Failed to get the file path for entry: ' + fileEntryID + ' the error message was ' + res[0]["Contents"]) filePath = res[0]['Contents']['path'] fileCurrentName = escape_illegal_characters_in_file_name(res[0]['Contents']['name']) if not zipName: zipName = fileCurrentName + '.zip' if not isfile(filePath): # in case that the user will send a directory return_error(fileEntryID + ' is not a file. Please recheck your input.') # copying the file to current location shutil.copy(filePath, fileCurrentName) # zipping the file if password: pyminizip.compress(fileCurrentName, zipName, password, 5) else: zf = zipfile.ZipFile(zipName, mode='w') try: zf.write(fileCurrentName, compress_type=compression) # testing for file integrity ret = zf.testzip() if ret is not None: return_error('There was a problem with the zipping, file: ' + ret + ' is corrupted') finally: zf.close() with open(zipName, 'rb') as f: file_data = f.read() demisto.results(fileResult(zipName, file_data)) results = [ { 'Type': entryTypes['note'], 'ContentsFormat': formats['json'], 'Contents': {'ZippedFiles': zipName}, 'EntryContext': { 'ZippedFiles': zipName, 'ZipFile.ZippedFile': zipName, 'File(val.EntryID=="' + fileEntryID + '").zipped': True }, 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('Zipped Files', [{'original name': fileCurrentName, 'zipped file': zipName}]) }] demisto.results(results)
def main(): if demisto.command() == 'fetch-indicators': indicator_types = argToList(demisto.params().get('indicator_type')) integration_context = get_integration_context() if not indicator_types: indicator_types = ['IP'] amount_indicators = int(demisto.getParam('amount_indicators')) demisto.info(f'starting feed with types {indicator_types}') demisto.info(f'starting feed with types {amount_indicators} size') for indicator_type in indicator_types: if int(integration_context.get(indicator_type, 0)) >= amount_indicators: continue indicators = [] csv_file = TYPE_TO_FILENAME[indicator_type] indicators_csv_file = open(Path('/perf/' + csv_file), newline='') fieldnames = argToList(demisto.params().get('fieldnames')) dialect = { 'delimiter': demisto.params().get('delimiter', ','), 'doublequote': demisto.params().get('doublequote', True), 'escapechar': demisto.params().get('escapechar', None), 'quotechar': demisto.params().get('quotechar', '"'), 'skipinitialspace': demisto.params().get('skipinitialspace', False) } iterator = build_iterator(indicators_csv_file, fieldnames, dialect) count = 0 if indicator_type == "Domain": prev_indicator = "google.com" prev_type = "Domain" elif indicator_type == "IP": prev_indicator = "8.8.8.8" prev_type = "IP" elif indicator_type == "File": prev_indicator = "82660430ab3d496ee4c8d4711e23174bbda0dbf7883cb0c0871f80851e1b34e0" prev_type = "File" elif indicator_type == "URL": prev_indicator = "https://www.google.com" prev_type = "URL" for item in iterator: if 'indicator' in item: indicator_val = item.get('indicator') if indicator_type != 'URL' else f"https://www.{item.get('indicator')}" count += 1 raw_json = dict(item) raw_json['value'] = indicator_val raw_json['type'] = indicator_type generatedDescription = "x" * int(demisto.getParam('indicators_custom_field_length')) fields = { "domainname": generatedDescription } currentIndicator = { "value": indicator_val, "type": indicator_type, "rawJSON": {}, "fields": fields } currentRelationships = [] for x in range(int(demisto.getParam('amount_relationships'))): currentRelationship = { "name": "Relates to", "reverseName": "Relates from", "type": "uses", "entityA": indicator_val, "entityAFamily": "indicator", "objectTypeA": indicator_type, "entityB": "{}".format(x) + prev_indicator, "entityBFamily": "indicator", "objectTypeB": prev_type, "fields": { "revoked": False, "firstSeenBySource": datetime.now().isoformat('T'), "lastSeenBySource": datetime.now().isoformat('T'), "description": "x" * int(demisto.getParam('relationship_description_length')) } } currentRelationships.append(currentRelationship) currentIndicator['relationships'] = currentRelationships indicators.append(currentIndicator) prev_indicator = indicator_val prev_type = indicator_type if count == amount_indicators: break else: raise Exception("abc") batch_size = int(demisto.params().get('batch_size')) batches = [] feed_start = timer() indicators = indicators[:amount_indicators] demisto.info(f'starting feed of {len(indicators)} size') for b in good_batch(indicators, batch_size): batch_start = timer() demisto.createIndicators(b) batch_end = timer() batch_time = batch_end - batch_start batch_info = create_batch(len(b), batch_time) batches.append(batch_info) feed_end = timer() demisto.info('finished feed') feed_total_time = feed_end - feed_start run_info = create_run_info(batches, len(indicators), feed_total_time) incidents = [{"name": demisto.params().get('incidents_name'), "type": "Access", "details": json.dumps(run_info)}] demisto.createIncidents(incidents) demisto.info('feed finished create result incident') integration_context[indicator_type] = amount_indicators set_integration_context(integration_context) elif demisto.command() == 'test-module': demisto.results('ok') elif demisto.command() == 'random-score-indicators': indicators = argToList(demisto.args().get('indicators')) or [] dbot_scores = [generate_dbotscore(i, get_indicator_type(i)) for i in indicators] ec = {} ec['DBotScore'] = dbot_scores md = tableToMarkdown("Indicator DBot Score", ec["DBotScore"]) demisto.results({ "Type": 1, "ContentsFormat": "json", "Contents": ec, "HumanReadable": md, "EntryContext": ec })
def main(): similar_text_field, similar_json_field, similar_categorical_field, exact_match_fields, display_fields, from_date, \ to_date, show_distance, confidence, max_incidents, query, aggregate, limit, show_actual_incident, \ incident_id, include_indicators_similarity = get_args() global_msg = "" populate_fields = similar_text_field + similar_json_field + similar_categorical_field + exact_match_fields \ + display_fields + ['id'] populate_high_level_fields = keep_high_level_field(populate_fields) incident, incident_id = load_current_incident(incident_id, populate_high_level_fields, from_date, to_date) if not incident: return_outputs_error(error_msg="%s \n" % MESSAGE_NO_CURRENT_INCIDENT % incident_id) return None, global_msg # load the related incidents populate_fields.remove('id') incidents, msg = get_all_incidents_for_time_window_and_exact_match( exact_match_fields, populate_high_level_fields, incident, from_date, to_date, query, limit) global_msg += "%s \n" % msg if not incidents: return_outputs_summary(confidence, 0, 0, [], global_msg) return_outputs_similar_incidents_empty() return None, global_msg number_incident_fetched = len(incidents) incidents_df = pd.DataFrame(incidents) incidents_df.index = incidents_df.id incidents_df = fill_nested_fields(incidents_df, incidents, similar_text_field, similar_categorical_field) # Find given fields that does not exist in the incident global_msg, incorrect_fields = find_incorrect_fields( populate_fields, incidents_df, global_msg) # remove fields that does not exist in the incidents display_fields, similar_text_field, similar_json_field, similar_categorical_field = \ remove_fields_not_in_incident(display_fields, similar_text_field, similar_json_field, similar_categorical_field, incorrect_fields=incorrect_fields) # Dumps all dict in the current incident incident_df = dumps_json_field_in_incident(incident) incident_df = fill_nested_fields(incident_df, incident, similar_text_field, similar_categorical_field) # Model prediction model = Model(p_transformation=TRANSFORMATION) model.init_prediction(incident_df, incidents_df, similar_text_field, similar_categorical_field, display_fields, similar_json_field) similar_incidents, fields_used = model.predict() if len(fields_used) == 0: global_msg += "%s \n" % MESSAGE_NO_FIELDS_USED return_outputs_summary(confidence, number_incident_fetched, 0, fields_used, global_msg) return_outputs_similar_incidents_empty() return None, global_msg # Get similarity based on indicators if include_indicators_similarity == "True": args_defined_by_user = { key: demisto.args().get(key) for key in KEYS_ARGS_INDICATORS } full_args_indicators_script = { **CONST_PARAMETERS_INDICATORS_SCRIPT, **args_defined_by_user } similar_incidents = enriched_with_indicators_similarity( full_args_indicators_script, similar_incidents) similar_incidents = prepare_incidents_for_display( similar_incidents, confidence, show_distance, max_incidents, fields_used, aggregate, include_indicators_similarity) # Filter incident to investigate incident_filter = prepare_current_incident(incident_df, display_fields, similar_text_field, similar_json_field, similar_categorical_field, exact_match_fields) # Return summary outputs of the automation number_incidents_found = len(similar_incidents) return_outputs_summary(confidence, number_incident_fetched, number_incidents_found, fields_used, global_msg) # Create context and outputs context = create_context_for_incidents(similar_incidents) return_outputs_similar_incidents(show_actual_incident, incident_filter, similar_incidents, context, TAG_INCIDENT) return similar_incidents, global_msg
def mirror_investigation(): """ Updates the integration context with a new or existing mirror. """ mirror_type = demisto.args().get('type', 'all') auto_close = demisto.args().get('autoclose', 'true') mirror_direction = demisto.args().get('direction', 'both') mirror_to = demisto.args().get('mirrorTo', 'group') channel_name = demisto.args().get('channelName', '') channel_topic = demisto.args().get('channelTopic', '') kick_admin = bool(strtobool(demisto.args().get('kickAdmin', 'false'))) investigation = demisto.investigation() if investigation.get('type') == PLAYGROUND_INVESTIGATION_TYPE: return_error('Can not perform this action in playground.') integration_context = demisto.getIntegrationContext() if not integration_context or not integration_context.get('mirrors', []): mirrors: list = [] else: mirrors = json.loads(integration_context['mirrors']) if not integration_context or not integration_context.get( 'conversations', []): conversations: list = [] else: conversations = json.loads(integration_context['conversations']) investigation_id = investigation.get('id') users = investigation.get('users') slack_users = search_slack_users(users) send_first_message = False users_to_invite = list(map(lambda u: u.get('id'), slack_users)) current_mirror = list( filter(lambda m: m['investigation_id'] == investigation_id, mirrors)) channel_filter: list = [] if channel_name: channel_filter = list( filter(lambda m: m['channel_name'] == channel_name, mirrors)) if not current_mirror: channel_name = channel_name or 'incident-{}'.format(investigation_id) if not channel_filter: if mirror_to == 'channel': conversation = CHANNEL_CLIENT.channels_create( name=channel_name).get('channel', {}) else: conversation = CHANNEL_CLIENT.groups_create( name=channel_name).get('group', {}) conversation_name = conversation.get('name') conversation_id = conversation.get('id') conversations.append(conversation) send_first_message = True else: mirrored_channel = channel_filter[0] conversation_id = mirrored_channel['channel_id'] conversation_name = mirrored_channel['channel_name'] mirror = { 'channel_id': conversation_id, 'channel_name': conversation_name, 'investigation_id': investigation.get('id'), 'mirror_type': mirror_type, 'mirror_direction': mirror_direction, 'mirror_to': mirror_to, 'auto_close': bool(strtobool(auto_close)), 'mirrored': False } else: mirror = mirrors.pop(mirrors.index(current_mirror[0])) conversation_id = mirror['channel_id'] if mirror_type: mirror['mirror_type'] = mirror_type if auto_close: mirror['auto_close'] = bool(strtobool(auto_close)) if mirror_direction: mirror['mirror_direction'] = mirror_direction if mirror_to and mirror['mirror_to'] != mirror_to: return_error('Cannot change the Slack channel type from Demisto.') if channel_name: return_error('Cannot change the Slack channel name.') if channel_topic: return_error('Cannot change the Slack channel topic.') conversation_name = mirror['channel_name'] mirror['mirrored'] = False set_topic = False if channel_topic: set_topic = True else: mirror_name = 'incident-{}'.format(investigation_id) channel_filter = list( filter(lambda m: m['channel_name'] == conversation_name, mirrors)) if 'channel_topic' in mirror: channel_topic = mirror['channel_topic'] elif channel_filter: channel_mirror = channel_filter[0] channel_topic = channel_mirror['channel_topic'] else: channel_topic = '' mirrored_investigations_ids = list( map(lambda m: 'incident-{}'.format(m['investigation_id']), channel_filter)) if not channel_topic or channel_topic.find('incident-') != -1: new_topic = ', '.join(mirrored_investigations_ids + [mirror_name]) if channel_topic != new_topic: channel_topic = new_topic set_topic = True if set_topic: CHANNEL_CLIENT.conversations_setTopic(channel=conversation_id, topic=channel_topic) mirror['channel_topic'] = channel_topic if mirror_type != 'none': if integration_context.get('bot_id'): bot_id = integration_context['bot_id'] else: bot_id = get_bot_id() users_to_invite += [bot_id] invite_users_to_conversation(conversation_id, users_to_invite) integration_context['bot_id'] = bot_id mirrors.append(mirror) set_to_latest_integration_context('mirrors', mirrors) set_to_latest_integration_context('conversations', conversations) if kick_admin: CHANNEL_CLIENT.conversations_leave(channel=conversation_id) if send_first_message: CLIENT.chat_postMessage( channel=conversation_id, text='This is the mirrored channel for incident {}.'.format( investigation_id)) demisto.results('Investigation mirrored successfully, channel: {}'.format( conversation_name))
def slack_send(): """ Sends a message to slack """ message = demisto.args().get('message', '') to = demisto.args().get('to') channel = demisto.args().get('channel') group = demisto.args().get('group') message_type = demisto.args().get('messageType', '') # From server original_message = demisto.args().get('originalMessage', '') # From server entry = demisto.args().get('entry') ignore_add_url = demisto.args().get( 'ignoreAddURL', False) or demisto.args().get('IgnoreAddURL', False) thread_id = demisto.args().get('threadID', '') severity = demisto.args().get('severity') # From server if message_type == MIRROR_TYPE and original_message.find( MESSAGE_FOOTER) != -1: # return so there will not be a loop of messages return if (to and group) or (to and channel) or (to and channel and group): return_error('Only one destination can be provided.') if severity: try: severity = int(severity) except Exception: severity = None pass if channel == INCIDENT_NOTIFICATION_CHANNEL or ( not channel and message_type == INCIDENT_OPENED): channel = DEDICATED_CHANNEL if channel == DEDICATED_CHANNEL and ( (severity is not None and severity < SEVERITY_THRESHOLD) or not NOTIFY_INCIDENTS): channel = None if not (to or group or channel): return_error('Either a user, group or channel must be provided.') response = slack_send_request(to, channel, group, entry, ignore_add_url, thread_id, message=message) if response: thread = response.get('ts') demisto.results({ 'Type': entryTypes['note'], 'Contents': 'Message sent to Slack successfully.\nThread ID is: {}'.format( thread), 'ContentsFormat': formats['text'], 'EntryContext': { 'Slack.Thread(val.ID===obj.ID)': { 'ID': thread }, } }) else: demisto.results('Could not send the message to Slack.')
regex_result = regex.search(data, regex_result.span()[1]) else: regex_result = regex.search(data) if regex_result: results = regex_result.group(group) results = results[0] if len(results) == 1 else results if results: human_readable = json.dumps(results) else: human_readable = 'Regex does not match.' context = {} if context_key: context = {context_key: results} # clearing the context field in order to override it instead of appending it. demisto.setContext('MatchRegex.results', results) return CommandResults(readable_output=human_readable, outputs=context, raw_response=results, ) if __name__ in ('__main__', '__builtin__', 'builtins'): try: return_results(main(demisto.args())) except Exception as exc: return_error(str(exc), error=exc)
from CommonServerPython import * from CommonServerUserPython import * import pandas as pd from bs4 import BeautifulSoup from sklearn.feature_extraction.text import CountVectorizer from numpy import dot from numpy.linalg import norm from email.utils import parseaddr import tldextract from urllib.parse import urlparse import re no_fetch_extract = tldextract.TLDExtract(suffix_list_urls=None) pd.options.mode.chained_assignment = None # default='warn' SIMILARITY_THRESHOLD = float(demisto.args().get('threshold', 0.97)) CLOSE_TO_SIMILAR_DISTANCE = 0.2 EMAIL_BODY_FIELD = 'emailbody' EMAIL_SUBJECT_FIELD = 'emailsubject' EMAIL_HTML_FIELD = 'emailbodyhtml' FROM_FIELD = 'emailfrom' FROM_DOMAIN_FIELD = 'fromdomain' MERGED_TEXT_FIELD = 'mereged_text' MIN_TEXT_LENGTH = 50 DEFAULT_ARGS = { 'limit': '1000', 'incidentTypes': 'Phishing', 'exsitingIncidentsLookback': '100 days ago', } FROM_POLICY_TEXT_ONLY = 'TextOnly'
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 args = demisto.args() DESCRIPTION = [ 'The playbook: "{}" may be a copy of a built-in playbook, you may consider using out of the box playbooks', 'The playbook: "{}" is using a sleep command, you may consider changing it', 'The playbook: "{}" is using the setIncident command 4 times or more, which could result with DB version violation', 'The playbook: "{}" is using the "EmailAskUser" functionality, you may consider switching it to Data Collection', 'The playbook: "{}" is using over 30 tasks, you may want to use sub-playbooks for better ' + 'organization of playbook tasks', ] RESOLUTION = [ "Consider using out of the box playbooks", "Consider changing it to prefered methods such as: https://xsoar.pan.dev/docs/playbooks/generic-polling " + "https://knowledgebase.paloaltonetworks.com/KCSArticleDetail?id=kA10g000000PPOaCAO", "Consider joining some of the setIncident tasks", "Communication Tasks: https://docs.paloaltonetworks.com/cortex/cortex-xsoar/6-0/" + "cortex-xsoar-admin/playbooks/playbook-tasks/communication-tasks", "Sub-playbook Tutorial: https://docs.paloaltonetworks.com/cortex/cortex-xsoar/6-0/" + "cortex-xsoar-admin/playbooks/configure-a-sub-playbook-loop/sub-playbook-tutorial", ] Thresholds = { "CustomPlaybookSetIncidentCount": 4, "CustomPlaybookLength": 30, }
import demistomock as demisto from CommonServerPython import * import re def main(args): value = args['value'] replace_with = args['replace_with'] output = list() start = 0 try: regex = re.compile(args['regex']) except (re.error, TypeError): raise DemistoException('Could not compile regex.') for match in regex.finditer(value): for index, _ in enumerate(match.groups(), start=1): end = match.start(index) output.append(value[start:end]) output.append(replace_with) start = match.end(index) output.append(value[start:]) # Handling the tail of the string return ''.join(output) if __name__ in ["__builtin__", "builtins", "__main__"]: result = main(demisto.args()) demisto.results(result)
def main(): try: args = demisto.args() method = args.get('method', '') full_url = args.get('url', '') body = args.get('body', '') request_content_type = args.get('request_content_type', '') response_content_type = args.get('response_content_type', '') parse_response_as = args.get('parse_response_as', RAW_RESPONSE) params = args.get('params', {}) headers = args.get('headers', {}) headers = create_headers(headers, request_content_type, response_content_type) auth = tuple(argToList(args.get('auth_credentials', None))) save_as_file = args.get('save_as_file', 'no') file_name = args.get('filename', 'http-file') timeout = arg_to_number(args.get('timeout', 10)) timeout_between_retries = args.get('timeout_between_retries', 5) retry_count = arg_to_number(args.get('retry_count', 3)) proxy = argToBoolean(args.get('proxy', False)) verify = argToBoolean(not args.get('unsecure', False)) client = Client(base_url=full_url, auth=auth, verify=verify, proxy=proxy) kwargs = { 'method': method, 'full_url': full_url, 'headers': headers, 'data': body, 'timeout': timeout, 'params': params, 'backoff_factor': timeout_between_retries } retry_on_status = args.get('retry_on_status', None) raise_on_status = True if retry_on_status else False retry_status_list = format_status_list(argToList(retry_on_status)) if raise_on_status: kwargs.update({ 'retries': retry_count, 'status_list_to_retry': retry_status_list, 'raise_on_status': raise_on_status }) enable_redirect = argToBoolean(args.get('enable_redirect', True)) if not enable_redirect: kwargs.update({ 'allow_redirects': enable_redirect }) res = client.http_request(**kwargs) parsed_res = get_parsed_response(res, parse_response_as) if save_as_file == 'yes': return fileResult(file_name, res.content) outputs = build_outputs(parsed_res, res) return CommandResults( readable_output=f"Sent a {method} request to {full_url}", outputs_prefix='HttpRequest.Response', outputs=outputs, raw_response={'data': parsed_res} ) except Exception as e: return_error(f'Failed to execute HttpV2 script. Error: {str(e)}')
def get_args(): # type: ignore """ Gets argument of this automation :return: Argument of this automation """ use_all_field = demisto.args().get('useAllFields') if use_all_field == 'True': similar_text_field = [] similar_json_field = ['CustomFields'] similar_categorical_field = [] exact_match_fields = ['type'] else: similar_text_field = demisto.args().get('similarTextField', '').split(',') similar_text_field = extract_fields_from_args(similar_text_field) similar_categorical_field = demisto.args().get( 'similarCategoricalField', '').split(',') similar_categorical_field = extract_fields_from_args( similar_categorical_field) similar_json_field = demisto.args().get('similarJsonField', '').split(',') similar_json_field = extract_fields_from_args(similar_json_field) exact_match_fields = demisto.args().get('fieldExactMatch', '').split(',') exact_match_fields = extract_fields_from_args(exact_match_fields) display_fields = demisto.args().get('fieldsToDisplay', '').split(',') display_fields = [x.strip() for x in display_fields if x] display_fields = list(set(['id', 'created', 'name'] + display_fields)) display_fields = list(dict.fromkeys(display_fields)) from_date = demisto.args().get('fromDate') to_date = demisto.args().get('toDate') show_similarity = demisto.args().get('showIncidentSimilarityForAllFields') confidence = float(demisto.args().get('minimunIncidentSimilarity')) max_incidents = int(demisto.args().get('maxIncidentsToDisplay')) query = demisto.args().get('query') aggregate = demisto.args().get('aggreagateIncidentsDifferentDate') limit = int(demisto.args()['limit']) show_actual_incident = demisto.args().get('showCurrentIncident') incident_id = demisto.args().get('incidentId') include_indicators_similarity = demisto.args().get( 'includeIndicatorsSimilarity') return similar_text_field, similar_json_field, similar_categorical_field, exact_match_fields, display_fields, \ from_date, to_date, show_similarity, confidence, max_incidents, query, aggregate, limit, \ show_actual_incident, incident_id, include_indicators_similarity
def main(): incident_type = demisto.args().get("incidentType", "Vulnerability") max_file_size = int(demisto.args().get("maxFileSize", 1024**2)) min_severity = int(demisto.args().get("minSeverity", 1)) file_entry = demisto.getFilePath(demisto.args().get("entryID")) with open(file_entry['path'], 'r') as f: data = f.read(max_file_size) if data: report = json.loads(xml2json(data)) generation_date = demisto.get( report, "ASSET_DATA_REPORT.HEADER.GENERATION_DATETIME") # Get asset list asset_list = demisto.get(report, "ASSET_DATA_REPORT.HOST_LIST.HOST") if not asset_list: demisto.results({ "Type": entryTypes["note"], "ContentsFormat": formats["text"], "Contents": 'No vulnerable assets were found' }) sys.exit(0) if not isinstance(asset_list, list): asset_list = [asset_list] # Get QIDs only if over relevant severity general_vulnerabilities = argToList( demisto.get( report, "ASSET_DATA_REPORT.GLOSSARY.VULN_DETAILS_LIST.VULN_DETAILS")) if not isinstance(general_vulnerabilities, list): general_vulnerabilities = [general_vulnerabilities] # Get list of QID with severity >= min_severity qid_severity = [ demisto.get(vulnerability, "QID.#text") for vulnerability in general_vulnerabilities if demisto.get(vulnerability, 'SEVERITY') and ( int(demisto.get(vulnerability, 'SEVERITY')) >= min_severity) ] for asset in asset_list: # Get Asset ID from Qualys ip = demisto.get(asset, "IP") if not ip: demisto.results({ "Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": 'No IP was found for asset {0}'.format(str(asset)) }) sys.exit(0) asset_id = get_asset_id_for_ip(ip) if not asset_id: demisto.results({ "Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": 'No ID was found for asset {0}'.format(str(asset)) }) sys.exit(0) # Get Asset vulnerability list vulnerabilities = argToList( demisto.get(asset, "VULN_INFO_LIST.VULN_INFO")) if not isinstance(vulnerabilities, list): vulnerabilities = [vulnerabilities] qids = map( lambda vulnerability: demisto.get(vulnerability, "QID.#text"), vulnerabilities) # Get only the QIDs that exists in asset and has severity >= min_severity qids = list(set(qids) & set(qid_severity)) for qid in qids: # Search for existing open incidents with the same Vendor ID and Asset ID. # Will open a new incident only if such an incident not exists. resp = demisto.executeCommand( "getIncidents", { "query": "vendorid: {0} and assetid: {1} and --status:Closed". format(qid, asset_id) }) if isError(resp[0]): demisto.results(resp) sys.exit(0) incident_number = demisto.get(resp[0], "Contents.total") try: incident_number = int(incident_number) except Exception: demisto.results({ "Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": 'Error while searching the incident repository' }) sys.exit(0) if incident_number == 0: # Create incident demisto.executeCommand( "createNewIncident", { "name": "Vulnerability - Asset {0} QID {1} - {2}".format( asset_id, qid, generation_date), "vendorid": str(qid), "type": incident_type, "assetid": str(asset_id) }) demisto.results("Done.") else: demisto.results({ "Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": 'No data could be read.' })
def main(): file_entry_id = demisto.args()['EntryID'] get_exif_tags(file_entry_id)
def main() -> None: """main function, parses params and runs command functions """ params = demisto.params() command = demisto.command() args = demisto.args() demisto.debug(f'Command being called is {command}') try: client = Client( app_id=params.get('app_id', ''), subscription_id=params.get('subscription_id', ''), resource_group_name=params.get('resource_group_name', ''), verify=not params.get('insecure', False), proxy=params.get('proxy', False), azure_ad_endpoint=params.get('azure_ad_endpoint', 'https://login.microsoftonline.com') or 'https://login.microsoftonline.com') if command == 'test-module': return_error( 'Please run `!azure-sql-auth-start` and `!azure-sql-auth-complete` to log in. ' 'You can validate the connection by running `!azure-sql-auth-test`\n ' 'For more details press the (?) button.') elif command == 'azure-sql-servers-list': return_results(azure_sql_servers_list_command(client, args)) elif command == 'azure-sql-db-list': return_results(azure_sql_db_list_command(client, args)) elif command == 'azure-sql-db-audit-policy-list': return_results(azure_sql_db_audit_policy_list_command( client, args)) elif command == 'azure-sql-db-audit-policy-create-update': return_results( azure_sql_db_audit_policy_create_update_command(client, args)) elif command == 'azure-sql-db-threat-policy-get': return_results(azure_sql_db_threat_policy_get_command( client, args)) elif command == 'azure-sql-db-threat-policy-create-update': return_results( azure_sql_db_threat_policy_create_update_command(client, args)) elif command == 'azure-sql-auth-start': return_results(start_auth(client)) elif command == 'azure-sql-auth-complete': return_results(complete_auth(client)) elif command == 'azure-sql-auth-reset': return_results(reset_auth(client)) elif command == 'azure-sql-auth-test': return_results(test_connection(client)) # Log exceptions and return errors except Exception as e: return_error( f'Failed to execute {demisto.command()} command.\nError:\n{str(e)}' )
def main() -> None: try: api_key = demisto.params().get('apikey') base_url = urljoin(demisto.params()['url'], '/api/') verify_certificate = not demisto.params().get('insecure', False) first_fetch_time = arg_to_timestamp( arg=demisto.params().get('first_fetch', '1 days'), arg_name='First fetch time', required=True ) assert isinstance(first_fetch_time, int) proxy = demisto.params().get('proxy', False) page = demisto.args().get('page', "1") page_count_no = demisto.args().get('max', "25") demisto.debug(f'Command being called is {demisto.command()}') params = {'page': page, 'max': page_count_no} headers = { 'Authorization': f'Bearer {api_key}' } client = Client( base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy) if demisto.command() == 'test-module': result = test_module_command(client) return_results(result) elif demisto.command() == 'fetch-incidents': # Set and define the fetch incidents command to run after activated via integration settings. fetch_incident_command = demisto.params().get('fetch_incident_command') max_results = arg_to_int( arg=demisto.params().get('max_fetch'), arg_name='max_fetch', required=False ) if not max_results or max_results > MAX_INCIDENTS_TO_FETCH: max_results = MAX_INCIDENTS_TO_FETCH next_run, incidents = fetch_incidents( client=client, max_results=max_results, last_run=demisto.getLastRun(), # getLastRun() gets the last run dict first_fetch_time=first_fetch_time, command_type=fetch_incident_command ) demisto.setLastRun(next_run) demisto.incidents(incidents) elif demisto.command() == 'gra-fetch-users': fetch_records(client, '/users', 'Gra.Users', 'employeeId', params) elif demisto.command() == 'gra-fetch-accounts': fetch_records(client, '/accounts', 'Gra.Accounts', 'id', params) elif demisto.command() == 'gra-fetch-active-resource-accounts': active_resource_url = '/resources/' + demisto.args().get('resource_name', 'Windows Security') + '/accounts' fetch_records(client, active_resource_url, 'Gra.Active.Resource.Accounts', 'id', params) elif demisto.command() == 'gra-fetch-user-accounts': user_account_url = '/users/' + demisto.args().get('employee_id') + '/accounts' fetch_records(client, user_account_url, 'Gra.User.Accounts', 'id', params) elif demisto.command() == 'gra-fetch-resource-highrisk-accounts': res_name = demisto.args().get('Resource_name', 'Windows Security') high_risk_account_resource_url = '/resources/' + res_name + '/accounts/highrisk' fetch_records(client, high_risk_account_resource_url, 'Gra.Resource.Highrisk.Accounts', 'id', params) elif demisto.command() == 'gra-fetch-hpa': fetch_records(client, '/accounts/highprivileged', 'Gra.Hpa', 'id', params) elif demisto.command() == 'gra-fetch-resource-hpa': resource_hpa = '/resources/' + demisto.args().get('resource_name', 'Windows Security') + '/accounts/highprivileged' fetch_records(client, resource_hpa, 'Gra.Resource.Hpa', 'id', params) elif demisto.command() == 'gra-fetch-orphan-accounts': fetch_records(client, '/accounts/orphan', 'Gra.Orphan.Accounts', 'id', params) elif demisto.command() == 'gra-fetch-resource-orphan-accounts': resource_orphan = '/resources/' + demisto.args().get('resource_name', 'Windows Security') + '/accounts/orphan' fetch_records(client, resource_orphan, 'Gra.Resource.Orphan.Accounts', 'id', params) elif demisto.command() == 'gra-user-activities': user_activities_url = '/user/' + demisto.args().get('employee_id') + '/activity' fetch_records(client, user_activities_url, 'Gra.User.Activity', 'employee_id', params) elif demisto.command() == 'gra-fetch-users-details': fetch_records(client, '/users/' + demisto.args().get('employee_id'), 'Gra.User', 'employeeId', params) elif demisto.command() == 'gra-highRisk-users': fetch_records(client, '/users/highrisk', 'Gra.Highrisk.Users', 'employeeId', params) elif demisto.command() == 'gra-cases': cases_url = '/cases/' + demisto.args().get('status') fetch_records(client, cases_url, 'Gra.Cases', 'caseId', params) elif demisto.command() == 'gra-user-anomalies': anomaly_url = '/users/' + demisto.args().get('employee_id') + '/anomalies/' fetch_records(client, anomaly_url, 'Gra.User.Anomalies', 'anomaly_name', params) # Log exceptions and return errors except Exception as e: demisto.error(traceback.format_exc()) # print the traceback return_error(f'Failed to execute {demisto.command()} command.\nError:\n{str(e)}')
def get_machines_command(): machines = get_machines()['value'] hostname = demisto.args().get('hostname') ip = demisto.args().get('ip') risk_score = demisto.args().get('risk_score') health_status = demisto.args().get('health_status') output = [] endpoint_context = [] for machine in machines: computer_dns_name = machine['computerDnsName'] last_external_ip = machine['lastExternalIpAddress'] machine_risk_score = machine['riskScore'] machine_health_status = machine['healthStatus'] if (hostname and hostname != computer_dns_name) or (ip and ip != last_external_ip) or \ (risk_score and risk_score != machine_risk_score) or \ (health_status and health_status != machine_health_status): continue current_machine_output = { 'ComputerDNSName': computer_dns_name, 'ID': machine['id'], 'AgentVersion': machine['agentVersion'], 'FirstSeen': machine['firstSeen'], 'LastSeen': machine['lastSeen'], 'HealthStatus': machine_health_status, 'IsAADJoined': machine['isAadJoined'], 'LastExternalIPAddress': last_external_ip, 'LastIPAddress': machine['lastIpAddress'], 'Tags': machine['machineTags'], 'OSBuild': machine['osBuild'], 'OSPlatform': machine['osPlatform'], 'RBACGroupID': machine['rbacGroupId'], 'RiskScore': machine_risk_score } current_endpoint_output = { 'Hostname': machine['computerDnsName'], 'IPAddress': machine['lastExternalIpAddress'], 'OS': machine['osPlatform'] } rbac_group_name = machine.get('rbacGroupName') if rbac_group_name: current_machine_output['RBACGroupName'] = rbac_group_name aad_device_id = machine.get('aadDeviceId') if aad_device_id: current_machine_output['AADDeviceID'] = aad_device_id os_version = machine.get('osVersion') if os_version: current_machine_output['OSVersion'] = os_version current_endpoint_output['OSVersion'] = os_version output.append(current_machine_output) endpoint_context.append(current_endpoint_output) if output: ec = { 'MicrosoftATP.Machine(val.ID && val.ID === obj.ID)': output, 'Endpoint(val.Hostname && val.Hostname === obj.Hostname)': endpoint_context } entry = { 'Type': entryTypes['note'], 'Contents': machines, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('Windows Defender ATP machines', output, removeNull=True), 'EntryContext': ec } else: entry = 'No results found' # type: ignore demisto.results(entry)
import demistomock as demisto from CommonServerPython import * from CommonServerUserPython import * import os import base64 from sane_doc_reports.main import run OUTPUT_FILE_PATH = 'out.docx' try: sane_json_b64 = demisto.args().get('sane_docx_report_base64', '').encode('utf-8') orientation = demisto.args().get('orientation', 'portrait').encode('utf-8') paper_size = demisto.args().get('paperSize', 'A4').encode('utf-8') with open('sane.json', 'wb') as f: f.write(base64.b64decode(sane_json_b64)) run( 'sane.json', OUTPUT_FILE_PATH, { 'orientation': orientation.decode('utf-8', 'ignore'), 'paper_size': paper_size.decode('utf-8', 'ignore') }) with open(OUTPUT_FILE_PATH, 'rb') as f: encoded = base64.b64encode(f.read()).decode('utf-8', 'ignore') os.remove(OUTPUT_FILE_PATH) return_outputs(readable_output='Successfully generated docx', outputs={}, raw_response={'data': encoded}) except Exception as e: err = repr(e)
def main(): entry_id = demisto.args()["entryID"] # File entity pdf_file = {"EntryID": entry_id} # URLS urls_ec = [] folders_to_remove = [] try: path = demisto.getFilePath(entry_id).get('path') if path: try: output_folder = "ReadPDF" os.makedirs(output_folder) except OSError as e: if e.errno != errno.EEXIST: raise e pass try: folders_to_remove.append(output_folder) cpy_file_path = f'{output_folder}/ReadPDF.pdf' shutil.copy(path, cpy_file_path) # Get metadata: metadata = get_pdf_metadata(cpy_file_path) # Get urls from the binary file binary_file_urls = get_urls_from_binary_file(cpy_file_path) # Get text: pdf_text_output_path = f'{output_folder}/PDFText.txt' text = get_pdf_text(cpy_file_path, pdf_text_output_path) # Get URLS + emails: pdf_html_content = get_pdf_htmls_content( cpy_file_path, output_folder) urls = re.findall(urlRegex, pdf_html_content) urls_set = set(urls) emails = re.findall(EMAIL_REGXEX, pdf_html_content) urls_set = urls_set.union(binary_file_urls) urls_set = urls_set.union(set(emails)) # this url is always generated with the pdf html file, and that's why we remove it urls_set.remove('http://www.w3.org/1999/xhtml') for url in urls_set: urls_ec.append({"Data": url}) # Get images: images = get_images_paths_in_path(output_folder) except Exception as e: demisto.results({ "Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": f"Could not load pdf file in EntryID {entry_id}\nError: {str(e)}" }) raise e readpdf_entry_object = build_readpdf_entry_object( pdf_file, metadata, text, urls_ec, images) demisto.results(readpdf_entry_object) else: demisto.results({ "Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": f"EntryID {entry_id} path could not be found" }) except ShellException as e: mark_suspicious( f'The script failed read PDF file due to an error: {str(e)}', entry_id) except Exception as e: return_error_without_exit( f'The script failed read PDF file due to an error: {str(e)}') finally: os.chdir(ROOT_PATH) for folder in folders_to_remove: shutil.rmtree(folder)
def main(): try: sane_json_b64 = demisto.args().get('sane_pdf_report_base64', '').encode('utf-8') orientation = demisto.args().get('orientation', 'portrait') resourceTimeout = demisto.args().get('resourceTimeout', '4000') reportType = demisto.args().get('reportType', 'pdf') headerLeftImage = demisto.args().get('customerLogo', '') headerRightImage = demisto.args().get('demistoLogo', '') pageSize = demisto.args().get('paperSize', 'letter') disableHeaders = demisto.args().get('disableHeaders', '') # Note: After headerRightImage the empty one is for legacy argv in server.js extra_cmd = f"{orientation} {resourceTimeout} {reportType} " + \ f'"{headerLeftImage}" "{headerRightImage}" "" ' + \ f'"{pageSize}" "{disableHeaders}"' isMDImagesSupported = is_demisto_version_ge(MD_IMAGE_SUPPORT_MIN_VER) if isMDImagesSupported: # start the server in a background thread demisto.debug('Starting markdown artifacts http server...') threading.Thread(target=startServer).start() time.sleep(5) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) result = sock.connect_ex(('localhost', MD_HTTP_PORT)) if result == 0: demisto.debug('Server is running') sock.close() else: demisto.error('Markdown artifacts server is not responding') # add md server address mdServerAddress = f'http://localhost:{MD_HTTP_PORT}' extra_cmd += f' "" "" "{mdServerAddress}"' # Generate a random input file so we won't override on concurrent usage input_id = random_string() input_file = INPUT_FILE_PATH.format(id=input_id) with open(WORKING_DIR / input_file, 'wb') as f: f.write(base64.b64decode(sane_json_b64)) # Generate a random output file so we won't override on concurrent usage output_id = random_string() output_file = OUTPUT_FILE_PATH.format(id=output_id) cmd = ['./reportsServer', input_file, output_file, 'dist' ] + shlex.split(extra_cmd) # Logging things for debugging params = f'[orientation="{orientation}",' \ f' resourceTimeout="{resourceTimeout}",' \ f' reportType="{reportType}", headerLeftImage="{headerLeftImage}",' \ f' headerRightImage="{headerRightImage}", pageSize="{pageSize}",' \ f' disableHeaders="{disableHeaders}"' if isMDImagesSupported: params += f', markdownArtifactsServerAddress="{mdServerAddress}"' LOG(f"Sane-pdf parameters: {params}]") cmd_string = " ".join(cmd) LOG(f"Sane-pdf cmd: {cmd_string}") LOG.print_log() # Execute the report creation out = subprocess.check_output(cmd, cwd=WORKING_DIR, stderr=subprocess.STDOUT) LOG(f"Sane-pdf output: {str(out)}") abspath_output_file = WORKING_DIR / output_file with open(abspath_output_file, 'rb') as f: encoded = base64.b64encode(f.read()).decode('utf-8', 'ignore') os.remove(abspath_output_file) return_outputs(readable_output='Successfully generated pdf', outputs={}, raw_response={'data': encoded}) except subprocess.CalledProcessError as e: tb = traceback.format_exc() wrap = "=====sane-pdf-reports error=====" err = f'{wrap}\n{tb}{wrap}, process error: {e.output}\n' return_error( f'[SanePdfReports Automation Error - CalledProcessError] - {err}') except Exception: tb = traceback.format_exc() wrap = "=====sane-pdf-reports error=====" err = f'{wrap}\n{tb}{wrap}\n' return_error(f'[SanePdfReports Automation Error - Exception] - {err}') finally: quit_driver_and_reap_children(isMDImagesSupported)
tableToMarkdown("AbuseIPDB report categories", categories, removeNull=True), 'EntryContext': { 'AbuseIPDB.Categories(val && val == obj)': createContext(categories, removeNull=True), } } return entry try: if demisto.command() == 'test-module': # Tests connectivity and credentails on login test_module() elif demisto.command() == 'ip': demisto.results(check_ip_command(**demisto.args())) elif demisto.command() == 'abuseipdb-check-cidr-block': demisto.results(check_block_command(**demisto.args())) elif demisto.command() == 'abuseipdb-report-ip': demisto.results(report_ip_command(**demisto.args())) elif demisto.command() == 'abuseipdb-get-blacklist': demisto.results(get_blacklist_command(**demisto.args())) elif demisto.command() == 'abuseipdb-get-categories': demisto.results( get_categories_command(**demisto.args())) # type:ignore except Exception as e: LOG.print_log() return_error(e.message)
def enable_engine_command(): path = demisto.args()['path'] engine_type = demisto.args()['type'] description = demisto.args().get('description') default_lease_ttl = demisto.args().get('default_lease_ttl') max_lease_ttl = demisto.args().get('max_lease_ttl') force_no_cache = demisto.args().get('force_no_cache') audit_non_hmac_request_keys = argToList(demisto.args().get( 'audit_non_hmac_request_keys', [])) audit_non_hmac_response_keys = argToList(demisto.args().get( 'audit_non_hmac_response_keys', [])) listing_visibility = demisto.args().get('listing_visibility') passthrough_request_headers = argToList(demisto.args().get( 'passthrough_request_headers', [])) kv_version = demisto.args().get('kv_version') local = demisto.args().get('local') seal_wrap = demisto.args().get('seal_wrap') enable_engine(path, engine_type, description, default_lease_ttl, max_lease_ttl, force_no_cache, audit_non_hmac_request_keys, audit_non_hmac_response_keys, listing_visibility, passthrough_request_headers, kv_version, local, seal_wrap) demisto.results('Engine enabled successfully')
def ip(): ip = demisto.args()['ip'] # output vars result_indicator = [] # type: list miner_name = '' dbotscore = 0 indicator_context_data = {} # type: dict entry_context = {} # type: dict # search for indicator in all miners defined by user for blacklist in BLACKLISTS: result_indicator = get_indicators_from_miner(blacklist, ip) if result_indicator: dbotscore = 3 break if dbotscore != 3: for whitelist in WHITELISTS: result_indicator = get_indicators_from_miner(whitelist, ip) if result_indicator: dbotscore = 1 break # start building output and context dbotscore_list = { 'Indicator': ip, 'Type': 'ip', 'Vendor': 'Palo Alto MineMeld', 'Score': dbotscore } if result_indicator: miner_name = result_indicator[0]['miner'] # add only malicious to context if dbotscore == 3: indicator_context_data = { 'MineMeld': { 'Indicators': result_indicator }, 'Malicious': { 'Vendor': 'Palo Alto MineMeld', 'Description': 'Indicator was found in MineMeld\'s blacklist: {}'.format( miner_name) }, 'Address': ip } else: indicator_context_data = { 'MineMeld': { 'Miner': { 'name': miner_name }, 'Indicators': result_indicator }, 'Address': ip } entry_context = { 'DBotScore': dbotscore_list, outputPaths['ip']: indicator_context_data, 'MineMeld.Indicators(val.indicator == obj.indicator)': result_indicator, 'MineMeld.Miner(val.name == obj.name)': { 'name': miner_name }, } result_text = 'MineMeld IP found at miner: {}'.format(miner_name) else: result_text = 'MineMeld IP severity - unknown' entry_context = { 'DBotScore': dbotscore_list, 'MineMeld.Indicators(val.indicator == obj.indicator)': result_indicator, 'MineMeld.Miner(val.name == obj.name)': { 'name': miner_name }, } demisto.results({ 'Type': entryTypes['note'], 'Contents': result_indicator, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown(result_text, result_indicator, ['indicator', 'type', 'comment']), 'EntryContext': entry_context })
def disable_engine_command(): path = demisto.args()['path'] disable_engine(path) demisto.results('Engine disabled successfully')
ec = {'AWS.Athena.Query(val.QueryExecutionId === obj.QueryExecutionId)': response} human_readable = tableToMarkdown('AWS Athena Query', response) return_outputs(human_readable, ec) """COMMAND BLOCK""" try: LOG('Command being called is {command}'.format(command=demisto.command())) if demisto.command() == 'test-module': client = aws_session() response = client.list_named_queries() if response['ResponseMetadata']['HTTPStatusCode'] == 200: demisto.results('ok') elif demisto.command() == 'aws-athena-start-query': start_query_execution_command(demisto.args()) elif demisto.command() == 'aws-athena-stop-query': stop_query_command(demisto.args()) elif demisto.command() == 'aws-athena-get-query-execution': get_query_execution_command(demisto.args()) elif demisto.command() == 'aws-athena-get-query-results': get_query_results_command(demisto.args()) except ResponseParserError as e: return_error('Could not connect to the AWS endpoint. Please check that the region is valid.\n {error}'.format( error=type(e))) LOG(e)
def query_logs_command(): ''' Return the result of querying the Logging service ''' args = demisto.args() start_time = args.get('startTime') end_time = args.get('endTime') time_range = args.get('timeRange') time_value = args.get('rangeValue') if (time_range): if (time_value): service_end_date = datetime.now() service_start_date = get_start_time(time_range, int(time_value)) else: raise Exception( 'Enter timeRange and timeValue, or startTime and endTime') else: # parses user input to datetime object service_start_date = datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S') service_end_date = datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S') # transforms datetime object to epoch time service_start_date_epoch = int(service_start_date.strftime('%s')) service_end_date_epoch = int(service_end_date.strftime('%s')) query = args.get('query') if ('limit' not in query.lower()): query += ' LIMIT 100' query_data = { "query": query, "startTime": service_start_date_epoch, "endTime": service_end_date_epoch, } response = query_loggings(query_data) try: result = response.json()['result'] pages = result['esResult']['hits']['hits'] table_name = result['esQuery']['table'][0].split('.')[1] except ValueError: raise Exception('Failed to parse the response from Cortex') output = [] for page in pages: row_contents = page.get('_source') row_contents['id'] = page.get('_id') row_contents['score'] = page.get('_score') transformed_row = transform_row_keys(row_contents) output.append(transformed_row) screened_results = results_screener('common', output) entry = { 'Type': entryTypes['note'], 'Contents': output, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('Logs ' + table_name + ' table', screened_results), 'EntryContext': { 'Cortex.Logging(val.id===obj.id)': output } } return entry
def main(): """ PARSE AND VALIDATE INTEGRATION PARAMS """ params = demisto.params() api_token = params.get('api-token') verify_certificate = not params.get('insecure', False) proxy = handle_proxy() LOG(f'Command being called is {demisto.command()}') try: client = Client(api_token=api_token, verify=verify_certificate, proxy=proxy) if demisto.command() == 'test-module': # This is the call made when pressing the integration Test button. result = test_module(client) return_results(result) elif demisto.command() == 'fetch-incidents': demisto.incidents(list_recent_jobs(client, params)) elif demisto.command() == 'twinwave-get-engines': return_results(get_engines(client)) elif demisto.command() == 'twinwave-submit-url': return_results(submit_url(client, demisto.args())) elif demisto.command() == 'twinwave-submit-file': return_results(submit_file(client, demisto.args())) elif demisto.command() == 'twinwave-resubmit-job': return_results(resubmit_job(client, demisto.args())) elif demisto.command() == 'twinwave-list-recent-jobs': return_results(list_recent_jobs(client, demisto.args())) elif demisto.command() == 'twinwave-get-job-summary': return_results(get_job_summary(client, demisto.args())) elif demisto.command() == 'twinwave-get-job-normalized-forensics': return_results(get_job_normalized_forensics( client, demisto.args())) elif demisto.command() == 'twinwave-get-task-normalized-forensics': return_results( get_task_normalized_forensics(client, demisto.args())) elif demisto.command() == 'twinwave-get-task-raw-forensics': return_results(get_task_raw_forensics(client, demisto.args())) elif demisto.command() == 'twinwave-download-submitted-resource': return_results(download_submitted_resource(client, demisto.args())) elif demisto.command() == 'twinwave-get-temp-artifact-url': return_results(get_temp_artifact_url(client, demisto.args())) elif demisto.command() == 'twinwave-search-across-jobs-and-resources': return_results( search_across_jobs_and_resources(client, demisto.args())) # Log exceptions except Exception as e: return_error( f'Failed to execute {demisto.command()} command. Error: {str(e)}')