Example #1
0
    def test_sandbox_api_build_id(self):
        """
        Test the SandboxAPI build_id property
        """
        sandbox_api = SandboxAPI(
            app_id=constants.VALID_SANDBOX_API["app_id"],
            sandbox_name=constants.VALID_SANDBOX_API["sandbox_name"],
        )

        # Succeed when getting a valid build_id property
        self.assertIsInstance(sandbox_api.build_id, str)

        # Succeed when setting the build_id property to a valid value
        self.assertIsNone(
            setattr(sandbox_api, "build_id",
                    constants.VALID_SANDBOX_API["build_id"]))

        # Fail when attempting to set the build_id property to an invalid value
        self.assertRaises(
            ValueError,
            setattr,
            sandbox_api,
            "build_id",
            constants.INVALID_SANDBOX_API_BUILD_ID["build_id"],
        )

        # Fail when attempting to get the build_id property when it contains an
        # invalid value
        sandbox_api._build_id = (  # pylint: disable=protected-access
            constants.INVALID_SANDBOX_API_BUILD_ID["build_id"])
        self.assertRaises(ValueError, getattr, sandbox_api, "build_id")

        # Fail when attempting to delete the build_id property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, sandbox_api, "build_id")
Example #2
0
    def test_sandbox_api_version(self):
        """
        Test the SandboxAPI version property
        """
        sandbox_api = SandboxAPI(
            app_id=constants.VALID_SANDBOX_API["app_id"],
            sandbox_name=constants.VALID_SANDBOX_API["sandbox_name"],
        )

        # Succeed when getting a valid version property
        self.assertIsInstance(sandbox_api.version, dict)

        # Succeed when setting the version property to a valid value
        self.assertIsNone(
            setattr(sandbox_api, "version",
                    constants.VALID_SANDBOX_API["version"]))

        # Fail when attempting to set the version property to an invalid value
        self.assertRaises(
            ValueError,
            setattr,
            sandbox_api,
            "version",
            constants.INVALID_SANDBOX_API_INCORRECT_VERSION_VALUES["version"],
        )

        # Fail when attempting to get the version property when it contains an
        # invalid value
        sandbox_api._version = constants.INVALID_SANDBOX_API_INCORRECT_VERSION_VALUES[  # pylint: disable=protected-access
            "version"]
        self.assertRaises(ValueError, getattr, sandbox_api, "version")

        # Fail when attempting to delete the version property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, sandbox_api, "version")
    def test_create_sandbox(self):
        """
        Test the create_sandbox function
        """
        # Succeed when calling the create_sandbox function and the api call
        # gets a valid response
        with patch.object(
            SandboxAPI,
            "http_post",
            return_value=test_constants.VALID_SANDBOX_CREATESANDBOX_API_RESPONSE_XML[
                "Element"
            ],
        ):
            with patch("veracode.api.get_app_id", return_value="1337"):
                sandbox_api = SandboxAPI(
                    app_name="31337", sandbox_name="Project Security"
                )
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertEqual(
                    submit_artifacts.create_sandbox(sandbox_api=sandbox_api), "1111111"
                )

            # Raise a RuntimeError when element_contains_error returns True
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=True
            ):
                self.assertRaises(
                    RuntimeError,
                    submit_artifacts.create_sandbox,
                    sandbox_api=sandbox_api,
                )

        # Raise a RuntimeError when calling the create_sandbox function and the
        # api call gets a response, but does not contain the requested
        # sandbox_name
        with patch.object(
            SandboxAPI,
            "http_post",
            return_value=test_constants.INVALID_SANDBOX_CREATESANDBOX_API_RESPONSE_XML_NO_SANDBOX[
                "Element"
            ],
        ):
            with patch("veracode.api.get_app_id", return_value="1337"):
                sandbox_api = SandboxAPI(
                    app_name="TestApp", sandbox_name="Project Security"
                )
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertRaises(
                    RuntimeError,
                    submit_artifacts.create_sandbox,
                    sandbox_api=sandbox_api,
                )
    def test_get_sandbox_id(self):
        """
        Test the get_sandbox_id function
        """
        # Succeed when calling the get_sandbox_id function and the api call
        # gets a valid response
        with patch.object(
            SandboxAPI,
            "http_get",
            return_value=test_constants.VALID_SANDBOX_GETSANDBOXLIST_API_RESPONSE_XML[
                "Element"
            ],
        ):
            with patch("veracode.api.get_app_id", return_value="1337"):
                sandbox_api = SandboxAPI(
                    app_name="TestApp", sandbox_name="Project Security"
                )
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertEqual(
                    submit_artifacts.get_sandbox_id(sandbox_api=sandbox_api),
                    "111111111",
                )

            # Raise a RuntimeError when element_contains_error returns True
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=True
            ):
                self.assertRaises(
                    RuntimeError,
                    submit_artifacts.get_sandbox_id,
                    sandbox_api=sandbox_api,
                )

        # Return None when calling the get_sandbox_id function and the api call
        # gets a valid response, but does not contain the requested
        # sandbox_name
        with patch.object(
            SandboxAPI,
            "http_get",
            return_value=test_constants.VALID_SANDBOX_GETSANDBOXLIST_API_RESPONSE_XML[
                "Element"
            ],
        ):
            with patch("veracode.api.get_app_id", return_value="1337"):
                sandbox_api = SandboxAPI(
                    app_name="TestApp", sandbox_name="Unknown Sandbox Name"
                )
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertIsNone(
                    submit_artifacts.get_sandbox_id(sandbox_api=sandbox_api)
                )
