def test_check_compliance(self, mock_in_compliance): """ Test the check_compliance function """ # Return True when calling the check_compliance function with a valid # results_api with ignore_compliance_status set to True and # ignore_compliance_status is True results_api = ResultsAPI( app_id=test_constants.VALID_RESULTS_API["app_id"]) results_api.ignore_compliance_status = True mock_in_compliance.return_value = True self.assertTrue( check_compliance.check_compliance(results_api=results_api)) # Return False when calling the check_compliance function with a valid # results_api with ignore_compliance_status set to False and # ignore_compliance_status is False results_api = ResultsAPI( app_id=test_constants.VALID_RESULTS_API["app_id"]) results_api.ignore_compliance_status = False mock_in_compliance.return_value = False self.assertFalse( check_compliance.check_compliance(results_api=results_api)) # Return True when calling the check_compliance function with a valid # results_api with ignore_compliance_status set to True and # ignore_compliance_status is False results_api = ResultsAPI( app_id=test_constants.VALID_RESULTS_API["app_id"]) results_api.ignore_compliance_status = True mock_in_compliance.return_value = False self.assertTrue( check_compliance.check_compliance(results_api=results_api)) # Return True when calling the check_compliance function with a valid # results_api with ignore_compliance_status set to False and # ignore_compliance_status is True results_api = ResultsAPI( app_id=test_constants.VALID_RESULTS_API["app_id"]) results_api.ignore_compliance_status = False mock_in_compliance.return_value = True self.assertTrue( check_compliance.check_compliance(results_api=results_api)) # Return False after calling the check_compliance function with a valid # results_api with ignore_compliance_status set to False and # ignore_compliance_status is True, but in_compliance's mock raises a # ValueError when called results_api = ResultsAPI( app_id=test_constants.VALID_RESULTS_API["app_id"]) results_api.ignore_compliance_status = False mock_in_compliance.return_value = True mock_in_compliance.side_effect = ValueError self.assertFalse( check_compliance.check_compliance(results_api=results_api))
def test_get_policy_compliance_status(self, mock_get_latest_completed_build): """ Test the get_policy_compliance_status function """ # Return a non-"Pass"ing string when calling the # get_policy_compliance_status function with a valid results_api and # get_latest_completed_build has a mocked response of "Did Not Pass" results_api = ResultsAPI( app_id=test_constants.VALID_RESULTS_API["app_id"]) mock_get_latest_completed_build.return_value = test_constants.VALID_RESULTS_API_GETAPPBUILDS_RESPONSE_XML_FAILING_POLICY_COMPLIANCE_STATUS[ "Element"] self.assertEqual( check_compliance.get_policy_compliance_status( results_api=results_api), "Did Not Pass", ) self.assertNotEqual( check_compliance.get_policy_compliance_status( results_api=results_api), "Pass", ) # Return a "Pass"ing string when calling the # get_policy_compliance_status function with a valid results_api and # get_latest_completed_build has a mocked response that returns None results_api = ResultsAPI( app_id=test_constants.VALID_RESULTS_API["app_id"]) mock_get_latest_completed_build.return_value = None self.assertNotEqual( check_compliance.get_policy_compliance_status( results_api=results_api), "Pass", ) # Return a non-"Pass"ing string when calling the # get_policy_compliance_status function with a valid results_api and # get_latest_completed_build has a mocked response that returns an # application with no build results_api = ResultsAPI( app_id=test_constants.VALID_RESULTS_API["app_id"]) mock_get_latest_completed_build.return_value = ( test_constants. VALID_RESULTS_API_GETAPPBUILDS_RESPONSE_XML_NO_BUILDS["Element"]) self.assertEqual( check_compliance.get_policy_compliance_status( results_api=results_api), "Unknown", ) self.assertNotEqual( check_compliance.get_policy_compliance_status( results_api=results_api), "Pass", )
def test_in_compliance(self, mock_get_policy_compliance_status): """ Test the in_compliance function """ # Succeed when calling the in_compliance function with a valid # results_api and compliance_status has a mocked response of "Pass" with patch("veracode.api.get_app_id", return_value="1337"): results_api = ResultsAPI( app_name=test_constants.VALID_RESULTS_API["app_name"]) mock_get_policy_compliance_status.return_value = "Pass" self.assertTrue( check_compliance.in_compliance(results_api=results_api)) # Return False when calling the in_compliance function with a valid # results_api and compliance_status has a mocked response of "Unknown" with patch("veracode.api.get_app_id", return_value="1337"): results_api = ResultsAPI( app_name=test_constants.VALID_RESULTS_API["app_name"]) mock_get_policy_compliance_status.return_value = "Unknown" self.assertRaises(ValueError, check_compliance.in_compliance, results_api=results_api) # Succeed when calling the in_compliance function with a valid # results_api and compliance_status has a mocked response of anything # but "Pass" # # https://analysiscenter.veracode.com/resource/2.0/applicationbuilds.xsd # and https://help.veracode.com/viewer/document/mo49_yYZJCUuKhwdE9WRFQ # for possible values with patch("veracode.api.get_app_id", return_value="1337"): results_api = ResultsAPI( app_name=test_constants.VALID_RESULTS_API["app_name"]) for value in [ "Calculating...", "Not Assessed", "Did Not Pass", "Conditional Pass", "Under Vendor Review", "UNKNOWN VALUE!()&@%", 300, 7.12, results_api, ]: mock_get_policy_compliance_status.return_value = value self.assertFalse( check_compliance.in_compliance(results_api=results_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 test_results_api__validate(self, mock_is_valid_attribute): """ Test the ResultsAPI _validate method """ with patch("veracode.api.get_app_id", return_value=constants.VALID_UPLOAD_API["app_id"]): results_api = ResultsAPI( app_name=constants.VALID_RESULTS_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, results_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( results_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, results_api, "_validate")
def test_results_api_http_post(self, mock_http_request): """ Test the ResultsAPI http_post method """ with patch("veracode.api.get_app_id", return_value=constants.VALID_UPLOAD_API["app_id"]): results_api = ResultsAPI( app_name=constants.VALID_RESULTS_API["app_name"]) # Fail when attempting to call the http_post method with invalid # arguments self.assertRaises(KeyError, results_api.http_post, endpoint="removefile.do") # Succeed when calling the http_post method with valid arguments # # As of the writing of this Veracode's Results API doesn't have any # endpoints that take a POST so the constants and endpoints below don't # align with a real-world scenario (because one doesn't exist) mock_http_request.return_value = constants.VALID_RESULTS_API_GETAPPBUILDS_RESPONSE_XML_PASSING_POLICY_COMPLIANCE_STATUS[ "Element"] self.assertIsInstance( results_api.http_post(endpoint="detailedreport.do"), InsecureElementTree.Element, ) # Fail when attempting to delete the http_post method, because the # deleter is intentionally missing self.assertRaises(AttributeError, delattr, results_api, "http_post")
def test_results_api_http_get(self, mock_http_request): """ Test the ResultsAPI http_get method """ with patch("veracode.api.get_app_id", return_value=constants.VALID_UPLOAD_API["app_id"]): results_api = ResultsAPI( app_name=constants.VALID_RESULTS_API["app_name"]) # Fail when attempting to call the http_get method with invalid # arguments self.assertRaises(KeyError, results_api.http_get, endpoint="getbuildlist.do") # Succeed when calling the http_get method with valid arguments mock_http_request.return_value = constants.VALID_RESULTS_API_GETAPPBUILDS_RESPONSE_XML_PASSING_POLICY_COMPLIANCE_STATUS[ "Element"] self.assertIsInstance( results_api.http_get(endpoint="getappbuilds.do"), InsecureElementTree.Element, ) # Fail when attempting to delete the http_get method, because the # deleter is intentionally missing self.assertRaises(AttributeError, delattr, results_api, "http_get")
def test_results_api_base_url(self): """ Test the ResultsAPI base_url property """ with patch("veracode.api.get_app_id", return_value=constants.VALID_UPLOAD_API["app_id"]): results_api = ResultsAPI( app_name=constants.VALID_RESULTS_API["app_name"]) # Succeed when getting a valid base_url property self.assertIsInstance(results_api.base_url, str) # Succeed when setting the base_url property to a valid value self.assertIsNone( setattr(results_api, "base_url", constants.VALID_RESULTS_API["base_url"])) # Fail when attempting to set the base_url property to an invalid value self.assertRaises( ValueError, setattr, results_api, "base_url", constants.INVALID_RESULTS_API_MISSING_DOMAIN["base_url"], ) # Fail when attempting to get the base_url property when it contains an # invalid value results_api._base_url = constants.INVALID_RESULTS_API_MISSING_DOMAIN[ # pylint: disable=protected-access "base_url"] self.assertRaises(ValueError, getattr, results_api, "base_url") # Fail when attempting to delete the base_url property, because the # deleter is intentionally missing self.assertRaises(AttributeError, delattr, results_api, "base_url")
def test_results_api_version(self): """ Test the ResultsAPI version property """ with patch("veracode.api.get_app_id", return_value=constants.VALID_UPLOAD_API["app_id"]): results_api = ResultsAPI( app_name=constants.VALID_RESULTS_API["app_name"]) # Succeed when getting a valid version property self.assertIsInstance(results_api.version, dict) # Succeed when setting the version property to a valid value self.assertIsNone( setattr(results_api, "version", constants.VALID_RESULTS_API["version"])) # Fail when attempting to set the version property to an invalid value self.assertRaises( ValueError, setattr, results_api, "version", constants.INVALID_RESULTS_API_INCORRECT_VERSION_VALUES["version"], ) # Fail when attempting to get the version property when it contains an # invalid value results_api._version = constants.INVALID_RESULTS_API_INCORRECT_VERSION_VALUES[ # pylint: disable=protected-access "version"] self.assertRaises(ValueError, getattr, results_api, "version") # Fail when attempting to delete the version property, because the # deleter is intentionally missing self.assertRaises(AttributeError, delattr, results_api, "version")
def test_results_api_ignore_compliance_status(self): """ Test the ResultsAPI ignore_compliance_status property """ with patch("veracode.api.get_app_id", return_value=constants.VALID_UPLOAD_API["app_id"]): results_api = ResultsAPI( app_name=constants.VALID_RESULTS_API["app_name"]) # Succeed when getting a valid ignore_compliance_status property self.assertIsInstance(results_api.ignore_compliance_status, bool) # Succeed when setting the ignore_compliance_status property to a valid # value self.assertIsNone( setattr( results_api, "ignore_compliance_status", constants.VALID_RESULTS_API["ignore_compliance_status"], )) # Fail when attempting to set the ignore_compliance_status property to # an invalid value self.assertRaises( ValueError, setattr, results_api, "ignore_compliance_status", constants.INVALID_RESULTS_API_INCORRECT_COMPLIANCE_STATUS[ "ignore_compliance_status"], ) # Fail when attempting to get the ignore_compliance_status property # when it contains an invalid value results_api._ignore_compliance_status = constants.INVALID_RESULTS_API_INCORRECT_COMPLIANCE_STATUS[ # pylint: disable=protected-access "ignore_compliance_status"] self.assertRaises(ValueError, getattr, results_api, "ignore_compliance_status") # Fail when attempting to delete the ignore_compliance_status property, # because the deleter is intentionally missing self.assertRaises(AttributeError, delattr, results_api, "ignore_compliance_status")
def test_results_api_app_name(self): """ Test the ResultsAPI app_name property """ # Fail when attempting to create a ResultsAPI object when the app_name # property wasn't provided to the constructor self.assertRaises(TypeError, ResultsAPI) # Succeed when creating a ResultsAPI 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"]): results_api = ResultsAPI( app_name=constants.VALID_RESULTS_API["app_name"]) self.assertIsInstance(getattr(results_api, "app_name"), str) # Succeed when setting the app_name property to a valid value self.assertIsNone( setattr(results_api, "app_name", constants.VALID_RESULTS_API["app_name"])) # Succeed when getting a valid app_name property self.assertIsInstance(results_api.app_name, str) # Fail when attempting to set the app_name property to an invalid value self.assertRaises( ValueError, setattr, results_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 results_api._app_name = constants.INVALID_RESULTS_API_INCORRECT_APP_NAME[ # pylint: disable=protected-access "app_name"] self.assertRaises(ValueError, getattr, results_api, "app_name") # Fail when attempting to delete the app_name property, because the # deleter is intentionally missing self.assertRaises(AttributeError, delattr, results_api, "app_name")
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 test_get_latest_completed_build(self): """ Test the get_latest_completed_build function """ # Succeed when calling the get_latest_completed_build function with a # valid results_api and the http_get method returns an # ElementTree.Element which contains the provided app_id with patch.object( ResultsAPI, "http_get", return_value=test_constants. VALID_RESULTS_API_GETAPPBUILDS_RESPONSE_XML_PASSING_POLICY_COMPLIANCE_STATUS[ "Element"], ): with patch("veracode.check_compliance.element_contains_error", return_value=False): with patch("veracode.api.get_app_id", return_value="1337"): results_api = ResultsAPI(app_name="TestApp") output = check_compliance.get_latest_completed_build( results_api=results_api) expected = ElementTree.fromstring( b'<ns0:application xmlns:ns0="https://analysiscenter.veracode.com/schema/2.0/applicationbuilds" app_name="TestApp" app_id="1337" industry_vertical="Manufacturing" assurance_level="Very High" business_criticality="Very High" origin="Not Specified" modified_date="2019-08-13T14:00:10-04:00" cots="false" business_unit="Not Specified" tags="">\n <ns0:customfield name="Custom 1" value="" />\n <ns0:customfield name="Custom 2" value="" />\n <ns0:customfield name="Custom 3" value="" />\n <ns0:customfield name="Custom 4" value="" />\n <ns0:customfield name="Custom 5" value="" />\n <ns0:customfield name="Custom 6" value="" />\n <ns0:customfield name="Custom 7" value="" />\n <ns0:customfield name="Custom 8" value="" />\n <ns0:customfield name="Custom 9" value="" />\n <ns0:customfield name="Custom 10" value="" />\n <ns0:build version="2019-10 Testing" build_id="1234321" submitter="Jon Zeolla" platform="Not Specified" lifecycle_stage="Deployed (In production and actively developed)" results_ready="true" policy_name="Veracode Recommended Medium" policy_version="1" policy_compliance_status="Pass" rules_status="Pass" grace_period_expired="false" scan_overdue="false">\n <ns0:analysis_unit analysis_type="Static" published_date="2019-10-13T16:20:30-04:00" published_date_sec="1570998030" status="Results Ready" />\n </ns0:build>\n </ns0:application>\n' ) self.assertEqual([output.tag, output.attrib], [expected.tag, expected.attrib]) # However, return False when the element_contains_error function # returns True with patch("veracode.check_compliance.element_contains_error", return_value=True): self.assertFalse( check_compliance.get_latest_completed_build( results_api=results_api)) # Return False when calling the get_latest_completed_build function # with a valid results_api and the http_get method returns an # ElementTree.Element which doesn't contain the provided app_id with patch.object( ResultsAPI, "http_get", return_value=test_constants. VALID_RESULTS_API_GETAPPBUILDS_RESPONSE_XML_PASSING_POLICY_COMPLIANCE_STATUS[ "Element"], ): with patch("veracode.check_compliance.element_contains_error", return_value=False): with patch("veracode.api.get_app_id", return_value="31337"): results_api = ResultsAPI(app_name="TestApp") output = check_compliance.get_latest_completed_build( results_api=results_api) self.assertFalse(output) # Return False when calling the get_latest_completed_build function # with a valid results_api and the http_get method raises one of a # series of exceptions with patch("veracode.api.get_app_id", return_value="1337"): results_api = ResultsAPI(app_name="TestApp") for err in [ HTTPError, ConnectionError, Timeout, TooManyRedirects, RequestException, ]: with patch( "veracode.check_compliance.element_contains_error", return_value=False, ): with patch.object(ResultsAPI, "http_get", side_effect=err): output = check_compliance.get_latest_completed_build( results_api=results_api) self.assertFalse(output)