Merge ~ebarretto/ubuntu-cve-tracker:oval-lsn into ubuntu-cve-tracker:master

Proposed by Eduardo Barretto
Status: Merged
Merged at revision: 3cc230c34f98e9fe6f4128380215a95f6d416928
Proposed branch: ~ebarretto/ubuntu-cve-tracker:oval-lsn
Merge into: ubuntu-cve-tracker:master
Diff against target: 411 lines (+178/-30)
4 files modified
scripts/fetch-lsns.py (+81/-0)
scripts/generate-oval (+14/-12)
scripts/oval_lib.py (+78/-16)
test/test_oval_lib_unit.py (+5/-2)
Reviewer Review Type Date Requested Status
Seth Arnold Approve
Alex Murray Approve
Review via email: mp+429162@code.launchpad.net

Description of the change

This PR adds LSNs to USN OVAL generation, as well as a fetch-lsns script.
Therefore an USN OVAL will contain both USNs and LSNs. The LSNs will be on their own definition, and basically it will check if you canonical-livepatch on your system, and if yes, it will check if you have the module version from the LSN loaded in /proc/modules. That way avoiding false positives if you don't have livepatch on your system.
This doesn't affect OCI USN OVAL, which relies on a manifest file and doesn't scan the actual system.

Currently this change is breaking 3 tests under test/ and that's because I changed the reference URL to USNs and LSNs. We had a hardcoded 'USN-' in the URL. To fix it I can either:
1. Change our infrastructure and USN DB to have keys as 'USN-XXXX-Y' instead of just 'XXXX-Y'
2. Do some logic before generating the URL

The 1 change requires more effort and will implicate in changes to our USN DB.

PS: We decided to go with 2. This PR is now ready for review + merge.

To post a comment you must log in.
Revision history for this message
Seth Arnold (seth-arnold) wrote :

Changing the USN DB from XXXX-Y to USN-XXXX-Y sounds really likely to cause problems in places we may not even know exist; can we add the LSNs with keys LSN-XXXX-Y and keep the USNs with XXXX-Y, and simply tolerate the asymmetry?

I know that adds more gross stuff here, but saves us from learning what needs to change in eg landscape and whoever else might be consuming the database.

I didn't spot anything in the code, but this is all pretty foreign to me. (Grabbing only twenty LSNs at a time, from the web server, seems likely to be brittle some day. We may not be able to do any better if this is what the web team has given us.)

Thanks

Revision history for this message
Eduardo Barretto (ebarretto) wrote :

Thanks Seth!
I added a small hack to make the id as USN-XXXX-YY until we address anything in the USN DB itself.

> (Grabbing only twenty LSNs at a time, from the web server, seems likely to be brittle some day. We may not be able to do any better if this is what the web team has given us.)

The idea is to get 20, as this is the default from the search page, more than it makes the request to take a longer time to get an answer, if any at all, as sometimes it just times out. And in the request I make, it is in newest order, which make us only get the latest one and it stops requesting whenever it hits an LSN that is already in the JSON file.

Revision history for this message
Eduardo Barretto (ebarretto) wrote :

It has been 10 days since last update.
Could someone review this?

Revision history for this message
Seth Arnold (seth-arnold) wrote :

