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