Пример #1
0
 def print_api_key_info(current_key_json):
     print(Color.control('Used API Key'))
     print('API Key: {}'.format(current_key_json['api_key']))
     print('Auth Level: {}'.format(current_key_json['auth_level_name']))
     if 'user' in current_key_json and current_key_json['user'] is not None:
         print('User: {} ({})'.format(current_key_json['user']['name'],
                                      current_key_json['user']['email']))
Пример #2
0
 def print_error_info(e):
     print(
         Color.control(
             'During the code execution, error has occurred. Please try again or contact the support.'
         ))
     print(Color.error('Message: \'{}\'.').format(str(e)) + '\n')
     print(traceback.format_exc())
Пример #3
0
    def print_limits_info(limits_data, limit_type):
        info_container = {
            'query': {
                'title': 'API query limits for used API Key',
                'available': 'Webservice API usage limits: {}',
                'used': 'Current API usage: {}',
            },
            'submission': {
                'title': 'Submission limits for used API Key',
                'available': 'Submission limits: {}',
                'used': 'Used submission limits: {}',
            },
            'quick_scan': {
                'title': 'Quick scan submission limits for used API Key',
                'available': 'Submission limits: {}',
                'used': 'Used submission limits: {}',
            },
        }
        formatted_limits = CliLimitsFormatter.format(limits_data, limit_type)

        texts = info_container[limit_type]

        if formatted_limits:
            print(Color.control(texts['title']))
            print(texts['available'].format(formatted_limits['available']))
            print(texts['used'].format(formatted_limits['used']))
            print('Is limit reached: {}'.format(
                Color.success('No') if formatted_limits['limit_reached'] is
                False else Color.error('Yes')))
