Пример #1
0
def upload_large_file(*, upload_api: UploadAPI, artifact: Path) -> bool:
    """
    https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/lzZ1eON0Bkr8iYjNVD9tqw

    This API call will create a new SAST build for an existing app if one does
    not already exist.  However, it prefers to manage the build versions so it
    can be mapped to code across separate systems
    """
    filename = artifact.name

    endpoint = "uploadlargefile.do"
    params = {"app_id": upload_api.app_id, "filename": filename}
    headers = {"Content-Type": "binary/octet-stream"}

    # If a sandbox_id is specified, add it to the params
    if isinstance(upload_api.sandbox_id, str):
        params["sandbox_id"] = upload_api.sandbox_id

    try:
        with open(artifact, "rb") as f:
            data = f.read()
            upload_api.http_post(
                endpoint=endpoint,
                data=data,
                params=params,
                headers=headers,
            )
        return True
    except:
        LOG.error(
            "Error encountered when attempting to upload %s to the Veracode Upload API",
            filename,
        )
        raise
Пример #2
0
    def test_upload_api_http_post(self, mock_http_request):
        """
        Test the UploadAPI http_post method
        """
        with patch("veracode.api.get_app_id",
                   return_value=constants.VALID_UPLOAD_API["app_id"]):
            upload_api = UploadAPI(
                app_name=constants.VALID_UPLOAD_API["app_name"])

        # Fail when attempting to call the http_post method with invalid
        # arguments
        self.assertRaises(KeyError,
                          upload_api.http_post,
                          endpoint="createuser.do")

        # Succeed when calling the http_post method with valid arguments
        mock_http_request.return_value = (
            constants.VALID_UPLOAD_API_UPLOADLARGEFILE_RESPONSE_XML["Element"])
        self.assertIsInstance(
            upload_api.http_post(endpoint="uploadlargefile.do"),
            InsecureElementTree.Element,
        )

        # Fail when attempting to delete the http_post method, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api, "http_post")
Пример #3
0
    def test_upload_api_base_url(self):
        """
        Test the UploadAPI base_url property
        """
        upload_api = UploadAPI(app_id=constants.VALID_UPLOAD_API["app_id"])

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

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

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

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

        # Fail when attempting to delete the base_url property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api, "base_url")
Пример #4
0
    def test_upload_api_build_id(self):
        """
        Test the UploadAPI build_id property
        """
        with patch("veracode.api.get_app_id",
                   return_value=constants.VALID_UPLOAD_API["app_id"]):
            upload_api = UploadAPI(
                app_name=constants.VALID_UPLOAD_API["app_name"])

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

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

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

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

        # Fail when attempting to delete the build_id property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api, "build_id")
Пример #5
0
    def test_upload_api_auto_scan(self):
        """
        Test the UploadAPI auto_scan property
        """
        upload_api = UploadAPI(app_id=constants.VALID_UPLOAD_API["app_id"])

        # Succeed when getting a valid auto_scan property
        self.assertIsInstance(upload_api.auto_scan, bool)

        # Succeed when setting the auto_scan property to a valid value
        self.assertIsNone(
            setattr(upload_api, "auto_scan",
                    constants.VALID_UPLOAD_API["auto_scan"]))

        # Fail when attempting to set the auto_scan property to an invalid
        # value
        self.assertRaises(
            ValueError,
            setattr,
            upload_api,
            "auto_scan",
            constants.INVALID_UPLOAD_API_AUTO_SCAN["auto_scan"],
        )

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

        # Fail when attempting to delete the auto_scan property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api, "auto_scan")
Пример #6
0
    def test_upload_api_version(self):
        """
        Test the UploadAPI version property
        """
        with patch("veracode.api.get_app_id",
                   return_value=constants.VALID_UPLOAD_API["app_id"]):
            upload_api = UploadAPI(
                app_name=constants.VALID_UPLOAD_API["app_name"])

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

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

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

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

        # Fail when attempting to delete the version property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api, "version")
Пример #7
0
    def test_upload_api_sandbox_id(self):
        """
        Test the UploadAPI sandbox_id property
        """
        upload_api = UploadAPI(app_id=constants.VALID_UPLOAD_API["app_id"])

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

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

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

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

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

        # Fail when attempting to delete the sandbox_id property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api, "sandbox_id")
