From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <gentoo-commits+bounces-1303884-garchives=archives.gentoo.org@lists.gentoo.org> Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 8FC1B139347 for <garchives@archives.gentoo.org>; Mon, 19 Jul 2021 02:55:08 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 367DBE0B2E; Mon, 19 Jul 2021 02:55:07 +0000 (UTC) Received: from smtp.gentoo.org (dev.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 10B1EE0B2E for <gentoo-commits@lists.gentoo.org>; Mon, 19 Jul 2021 02:55:07 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 9AADD342AD5 for <gentoo-commits@lists.gentoo.org>; Mon, 19 Jul 2021 02:55:05 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 323D57D9 for <gentoo-commits@lists.gentoo.org>; Mon, 19 Jul 2021 02:55:04 +0000 (UTC) From: "John Helmert III" <ajak@gentoo.org> To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "John Helmert III" <ajak@gentoo.org> Message-ID: <1626663293.f1634540fe60edd3cbcff258b04d3b4e3aa31577.ajak@gentoo> Subject: [gentoo-commits] proj/security:ajak-cvetool commit in: bin/ X-VCS-Repository: proj/security X-VCS-Files: bin/GLSATool.py X-VCS-Directories: bin/ X-VCS-Committer: ajak X-VCS-Committer-Name: John Helmert III X-VCS-Revision: f1634540fe60edd3cbcff258b04d3b4e3aa31577 X-VCS-Branch: ajak-cvetool Date: Mon, 19 Jul 2021 02:55:04 +0000 (UTC) Precedence: bulk List-Post: <mailto:gentoo-commits@lists.gentoo.org> List-Help: <mailto:gentoo-commits+help@lists.gentoo.org> List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org> List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org> List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org> X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 27477205-ac83-4e32-a48a-b8a235d1b36a X-Archives-Hash: 18536d6ebd5897d9b0a5f17e0aef5721 commit: f1634540fe60edd3cbcff258b04d3b4e3aa31577 Author: John Helmert III <ajak <AT> gentoo <DOT> org> AuthorDate: Mon Jul 19 02:49:49 2021 +0000 Commit: John Helmert III <ajak <AT> gentoo <DOT> org> CommitDate: Mon Jul 19 02:54:53 2021 +0000 URL: https://gitweb.gentoo.org/proj/security.git/commit/?id=f1634540 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 <AT> gentoo.org> bin/GLSATool.py | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file 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!")