[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: b3cdddf783f0f31bc2b44e85edec6abade128fe3 Author: John Helmert III gentoo org> AuthorDate: Sat Jul 24 03:18:26 2021 + Commit: John Helmert III gentoo org> CommitDate: Sat Jul 24 03:18:26 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=b3cdddf7 glsatool: avoid trying to publish GLSAs with TODOs Signed-off-by: John Helmert III gentoo.org> bin/GLSATool.py | 4 1 file changed, 4 insertions(+) diff --git a/bin/GLSATool.py b/bin/GLSATool.py index a2a1b1b..9aa21b9 100644 --- a/bin/GLSATool.py +++ b/bin/GLSATool.py @@ -85,6 +85,10 @@ class GLSATool: features='lxml') glsa_id = 'glsa-' + released_soup.find('strong').text.split()[1] +# If there are red flags glsa_id will end up being 'for', so +# bail out on the releasing process just like GLSAMaker would +assert 'for' not in glsa_id + # Grab the xml xml = self.request(xml_path) xml_filename = '{}.xml'.format(glsa_id)
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: cd40de0310372a545d7190f716de184e5882be41 Author: John Helmert III gentoo org> AuthorDate: Sat Jul 24 03:19:04 2021 + Commit: John Helmert III gentoo org> CommitDate: Sat Jul 24 03:19:04 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=cd40de03 glsatool: implement closing bugs when releasing Signed-off-by: John Helmert III gentoo.org> bin/GLSATool.py | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/GLSATool.py b/bin/GLSATool.py index 9aa21b9..7f3a9b2 100644 --- a/bin/GLSATool.py +++ b/bin/GLSATool.py @@ -74,6 +74,7 @@ class GLSATool: release_path = '/glsas/{}/release'.format(num) xml_path = '/glsas/{}/download.xml'.format(num) txt_path = '/glsas/{}/download.txt'.format(num) +finalize_path = '/glsas/{}/finalize_release'.format(num) data = { 'value': 'Release ', @@ -110,9 +111,11 @@ class GLSATool: f.write(txt) print("Wrote {}".format(txt_filename)) -# TODO: -# Mail it # Close bugs +self.request(finalize_path, 'POST', data={'close_bugs': 1}) + +# TODO: Mail it + def new_whiteboard(self, old_whiteboard): regex = re.compile('[A-C~][0-4] \[.*\]')
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: f1634540fe60edd3cbcff258b04d3b4e3aa31577 Author: John Helmert III gentoo org> AuthorDate: Mon Jul 19 02:49:49 2021 + Commit: John Helmert III gentoo org> CommitDate: Mon Jul 19 02:54:53 2021 + 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 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: secur...@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',
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: 4a160a6b646b01fa14f59ac14337640141451864 Author: John Helmert III gentoo org> AuthorDate: Sat Jul 17 16:46:39 2021 + Commit: John Helmert III gentoo org> CommitDate: Mon Jul 19 02:54:43 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=4a160a6b cvetool: fix missing import Signed-off-by: John Helmert III gentoo.org> bin/CVETool.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/CVETool.py b/bin/CVETool.py index 7a5c576..29eab39 100644 --- a/bin/CVETool.py +++ b/bin/CVETool.py @@ -1,4 +1,5 @@ import re +import os import sys from base64 import b64encode
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: b95debb109f03769167713f63d572e5857709b39 Author: John Helmert III gentoo org> AuthorDate: Tue Jul 6 23:32:42 2021 + Commit: John Helmert III gentoo org> CommitDate: Tue Jul 6 23:32:42 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=b95debb1 glsatool: reorganize into module and script (like cvetool) Signed-off-by: John Helmert III gentoo.org> bin/{glsatool => GLSATool.py} | 4 +- bin/glsatool | 116 ++ 2 files changed, 6 insertions(+), 114 deletions(-) diff --git a/bin/glsatool b/bin/GLSATool.py old mode 100755 new mode 100644 similarity index 98% copy from bin/glsatool copy to bin/GLSATool.py index 6755f32..c7fc804 --- a/bin/glsatool +++ b/bin/GLSATool.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from configparser import ConfigParser import argparse import os @@ -104,7 +102,7 @@ def bgo_key(): return apikey -if __name__ == '__main__': +def glsatool(): parser = argparse.ArgumentParser() parser.add_argument('-b', '--bugs', required=True, nargs='+') parser.add_argument('-t', '--title', required=True) diff --git a/bin/glsatool b/bin/glsatool index 6755f32..2f8e88a 100755 --- a/bin/glsatool +++ b/bin/glsatool @@ -1,115 +1,9 @@ #!/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), - 'comment': {'comment': 'GLSA request filed.'}} -print('https://bugs.gentoo.org/{}: {} -> {}' - .format(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() -
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: f6fcf4b3d4a640ba54b2eaa2ed68f5f1ef8a11bd Author: John Helmert III gentoo org> AuthorDate: Tue Jul 6 02:25:48 2021 + Commit: John Helmert III gentoo org> CommitDate: Tue Jul 6 02:26:44 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=f6fcf4b3 glsamaker: readability improvements Signed-off-by: John Helmert III gentoo.org> bin/glsatool | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/glsatool b/bin/glsatool index f1d69c6..6755f32 100755 --- a/bin/glsatool +++ b/bin/glsatool @@ -67,10 +67,10 @@ class GLSATool: 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']) +update = {'whiteboard': self.new_whiteboard(bug.whiteboard), + 'comment': {'comment': 'GLSA request filed.'}} +print('https://bugs.gentoo.org/{}: {} -> {}' + .format(str(bug.id), bug.whiteboard, update['whiteboard'])) self.bgo.update_bugs([bug.id], update) def new_glsa(self, title, bugs):
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: 6dc80e16f0f208b7bbe143160186c930b151d8e1 Author: John Helmert III gentoo org> AuthorDate: Tue Jul 6 02:03:14 2021 + Commit: John Helmert III gentoo org> CommitDate: Tue Jul 6 02:03:43 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=6dc80e16 glsatool: new tool Signed-off-by: John Helmert III gentoo.org> bin/glsatool | 115 +++ 1 file changed, 115 insertions(+) diff --git a/bin/glsatool b/bin/glsatool new file mode 100755 index 000..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)
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: be4a8b7e8023688a31e931b46fc3ef8651a290a5 Author: John Helmert III gentoo org> AuthorDate: Mon Jul 5 20:27:13 2021 + Commit: John Helmert III gentoo org> CommitDate: Mon Jul 5 20:28:01 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=be4a8b7e glsatool: drop, accidentally added, not ready yet Signed-off-by: John Helmert III gentoo.org> bin/glsatool | 74 1 file changed, 74 deletions(-) diff --git a/bin/glsatool b/bin/glsatool deleted file mode 100755 index 4582a40..000 --- a/bin/glsatool +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python - -import argparse -import os -import re -import typing - -import bugzilla -import bracex -import pkgcore.config -from pkgcore.ebuild import atom -import requests - -from cvetool import CVETool - -PKG_SEPARATORS = re.compile(r':\s|[\s,;(){}[\]]') -GLSAMAKER_URI = 'https://glsamaker.gentoo.org' -bgo = bugzilla.Bugzilla('https://bugs.gentoo.org') -repo = pkgcore.config.load_config().repo['gentoo'] - - -class GLSATool: -""" Utility to ease GLSA handling in GLSAMaker """ - -def __init__(self, auth): -self.auth = auth - -# https://github.com/mgorny/kuroneko/blob/master/kuroneko/scraper.py#L80 -def find_package_specs(s: str) -> typing.Iterable[atom.atom]: -"""Find potentially valid package specifications in given string.""" -words = set() -# consider all possible expansions -for exp in bracex.iexpand(s): -words.update(PKG_SEPARATORS.split(exp)) -for w in words: -# skip anything that couldn't be cat/pkg early -if '/' not in w: -continue -try: -yield atom.atom(w) -except MalformedAtom: -continue - -def new_glsa(auth, title, bugs): -post = requests.post(GLSAMAKER_URI + '/glsas', - data={'title': title + ' [DRAFT]', - 'bugs': ','.join(bugs), - 'access': 'public', - 'import_references': '1', - 'what': 'request', # ??? - 'authenticity_token': 'k75YYdGlcL+dlZS7RKXSVxKaKl2tiiMvwWlReFtKzt3NCKDE2AeskkrZ851xJB7uCBRUTpstV+/aqUTEx3MfIQ=='}, - headers={'Authorization': 'Basic ' + auth}) -if not post.ok: -import pdb; pdb.set_trace() - - -def get_auth(): -authpath = os.path.join(os.path.expanduser('~'), '.config', 'cvetool_auth') -if 'CVETOOL_AUTH' in os.environ: -return os.environ['CVETOOL_AUTH'] -elif os.path.isfile(authpath): -with open(authpath, 'r') as authfile: -return authfile.readlines()[0] - - -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 = get_auth() -for bug in args.bugs: -CVETool(auth, 'dobug', [bug]) -new_glsa(auth, args.title, args.bugs)
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: 5976eb82d7f4af4de9083914cfb728ed1a331e38 Author: John Helmert III gentoo org> AuthorDate: Mon Jul 5 20:10:05 2021 + Commit: John Helmert III gentoo org> CommitDate: Mon Jul 5 20:20:36 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=5976eb82 cvetool: reorganize cvetool code into python module and callable script Signed-off-by: John Helmert III gentoo.org> bin/CVETool.py | 18 ++ bin/cvetool| 25 ++-- bin/glsatool | 74 ++ 3 files changed, 94 insertions(+), 23 deletions(-) diff --git a/bin/CVETool.py b/bin/CVETool.py index c5996f6..7a5c576 100644 --- a/bin/CVETool.py +++ b/bin/CVETool.py @@ -240,3 +240,21 @@ class CVETool: if jsondata: return response.json() return response.text + + +def cvetool(): +if len(sys.argv) == 1: +CVETool(None, 'usage', sys.argv[2:]) + +auth = None +authpath = os.path.join(os.path.expanduser('~'), '.config', 'cvetool_auth') +if 'CVETOOL_AUTH' in os.environ: +auth = os.environ['CVETOOL_AUTH'] +elif os.path.isfile(authpath): +with open(authpath, 'r') as authfile: +auth = authfile.readlines()[0] +elif 'CVETOOL_AUTH' not in os.environ and not sys.argv[1] == 'pw': +print('CVETOOL_AUTH environment variable missing. Generate its contents with the pw subcommand.') +sys.exit(1) + +CVETool(auth, sys.argv[1], sys.argv[2:]) diff --git a/bin/cvetool b/bin/cvetool index 7e30837..d5aa25f 100755 --- a/bin/cvetool +++ b/bin/cvetool @@ -2,32 +2,11 @@ # Copyright 2016 Alex Legler # Distributed under the terms of the GNU General Public License v3 -import os -import re -import sys - -from CVETool import CVETool - -def main(): -if len(sys.argv) == 1: -CVETool(None, 'usage', sys.argv[2:]) - -auth = None -authpath = os.path.join(os.path.expanduser('~'), '.config', 'cvetool_auth') -if 'CVETOOL_AUTH' in os.environ: -auth = os.environ['CVETOOL_AUTH'] -elif os.path.isfile(authpath): -with open(authpath, 'r') as authfile: -auth = authfile.readlines()[0] -elif 'CVETOOL_AUTH' not in os.environ and not sys.argv[1] == 'pw': -print('CVETOOL_AUTH environment variable missing. Generate its contents with the pw subcommand.') -sys.exit(1) - -CVETool(auth, sys.argv[1], sys.argv[2:]) +from CVETool import CVETool, cvetool if __name__ == "__main__": try: -main() +cvetool() except KeyboardInterrupt: print('\n ! Exiting.') diff --git a/bin/glsatool b/bin/glsatool new file mode 100755 index 000..4582a40 --- /dev/null +++ b/bin/glsatool @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +import argparse +import os +import re +import typing + +import bugzilla +import bracex +import pkgcore.config +from pkgcore.ebuild import atom +import requests + +from cvetool import CVETool + +PKG_SEPARATORS = re.compile(r':\s|[\s,;(){}[\]]') +GLSAMAKER_URI = 'https://glsamaker.gentoo.org' +bgo = bugzilla.Bugzilla('https://bugs.gentoo.org') +repo = pkgcore.config.load_config().repo['gentoo'] + + +class GLSATool: +""" Utility to ease GLSA handling in GLSAMaker """ + +def __init__(self, auth): +self.auth = auth + +# https://github.com/mgorny/kuroneko/blob/master/kuroneko/scraper.py#L80 +def find_package_specs(s: str) -> typing.Iterable[atom.atom]: +"""Find potentially valid package specifications in given string.""" +words = set() +# consider all possible expansions +for exp in bracex.iexpand(s): +words.update(PKG_SEPARATORS.split(exp)) +for w in words: +# skip anything that couldn't be cat/pkg early +if '/' not in w: +continue +try: +yield atom.atom(w) +except MalformedAtom: +continue + +def new_glsa(auth, title, bugs): +post = requests.post(GLSAMAKER_URI + '/glsas', + data={'title': title + ' [DRAFT]', + 'bugs': ','.join(bugs), + 'access': 'public', + 'import_references': '1', + 'what': 'request', # ??? + 'authenticity_token': 'k75YYdGlcL+dlZS7RKXSVxKaKl2tiiMvwWlReFtKzt3NCKDE2AeskkrZ851xJB7uCBRUTpstV+/aqUTEx3MfIQ=='}, + headers={'Authorization': 'Basic ' + auth}) +if not post.ok: +import pdb; pdb.set_trace() + + +def get_auth(): +authpath = os.path.join(os.path.expanduser('~'), '.config', 'cvetool_auth') +if 'CVETOOL_AUTH' in os.environ: +return os.environ['CVETOOL_AUTH'] +elif os.path.isfile(authpath): +with open(authpath, 'r') as authfile: +return authfile.readlines()[0] + + +if __name__ ==
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: abe128db3bf0ede3f813de854ccee897941638f1 Author: John Helmert III gentoo org> AuthorDate: Mon Jul 5 18:38:38 2021 + Commit: John Helmert III gentoo org> CommitDate: Mon Jul 5 18:38:38 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=abe128db bin/: split CVETool class into own file ...and rename cvetool.py back to cvetool Signed-off-by: John Helmert III gentoo.org> bin/{cvetool.py => CVETool.py} | 33 ++--- bin/cvetool| 33 + 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/bin/cvetool.py b/bin/CVETool.py old mode 100755 new mode 100644 similarity index 90% rename from bin/cvetool.py rename to bin/CVETool.py index 557c030..c5996f6 --- a/bin/cvetool.py +++ b/bin/CVETool.py @@ -1,12 +1,8 @@ -#!/usr/bin/env python3 -# Copyright 2016 Alex Legler -# Distributed under the terms of the GNU General Public License v3 - import re import sys -import os -from urllib.parse import urlencode + from base64 import b64encode +from urllib.parse import urlencode import requests GLSAMAKER_URI = 'https://glsamaker.gentoo.org' @@ -244,28 +240,3 @@ class CVETool: if jsondata: return response.json() return response.text - - -def main(): -if len(sys.argv) == 1: -CVETool(None, 'usage', sys.argv[2:]) - -auth = None -authpath = os.path.join(os.path.expanduser('~'), '.config', 'cvetool_auth') -if 'CVETOOL_AUTH' in os.environ: -auth = os.environ['CVETOOL_AUTH'] -elif os.path.isfile(authpath): -with open(authpath, 'r') as authfile: -auth = authfile.readlines()[0] -elif 'CVETOOL_AUTH' not in os.environ and not sys.argv[1] == 'pw': -print('CVETOOL_AUTH environment variable missing. Generate its contents with the pw subcommand.') -sys.exit(1) - -CVETool(auth, sys.argv[1], sys.argv[2:]) - - -if __name__ == "__main__": -try: -main() -except KeyboardInterrupt: -print('\n ! Exiting.') diff --git a/bin/cvetool b/bin/cvetool new file mode 100755 index 000..7e30837 --- /dev/null +++ b/bin/cvetool @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# Copyright 2016 Alex Legler +# Distributed under the terms of the GNU General Public License v3 + +import os +import re +import sys + +from CVETool import CVETool + +def main(): +if len(sys.argv) == 1: +CVETool(None, 'usage', sys.argv[2:]) + +auth = None +authpath = os.path.join(os.path.expanduser('~'), '.config', 'cvetool_auth') +if 'CVETOOL_AUTH' in os.environ: +auth = os.environ['CVETOOL_AUTH'] +elif os.path.isfile(authpath): +with open(authpath, 'r') as authfile: +auth = authfile.readlines()[0] +elif 'CVETOOL_AUTH' not in os.environ and not sys.argv[1] == 'pw': +print('CVETOOL_AUTH environment variable missing. Generate its contents with the pw subcommand.') +sys.exit(1) + +CVETool(auth, sys.argv[1], sys.argv[2:]) + + +if __name__ == "__main__": +try: +main() +except KeyboardInterrupt: +print('\n ! Exiting.')
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: 833da1349cff01ccea594ac104d603961b480a71 Author: John Helmert III gentoo org> AuthorDate: Mon Jul 5 01:29:27 2021 + Commit: John Helmert III gentoo org> CommitDate: Mon Jul 5 01:30:16 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=833da134 cvetool: rename to cvetool.py This is necessary so other tools can import the CVETool class itself Signed-off-by: John Helmert III gentoo.org> bin/{cvetool => cvetool.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/cvetool b/bin/cvetool.py old mode 100755 new mode 100644 similarity index 100% rename from bin/cvetool rename to bin/cvetool.py
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: f38466de27e3785cadbfaa45d435dc03445197e9 Author: John Helmert III gentoo org> AuthorDate: Mon Jul 5 01:51:29 2021 + Commit: John Helmert III gentoo org> CommitDate: Mon Jul 5 01:52:58 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=f38466de cvetool: avoid referencing sys.argv in CVETool constructor This is wrong because we pass in sys.argv in the constructor arguments anyway, and referring to sys.argv directly breaks consumers that aren't the cvetool script. The last use of sys.argv in the constructor is when command is invalid and self.usage(sys.argv[0]) is called, if you hit this it means you were calling CVETool programmatically, so surely you can debug it :) Signed-off-by: John Helmert III gentoo.org> bin/cvetool.py | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bin/cvetool.py b/bin/cvetool.py old mode 100644 new mode 100755 index 744e2a5..557c030 --- a/bin/cvetool.py +++ b/bin/cvetool.py @@ -36,9 +36,9 @@ class CVETool: sys.exit(1) try: -self.info(self.cleanup_cve(sys.argv[2])) +self.info(self.cleanup_cve(args[0])) except ValueError: -print('"{}" is not a valid CVE identifier!'.format(sys.argv[2])) +print('"{}" is not a valid CVE identifier!'.format(args[0])) sys.exit(1) elif command == 'assign': if len(args) < 2: @@ -53,7 +53,7 @@ class CVETool: print('Returns a list of the real CVE IDs') sys.exit(1) -self.getcveidlist([self.cleanup_cve(cve) for cve in args[0:]]) +self.getcveidlist([self.cleanup_cve(cve) for cve in args]) elif command == 'new': if len(args) != 1: print('Usage: new ') @@ -61,9 +61,9 @@ class CVETool: sys.exit(1) try: -self.new(self.cleanup_cve(sys.argv[2])) +self.new(self.cleanup_cve(args[0])) except ValueError: -print('"{}" is not a valid CVE identifier!'.format(sys.argv[2])) +print('"{}" is not a valid CVE identifier!'.format(args[0])) sys.exit(1) elif command == 'nfu': if len(args) != 1: @@ -78,14 +78,14 @@ class CVETool: print('Generates a base64-encoded credential for storing') sys.exit(1) -self.pw(sys.argv[2], sys.argv[3]) +self.pw(args[0], args[1]) elif command == 'dobug': if len(args) != 1: print('Usage: dobug ') print('Adds and assigns a bug\'s CVEs') sys.exit(1) -self.dobug(sys.argv[2]) +self.dobug(args[0]) else: self.usage(sys.argv[0]) sys.exit(1)
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: b599466bea8a657b2716a96d9c0a355728af4f7c Author: John Helmert III gentoo org> AuthorDate: Mon Jul 5 01:40:16 2021 + Commit: John Helmert III gentoo org> CommitDate: Mon Jul 5 01:43:32 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=b599466b cvetool: sanity check CVETool args rather than sys.argv Signed-off-by: John Helmert III gentoo.org> bin/cvetool.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/cvetool.py b/bin/cvetool.py index 233375a..744e2a5 100644 --- a/bin/cvetool.py +++ b/bin/cvetool.py @@ -73,14 +73,14 @@ class CVETool: self.nfu(self.cleanup_cve(args[0])) elif command == 'pw': -if len(sys.argv) != 4: +if len(args) != 2: print('Usage: pw ') print('Generates a base64-encoded credential for storing') sys.exit(1) self.pw(sys.argv[2], sys.argv[3]) elif command == 'dobug': -if len(sys.argv) != 3: +if len(args) != 1: print('Usage: dobug ') print('Adds and assigns a bug\'s CVEs') sys.exit(1)
[gentoo-commits] proj/security:ajak-cvetool commit in: bin/
commit: eed0fdb7e16ff4d2b475f7803a6888c8a3c0d7da Author: John Helmert III gentoo org> AuthorDate: Sun Jul 4 04:41:53 2021 + Commit: John Helmert III gentoo org> CommitDate: Sun Jul 4 04:41:53 2021 + URL:https://gitweb.gentoo.org/proj/security.git/commit/?id=eed0fdb7 cvetool: implement dobug command This command grabs bug data from Bugzilla and adds the CVEs in its alias field to the GLSAMaker CVE database and assigns the CVEs to that bug in GLSAMaker. Signed-off-by: John Helmert III gentoo.org> bin/cvetool | 55 ++- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/bin/cvetool b/bin/cvetool index dc9c35d..233375a 100755 --- a/bin/cvetool +++ b/bin/cvetool @@ -9,7 +9,8 @@ from urllib.parse import urlencode from base64 import b64encode import requests -URI_BASE = 'https://glsamaker.gentoo.org' +GLSAMAKER_URI = 'https://glsamaker.gentoo.org' +BGO_URI = 'https://bugs.gentoo.org' class CVETool: @@ -78,6 +79,13 @@ class CVETool: sys.exit(1) self.pw(sys.argv[2], sys.argv[3]) +elif command == 'dobug': +if len(sys.argv) != 3: +print('Usage: dobug ') +print('Adds and assigns a bug\'s CVEs') +sys.exit(1) + +self.dobug(sys.argv[2]) else: self.usage(sys.argv[0]) sys.exit(1) @@ -162,6 +170,36 @@ class CVETool: def pw(self, user, password): print(b64encode(bytes(user + ':' + password, 'utf-8')).decode('ascii')) +def dobug(self, bug): +cves = [] +data = self.request('/rest/bug/' + bug, jsondata=True, bgo=True) +for alias in data['bugs'][0]['alias']: +# If we were able to catch a sane error in new() to +# reflect a duplicate CVE we wouldn't have to check if the +# CVE exists beforehand with cve_exists, but it seems the +# only other way is to try to do two requests and check if +# one fails and the other succeeds (as new() currently +# works). By doing it this way though, we actually reduce +# the number of requests by not making useless requests in +# new(). +if self.is_cve(alias) and not self.cve_exists(alias): +self.new(alias) +cves.append(alias) +# We can do assignment in one request, so do it +if cves: +self.assign(bug, cves) + +def cve_exists(self, cve): +try: +return self.request('/cve/info/' + cve, method='HEAD') == '' +except RuntimeError: +return False + +@staticmethod +def is_cve(string): +regex = re.compile('^(CVE-)?\d{4}-\d{4,}$') +return regex.match(string) + def get_internal_cve_id(self, cve): """ Resolves a CVE id to the internal databse ID """ return self.json_request('/cve/info/' + cve + '.json')['id'] @@ -170,8 +208,7 @@ class CVETool: return self.request(uri, method, jsondata=True) def cleanup_cve(self, string): -regex = re.compile('^(CVE-)?\d{4}-\d{4,}$') -if not regex.match(string): +if not self.is_cve(string): raise ValueError('Cannot parse CVE: ' + string) if not string.startswith('CVE-'): @@ -179,8 +216,12 @@ class CVETool: else: return string -def request(self, uri, method='GET', jsondata=False): -full_uri = URI_BASE + uri +def request(self, uri, method='GET', jsondata=False, bgo=False): +if bgo: +full_uri = BGO_URI + uri +else: +full_uri = GLSAMAKER_URI + uri + if method == 'GET': response = \ requests.get(full_uri, @@ -189,6 +230,10 @@ class CVETool: response = \ requests.post(full_uri, headers={'Authorization': 'Basic ' + self.auth}) +elif method == 'HEAD': +response = \ +requests.head(full_uri, + headers={'Authorization': 'Basic ' + self.auth}) status = response.status_code if status == 404: