|
2 | 2 | import http.client
|
3 | 3 | http.client._MAXHEADERS = 1000
|
4 | 4 |
|
| 5 | +import csv |
| 6 | + |
5 | 7 | from blackduck import Client
|
6 | 8 |
|
7 | 9 | import argparse
|
|
10 | 12 | from pprint import pprint
|
11 | 13 |
|
12 | 14 | logging.basicConfig(
|
13 |
| - level=logging.DEBUG, |
| 15 | + level=logging.INFO, |
14 | 16 | format="[%(asctime)s] {%(module)s:%(lineno)d} %(levelname)s - %(message)s"
|
15 | 17 | )
|
16 | 18 |
|
17 | 19 | parser = argparse.ArgumentParser("Get a specific component and list its vulnerabilities")
|
18 | 20 | parser.add_argument("--base-url", required=True, help="Hub server URL e.g. https://your.blackduck.url")
|
19 | 21 | parser.add_argument("--token-file", dest='token_file', required=True, help="containing access token")
|
| 22 | +parser.add_argument("--csv-file", dest='csv_file', help="Supply a CSV file name to get output formatted in CSV") |
20 | 23 | parser.add_argument("--project", dest='project_name', required=True, help="Project that contains the BOM components")
|
21 | 24 | parser.add_argument("--version", dest='version_name', required=True, help="Version that contains the BOM components")
|
22 | 25 | parser.add_argument("--no-verify", dest='verify', action='store_false', help="disable TLS certificate verification")
|
|
52 | 55 | bom_component_vuln['upgrade_guidance'] = upgrade_guidance
|
53 | 56 |
|
54 | 57 | vuln_details = bd.get_json(f"/api/vulnerabilities/{vuln_name}")
|
| 58 | + bom_component_vuln['vulnerability_details'] = vuln_details |
55 | 59 |
|
56 |
| - pprint(bd.list_resources(vuln_details)) |
57 | 60 | if 'related-vulnerability' in bd.list_resources(vuln_details):
|
58 | 61 | related_vuln = bd.get_resource("related-vulnerability", vuln_details, items=False)
|
59 | 62 | else:
|
60 | 63 | related_vuln = None
|
61 | 64 | bom_component_vuln['related_vulnerability'] = related_vuln
|
62 | 65 | all_bom_component_vulns.append(bom_component_vuln)
|
63 | 66 |
|
64 |
| -pprint(all_bom_component_vulns) |
| 67 | +if args.csv_file: |
| 68 | + '''Note: See the BD API doc and in particular .../api-doc/public.html#_bom_vulnerability_endpoints |
| 69 | + for a complete list of the fields available. The below code shows a subset of them just to |
| 70 | + illustrate how to write out the data into a CSV format. |
| 71 | + ''' |
| 72 | + logging.info(f"Exporting {len(all_bom_component_vulns)} records to CSV file {args.csv_file}") |
| 73 | + with open(args.csv_file, 'w') as csv_f: |
| 74 | + field_names = [ |
| 75 | + 'Vulnerability Name', |
| 76 | + 'Vulnerability Description', |
| 77 | + 'Remediation Status', |
| 78 | + 'Component', |
| 79 | + 'Component Version', |
| 80 | + 'Exploit Available', |
| 81 | + 'Workaround Available', |
| 82 | + 'Solution Available', |
| 83 | + 'Upgrade Guidance - short term', |
| 84 | + 'Upgrade Guidance - long term', |
| 85 | + ] |
| 86 | + writer = csv.DictWriter(csv_f, fieldnames = field_names) |
| 87 | + writer.writeheader() |
| 88 | + for comp_vuln in all_bom_component_vulns: |
| 89 | + row_data = { |
| 90 | + 'Vulnerability Name': comp_vuln['vulnerabilityName'], |
| 91 | + 'Vulnerability Description': comp_vuln['description'], |
| 92 | + 'Remediation Status': comp_vuln['remediationStatus'], |
| 93 | + 'Component': comp_vuln['componentName'], |
| 94 | + 'Component Version': comp_vuln['componentVersionName'], |
| 95 | + 'Exploit Available': comp_vuln['vulnerability_details'].get('exploitPublishDate', 'None available'), |
| 96 | + 'Workaround Available': comp_vuln['vulnerability_details'].get('workaround', 'None available'), |
| 97 | + 'Solution Available': comp_vuln['vulnerability_details'].get('solution', 'None available'), |
| 98 | + 'Upgrade Guidance - short term': comp_vuln['upgrade_guidance'].get('shortTerm', 'None available'), |
| 99 | + 'Upgrade Guidance - long term': comp_vuln['upgrade_guidance'].get('longTerm', 'None available') |
| 100 | + } |
| 101 | + writer.writerow(row_data) |
| 102 | +else: |
| 103 | + pprint(all_bom_component_vulns) |
0 commit comments