summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/selftest/cases/cve_check.py
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oeqa/selftest/cases/cve_check.py')
-rw-r--r--meta/lib/oeqa/selftest/cases/cve_check.py208
1 files changed, 207 insertions, 1 deletions
diff --git a/meta/lib/oeqa/selftest/cases/cve_check.py b/meta/lib/oeqa/selftest/cases/cve_check.py
index 3f343a2841..60cecd1328 100644
--- a/meta/lib/oeqa/selftest/cases/cve_check.py
+++ b/meta/lib/oeqa/selftest/cases/cve_check.py
@@ -1,9 +1,19 @@
1from oe.cve_check import Version 1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7import json
8import os
2from oeqa.selftest.case import OESelftestTestCase 9from oeqa.selftest.case import OESelftestTestCase
10from oeqa.utils.commands import bitbake, get_bb_vars
3 11
4class CVECheck(OESelftestTestCase): 12class CVECheck(OESelftestTestCase):
5 13
6 def test_version_compare(self): 14 def test_version_compare(self):
15 from oe.cve_check import Version
16
7 result = Version("100") > Version("99") 17 result = Version("100") > Version("99")
8 self.assertTrue( result, msg="Failed to compare version '100' > '99'") 18 self.assertTrue( result, msg="Failed to compare version '100' > '99'")
9 result = Version("2.3.1") > Version("2.2.3") 19 result = Version("2.3.1") > Version("2.2.3")
@@ -34,3 +44,199 @@ class CVECheck(OESelftestTestCase):
34 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' < '1.0r'") 44 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' < '1.0r'")
35 result = Version("1.0b","alphabetical") > Version("1.0","alphabetical") 45 result = Version("1.0b","alphabetical") > Version("1.0","alphabetical")
36 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' > '1.0'") 46 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' > '1.0'")
47
48 # consider the trailing "p" and "patch" as patched released when comparing
49 result = Version("1.0","patch") < Version("1.0p1","patch")
50 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0' < '1.0p1'")
51 result = Version("1.0p2","patch") > Version("1.0p1","patch")
52 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0p2' > '1.0p1'")
53 result = Version("1.0_patch2","patch") < Version("1.0_patch3","patch")
54 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0_patch2' < '1.0_patch3'")
55
56
57 def test_convert_cve_version(self):
58 from oe.cve_check import convert_cve_version
59
60 # Default format
61 self.assertEqual(convert_cve_version("8.3"), "8.3")
62 self.assertEqual(convert_cve_version(""), "")
63
64 # OpenSSL format version
65 self.assertEqual(convert_cve_version("1.1.1t"), "1.1.1t")
66
67 # OpenSSH format
68 self.assertEqual(convert_cve_version("8.3_p1"), "8.3p1")
69 self.assertEqual(convert_cve_version("8.3_p22"), "8.3p22")
70
71 # Linux kernel format
72 self.assertEqual(convert_cve_version("6.2_rc8"), "6.2-rc8")
73 self.assertEqual(convert_cve_version("6.2_rc31"), "6.2-rc31")
74
75
76 def test_recipe_report_json(self):
77 config = """
78INHERIT += "cve-check"
79CVE_CHECK_FORMAT_JSON = "1"
80"""
81 self.write_config(config)
82
83 vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
84 summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
85 recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "m4-native_cve.json")
86
87 try:
88 os.remove(summary_json)
89 os.remove(recipe_json)
90 except FileNotFoundError:
91 pass
92
93 bitbake("m4-native -c cve_check")
94
95 def check_m4_json(filename):
96 with open(filename) as f:
97 report = json.load(f)
98 self.assertEqual(report["version"], "1")
99 self.assertEqual(len(report["package"]), 1)
100 package = report["package"][0]
101 self.assertEqual(package["name"], "m4-native")
102 found_cves = { issue["id"]: issue["status"] for issue in package["issue"]}
103 self.assertIn("CVE-2008-1687", found_cves)
104 self.assertEqual(found_cves["CVE-2008-1687"], "Patched")
105
106 self.assertExists(summary_json)
107 check_m4_json(summary_json)
108 self.assertExists(recipe_json)
109 check_m4_json(recipe_json)
110
111
112 def test_image_json(self):
113 config = """
114INHERIT += "cve-check"
115CVE_CHECK_FORMAT_JSON = "1"
116"""
117 self.write_config(config)
118
119 vars = get_bb_vars(["CVE_CHECK_DIR", "CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
120 report_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
121 print(report_json)
122 try:
123 os.remove(report_json)
124 except FileNotFoundError:
125 pass
126
127 bitbake("core-image-minimal-initramfs")
128 self.assertExists(report_json)
129
130 # Check that the summary report lists at least one package
131 with open(report_json) as f:
132 report = json.load(f)
133 self.assertEqual(report["version"], "1")
134 self.assertGreater(len(report["package"]), 1)
135
136 # Check that a random recipe wrote a recipe report to deploy/cve/
137 recipename = report["package"][0]["name"]
138 recipe_report = os.path.join(vars["CVE_CHECK_DIR"], recipename + "_cve.json")
139 self.assertExists(recipe_report)
140 with open(recipe_report) as f:
141 report = json.load(f)
142 self.assertEqual(report["version"], "1")
143 self.assertEqual(len(report["package"]), 1)
144 self.assertEqual(report["package"][0]["name"], recipename)
145
146
147 def test_recipe_report_json_unpatched(self):
148 config = """
149INHERIT += "cve-check"
150CVE_CHECK_FORMAT_JSON = "1"
151CVE_CHECK_REPORT_PATCHED = "0"
152"""
153 self.write_config(config)
154
155 vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
156 summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
157 recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "m4-native_cve.json")
158
159 try:
160 os.remove(summary_json)
161 os.remove(recipe_json)
162 except FileNotFoundError:
163 pass
164
165 bitbake("m4-native -c cve_check")
166
167 def check_m4_json(filename):
168 with open(filename) as f:
169 report = json.load(f)
170 self.assertEqual(report["version"], "1")
171 self.assertEqual(len(report["package"]), 1)
172 package = report["package"][0]
173 self.assertEqual(package["name"], "m4-native")
174 #m4 had only Patched CVEs, so the issues array will be empty
175 self.assertEqual(package["issue"], [])
176
177 self.assertExists(summary_json)
178 check_m4_json(summary_json)
179 self.assertExists(recipe_json)
180 check_m4_json(recipe_json)
181
182
183 def test_recipe_report_json_ignored(self):
184 config = """
185INHERIT += "cve-check"
186CVE_CHECK_FORMAT_JSON = "1"
187CVE_CHECK_REPORT_PATCHED = "1"
188"""
189 self.write_config(config)
190
191 vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
192 summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
193 recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "logrotate_cve.json")
194
195 try:
196 os.remove(summary_json)
197 os.remove(recipe_json)
198 except FileNotFoundError:
199 pass
200
201 bitbake("logrotate -c cve_check")
202
203 def check_m4_json(filename):
204 with open(filename) as f:
205 report = json.load(f)
206 self.assertEqual(report["version"], "1")
207 self.assertEqual(len(report["package"]), 1)
208 package = report["package"][0]
209 self.assertEqual(package["name"], "logrotate")
210 found_cves = {}
211 for issue in package["issue"]:
212 found_cves[issue["id"]] = {
213 "status" : issue["status"],
214 "detail" : issue["detail"] if "detail" in issue else "",
215 "description" : issue["description"] if "description" in issue else ""
216 }
217 # m4 CVE should not be in logrotate
218 self.assertNotIn("CVE-2008-1687", found_cves)
219 # logrotate has both Patched and Ignored CVEs
220 self.assertIn("CVE-2011-1098", found_cves)
221 self.assertEqual(found_cves["CVE-2011-1098"]["status"], "Patched")
222 self.assertEqual(len(found_cves["CVE-2011-1098"]["detail"]), 0)
223 self.assertEqual(len(found_cves["CVE-2011-1098"]["description"]), 0)
224 detail = "not-applicable-platform"
225 description = "CVE is debian, gentoo or SUSE specific on the way logrotate was installed/used"
226 self.assertIn("CVE-2011-1548", found_cves)
227 self.assertEqual(found_cves["CVE-2011-1548"]["status"], "Ignored")
228 self.assertEqual(found_cves["CVE-2011-1548"]["detail"], detail)
229 self.assertEqual(found_cves["CVE-2011-1548"]["description"], description)
230 self.assertIn("CVE-2011-1549", found_cves)
231 self.assertEqual(found_cves["CVE-2011-1549"]["status"], "Ignored")
232 self.assertEqual(found_cves["CVE-2011-1549"]["detail"], detail)
233 self.assertEqual(found_cves["CVE-2011-1549"]["description"], description)
234 self.assertIn("CVE-2011-1550", found_cves)
235 self.assertEqual(found_cves["CVE-2011-1550"]["status"], "Ignored")
236 self.assertEqual(found_cves["CVE-2011-1550"]["detail"], detail)
237 self.assertEqual(found_cves["CVE-2011-1550"]["description"], description)
238
239 self.assertExists(summary_json)
240 check_m4_json(summary_json)
241 self.assertExists(recipe_json)
242 check_m4_json(recipe_json)