diff options
author | John Helmert III <ajak@gentoo.org> | 2021-07-05 21:03:14 -0500 |
---|---|---|
committer | John Helmert III <ajak@gentoo.org> | 2021-07-05 21:03:43 -0500 |
commit | 6dc80e16f0f208b7bbe143160186c930b151d8e1 (patch) | |
tree | d39492922beb91af31106baa4e4f88cc073156ca | |
parent | glsatool: drop, accidentally added, not ready yet (diff) | |
download | security-6dc80e16.tar.gz security-6dc80e16.tar.bz2 security-6dc80e16.zip |
glsatool: new tool
Signed-off-by: John Helmert III <ajak@gentoo.org>
-rwxr-xr-x | bin/glsatool | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/bin/glsatool b/bin/glsatool new file mode 100755 index 0000000..f1d69c6 --- /dev/null +++ b/bin/glsatool @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +from configparser import ConfigParser +import argparse +import os +import re + +import bugzilla +import requests +from bs4 import BeautifulSoup as bs + +from CVETool import CVETool + +GLSAMAKER_URI = 'https://glsamaker.gentoo.org' + + +class GLSATool: + """ Utility to ease GLSA handling in GLSAMaker """ + + def __init__(self, glsamaker_key, bgo_key): + self.auth = glsamaker_key + self.bgo = bugzilla.Bugzilla('https://bugs.gentoo.org', + api_key=bgo_key, force_rest=True) + + def get_csrf_token(self): + soup = bs(self.request('/glsas/new'), features='lxml') + csrf_token = \ + soup.find('input', {'name': 'authenticity_token'})['value'] + return csrf_token + + def request(self, path, method='GET', data=None): + if method == 'GET': + response = requests.get(GLSAMAKER_URI + path, + headers={'Authorization': + 'Basic ' + self.auth}) + elif method == 'POST': + if data: + response = requests.post(GLSAMAKER_URI + path, + data=data, + headers={'Authorization': + 'Basic ' + self.auth}) + else: + response = requests.post(GLSAMAKER_URI + path, + headers={'Authorization': + 'Basic ' + self.auth}) + if not response.ok: + raise RuntimeError(path + ': ' + str(response.status_code)) + return response.text + + def new_whiteboard(self, old_whiteboard): + regex = re.compile('[A-C~][0-4] \[.*\]') + severity = old_whiteboard[:2] + new = ['glsa'] + + if not regex.match(old_whiteboard): + # Don't even try to operate on a whiteboard with a strange + # format + raise RuntimeError("Bad whiteboard! '" + old_whiteboard + "'") + + # Iterate over words within the [] part of whiteboard + for word in re.sub('[\[\]]', '', old_whiteboard[2:]).split(): + if 'glsa' not in word: + new += [word] + if 'cve' not in new: + new.append('cve') + return severity + ' [' + ' '.join(new) + ']' + + def update_bugs(self, bugs): + for bug in self.bgo.getbugs(bugs): + update = {'whiteboard': self.new_whiteboard(bug.whiteboard)} + update['comment'] = {'comment': 'GLSA request filed.'} + print('https://bugs.gentoo.org/' + str(bug.id) + ': ' + + bug.whiteboard + ' -> ' + update['whiteboard']) + self.bgo.update_bugs([bug.id], update) + + def new_glsa(self, title, bugs): + data = { + 'title': title + ' [DRAFT]', + 'bugs': ','.join(bugs), + 'access': 'public', + 'import_references': '1', + 'what': 'request', # ??? + 'authenticity_token': self.get_csrf_token() + } + self.request('/glsas', method='POST', data=data) + print("GLSA request filed") + self.update_bugs(bugs) + + +def glsamaker_key(): + authpath = os.path.join(os.path.expanduser('~'), '.config', 'cvetool_auth') + if 'CVETOOL_AUTH' in os.environ: + return os.environ['CVETOOL_AUTH'] + if os.path.isfile(authpath): + with open(authpath, 'r') as authfile: + return authfile.readlines()[0] + + +def bgo_key(): + bugzrc = os.path.expanduser("~/.bugzrc") + config = ConfigParser() + config.read(bugzrc) + apikey = config['default']['key'] + return apikey + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('-b', '--bugs', required=True, nargs='+') + parser.add_argument('-t', '--title', required=True) + args = parser.parse_args() + auth = glsamaker_key() + for bug in args.bugs: + CVETool(auth, 'dobug', [bug]) + GLSATool(auth, bgo_key()).new_glsa(args.title, args.bugs) |