Sorry :( my only thought on the newer changes is that it might be nice to put the hack in a function, so when (if?) we ever get to undo it, we only have to do it in one place.

It's only two lines though, maybe it's not a big deal.

Thanks

Revision history for this message
Alex Murray (alexmurray) wrote :

LGTM - minor comment re adding the USN- prefix to USN IDs.

review: Approve
Revision history for this message
Eduardo Barretto (ebarretto) wrote :

Thanks Alex and Seth,
I took both suggestions into consideration and added a prepend_usn_to_id function using regex, making it easier to adjust or remove it whenever we need.
I've also gave +x to the fetch-lsns script.

I would appreciate a check on both last commits just to make sure I didn't break anything.
Thanks!

Revision history for this message
Alex Murray (alexmurray) wrote :

LGTM!

review: Approve
Revision history for this message
Seth Arnold (seth-arnold) wrote :

a988b5f and a495a0c look good to me! I do kinda vaguely wonder how much time python's going to spend compiling that regex over and over again but lets just pretend it's fine for now and get this landed.

Thanks :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/scripts/fetch-lsns.py b/scripts/fetch-lsns.py
0new file mode 1007550new file mode 100755
index 0000000..109a149
--- /dev/null
+++ b/scripts/fetch-lsns.py
@@ -0,0 +1,81 @@
1#!/usr/bin/env python3
2#
3# Author: Eduardo Barretto
4# Copyright (C) 2022- Canonical Ltd.
5#
6# This script is distributed under the terms and conditions of the GNU General
7# Public License, Version 3 or later. See http://www.gnu.org/copyleft/gpl.html
8# for details.
9
10import datetime
11import json
12import requests
13import os
14
15url = "https://ubuntu.com/security/notices.json?order=newest&details=LSN"
16data = json.loads(requests.get(url).text)
17total = data['total_results']
18filename = 'database-lsn.json'
19
20db = {}
21if os.path.exists(filename):
22 with open(filename, 'r') as json_file:
23 try:
24 db = json.load(json_file)
25 print('Reading database-lsn.json')
26 except json.decoder.JSONDecodeError:
27 print('Creating database-lsn.json')
28
29offset = 0
30with open(filename, 'w+') as json_file:
31 while offset < total:
32 data = json.loads(requests.get(url + '&offset=' + str(offset)).text)
33 for notice in data['notices']:
34 lsn_id = notice['id']
35 if lsn_id in db:
36 print('database is up-to-date')
37 offset = total
38 break
39 else:
40 print('importing {}'.format(lsn_id))
41 db[lsn_id] = {}
42 db[lsn_id]['description'] = notice['description']
43 db[lsn_id]['releases'] = {}
44 for release in notice['release_packages']:
45 db[lsn_id]['releases'][release] = {'sources': {},
46 'binaries': {},
47 'allbinaries': {}}
48 for item in notice['release_packages'][release]:
49 # lsn json have two entries for same source
50 # one containing the binary as version and
51 # another with the livepatch module version
52 if not item['is_source']:
53 continue
54 db[lsn_id]['releases'][release]['sources'][item['name']] = {
55 'version': item['version'],
56 'description': item['description']
57 }
58 version = item['version'].replace('.', '_')
59 module_name = "lkp_Ubuntu_" + version.split('-')[0] + \
60 r"[_|\d]+_" + item['name'].split('-')[0] + "_(\d+)"
61 db[lsn_id]['releases'][release]['allbinaries'][item['name']] = {
62 "pocket": "livepatch",
63 "module": module_name,
64 "version": lsn_id.split('-')[1].lstrip('0')
65 }
66 db[lsn_id]['title'] = notice['title']
67 date = datetime.datetime.strptime(notice['published'], "%Y-%m-%dT%H:%M:%S")
68 db[lsn_id]['timestamp'] = datetime.datetime.timestamp(date)
69 db[lsn_id]['summary'] = notice['title']
70 db[lsn_id]['action'] = notice['instructions']
71 db[lsn_id]['is_hidden'] = 'False'
72 db[lsn_id]['cves'] = notice['cves_ids']
73 db[lsn_id]['id'] = notice['id']
74 db[lsn_id]['isummary'] = notice['summary']
75 db[lsn_id]['related_notices'] = []
76 for rn in notice['related_notices']:
77 db[lsn_id]['related_notices'].append(rn['id'])
78
79 offset += 20
80
81 json.dump(db, json_file, indent=4)
diff --git a/scripts/generate-oval b/scripts/generate-oval
index 0b91d9a..ddcd74b 100755
--- a/scripts/generate-oval
+++ b/scripts/generate-oval
@@ -466,7 +466,6 @@ def debug(message):
466 if debug_level > 0:466 if debug_level > 0:
467 sys.stdout.write('\rDEBUG: {0}\n'.format(message))467 sys.stdout.write('\rDEBUG: {0}\n'.format(message))
468468
469
470def progress_bar(current, total, size=20):469def progress_bar(current, total, size=20):
471 """ show a simple progress bar on the CLI """470 """ show a simple progress bar on the CLI """
472 current_percent = float(current) / total471 current_percent = float(current) / total
@@ -478,6 +477,10 @@ def progress_bar(current, total, size=20):
478477
479 sys.stdout.flush()478 sys.stdout.flush()
480479
480def prepend_usn_to_id(usn_database, usn_id):
481 if re.search(r'^[0-9]+-[0-9]$', usn_id):
482 usn_database[usn_id]['id'] = 'USN-' + usn_id
483
481484
482# Class to contain the binary package cache485# Class to contain the binary package cache
483class PackageCache():486class PackageCache():
@@ -634,15 +637,12 @@ class PackageCache():
634# loads usn database.json based given a path to it.637# loads usn database.json based given a path to it.
635# To get the database proceed as: $UCT/scripts/fetch-db database.json.bz2638# To get the database proceed as: $UCT/scripts/fetch-db database.json.bz2
636def get_usn_database(usn_db_dir):639def get_usn_database(usn_db_dir):
637 data = None640 data = {}
638 default_usn_database = os.path.join(usn_db_dir, 'database.json')641 for filename in glob.glob(os.path.join(usn_db_dir, 'database*.json')):
639 if not os.path.exists(default_usn_database):642 with open(filename, 'r') as f:
640 error('{} must exists'.format(default_usn_database))643 data.update(json.load(f))
641644
642 with open(default_usn_database, 'r') as database:645 return data
643 data = json.load(database)
644 return data
645 return None
646646
647# Usage:647# Usage:
648# for a given release only:648# for a given release only:
@@ -693,18 +693,20 @@ def generate_oval_usn(outdir, usn, usn_release, cve_dir, usn_db_dir, ociprefix=N
693693
694 # Generate OVAL USN data694 # Generate OVAL USN data
695 if usn:695 if usn:
696 prepend_usn_to_id(usn_database, usn)
696 for oval in ovals:697 for oval in ovals:
697 oval.generate_usn_oval(usn_database[usn], usn, cve_dir)698 oval.generate_usn_oval(usn_database[usn], usn_database[usn]['id'], cve_dir)
698 else:699 else:
699 for usn in usn_database.keys():700 for usn in usn_database.keys():
701 prepend_usn_to_id(usn_database, usn)
700 for oval in ovals:702 for oval in ovals:
701 oval.generate_usn_oval(usn_database[usn], usn, cve_dir)703 oval.generate_usn_oval(usn_database[usn], usn_database[usn]['id'], cve_dir)
702704
703 for oval in ovals:705 for oval in ovals:
704 oval.write_oval_elements()706 oval.write_oval_elements()
705707
706
707 return True708 return True
708709
710
709if __name__ == '__main__':711if __name__ == '__main__':
710 main()712 main()
diff --git a/scripts/oval_lib.py b/scripts/oval_lib.py
index 95c3856..2d86175 100644
--- a/scripts/oval_lib.py
+++ b/scripts/oval_lib.py
@@ -53,6 +53,12 @@ def _open(fn, mode, encoding='utf-8'):
53 return fd53 return fd
5454
55def prepare_instructions(instruction, cve, product_description, package):55def prepare_instructions(instruction, cve, product_description, package):
56 if "LSN" in cve:
57 instruction = """\n
58To check your kernel type and Livepatch version, enter this command:
59
60canonical-livepatch status"""
61
56 if not instruction:62 if not instruction:
57 instruction = """\n63 instruction = """\n
58Update Instructions:64Update Instructions:
@@ -64,7 +70,9 @@ by updating your system to the following package versions:""".format(cve)
64 for binary in package["binaries"]:70 for binary in package["binaries"]:
65 instruction += """{0} - {1}\n""".format(binary, package["fix-version"])71 instruction += """{0} - {1}\n""".format(binary, package["fix-version"])
6672
67 if "Long Term" in product_description or "Interim" in product_description:73 if "LSN" in cve:
74 instruction += "Livepatch subscription required"
75 elif "Long Term" in product_description or "Interim" in product_description:
68 instruction += "No subscription required"76 instruction += "No subscription required"
69 else:77 else:
70 instruction += product_description78 instruction += product_description
@@ -737,7 +745,7 @@ class OvalGeneratorUSN():
737 'variable')745 'variable')
738 cve_base_url = 'https://ubuntu.com/security/{}'746 cve_base_url = 'https://ubuntu.com/security/{}'
739 mitre_base_url = 'https://cve.mitre.org/cgi-bin/cvename.cgi?name={}'747 mitre_base_url = 'https://cve.mitre.org/cgi-bin/cvename.cgi?name={}'
740 usn_base_url = 'https://ubuntu.com/security/notices/USN-{}'748 usn_base_url = 'https://ubuntu.com/security/notices/{}'
741 lookup_cve_path = ['./active', './retired']749 lookup_cve_path = ['./active', './retired']
742 generator_version = '1'750 generator_version = '1'
743 oval_schema_version = '5.11.1'751 oval_schema_version = '5.11.1'
@@ -746,6 +754,7 @@ class OvalGeneratorUSN():
746 def __init__(self, release_codename, release_name, outdir='./', cve_dir=None, prefix='', oval_format='dpkg'):754 def __init__(self, release_codename, release_name, outdir='./', cve_dir=None, prefix='', oval_format='dpkg'):
747 self.release_codename = release_codename.replace('/', '_')755 self.release_codename = release_codename.replace('/', '_')
748 self.release_name = release_name756 self.release_name = release_name
757 self.pocket = "security"
749 self.product_description = None758 self.product_description = None
750 self.current_oval = None759 self.current_oval = None
751 self.tmpdir = tempfile.mkdtemp(prefix='oval_lib-')760 self.tmpdir = tempfile.mkdtemp(prefix='oval_lib-')
@@ -940,7 +949,7 @@ class OvalGeneratorUSN():
940 'usn_id': usn_object['id'],949 'usn_id': usn_object['id'],
941 'ns': self.ns,950 'ns': self.ns,
942 'title': "{} -- {}".format(usn_object['id'], usn_object['title']),951 'title': "{} -- {}".format(usn_object['id'], usn_object['title']),
943 'plataform': "{}".format(self.release_name),952 'platform': "{}".format(self.release_name),
944 'usn_url': self.usn_base_url.format(usn_object['id']),953 'usn_url': self.usn_base_url.format(usn_object['id']),
945 'description': escape(' '.join((usn_object['description'].strip() + instructions).split('\n'))),954 'description': escape(' '.join((usn_object['description'].strip() + instructions).split('\n'))),
946 'cves_references': cve_references,955 'cves_references': cve_references,
@@ -954,7 +963,12 @@ class OvalGeneratorUSN():
954 criteria = []963 criteria = []
955 kernel = False964 kernel = False
956 for test_ref in test_refs:965 for test_ref in test_refs:
957 if 'kernel' in test_ref and self.oval_format == 'dpkg':966 if self.pocket == 'livepatch' and self.oval_format == 'dpkg':
967 criteria.append('<criteria operator="AND">')
968 criteria.append(' <criterion test_ref="{0}:tst:{1}" comment="{2}" />'.format(self.ns, str(int(test_ref['testref_id']) + 1), self.product_description))
969 criteria.append(' <criterion test_ref="{0}:tst:{1}" comment="{2}" />'.format(self.ns, test_ref['testref_id'], self.product_description))
970 criteria.append('</criteria>')
971 elif 'kernel' in test_ref and self.oval_format == 'dpkg':
958 kernel = True972 kernel = True
959 criteria.append('<criteria operator="AND">')973 criteria.append('<criteria operator="AND">')
960 criteria.append(' <criterion test_ref="{0}:tst:{1}" comment="{2}" />'.format(self.ns, test_ref['testref_id'], self.product_description))974 criteria.append(' <criterion test_ref="{0}:tst:{1}" comment="{2}" />'.format(self.ns, test_ref['testref_id'], self.product_description))
@@ -972,9 +986,9 @@ class OvalGeneratorUSN():
972 <metadata>986 <metadata>
973 <title>{title}</title>987 <title>{title}</title>
974 <affected family="unix">988 <affected family="unix">
975 <platform>{plataform}</platform>989 <platform>{platform}</platform>
976 </affected>990 </affected>
977 <reference source="USN" ref_url="{usn_url}" ref_id="USN-{usn_id}"/>991 <reference source="USN" ref_url="{usn_url}" ref_id="{usn_id}"/>
978 {cves_references}992 {cves_references}
979 <description>{description}</description>993 <description>{description}</description>
980 <advisory from="security@ubuntu.com">994 <advisory from="security@ubuntu.com">
@@ -1015,6 +1029,19 @@ class OvalGeneratorUSN():
1015 <ind:state state_ref="{ns}:ste:{id}"/>1029 <ind:state state_ref="{ns}:ste:{id}"/>
1016 </ind:variable_test>""".format(**mapping)1030 </ind:variable_test>""".format(**mapping)
10171031
1032 elif self.pocket == 'livepatch':
1033 mapping['liv-id'] = str(int(test_ref['testref_id']) + 1)
1034 test = \
1035 """
1036 <unix:file_test id="{ns}:tst:{liv-id}" version="1" check="all" check_existence="all_exist" comment="canonical-livepatch installed">
1037 <unix:object object_ref="{ns}:obj:{liv-id}" />
1038 <unix:state state_ref="{ns}:ste:{liv-id}" />
1039 </unix:file_test>
1040 <ind:textfilecontent54_test id="{ns}:tst:{id}" version="1" check="all" check_existence="all_exist" comment="livepatch testing">
1041 <ind:object object_ref="{ns}:obj:{id}"/>
1042 <ind:state state_ref="{ns}:ste:{id}"/>
1043 </ind:textfilecontent54_test>""".format(**mapping)
1044
1018 else:1045 else:
1019 test = \1046 test = \
1020 """1047 """
@@ -1053,6 +1080,21 @@ class OvalGeneratorUSN():
1053 <ind:var_ref>{ns}:var:{id}</ind:var_ref>1080 <ind:var_ref>{ns}:var:{id}</ind:var_ref>
1054 </ind:variable_object>""".format(**mapping)1081 </ind:variable_object>""".format(**mapping)
10551082
1083 elif self.pocket == "livepatch":
1084 mapping['liv-id'] = str(int(test_ref['testref_id']) + 1)
1085 mapping['module'] = test_ref['pkgs']
1086 _object = \
1087 """
1088 <unix:file_object id="{ns}:obj:{liv-id}" version="1" comment="{product}">
1089 <unix:filepath>/snap/bin/canonical-livepatch</unix:filepath>
1090 </unix:file_object>
1091 <ind:textfilecontent54_object id="{ns}:obj:{id}" version="1" comment="{product}">
1092 <ind:filepath datatype="string">/proc/modules</ind:filepath>
1093 <!-- <ind:pattern operation="pattern match">^{module}\s.*$</ind:pattern> -->
1094 <ind:pattern operation="pattern match" var_ref="{ns}:var:{id}" var_check="at least one" />
1095 <ind:instance datatype="int">1</ind:instance>
1096 </ind:textfilecontent54_object>""".format(**mapping)
1097
1056 else:1098 else:
1057 _object = \1099 _object = \
1058 """1100 """
@@ -1100,6 +1142,18 @@ class OvalGeneratorUSN():
1100 <ind:value operation="greater than" datatype="debian_evr_string" var_ref="{ns}:var:{varid}" var_check="at least one" />1142 <ind:value operation="greater than" datatype="debian_evr_string" var_ref="{ns}:var:{varid}" var_check="at least one" />
1101 </ind:variable_state>""".format(**mapping)1143 </ind:variable_state>""".format(**mapping)
11021144
1145 elif self.pocket == "livepatch":
1146 mapping['liv-id'] = str(int(test_ref['testref_id']) + 1)
1147 mapping['bversion'] = binary_version
1148 state = \
1149 """
1150 <unix:file_state id="{ns}:ste:{liv-id}" version="1">
1151 <unix:size datatype="int" operation="greater than">0</unix:size>
1152 </unix:file_state>
1153 <ind:textfilecontent54_state id="{ns}:ste:{id}" version="1">
1154 <ind:subexpression datatype="int" operation="less than">{bversion}</ind:subexpression>
1155 </ind:textfilecontent54_state>""".format(**mapping)
1156
1103 else:1157 else:
1104 if binary_version.find(':') != -1:1158 if binary_version.find(':') != -1:
1105 mapping['bversion'] = binary_version1159 mapping['bversion'] = binary_version
@@ -1250,7 +1304,12 @@ class OvalGeneratorUSN():
1250 def get_version_from_binaries(self, usn_allbinaries):1304 def get_version_from_binaries(self, usn_allbinaries):
1251 version_map = collections.defaultdict(list)1305 version_map = collections.defaultdict(list)
1252 for k, v in usn_allbinaries.items():1306 for k, v in usn_allbinaries.items():
1253 version_map[v['version']].append(k)1307 if 'module' in v:
1308 self.pocket = 'livepatch'
1309 version_map[v['version']].append(v['module'])
1310 else:
1311 self.pocket = 'security'
1312 version_map[v['version']].append(k)
12541313
1255 return version_map1314 return version_map
12561315
@@ -1289,20 +1348,19 @@ class OvalGeneratorUSN():
1289 return usn_allbinaries1348 return usn_allbinaries
12901349
1291 def update_release_name_from_pocket_or_stamp(self, binaries, stamp):1350 def update_release_name_from_pocket_or_stamp(self, binaries, stamp):
1292 pocket = "security"
1293 for b in binaries:1351 for b in binaries:
1294 try:1352 try:
1295 pocket = binaries[b]['pocket']1353 self.pocket = binaries[b]['pocket']
1296 break1354 break
1297 except KeyError:1355 except KeyError:
1298 # trusty usns don't have pocket, so try to check on timestamp1356 # trusty usns don't have pocket, so try to check on timestamp
1299 if self.release_codename == 'trusty' and stamp >= release_stamp('esm/trusty'):1357 if self.release_codename == 'trusty' and stamp >= release_stamp('esm/trusty'):
1300 pocket = 'esm'1358 self.pocket = 'esm'
1301 else:1359 else:
1302 pocket = 'security'1360 self.pocket = 'security'
1303 break1361 break
13041362
1305 if pocket in ['security', 'updates']:1363 if self.pocket in ['security', 'updates', 'livepatch']:
1306 self.release_name = release_name(self.release_codename)1364 self.release_name = release_name(self.release_codename)
1307 self.product_description = get_subproject_description(self.release_codename)1365 self.product_description = get_subproject_description(self.release_codename)
1308 else:1366 else:
@@ -1311,8 +1369,8 @@ class OvalGeneratorUSN():
1311 self.release_name = release_name('esm/' + self.release_codename)1369 self.release_name = release_name('esm/' + self.release_codename)
1312 self.product_description = get_subproject_description('esm/' + self.release_codename)1370 self.product_description = get_subproject_description('esm/' + self.release_codename)
1313 else:1371 else:
1314 self.release_name = release_name(pocket + '/' + self.release_codename)1372 self.release_name = release_name(self.pocket + '/' + self.release_codename)
1315 self.product_description = get_subproject_description(pocket + '/' + self.release_codename)1373 self.product_description = get_subproject_description(self.pocket + '/' + self.release_codename)
13161374
1317 def generate_usn_oval(self, usn_object, usn_number, cve_dir):1375 def generate_usn_oval(self, usn_object, usn_number, cve_dir):
1318 if self.release_codename not in usn_object['releases'].keys():1376 if self.release_codename not in usn_object['releases'].keys():
@@ -1327,6 +1385,11 @@ class OvalGeneratorUSN():
13271385
1328 binary_versions = self.get_version_from_binaries(usn_allbinaries)1386 binary_versions = self.get_version_from_binaries(usn_allbinaries)
13291387
1388 # OCI OVAL does not check running system, therefore it can
1389 # skip LSNs
1390 if self.oval_format == "oci" and self.pocket == 'livepatch':
1391 return
1392
1330 # group binaries with same version (most likely from same source)1393 # group binaries with same version (most likely from same source)
1331 # and create a test_ref for the group to be used when creating1394 # and create a test_ref for the group to be used when creating
1332 # the oval def, test, state and var.1395 # the oval def, test, state and var.
@@ -1343,12 +1406,11 @@ class OvalGeneratorUSN():
1343 # prepare update instructions1406 # prepare update instructions
1344 pkg['binaries'] = binary_versions[key]1407 pkg['binaries'] = binary_versions[key]
1345 pkg['fix-version'] = key1408 pkg['fix-version'] = key
1346 instructions = prepare_instructions(instructions, "USN-" + usn_number, self.product_description, pkg)1409 instructions = prepare_instructions(instructions, usn_object['id'], self.product_description, pkg)
13471410
1348 # Create the oval objects1411 # Create the oval objects
1349 # Only need one definition, but if multiple versions of binary pkgs,1412 # Only need one definition, but if multiple versions of binary pkgs,
1350 # then may need several test, object, state and var1413 # then may need several test, object, state and var
1351
1352 usn_def = self.create_usn_definition(usn_object, usn_number, id_base, test_refs, cve_dir, instructions)1414 usn_def = self.create_usn_definition(usn_object, usn_number, id_base, test_refs, cve_dir, instructions)
1353 self.oval_structure['definition'].write(usn_def)1415 self.oval_structure['definition'].write(usn_def)
13541416
diff --git a/test/test_oval_lib_unit.py b/test/test_oval_lib_unit.py
index c99a41b..f603210 100644
--- a/test/test_oval_lib_unit.py
+++ b/test/test_oval_lib_unit.py
@@ -52,6 +52,8 @@ class TestOvalLibUnit:
52 usn_mock = "4388-1"52 usn_mock = "4388-1"
53 id_base_mock = 4388100000053 id_base_mock = 43881000000
54 test_cve_file = "CVE-TEST"54 test_cve_file = "CVE-TEST"
55 usn_object_mock['id'] = "USN-" + usn_mock
56
5557
56 bin_dict_mock = collections.defaultdict(list)58 bin_dict_mock = collections.defaultdict(list)
57 bin_dict_mock = {'5.0.0.1042.27': ['linux-image-gke-5.0'], '5.0.0-1059.64':59 bin_dict_mock = {'5.0.0.1042.27': ['linux-image-gke-5.0'], '5.0.0-1059.64':
@@ -83,7 +85,7 @@ class TestOvalLibUnit:
83 definition_mock = """85 definition_mock = """
84 <definition id="oval:com.ubuntu.bionic:def:43881000000" version="1" class="patch">86 <definition id="oval:com.ubuntu.bionic:def:43881000000" version="1" class="patch">
85 <metadata>87 <metadata>
86 <title>4388-1 -- Linux kernel vulnerabilities</title>88 <title>USN-4388-1 -- Linux kernel vulnerabilities</title>
87 <affected family="unix">89 <affected family="unix">
88 <platform>Ubuntu 18.04 LTS</platform>90 <platform>Ubuntu 18.04 LTS</platform>
89 </affected>91 </affected>
@@ -276,7 +278,7 @@ class TestOvalLibUnit:
276 invalid_priority_ret = """278 invalid_priority_ret = """
277 <definition id="oval:com.ubuntu.bionic:def:43881000000" version="1" class="patch">279 <definition id="oval:com.ubuntu.bionic:def:43881000000" version="1" class="patch">
278 <metadata>280 <metadata>
279 <title>4388-1 -- Linux kernel vulnerabilities</title>281 <title>USN-4388-1 -- Linux kernel vulnerabilities</title>
280 <affected family="unix">282 <affected family="unix">
281 <platform>Ubuntu 18.04 LTS</platform>283 <platform>Ubuntu 18.04 LTS</platform>
282 </affected>284 </affected>
@@ -497,6 +499,7 @@ No subscription required"""
497 create_bug_ref_mock.return_value = self.url_ref_mock499 create_bug_ref_mock.return_value = self.url_ref_mock
498 get_usn_severity_mock.return_value = self.avg_severity_mock500 get_usn_severity_mock.return_value = self.avg_severity_mock
499501
502 print(self.usn_object_mock)
500 definition_ret = oval_lib.OvalGeneratorUSN.create_usn_definition(503 definition_ret = oval_lib.OvalGeneratorUSN.create_usn_definition(
501 self.oval_gen_mock, self.usn_object_mock, self.usn_mock,504 self.oval_gen_mock, self.usn_object_mock, self.usn_mock,
502 self.id_base_mock, self.test_refs_mock, rel_test_path,505 self.id_base_mock, self.test_refs_mock, rel_test_path,

Subscribers

People subscribed via source and target branches