コード例 #1
0
 def stop_scan(self, scan_guid):
     api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
     response = api.stop_scan(scan_guid)
     if response.response_code == 401:
         Logger.app.critical("An Authorization Error occured.")
         sys.exit(ExitStatus.failure)
     return response.success
コード例 #2
0
ファイル: proxy.py プロジェクト: vanbenschoten/webbreaker
    def _download_proxy(self, webmacro, setting, server):

        api = WebInspectApi(server,
                            verify_ssl=False,
                            username=self.username,
                            password=self.password)

        if webmacro:
            response = api.download_proxy_webmacro(self.proxy_name)
            extension = 'webmacro'
        elif setting:
            response = api.download_proxy_setting(self.proxy_name)
            extension = 'xml'
        else:
            Logger.app.error("Please enter a file type to download.")
            sys.exit(ExitStatus.failure)

        APIHelper().check_for_response_errors(response)

        try:
            with open('{0}-proxy.{1}'.format(self.proxy_name, extension),
                      'wb') as f:
                Logger.app.info(
                    'Scan results file is available: {0}-proxy.{1}'.format(
                        self.proxy_name, extension))
                f.write(response.data)
        except UnboundLocalError as e:
            Logger.app.error('Error saving file locally {}'.format(e))
            sys.exit(ExitStatus.failure)
コード例 #3
0
    def create_scan(self):
        """
        Launches and monitors a scan
        :return: If scan was able to launch, scan_id. Otherwise none.
        """
        try:
            Logger.app.debug("Creating Scan in webinspect client")
            overrides = json.dumps(webinspectjson.formatted_settings_payload(self.settings, self.scan_name, self.runenv,
                                                                             self.scan_mode, self.scan_scope,
                                                                             self.login_macro,
                                                                             self.scan_policy, self.scan_start,
                                                                             self.start_urls, self.workflow_macros,
                                                                             self.allowed_hosts))

            api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
            response = api.create_scan(overrides)

            if response.response_code == 401:
                Logger.app.critical("An Authorization Error occured.")
                sys.exit(ExitStatus.failure)
            logger_response = json.dumps(response, default=lambda o: o.__dict__, sort_keys=True)
            Logger.app.debug("Request sent to {0}:\n{1}".format(self.url, overrides))
            Logger.app.debug("Response from {0}:\n{1}\n".format(self.url, logger_response))

            if response.success:
                scan_id = response.data['ScanId']
                sys.stdout.write(str('WebInspect scan launched on {0} your scan id: {1}\n'.format(self.url, scan_id)))
            else:
                Logger.app.error("No scan was launched!\n {}".format(response.message))
                sys.exit(ExitStatus.failure)
            return scan_id

        except (ValueError, UnboundLocalError) as e:
            Logger.app.error("Creating the WebInspect scan failed! {}".format(e))
コード例 #4
0
 def export_scan_results(self, scan_id, extension):
     """
     Save scan results to file
     :param scan_id:
     :param extension:
     :return:
     """
     # Export scan as a xml for Threadfix or other Vuln Management System
     Logger.app.info('Exporting scan: {} as {}'.format(scan_id, extension))
     detail_type = 'Full' if extension == 'xml' else None
     api = WebInspectApi(self.url,
                         verify_ssl=False,
                         username=self.username,
                         password=self.password)
     response = api.export_scan_format(scan_id, extension, detail_type)
     if response.response_code == 401:
         Logger.app.critical(
             "An authentication error occurred, exporting scan results!")
         sys.exit(ExitStatus.failure)
     if response.success:
         try:
             with open('{0}.{1}'.format(self.scan_name, extension),
                       'wb') as f:
                 Logger.app.debug(
                     str('Scan results file is available: {0}.{1}\n'.format(
                         self.scan_name, extension)))
                 f.write(response.data)
                 print(
                     str('Scan results file is available: {0}.{1}\n'.format(
                         self.scan_name, extension)))
         except UnboundLocalError as e:
             Logger.app.error('Error saving file locally! {}'.format(e))
     else:
         Logger.app.error('Unable to retrieve scan results! {} '.format(
             response.message))
