diff --git a/docs/analytics.md b/docs/analytics.md index a1feec6..5a0d643 100644 --- a/docs/analytics.md +++ b/docs/analytics.md @@ -7,16 +7,20 @@ 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 -- `Analytics().get(guid)`: check the status of the report request and return the report contents when ready. Note that this method returns a tuple of `status` (string) and `results` (list); when `status` is `COMPLETED`, the `results` list will populate with results. +- `Analytics().get(guid, report_type(findings))`: check the status of the report request and return the report contents when ready. Note that this method returns a tuple of `status` (string) and `results` (list); when `status` is `COMPLETED`, the `results` list will populate with results. Also, you need to specify the type of data expected by the GUID with `report_type`; this defaults to `findings`. + +- `Analytics().get_findings(guid)`: check the status of a findings report request specified by `guid` and return the report contents when ready. Note that this method returns a tuple of `status` (string) and `results` (list); when `status` is `COMPLETED`, the `results` list will populate with results. + +- `Analytics().get_scans(guid)`: check the status of a scans report request specified by `guid` and return the report contents when ready. Note that this method returns a tuple of `status` (string) and `results` (list); when `status` is `COMPLETED`, the `results` list will populate with results. [All docs](docs.md) diff --git a/pyproject.toml b/pyproject.toml index 9a96679..c478f74 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = 'veracode_api_py' -version = '0.9.49' +version = '0.9.50' authors = [ {name = "Tim Jarrett", email="tjarrett@veracode.com"} ] description = 'Python helper library for working with the Veracode APIs. Handles retries, pagination, and other features of the modern Veracode REST APIs.' readme = 'README.md' @@ -22,4 +22,4 @@ dependencies = {file = ["requirements.txt"]} [project.urls] "Homepage" = "https://github.com/veracode/veracode-api-py" "Bug Tracker" = "https://github.com/veracode/veracode-api-py/issues" -"Download" = "https://github.com/veracode/veracode-api-py/archive/v_0949.tar.gz" +"Download" = "https://github.com/veracode/veracode-api-py/archive/v_0950.tar.gz" diff --git a/setup.py b/setup.py index 12cf7bb..6b17510 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name = 'veracode_api_py', packages = ['veracode_api_py'], - version = '0.9.49', + version = '0.9.50', license='MIT', description = 'Python helper library for working with the Veracode APIs. Handles retries, pagination, and other features of the modern Veracode REST APIs.', long_description = long_description, @@ -15,7 +15,7 @@ author = 'Tim Jarrett', author_email = 'tjarrett@veracode.com', url = 'https://github.com/tjarrettveracode', - download_url = 'https://github.com/veracode/veracode-api-py/archive/v_0949.tar.gz', + download_url = 'https://github.com/veracode/veracode-api-py/archive/v_0950.tar.gz', keywords = ['veracode', 'veracode-api'], install_requires=[ 'veracode-api-signing' diff --git a/veracode_api_py/analytics.py b/veracode_api_py/analytics.py index 3fa04ed..30bc1f1 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 @@ -51,12 +55,21 @@ def create_report(self,report_type,last_updated_start_date,last_updated_end_date else: 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): + def get_findings(self, guid: UUID): + thestatus, thefindings = self.get(guid=guid,report_type='findings') + return thestatus, thefindings + + def get_scans(self, guid: UUID): + thestatus, thescans = self.get(guid=guid,report_type='scans') + return thestatus, thescans + + def get(self,guid: UUID,report_type='findings'): + # handle multiple scan types uri = "{}/{}".format(self.base_url,guid) - theresponse = APIHelper()._rest_paged_request(uri,"GET","findings",{},fullresponse=True) + theresponse = APIHelper()._rest_paged_request(uri,"GET",report_type,{},fullresponse=True) thestatus = theresponse.get('_embedded',{}).get('status','') - thefindings = theresponse.get('_embedded',{}).get('findings',{}) - return thestatus, thefindings + thebody = theresponse.get('_embedded',{}).get(report_type,{}) + return thestatus, thebody #helper methods def _case_insensitive_list_compare(self,input_list:list, target_list:list): @@ -64,6 +77,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