Joe Security Deprecated

Deprecated. Use Joe Security v2 instead.

Forensics & Malware Analysis · Joe Security

Details

IDJoe Security
ProviderJoe Security LLC
CategoryForensics & Malware Analysis
From Version5.0.0
Docker Imagedemisto/python:2.7.18.6174823
Supported ModulesAgentix XSIAM EDR Cortex Cloud Cloud Runtime Security

README

Overview


Use the Joe Security Sandbox integration to detect and analyze potentially malicious files.
Using the integration you can analyze URL links and sample files on different machine types (Windows, Android, iOS and Mac OS X).

All file types are supported.

This integration was integrated and tested with Joe Security v2.

Playbooks


  • JoeSecurity -Detonate URL
  • JoeSecurity -Detonate File
  • JoeSecurity -Detonate File From URL

Use Cases


  • Add a file to the integrations war room.
  • Sample a file.
  • Get information on an old analysis.
  • Send a URL sample to Joe Security.

Prerequisites


Before you configure the integration, retrieve the API key from your Joe Security environment.

  1. Use this link to log in to the Joe Security platform. 
  2. Click the button in the top-right corner and select Settings.
  3. In the API Key section, select the I Agree checkbox. 
  4. Click the Generate API key button.
  5. Copy the API key for later use.

Configure the Joe Security Integration on Cortex XSOAR


  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for Joe Security.
  3. Click Add instance to create and configure a new integration instance.
    • Name: A textual name for the integration instance.
    • Joe Security URL: URL of the Joe Security server
    • API Key
    • Trust any certificate (not secure)
    • Do not use by default
    • Cortex XSOAR engine
  4. Click Test to validate the URLs and connection.

Commands


You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook. After you successfully execute a command, a DBot message appears in the War Room with the command details.

  1. Ping the server: joe-is-online
  2. Submit a URL for analysis: joe-analysis-submit-url
  3. Get analysis information: joe-analysis-info
  4. Get analyes list: joe-list-analysis
  5. Submit sample for analysis: joe-analysis-submit-sample
  6. Search Analyses: joe-search
  7. Download a report: joe-download-report
  8. Download analysis file: joe-download-sample
  9. Detonate a file: joe-detonate-file
  10. Detonate a URL: joe-detonate-url

Ping the server


Pings the Joe Security server to verify that it is responsive.

Base Command

joe-is-online

Input

There is no input for this command.

Context Data

There is no context data for this command.

Raw Output

There is not raw output for this command.

Submit a URL for analysis


Submits a URL to Joe Security for analysis.

Base Command

joe-analysis-submit-url

Input
Parameter Required Description
url Required URL to submit for analysis.
should_wait Optional Specifies if the command polls for the result of the analysis.
comments Optional Comments for the analysis.
Systems Optional

Comma separated list of operating systems to run analysis on.

Valid values are:

  • w7
  • w7x64
  • w7_1
  • w7_2
  • w7native
  • android2
  • android3
  • mac1
  • w7l
  • w7x64l
  • w10
  • android4
  • w7x64native
  • w7_3
  • w10native
  • android5native_1
  • w7_4
  • w7_5
  • w10x64
  • w7x64_hvm
  • android6
  • iphone1
  • w7_sec
  • macvm
  • w7_lang_packs
  • w7x64native_hvm
  • lnxubuntu1
  • lnxcentos1android7_nougat
internet-access Optional

If to enable full internet access (boolean).

Default is True.

 

Context Data
Path Type Description
Joe.Analysis.WebID String Web ID
Joe.Analysis.FileName String Sample data, could be a file name or URL
Joe.Analysis.Status String Analysis status
Joe.Analysis.Comments String Analysis comments
Joe.Analysis.Time Date Time submitted
Joe.Analysis.Runs Unknown Sub-analysis information
Joe.Analysis.Result String Analysis results
Joe.Analysis.Errors Unknown Errors raised during sampling
Joe.Analysis.Systems Unknown Analysis operating system
Joe.Analysis.MD5 String MD5 hash of the analysis sample
Joe.Analysis.SHA1 String SHA-1 hash of the analysis sample
Joe.Analysis.SHA256 String SHA-256 has of the analysis sample
DBotScore.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Indicator Unknown The name of the sample file or URL
DBotScore.Type String

url - for URL samples

file - for anything not URL sample

DBotScore.Score String

Cortex XSOAR Dbot Score:

  • Bad
  • Suspicious
  • Good
DBotScore.Malicious.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Malicious.Detections String The sub analysis detection statuses
DBotScore.Malicious.SHA1 String SHA-1 hash of the file

Raw Output

There is no raw output for this command.

Get analysis information


Returns information for a specified analysis.

Base Command

joe-analysis-info

Input
Parameter Required Description
webId Required Web ID. Supports comma-separated arrays.

 

Context Data
Path Type Description
Joe.Analysis.WebID String Web ID
Joe.Analysis.SampleName String Sample Data, could be a file name or URL
Joe.Analysis.Status String Analysis status
Joe.Analysis.Comments String Analysis comments
Joe.Analysis.Time Date Submitted time
Joe.Analysis.Runs Unknown Sub-analysis information
Joe.Analysis.Result String Analysis results
Joe.Analysis.Errors Unknown Errors raised during sampling
Joe.Analysis.Systems Unknown Analysis operating system
Joe.Analysis.MD5 String MD5 hash of the analysis sample
Joe.Analysis.SHA1 String SHA-1 hash of the analysis sample
Joe.Analysis.SHA256 String SHA-256 hash of the analysis sample
DBotScore.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Indicator Unknown The name of the sample file or URL
DBotScore.Type string

url - for URL samples

file - for anything not URL sample

DBotScore.Score String

Cortex XSOAR Dbot Score:

  • Bad
  • Suspicious
  • Good
DBotScore.Malicious.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Malicious.Detections String The sub analysis detection statuses
DBotScore.Malicious.SHA1 String The SHA-1 hash of the file
 
Raw Output

There is no raw output for this command.

Get analyses list


Returns a list of all analyses.

Base Command

joe-list-analysis

Input

There is no input for this command. 

Context Data
Path Type Description
Joe.Analysis.WebID String Web ID
Joe.Analysis.SampleName String Sample Data, could be a file name or URL
Joe.Analysis.Status String Analysis status
Joe.Analysis.Comments String Analysis comments
Joe.Analysis.Time Date Submitted time
Joe.Analysis.Runs Unknown Sub-analysis information
Joe.Analysis.Result String Analysis results
Joe.Analysis.Errors Unknown Errors raised during sampling
Joe.Analysis.Systems Unknown Analysis operating system
Joe.Analysis.MD5 String MD5 hash of the analysis sample
Joe.Analysis.SHA1 String SHA-1 hash of the analysis sample
Joe.Analysis.SHA256 String SHA-256 hash of the analysis sample
DBotScore.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Indicator Unknown The name of the sample file or URL
DBotScore.Type String

url - for URL samples

file - for anything not URL sample

DBotScore.Score String

Cortex XSOAR Dbot Score:

  • Bad
  • Suspicious
  • Good
DBotScore.Malicious.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Malicious.Detections String The sub analysis detection statuses
DBotScore.Malicious.SHA1 String The SHA-1 hash of the file
 
Raw Output

There is no raw output for this command.

Submit sample for analysis


Submits a sample to Joe Security for analysis.

Base Command

joe-analysis-submit-sample

Input
Parameter Required Description
file_id Optional War Room entry of a file (for example, 3245@4).
sample_url Optional URL of a sample file. Supports comma-seperated arrays.
should_wait Optional Specifies if the command polls for the result of the analysis
comments Optional Comments for the analysis
systems Optional

Comma separated list of operating systems to run analysis on.

Valid values are:

  • w7
  • w7x64
  • w7_1
  • w7_2
  • w7native
  • android2
  • android3
  • mac1
  • w7l
  • w7x64l
  • w10
  • android4
  • w7x64native
  • w7_3
  • w10native
  • android5native_1
  • w7_4
  • w7_5
  • w10x64
  • w7x64_hvm
  • android6
  • iphone1
  • w7_sec
  • macvm
  • w7_lang_packs
  • w7x64native_hvm
  • lnxubuntu1
  • lnxcentos1
  • android7_nougat
internet-access Optional Enable full internet access. Default is True.

 

