Skip to content

Commit

Permalink
Merge branch 'veracode:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
cadonuno authored Nov 28, 2024
2 parents fd7cacd + e5cc7d6 commit e494c9b
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 20 deletions.
14 changes: 9 additions & 5 deletions docs/analytics.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@ 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 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'
- `Analytics().create_report(report_type ('findings'),last_updated_start_date(opt), last_updated_end_date (opt), scan_type (opt), finding_status(opt), passed_policy(opt), policy_sandbox(opt), application_id(opt), rawjson(opt), deletion_start_date(opt), deletion_end_date(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 supports `findings`, `scans`, and `deletedscans`.
- `last_updated_start_date`: required for `findings` report type, beginning of date range for new or changed findings or scans
- `last_updated_end_date`: optional, end of date range for new or changed findings or scans
- `scan_type`: optional, one or more of 'Static Analysis', 'Dynamic Analysis', 'Manual', 'Software Composition Analysis', 'SCA'. `SCA` is only supported for the `findings` report type.
- `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
- `deletion_start_date`: required for `deletedscans` report type, beginning of date range for deleted scans.
- `deletion_end_date`: optional, end of date range for deleted scans.

- `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.

- `Analytics().get_deletedscans(guid)`: check the status of a deleted 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)
5 changes: 2 additions & 3 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,14 @@ As an alternative to importing individual objects into your library, you can acc

### Analytics Reporting

1. *Accessing*: The Reporting API is available to Veracode customers by request.
1. *More information*: See the [Veracode Docs](https://docs.veracode.com/r/Reporting_REST_API).
1. *See Also*: You can also access these methods from the [Analytics class](analytics.md).

- `create_analytics_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 only supports `findings`, `scans` and `deletedscans`
- `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'
- `scan_type`: optional, one or more of 'Static Analysis', 'Dynamic Analysis', 'Manual', 'Software Composition Analysis', 'SCA'. `SCA` is only supported for the `findings` type
- `finding_status`: optional, 'Open' or 'Closed'
- `passed_policy`: optional, boolean
- `policy_sandbox`: optional, 'Policy' or 'Sandbox'
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = 'veracode_api_py'
version = '0.9.55'
version = '0.9.56'
authors = [ {name = "Tim Jarrett", email="[email protected]"} ]
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'
Expand All @@ -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_0955.tar.gz"
"Download" = "https://github.com/veracode/veracode-api-py/archive/v_0956.tar.gz"
32 changes: 32 additions & 0 deletions samples/reportingapi_deleted_sample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import time
import sys
import json
import datetime
from veracode_api_py import Analytics

wait_seconds = 15

print('Generating deleted scans report...')
theguid = Analytics().create_report(report_type="deletedscans",deletion_start_date='2024-07-01',deletion_end_date='2024-12-31')

print('Checking status for report {}...'.format(theguid))
thestatus,thescans=Analytics().get_deleted_scans(theguid)

while thestatus != 'COMPLETED':
print('Waiting {} seconds before we try again...'.format(wait_seconds))
time.sleep(wait_seconds)
print('Checking status for report {}...'.format(theguid))
thestatus,thescans=Analytics().get_deleted_scans(theguid)

recordcount = len(thescans)

print('Retrieved {} scans'.format(recordcount))

if recordcount > 0:
now = datetime.datetime.now().astimezone()
filename = 'report-{}'.format(now)
with open('{}.json'.format(filename), 'w') as outfile:
json.dump(thescans,outfile)
outfile.close()

print('Wrote {} findings to {}.json'.format(recordcount,filename))
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
setup(
name = 'veracode_api_py',
packages = ['veracode_api_py'],
version = '0.9.54',
version = '0.9.56',
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,
long_description_content_type="text/markdown",
author = 'Tim Jarrett',
author_email = '[email protected]',
url = 'https://github.com/tjarrettveracode',
download_url = 'https://github.com/veracode/veracode-api-py/archive/v_0955.tar.gz',
download_url = 'https://github.com/veracode/veracode-api-py/archive/v_0956.tar.gz',
keywords = ['veracode', 'veracode-api'],
install_requires=[
'veracode-api-signing'
Expand Down
30 changes: 25 additions & 5 deletions veracode_api_py/analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,46 @@
from .apihelper import APIHelper

class Analytics():
report_types = [ "findings", "scans" ]
report_types = [ "findings", "scans", "deletedscans" ]

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'

#public methods
def create_report(self,report_type,last_updated_start_date,last_updated_end_date=None,
def create_report(self,report_type,last_updated_start_date=None,last_updated_end_date=None,
scan_type:list = [], finding_status=None,passed_policy=None,
policy_sandbox=None,application_id=None,rawjson=False):
policy_sandbox=None,application_id=None,rawjson=False, deletion_start_date=None,
deletion_end_date=None):

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 }
report_def = { 'report_type': report_type }

if last_updated_start_date:
report_def['last_updated_start_date'] = last_updated_start_date
else:
if report_type in ['findings','scans']:
raise ValueError("{} report type requires a last updated start date.").format(report_type)

if last_updated_end_date:
report_def['last_updated_end_date'] = last_updated_end_date

if deletion_end_date:
report_def['deletion_end_date'] = deletion_end_date

if deletion_start_date:
report_def['deletion_start_date'] = deletion_start_date
else:
if report_type == 'deletedscans':
raise ValueError("{} report type requires a deleteion start date.").format(report_type)

if len(scan_type) > 0:
if report_type == 'findings':
valid_scan_types = self.findings_scan_types
elif report_type == 'scans':
elif report_type in [ 'scans', 'deletedscans' ]:
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))
Expand Down Expand Up @@ -62,6 +78,10 @@ def get_findings(self, guid: UUID):
def get_scans(self, guid: UUID):
thestatus, thescans = self.get(guid=guid,report_type='scans')
return thestatus, thescans

def get_deleted_scans(self, guid: UUID):
thestatus, thescans = self.get(guid=guid,report_type='deletedscans')
return thestatus, thescans

def get(self,guid: UUID,report_type='findings'):
# handle multiple scan types
Expand Down
20 changes: 17 additions & 3 deletions veracode_api_py/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,15 +641,29 @@ def dyn_start_scan(self, length, unit):
return DynUtils().start_scan(length,unit)

# analytics apis
def create_analytics_report(self,report_type,last_updated_start_date,last_updated_end_date=None,
def create_analytics_report(self,report_type,last_updated_start_date=None,last_updated_end_date=None,
scan_type:list = [], finding_status=None,passed_policy=None,
policy_sandbox=None,application_id=None,rawjson=False):
policy_sandbox=None,application_id=None,rawjson=False,deletion_start_date=None,
deletion_end_date=None):
return Analytics().create_report(report_type=report_type,last_updated_start_date=last_updated_start_date,
last_updated_end_date=last_updated_end_date,scan_type=scan_type,
finding_status=finding_status,passed_policy=passed_policy,
policy_sandbox=policy_sandbox,application_id=application_id,
rawjson=rawjson)
rawjson=rawjson, deletion_start_date=deletion_start_date,
deletion_end_date=deletion_end_date)

def get_analytics_report(self,guid: UUID):
status, findings = Analytics().get(guid=guid)
return status, findings

def get_analytics_findings_report(self,guid:UUID):
status, findings = Analytics().get_findings(guid=guid)
return status, findings

def get_analytics_scans(self,guid:UUID):
status, findings = Analytics().get_scans(guid=guid)
return status, findings

def get_analytics_deleted_scans(self,guid:UUID):
status, findings = Analytics().get_deleted_scans(guid=guid)
return status, findings

0 comments on commit e494c9b

Please sign in to comment.