# SPDX-FileCopyrightText: Huawei Inc. # # SPDX-License-Identifier: Apache-2.0 # CVE-check example script # Reporting based on the cve-check JSON format: conversion to CSV and summary import sys import getopt infile = "in.json" outfile = "out.csv" show_all = False show_summary = False to_csv = False def show_syntax_and_exit(code): """ Show the program syntax and exit with an errror Arguments: code: the error code to return """ print("Syntax: %s [-h] [-a] [-s] [-c] [-i inputfile][-o outputfile]" % sys.argv[0]) print("Default files: in.json and out.csv") print( "Use -c or --to-csv to generate a CSV report, output file is then needed, out.csv by default" ) print("Use -a or --all to list all issues, otherwise we filter only unpatched ones") print("Use -s or --summary to show a summary of the issues") sys.exit(code) def exit_error(code, message): """ Show the error message and exit with an errror Arguments: code: the error code to return message: the message to show """ print("Error: %s" % message) sys.exit(code) def parse_args(argv): """ Parse the program arguments, put options in global variables Arguments: argv: program arguments """ global infile, outfile, show_all, show_summary, to_csv try: opts, args = getopt.getopt( argv, "hi:o:asc", ["help", "input", "output", "summary", "to-csv"] ) except getopt.GetoptError: show_syntax_and_exit(1) for opt, arg in opts: if opt in ("-h", "--help"): show_syntax_and_exit(0) elif opt in ("-a", "--all"): show_all = True elif opt in ("-i", "--input"): infile = arg elif opt in ("-c", "--to-csv"): to_csv = True elif opt in ("-o", "--output"): outfile = arg elif opt in ("-s", "--summary"): show_summary = True def load_json(filename): """ Load the JSON file, return the resulting dictionary Arguments: filename: the file to open Returns: Parsed file as a dictionary """ import json out = {} try: with open(filename, "r") as f: out = json.load(f) except FileNotFoundError: exit_error(1, "Input file (%s) not found" % (filename)) except json.decoder.JSONDecodeError as error: exit_error(1, "Malformed JSON file: %s" % str(error)) return out def process_data(filename, data, unpatched_only, do_summary, do_csv): """ Write the resulting CSV with one line for each package Arguments: filename: the file to write to data: dictionary from parsing the JSON file unpatched_only: True if we want only unpatched issues, False otherwise Returns: Parsed file as a dictionary """ if not "version" in data or data["version"] != "1": exit_error(1, "Unrecognized format version number") if not "package" in data: exit_error(1, "Mandatory 'package' key not found") lines = "" total_issue_count = 0 for package in data["package"]: keys_in_package = {"name", "layer", "version", "issue"} if keys_in_package - package.keys(): exit_error( 1, "Missing a mandatory key in package: %s" % (keys_in_package - package.keys()), ) package_name = package["name"] layer = package["layer"] package_version = package["version"] package_summary = "Issues for package %s (version %s):\n\t" % ( package_name, package_version, ) issue_count = 0 for issue in package["issue"]: keys_in_issue = {"id", "scorev2", "scorev3", "vector", "status"} if keys_in_issue - issue.keys(): exit_error( 1, "Missing mandatory keys %s in 'issue' for the package '%s'" % (keys_in_issue - issue.keys(), package_name), ) cve_id = issue["id"] scorev2 = issue["scorev2"] scorev3 = issue["scorev3"] vector = issue["vector"] status = issue["status"] if (unpatched_only == False) or (status == "Unpatched"): lines += "%s;%s;%s;%s;%s;%s;%s\n" % ( layer, package_name, package_version, cve_id, scorev2, scorev3, vector, ) package_summary += "%s " % (cve_id) issue_count += 1 if do_summary and issue_count > 0: package_summary += "\n\tCount: %d\n" % (issue_count) print(package_summary) total_issue_count += issue_count if do_csv: with open(filename, "w") as f: f.write(lines) if do_summary: print("Global issue count: %d" % (total_issue_count)) def main(argv): parse_args(argv) data = load_json(infile) process_data(outfile, data, not show_all, show_summary, to_csv) if __name__ == "__main__": main(sys.argv[1:])