blob: d0b221370398906bad780ce5429d7231008d56d8 [file] [log] [blame]
Andrew Geisslerd5838332022-05-27 11:33:10 -05001import json
2import os
Andrew Geisslerd1e89492021-02-12 15:35:20 -06003from oeqa.selftest.case import OESelftestTestCase
Andrew Geisslerd5838332022-05-27 11:33:10 -05004from oeqa.utils.commands import bitbake, get_bb_vars
Andrew Geisslerd1e89492021-02-12 15:35:20 -06005
6class CVECheck(OESelftestTestCase):
7
8 def test_version_compare(self):
Andrew Geisslerd5838332022-05-27 11:33:10 -05009 from oe.cve_check import Version
10
Andrew Geisslerd1e89492021-02-12 15:35:20 -060011 result = Version("100") > Version("99")
12 self.assertTrue( result, msg="Failed to compare version '100' > '99'")
13 result = Version("2.3.1") > Version("2.2.3")
14 self.assertTrue( result, msg="Failed to compare version '2.3.1' > '2.2.3'")
15 result = Version("2021-01-21") > Version("2020-12-25")
16 self.assertTrue( result, msg="Failed to compare version '2021-01-21' > '2020-12-25'")
17 result = Version("1.2-20200910") < Version("1.2-20200920")
18 self.assertTrue( result, msg="Failed to compare version '1.2-20200910' < '1.2-20200920'")
19
20 result = Version("1.0") >= Version("1.0beta")
21 self.assertTrue( result, msg="Failed to compare version '1.0' >= '1.0beta'")
22 result = Version("1.0-rc2") > Version("1.0-rc1")
23 self.assertTrue( result, msg="Failed to compare version '1.0-rc2' > '1.0-rc1'")
24 result = Version("1.0.alpha1") < Version("1.0")
25 self.assertTrue( result, msg="Failed to compare version '1.0.alpha1' < '1.0'")
26 result = Version("1.0_dev") <= Version("1.0")
27 self.assertTrue( result, msg="Failed to compare version '1.0_dev' <= '1.0'")
28
29 # ignore "p1" and "p2", so these should be equal
30 result = Version("1.0p2") == Version("1.0p1")
31 self.assertTrue( result ,msg="Failed to compare version '1.0p2' to '1.0p1'")
32 # ignore the "b" and "r"
33 result = Version("1.0b") == Version("1.0r")
34 self.assertTrue( result ,msg="Failed to compare version '1.0b' to '1.0r'")
35
36 # consider the trailing alphabet as patched level when comparing
37 result = Version("1.0b","alphabetical") < Version("1.0r","alphabetical")
38 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' < '1.0r'")
39 result = Version("1.0b","alphabetical") > Version("1.0","alphabetical")
40 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' > '1.0'")
Andrew Geissler95ac1b82021-03-31 14:34:31 -050041
42 # consider the trailing "p" and "patch" as patched released when comparing
43 result = Version("1.0","patch") < Version("1.0p1","patch")
44 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0' < '1.0p1'")
45 result = Version("1.0p2","patch") > Version("1.0p1","patch")
46 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0p2' > '1.0p1'")
47 result = Version("1.0_patch2","patch") < Version("1.0_patch3","patch")
48 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0_patch2' < '1.0_patch3'")
Andrew Geisslerd5838332022-05-27 11:33:10 -050049
50
51 def test_recipe_report_json(self):
52 config = """
53INHERIT += "cve-check"
54CVE_CHECK_FORMAT_JSON = "1"
55"""
56 self.write_config(config)
57
58 vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
59 summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
60 recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "m4-native_cve.json")
61
62 try:
63 os.remove(summary_json)
64 os.remove(recipe_json)
65 except FileNotFoundError:
66 pass
67
68 bitbake("m4-native -c cve_check")
69
70 def check_m4_json(filename):
71 with open(filename) as f:
72 report = json.load(f)
73 self.assertEqual(report["version"], "1")
74 self.assertEqual(len(report["package"]), 1)
75 package = report["package"][0]
76 self.assertEqual(package["name"], "m4-native")
77 found_cves = { issue["id"]: issue["status"] for issue in package["issue"]}
78 self.assertIn("CVE-2008-1687", found_cves)
79 self.assertEqual(found_cves["CVE-2008-1687"], "Patched")
80
81 self.assertExists(summary_json)
82 check_m4_json(summary_json)
83 self.assertExists(recipe_json)
84 check_m4_json(recipe_json)
85
86
87 def test_image_json(self):
88 config = """
89INHERIT += "cve-check"
90CVE_CHECK_FORMAT_JSON = "1"
91"""
92 self.write_config(config)
93
94 vars = get_bb_vars(["CVE_CHECK_DIR", "CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
95 report_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
96 print(report_json)
97 try:
98 os.remove(report_json)
99 except FileNotFoundError:
100 pass
101
102 bitbake("core-image-minimal-initramfs")
103 self.assertExists(report_json)
104
105 # Check that the summary report lists at least one package
106 with open(report_json) as f:
107 report = json.load(f)
108 self.assertEqual(report["version"], "1")
109 self.assertGreater(len(report["package"]), 1)
110
111 # Check that a random recipe wrote a recipe report to deploy/cve/
112 recipename = report["package"][0]["name"]
113 recipe_report = os.path.join(vars["CVE_CHECK_DIR"], recipename + "_cve.json")
114 self.assertExists(recipe_report)
115 with open(recipe_report) as f:
116 report = json.load(f)
117 self.assertEqual(report["version"], "1")
118 self.assertEqual(len(report["package"]), 1)
119 self.assertEqual(report["package"][0]["name"], recipename)
Andrew Geissler615f2f12022-07-15 14:00:58 -0500120
121
122 def test_recipe_report_json_unpatched(self):
123 config = """
124INHERIT += "cve-check"
125CVE_CHECK_FORMAT_JSON = "1"
126CVE_CHECK_REPORT_PATCHED = "0"
127"""
128 self.write_config(config)
129
130 vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
131 summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
132 recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "m4-native_cve.json")
133
134 try:
135 os.remove(summary_json)
136 os.remove(recipe_json)
137 except FileNotFoundError:
138 pass
139
140 bitbake("m4-native -c cve_check")
141
142 def check_m4_json(filename):
143 with open(filename) as f:
144 report = json.load(f)
145 self.assertEqual(report["version"], "1")
146 self.assertEqual(len(report["package"]), 1)
147 package = report["package"][0]
148 self.assertEqual(package["name"], "m4-native")
149 #m4 had only Patched CVEs, so the issues array will be empty
150 self.assertEqual(package["issue"], [])
151
152 self.assertExists(summary_json)
153 check_m4_json(summary_json)
154 self.assertExists(recipe_json)
155 check_m4_json(recipe_json)
156
157
158 def test_recipe_report_json_ignored(self):
159 config = """
160INHERIT += "cve-check"
161CVE_CHECK_FORMAT_JSON = "1"
162CVE_CHECK_REPORT_PATCHED = "1"
163"""
164 self.write_config(config)
165
166 vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
167 summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
168 recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "logrotate_cve.json")
169
170 try:
171 os.remove(summary_json)
172 os.remove(recipe_json)
173 except FileNotFoundError:
174 pass
175
176 bitbake("logrotate -c cve_check")
177
178 def check_m4_json(filename):
179 with open(filename) as f:
180 report = json.load(f)
181 self.assertEqual(report["version"], "1")
182 self.assertEqual(len(report["package"]), 1)
183 package = report["package"][0]
184 self.assertEqual(package["name"], "logrotate")
185 found_cves = { issue["id"]: issue["status"] for issue in package["issue"]}
186 # m4 CVE should not be in logrotate
187 self.assertNotIn("CVE-2008-1687", found_cves)
188 # logrotate has both Patched and Ignored CVEs
189 self.assertIn("CVE-2011-1098", found_cves)
190 self.assertEqual(found_cves["CVE-2011-1098"], "Patched")
191 self.assertIn("CVE-2011-1548", found_cves)
192 self.assertEqual(found_cves["CVE-2011-1548"], "Ignored")
193 self.assertIn("CVE-2011-1549", found_cves)
194 self.assertEqual(found_cves["CVE-2011-1549"], "Ignored")
195 self.assertIn("CVE-2011-1550", found_cves)
196 self.assertEqual(found_cves["CVE-2011-1550"], "Ignored")
197
198 self.assertExists(summary_json)
199 check_m4_json(summary_json)
200 self.assertExists(recipe_json)
201 check_m4_json(recipe_json)