Merge ~alexmurray/ubuntu-cve-tracker:python3-12-deprecation-fixups into ubuntu-cve-tracker:master

Proposed by Alex Murray
Status: Merged
Merge reported by: Steve Beattie
Merged at revision: b50dcd7ffc132ad87b39990ead6d05694faead0d
Proposed branch: ~alexmurray/ubuntu-cve-tracker:python3-12-deprecation-fixups
Merge into: ubuntu-cve-tracker:master
Diff against target: 249 lines (+29/-30)
3 files modified
scripts/active_edit (+2/-2)
scripts/check-cves (+9/-9)
scripts/oval_lib.py (+18/-19)
Reviewer Review Type Date Requested Status
Steve Beattie Approve
Review via email: mp+461222@code.launchpad.net

Description of the change

I suspect we have other scripts that will need similar fixes so will try and capture as many as I can here.

To post a comment you must log in.
8683bc4... by Alex Murray

scripts/oval_lib.py: update for Python 3.12 deprecations

Signed-off-by: Alex Murray <email address hidden>

b50dcd7... by Alex Murray

scripts/active_edit: update for Python 3.12 deprecations

Signed-off-by: Alex Murray <email address hidden>

Revision history for this message
Steve Beattie (sbeattie) wrote :

For the datetime changes,

- public_date = datetime.datetime.utcnow().strftime("%Y-%m-%d")
+ public_date = datetime.datetime.now(datetime.UTC).strftime("%Y-%m-%d")

datetime.UTC was introduced in python 3.11 (so ubuntu 23.10, mantic), so jammy and older won't have this. We'll want to use datetime.timezone.utc instead; while most people should be running mantic or newer, we do have team members and systems running older releases than that. Given that datetime.datetime.now(datetime.timezone.utc) is a bit unwieldy, we could do something like:

  from datetime import datetime, timezone
  public_date = datetime.now(timezone.utc).strftime("%Y-%m-%d")

Thanks.

Revision history for this message
Steve Beattie (sbeattie) wrote :
Revision history for this message
Steve Beattie (sbeattie) wrote :

I went ahead and fixed a bunch more and did the conversion to use datetime.timezone.utc instead of datetime.UTC, and then merged everything in https://git.launchpad.net/ubuntu-cve-tracker/commit/?id=92593eaa749bd40f80856e717c2186064f2993f5

Unfortunately, I ended up needing to rebase on top of master due to a merge conflict, so launchpad is not autoclosing this merge request.

review: Approve
Revision history for this message
Steve Beattie (sbeattie) wrote :