Пример #8
0
    def test_upload_api_build_dir(self):
        """
        Test the UploadAPI build_dir property
        """
        upload_api = UploadAPI(app_id=constants.VALID_UPLOAD_API["app_id"])

        # Succeed when getting a valid build_dir property
        self.assertIsInstance(upload_api.build_dir, Path)

        # Succeed when setting the build_dir property to a valid value
        self.assertIsNone(
            setattr(upload_api, "build_dir",
                    constants.VALID_UPLOAD_API["build_dir"]))

        # Fail when attempting to set the build_dir property to an invalid
        # value
        self.assertRaises(
            ValueError,
            setattr,
            upload_api,
            "build_dir",
            constants.INVALID_UPLOAD_API_BUILD_DIR["build_dir"],
        )

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

        # Fail when attempting to delete the build_dir property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api, "build_dir")
Пример #9
0
    def test_upload_api__validate(self, mock_is_valid_attribute):
        """
        Test the UploadAPI _validate method
        """
        with patch("veracode.api.get_app_id",
                   return_value=constants.VALID_UPLOAD_API["app_id"]):
            upload_api = UploadAPI(
                app_name=constants.VALID_UPLOAD_API["app_name"])

        # Mock all attributes are invalid
        mock_is_valid_attribute.return_value = False

        # Fail when attempting to call the _validate method, given that the
        # attributes are invalid
        self.assertRaises(
            ValueError,
            upload_api._validate,  # pylint: disable=protected-access
            key="key",
            value="patched to be invalid",
        )

        # Mock all attributes are valid
        mock_is_valid_attribute.return_value = True

        # Succeed when calling the _validate method, given that the attributes
        # are valid
        self.assertTrue(
            upload_api._validate(  # pylint: disable=protected-access
                key="key",
                value="patched to be valid"))

        # Fail when attempting to delete the _validate method, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api, "_validate")
Пример #10
0
    def test_cancel_build(self):
        """
        Test the cancel_build function
        """
        # Succeed when calling the cancel_build function and the api call gets
        # a valid response
        with patch.object(
            UploadAPI,
            "http_get",
            return_value=test_constants.VALID_UPLOAD_API_DELETEBUILD_RESPONSE_XML[
                "Element"
            ],
        ):
            # Policy scan
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api = UploadAPI(app_name="31337")
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertTrue(submit_artifacts.cancel_build(upload_api=upload_api))

            # Sandbox scan
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api.sandbox_id = "12345"
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertTrue(submit_artifacts.cancel_build(upload_api=upload_api))

            # Return False when element_contains_error returns True
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=True
            ):
                self.assertFalse(submit_artifacts.cancel_build(upload_api=upload_api))

        # Return False when calling the cancel_build function and the api call
        # raises a ConnectionError
        with patch.object(
            UploadAPI,
            "http_get",
            return_value=test_constants.VALID_UPLOAD_API_DELETEBUILD_RESPONSE_XML[
                "Element"
            ],
            side_effect=ConnectionError,
        ):
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api = UploadAPI(app_name="31337")
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertFalse(submit_artifacts.cancel_build(upload_api=upload_api))
Пример #11
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
        )
Пример #12
0
def create_build(*, upload_api: UploadAPI) -> bool:
    """
    https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/vhuQ5lMdxRNQWUK1br1mDg
    """
    try:
        endpoint = "createbuild.do"
        params = {"app_id": upload_api.app_id, "version": upload_api.build_id}

        # If a sandbox_id is specified, add it to the params
        if isinstance(upload_api.sandbox_id, str):
            params["sandbox_id"] = upload_api.sandbox_id

        # Create the build
        response = upload_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)
            return False
        return True
    except (
            HTTPError,
            ConnectionError,
            Timeout,
            TooManyRedirects,
            RequestException,
    ):
        LOG.error("Exception encountered when calling the Veracode API")
        return False
Пример #13
0
def begin_prescan(*, upload_api: UploadAPI) -> bool:
    """
    https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/PX5ReM5acqjM~IOVEg2~rA
    """
    endpoint = "beginprescan.do"
    params = {
        "app_id": upload_api.app_id,
        "scan_all_nonfatal_top_level_modules":
        upload_api.scan_all_nonfatal_top_level_modules,
        "auto_scan": upload_api.auto_scan,
    }

    # If a sandbox_id is specified, add it to the params
    if isinstance(upload_api.sandbox_id, str):
        params["sandbox_id"] = upload_api.sandbox_id

    try:
        response = upload_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)
            return False
        return True
    except (
            HTTPError,
            ConnectionError,
            Timeout,
            TooManyRedirects,
            RequestException,
    ):
        LOG.error("Exception encountered when calling the Veracode API")
        return False