Example #5
0
    def test_sandbox_api_app_name(self):
        """
        Test the SandboxAPI app_name property
        """
        # Fail when attempting to create an SandboxAPI object when the app_name
        # property wasn't provided to the constructor
        self.assertRaises(TypeError, SandboxAPI)

        # Succeed when creating an SandboxAPI object when the app_name property is
        # properly provided to the constructor
        with patch("veracode.api.get_app_id",
                   return_value=constants.VALID_UPLOAD_API["app_id"]):
            sandbox_api = SandboxAPI(
                app_name=constants.VALID_SANDBOX_API["app_name"],
                sandbox_name=constants.VALID_SANDBOX_API["sandbox_name"],
            )

        self.assertIsInstance(getattr(sandbox_api, "app_name"), str)

        # Succeed when setting the app_name property to a valid value
        self.assertIsNone(
            setattr(sandbox_api, "app_name",
                    constants.VALID_SANDBOX_API["app_name"]))

        # Succeed when getting a valid app_name property
        self.assertIsInstance(sandbox_api.app_name, str)

        # Fail when attempting to set the app_name property to an invalid value
        self.assertRaises(
            ValueError,
            setattr,
            sandbox_api,
            "app_name",
            constants.INVALID_RESULTS_API_INCORRECT_APP_NAME["app_name"],
        )

        # Fail when attempting to get the app_name property when it contains an
        # invalid value
        sandbox_api._app_name = constants.INVALID_RESULTS_API_INCORRECT_APP_NAME[  # pylint: disable=protected-access
            "app_name"]
        self.assertRaises(ValueError, getattr, sandbox_api, "app_name")

        # Fail when attempting to delete the app_name property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, sandbox_api, "app_name")
Example #6
0
    def test_sandbox_api_sandbox_id(self):
        """
        Test the SandboxAPI sandbox_id property
        """
        with patch("veracode.api.get_app_id",
                   return_value=constants.VALID_UPLOAD_API["app_id"]):
            sandbox_api = SandboxAPI(
                app_name=constants.VALID_SANDBOX_API["app_name"],
                sandbox_name=constants.VALID_SANDBOX_API["sandbox_name"],
            )

        # Succeed when getting a the default sandbox_id property
        self.assertIsNone(sandbox_api.sandbox_id)

        # Succeed when setting the sandbox_id property to a valid value
        self.assertIsNone(setattr(sandbox_api, "sandbox_id", None))
        self.assertIsNone(setattr(sandbox_api, "sandbox_id", "12489"))

        # Succeed when getting a valid sandbox_id property
        self.assertIsInstance(sandbox_api.sandbox_id, str)

        # Fail when attempting to set the sandbox_id property to an invalid
        # value
        self.assertRaises(
            ValueError,
            setattr,
            sandbox_api,
            "sandbox_id",
            12489,
        )

        # Fail when attempting to get the sandbox_id property when it contains
        # an invalid value
        sandbox_api._sandbox_id = 12489  # pylint: disable=protected-access
        self.assertRaises(ValueError, getattr, sandbox_api, "sandbox_id")

        # Fail when attempting to delete the sandbox_id property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, sandbox_api, "sandbox_id")