Пример #4
0
 def print_call_info(cli_object):
     print(Color.control('Request was sent at ' + '{:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())))
     print('Endpoint URL: {}'.format(cli_object.api_object.get_full_endpoint_url()))
     print('HTTP Method: {}'.format(cli_object.api_object.request_method_name.upper()))
     print('Sent GET params: {}'.format(cli_object.api_object.params))
     print('Sent POST params: {}'.format(cli_object.api_object.data))
     print('Sent files: {}'.format(cli_object.api_object.files))
Пример #5
0
 def print_shorten_call_info(cli_object):
     print(Color.control('Endpoint data which will be reached:'))
     print('Endpoint URL: {}'.format(
         cli_object.api_object.get_full_endpoint_url()))
     print('HTTP Method: {}'.format(
         cli_object.api_object.request_method_name.upper()))
     print('Sent GET params: {}'.format(cli_object.api_object.params))
     print('Sent POST params: {}'.format(cli_object.api_object.data))
Пример #6
0
 def print_showing_response(arg_iter, iteration=None):
     show_response_msg = 'Showing response'
     if iteration is not None:
         show_response_msg = '{} for file \'{}\' - {}'.format(
             show_response_msg, arg_iter['file'] if isinstance(
                 arg_iter['file'], str) else arg_iter['file'].name,
             iteration)
     print(Color.control(show_response_msg))
Пример #7
0
 def print_response_summary(iter_cli_object, iteration=None):
     print(
         Color.control('Received response at {}{}'.format(
             CliMsgPrinter.date_form.format(datetime.datetime.now()),
             '- {}'.format(iteration) if iteration is not None else '')))
     print('Response status code: {}'.format(
         iter_cli_object.get_colored_response_status_code()))
     print('Message: {}'.format(
         iter_cli_object.get_colored_prepared_response_msg()))
Пример #8
0
    def run(self):
        self.request_session = requests.Session()
        self.load_config()
        self.prepare_test_env()
        
        map_of_available_actions = self.get_map_of_available_actions()
        current_key_json, current_key_response_headers = self.get_current_key_data()
        
        parser = self.prepare_parser(current_key_json, map_of_available_actions)
        args = self.rebuild_args(vars(parser.parse_args()))
        self.loaded_action = args['chosen_action']

        if self.loaded_action is not None:
            args_iterations = self.prepare_args_iterations(args)

            if_multiple_calls = True if args['chosen_action'] in ACTION_WITH_MULTIPLE_CALL_SUPPORT and len(args['file']) > 1 else False
            cli_object = map_of_available_actions[args['chosen_action']]

            if args['verbose'] is True:
                if isinstance(cli_object, dict) is False:
                    cli_object.init_verbose_mode()
                start_msg = 'Running \'{}\' in version \'{}\'. Webservice version: \'{}\', API version: \'{}\''.format(self.program_name, self.program_version, current_key_response_headers['Webservice-Version'], current_key_response_headers['Api-Version'])
                print(Color.control(start_msg))

            CliPrompts.prompt_for_dir_content_submission(if_multiple_calls, args)
            CliPrompts.prompt_for_sharing_confirmation(args, self.config['server'])
            CliHelper.check_if_version_is_supported(args, current_key_response_headers['Webservice-Version'], self.config['server'])
            number_of_iterations = len(args_iterations)

            for index, arg_iter in enumerate(args_iterations):
                current_iteration = '{}/{}'.format(index + 1, number_of_iterations) if if_multiple_calls is True else None
                iter_cli_object = deepcopy(cli_object)
                iter_cli_object.attach_args(arg_iter)

                if arg_iter['verbose'] is True:
                    if if_multiple_calls is False or index == 0:
                        CliMsgPrinter.print_api_key_info(current_key_json)

                    if 'file' in arg_iter:
                        iter_cli_object.attach_file(arg_iter['file'])

                    if if_multiple_calls is False:
                        CliMsgPrinter.print_full_call_info(iter_cli_object)
                    else:
                        if index == 0:
                            CliMsgPrinter.print_shorten_call_info(iter_cli_object)

                        CliMsgPrinter.print_shortest_call_info(iter_cli_object, current_iteration)
                elif 'file' in arg_iter:
                    iter_cli_object.attach_file(arg_iter['file'])

                try:
                    iter_cli_object.api_object.call(self.request_session, self.vxapi_cli_headers)
                    if arg_iter['chosen_action'] == ACTION_KEY_CURRENT:
                        self.write_current_key_data_to_cache(iter_cli_object)

                    if arg_iter['verbose'] is True:
                        CliMsgPrinter.print_response_summary(iter_cli_object, current_iteration)
                    elif if_multiple_calls:
                        print(Color.control('{} - {} - {}'.format(arg_iter['file'] if isinstance(arg_iter['file'], str) else arg_iter['file'].name, CliMsgPrinter.date_form.format(datetime.datetime.now()), current_iteration)))

                    api_response_headers = iter_cli_object.api_object.get_api_response().headers
                    submission_limits = json.loads(api_response_headers['Submission-Limits']) if 'Submission-Limits' in api_response_headers else {}
                    quick_scan_limits = json.loads(api_response_headers['Quick-Scan-Limits']) if 'Quick-Scan-Limits' in api_response_headers else {}
                    api_limits = json.loads(api_response_headers['Api-Limits']) if 'Api-Limits' in api_response_headers else {}

                    if arg_iter['verbose'] is True:
                        CliMsgPrinter.print_limits_info(api_limits, 'query')
                        CliMsgPrinter.print_limits_info(submission_limits, 'submission')
                        CliMsgPrinter.print_limits_info(quick_scan_limits, 'quick_scan')

                    if arg_iter['verbose'] is True:
                        CliMsgPrinter.print_showing_response(arg_iter, current_iteration)

                    sys.stdout.buffer.write(iter_cli_object.get_result_msg().encode())

                    if iter_cli_object.api_object.if_request_success() is False and if_multiple_calls is True and iter_cli_object.api_object.api_expected_data_type == ApiCaller.CONST_EXPECTED_DATA_TYPE_JSON:
                        response_json = iter_cli_object.api_object.get_response_json()
                        if 'Exceeded maximum API requests' in response_json['message']:
                            raise ExceededApiLimitsError('Requests exceeded maximum API requests, the rest of the unsubmitted files won\'t be processed, exiting ...')
                        elif 'Quota limit has been exceeded' in response_json['message']:
                            raise ExceededApiLimitsError('Requests exceeded maximum quota limit, the rest of the unsubmitted files won\'t be processed, exiting ...')
                    iter_cli_object.do_post_processing()
                except ExceededApiLimitsError as e:
                    raise e
                except Exception as e:
                    if if_multiple_calls is True:
                        CliMsgPrinter.print_error_info(e)
                    else:
                        raise e

                sys.stdout.write('\n')
        else:
            print(Color.control('No option was selected. To check CLI options, run script in help mode: \'{} -h\''.format(__file__)))
Пример #9
0
def main():
    try:
        if os.path.exists('config.py'):
            from config import get_config
            config = get_config()
        else:
            raise MissingConfigurationError(
                'Configuration is missing. Before running CLI, please copy the file \'config_tpl.py\' from current dir, rename it to \'config.py\', and fill'
            )

        program_name = 'VxWebService Python API Connector'
        program_version = __version__
        vxapi_cli_headers = {'User-agent': 'VxApi CLI Connector'}

        if config['server'].endswith('/'):
            config['server'] = config['server'][:-1]

        if config['server'].endswith('vxstream-sandbox.com'):
            config['server'] = config['server'].replace(
                'vxstream-sandbox.com', 'falcon-sandbox.com')

        map_of_available_actions = OrderedDict([
            (ACTION_GET_API_LIMITS,
             CliApiLimitsSummary(
                 ApiApiLimitsSummary(config['api_key'], config['api_secret'],
                                     config['server']))),
            (ACTION_GET_API_QUERY_LIMITS,
             CliApiQueryLimits(
                 ApiApiQueryLimits(config['api_key'], config['api_secret'],
                                   config['server']))),
            (ACTION_GET_API_SUBMISSION_LIMITS,
             CliApiSubmissionLimits(
                 ApiApiSubmissionLimits(config['api_key'],
                                        config['api_secret'],
                                        config['server']))),
            (ACTION_GET_ENVIRONMENTS,
             CliEnvironments(
                 ApiEnvironments(config['api_key'], config['api_secret'],
                                 config['server']))),
            (ACTION_GET_FEED,
             CliFeed(
                 ApiFeed(config['api_key'], config['api_secret'],
                         config['server']))),
            (ACTION_GET_NSSF_FILES,
             CliNssfDownload(
                 ApiNssfDownload(config['api_key'], config['api_secret'],
                                 config['server']))),
            (ACTION_GET_NSSF_LIST,
             CliNssfList(
                 ApiNssfList(config['api_key'], config['api_secret'],
                             config['server']))),
            (ACTION_GET_RELATIONSHIPS,
             CliRelationships(
                 ApiRelationships(config['api_key'], config['api_secret'],
                                  config['server']))),
            (ACTION_GET_RESULT,
             CliResult(
                 ApiResult(config['api_key'], config['api_secret'],
                           config['server']))),
            (ACTION_GET_SAMPLE_DROPPED_FILES,
             CliSampleDroppedFiles(
                 ApiSampleDroppedFiles(config['api_key'], config['api_secret'],
                                       config['server']))),
            (ACTION_GET_SAMPLE_SCREENSHOTS,
             CliSampleScreenshots(
                 ApiSampleScreenshots(config['api_key'], config['api_secret'],
                                      config['server']))),
            (ACTION_GET_SCAN,
             CliScan(
                 ApiScan(config['api_key'], config['api_secret'],
                         config['server']))),
            (ACTION_GET_BULK_SCAN,
             CliBulkScan(
                 ApiBulkScan(config['api_key'], config['api_secret'],
                             config['server']))),
            (ACTION_GET_STATE,
             CliState(
                 ApiState(config['api_key'], config['api_secret'],
                          config['server']))),
            (ACTION_GET_SUMMARY,
             CliSummary(
                 ApiSummary(config['api_key'], config['api_secret'],
                            config['server']))),
            (ACTION_GET_BULK_SUMMARY,
             CliBulkSummary(
                 ApiBulkSummary(config['api_key'], config['api_secret'],
                                config['server']))),
            (ACTION_GET_SYSTEM_BACKEND,
             CliSystemBackend(
                 ApiSystemBackend(config['api_key'], config['api_secret'],
                                  config['server']))),
            (ACTION_GET_SYSTEM_IN_PROGRESS,
             CliSystemInProgress(
                 ApiSystemInProgress(config['api_key'], config['api_secret'],
                                     config['server']))),
            (ACTION_GET_SYSTEM_HEARTBEAT,
             CliSystemHeartbeat(
                 ApiSystemHeartbeat(config['api_key'], config['api_secret'],
                                    config['server']))),
            (ACTION_GET_SYSTEM_STATE,
             CliSystemState(
                 ApiSystemState(config['api_key'], config['api_secret'],
                                config['server']))),
            (ACTION_GET_SYSTEM_STATS,
             CliSystemStats(
                 ApiSystemStats(config['api_key'], config['api_secret'],
                                config['server']))),
            (ACTION_GET_SYSTEM_QUEUE_SIZE,
             CliSystemQueueSize(
                 ApiSystemQueueSize(config['api_key'], config['api_secret'],
                                    config['server']))),
            (ACTION_GET_URL_HASH,
             CliUrlHash(
                 ApiUrlHash(config['api_key'], config['api_secret'],
                            config['server']))),
            (ACTION_REANALYZE_SAMPLE,
             CliReanalyze(
                 ApiReanalyze(config['api_key'], config['api_secret'],
                              config['server']))),
            (ACTION_SEARCH,
             CliSearch(
                 ApiSearch(config['api_key'], config['api_secret'],
                           config['server']))),
            (ACTION_SUBMIT_DROPPED_FILE,
             CliDroppedFileSubmit(
                 ApiDroppedFileSubmit(config['api_key'], config['api_secret'],
                                      config['server']))),
            (ACTION_SUBMIT_FILE,
             CliSubmitFile(
                 ApiSubmitFile(config['api_key'], config['api_secret'],
                               config['server']))),
            (ACTION_SUBMIT_URL_FILE,
             CliSubmitUrlFile(
                 ApiSubmitFile(config['api_key'], config['api_secret'],
                               config['server']))),
            (ACTION_SUBMIT_URL,
             CliSubmitUrl(
                 ApiSubmitUrl(config['api_key'], config['api_secret'],
                              config['server']))),
        ])

        request_session = requests.Session()

        api_object_api_key_data = ApiApiKeyData(config['api_key'],
                                                config['api_secret'],
                                                config['server'])
        api_object_api_key_data.call(request_session, vxapi_cli_headers)
        api_key_data_json_response = api_object_api_key_data.get_response_json(
        )

        if api_object_api_key_data.get_response_status_code(
        ) != 200 or api_key_data_json_response['response_code'] != 0:
            base_error_message = 'Can\'t retrieve data for given API Key \'{}\' in the webservice: \'{}\'. Response status code: \'{}\''.format(
                config['api_key'], config['server'],
                api_object_api_key_data.get_response_status_code())
            if 'response' in api_key_data_json_response and 'error' in api_key_data_json_response[
                    'response']:
                base_error_message += '. Response message: \'{}\''.format(
                    api_key_data_json_response['response']['error'])

            raise RetrievingApiKeyDataError(base_error_message)

        used_api_key_data = api_key_data_json_response['response']
        parser = argparse.ArgumentParser(
            description=program_name,
            formatter_class=argparse.ArgumentDefaultsHelpFormatter,
            add_help=False)
        parser.add_argument('--version',
                            '-ver',
                            action='version',
                            version='{} - version {}'.format(
                                program_name, program_version))
        CliArgumentBuilder(parser).add_help_argument()

        subparsers = parser.add_subparsers(
            help='Action names for \'{}\' auth level'.format(
                used_api_key_data['auth_level_name']),
            dest="chosen_action")

        for name, cli_object in map_of_available_actions.items():
            if cli_object.api_object.endpoint_auth_level <= used_api_key_data[
                    'auth_level']:
                child_parser = subparsers.add_parser(
                    name=name,
                    help=cli_object.help_description,
                    add_help=False)
                cli_object.add_parser_args(child_parser)

        args = vars(parser.parse_args())

        if args['chosen_action'] is not None:
            args_iterations = []
            if_multiple_calls = True if args[
                'chosen_action'] == ACTION_SUBMIT_FILE and len(
                    args['file']) > 1 else False
            if args['chosen_action'] == ACTION_SUBMIT_FILE:
                for file in args['file']:
                    arg_iter = args.copy()
                    arg_iter['file'] = file
                    args_iterations.append(arg_iter)
            else:
                args_iterations = [args]

            cli_object = map_of_available_actions[args['chosen_action']]

            if args['verbose'] is True:
                cli_object.init_verbose_mode()
                print(
                    Color.control('Running \'{}\' in version \'{}\''.format(
                        program_name, program_version)))

            CliHelper.prompt_for_dir_content_submission(args)
            CliHelper.prompt_for_sharing_confirmation(args, config['server'])
            CliHelper.check_if_version_is_supported(
                args,
                ApiInstanceVersion(config['api_key'], config['api_secret'],
                                   config['server']), request_session,
                vxapi_cli_headers, MINIMAL_SUPPORTED_INSTANCE_VERSION)

            for index, arg_iter in enumerate(args_iterations):
                cli_object.attach_args(arg_iter)
                if arg_iter['verbose'] is True:
                    if arg_iter['chosen_action'] != ACTION_GET_API_LIMITS and (
                            if_multiple_calls is False or index == 0):
                        # API limits checking should be done here, to ensure that user always will be able to run command in help mode. Also there is no need to run it in non verbose mode.
                        api_object_api_limits = ApiApiQueryLimits(
                            config['api_key'], config['api_secret'],
                            config['server'])
                        api_object_api_limits.call(request_session,
                                                   vxapi_cli_headers)
                        api_limits_response_json = api_object_api_limits.get_response_json(
                        )

                        # Ignore when WebService doesn't have that endpoint
                        if api_object_api_limits.get_response_status_code(
                        ) != 404:
                            if api_object_api_limits.get_response_status_code(
                            ) != 200 or api_limits_response_json[
                                    'response_code'] == -1:
                                raise RetrievingApiKeyDataError(
                                    'Can\'t check API limits before calling requested endpoint in webservice: \'{}\'. Response status code: \'{}\''
                                    .format(
                                        config['server'],
                                        api_object_api_limits.
                                        get_response_status_code()))

                            if api_object_api_limits.get_response_status_code(
                            ) == 200 and api_limits_response_json[
                                    'response_code'] == 0 and api_limits_response_json[
                                        'response']['limit_reached'] is True:
                                name_of_reached_limit = api_limits_response_json[
                                    'response']['name_of_reached_limit']
                                raise ReachedApiLimitError(
                                    'Exceeded maximum API requests per {}({}). Please try again later.'
                                    .format(
                                        name_of_reached_limit,
                                        api_limits_response_json['response']
                                        ['used'][name_of_reached_limit]))

                        if api_object_api_limits.get_response_status_code(
                        ) == 200 and api_limits_response_json[
                                'response_code'] == 0 and api_limits_response_json[
                                    'response']['used']:
                            api_usage = OrderedDict()
                            api_usage_limits = api_limits_response_json[
                                'response']['limits']
                            is_api_limit_reached = False

                            for period, used_limit in api_limits_response_json[
                                    'response']['used'].items():
                                # Given request is made after checking api limits. It means that we have to add 1 to current limits, to simulate that what happen after making requested API call
                                api_usage[period] = used_limit + 1
                                if is_api_limit_reached is False and api_usage[
                                        period] == api_usage_limits[period]:
                                    is_api_limit_reached = True

                            print(Color.control('API Limits for used API Key'))
                            print('Webservice API usage limits: {}'.format(
                                api_usage_limits))
                            print('Current API usage: {}'.format(
                                json.dumps(api_usage)))
                            print('Is limit reached: {}'.format(
                                Color.success('No') if is_api_limit_reached is
                                False else Color.error('Yes')))

                    if if_multiple_calls is False or index == 0:
                        print(Color.control('Used API Key'))
                        print('API Key: {}'.format(
                            used_api_key_data['api_key']))
                        print('Auth Level: {}'.format(
                            used_api_key_data['auth_level_name']))
                        if used_api_key_data['user'] is not None:
                            print('User: {} ({})'.format(
                                used_api_key_data['user']['name'],
                                used_api_key_data['user']['email']))

                    if arg_iter['chosen_action'] == ACTION_SUBMIT_FILE:
                        if if_multiple_calls is True and index == 0:
                            print(
                                Color.control(
                                    'Starting the process of sending multiple files ...'
                                ))

                        cli_object.attach_file(arg_iter['file'])

                    CliHelper.print_call_info(cli_object)
                elif arg_iter['chosen_action'] == ACTION_SUBMIT_FILE:
                    cli_object.attach_file(arg_iter['file'])

                try:
                    cli_object.api_object.call(request_session,
                                               vxapi_cli_headers)
                except Exception as e:
                    if if_multiple_calls is True:
                        CliHelper.print_error_info(e)
                    else:
                        raise e

                if arg_iter['verbose'] is True:
                    print(
                        Color.control('Received response at ' +
                                      '{:%Y-%m-%d %H:%M:%S}'.format(
                                          datetime.datetime.now())))
                    print('Response status code: {}'.format(
                        cli_object.get_colored_response_status_code()))
                    print('Message: {}'.format(
                        cli_object.get_colored_prepared_response_msg()))
                    show_response_msg = 'Showing response'
                    if if_multiple_calls is True:
                        show_response_msg = '{} for file \'{}\''.format(
                            show_response_msg, arg_iter['file'].name)
                    print(Color.control(show_response_msg))
                elif if_multiple_calls:
                    print(Color.control(arg_iter['file'].name))

                print(cli_object.get_result_msg())

                if cli_object.api_object.get_response_msg_success_nature(
                ) is False and if_multiple_calls is True and cli_object.api_object.api_expected_data_type == ApiCaller.CONST_EXPECTED_DATA_TYPE_JSON:
                    response_json = cli_object.api_object.get_response_json()
                    if 'response_code' in response_json and 'Exceeded maximum API requests' in response_json[
                            'response']['error']:
                        raise Exception(
                            'Requests exceeded maximum API requests, the rest of the unsubmitted files won\'t be processed, exiting ...'
                        )
                cli_object.do_post_processing()

                if arg_iter['verbose'] is True:
                    print('\n')
        else:
            print(
                Color.control(
                    'No option was selected. To check CLI options, run script in help mode: \'{} -h\''
                    .format(__file__)))
    except Exception as e:
        CliHelper.print_error_info(e)
Пример #10
0
 def print_shortest_call_info(cli_object, iteration):
     print(
         Color.control('Request was sent at {} - {}'.format(
             CliMsgPrinter.date_form.format(datetime.datetime.now()),
             iteration)))
     print('Sent files: {}'.format(cli_object.api_object.files))
Пример #11
0
def main():
    try:
        if os.path.exists('config.py'):
            from config import get_config
            config = get_config()
        else:
            raise MissingConfigurationError(
                'Configuration is missing. Before running CLI, please copy the file \'config_tpl.pl\' from current dir, rename it to \'config.pl\', and fill'
            )

        program_name = 'VxWebService Python API Connector'
        program_version = __version__
        vxapi_cli_headers = {'User-agent': 'VxApi CLI Connector'}

        if config['server'].endswith('/'):
            config['server'] = config['server'][:-1]

        map_of_available_actions = OrderedDict([
            ('get_api_limits',
             CliApiLimits(
                 ApiApiLimits(config['api_key'], config['api_secret'],
                              config['server']))),
            ('get_feed',
             CliFeed(
                 ApiFeed(config['api_key'], config['api_secret'],
                         config['server']))),
            ('get_relationships',
             CliRelationships(
                 ApiRelationships(config['api_key'], config['api_secret'],
                                  config['server']))),
            ('get_result',
             CliResult(
                 ApiResult(config['api_key'], config['api_secret'],
                           config['server']))),
            ('get_sample_dropped_files',
             CliSampleDroppedFiles(
                 ApiSampleDroppedFiles(config['api_key'], config['api_secret'],
                                       config['server']))),
            ('get_sample_screenshots',
             CliSampleScreenshots(
                 ApiSampleScreenshots(config['api_key'], config['api_secret'],
                                      config['server']))),
            ('get_scan',
             CliScan(
                 ApiScan(config['api_key'], config['api_secret'],
                         config['server']))),
            ('get_state',
             CliState(
                 ApiState(config['api_key'], config['api_secret'],
                          config['server']))),
            ('get_summary',
             CliSummary(
                 ApiSummary(config['api_key'], config['api_secret'],
                            config['server']))),
            ('get_system_backend',
             CliSystemBackend(
                 ApiSystemBackend(config['api_key'], config['api_secret'],
                                  config['server']))),
            ('get_system_in_progress',
             CliSystemInProgress(
                 ApiSystemInProgress(config['api_key'], config['api_secret'],
                                     config['server']))),
            ('get_system_heartbeat',
             CliSystemHeartbeat(
                 ApiSystemHeartbeat(config['api_key'], config['api_secret'],
                                    config['server']))),
            ('get_system_state',
             CliSystemState(
                 ApiSystemState(config['api_key'], config['api_secret'],
                                config['server']))),
            ('get_system_stats',
             CliSystemStats(
                 ApiSystemStats(config['api_key'], config['api_secret'],
                                config['server']))),
            ('get_system_queue_size',
             CliSystemQueueSize(
                 ApiSystemQueueSize(config['api_key'], config['api_secret'],
                                    config['server']))),
            ('get_quota',
             CliQuota(
                 ApiQuota(config['api_key'], config['api_secret'],
                          config['server']))),
            ('reanalyze_sample',
             CliReanalyze(
                 ApiReanalyze(config['api_key'], config['api_secret'],
                              config['server']))),
            ('search',
             CliSearch(
                 ApiSearch(config['api_key'], config['api_secret'],
                           config['server']))),
            ('submit_dropped_file',
             CliDroppedFileSubmit(
                 ApiDroppedFileSubmit(config['api_key'], config['api_secret'],
                                      config['server']))),
            ('submit_file',
             CliSubmitFile(
                 ApiSubmitFile(config['api_key'], config['api_secret'],
                               config['server']))),
            ('submit_url_file',
             CliSubmitUrlFile(
                 ApiSubmitFile(config['api_key'], config['api_secret'],
                               config['server']))),
            ('submit_url',
             CliSubmitUrl(
                 ApiSubmitUrl(config['api_key'], config['api_secret'],
                              config['server']))),
        ])

        request_session = requests.Session()

        api_object_api_key_data = ApiApiKeyData(config['api_key'],
                                                config['api_secret'],
                                                config['server'])
        api_object_api_key_data.call(request_session, vxapi_cli_headers)
        if api_object_api_key_data.get_response_status_code(
        ) != 200 or api_object_api_key_data.get_response_json(
        )['response_code'] != 0:
            raise RetrievingApiKeyDataError(
                'Can\'t retrieve data for api_key \'{}\' in the webservice: \'{}\'. Response status code: \'{}\''
                .format(config['api_key'], config['server'],
                        api_object_api_key_data.get_response_status_code()))

        used_api_key_data = api_object_api_key_data.get_response_json(
        )['response']
        parser = argparse.ArgumentParser(
            description=program_name,
            formatter_class=argparse.ArgumentDefaultsHelpFormatter,
            add_help=False)
        parser.add_argument('--version',
                            '-ver',
                            action='version',
                            version='{} - version {}'.format(
                                program_name, program_version))
        CliArgumentBuilder(parser).add_help_argument()

        subparsers = parser.add_subparsers(
            help='Action names for \'{}\' auth level'.format(
                used_api_key_data['auth_level_name']),
            dest="chosen_action")

        for name, cli_object in map_of_available_actions.items():
            if cli_object.api_object.endpoint_auth_level <= used_api_key_data[
                    'auth_level']:
                child_parser = subparsers.add_parser(
                    name=name,
                    help=cli_object.help_description,
                    add_help=False)
                cli_object.add_parser_args(child_parser)

        args = vars(parser.parse_args())

        if args['chosen_action'] is not None:
            cli_object = map_of_available_actions[args['chosen_action']]
            cli_object.attach_args(args)
            if args['verbose'] is True:
                cli_object.init_verbose_mode()
                print(
                    Color.control('Running \'{}\' in version \'{}\''.format(
                        program_name, program_version)))

                if args['chosen_action'] != 'get_api_limits':
                    # API limits checking should be done here, to ensure that user always will be able to run command in help mode. Also there is no need to run it in non verbose mode.
                    api_object_api_limits = ApiApiLimits(
                        config['api_key'], config['api_secret'],
                        config['server'])
                    api_object_api_limits.call(request_session,
                                               vxapi_cli_headers)
                    api_limits_response_json = api_object_api_limits.get_response_json(
                    )

                    # Ignore when WebService doesn't have that endpoint
                    if api_object_api_limits.get_response_status_code() != 404:
                        if api_object_api_limits.get_response_status_code(
                        ) != 200 or api_limits_response_json[
                                'response_code'] == -1:
                            raise RetrievingApiKeyDataError(
                                'Can\'t check API limits before calling requested endpoint in webservice: \'{}\'. Response status code: \'{}\''
                                .format(
                                    config['server'],
                                    api_object_api_limits.
                                    get_response_status_code()))

                        if api_object_api_limits.get_response_status_code(
                        ) == 200 and api_limits_response_json[
                                'response_code'] == 0 and api_limits_response_json[
                                    'response']['limit_reached'] is True:
                            name_of_reached_limit = api_limits_response_json[
                                'response']['name_of_reached_limit']
                            raise ReachedApiLimitError(
                                'Exceeded maximum API requests per {}({}). Please try again later.'
                                .format(
                                    name_of_reached_limit,
                                    api_limits_response_json['response']
                                    ['used'][name_of_reached_limit]))

                    if api_object_api_limits.get_response_status_code(
                    ) == 200 and api_limits_response_json['response_code'] == 0:
                        api_usage = OrderedDict()
                        api_usage_limits = api_limits_response_json[
                            'response']['limits']
                        is_api_limit_reached = False

                        for period, used_limit in api_limits_response_json[
                                'response']['used'].items():
                            # Given request is made after checking api limits. It means that we have to add 1 to current limits, to simulate that what happen after making requested API call
                            api_usage[period] = used_limit + 1
                            if is_api_limit_reached is False and api_usage[
                                    period] == api_usage_limits[period]:
                                is_api_limit_reached = True

                        print(Color.control('API Limits for used API Key'))
                        print('Webservice API usage limits: {}'.format(
                            api_usage_limits))
                        print('Current API usage: {}'.format(
                            json.dumps(api_usage)))
                        print('Is limit reached: {}'.format(
                            Color.success('No') if is_api_limit_reached is
                            False else Color.error('Yes')))

                print(Color.control('Used API Key'))
                print('API Key: {}'.format(used_api_key_data['api_key']))
                print('Auth Level: {}'.format(
                    used_api_key_data['auth_level_name']))
                if used_api_key_data['user'] is not None:
                    print('User: {} ({})'.format(
                        used_api_key_data['user']['name'],
                        used_api_key_data['user']['email']))

                print(
                    Color.control('Request was sent at ' +
                                  '{:%Y-%m-%d %H:%M:%S}'.format(
                                      datetime.datetime.now())))
                print('Endpoint URL: {}'.format(
                    cli_object.api_object.get_full_endpoint_url()))
                print('HTTP Method: {}'.format(
                    cli_object.api_object.request_method_name.upper()))
                print('Sent GET params: {}'.format(
                    cli_object.api_object.params))
                print('Sent POST params: {}'.format(
                    cli_object.api_object.data))
                print('Sent files: {}'.format(cli_object.api_object.files))

            cli_object.api_object.call(request_session, vxapi_cli_headers)
            if args['verbose'] is True:
                print(
                    Color.control('Received response at ' +
                                  '{:%Y-%m-%d %H:%M:%S}'.format(
                                      datetime.datetime.now())))
                print('Response status code: {}'.format(
                    cli_object.get_colored_response_status_code()))
                print('Message: {}'.format(
                    cli_object.get_colored_prepared_response_msg()))
                print(Color.control('Showing response'))

            print(cli_object.get_result_msg())
            cli_object.do_post_processing()

            if args['verbose'] is True:
                print('\n')
        else:
            print(
                Color.control(
                    'No option was selected. To check CLI options, run script in help mode: \'{} -h\''
                    .format(__file__)))
    except Exception as exc:
        print(
            Color.control(
                'During the code execution, error has occurred. Please try again or contact the support.'
            ))
        print(Color.error('Message: \'{}\'.').format(str(exc)) + '\n')