-
Notifications
You must be signed in to change notification settings - Fork 5
/
yml_utils.py
153 lines (135 loc) · 5.09 KB
/
yml_utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env python
from __future__ import print_function
import re
import sys
import base64
import requests
import datetime
import os
try:
from apikey import APIKEY
except:
APIKEY = os.environ.get("BUGZILLA_API_KEY")
class Advisory:
def __init__(self, bugJSON, advisoryText):
self.id = bugJSON['id']
self.ids = [ bugJSON['id'] ]
self.severity = getSeverity(bugJSON)
advisory_lines = advisoryText.decode("utf-8").split("\n")
self.cve = bugJSON['alias'] if bugJSON['alias'] else ""
self.title = advisory_lines[0].strip()
self.reporter = advisory_lines[1].strip() #cleanUpRealName(bugJSON['creator_details']['real_name'])
self.description = "\n".join(advisory_lines[2:]).strip()
def pprint(self):
print(self.id)
print("\t", self.severity)
print("\t", self.title)
print("\t", self.reporter)
print("\t", self.description)
print("\t")
def getCVE(self):
if self.cve:
return self.cve
return f"MFSA-RESERVE-{datetime.date.today().year}-{self.id}"
def getTitle(self):
if ":" in self.title:
return "'" + self.title + "'"
return self.title
@staticmethod
def is_reference(advisoryText):
advisory_lines = advisoryText.decode("utf-8").split("\n")
if "ref:" in advisory_lines[0]:
return int(advisory_lines[0].replace("ref:", "").strip())
return None
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
def cleanUpRealName(name):
name = re.sub(" \[:[^\]]+\]", "", name)
name = re.sub(" \(:[^\)]+\)", "", name)
name = re.sub(" \(needinfo[^\)]+\)", "", name)
name = re.sub(" \(ni [^\)]+\)", "", name)
return name
def getSeverity(bugJSON):
severity = None
for k in bugJSON['keywords']:
if k in ["sec-critical", "sec-high", "sec-moderate", "sec-low"]:
thisSev = k.replace("sec-", "")
if severity is not None:
severity = getMaxSeverity(severity, thisSev)
else:
severity = thisSev
if severity is None:
raise Exception(str(bugJSON['id']) + " is missing a sec keyword")
return severity
def sortAdvisories(advisories):
for a in advisories:
if a.severity == "critical":
yield a
for a in advisories:
if a.severity == "high":
yield a
for a in advisories:
if a.severity == "moderate":
yield a
for a in advisories:
if a.severity == "low":
yield a
def bugLinkToRest(link):
return link.replace("/buglist.cgi?", "/rest/bug?")
def doBugRequest(link):
r = requests.get(bugLinkToRest(link))
bugs = r.json()
return bugs['bugs']
def getAdvisoryAttachment(bugid):
link = "https://bugzilla.mozilla.org/rest/bug/" + str(bugid) + "/attachment?api_key=" + APIKEY
r = requests.get(link)
try:
attachments = r.json()['bugs'][str(bugid)]
except:
raise Exception("Couldn't parse " + str(bugid) + "'s response for a list of attachments. Response:\n\n" + str(r.text))
advisory = None
for a in attachments:
if a['description'] == "advisory.txt" and not a['is_obsolete']:
if advisory is not None:
raise Exception(str(bugid) + " has two advisory.txt attachments")
advisory = base64.b64decode(a['data'])
if advisory is None:
raise Exception(str(bugid) + " is missing an advisory.txt attachment")
return advisory
def getMaxSeverity(current, this):
if this == "critical":
return "critical"
elif current in ["low", "moderate"] and this == "high":
return "high"
elif current in ["low"] and this == "moderate":
return "moderate"
return current
def sanityCheckBugs(bugs, require_cves=False):
retvalue = True
for b in bugs:
bugid = b['id']
# Check for CVE
if require_cves and not b['alias']:
eprint(bugid, "is missing a CVE identified. Please contact Tom Ritter (cc Dan Veditz) to have one assigned.")
retvalue = False
# Check for severity keywords
try:
getSeverity(b)
except Exception as e:
eprint(bugid, "seems to have some problem with the severity. If you can resolve it, please do, otherwise contact Tom Ritter (and/or Dan Veditz)")
eprint("Exception:")
eprint(e)
retvalue = False
# Check if the bug is fixed or not
if b['status'] != "RESOLVED" and b['status'] != "VERIFIED":
eprint(bugid, "is not marked as fixed, but is marked for this version")
retvalue = False
# Check if the bug has an advisory
try:
getAdvisoryAttachment(bugid)
except Exception as e:
eprint(bugid, "might be missing an advisory attachment. Please create an attachment named advisory.txt as described here: https://wiki.mozilla.org/Security/Firefox/Security_Bug_Life_Cycle/Security_Advisories#Write_the_advisories")
eprint("Exception:")
eprint(e)
retvalue = False
return retvalue