Context Data
Path Type Description
Joe.Analysis.WebID String Web ID
Joe.Analysis.SampleName String Sample data, could be a file name or URL
Joe.Analysis.Status String Analysis status
Joe.Analysis.Comments String Analysis comments
Joe.Analysis.Time Date Submitted time
Joe.Analysis.Runs Unknown Sub-analysis information
Joe.Analysis.Result String Analysis results
Joe.Analysis.Errors Unknown Errors raised during sampling
Joe.Analysis.Systems Unknown Analysis operating system
Joe.Analysis.MD5 String MD5 hash of the analysis sample
Joe.Analysis.SHA1 String SHA-1 hash of the analysis sample
Joe.Analysis.SHA256 String SHA-256 hash of the analysis sample
DBotScore.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Indicator Unknown The name of the sample file or URL
DBotScore.Type String

url - for URL samples

file - for anything not URL sample

DBotScore.Score String

Cortex XSOAR Dbot Score:

  • Bad
  • Suspicious
  • Good
DBotScore.Malicious.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Malicious.Detections String The sub analysis detection statuses
DBotScore.Malicious.SHA1 String The SHA-1 hash of the file
 
Raw Output

There is no raw output for this command.

Search Analyses


Search through all analyses in Joe Security.

Base Command

joe-search

Input
Parameter Description
query

String to search for in these fields:

  • webID
  • MD5
  • SHA1
  • SHA256
  • filename
  • URL
  • comments

 

Context Data
Path Type Description
Joe.Analysis.WebID String Web ID
Joe.Analysis.SampleName String Sample data, could be a file name or URL
Joe.Analysis.Status String Analysis status
Joe.Analysis.Comments String Analysis comments
Joe.Analysis.Time Date Submitted time
Joe.Analysis.Runs Unknown Sub-analysis information
Joe.Analysis.Result String Analysis results
Joe.Analysis.Errors Unknown Errors raised during sampling
Joe.Analysis.Systems Unknown Analysis operating system
Joe.Analysis.MD5 String MD5 has of the analysis sample
Joe.Analysis.SHA1 String SHA-1 hash of the analysis sample
Joe.Analysis.SHA256 String SHA-256 has of the analysis sample
DBotScore.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Indicator Unknown The name of the sample file or URL
DBotScore.Type String

url - for URL samples

file - for anything not URL sample

DBotScore.Score String

Cortex XSOAR Dbot Score:

  • Bad
  • Suspicious
  • Good
DBotScore.Malicious.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Malicious.Detections String The sub analysis detection statuses
DBotScore.Malicious.SHA1 String The SHA-1 hash of the file

 

Raw Output

There is no raw output for this command.

Download a report


Downloads a resource associated to a report. This can be the full report, dropped binaries, and so on. See all supported report types here:

Base Command

joe-download-report

Input
Parameter Required Description
webid Required

Web ID

type Optional

Resource type to download, default is html

 

Context Data
Path Type Description
InfoFile.Name String Name of the file
InfoFile.EntryID String The entry ID of the sample
InfoFile.Size Number The size of the file
InfoFile.Type String File type (for example, PE)
InfoFile.Info String Basic information about the file
File.Extension String File extension

 

Raw Output

There is no raw output for this command.

Download analysis file


Downloads the sample file of an analysis. For security considerations, the extension is dontrun.

Base Command

joe-download-sample

Input
Parameter Required Description
webid Required

Web ID

 

Context Data
Path Type Description
File.Size Number The size of the file
File.SHA1 String SHA-1 hash of the file
File.SHA256 String SHA-256 hash of the file
File.Name String The sample name
File.SSDeep String ssdeep hash of the file
File.EntryID String War room entry ID of the file
File.Info String Basic information of the file
File.Type String File type (for example PE)
File MD5 String MD5 hash of the file
File.Extension String File extension

 

Raw Output

There is no raw output for this command.

Detonate a file


Submits a file for analysis.

Base Command

joe-detonate-file

Input
Parameter Required Description
file_id Optional War room entry of a file (for example, 3245@4)
sample_url Optional URL of a sample file
comments Optional Comments for the analysis
systems Optional

Comma separated list of operating systems to run the analysis on.

Valid values are:

  • w7
  • w7x64
  • w7_1
  • w7_2
  • w7native
  • android2
  • android3
  • mac1
  • w7l
  • w7x64l
  • w10
  • android4
  • w7x64native
  • w7_3
  • w10native
  • android5native_1
  • w7_4
  • w7_5
  • w10x64
  • w7x64_hvm
  • android6
  • iphone1
  • w7_sec
  • macvm
  • w7_lang_packs
  • w7x64native_hvm
  • lnxubuntu1
  • lnxcentos1
  • android7_nougat