(I didn't squash the commits, all the individual ones are still there, that's just how cgit shows the merge request.)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/scripts/active_edit b/scripts/active_edit
index dadaf35..b02c28e 100755
--- a/scripts/active_edit
+++ b/scripts/active_edit
@@ -99,7 +99,7 @@ def fetch_kernel_fixes(url):
99 if re.match("commit [0-9a-f]{40} upstream.", line):99 if re.match("commit [0-9a-f]{40} upstream.", line):
100 # This is an LTS backport, skip it100 # This is an LTS backport, skip it
101 return []101 return []
102 if re.match("\[ Upstream commit [0-9a-f]{40} \]", line):102 if re.match(r"\[ Upstream commit [0-9a-f]{40} \]", line):
103 # This is an LTS backport, skip it103 # This is an LTS backport, skip it
104 return []104 return []
105 if not commit_hash and line.startswith("From "):105 if not commit_hash and line.startswith("From "):
@@ -316,7 +316,7 @@ def create_or_update_cve(cve, packages, priority=None, bug_urls=None,
316 # Set a default public date only when the CVE isn't being added to the316 # Set a default public date only when the CVE isn't being added to the
317 # embargoed tree317 # embargoed tree
318 if not embargoed and not public_date:318 if not embargoed and not public_date:
319 public_date = datetime.datetime.utcnow().strftime("%Y-%m-%d")319 public_date = datetime.datetime.now(datetime.UTC).strftime("%Y-%m-%d")
320320
321 if update:321 if update:
322 mode = "a"322 mode = "a"
diff --git a/scripts/check-cves b/scripts/check-cves
index 322f38b..0865e4a 100755
--- a/scripts/check-cves
+++ b/scripts/check-cves
@@ -183,7 +183,7 @@ def convert_to_nvd(cves=[], desc=""):
183 nvd = {"CVE_data_type": "CVE",183 nvd = {"CVE_data_type": "CVE",
184 "CVE_data_format": "MITRE",184 "CVE_data_format": "MITRE",
185 "CVE_data_version": "4.0",185 "CVE_data_version": "4.0",
186 "CVE_data_timestamp": datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%MZ"),186 "CVE_data_timestamp": datetime.datetime.now(datetime.UTC).strftime("%Y-%m-%dT%H:%MZ"),
187 "CVE_Items": []}187 "CVE_Items": []}
188188
189 keys = list(cves.keys())189 keys = list(cves.keys())
@@ -474,8 +474,8 @@ def read_locate_cves_output(f):
474 subject += " " + s.strip()474 subject += " " + s.strip()
475475
476 # Try to fake up some urls476 # Try to fake up some urls
477 rhsa_regex = '\[RHSA-\d\d\d\d:\d+-\d+\]'477 rhsa_regex = r'\[RHSA-\d\d\d\d:\d+-\d+\]'
478 osssec_regex = '\[oss-security\]'478 osssec_regex = r'\[oss-security\]'
479 if re.search(r'' + rhsa_regex, subject):479 if re.search(r'' + rhsa_regex, subject):
480 rhsa = re.sub(r'.*(%s).*' % rhsa_regex, r'\1', subject).strip('[|]')480 rhsa = re.sub(r'.*(%s).*' % rhsa_regex, r'\1', subject).strip('[|]')
481 url = "https://rhn.redhat.com/errata/%s-%s.html" % (rhsa.split(':')[0], rhsa.split(':')[1].split('-')[0])481 url = "https://rhn.redhat.com/errata/%s-%s.html" % (rhsa.split(':')[0], rhsa.split(':')[1].split('-')[0])
@@ -651,7 +651,7 @@ class CVEHandler(xml.sax.handler.ContentHandler):
651 raise KeyError("NVD JSON in '%s' seems invalid" % fp.name)651 raise KeyError("NVD JSON in '%s' seems invalid" % fp.name)
652652
653 metadata = cve["CVE_data_meta"]653 metadata = cve["CVE_data_meta"]
654 if not re.match('^CVE-\d{4}-\d{4,}$', metadata["ID"]):654 if not re.match(r'^CVE-\d{4}-\d{4,}$', metadata["ID"]):
655 print("Ignoring invalid CVE with ID '%s'" % metadata["ID"])655 print("Ignoring invalid CVE with ID '%s'" % metadata["ID"])
656 return656 return
657 self.curr_cve = metadata["ID"]657 self.curr_cve = metadata["ID"]
@@ -850,8 +850,8 @@ class CVEHandler(xml.sax.handler.ContentHandler):
850 if suggestion.startswith('a ') and len(phrases) > 1:850 if suggestion.startswith('a ') and len(phrases) > 1:
851 suggestion = phrases[-2]851 suggestion = phrases[-2]
852852
853 version_preps = '(\s+(before|through|prior to|versions?|[<>]=?))+\s*'853 version_preps = r'(\s+(before|through|prior to|versions?|[<>]=?))+\s*'
854 version_regex = '\s+([a-zA-Z\._\-]*[0-9]+[a-zA-Z\._\-]*)+'854 version_regex = r'\s+([a-zA-Z\._\-]*[0-9]+[a-zA-Z\._\-]*)+'
855 # prefer 'Apple iOS before <version>' or 'Apple Mac OS X through855 # prefer 'Apple iOS before <version>' or 'Apple Mac OS X through
856 # <version' in the last phrase over other suggestions856 # <version' in the last phrase over other suggestions
857 if not re.search(r'' + version_preps + version_regex, suggestion):857 if not re.search(r'' + version_preps + version_regex, suggestion):
@@ -1405,7 +1405,7 @@ class CVEHandler(xml.sax.handler.ContentHandler):
1405 cmd = ['./scripts/active_edit', '-c', cve, '--yes',1405 cmd = ['./scripts/active_edit', '-c', cve, '--yes',
1406 '--public',1406 '--public',
1407 # set date as now1407 # set date as now
1408 datetime.datetime.utcnow().strftime("%Y-%m-%d")]1408 datetime.datetime.now(datetime.UTC).strftime("%Y-%m-%d")]
1409 if breakfix:1409 if breakfix:
1410 cmd.extend(['-k'])1410 cmd.extend(['-k'])
1411 for url in ref_urls:1411 for url in ref_urls:
@@ -1750,7 +1750,7 @@ def refresh_cves(cve_refresh_list, full_refresh=True):
1750 debug("updated pubdate for %s" % (cvefile))1750 debug("updated pubdate for %s" % (cvefile))
17511751
1752 # Add CVE Reference, if it's missing1752 # Add CVE Reference, if it's missing
1753 if 'References' in data and re.match('^CVE-\d+-\d+$', cve):1753 if 'References' in data and re.match(r'^CVE-\d+-\d+$', cve):
1754 mitre_ref = "https://cve.mitre.org/cgi-bin/cvename.cgi?name=" + cve1754 mitre_ref = "https://cve.mitre.org/cgi-bin/cvename.cgi?name=" + cve
1755 if mitre_ref not in data['References']:1755 if mitre_ref not in data['References']:
1756 cve_lib.add_reference(cvefile, mitre_ref)1756 cve_lib.add_reference(cvefile, mitre_ref)
@@ -1808,7 +1808,7 @@ for cve in new_cves:
1808 # pick half as often, if year is 2 years ago we want to pick1808 # pick half as often, if year is 2 years ago we want to pick
1809 # 1/4 as often etc - so do 1/2^(diff)1809 # 1/4 as often etc - so do 1/2^(diff)
1810 year = int(re.split('-', cve)[1])1810 year = int(re.split('-', cve)[1])
1811 now = datetime.datetime.utcnow().year1811 now = datetime.datetime.now(datetime.UTC).year
1812 prob = 1.0 / math.pow(2, now - year)1812 prob = 1.0 / math.pow(2, now - year)
1813 rand = random.random()1813 rand = random.random()
1814 if rand > prob:1814 if rand > prob:
diff --git a/scripts/oval_lib.py b/scripts/oval_lib.py
1815old mode 1006441815old mode 100644
1816new mode 1007551816new mode 100755
index d60c6dc..ace0cb3
--- a/scripts/oval_lib.py
+++ b/scripts/oval_lib.py
@@ -29,7 +29,6 @@ import tempfile
29import collections29import collections
30import glob30import glob
31import xml.etree.cElementTree as etree31import xml.etree.cElementTree as etree
32import json
33from xml.dom import minidom32from xml.dom import minidom
34from typing import Tuple # Needed because of Python < 3.9 and to also support < 3.733from typing import Tuple # Needed because of Python < 3.9 and to also support < 3.7
3534
@@ -105,15 +104,15 @@ def is_kernel_binaries(binaries):
105"""104"""
106def process_kernel_binaries(binaries, oval_format):105def process_kernel_binaries(binaries, oval_format):
107 packages = ' '.join(binaries)106 packages = ' '.join(binaries)
108 parts = re.findall('linux-image-[a-z]*-?([\d|\.]+-)\d+(-[\w|-]+)', packages)107 parts = re.findall(r'linux-image-[a-z]*-?([\d|\.]+-)\d+(-[\w|-]+)', packages)
109 if parts:108 if parts:
110 values = set(map(lambda x: x[0], parts))109 values = set(map(lambda x: x[0], parts))
111 version = ''.join(values)110 version = ''.join(values)
112 values = sorted(set(map(lambda x: x[1], parts)))111 values = sorted(set(map(lambda x: x[1], parts)))
113 flavours = '|'.join(values)112 flavours = '|'.join(values)
114 regex = version + '\d+(' + flavours + ')'113 regex = version + r'\d+(' + flavours + ')'
115 if oval_format == 'oci':114 if oval_format == 'oci':
116 regex = 'linux-image-(?:unsigned-)?' + version + '\d+(?:' + flavours + ')'115 regex = 'linux-image-(?:unsigned-)?' + version + r'\d+(?:' + flavours + ')'
117 return regex116 return regex
118117
119 return None118 return None
@@ -312,7 +311,7 @@ class CVE:
312 for url in info['References'].split('\n'):311 for url in info['References'].split('\n'):
313 if 'https://ubuntu.com/security/notices/USN-' in url:312 if 'https://ubuntu.com/security/notices/USN-' in url:
314 self.usns.append(url[40:])313 self.usns.append(url[40:])
315 elif re.match("https?:\/\/(bugs\.)?launchpad\.net\/(.*\/\+bug|bugs)\/\d+", url):314 elif re.match(r"https?:\/\/(bugs\.)?launchpad\.net\/(.*\/\+bug|bugs)\/\d+", url):
316 self.bugs.append(url)315 self.bugs.append(url)
317 elif url:316 elif url:
318 self.references.append(url)317 self.references.append(url)
@@ -711,7 +710,7 @@ class OvalGenerator:
711 instance = etree.SubElement(object, "ind-def:instance",attrib={"datatype": "int"})710 instance = etree.SubElement(object, "ind-def:instance",attrib={"datatype": "int"})
712711
713 filepath.text = "/etc/lsb-release"712 filepath.text = "/etc/lsb-release"
714 pattern.text = "^[\s\S]*DISTRIB_CODENAME=([a-z]+)$"713 pattern.text = r"^[\s\S]*DISTRIB_CODENAME=([a-z]+)$"
715 instance.text = "1"714 instance.text = "1"
716 else:715 else:
717 family_object = etree.Element("")716 family_object = etree.Element("")
@@ -1034,7 +1033,7 @@ class OvalGenerator:
10341033
1035 final_binaries = []1034 final_binaries = []
1036 if self.oval_format == 'oci':1035 if self.oval_format == 'oci':
1037 variable_values = '(?::\w+|)\s+(.*)$'1036 variable_values = r'(?::\w+|)\s+(.*)$'
1038 for binary in binaries:1037 for binary in binaries:
1039 final_binaries.append(f'^{binary}{variable_values}')1038 final_binaries.append(f'^{binary}{variable_values}')
1040 else:1039 else:
@@ -1060,9 +1059,9 @@ class OvalGenerator:
1060 if self.oval_format == 'oci':1059 if self.oval_format == 'oci':
1061 if package.is_kernel_pkg:1060 if package.is_kernel_pkg:
1062 regex = process_kernel_binaries(binaries, 'oci')1061 regex = process_kernel_binaries(binaries, 'oci')
1063 final_binaries = [f'^{regex}(?::\w+|)\s+(.*)$']1062 final_binaries = [rf'^{regex}(?::\w+|)\s+(.*)$']
1064 else:1063 else:
1065 variable_values = '(?::\w+|)\s+(.*)$'1064 variable_values = r'(?::\w+|)\s+(.*)$'
10661065
1067 final_binaries = []1066 final_binaries = []
1068 for binary in binaries:1067 for binary in binaries:
@@ -1098,7 +1097,7 @@ class OvalGenerator:
1098 concat = etree.SubElement(var, "concat")1097 concat = etree.SubElement(var, "concat")
1099 component = etree.SubElement(concat, "literal_component")1098 component = etree.SubElement(concat, "literal_component")
1100 regex = etree.SubElement(concat, "regex_capture", attrib={1099 regex = etree.SubElement(concat, "regex_capture", attrib={
1101 "pattern": "^([\d|\.]+-\d+)[-|\w]+$"1100 "pattern": r"^([\d|\.]+-\d+)[-|\w]+$"
1102 })1101 })
11031102
1104 etree.SubElement(regex, "object_component", attrib={1103 etree.SubElement(regex, "object_component", attrib={
@@ -1171,7 +1170,7 @@ class OvalGenerator:
1171 return object1170 return object
11721171
1173 def _generate_state_kernel_element(self, comment, id, version) -> None:1172 def _generate_state_kernel_element(self, comment, id, version) -> None:
1174 patched = re.search('([\d|\.]+-\d+)[\.|\d]+', version)1173 patched = re.search(r'([\d|\.]+-\d+)[\.|\d]+', version)
1175 if patched:1174 if patched:
1176 patched = patched.group(1)1175 patched = patched.group(1)
1177 else:1176 else:
@@ -1285,9 +1284,9 @@ class OvalGenerator:
1285 if self.oval_format == 'oci':1284 if self.oval_format == 'oci':
1286 if package.is_kernel_pkg:1285 if package.is_kernel_pkg:
1287 regex = process_kernel_binaries(binaries, 'oci')1286 regex = process_kernel_binaries(binaries, 'oci')
1288 final_binaries = [f'^{regex}(?::\w+|)\s+(.*)$']1287 final_binaries = [rf'^{regex}(?::\w+|)\s+(.*)$']
1289 else:1288 else:
1290 variable_values = '(?::\w+|)\s+(.*)$'1289 variable_values = r'(?::\w+|)\s+(.*)$'
12911290
1292 final_binaries = []1291 final_binaries = []
1293 for binary in binaries:1292 for binary in binaries:
@@ -2065,7 +2064,7 @@ class OvalGeneratorUSN():
2065 def create_release_object(self):2064 def create_release_object(self):
2066 if self.oval_format == 'dpkg':2065 if self.oval_format == 'dpkg':
2067 _object =\2066 _object =\
2068 f"""2067 rf"""
2069 <ind:family_object id="{self.ns}:obj:{self.id}" version="1" comment="The singleton family object."/>2068 <ind:family_object id="{self.ns}:obj:{self.id}" version="1" comment="The singleton family object."/>
2070 <ind:textfilecontent54_object id="{self.ns}:obj:{self.id+1}" version="1">2069 <ind:textfilecontent54_object id="{self.ns}:obj:{self.id+1}" version="1">
2071 <ind:filepath datatype="string">/etc/lsb-release</ind:filepath>2070 <ind:filepath datatype="string">/etc/lsb-release</ind:filepath>
@@ -2099,7 +2098,7 @@ class OvalGeneratorUSN():
2099 bugs = ""2098 bugs = ""
21002099
2101 for url in urls:2100 for url in urls:
2102 is_bug = re.match("https?:\/\/(bugs\.)?launchpad\.net\/(.*\/\+bug|bugs)\/\d+", url)2101 is_bug = re.match(r"https?:\/\/(bugs\.)?launchpad\.net\/(.*\/\+bug|bugs)\/\d+", url)
21032102
2104 if is_bug:2103 if is_bug:
2105 bug_urls.append(url)2104 bug_urls.append(url)
@@ -2373,7 +2372,7 @@ class OvalGeneratorUSN():
23732372
2374 elif 'kernelobj' in test_ref:2373 elif 'kernelobj' in test_ref:
2375 binary_version = test_ref['version']2374 binary_version = test_ref['version']
2376 binary_version = re.search('([\d|\.]+-\d+)[\.|\d]+', binary_version)2375 binary_version = re.search(r'([\d|\.]+-\d+)[\.|\d]+', binary_version)
2377 mapping['bversion'] = "0:" + binary_version.group(1)2376 mapping['bversion'] = "0:" + binary_version.group(1)
23782377
2379 state = \2378 state = \
@@ -2431,7 +2430,7 @@ class OvalGeneratorUSN():
2431 if self.oval_format == 'dpkg':2430 if self.oval_format == 'dpkg':
2432 if 'kernel' in test_ref:2431 if 'kernel' in test_ref:
2433 variable = \2432 variable = \
2434 """2433 r"""
2435 <local_variable id="{ns}:var:{id}" datatype="debian_evr_string" version="1" comment="kernel version in evr format">2434 <local_variable id="{ns}:var:{id}" datatype="debian_evr_string" version="1" comment="kernel version in evr format">
2436 <concat>2435 <concat>
2437 <literal_component>0:</literal_component>2436 <literal_component>0:</literal_component>
@@ -2453,7 +2452,7 @@ class OvalGeneratorUSN():
2453 else:2452 else:
2454 for binary in binaries_list:2453 for binary in binaries_list:
2455 values += \2454 values += \
2456 """<value>^{}(?::\w+|)\s+(.*)$</value>2455 r"""<value>^{}(?::\w+|)\s+(.*)$</value>
2457 """.format(binary)2456 """.format(binary)
24582457
2459 mapping['values'] = values.strip()2458 mapping['values'] = values.strip()
@@ -2504,7 +2503,7 @@ class OvalGeneratorUSN():
2504 urls = []2503 urls = []
2505 for cve in cves:2504 for cve in cves:
2506 # Takes urls from the list2505 # Takes urls from the list
2507 is_url = re.match('(www|http:|https:)+[^\s]+[\w]', cve)2506 is_url = re.match(r'(www|http:|https:)+[^\s]+[\w]', cve)
25082507
2509 if is_url:2508 if is_url:
2510 urls.append(cve)2509 urls.append(cve)

Subscribers

People subscribed via source and target branches