diff mbox series

[RFC,v2,10/12] create-spdx-3.0: Use FQDN spdx ids

Message ID 20231031224733.367227-11-louis.rannou@syslinbit.com
State New
Headers show
Series SPDX3 Proof-of-Concept | expand

Commit Message

Louis Rannou Oct. 31, 2023, 10:47 p.m. UTC
From: Samantha Jalabert <samantha.jalabert@syslinbit.com>

Create a function to generate spdxIds
Create a function to generate relationship and remove add_relationship method
Implement both functions

Signed-off-by: Samantha Jalabert <samantha.jalabert@syslinbit.com>
Signed-off-by: Louis Rannou <louis.rannou@syslinbit.com>
---
 meta/classes/create-spdx-3.0.bbclass | 73 ++++++++++++++++++++--------
 meta/lib/oe/spdx3.py                 | 27 ----------
 2 files changed, 53 insertions(+), 47 deletions(-)
diff mbox series

Patch

diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass
index 2cd91dd791..3ef01783a7 100644
--- a/meta/classes/create-spdx-3.0.bbclass
+++ b/meta/classes/create-spdx-3.0.bbclass
@@ -42,6 +42,10 @@  SPDX_SUPPLIER[doc] = "The SPDX PackageSupplier field for SPDX packages created f
     is the contact information for the person or organization who is doing the \
     build."
 
+def new_spdxid(d, doc, *suffix):
+    pn = d.getVar("PN")
+    return "/".join([get_doc_namespace(d, doc), pn] + list(suffix))
+
 def extract_licenses(filename):
     import re
 
@@ -83,21 +87,21 @@  def generate_creationInfo(d, document, comment=None):
 
     tool = oe.spdx3.SPDX3Tool()
     tool.name = "OpenEmbedded Core create-spdx.bbclass"
-    tool.spdxId = "spdx-" + d.getVar("PN") + ":SPDXRef-Actor-" + tool.name.replace(" ", "")
+    tool.spdxId = new_spdxid(d, document, "Actor", tool.name.replace(" ", ""))
     tool.creationInfo = document.creationInfo
     document.element.append(tool)
     document.creationInfo.createdUsing.append(tool)
 
     organization = oe.spdx3.SPDX3Organization()
     organization.name = d.getVar("SPDX_ORG")
-    organization.spdxId = "spdx-" + d.getVar("PN") + ":SPDXRef-Actor-" + organization.name.replace(" ", "")
+    organization.spdxId = new_spdxid(d, document, "Actor", organization.name.replace(" ", ""))
     organization.creationInfo = document.creationInfo
     document.element.append(organization)
     document.creationInfo.createdBy.append(organization)
 
     person = oe.spdx3.SPDX3Person()
     person.name = "Person: N/A ()"
-    person.spdxId = "spdx-" + d.getVar("PN") + ":SPDXRef-Actor-" + person.name.replace(" ", "")
+    person.spdxId = new_spdxid(d, document, "Actor", person.name.replace(" ", ""))
     document.creationInfo.createdBy.append(person)
     document.element.append(person)
 
@@ -124,7 +128,7 @@  def get_supplier(d, doc=None):
         raise KeyError("%r is not a valid SPDX agent type" % agentType)
 
     agent.name = agentName
-    agent.spdxId = "spdx-" + d.getVar("PN") + ":SPDXRef-Actor-" + agent.name.replace(" ", "")
+    agent.spdxId = new_spdxid(d, doc, "Actor", agent.name)
     agent.creationInfo = doc.creationInfo
 
     return agent
@@ -136,9 +140,35 @@  def create_annotation(d, doc, recipe, comment):
     c.annotationType = "other"
     c.subject = recipe.spdxId
     c.statement = comment
+    c.spdxId = new_spdxid(d, doc, "annotation", comment)
 
     doc.element.append(c)
 
+def create_relationship(d, doc, _from, relationshipType, to):
+    import oe.spdx3
+
+    if isinstance(_from, oe.spdx3.SPDX3Element):
+        _from = _from.spdxId
+    
+    if isinstance(to, oe.spdx3.SPDX3Element):
+        to = to.spdxId
+
+    for el in doc.element:
+        if isinstance(el, oe.spdx3.SPDX3Relationship) and \
+        el._from == _from and \
+        el.relationshipType == relationshipType:
+            el.to.append(to)
+            return el.spdxId
+    
+    r = oe.spdx3.SPDX3Relationship()
+    r.spdxId = new_spdxid(d, doc, "Relationship", relationshipType)
+    r._from = _from
+    r.to.append(to)
+    r.relationshipType = relationshipType
+
+    doc.element.append(r)
+    return r.spdxId
+
 def recipe_spdx_is_native(doc, recipe):
     import oe.spdx3
 