internet-access Optional If to enable full internet access. Default is True

  

Context Data
Path Type Description
Joe.Analysis.WebID String Web ID
Joe.Analysis.SampleName String Sample Data, could be a file name or URL
Joe.Analysis.Status String Analysis status
Joe.Analysis.Comments String Analysis comments
Joe.Analysis.Time Date Submission time
Joe.Analysis.Runs Unknown Sub-analysis information
Joe.Analysis.Result String Analysis results
Joe.Analysis.Errors Unknown Errors raised during sampling
Joe.Analysis.Systems Unknown Analysis operating system
Joe.Analysis.MD5 String MD5 hash of the analysis sample
Joe.Analysis.SHA1 String SHA-1 hash of the analysis sample
Joe.Analysis.SHA256 String SHA-256 hash of the analysis sample
DBotScore.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Indicator Unknown The name of the sample file or URL
DBotScore.Type String

url - for URL samples

file - for anything not URL sample

DBotScore.Score String

Cortex XSOAR Dbot Score:

  • Bad
  • Suspicious
  • Good
DBotScore.Malicious.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Malicious.Detections String The sub analysis detection statuses
DBotScore.Malicious.SHA1 String The SHA-1 has of the file
 
Raw Output

There is no raw output for this command.

Detonate a URL


Submits a URL for analysis.

Base Command

joe-detonate-url

Input
Parameter Required Description
url Required sample URL
comments Optional Comments for the analysis
systems Optional

Comma separated list of operating systems to run the analysis on.

Valid values are:

  • w7
  • w7x64
  • w7_1
  • w7_2
  • w7native
  • android2
  • android3
  • mac1
  • w7l
  • w7x64l
  • w10
  • android4
  • w7x64native
  • w7_3
  • w10native
  • android5native_1
  • w7_4
  • w7_5
  • w10x64
  • w7x64_hvm
  • android6
  • iphone1
  • w7_sec
  • macvm
  • w7_lang_packs
  • w7x64native_hvm
  • lnxubuntu1
  • lnxcentos1
  • android7_nougat
internet-access Optional If to enable full internet access. Default is True.

 

Context Data
Path Type Description
Joe.Analysis.WebID String Web ID
Joe.Analysis.SampleName String Sample data, could be a file name or URL
Joe.Analysis.Status String Analysis status
Joe.Analysis.Comments String Analysis comments
Joe.Analysis.Time Date Submission time
Joe.Analysis.Runs Unknown Sub-analysis information
Joe.Analysis.Result String Analysis results
Joe.Analysis.Errors Unknown Errors raised during sampling
Joe.Analysis.Systems Unknown Analysis operating system
Joe.Analysis.MD5 String MD5 hash of the analysis sample
Joe.Analysis.SHA1 String SHA-1 hash of the analysis sample
Joe.Analysis.SHA256 String SHA-256 hash of the analysis sample
DBotScore.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Indicator Unknown The name of the sample file or URL
DBotScore.Type String

url - for URL samples

file - for anything not URL sample

DBotScore.Score String

Cortex XSOAR Dbot Score:

  • Bad
  • Suspicious
  • Good
DBotScore.Malicious.Vendor String The name of the vendor (JoeSecurity)
DBotScore.Malicious.Detections String The sub analysis detection statuses
DBotScore.Malicious.SHA1 String The SHA-1 hash of the file

 

Raw Output

There is no raw output for this command.

Configuration parameters

  • url — Joe Security Url (required)
  • api_key — API Key (required)
  • insecure — Trust any certificate (not secure)
  • maxpolls — Max. Polling Time (in seconds):
  • verbose — Verbose (show log in case of error)
  • proxy — Use system proxy settings

Commands (10)

  • joe-analysis-info Deprecated

    Show information about an analysis.

  • joe-analysis-submit-sample Deprecated

    Submit a sample for analysis.

  • joe-analysis-submit-url Deprecated

    Submit a url for analysis.

  • joe-detonate-file Deprecated

    Submit a sample for analysis.

  • joe-detonate-url Deprecated

    Submit a url for analysis.

  • joe-download-report Deprecated

    Download a resource belonging to a report. This can be the full report, dropped binaries, etc. See integration README for the full supported report types.

  • joe-download-sample Deprecated

    Download the sample file of an analysis. for security reasons, the extension will be "dontrun"

  • joe-is-online Deprecated

    Check if Joe Sandbox is online or in maintenance mode.

  • joe-list-analysis Deprecated

    List all analyses.

  • joe-search Deprecated

    Search through all analyses.