Пример #14
0
    def test_upload_api_scan_all_nonfatal_top_level_modules(self):
        """
        Test the UploadAPI scan_all_nonfatal_top_level_modules property
        """
        with patch("veracode.api.get_app_id",
                   return_value=constants.VALID_UPLOAD_API["app_id"]):
            upload_api = UploadAPI(
                app_name=constants.VALID_UPLOAD_API["app_name"])

        # Succeed when getting a valid scan_all_nonfatal_top_level_modules
        # property
        self.assertIsInstance(upload_api.scan_all_nonfatal_top_level_modules,
                              bool)

        # Succeed when setting the scan_all_nonfatal_top_level_modules property
        # to a valid value
        self.assertIsNone(
            setattr(
                upload_api,
                "scan_all_nonfatal_top_level_modules",
                constants.
                VALID_UPLOAD_API["scan_all_nonfatal_top_level_modules"],
            ))

        # Fail when attempting to set the scan_all_nonfatal_top_level_modules
        # property to an invalid value
        self.assertRaises(
            ValueError,
            setattr,
            upload_api,
            "scan_all_nonfatal_top_level_modules",
            constants.INVALID_UPLOAD_API_SCAN_ALL_NONFATAL_TOP_LEVEL_MODULES[
                "scan_all_nonfatal_top_level_modules"],
        )

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

        # Fail when attempting to delete the
        # scan_all_nonfatal_top_level_modules property, because the deleter is
        # intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api,
                          "scan_all_nonfatal_top_level_modules")
Пример #15
0
    def test_upload_api_app_name(self):
        """
        Test the UploadAPI app_name property
        """
        # Fail when attempting to create an UploadAPI object when the app_name
        # property wasn't provided to the constructor
        self.assertRaises(TypeError, UploadAPI)

        # Succeed when creating an UploadAPI 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"]):
            upload_api = UploadAPI(
                app_name=constants.VALID_UPLOAD_API["app_name"])

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

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

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

        # Fail when attempting to set the app_name property to an invalid value
        self.assertRaises(
            ValueError,
            setattr,
            upload_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
        upload_api._app_name = constants.INVALID_RESULTS_API_INCORRECT_APP_NAME[  # pylint: disable=protected-access
            "app_name"]
        self.assertRaises(ValueError, getattr, upload_api, "app_name")

        # Fail when attempting to delete the app_name property, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api, "app_name")
Пример #16
0
    def test_upload_api_http_get(self, mock_http_request):
        """
        Test the UploadAPI http_get method
        """
        upload_api = UploadAPI(app_id=constants.VALID_UPLOAD_API["app_id"])

        # Fail when attempting to call the http_get method with invalid
        # arguments
        self.assertRaises(KeyError,
                          upload_api.http_get,
                          endpoint="getappbuilds.do")

        # Succeed when calling the http_get method with valid arguments
        mock_http_request.return_value = (
            constants.VALID_UPLOAD_API_GETAPPINFO_RESPONSE_XML["Element"])
        self.assertIsInstance(upload_api.http_get(endpoint="getappinfo.do"),
                              InsecureElementTree.Element)

        # Fail when attempting to delete the http_get method, because the
        # deleter is intentionally missing
        self.assertRaises(AttributeError, delattr, upload_api, "http_get")
Пример #17
0
def cancel_build(*, upload_api: UploadAPI) -> bool:
    """
    Cancel an application build

    https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/rERUQewXKGx2D_zaoi6wGw
    """
    try:
        endpoint = "deletebuild.do"
        params = {"app_id": upload_api.app_id}

        # If a sandbox_id is specified, add it to the params
        if isinstance(upload_api.sandbox_id, str):
            params["sandbox_id"] = upload_api.sandbox_id

        # https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/rERUQewXKGx2D_zaoi6wGw
        response = upload_api.http_get(endpoint=endpoint, params=params)

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

        if isinstance(upload_api.sandbox_id, str):
            LOG.info(
                "Successfully cancelled the build in sandbox id %s of application id %s",
                upload_api.sandbox_id,
                upload_api.app_id,
            )
            return True

        LOG.info("Successfully cancelled the build application id %s",
                 upload_api.app_id)
        return True
    except (
            HTTPError,
            ConnectionError,
            Timeout,
            TooManyRedirects,
            RequestException,
            RuntimeError,
    ):
        return False
Пример #18
0
def build_exists(*, upload_api: UploadAPI) -> bool:
    """
    Return whether a build already exists

    https://help.veracode.com/reader/orRWez4I0tnZNaA_i0zn9g/Yjclv0XIfU1v_yqmkt18zA
    """

    try:
        endpoint = "getbuildlist.do"
        params = {"app_id": upload_api.app_id}

        # If a sandbox_id is specified, add it to the params
        if isinstance(upload_api.sandbox_id, str):
            params["sandbox_id"] = upload_api.sandbox_id

        response = upload_api.http_get(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:
            # If we don't throw, at least one build already exists
            response[0].get("build_id")
            return False

        except IndexError:
            # No existing builds
            return True

    except (
            HTTPError,
            ConnectionError,
            Timeout,
            TooManyRedirects,
            RequestException,
            RuntimeError,
    ) as e:
        raise RuntimeError from e
Пример #19
0
    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))
Пример #20
0
    def test_build_exists(self):
        """
        Test the build_exists function
        """
        with patch("veracode.api.get_app_id", return_value="1337"):
            upload_api = UploadAPI(app_name=test_constants.VALID_UPLOAD_API["app_name"])

        with patch.object(
            UploadAPI,
            "http_get",
            return_value=test_constants.VALID_UPLOAD_API_GETBUILDLIST_MISSING_BUILDID_IN_RESPONSE_XML[
                "Element"
            ],
        ):
            # Succeed when no existing build IDs are present
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertTrue(submit_artifacts.build_exists(upload_api=upload_api))

            # 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.build_exists,
                    upload_api=upload_api,
                )

        ## Create Sandbox Scan and have existing build ID
        upload_api.sandbox_id = "12345"
        with patch.object(
            UploadAPI,
            "http_get",
            return_value=test_constants.VALID_UPLOAD_API_GETBUILDLIST_BUILDID_IN_RESPONSE_XML[
                "Element"
            ],
        ):
            # Fail when build already exists
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertFalse(submit_artifacts.build_exists(upload_api=upload_api))

        # Raise RuntimeError when HTTPError occurs
        with patch("veracode.api.VeracodeXMLAPI.http_get") as mock_http:
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                mock_http.side_effect = HTTPError()
                self.assertRaises(
                    RuntimeError,
                    submit_artifacts.build_exists,
                    upload_api=upload_api,
                )

        # Raise RuntimeError when HTTPError occurs
        with patch("veracode.api.VeracodeXMLAPI.http_get") as mock_http:
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                mock_http.side_effect = HTTPError()
                self.assertRaises(
                    RuntimeError,
                    submit_artifacts.build_exists,
                    upload_api=upload_api,
                )
Пример #21
0
    def test_setup_scan_prereqs(self):
        """
        Test the setup_scan_prereqs function
        """
        with patch("veracode.api.get_app_id", return_value="1337"):
            upload_api = UploadAPI(app_name=test_constants.VALID_UPLOAD_API["app_id"])

        ## Policy Scan
        # Successful when build exists and new build creation succeeds
        with patch("veracode.submit_artifacts.create_build", return_value=True):
            with patch("veracode.submit_artifacts.build_exists", return_value=True):
                self.assertTrue(
                    submit_artifacts.setup_scan_prereqs(upload_api=upload_api)
                )

        # Fail when build already exists and build creation fails
        with patch("veracode.submit_artifacts.create_build", return_value=False):
            with patch("veracode.submit_artifacts.build_exists", return_value=True):
                self.assertFalse(
                    submit_artifacts.setup_scan_prereqs(upload_api=upload_api)
                )

        ## Sandbox Scan
        upload_api.sandbox_id = "12345"
        # Succeed when build exists and new build creation succeeds
        with patch("veracode.submit_artifacts.create_build", return_value=True):
            with patch("veracode.submit_artifacts.build_exists", return_value=True):
                self.assertTrue(
                    submit_artifacts.setup_scan_prereqs(upload_api=upload_api)
                )

        # Succeed when no builds exist and build creation succeeds
        with patch("veracode.submit_artifacts.build_exists", return_value=False):
            with patch("veracode.submit_artifacts.create_build", return_value=True):
                # Succeed when no build exists and build creation succeeds
                with patch("veracode.submit_artifacts.cancel_build", return_value=True):
                    self.assertTrue(
                        submit_artifacts.setup_scan_prereqs(upload_api=upload_api)
                    )

                # Fail when when build cancellation fails
                with patch(
                    "veracode.submit_artifacts.cancel_build", return_value=False
                ):
                    self.assertFalse(
                        submit_artifacts.setup_scan_prereqs(upload_api=upload_api)
                    )

        # Fail when build exists, build cancellation succeeds, and build creation fails
        with patch("veracode.submit_artifacts.build_exists", return_value=True):
            with patch("veracode.submit_artifacts.create_build", return_value=False):
                with patch("veracode.submit_artifacts.cancel_build", return_value=True):
                    self.assertFalse(
                        submit_artifacts.setup_scan_prereqs(upload_api=upload_api)
                    )

                # Fail when build cancellation fails
                with patch(
                    "veracode.submit_artifacts.cancel_build", return_value=False
                ):
                    self.assertFalse(
                        submit_artifacts.setup_scan_prereqs(upload_api=upload_api)
                    )
Пример #22
0
    def test_create_build(self):
        """
        Test the create_build function
        """
        # Test the create_build function when the api call gets a valid response
        with patch.object(
            UploadAPI,
            "http_post",
            return_value=test_constants.VALID_UPLOAD_API_CREATEBUILD_RESPONSE_XML[
                "Element"
            ],
        ):
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan, no error in response body
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    self.assertTrue(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )

                    # Sandbox scan, no error in response body
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    upload_api.sandbox_id = "12345"
                    self.assertTrue(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )

            # Fail when the create_build function gets a response containing an
            # error in the response body
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=True
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan, response body contains error
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    self.assertFalse(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )

                    # Sandbox scan, response body contains error
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    upload_api.sandbox_id = "12345"
                    self.assertFalse(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )

        # Fail when calling the create_build function and the api call gets a
        # mocked error message response and a mocked side effect of HTTPError
        with patch.object(
            UploadAPI,
            "http_post",
            return_value=test_constants.VERACODE_ERROR_RESPONSE_XML["Element"],
            side_effect=HTTPError(),
        ):
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan, no error in response body
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    self.assertFalse(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )

                    # Sandbox scan, no error in response body
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    upload_api.sandbox_id = "12345"
                    self.assertFalse(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )
Пример #23
0
    def test_upload_large_file(self, mock_element_contains_error):
        """
        Test the upload_large_file function
        """
        mock_element_contains_error.return_value = False
        # Succeed when calling the upload_large_file function and the api call
        # gets a valid response
        with patch.object(
            UploadAPI,
            "http_post",
            return_value=test_constants.VALID_UPLOAD_API_UPLOADLARGEFILE_RESPONSE_XML[
                "bytes"
            ],
        ):
            # Policy scan
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api = UploadAPI(
                    app_name=test_constants.VALID_UPLOAD_API["app_name"]
                )
                valid_artifact = test_constants.VALID_FILE["Path"]

            with patch(
                "veracode.submit_artifacts.open",
                new=mock_open(read_data=test_constants.VALID_FILE["bytes"]),
            ):
                self.assertTrue(
                    submit_artifacts.upload_large_file(
                        upload_api=upload_api, artifact=valid_artifact
                    )
                )

            # Sandbox scan
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api = UploadAPI(
                    app_name=test_constants.VALID_UPLOAD_API["app_name"]
                )
                upload_api.sandbox_id = "12345"
                valid_artifact = test_constants.VALID_FILE["Path"]

            with patch(
                "veracode.submit_artifacts.open",
                new=mock_open(read_data=test_constants.VALID_FILE["bytes"]),
            ):
                self.assertTrue(
                    submit_artifacts.upload_large_file(
                        upload_api=upload_api, artifact=valid_artifact
                    )
                )

        # Fail when calling the upload_large_file function and the api call
        # raises a HTTPError
        with patch.object(
            UploadAPI,
            "http_post",
            return_value=test_constants.VALID_UPLOAD_API_UPLOADLARGEFILE_RESPONSE_XML[
                "bytes"
            ],
            side_effect=HTTPError(),
        ):
            # Policy scan
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api = UploadAPI(
                    app_name=test_constants.VALID_UPLOAD_API["app_name"]
                )
                valid_artifact = test_constants.VALID_FILE["Path"]

            with patch(
                "veracode.submit_artifacts.open",
                new=mock_open(read_data=test_constants.VALID_FILE["bytes"]),
            ):
                self.assertRaises(
                    HTTPError,
                    submit_artifacts.upload_large_file,
                    upload_api=upload_api,
                    artifact=valid_artifact,
                )

            # Sandbox scan
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api = UploadAPI(
                    app_name=test_constants.VALID_UPLOAD_API["app_name"]
                )
                upload_api.sandbox_id = "12345"
                valid_artifact = test_constants.VALID_FILE["Path"]

            with patch(
                "veracode.submit_artifacts.open",
                new=mock_open(read_data=test_constants.VALID_FILE["bytes"]),
            ):
                self.assertRaises(
                    HTTPError,
                    submit_artifacts.upload_large_file,
                    upload_api=upload_api,
                    artifact=valid_artifact,
                )
Пример #24
0
    def test_begin_prescan(self):
        """
        Test the begin_prescan function
        """
        # Succeed when calling the begin_prescan function and the api call gets
        # a valid response
        with patch.object(
            UploadAPI,
            "http_post",
            return_value=test_constants.VALID_UPLOAD_API_BEGINPRESCAN_RESPONSE_XML[
                "Element"
            ],
        ):
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    self.assertTrue(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )

                    # Sandbox scan
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    upload_api.sandbox_id = "12345"
                    self.assertTrue(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )

            # Fail when the begin_prescan function gets a response containing an
            # error in the response body
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=True
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    self.assertFalse(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )

                    # Sandbox scan
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    upload_api.sandbox_id = "12345"
                    self.assertFalse(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )

        # Fail when calling the begin_prescan function and the api call gets a
        # mocked side effect of HTTPError
        with patch.object(UploadAPI, "http_post", side_effect=HTTPError()):
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan
                    upload_api = UploadAPI(app_name="31337")
                    self.assertFalse(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )

                    # Sandbox scan
                    upload_api = UploadAPI(app_name="31337")
                    upload_api.sandbox_id = "12345"
                    self.assertFalse(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )
Пример #25
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)
Пример #26
0
def submit_artifacts(  # pylint: disable=too-many-return-statements, too-many-branches
        *,
        upload_api: UploadAPI,
        sandbox_api: SandboxAPI = None) -> bool:
    """
    Submit build artifacts to Veracode for SAST
    """
    artifacts: List[Path] = []

    # If we were provided a sandbox_api object, attempt to get the sandbox_id
    # that maps to the sandbox_name and if it doesn't exist, make one
    if sandbox_api:
        try:
            upload_api.sandbox_id = get_sandbox_id(sandbox_api=sandbox_api)
        except RuntimeError:
            LOG.warning(
                "Unable to get the sandbox_id for sandbox_name %s",
                sandbox_api.sandbox_name,
            )
            return False

        if not upload_api.sandbox_id:
            try:
                upload_api.sandbox_id = create_sandbox(sandbox_api=sandbox_api)
            except RuntimeError:
                LOG.error(
                    "Unable to create a sandbox named %s in app_id %s",
                    sandbox_api.sandbox_name,
                    sandbox_api.app_id,
                )
                return False

    # Setup the scan prereqs
    if not setup_scan_prereqs(upload_api=upload_api):
        # Scan prereq setup failed
        return False
    LOG.info("Successfully setup the scan prerequisites in Veracode")

    LOG.info("Beginning pre-upload file filtering")
    for artifact in upload_api.build_dir.iterdir():
        LOG.debug("Calling filter_file on %s", artifact)
        if filter_file(artifact=artifact):
            artifacts += [artifact]

    # Check to see if the artifacts list is empty
    if not artifacts:
        LOG.error("Nothing to upload")
        return False

    LOG.info("Beginning file uploads")
    for artifact in artifacts:
        if upload_large_file(upload_api=upload_api, artifact=artifact):
            LOG.info("Successfully uploaded %s", artifact)
        else:
            LOG.error("Failed to upload %s", artifact)
            return False

    LOG.info("File uploads complete")
    if begin_prescan(upload_api=upload_api):
        LOG.info("Successfully began the prescan")
    else:
        LOG.error("Failed to start the prescan")
        return False

    return True