aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Helmert III <ajak@gentoo.org>2021-07-05 21:03:14 -0500
committerJohn Helmert III <ajak@gentoo.org>2021-07-05 21:03:43 -0500
commit6dc80e16f0f208b7bbe143160186c930b151d8e1 (patch)
treed39492922beb91af31106baa4e4f88cc073156ca
parentglsatool: drop, accidentally added, not ready yet (diff)
downloadsecurity-6dc80e16.tar.gz
security-6dc80e16.tar.bz2
security-6dc80e16.zip
glsatool: new tool
Signed-off-by: John Helmert III <ajak@gentoo.org>
-rwxr-xr-xbin/glsatool115
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)