import demistomock as demisto
from CommonServerPython import *
from CommonServerUserPython import *

''' IMPORTS '''
import os
import time
import shutil
import requests
from distutils.util import strtobool

# disable insecure warnings
requests.packages.urllib3.disable_warnings()

''' GLOBAL VARS '''
BASE_URL = urljoin(demisto.params().get('url'), 'api/')
USE_SSL = not demisto.params().get('insecure', False)
MAX_POLLS = int(demisto.params().get('maxpolls', 300))
USE_PROXY = demisto.params().get('proxy', True)

nothing_to_analyze_message = 'We found nothing to analyze in your uploaded email' \
                             '(possibly all elements where whitelisted, check Input filtering in your Settings).'
nothing_to_analyze_output = {
    'Type': entryTypes['note'],
    'ContentsFormat': formats['markdown'],
    'Contents': 'We found nothing to analyze in your uploaded email',
    'HumanReadable': 'We found nothing to analyze in your uploaded email'
}

''' HELPER FUNCTIONS '''


def http_post(url_suffix, data=None, files=None, parse_json=True):
    data = {} if data is None else data

    LOG('running request with url=%s\n\tdata=%s\n\tfiles=%s' % (BASE_URL + url_suffix,
                                                                data, files,))
    data.setdefault('apikey', demisto.params()['api_key'])

    res = requests.post(BASE_URL + url_suffix, verify=USE_SSL, data=data, files=files)

    if res.status_code == 403:
        raise Exception('API Key is incorrect')

    if res.status_code != 200:
        error_msg = res.json()['errors'][0]['message']
        if error_msg == nothing_to_analyze_message:
            return 'nothing_to_analyze'

        LOG('result is: %s' % (res.json(),))
        error_msg = res.json()['errors'][0]['message']
        raise Exception('Your request failed with the following error: %s.\n%s' % (res.reason, error_msg,))

    if parse_json:
        return res.json()
    else:
        return res.content


def analysis_to_entry(title, info):
    if not isinstance(info, list):
        info = [info]

    context = []
    table = []
    dbot_scores = []
    for analysis in info:
        analysis_info = {
            'ID': analysis['webid'],  # for detonate generic polling
            'WebID': analysis['webid'],
            'SampleName': analysis['filename'],
            'Status': analysis['status'],
            'Comments': analysis['comments'],
            'Time': analysis['time'],
            'MD5': analysis['md5'],
            'SHA1': analysis['sha1'],
            'SHA256': analysis['sha256'],
            'Systems': list(set([run['system'] for run in analysis['runs']])),
            'Result': ', '.join([run['detection'] for run in analysis['runs']]),
            'Errors': [run['error'] for run in analysis['runs']],
        }

        analysis_context = dict(analysis_info)
        analysis_context['Runs'] = analysis['runs']

        analysis_table = dict(analysis_info)
        if not any(analysis_table['Errors']):
            analysis_table['Errors'] = None

        dbot_score = 0
        malicious = None
        if 'malicious' in analysis_info['Result']:
            dbot_score = 3
            malicious = {
                'Vendor': 'JoeSecurity',
                'Detections': ', '.join(set([run['detection'] for run in analysis['runs']])),
                'SHA1': analysis_info['SHA1'],
            }
        elif 'suspicious' in analysis_info['Result']:
            dbot_score = 2
        elif 'clean' in analysis_info['Result']:
            dbot_score = 1

        dbot_scores.append({
            'Vendor': 'JoeSecurity',
            'Indicator': analysis.get('MD5', analysis.get('filename')),
            'Type': 'file' if analysis_info['MD5'] else 'url',
            'Score': dbot_score,
            'Malicious': malicious,
        })
        context.append(analysis_context)
        table.append(analysis_table)

    entry = {
        'ContentsFormat': formats['json'],
        'Type': entryTypes['note'],
        'Contents': context,
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': tableToMarkdown(title, table, removeNull=True),
        'EntryContext': {'Joe.Analysis(val.ID && val.ID == obj.ID)': createContext(context, removeNull=True),
                         'DBotScore': createContext(dbot_scores, removeNull=True), }
    }

    return entry


