From fc0f34ca6235efbd0833b7ede4d4844d43883709 Mon Sep 17 00:00:00 2001 From: Tim Jarrett Date: Fri, 27 Sep 2024 14:39:39 -0400 Subject: [PATCH] work in progress on scans report --- docs/analytics.md | 6 +++--- veracode_api_py/analytics.py | 24 ++++++++++++++---------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/analytics.md b/docs/analytics.md index a1feec6..995c169 100644 --- a/docs/analytics.md +++ b/docs/analytics.md @@ -7,12 +7,12 @@ The following methods call Veracode REST APIs and return JSON. 1. The Reporting API is available to Veracode customers by request. More information about the API is available in the [Veracode Docs](https://docs.veracode.com/r/Reporting_REST_API). - `Analytics().create_report(report_type ('findings'),last_updated_start_date, last_updated_end_date (opt), scan_type (opt), finding_status(opt), passed_policy(opt), policy_sandbox(opt), application_id(opt), rawjson(opt))`: set up a request for a report. By default this command returns the GUID of the report request; specify `rawjson=True` to get the full response. Dates should be specified as `YYYY-MM-DD HH:MM:SS` with the timestamp optional. Options include: - - `report_type`: required, currently only supports `findings` + - `report_type`: required, currently supports `findings` and `scans`. - `last_updated_start_date`: required, beginning of date range for new or changed findings - `last_updated_end_date`: optional, end of date range for new or changed findings - `scan_type`: optional, one or more of 'Static Analysis', 'Dynamic Analysis', 'Manual', 'Software Composition Analysis', 'SCA' - - `finding_status`: optional, 'Open' or 'Closed' - - `passed_policy`: optional, boolean + - `finding_status`: optional, 'Open' or 'Closed'. Applies only to the `findings` report. + - `passed_policy`: optional, boolean. Applies only to the `findings` report. - `policy_sandbox`: optional, 'Policy' or 'Sandbox' - `application_id`: optional, application ID for which to return results - `rawjson`: optional, defaults to False. Returns full response if True, the GUID of the request if false diff --git a/veracode_api_py/analytics.py b/veracode_api_py/analytics.py index 3fa04ed..36a54a8 100644 --- a/veracode_api_py/analytics.py +++ b/veracode_api_py/analytics.py @@ -6,9 +6,10 @@ from .apihelper import APIHelper class Analytics(): - report_types = [ "findings" ] + report_types = [ "findings", "scans" ] - scan_types = ["Static Analysis", "Dynamic Analysis", "Manual", "SCA", "Software Composition Analysis" ] + findings_scan_types = ["Static Analysis", "Dynamic Analysis", "Manual", "SCA", "Software Composition Analysis" ] + scan_scan_types = ["Static Analysis", "Dynamic Analysis", "Manual" ] base_url = 'appsec/v1/analytics/report' @@ -16,7 +17,9 @@ class Analytics(): def create_report(self,report_type,last_updated_start_date,last_updated_end_date=None, scan_type:list = [], finding_status=None,passed_policy=None, policy_sandbox=None,application_id=None,rawjson=False): - #TODO validate report_type, add scan_type + + if report_type not in self.report_types: + raise ValueError("{} is not in the list of valid report types ({})".format(report_type,self.report_types)) report_def = { "report_type": report_type,"last_updated_start_date": last_updated_start_date } @@ -24,12 +27,13 @@ def create_report(self,report_type,last_updated_start_date,last_updated_end_date report_def['last_updated_end_date'] = last_updated_end_date if len(scan_type) > 0: - # validate against self.scan_types - if self._case_insensitive_list_compare(scan_type,self.scan_types): - report_def['scan_type'] = scan_type - else: - print("Invalid scan_type provided. Valid types are {}".format(self.scan_types)) - return + if report_type == 'findings': + valid_scan_types = self.findings_scan_types + elif report_type == 'scans': + valid_scan_types = self.scan_scan_types + if not(self._case_insensitive_list_compare(scan_type,valid_scan_types)): + raise ValueError("{} is not in the list of valid scan types ({})".format(report_type,valid_scan_types)) + report_def['scan_type'] = scan_type if finding_status: report_def['finding_status'] = finding_status @@ -52,6 +56,7 @@ def create_report(self,report_type,last_updated_start_date,last_updated_end_date return response['_embedded']['id'] #we will usually just need the guid so we can come back and fetch the report def get(self,guid: UUID): + # handle multiple scan types uri = "{}/{}".format(self.base_url,guid) theresponse = APIHelper()._rest_paged_request(uri,"GET","findings",{},fullresponse=True) thestatus = theresponse.get('_embedded',{}).get('status','') @@ -64,6 +69,5 @@ def _case_insensitive_list_compare(self,input_list:list, target_list:list): target_set = self._lowercase_set_from_list(target_list) return target_set.issuperset(input_set) - def _lowercase_set_from_list(self,thelist:list): return set([x.lower() for x in thelist]) \ No newline at end of file