コード例 #5
0
 def policy_exists(self, policy_guid):
     # true if policy exists
     api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
     response = api.get_policy_by_guid(policy_guid)
     if response.response_code == 401:
         Logger.app.critical("An Authorization Error occured.")
         sys.exit(ExitStatus.failure)
     return response.success
コード例 #6
0
ファイル: proxy.py プロジェクト: vanbenschoten/webbreaker
    def _verify_proxy_server(self, server):
        api = WebInspectApi(server,
                            verify_ssl=False,
                            username=self.username,
                            password=self.password)
        response = api.get_proxy_information(self.proxy_name)
        APIHelper().check_for_response_errors(response)

        return response.data
コード例 #7
0
ファイル: wiswag.py プロジェクト: matt-fevold/webbreaker
class WebInspectWiswag:
    def __init__(self, url, wiswag_name, username=None, password=None, server=None):
        auth_config = WebInspectAuth()
        self.wiswag_name = wiswag_name
        self.host = server
        self.username, self.password = auth_config.authenticate(username, password)

        if self.host is None:
            self.host = self.get_endpoint()

        self.api = WebInspectApi(self.host, verify_ssl=False, username=self.username, password=self.password)
        self.wiswag(url)

    def wiswag(self, url):
        if self.wiswag_name is None:
            self._generate_random_wiswag_name()

        self.api.create_wiswag(url, self.wiswag_name)

        # go through the settings list 3 times (~15 secs before timeout)
        for i in range(3):
            response = self.api.list_settings()
            APIHelper().check_for_response_errors(response)
            if response.data is not None:
                for settingListName in response.data:
                    if settingListName == self.wiswag_name:
                        Logger.app.info("Found wiswag_name: {}".format(self.wiswag_name))
                        self._download_wiswag(self.wiswag_name)
                        sys.exit(ExitStatus.success)
            else:
                Logger.app.info("Fail to find wiswag_name {}. Retrying".format(self.wiswag_name))
                sleep(5)
        Logger.app.error("Timeout error: Can not find wiswag_name {}".format(self.wiswag_name))

    def _download_wiswag(self, wiswag_name):
        response = self.api.download_settings(wiswag_name)
        extension = 'xml'

        try:
            with open('{0}.{1}'.format(wiswag_name, extension), 'wb') as f:
                f.write(response.data)
        except UnboundLocalError as e:
            Logger.app.error('Error saving file locally {}'.format(e))
            sys.exit(ExitStatus.failure)

    def _generate_random_wiswag_name(self):
        self.wiswag_name = "wiswag" + "-" + "".join(
            random.choice(string.ascii_uppercase + string.digits) for _ in range(5))

    def get_endpoint(self):
        jit_scheduler = WebInspectJitScheduler(username=self.username,
                                               password=self.password)
        Logger.app.info("Querying WebInspect scan engines for availability.")

        endpoint = jit_scheduler.get_endpoint()
        return endpoint
コード例 #8
0
 def get_policy_by_name(self, policy_name):
     api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
     response = api.get_policy_by_name(policy_name)
     if response.response_code == 401:
         Logger.app.critical("An authentication error occured, retrieving the policy name!")
         sys.exit(ExitStatus.failure)
     if response.success:
         return response.data
     else:
         return None
コード例 #9
0
ファイル: proxy.py プロジェクト: vanbenschoten/webbreaker
    def _list_proxy(self, server):
        if self.proxy_name is None:
            self._generate_random_proxy_name()
        api = WebInspectApi(server,
                            verify_ssl=False,
                            username=self.username,
                            password=self.password)

        response = api.list_proxies()
        APIHelper().check_for_response_errors(response)
        return response.data
