From: Stefano Tondo <[email protected]> Add two test methods to SPDX30Check: - test_openvex_integration: Verifies VEX relationships exist in SPDX output and packages have PURLs for VEX product identification - test_openvex_standalone_files: Verifies standalone .vex.json files are created with proper metadata when OPENVEX_GENERATE_STANDALONE=1
Signed-off-by: Stefano Tondo <[email protected]> --- meta/lib/oeqa/selftest/cases/spdx.py | 90 ++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/spdx.py b/meta/lib/oeqa/selftest/cases/spdx.py index 8285189382..661daa17d8 100644 --- a/meta/lib/oeqa/selftest/cases/spdx.py +++ b/meta/lib/oeqa/selftest/cases/spdx.py @@ -443,3 +443,93 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): r'\d', f"Version '{version}' for package '{name}' should contain digits" ) + + def test_openvex_integration(self): + """ + Test that OpenVEX generation is integrated into SPDX workflow. + + Verifies VEX relationships are created for vulnerabilities and + packages have PURLs suitable for VEX product identification. + """ + objset = self.check_recipe_spdx( + "busybox", + "{DEPLOY_DIR_SPDX}/{SSTATE_PKGARCH}/static/static-busybox.spdx.json", + task="create_recipe_spdx", + extraconf=""" OPENVEX_AUTHOR = "Test Author" + OPENVEX_ROLE = "securityAdvisor" + """, + ) + + # Check for VEX relationships (any type: Fixed, Affected, NotAffected, etc.) + vex_count = 0 + for rel in objset.foreach_type(oe.spdx30.security_VexVulnAssessmentRelationship): + vex_count += 1 + self.assertIsNotNone(rel.from_, "VEX relationship missing 'from' field") + self.assertIsNotNone(rel.to, "VEX relationship missing 'to' field") + + if vex_count: + self.logger.info(f"Found {vex_count} VEX relationships in SPDX") + else: + self.logger.info("No VEX relationships found (expected if no CVEs)") + + # Verify packages have PURLs for VEX product identification + packages_with_purls = [] + for pkg in objset.foreach_type(oe.spdx30.software_Package): + if hasattr(pkg, "externalIdentifier") and pkg.externalIdentifier: + for ext_id in pkg.externalIdentifier: + if hasattr(ext_id, "externalIdentifierType"): + if "packageurl" in str(ext_id.externalIdentifierType).lower(): + packages_with_purls.append(pkg.name) + break + + self.assertGreater( + len(packages_with_purls), 0, + "Should have packages with PURLs for VEX product identification" + ) + self.logger.info(f"Found {len(packages_with_purls)} packages with PURLs") + + def test_openvex_standalone_files(self): + """ + Test that standalone OpenVEX files are generated when enabled. + + Verifies OpenVEX JSON files are created with required metadata + for a recipe with known CVEs (busybox). + """ + import json + from pathlib import Path + + self.check_recipe_spdx( + "busybox", + "{DEPLOY_DIR_SPDX}/{SSTATE_PKGARCH}/static/static-busybox.spdx.json", + task="create_recipe_spdx", + extraconf=""" OPENVEX_GENERATE_STANDALONE = "1" + OPENVEX_AUTHOR = "Test Security Team" + OPENVEX_ROLE = "securityAdvisor" + """, + ) + + deploy_dir_spdx = get_bb_var("DEPLOY_DIR_SPDX") + sstate_pkgarch = get_bb_var("SSTATE_PKGARCH", "busybox") + + vex_file = Path(deploy_dir_spdx) / sstate_pkgarch / "recipes" / "busybox.vex.json" + + self.assertExists(str(vex_file), "busybox.vex.json should exist (busybox has known CVEs)") + + with open(vex_file, "r") as f: + vex_data = json.load(f) + + self.assertIn("@context", vex_data, "VEX missing @context") + self.assertIn("statements", vex_data, "VEX missing statements") + self.assertGreater(len(vex_data["statements"]), 0, "VEX should have at least one statement") + + self.assertEqual( + vex_data["author"], + "Test Security Team", + "VEX author not set correctly" + ) + + self.logger.info( + f"Validated OpenVEX file: busybox.vex.json " + f"({len(vex_data['statements'])} statements)" + ) + -- 2.53.0
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#234293): https://lists.openembedded.org/g/openembedded-core/message/234293 Mute This Topic: https://lists.openembedded.org/mt/118596972/21656 Group Owner: [email protected] Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