Example #7
0
    def test_apply_config(self):
        """
        Test the apply_config function
        """
        configuration = copy.deepcopy(test_constants.CLEAN_EFFECTIVE_CONFIG)

        # Succeed when calling the apply_config function with a valid
        # Upload API object and config
        upload_api = UploadAPI(app_id="31337")
        applied_upload_api = config.apply_config(api=upload_api, config=configuration)
        self.assertEqual(applied_upload_api, upload_api)

        # Succeed when calling the apply_config function with a valid
        # Results API object and config
        results_api = ResultsAPI(app_id="31337")
        applied_results_api = config.apply_config(api=results_api, config=configuration)
        self.assertEqual(applied_results_api, results_api)

        # Succeed when calling the apply_config function with a valid
        # Sandbox API object and config
        sandbox_api = SandboxAPI(
            app_id="31337", sandbox_name="easy_sast/fb/jonzeolla/testing"
        )
        applied_sandbox_api = config.apply_config(api=sandbox_api, config=configuration)
        self.assertEqual(applied_sandbox_api, sandbox_api)

        # Ensure calling the apply_config function with different `app_id`s
        # does not result in an object with the same version string (which is
        # unique per-API)
        upload_api = UploadAPI(app_id="31337")
        applied_upload_api = config.apply_config(api=upload_api, config=configuration)
        # Note: This must be different than the above app_id
        results_api = ResultsAPI(app_id="1337")
        applied_results_api = config.apply_config(api=results_api, config=configuration)
        self.assertNotEqual(applied_results_api.version, applied_upload_api.version)

        # Fail when calling the apply_config function with a string instead of
        # an API object
        astring = "wrong type"
        self.assertRaises(
            TypeError, config.apply_config, api=astring, config=configuration
        )

        # Succeed when calling the apply_config function with a valid
        # Results API object and config
        configuration["apis"]["unknown"] = {"a": "b"}
        results_api = ResultsAPI(app_id="31337")
        self.assertEqual(
            config.apply_config(api=results_api, config=configuration), results_api
        )
Example #8
0
    def test_sandbox_api_base_url(self):
        """
        Test the SandboxAPI base_url property
        """
        with patch("veracode.api.get_app_id",
                   return_value=constants.VALID_UPLOAD_API["app_id"]):
            sandbox_api = SandboxAPI(
                app_name=constants.VALID_SANDBOX_API["app_name"],
                sandbox_name=constants.VALID_SANDBOX_API["sandbox_name"],
            )

        # Succeed when getting a valid base_url property
        self.assertIsInstance(sandbox_api.base_url, str)

        # Succeed when setting the base_url property to a valid value
        self.assertIsNone(
            setattr(sandbox_api, "base_url",
                    constants.VALID_SANDBOX_API["base_url"]))

        # Fail when attempting to set the base_url property to an invalid value
        self.assertRaises(
            ValueError,
            setattr,
            sandbox_api,
            "base_url",
            constants.INVALID_SANDBOX_API_INCORRECT_DOMAIN["base_url"],
        )

        # Fail when attempting to get the base_url property when it contains an
        # invalid value
        sandbox_api._base_url = constants.INVALID_SANDBOX_API_INCORRECT_DOMAIN[  # pylint: disable=protected-access
            "base_url"]
        self.assertRaises(ValueError, getattr, sandbox_api, "base_url")

        # Fail when attempting to delete the base_url property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, sandbox_api, "base_url")
