예제 #1
0
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)
예제 #2
0
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'],
    }
예제 #3
0
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)
예제 #4
0
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")
예제 #5
0
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})
예제 #6
0
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)
예제 #7
0
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')
예제 #8
0
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)
예제 #9
0
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'))
예제 #10
0
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)
예제 #11
0
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
예제 #12
0
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
예제 #13
0
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
예제 #14
0
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')
예제 #15
0
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', {}, {})
예제 #16
0
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)
예제 #17
0
파일: ExtraHop.py 프로젝트: demisto/content
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
예제 #18
0
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')
예제 #19
0
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', {}, {})
예제 #20
0
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)
예제 #22
0
파일: URLScan.py 프로젝트: demisto/content
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
예제 #23
0
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)
예제 #24
0
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})
예제 #25
0
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
예제 #26
0
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
        }
    }
예제 #27
0
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
예제 #28
0
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
예제 #29
0
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
예제 #30
0
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
예제 #31
0
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):
예제 #32
0
            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(
예제 #33
0
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
예제 #34
0
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)
        }
    })
예제 #35
0
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)
예제 #36
0
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
        })
예제 #37
0
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
예제 #38
0
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))
예제 #39
0
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.')
예제 #40
0
            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)
예제 #41
0
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)
예제 #44
0
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)}')
예제 #45
0
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
예제 #46
0
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.'
        })
예제 #47
0
def main():
    file_entry_id = demisto.args()['EntryID']
    get_exif_tags(file_entry_id)
예제 #48
0
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)}'
        )
예제 #49
0
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)
예제 #51
0
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)
예제 #52
0
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)
예제 #53
0
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)
예제 #54
0
        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)
예제 #55
0
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')
예제 #56
0
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
    })
예제 #57
0
def disable_engine_command():
    path = demisto.args()['path']

    disable_engine(path)

    demisto.results('Engine disabled successfully')
예제 #58
0
    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)
예제 #59
0
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
예제 #60
0
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)}')