def poll_webid(web_id):
    result = {'data': {'status': 'pending'}}
    max_polls = MAX_POLLS

    while (max_polls >= 0) and result['data']['status'] != 'finished':
        if result['data']['status'] != 'pending':
            LOG('error while polling: result is %s' % (result,))
        result = info_request(web_id)
        time.sleep(1)
        max_polls -= 1

    LOG('reached max_polls #%d' % (max_polls,))
    if max_polls < 0:
        return analysis_to_entry('Polling timeout on Analysis #' + web_id, result['data'])
    else:
        return analysis_to_entry('Analysis #' + web_id, result['data'])


''' FUNCTIONS '''


def is_online():
    cmd_url = 'v2/server/online'
    res = http_post(cmd_url)
    return res['data']['online']


def list_analysis():
    cmd_url = 'v2/analysis/list'
    res = http_post(cmd_url)

    data = [info_request(web_id['webid'])['data'] for web_id in res['data']]
    return analysis_to_entry('All Analyses:', data)


def analysis_info():
    ids = demisto.args().get('webid')
    if type(ids) in STRING_TYPES:
        ids = ids.split(',')
    LOG('info: web_id = %s' % (ids,))
    res = [info_request(webid)['data'] for webid in ids]
    return analysis_to_entry('Analyses:', res)


def info_request(web_id):
    cmd_url = 'v2/analysis/info'
    return http_post(cmd_url, data={'webid': web_id})


def search():
    cmd_url = 'v2/analysis/search'
    query = demisto.args().get('query')
    res = http_post(cmd_url, data={'q': query})
    if len(res['data']) == 0:
        return 'No Result was found.'

    data = [info_request(web_id['webid'])['data'] for web_id in res['data']]
    return analysis_to_entry('Analysis Search Results:', data)


def analyse_url():
    args = demisto.args()
    url = args.get('url')
    internet_access = bool(strtobool(args.get('internet-access', 'true')))
    comments = args.get('comments')
    systems = args.get('systems')

    should_wait = bool(strtobool(demisto.get(args, 'should_wait')))

    return analyse_url_request(url, should_wait, internet_access, comments, systems)


def analyse_url_request(url, should_wait, internet_access, comments='', systems=''):
    data = {
        'accept-tac': 1,
        'url': url,
        'internet-access': 1 if internet_access else 0,
    }
    if comments != '':
        data['comments'] = comments
    if systems != '':
        data['systems[]'] = [s.strip() for s in systems.split(',')]
    res = http_post('v2/analysis/submit', data=data)

    if 'errors' in res:
        LOG('Error! in command analyse_url: url=%s' % (url,))
        LOG('got the following errors:\n' + '\n'.join(e['message'] for e in res['errors']))
        raise Exception('command failed to run.')

    if should_wait:
        return poll_webid(res['data']['webids'][0])

    web_id = res['data']['webids'][0]
    result = info_request(web_id)
    return analysis_to_entry('Analysis #%s' % (web_id,), result['data'])


def analyse_sample():
    args = demisto.args()
    file_entry = args.get('file_id', '')
    if type(file_entry) in STRING_TYPES:
        file_entry = [f for f in file_entry.split(',') if f != '']
    sample_url = args.get('sample_url', '')
    if type(sample_url) in STRING_TYPES:
        sample_url = [f for f in sample_url.split(',') if f != '']
    internet_access = bool(strtobool(args.get('internet-access', 'true')))
    should_wait = bool(strtobool(demisto.get(args, 'should_wait')))
    comments = args.get('comments', '')
    systems = args.get('systems', '')

    if (len(file_entry) == 0 and len(sample_url) == 0) or ([] not in [file_entry, sample_url]):
        raise ValueError('You must specify one (and only one) of the following: sample_url, file_id.')

    LOG('analysing sample')
    if len(file_entry) != 0:
        return [analyse_sample_file_request(f, should_wait, internet_access, comments, systems) for f in file_entry]
    else:
        return [analyse_sample_url_request(s, should_wait, internet_access, comments, systems) for s in sample_url]