@@ -340,7 +370,7 @@  def add_package_files(d, doc, spdx_pkg, topdir, get_spdxid, get_types, *, archiv
 
                 doc.element.append(spdx_file)
 
-                doc.add_relationship(spdx_pkg, "contains", spdx_file)
+                create_relationship(d, doc, spdx_pkg, "contains", spdx_file)
 
                 spdx_files.append(spdx_file)
                 file_counter += 1
@@ -386,14 +416,14 @@  def collect_dep_recipes(d, doc, spdx_recipe):
         dep_recipes.append(oe.sbom.DepRecipe(spdx_dep_doc, spdx_dep_sha1, spdx_dep_recipe))
 
         dep_recipe_ref = oe.spdx3.SPDX3ExternalMap()
-        dep_recipe_ref.externalId = "DocumentRef-%s" % spdx_dep_doc["name"]
+        dep_recipe_ref.externalId = spdx_dep_doc["spdxId"]
         hashSha1 = oe.spdx3.SPDX3Hash()
         hashSha1.algorithm = "sha1"
         hashSha1.hashValue = spdx_dep_sha1
         dep_recipe_ref.verifiedUsing.append(hashSha1)
 
         doc.imports.append(dep_recipe_ref)
-        doc.add_relationship("%s:%s" % (dep_recipe_ref.externalId, spdx_dep_recipe["spdxId"]), "buildDependency", spdx_recipe)
+        create_relationship(d, doc, dep_recipe_ref.externalId, "buildDependency", spdx_recipe)
 
     # return dep_recipes
 
@@ -415,7 +445,7 @@  def add_download_packages(d, doc, recipe):
         for name in f.names:
             package = oe.spdx3.SPDX3Package()
             package.name = "%s-source-%d" % (d.getVar("PN"), download_idx + 1)
-            package.spdxId = oe.sbom.get_download_spdxid(d, download_idx + 1)
+            package.spdxId = new_spdxid(d, doc, "source", str(download_idx + 1))
 
             if f.type == "file":
                 continue
@@ -446,8 +476,8 @@  def add_download_packages(d, doc, recipe):
             package.downloadLocation = uri
             doc.element.append(package)
 
-            doc.add_relationship(doc, "describes", package)
-            doc.add_relationship(package, "buildDependency", recipe)
+            create_relationship(d, doc, doc, "describes", package)
+            create_relationship(d, doc, package, "buildDependency", recipe)
 
 def collect_direct_deps(d, dep_task):
     current_task = "do_" + d.getVar("BB_CURRENTTASK")
@@ -529,10 +559,11 @@  python do_create_spdx() {
 
     doc.name = "recipe-" + d.getVar("PN")
     doc.documentNamespace = get_doc_namespace(d, doc)
+    doc.spdxId = new_spdxid(d, doc, "Document")
     generate_creationInfo(d, doc)
 
     recipe = oe.spdx3.SPDX3Package()
-    recipe.spdxId = oe.sbom.get_recipe_spdxid(d)
+    recipe.spdxId = new_spdxid(d, doc, "Recipe")
     recipe.name = d.getVar("PN")
     recipe.packageVersion = d.getVar("PV")
     recipe.suppliedBy.append(get_supplier(d, doc))
@@ -564,7 +595,7 @@  python do_create_spdx() {
 
     doc.element.append(recipe)
 
-    doc.add_relationship(doc, "describes", recipe)
+    create_relationship(d, doc, doc, "describes", recipe)
 
     add_download_packages(d, doc, recipe)
 
@@ -578,7 +609,7 @@  python do_create_spdx() {
                 doc,
                 recipe,
                 spdx_workdir,
-                lambda file_counter: "SPDXRef-SourceFile-%s-%d" % (d.getVar("PN"), file_counter),
+                lambda file_counter: new_spdxid(d, doc, "sourcefile", str(file_counter)),
                 lambda filepath: ["source"],
                 ignore_dirs=[".git"],
                 ignore_top_level_dirs=["temp"],
@@ -608,6 +639,7 @@  python do_create_spdx() {
             pkg_name = d.getVar("PKG:%s" % package) or package
             doc.name = pkg_name
             doc.documentNamespace = get_doc_namespace(d, doc)
+            doc.spdxId = new_spdxid(d, doc, "Document")
             generate_creationInfo(d, doc)
 
             # TODO: Rework when License Profile implemented
@@ -618,7 +650,7 @@  python do_create_spdx() {
 
             spdx_package = oe.spdx3.SPDX3Package()
 
-            spdx_package.spdxId = oe.sbom.get_package_spdxid(pkg_name)
+            spdx_package.spdxId = new_spdxid(d, doc, "package", pkg_name)
             spdx_package.name = pkg_name
             spdx_package.packageVersion = d.getVar("PV")
             # TODO: Rework when License Profile implemented
@@ -627,8 +659,8 @@  python do_create_spdx() {
 
             doc.element.append(spdx_package)
 
-            doc.add_relationship(recipe, "generates", spdx_package)
-            doc.add_relationship(doc, "describes", spdx_package)
+            create_relationship(d, doc, recipe, "generates", spdx_package)
+            create_relationship(d, doc, doc, "describes", spdx_package)
 
             package_archive = deploy_dir_spdx / "packages" / (doc.name + ".tar.zst")
             with optional_tarfile(package_archive, archive_packaged) as archive:
@@ -637,7 +669,7 @@  python do_create_spdx() {
                     doc,
                     spdx_package,
                     pkgdest / package,
-                    lambda file_counter: oe.sbom.get_packaged_file_spdxid(pkg_name, file_counter),
+                    lambda file_counter: new_spdxid(d, doc, "package", pkg_name, "file", str(file_counter)),
                     lambda filepath: ["executable"],
                     ignore_top_level_dirs=['CONTROL', 'DEBIAN'],
                     archive=archive,
@@ -961,12 +993,13 @@  def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx
     doc = oe.spdx3.SPDX3SpdxDocument()
     doc.name = rootfs_name
     doc.documentNamespace = get_doc_namespace(d, doc)
+    doc.spdxId = new_spdxid(d, doc, "Document")
     generate_creationInfo(d, doc)
 
     image = oe.spdx3.SPDX3Package()
     image.name = d.getVar("PN")
     image.packageVersion = d.getVar("PV")
-    image.spdxId = rootfs_spdxid
+    image.spdxId = new_spdxid(d, doc, "image", rootfs_spdxid)
     image.suppliedBy.append(get_supplier(d, doc))
 
     doc.element.append(image)
@@ -997,7 +1030,7 @@  def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx
         for p in j_pkg_pkgs['Package']:
             if p['name'] == name:
                 pkg_ref = oe.spdx3.SPDX3ExternalMap()
-                pkg_ref.externalId = "DocumentRef-%s" % j_pkg_doc['name']
+                pkg_ref.externalId = j_pkg_doc['spdxId']
                 pkg_ref.definingDocument = j_pkg_doc['documentNamespace']
                 hashSha1 = oe.spdx3.SPDX3Hash()
                 hashSha1.algorithm = "sha1"
@@ -1005,7 +1038,7 @@  def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx
                 pkg_ref.verifiedUsing.append(hashSha1)
 
                 doc.imports.append(pkg_ref)
-                doc.add_relationship(image, "contains", "%s:%s" % (pkg_ref.externalId, p['spdxId']))
+                create_relationship(d, doc, image, "contains", pkg_ref.externalId)
                 break
         else:
             bb.fatal("Unable to find package with name '%s' in SPDX file %s" % (name, pkg_spdx_path))
diff --git a/meta/lib/oe/spdx3.py b/meta/lib/oe/spdx3.py
index 1a404e0b43..9ab57ac015 100644
--- a/meta/lib/oe/spdx3.py
+++ b/meta/lib/oe/spdx3.py
@@ -134,33 +134,6 @@  class SPDX3Element(SPDXObject):
                     main.update({key: value})
         return main
 
-    def add_relationship(self, _from, relationship, _to):
-        if isinstance(_from, SPDX3Element):
-            from_spdxid = _from.spdxId
-        else:
-            from_spdxid = _from
-
-        if isinstance(_to, SPDX3Element):
-            to_spdxid = _to.spdxId
-        else:
-            to_spdxid = _to
-
-        for element in self.element:
-            if isinstance(element, SPDX3Relationship) \
-            and element._from == from_spdxid \
-            and element.relationshipType == relationship:
-                element.to.append(to_spdxid)
-                return element.spdxId
-
-        r = SPDX3Relationship(
-            _from=from_spdxid,
-            relationshipType=relationship,
-            to = [to_spdxid]
-        )
-
-        self.element.append(r)
-        return r.spdxId
-
     def find_external_map(self, sourceDocumentNamespace):
         for i in self.imports:
             if i.definingDocument == sourceDocumentNamespace: