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
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")
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")
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")
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")
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")
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")
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")
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")
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))
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 )
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
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
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")
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")
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")
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
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
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))
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, )
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) )
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) )
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, )
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) )
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)
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