def analyse_sample_file_request(file_entry, should_wait, internet_access, comments='', systems=''):
    data = {
        'accept-tac': 1,
        'internet-access': 1 if internet_access else 0,
    }
    if comments != '':
        data['comments'] = comments
    if systems != '':
        data['systems[]'] = [s.strip() for s in systems.split(',')]  # type: ignore

    # removing backslashes from filename as the API does not like it
    # if given filename such as dir\file.xlsx - the sample will end with the name file.xlsx
    filename = os.path.basename(demisto.getFilePath(file_entry)['name'])
    if isinstance(filename, unicode):  # py2 way of checking if a var is of type unicode
        filename = filename.encode('ascii', 'ignore')
    fixed_filename = filename.replace('\\', '/')

    with open(demisto.getFilePath(file_entry)['path'], 'rb') as f:
        res = http_post('v2/analysis/submit', data=data, files={'sample': (fixed_filename, f)})

    if res == 'nothing_to_analyze':
        return nothing_to_analyze_output

    if 'errors' in res:
        LOG('Error! in command sample file: file_entry=%s' % (file_entry,))
        LOG('got the following errors:\n' + '\n'.join(e['message'] for e in res['errors']))
        raise Exception('command failed to run.')

    os.remove(os.path.basename(demisto.getFilePath(file_entry)['name']))

    if should_wait:
        return poll_webid(res['data']['webids'][0])

    web_id = res['data']['webids'][0]
    result = info_request(web_id)
    return analysis_to_entry('Analysis #%s' % (web_id,), result['data'])


def analyse_sample_url_request(sample_url, should_wait, internet_access, comments, systems):
    data = {
        'accept-tac': 1,
        'sample-url': sample_url,
        'internet-access': 1 if internet_access else 0,
    }
    if comments != '':
        data['comments'] = comments
    if systems != '':
        data['systems[]'] = [s.strip() for s in systems.split(',')]

    res = http_post('v2/analysis/submit', data=data)

    if res == 'nothing_to_analyze':
        return nothing_to_analyze_output

    if 'errors' in res:
        LOG('Error! in command sample file: file url=%s' % (sample_url,))
        LOG('got the following errors:\n' + '\n'.join(e['message'] for e in res['errors']))
        raise Exception('command failed to run.')

    if should_wait:
        return poll_webid(res['data']['webids'][0])

    web_id = res['data']['webids'][0]
    result = info_request(res['data']['webids'][0])
    return analysis_to_entry('Analysis #%s' % (web_id,), result['data'])


def download_report():
    args = demisto.args()
    webid = args.get('webid')
    rsc_type = args.get('type')
    return download_request(webid, rsc_type)


def download_sample():
    args = demisto.args()
    webid = args.get('webid')
    rsc_type = 'sample'
    return download_request(webid, rsc_type)


def download_request(webid, rsc_type):
    res = http_post('v2/analysis/download', data={'webid': webid, 'type': rsc_type.lower()}, parse_json=False)

    info = info_request(webid)
    if rsc_type == 'sample':
        return fileResult('%s.dontrun' % (info.get('filename', webid),), res)
    else:
        return fileResult('%s_report.%s' % (info.get('filename', webid), rsc_type,), res, entryTypes['entryInfoFile'])


''' EXECUTION CODE '''
LOG('command is %s' % (demisto.command(),))
try:
    handle_proxy()
    if demisto.command() in ['test-module', 'joe-is-online']:
        # This is the call made when pressing the integration test button.
        if is_online():
            demisto.results('ok')
        else:
            demisto.results('not online')
    elif demisto.command() == 'joe-list-analysis':
        demisto.results(list_analysis())
    elif demisto.command() == 'joe-analysis-info':
        demisto.results(analysis_info())
    elif demisto.command() == 'joe-analysis-submit-url':
        demisto.results(analyse_url())
    elif demisto.command() == 'joe-detonate-url':
        demisto.args()['should_wait'] = 'True'
        demisto.results(analyse_url())
    elif demisto.command() == 'joe-analysis-submit-sample':
        demisto.results(analyse_sample())
    elif demisto.command() == 'joe-detonate-file':
        demisto.args()['should_wait'] = 'True'
        demisto.results(analyse_sample())
    elif demisto.command() == 'joe-download-report':
        demisto.results(download_report())
    elif demisto.command() == 'joe-download-sample':
        demisto.results(download_sample())
    elif demisto.command() == 'joe-search':
        demisto.results(search())

except Exception as e:
    if demisto.params().get('verbose'):
        LOG(e.message)
        if demisto.command() != 'test-module':
            LOG.print_log()

    demisto.results({
        'Type': entryTypes['error'],
        'ContentsFormat': formats['text'],
        'Contents': 'error has occurred: %s' % (e.message,),
    })