Gentoo Archives: gentoo-commits

From: John Helmert III <ajak@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/security:ajak-cvetool commit in: bin/
Date: Tue, 06 Jul 2021 02:03:57
Message-Id: 1625537023.6dc80e16f0f208b7bbe143160186c930b151d8e1.ajak@gentoo
1 commit: 6dc80e16f0f208b7bbe143160186c930b151d8e1
2 Author: John Helmert III <ajak <AT> gentoo <DOT> org>
3 AuthorDate: Tue Jul 6 02:03:14 2021 +0000
4 Commit: John Helmert III <ajak <AT> gentoo <DOT> org>
5 CommitDate: Tue Jul 6 02:03:43 2021 +0000
6 URL: https://gitweb.gentoo.org/proj/security.git/commit/?id=6dc80e16
7
8 glsatool: new tool
9
10 Signed-off-by: John Helmert III <ajak <AT> gentoo.org>
11
12 bin/glsatool | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 1 file changed, 115 insertions(+)
14
15 diff --git a/bin/glsatool b/bin/glsatool
16 new file mode 100755
17 index 0000000..f1d69c6
18 --- /dev/null
19 +++ b/bin/glsatool
20 @@ -0,0 +1,115 @@
21 +#!/usr/bin/env python
22 +
23 +from configparser import ConfigParser
24 +import argparse
25 +import os
26 +import re
27 +
28 +import bugzilla
29 +import requests
30 +from bs4 import BeautifulSoup as bs
31 +
32 +from CVETool import CVETool
33 +
34 +GLSAMAKER_URI = 'https://glsamaker.gentoo.org'
35 +
36 +
37 +class GLSATool:
38 + """ Utility to ease GLSA handling in GLSAMaker """
39 +
40 + def __init__(self, glsamaker_key, bgo_key):
41 + self.auth = glsamaker_key
42 + self.bgo = bugzilla.Bugzilla('https://bugs.gentoo.org',
43 + api_key=bgo_key, force_rest=True)
44 +
45 + def get_csrf_token(self):
46 + soup = bs(self.request('/glsas/new'), features='lxml')
47 + csrf_token = \
48 + soup.find('input', {'name': 'authenticity_token'})['value']
49 + return csrf_token
50 +
51 + def request(self, path, method='GET', data=None):
52 + if method == 'GET':
53 + response = requests.get(GLSAMAKER_URI + path,
54 + headers={'Authorization':
55 + 'Basic ' + self.auth})
56 + elif method == 'POST':
57 + if data:
58 + response = requests.post(GLSAMAKER_URI + path,
59 + data=data,
60 + headers={'Authorization':
61 + 'Basic ' + self.auth})
62 + else:
63 + response = requests.post(GLSAMAKER_URI + path,
64 + headers={'Authorization':
65 + 'Basic ' + self.auth})
66 + if not response.ok:
67 + raise RuntimeError(path + ': ' + str(response.status_code))
68 + return response.text
69 +
70 + def new_whiteboard(self, old_whiteboard):
71 + regex = re.compile('[A-C~][0-4] \[.*\]')
72 + severity = old_whiteboard[:2]
73 + new = ['glsa']
74 +
75 + if not regex.match(old_whiteboard):
76 + # Don't even try to operate on a whiteboard with a strange
77 + # format
78 + raise RuntimeError("Bad whiteboard! '" + old_whiteboard + "'")
79 +
80 + # Iterate over words within the [] part of whiteboard
81 + for word in re.sub('[\[\]]', '', old_whiteboard[2:]).split():
82 + if 'glsa' not in word:
83 + new += [word]
84 + if 'cve' not in new:
85 + new.append('cve')
86 + return severity + ' [' + ' '.join(new) + ']'
87 +
88 + def update_bugs(self, bugs):
89 + for bug in self.bgo.getbugs(bugs):
90 + update = {'whiteboard': self.new_whiteboard(bug.whiteboard)}
91 + update['comment'] = {'comment': 'GLSA request filed.'}
92 + print('https://bugs.gentoo.org/' + str(bug.id) + ': ' +
93 + bug.whiteboard + ' -> ' + update['whiteboard'])
94 + self.bgo.update_bugs([bug.id], update)
95 +
96 + def new_glsa(self, title, bugs):
97 + data = {
98 + 'title': title + ' [DRAFT]',
99 + 'bugs': ','.join(bugs),
100 + 'access': 'public',
101 + 'import_references': '1',
102 + 'what': 'request', # ???
103 + 'authenticity_token': self.get_csrf_token()
104 + }
105 + self.request('/glsas', method='POST', data=data)
106 + print("GLSA request filed")
107 + self.update_bugs(bugs)
108 +
109 +
110 +def glsamaker_key():
111 + authpath = os.path.join(os.path.expanduser('~'), '.config', 'cvetool_auth')
112 + if 'CVETOOL_AUTH' in os.environ:
113 + return os.environ['CVETOOL_AUTH']
114 + if os.path.isfile(authpath):
115 + with open(authpath, 'r') as authfile:
116 + return authfile.readlines()[0]
117 +
118 +
119 +def bgo_key():
120 + bugzrc = os.path.expanduser("~/.bugzrc")
121 + config = ConfigParser()
122 + config.read(bugzrc)
123 + apikey = config['default']['key']
124 + return apikey
125 +
126 +
127 +if __name__ == '__main__':
128 + parser = argparse.ArgumentParser()
129 + parser.add_argument('-b', '--bugs', required=True, nargs='+')
130 + parser.add_argument('-t', '--title', required=True)
131 + args = parser.parse_args()
132 + auth = glsamaker_key()
133 + for bug in args.bugs:
134 + CVETool(auth, 'dobug', [bug])
135 + GLSATool(auth, bgo_key()).new_glsa(args.title, args.bugs)