コード例 #10
0
ファイル: wiswag.py プロジェクト: matt-fevold/webbreaker
    def __init__(self, url, wiswag_name, username=None, password=None, server=None):
        auth_config = WebInspectAuth()
        self.wiswag_name = wiswag_name
        self.host = server
        self.username, self.password = auth_config.authenticate(username, password)

        if self.host is None:
            self.host = self.get_endpoint()

        self.api = WebInspectApi(self.host, verify_ssl=False, username=self.username, password=self.password)
        self.wiswag(url)
コード例 #11
0
ファイル: proxy.py プロジェクト: vanbenschoten/webbreaker
    def _delete_proxy(self, server):
        api = WebInspectApi(server,
                            verify_ssl=False,
                            username=self.username,
                            password=self.password)

        response = api.delete_proxy(self.proxy_name)
        APIHelper().check_for_response_errors(response)

        Logger.app.info("Proxy: '{0}' deleted from '{1}'".format(
            self.proxy_name, server))
コード例 #12
0
 def get_scan_status(self, scan_guid):
     api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
     try:
         response = api.get_current_status(scan_guid)
         if response.response_code == 401:
             Logger.app.critical("An Authorization Error occured.")
             sys.exit(ExitStatus.failure)
         status = json.loads(response.data_json())['ScanStatus']
         return status
     except (ValueError, UnboundLocalError, TypeError) as e:
         Logger.app.error("get_scan_status failed: {}".format(e))
         return "Unknown"
コード例 #13
0
    def list_webmacros(self):
        try:
            api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
            response = api.list_webmacros()
            if response.response_code == 401:
                Logger.app.critical("An Authorization Error occured.")
                sys.exit(ExitStatus.failure)
            if response.success:
                for webmacro in response.data:
                    Logger.console.info("{}".format(webmacro))
            else:
                Logger.app.error("{}".format(response.message))

        except (ValueError, UnboundLocalError) as e:
            Logger.app.error("list_webmacros failed: {}".format(e))
コード例 #14
0
ファイル: proxy.py プロジェクト: vanbenschoten/webbreaker
    def _upload_proxy(self, upload_file, server):
        try:
            api = WebInspectApi(server,
                                verify_ssl=False,
                                username=self.username,
                                password=self.password)
            response = api.upload_webmacro_proxy(self.proxy_name, upload_file)
            APIHelper().check_for_response_errors(response)

            Logger.app.info("Uploaded '{0}' to '{1}' on: {2}.".format(
                upload_file, self.proxy_name, server))

        except (ValueError, UnboundLocalError) as e:
            Logger.app.error("Error uploading policy {}".format(e))
            sys.exit(ExitStatus.failure)
コード例 #15
0
    def upload_webmacros(self):
        try:
            for webmacro in self.webinspect_upload_webmacros:
                api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
                response = api.upload_webmacro(webmacro)
                if response.response_code == 401:
                    Logger.app.critical("An Authorization Error occured.")
                    sys.exit(ExitStatus.failure)
                if response.success:
                    Logger.console.debug("Uploaded webmacro {} to server.".format(webmacro))
                else:
                    Logger.app.error("Error uploading webmacro {0}. {1}".format(webmacro, response.message))

        except (ValueError, UnboundLocalError) as e:
            logexceptionhelper.LogErrorUploading("webmacro", e)
            logexceptionhelper.LogNoWebInspectServerFound(e)
コード例 #16
0
    def __settings_exists__(self):
        try:
            api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
            response = api.list_settings()
            if response.response_code == 401:
                Logger.app.critical("An Authorization Error occured.")
                sys.exit(ExitStatus.failure)
            if response.success:
                for setting in response.data:
                    if setting in self.settings:
                        return True

        except (ValueError, UnboundLocalError) as e:
            Logger.app.error("Unable to determine if setting file exists, scan will continue without setting!"
                             "Error: {}".format(e))
        return False
コード例 #17
0
 def wait_for_scan_status_change(self, scan_id):
     """
     Blocking call, will remain in this method until status of scan changes
     :param scan_id:
     :return:
     """
     # WebInspect Scan has started, wait here until it's done
     api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
     response = api.wait_for_status_change(scan_id)  # this line is the blocker
     if response.response_code == 401:
         Logger.app.critical("An Authorization Error occured.")
         sys.exit(ExitStatus.failure)
     if response.success:
         Logger.console.debug('Scan status {}'.format(response.data))
     else:
         Logger.app.debug('Scan status not known because: {}'.format(response.message))
コード例 #18
0
ファイル: proxy.py プロジェクト: vanbenschoten/webbreaker
    def _get_proxy_certificate(self, server):
        path = Config().cert
        api = WebInspectApi(server,
                            verify_ssl=False,
                            username=self.username,
                            password=self.password)

        response = api.cert_proxy()
        APIHelper().check_for_response_errors(response)

        try:
            with open(path, 'wb') as f:
                f.write(response.data)
                Logger.app.info(
                    'Certificate has downloaded to\t:\t{}'.format(path))
        except UnboundLocalError as e:
            Logger.app.error('Error saving certificate locally {}'.format(e))
コード例 #19
0
    def upload_policy(self):
        # if a policy of the same name already exists, delete it prior to upload
        try:
            api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
            # bit of ugliness here. I'd like to just have the policy name at this point but I don't
            # so find it in the full path
            # TODO: Verify split here
            response = api.get_policy_by_name(ntpath.basename(self.webinspect_upload_policy).split('.')[0])
            if response.response_code == 401:
                Logger.app.critical("An Authorization Error occured.")
                sys.exit(ExitStatus.failure)
            if response.success and response.response_code == 200:  # the policy exists on the server already
                api = webinspectapi.WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
                response = api.delete_policy(response.data['uniqueId'])
                if response.success:
                    Logger.app.debug("Deleted policy {} from server".format(
                        ntpath.basename(self.webinspect_upload_policy).split('.')[0]))
        except (ValueError, UnboundLocalError, TypeError) as e:
            Logger.app.error("Verify if deletion of existing policy failed: {}".format(e))

        try:
            api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
            response = api.upload_policy(self.webinspect_upload_policy)
            if response.response_code == 401:
                Logger.app.critical("An Authorization Error occured.")
                sys.exit(ExitStatus.failure)
            if response.success:
                Logger.console.debug("Uploaded policy {} to server.".format(self.webinspect_upload_policy))
            else:
                Logger.app.error("Error uploading policy {0}. {1}".format(self.webinspect_upload_policy,
                                                                          response.message))

        except (ValueError, UnboundLocalError, TypeError, NameError) as e:
            logexceptionhelper.LogErrorUploading("policy", e)
            logexceptionhelper.LogNoWebInspectServerFound(e)
コード例 #20
0
    def get_scan_issues(self, scan_name=None, scan_guid=None, pretty=False):
        try:

            if scan_name:
                api = WebInspectApi(self.url,
                                    verify_ssl=False,
                                    username=self.username,
                                    password=self.password)
                response = api.get_scan_by_name(scan_name)
                if response.response_code == 401:
                    Logger.app.critical(
                        "An authentication error occurred, retrieving scan issues!"
                    )
                    sys.exit(ExitStatus.failure)
                if response.success:
                    scan_guid = response.data[0]['ID']
                else:
                    Logger.app.error(response.message)
                    return None

            api = WebInspectApi(self.url,
                                verify_ssl=False,
                                username=self.username,
                                password=self.password)
            response = api.get_scan_issues(scan_guid)
            if response.response_code == 401:
                Logger.app.critical("An authentication error occurred!")
                sys.exit(ExitStatus.failure)
            if response.success:
                return response.data_json(pretty=True)
            else:
                return None
        except (ValueError, UnboundLocalError) as e:
            Logger.app.error(
                "There was an error getting scan issues: {}".format(e))
