diff options
author | Neil Williams <codehelp@debian.org> | 2021-12-20 10:46:25 +0000 |
---|---|---|
committer | Neil Williams <codehelp@debian.org> | 2022-01-27 09:08:15 +0000 |
commit | 6782f36269538e8c2772d14cf1cd720f26a334bb (patch) | |
tree | 8ee27e80a7ba3fc39a508d563d2f1d649fb9e9fe /bin/grab-cve-in-fix | |
parent | 2d0ec6a36d9ca06da12a70b85d8a04cdf9c45180 (diff) |
Add support for --input accepting email text on STDIN
Diffstat (limited to 'bin/grab-cve-in-fix')
-rwxr-xr-x | bin/grab-cve-in-fix | 105 |
1 files changed, 78 insertions, 27 deletions
diff --git a/bin/grab-cve-in-fix b/bin/grab-cve-in-fix index 11fd986786..cabda5584a 100755 --- a/bin/grab-cve-in-fix +++ b/bin/grab-cve-in-fix @@ -32,12 +32,13 @@ grab-cve-in-fix - #1001451 # pylint: disable=too-few-public-methods # Examples: -# --email https://lists.debian.org/debian-devel-changes/2021/12/msg01280.html +# --archive https://lists.debian.org/debian-devel-changes/2021/12/msg01280.html # --tracker https://tracker.debian.org/news/1285227/accepted-freerdp2-241dfsg1-1-source-into-unstable/ import argparse import os import glob +import logging import re import sys import requests @@ -65,6 +66,14 @@ class ParseChanges: self.bugs = {} self.parsed = [] self.unstable_version = None + self.logger = logging.getLogger("grab-cve-in-fix") + self.logger.setLevel(logging.DEBUG) + # console logging + ch = logging.StreamHandler() + ch.setLevel(logging.DEBUG) + formatter = logging.Formatter("%(name)s - %(levelname)s - %(message)s") + ch.setFormatter(formatter) + self.logger.addHandler(ch) def _read_cvelist(self): os.chdir(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) @@ -73,6 +82,12 @@ class ParseChanges: for bug in data: if bug.header.name == cve: self.bugs[cve] = bug + if not self.cves: + self.logger.warning( + "no CVEs found in the changes output " "for %s %s", + self.source_package, + self.unstable_version, + ) def parse(self): """Parser-specific code to pick out the DEB822 content""" @@ -84,7 +99,7 @@ class ParseChanges: rel = Changes(self.parsed) changes = rel.get("Changes") if not changes: - sys.stderr.write("ERROR:%s %s\n" % (rel, self.parsed)) + self.logger.error("%s %s\n", rel, self.parsed) return self.source_package = rel.get("Source") self.unstable_version = rel.get("Version") @@ -113,9 +128,11 @@ class ParseChanges: if line.package != self.source_package: continue # allow for removed, old or alternate pkg names if line.version: - print( - f"{cve} already has annotation for " - f"- {self.source_package} {line.version}" + self.logger.info( + "%s already has annotation for - %s %s", + cve, + self.source_package, + line.version, ) else: mod_line = line._replace(version=self.unstable_version) @@ -129,12 +146,16 @@ class ParseChanges: if not modified: return if os.path.exists(cve_file): - raise OSError("%s already exists" % cve_file) + self.logger.critical("%s already exists", cve_file) + return -1 mods = [] for cve in modified: - print( - f"Writing to ./{cve_file} with update for {cve.header.name} " - f"- {self.source_package} {self.unstable_version}" + self.logger.info( + "Writing to ./%s with update for %s - %s %s", + cve_file, + cve.header.name, + self.source_package, + self.unstable_version, ) with open(cve_file, "a") as snippet: writecvelist(modified, snippet) @@ -144,11 +165,9 @@ class ParseSources(ParseChanges): """Read latest version in unstable from updated local Sources files""" def parse(self): - print("Retrieving data from local packages data...") + self.logger.info("Retrieving data from local packages data...") if not self.source_package or not self.cves: - sys.stderr.write( - "ERROR: for offline use, specify both --src and --cves options\n" - ) + self.logger.error("for offline use, specify both --src and --cves options") return 1 # self.url contains pkgdir which needs to contain Sources files os.chdir(self.url) @@ -170,17 +189,19 @@ class ParseTrackerAccepted(ParseChanges): e.g. https://tracker.debian.org/news/1285227/accepted-freerdp2-241dfsg1-1-source-into-unstable/ """ + MARKER = '<div class="email-news-body">' + def parse(self): - print("Retrieving data from distro-tracker...") + self.logger.info("Retrieving data from distro-tracker...") req = requests.get(self.url) if req.status_code != requests.codes.ok: # pylint: disable=no-member return 2 self.parsed = [] for line in req.text.splitlines(): - if not self.parsed and not line.startswith('<div class="email-news-body">'): + if not self.parsed and not line.startswith(self.MARKER): continue - if '<div class="email-news-body">' in line: - line = line.replace('<div class="email-news-body">', "") + if self.MARKER in line: + line = line.replace(self.MARKER, "") if "<pre>" in line: line = line.replace("<pre>", "") if line.startswith("\t"): @@ -202,7 +223,7 @@ class ParseDDChanges(ParseChanges): """ def parse(self): - print("Retrieving data from debian-devel-changes archive...") + self.logger.info("Retrieving data from debian-devel-changes archive...") req = requests.get(self.url) if req.status_code != requests.codes.ok: # pylint: disable=no-member return 3 @@ -219,11 +240,33 @@ class ParseDDChanges(ParseChanges): return 0 +class ParseDDStdIn(ParseChanges): + """ + Parse an email originating from debian-devel-changes passed + on STDIN + """ + + MARKER = "-----BEGIN PGP SIGNED MESSAGE-----" + + def parse(self): + self.logger.info("Retrieving data from debian-devel-changes archive...") + content = sys.stdin.read() + for line in content.splitlines(): + if not self.parsed and not line.startswith(self.MARKER): + continue + self.parsed.append(line) + self._read_changes() + self._read_cvelist() + self.add_unstable_version() + return 0 + + def main(): """ 1: Provide an option to parse the email from debian-devel-changes 2: Provide an option to lookup the information using tracker.d.o - 3: Fallback to lookup the information in the local apt-cache + 3: Provide an option to read an email from debian-devel-changes on stdin + 4: Fallback to lookup the information in the local apt-cache data populated by 'make update-packages' data/packages/sid__main_Sources data/packages/sid__contrib_Sources @@ -231,17 +274,22 @@ def main(): """ parser = argparse.ArgumentParser( description="Grab CVE data from a package upload for manual review", - usage="%(prog)s [-h] [[--email EMAIL] | [--tracker TRACKER]] | " + usage="%(prog)s [-h] [[--input] | [--archive URL] | [--tracker TRACKER]] | " "[[--src SRC] & [--cves [CVES ...]]]", epilog="Data is written to a new <source_package>.list " "file which can be used with './bin/merge-cve-files'", ) online = parser.add_argument_group( - "Online - query either the " - "distro-tracker or debian-devel-changes mail archive" + "Online - query one of distro-tracker or " + "debian-devel-changes mail archive or debian-devel-changes email" + ) + online.add_argument( + "--input", + action="store_true", + help="Read from a debian-devel-changes email on STDIN", ) online.add_argument( - "--email", + "--archive", help="URL of debian-devel-changes " "announcement in the list archive", ) online.add_argument( @@ -258,8 +306,11 @@ def main(): "--cves", nargs="*", help="CVE ID tag with version from local packages files" ) args = parser.parse_args() - if args.email: - data = ParseDDChanges(args.email) + if args.input: + data = ParseDDStdIn(args.input) + return data.parse() + if args.archive: + data = ParseDDChanges(args.archive) return data.parse() if args.tracker: data = ParseTrackerAccepted(args.tracker) @@ -270,8 +321,8 @@ def main(): data.source_package = args.src data.cves = args.cves return data.parse() - sys.stderr.write("Unable to parse local package data!\n") - sys.stderr.write("Try running 'make update-packages'\n") + self.logger.error("Unable to parse local package data!") + self.logger.error("Try running 'make update-packages'") return -1 |