Example #9
0
    def test_sandbox_api_sandbox_name(self):
        """
        Test the SandboxAPI sandbox_name property
        """
        sandbox_api = SandboxAPI(
            app_id=constants.VALID_SANDBOX_API["app_id"],
            sandbox_name=constants.VALID_SANDBOX_API["sandbox_name"],
        )

        # Succeed when getting a valid sandbox_name property
        self.assertIsInstance(sandbox_api.sandbox_name, str)

        # Succeed when setting the sandbox_name property to a valid value
        self.assertIsNone(
            setattr(sandbox_api, "sandbox_name",
                    constants.VALID_SANDBOX_API["sandbox_name"]))

        # Fail when attempting to set the sandbox_name property to an invalid
        # value
        self.assertRaises(
            ValueError,
            setattr,
            sandbox_api,
            "sandbox_name",
            constants.INVALID_SANDBOX_API_SANDBOX_NAME["sandbox_name"],
        )

        # Fail when attempting to get the sandbox_name property when it
        # contains an invalid value
        sandbox_api._sandbox_name = constants.INVALID_SANDBOX_API_SANDBOX_NAME[  # pylint: disable=protected-access
            "sandbox_name"]
        self.assertRaises(ValueError, getattr, sandbox_api, "sandbox_name")

        # Fail when attempting to delete the sandbox_name property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, sandbox_api, "sandbox_name")
Example #10
0
def get_sandbox_id(*, sandbox_api: SandboxAPI) -> Union[str, None]:
    """
    Query for and return the sandbox_id

    https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/twPT73YBy_iQvrsGEZamhQ
    """
    try:
        endpoint = "getsandboxlist.do"
        params = {"app_id": sandbox_api.app_id}

        sandboxes = sandbox_api.http_get(endpoint=endpoint, params=params)

        if element_contains_error(parsed_xml=sandboxes):
            LOG.error("Veracode returned an error when attempting to call %s",
                      endpoint)
            raise RuntimeError

        for sandbox in sandboxes:
            if sandbox_api.sandbox_name == sandbox.get("sandbox_name"):
                # Returns the first sandbox_name match as duplicates are not
                # allowed by Veracode
                return sandbox.get("sandbox_id")

        # No sandbox_id exists with the provided sandbox_name
        LOG.info(
            "A sandbox named %s does not exist in application id %s",
            sandbox_api.sandbox_name,
            sandbox_api.app_id,
        )
        return None
    except (
            HTTPError,
            ConnectionError,
            Timeout,
            TooManyRedirects,
            RequestException,
            RuntimeError,
    ) as e:
        raise RuntimeError from e
