diff options
author | John Helmert III <ajak@gentoo.org> | 2021-07-18 21:49:49 -0500 |
---|---|---|
committer | John Helmert III <ajak@gentoo.org> | 2021-07-18 21:54:53 -0500 |
commit | f1634540fe60edd3cbcff258b04d3b4e3aa31577 (patch) | |
tree | ab925018eb698f101c854c3eb8a9d2a1bf024453 | |
parent | cvetool: fix missing import (diff) | |
download | security-f1634540fe60edd3cbcff258b04d3b4e3aa31577.tar.gz security-f1634540fe60edd3cbcff258b04d3b4e3aa31577.tar.bz2 security-f1634540fe60edd3cbcff258b04d3b4e3aa31577.zip |
glsatool: add partial releasing functionality
This separates the previous functionality into a `glsatool new` and adds
some new functionality as `glsatool release`. Currently only fetches the
GLSA XML and text, places the XML in your glsa.git repository, and adds
the necessary headers to the mail text.
Signed-off-by: John Helmert III <ajak@gentoo.org>
-rw-r--r-- | bin/GLSATool.py | 99 |
1 files changed, 90 insertions, 9 deletions
diff --git a/bin/GLSATool.py b/bin/GLSATool.py index c7fc804..a2a1b1b 100644 --- a/bin/GLSATool.py +++ b/bin/GLSATool.py @@ -2,6 +2,7 @@ from configparser import ConfigParser import argparse import os import re +import sys import bugzilla import requests @@ -19,9 +20,15 @@ class GLSATool: 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') + config_path = os.path.join(os.path.expanduser('~'), + '.config', 'glsatool') + c = ConfigParser() + c.read(config_path) + self.glsa_path = c['default']['glsa'] + self.from_str = c['default']['from'] + + def get_csrf_token(self, path): + soup = bs(self.request(path), features='lxml') csrf_token = \ soup.find('input', {'name': 'authenticity_token'})['value'] return csrf_token @@ -45,6 +52,64 @@ class GLSATool: raise RuntimeError(path + ': ' + str(response.status_code)) return response.text + def get_int_input(self, msg): + while True: + i = input(msg) + try: + return int(i) + except (ValueError, EOFError): + continue + + def release_glsa(self, num=None): + if not num: + soup = bs(self.request('/glsas/drafts'), features='lxml') + glsas = soup.find_all('tr', {'class': True}) + for idx, item in enumerate(glsas): + print('[{0}] {1}'.format(idx, item.find('a').text)) + i = self.get_int_input("Which GLSA to release? ") + print("Selected '{0}'".format(glsas[i].a.text)) + num = glsas[i].a['href'][-4:] + + prepare_path = '/glsas/{}/prepare_release'.format(num) + release_path = '/glsas/{}/release'.format(num) + xml_path = '/glsas/{}/download.xml'.format(num) + txt_path = '/glsas/{}/download.txt'.format(num) + + data = { + 'value': 'Release >', + 'authenticity_token': self.get_csrf_token(prepare_path) + } + + # Click the "release" button + released_soup = bs(self.request(release_path, method='POST', data=data), + features='lxml') + glsa_id = 'glsa-' + released_soup.find('strong').text.split()[1] + + # Grab the xml + xml = self.request(xml_path) + xml_filename = '{}.xml'.format(glsa_id) + xml_path = os.path.join(self.glsa_path, xml_filename) + + # Write and (TODO) commit it + with open(xml_path, 'w') as f: + f.write(xml) + print("Wrote {}".format(xml_filename)) + + # Grab the mail text + txt = self.request(txt_path) + txt_filename = '{}.txt'.format(glsa_id) + + # Write it + with open(txt_filename, 'w') as f: + f.write('From: {}\n'.format(self.from_str)) + f.write('Reply-To: security@gentoo.org\n') + f.write(txt) + print("Wrote {}".format(txt_filename)) + + # TODO: + # Mail it + # Close bugs + def new_whiteboard(self, old_whiteboard): regex = re.compile('[A-C~][0-4] \[.*\]') severity = old_whiteboard[:2] @@ -78,7 +143,7 @@ class GLSATool: 'access': 'public', 'import_references': '1', 'what': 'request', # ??? - 'authenticity_token': self.get_csrf_token() + 'authenticity_token': self.get_csrf_token('/glsas/new') } self.request('/glsas', method='POST', data=data) print("GLSA request filed") @@ -104,10 +169,26 @@ def bgo_key(): def glsatool(): parser = argparse.ArgumentParser() - parser.add_argument('-b', '--bugs', required=True, nargs='+') - parser.add_argument('-t', '--title', required=True) + subparsers = parser.add_subparsers(dest='command') + + new_parser = subparsers.add_parser('new') + new_parser.add_argument('-b', '--bugs', required=True, nargs='+') + new_parser.add_argument('-t', '--title', required=True) + + release_parser = subparsers.add_parser('release') + release_parser.add_argument('-i', '--id') + 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) + gtool = GLSATool(auth, bgo_key()) + if args.command == 'new': + for bug in args.bugs: + CVETool(auth, 'dobug', [bug]) + gtool.new_glsa(args.title, args.bugs) + elif args.command == 'release': + if args.id: + gtool.release_glsa(num=args.id) + else: + gtool.release_glsa() + else: + print("No command given!") |