mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
scripts/sbom: add SPDX source graph
Implement the SPDX source graph which contains all source files involved during the build, along with the licensing information for each file. Assisted-by: Cursor:claude-sonnet-4-5 Assisted-by: OpenCode:GLM-4-7 Co-developed-by: Maximilian Huber <maximilian.huber@tngtech.com> Signed-off-by: Maximilian Huber <maximilian.huber@tngtech.com> Signed-off-by: Luis Augenstein <luis.augenstein@tngtech.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
b01912114e
commit
e70c84a564
|
|
@ -10,6 +10,7 @@ from sbom.path_utils import PathStr
|
|||
from sbom.spdx_graph.kernel_file import KernelFileCollection
|
||||
from sbom.spdx_graph.spdx_graph_model import SpdxGraph, SpdxIdGeneratorCollection
|
||||
from sbom.spdx_graph.shared_spdx_elements import SharedSpdxElements
|
||||
from sbom.spdx_graph.spdx_source_graph import SpdxSourceGraph
|
||||
from sbom.spdx_graph.spdx_output_graph import SpdxOutputGraph
|
||||
|
||||
|
||||
|
|
@ -54,4 +55,12 @@ def build_spdx_graphs(
|
|||
KernelSpdxDocumentKind.OUTPUT: output_graph,
|
||||
}
|
||||
|
||||
if len(kernel_files.source) > 0:
|
||||
spdx_graphs[KernelSpdxDocumentKind.SOURCE] = SpdxSourceGraph.create(
|
||||
source_files=list(kernel_files.source.values()),
|
||||
external_files=list(kernel_files.external.values()),
|
||||
shared_elements=shared_elements,
|
||||
spdx_id_generators=spdx_id_generators,
|
||||
)
|
||||
|
||||
return spdx_graphs
|
||||
|
|
|
|||
130
scripts/sbom/sbom/spdx_graph/spdx_source_graph.py
Normal file
130
scripts/sbom/sbom/spdx_graph/spdx_source_graph.py
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR MIT
|
||||
# Copyright (C) 2025 TNG Technology Consulting GmbH
|
||||
|
||||
from dataclasses import dataclass
|
||||
from sbom.spdx import SpdxIdGenerator
|
||||
from sbom.spdx.core import Element, NamespaceMap, Relationship, SpdxDocument
|
||||
from sbom.spdx.simplelicensing import LicenseExpression
|
||||
from sbom.spdx.software import File, Sbom
|
||||
from sbom.spdx_graph.kernel_file import KernelFile
|
||||
from sbom.spdx_graph.shared_spdx_elements import SharedSpdxElements
|
||||
from sbom.spdx_graph.spdx_graph_model import SpdxGraph, SpdxIdGeneratorCollection
|
||||
|
||||
|
||||
@dataclass
|
||||
class SpdxSourceGraph(SpdxGraph):
|
||||
"""SPDX graph representing source files"""
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
source_files: list[KernelFile],
|
||||
external_files: list[KernelFile],
|
||||
shared_elements: SharedSpdxElements,
|
||||
spdx_id_generators: SpdxIdGeneratorCollection,
|
||||
) -> "SpdxSourceGraph":
|
||||
"""
|
||||
Args:
|
||||
source_files: List of files within the kernel source tree.
|
||||
external_files: Files outside both source and object trees.
|
||||
shared_elements: Shared SPDX elements used across multiple documents.
|
||||
spdx_id_generators: Collection of SPDX ID generators.
|
||||
|
||||
Returns:
|
||||
SpdxSourceGraph: The SPDX source graph.
|
||||
"""
|
||||
# SpdxDocument
|
||||
source_spdx_document = SpdxDocument(
|
||||
spdxId=spdx_id_generators.source.generate(),
|
||||
profileConformance=["core", "software", "simpleLicensing"],
|
||||
namespaceMap=[
|
||||
NamespaceMap(prefix=generator.prefix, namespace=generator.namespace)
|
||||
for generator in [spdx_id_generators.source, spdx_id_generators.base]
|
||||
if generator.prefix is not None
|
||||
],
|
||||
)
|
||||
|
||||
# Sbom
|
||||
source_sbom = Sbom(
|
||||
spdxId=spdx_id_generators.source.generate(),
|
||||
software_sbomType=["source"],
|
||||
)
|
||||
|
||||
# Src Tree Elements
|
||||
src_tree_element = File(
|
||||
spdxId=spdx_id_generators.source.generate(),
|
||||
name="$(src_tree)",
|
||||
software_fileKind="directory",
|
||||
)
|
||||
src_tree_contains_relationship = Relationship(
|
||||
spdxId=spdx_id_generators.source.generate(),
|
||||
relationshipType="contains",
|
||||
from_=src_tree_element,
|
||||
to=[],
|
||||
)
|
||||
|
||||
# Source file elements
|
||||
source_file_elements: list[Element] = [file.spdx_file_element for file in source_files]
|
||||
external_file_elements: list[Element] = [file.spdx_file_element for file in external_files]
|
||||
|
||||
# Source file license elements
|
||||
source_file_license_identifiers, source_file_license_relationships = source_file_license_elements(
|
||||
source_files, spdx_id_generators.source
|
||||
)
|
||||
|
||||
# Update relationships
|
||||
source_spdx_document.rootElement = [source_sbom]
|
||||
source_sbom.rootElement = [src_tree_element]
|
||||
source_sbom.element = [
|
||||
src_tree_element,
|
||||
src_tree_contains_relationship,
|
||||
*source_file_elements,
|
||||
*external_file_elements,
|
||||
*source_file_license_identifiers,
|
||||
*source_file_license_relationships,
|
||||
]
|
||||
src_tree_contains_relationship.to = source_file_elements
|
||||
|
||||
source_graph = SpdxSourceGraph(
|
||||
source_spdx_document,
|
||||
shared_elements.agent,
|
||||
shared_elements.creation_info,
|
||||
source_sbom,
|
||||
)
|
||||
return source_graph
|
||||
|
||||
|
||||
def source_file_license_elements(
|
||||
source_files: list[KernelFile], spdx_id_generator: SpdxIdGenerator
|
||||
) -> tuple[list[LicenseExpression], list[Relationship]]:
|
||||
"""
|
||||
Creates SPDX license expressions and links them to the given source files
|
||||
via hasDeclaredLicense relationships.
|
||||
|
||||
Args:
|
||||
source_files: List of files within the kernel source tree.
|
||||
spdx_id_generator: Generator for unique SPDX IDs.
|
||||
|
||||
Returns:
|
||||
Tuple of (license expressions, hasDeclaredLicense relationships).
|
||||
"""
|
||||
license_expressions: dict[str, LicenseExpression] = {}
|
||||
for file in source_files:
|
||||
if file.license_identifier is None or file.license_identifier in license_expressions:
|
||||
continue
|
||||
license_expressions[file.license_identifier] = LicenseExpression(
|
||||
spdxId=spdx_id_generator.generate(),
|
||||
simplelicensing_licenseExpression=file.license_identifier,
|
||||
)
|
||||
|
||||
source_file_license_relationships = [
|
||||
Relationship(
|
||||
spdxId=spdx_id_generator.generate(),
|
||||
relationshipType="hasDeclaredLicense",
|
||||
from_=file.spdx_file_element,
|
||||
to=[license_expressions[file.license_identifier]],
|
||||
)
|
||||
for file in source_files
|
||||
if file.license_identifier is not None
|
||||
]
|
||||
return ([*license_expressions.values()], source_file_license_relationships)
|
||||
Loading…
Reference in New Issue
Block a user