コード例 #21
0
    def get_scan_log(self, scan_name=None, scan_guid=None):
        try:

            if scan_name:
                api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
                response = api.get_scan_by_name(scan_name)
                if response.response_code == 401:
                    Logger.app.critical("An an authentication error occurred while retrieving scan name!")
                    sys.exit(ExitStatus.failure)
                if response.success:
                    scan_guid = response.data[0]['ID']
                else:
                    Logger.app.error(response.message)
                    return None

            api = WebInspectApi(self.url, verify_ssl=False, username=self.username, password=self.password)
            response = api.get_scan_log(scan_guid)
            if response.response_code == 401:
                Logger.app.critical("An authentication error occurred while reading the scan log!")
                sys.exit(ExitStatus.failure)
            if response.success:
                return response.data_json()
            else:
                return None
        except (ValueError, UnboundLocalError) as e:
            Logger.app.error("get_scan_log failed: {}".format(e))
コード例 #22
0
 def _set_api(self):
     self.api = WebInspectApi(self.host,
                              verify_ssl=False,
                              username=self.username,
                              password=self.password)
コード例 #23
0
class WebInspectAPIHelper(object):
    def __init__(self,
                 host=None,
                 username=None,
                 password=None,
                 webinspect_setting_overrides=None,
                 silent=False):
        # If a host is passed then we are doing a download or a list,  otherwise a scan.
        self.host = host
        self.username = username
        self.password = password

        # if - we are running a webinspect scan
        if webinspect_setting_overrides is not None:
            self.setting_overrides = webinspect_setting_overrides
            # set the host to be the available endpoint
            self.host = self.setting_overrides.endpoint
        else:
            self.setting_overrides = None

        self._set_api()

        self.silent = silent

        if self.silent is False:  # want to be able to hide this output for multithreading
            webinspect_logexceptionhelp.log_info_using_webinspect_server(
                self.host)

    def _set_api(self):
        self.api = WebInspectApi(self.host,
                                 verify_ssl=False,
                                 username=self.username,
                                 password=self.password)

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def create_scan(self):
        """
        Launches and monitors a scan
        :return: If scan was able to launch, scan_id. Otherwise none.
        """
        try:
            Logger.app.debug("Creating Scan in webinspect client")
            overrides = json.dumps(
                webinspectjson.formatted_settings_payload(
                    self.setting_overrides.settings,
                    self.setting_overrides.scan_name,
                    self.setting_overrides.runenv,
                    self.setting_overrides.scan_mode,
                    self.setting_overrides.scan_scope,
                    self.setting_overrides.login_macro,
                    self.setting_overrides.scan_policy,
                    self.setting_overrides.scan_start,
                    self.setting_overrides.start_urls,
                    self.setting_overrides.workflow_macros,
                    self.setting_overrides.allowed_hosts))
            response = self.api.create_scan(overrides)

            logger_response = json.dumps(response,
                                         default=lambda o: o.__dict__,
                                         sort_keys=True)
            Logger.app.debug("Request sent to {0}:\n{1}".format(
                self.setting_overrides.endpoint, overrides))
            Logger.app.debug("Response from {0}:\n{1}\n".format(
                self.setting_overrides.endpoint, logger_response))

            scan_id = response.data['ScanId']
            webinspect_logexceptionhelp.log_info_scan_start(
                self.setting_overrides.endpoint, scan_id)
            return scan_id

        except (ValueError, UnboundLocalError) as e:
            webinspect_logexceptionhelp.log_error_scan_start_failed(e)
            sys.exit(ExitStatus.failure)

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def export_scan_results(self, scan_id, extension, scan_name=None):
        """
        Save scan results to file, if you pass a scan name it will have that name, otherwise it will read from the
            overrides for the scan name
        :param scan_id:
        :param extension:
        :param scan_name: name of scan to be saved locally
        :return:
        """
        # Export scan as a xml for Threadfix or other Vuln Management System
        Logger.app.info('Exporting scan: {} as {}'.format(scan_id, extension))
        detail_type = 'Full' if extension == 'xml' else None
        response = self.api.export_scan_format(scan_id, extension, detail_type)
        #APIHelper().check_for_response_errors(response)

        # setting_overrides is on a webinspect scan
        if scan_name == None:
            scan_name = self.setting_overrides.scan_name

        try:
            with open('{0}.{1}'.format(scan_name, extension), 'wb') as f:
                f.write(response.data)
                webinspect_logexceptionhelp.log_info_successful_scan_export(
                    scan_name, extension)
        except (UnboundLocalError, IOError) as e:
            webinspect_logexceptionhelp.log_error_failed_scan_export(e)

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def get_policy_by_guid(self, policy_guid):
        response = self.api.get_policy_by_guid(policy_guid)
        #APIHelper().check_for_response_errors(response)

        return response.data

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def get_policy_by_name(self, policy_name):
        response = self.api.get_policy_by_name(policy_name)
        #APIHelper().check_for_response_errors(response)

        return response.data

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def get_scan_by_name(self, scan_name):
        """
        Search Webinspect server for a scan matching scan_name
        :param scan_name:
        :return: List of search results
        """
        # scan_name = self._trim_ext(scan_name)

        response = self.api.get_scan_by_name(scan_name)
        #APIHelper().check_for_response_errors(response)

        return response.data

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def get_scan_status(self, scan_guid):
        """
        Get scan status from the Webinspect server
        :param scan_guid:
        :return: Current status of scan
        """
        try:
            response = self.api.get_current_status(scan_guid)
            #APIHelper().check_for_response_errors(response)

            status = json.loads(response.data_json())['ScanStatus']
            return status
        except (ValueError, TypeError, UnboundLocalError) as e:
            webinspect_logexceptionhelp.log_error_get_scan_status(e)
            return None

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def list_scans(self):
        """
        List all scans found on host
        :return: response.data from the Webinspect server
        """
        try:
            response = self.api.list_scans()
            #APIHelper().check_for_response_errors(response)

            return response.data

        except (ValueError, UnboundLocalError, NameError) as e:
            webinspect_logexceptionhelp.log_error_list_scans(e)

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def list_running_scans(self):
        """
        List all running scans on host
        :return:
        """
        response = self.api.list_running_scans()

        return response

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def policy_exists(self, policy_guid):
        # true if policy exists
        response = self.api.get_policy_by_guid(policy_guid)
        #APIHelper().check_for_response_errors(response)
        return response.success

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def stop_scan(self, scan_guid):
        response = self.api.stop_scan(scan_guid)
        #APIHelper().check_for_response_errors(response)
        return response.success

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def upload_policy(self):
        # if a policy of the same name already exists, delete it prior to upload
        try:
            # bit of ugliness here. I'd like to just have the policy name at this point but I don't
            # so find it in the full path
            # TODO: Verify split here
            response = self.api.get_policy_by_name(
                ntpath.basename(
                    self.setting_overrides.webinspect_upload_policy).split('.')
                [0])
            #APIHelper().check_for_response_errors(response)

            if response.success and response.response_code == 200:  # the policy exists on the server already
                response = self.api.delete_policy(response.data['uniqueId'])
                #APIHelper().check_for_response_errors(response)

                Logger.app.debug("Deleted policy {} from server".format(
                    ntpath.basename(
                        self.setting_overrides.webinspect_upload_policy).split(
                            '.')[0]))
        except (ValueError, UnboundLocalError, TypeError) as e:
            webinspect_logexceptionhelp.log_error_policy_deletion(e)

        try:
            response = self.api.upload_policy(
                self.setting_overrides.webinspect_upload_policy)
            #APIHelper().check_for_response_errors(response)
            Logger.console.debug("Uploaded policy {} to server.".format(
                self.setting_overrides.webinspect_upload_policy))

        except (ValueError, UnboundLocalError, TypeError, NameError) as e:
            webinspect_logexceptionhelp.log_error_uploading("policy", e)
            webinspect_logexceptionhelp.log_no_webinspect_server_found(e)

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def upload_settings(self):

        try:
            response = self.api.upload_settings(
                self.setting_overrides.webinspect_upload_settings)
            #APIHelper().check_for_response_errors(response)

            Logger.console.debug("Uploaded settings {} to server.".format(
                self.setting_overrides.webinspect_upload_settings))

        except (ValueError, UnboundLocalError, NameError) as e:
            webinspect_logexceptionhelp.log_error_uploading("settings", e)
            webinspect_logexceptionhelp.log_no_webinspect_server_found(e)

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def upload_webmacros(self):
        try:
            for webmacro in self.setting_overrides.webinspect_upload_webmacros:
                response = self.api.upload_webmacro(webmacro)
                #APIHelper().check_for_response_errors(response)
                Logger.console.debug(
                    "Uploaded webmacro {} to server.".format(webmacro))

        except (ValueError, UnboundLocalError) as e:
            webinspect_logexceptionhelp.log_error_uploading("webmacro", e)
            webinspect_logexceptionhelp.log_no_webinspect_server_found(e)

    @CircuitBreaker(fail_max=5, reset_timeout=60)
    def verify_scan_policy(self, config):
        try:
            if self.setting_overrides.scan_policy:
                # two happy paths: either the provided policy refers to an existing builtin policy, or it refers to
                # a local policy we need to first upload and then use.

                built_in = self._check_if_built_in(config)

                if built_in:
                    idx = self._get_index(config)

                    policy_guid = config.mapped_policies[idx[0]][1]
                    Logger.app.info(
                        "scan_policy {} with policyID {} has been selected.".
                        format(self.setting_overrides.scan_policy,
                               policy_guid))
                    Logger.app.info(
                        "Checking to make sure a policy with that ID exists in WebInspect."
                    )
                    if not self.policy_exists(policy_guid):
                        Logger.app.error(
                            "Scan policy {} cannot be located on the WebInspect server. Stopping"
                            .format(self.setting_overrides.scan_policy))
                        sys.exit(ExitStatus.failure)
                    else:
                        Logger.app.info(
                            "Found policy {} in WebInspect.".format(
                                policy_guid))
                else:
                    # Not a builtin. Assume that caller wants the provided policy to be uploaded
                    Logger.app.info(
                        "Provided scan policy is not built-in, so will assume it needs to be uploaded."
                    )
                    self.upload_policy()
                    policy = self.get_policy_by_name(
                        self.setting_overrides.scan_policy)
                    if policy:
                        policy_guid = policy['uniqueId']
                    else:
                        Logger.app.error(
                            "The policy name is either incorrect or not available in {}."
                            .format('.webbreaker/etc/webinspect/policies'))
                        sys.exit(ExitStatus.failure)

                # Change the provided policy name into the corresponding policy id for scan creation.
                policy_id = self.get_policy_by_guid(policy_guid)['id']
                self.setting_overrides.scan_policy = policy_id
                Logger.app.debug("New scan policy has been set")

            else:
                Logger.app.debug(
                    "No WebInspect Scan Override Policy was selected: {}!".
                    format(self.setting_overrides.scan_policy))

        except (UnboundLocalError, NameError) as e:
            webinspect_logexceptionhelp.log_no_webinspect_server_found(e)

    def _check_if_built_in(self, config):
        """
        check if scan policy is a built in, this is abstracted from verify_scan_policy so it can be mocked.
        :param config:
        :return:
        """
        if str(self.setting_overrides.scan_policy).lower() in [
                str(x[0]).lower() for x in config.mapped_policies
        ]:
            return True
        else:
            return False

    def _get_index(self, config):
        """
        # wow what a list comprehension. not a single comment - this was added posthumously.
        this was abstracted from verify_scan_policy so mocking could occur.
        :param config:
        :return:
        """
        index = [
            x for x, y in enumerate(config.mapped_policies)
            if y[0] == str(self.setting_overrides.scan_policy).lower()
        ]

        return index