Example #11
0
def create_sandbox(*, sandbox_api: SandboxAPI) -> str:
    """
    Create a sandbox and return the sandbox_id

    https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/jp8rPey8I5WsuWz7bY2SZg
    """
    try:
        endpoint = "createsandbox.do"
        params = {
            "app_id": sandbox_api.app_id,
            "sandbox_name": sandbox_api.sandbox_name,
        }

        response = sandbox_api.http_post(endpoint=endpoint, params=params)

        if element_contains_error(parsed_xml=response):
            LOG.error("Veracode returned an error when attempting to call %s",
                      endpoint)
            raise RuntimeError

        try:
            # Because we only make one sandbox at a time, we can use index 0 to
            # extract and then return the sandbox_id
            return response[0].get("sandbox_id")
        except (KeyError, IndexError) as e:
            LOG.error(
                "Unable to extract the sandbox_id from the Veracode response")
            raise RuntimeError from e
    except (
            HTTPError,
            ConnectionError,
            Timeout,
            TooManyRedirects,
            RequestException,
            RuntimeError,
    ) as e:
        raise RuntimeError from e
    def test_submit_artifacts(  # pylint: disable=too-many-arguments, too-many-statements
        self,
        mock_get_sandbox_id,
        mock_create_sandbox,
        mock_iterdir,
        mock_setup_scan_prereqs,
        mock_filter_file,
        mock_upload_large_file,
        mock_begin_prescan,
    ):
        """
        Test the submit_artifacts function
        """
        with patch("veracode.api.get_app_id", return_value="1337"):
            upload_api = UploadAPI(app_name=test_constants.VALID_UPLOAD_API["app_name"])
            sandbox_api = SandboxAPI(
                app_name=test_constants.VALID_SANDBOX_API["app_name"],
                sandbox_name=test_constants.VALID_SANDBOX_API["sandbox_name"],
            )

        def iterdir_generator_valid():
            f = test_constants.VALID_FILE["Path"]
            yield f

        def iterdir_generator_invalid():
            f = test_constants.INVALID_FILE["Path"]
            yield f

        ## Testing with sandbox_api set
        # Return True if sandbox_api is set, the sandbox was already created,
        # and everything else follows the Happy Path
        mock_get_sandbox_id.return_value = test_constants.VALID_SANDBOX_API[
            "sandbox_id"
        ]
        mock_create_sandbox.return_value = None  # Unused
        mock_setup_scan_prereqs.return_value = True
        mock_iterdir.return_value = iterdir_generator_valid()
        mock_filter_file.return_value = True
        mock_upload_large_file.return_value = True
        mock_begin_prescan.return_value = True
        self.assertTrue(
            submit_artifacts.submit_artifacts(
                upload_api=upload_api, sandbox_api=sandbox_api
            )
        )

        # Return True if sandbox_api is set, the sandbox wasn't yet created in
        # Veracode, and everything else follows the Happy Path
        mock_get_sandbox_id.return_value = None
        mock_create_sandbox.return_value = test_constants.VALID_SANDBOX_API[
            "sandbox_id"
        ]
        mock_setup_scan_prereqs.return_value = True
        mock_iterdir.return_value = iterdir_generator_valid()
        mock_filter_file.return_value = True
        mock_upload_large_file.return_value = True
        mock_begin_prescan.return_value = True
        self.assertTrue(
            submit_artifacts.submit_artifacts(
                upload_api=upload_api, sandbox_api=sandbox_api
            )
        )

        # Return False if sandbox_api is set, and get_sandbox_id raises a
        # RuntimeError
        with patch(
            "veracode.submit_artifacts.get_sandbox_id", side_effect=RuntimeError
        ):
            mock_get_sandbox_id.return_value = None
            mock_create_sandbox.return_value = None  # Unused
            mock_setup_scan_prereqs.return_value = True  # Unused
            mock_iterdir.return_value = iterdir_generator_valid()  # Unused
            mock_filter_file.return_value = True  # Unused
            mock_upload_large_file.return_value = True  # Unused
            mock_begin_prescan.return_value = True  # Unused
            self.assertFalse(
                submit_artifacts.submit_artifacts(
                    upload_api=upload_api, sandbox_api=sandbox_api
                )
            )

        # Return False if sandbox_api is set, get_sandbox_id returns None, but
        # create_sandbox raises a RuntimeError
        with patch(
            "veracode.submit_artifacts.create_sandbox", side_effect=RuntimeError
        ):
            mock_get_sandbox_id.return_value = None
            mock_create_sandbox.return_value = None
            mock_setup_scan_prereqs.return_value = True  # Unused
            mock_iterdir.return_value = iterdir_generator_valid()  # Unused
            mock_filter_file.return_value = True  # Unused
            mock_upload_large_file.return_value = True  # Unused
            mock_begin_prescan.return_value = True  # Unused
            self.assertFalse(
                submit_artifacts.submit_artifacts(
                    upload_api=upload_api, sandbox_api=sandbox_api
                )
            )

        ## Testing without sandbox_api set
        # Return True if sandbox_api isn't set and everything follows the Happy
        # Path
        mock_get_sandbox_id.return_value = None  # Unused
        mock_create_sandbox.return_value = None  # Unused
        mock_setup_scan_prereqs.return_value = True
        mock_iterdir.return_value = iterdir_generator_valid()
        mock_filter_file.return_value = True
        mock_upload_large_file.return_value = True
        mock_begin_prescan.return_value = True
        self.assertTrue(submit_artifacts.submit_artifacts(upload_api=upload_api))

        # Return False if setup_scan_prereqs returns False
        mock_get_sandbox_id.return_value = None  # Unused
        mock_create_sandbox.return_value = None  # Unused
        mock_setup_scan_prereqs.return_value = False
        mock_iterdir.return_value = iterdir_generator_valid()
        mock_filter_file.return_value = True
        mock_upload_large_file.return_value = True
        mock_begin_prescan.return_value = True
        self.assertFalse(submit_artifacts.submit_artifacts(upload_api=upload_api))

        # Return False if filter_file always returns False, meaning artifacts
        # is empty
        mock_get_sandbox_id.return_value = None  # Unused
        mock_create_sandbox.return_value = None  # Unused
        mock_setup_scan_prereqs.return_value = True
        mock_iterdir.return_value = iterdir_generator_invalid()
        mock_filter_file.return_value = False
        mock_upload_large_file.return_value = True
        mock_begin_prescan.return_value = True
        self.assertFalse(submit_artifacts.submit_artifacts(upload_api=upload_api))

        # Return False if upload_large_file always returns False, meaning
        # something is wrong with the file upload
        mock_get_sandbox_id.return_value = None  # Unused
        mock_create_sandbox.return_value = None  # Unused
        mock_setup_scan_prereqs.return_value = True
        mock_iterdir.return_value = iterdir_generator_valid()
        mock_filter_file.return_value = True
        mock_upload_large_file.return_value = False
        mock_begin_prescan.return_value = True
        self.assertFalse(submit_artifacts.submit_artifacts(upload_api=upload_api))

        # Return False if begin_prescan returns False, meaning the prescan was
        # unable to be started
        mock_get_sandbox_id.return_value = None  # Unused
        mock_create_sandbox.return_value = None  # Unused
        mock_setup_scan_prereqs.return_value = True
        mock_iterdir.return_value = iterdir_generator_valid()
        mock_filter_file.return_value = True
        mock_upload_large_file.return_value = True
        mock_begin_prescan.return_value = False
        self.assertFalse(submit_artifacts.submit_artifacts(upload_api=upload_api))
Example #13
0
def main() -> None:
    """
    Integration with Veracode Static Analysis
    """
    ## Setup logging
    # Format the logs as JSON for simplicity
    formatting = json.dumps(
        {
            "timestamp": "%(asctime)s",
            "namespace": "%(name)s",
            "loglevel": "%(levelname)s",
            "message": "%(message)s",
        }
    )
    # Default to a log level of WARNING until the config is parsed
    logging.basicConfig(level="WARNING", format=formatting)
    log = logging.getLogger(__project_name__)

    # Get the effective config
    try:
        config = get_config()
    except ValueError:
        log.error("Unable to create a valid configuration")
        sys.exit(1)

    # Update the log level to whatever was set in the config
    logging.getLogger().setLevel(config["loglevel"])

    # Create the API objects and apply the config
    try:
        results_api = apply_config(
            api=ResultsAPI(app_id=config["apis"]["results"]["app_id"]), config=config
        )
        upload_api = apply_config(
            api=UploadAPI(app_id=config["apis"]["upload"]["app_id"]), config=config
        )
        if "sandbox_name" in config["apis"]["sandbox"]:
            sandbox_api = apply_config(
                api=SandboxAPI(
                    app_id=config["apis"]["sandbox"]["app_id"],
                    sandbox_name=config["apis"]["sandbox"]["sandbox_name"],
                ),
                config=config,
            )
        else:
            sandbox_api = None
    except (TypeError, NameError):
        log.error("Unable to create valid API objects")
        sys.exit(1)

    # Configure the environment
    for step in config["workflow"]:
        if step == "submit_artifacts":
            configure_environment(
                api_key_id=config["api_key_id"], api_key_secret=config["api_key_secret"]
            )
            success = submit_artifacts(upload_api=upload_api, sandbox_api=sandbox_api)

            if success:
                log.info("Successfully submit build artifacts for scanning")
            else:
                log.error("Failed to submit build artifacts for scanning")
                sys.exit(1)
        elif step == "check_compliance":
            configure_environment(
                api_key_id=config["api_key_id"], api_key_secret=config["api_key_secret"]
            )
            if not check_compliance(results_api=results_api):
                sys.exit(1)