Skip to content

Commit 050fc76

Browse files
Syeda Shagufta NaazUrist-McGit
authored andcommitted
feat(repack): add source and binary components filtering option
- introduce two new options to the repack command: --sources: repack only source components (drop binaries) --binaries: repack only binary components (drop sources) - supports both CycloneDX and SPDX SBOM format - for source SBOMs, connect root to source packages to keep the graph connected Signed-off-by: Syeda Shagufta Naaz <syedashagufta.naaz@siemens.com>
1 parent e0dd401 commit 050fc76

File tree

3 files changed

+118
-5
lines changed

3 files changed

+118
-5
lines changed

src/debsbom/commands/repack.py

Lines changed: 114 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@
77
import sys
88

99
from ..bomwriter import BomWriter
10-
from .input import SbomInput, RepackInput
10+
from .input import SbomInput, RepackInput, SourceBinaryInput
1111
from ..generate.generate import Debsbom
1212
from ..repack.packer import BomTransformer, Packer
1313
from ..resolver.resolver import PackageStreamResolver
1414
from ..util.compression import Compression
15-
15+
from .download import DownloadCmd
16+
from ..sbom import SBOMType, SPDX_REF_DOCUMENT
1617

1718
logger = logging.getLogger(__name__)
1819

1920

20-
class RepackCmd(SbomInput, RepackInput):
21+
class RepackCmd(SbomInput, RepackInput, SourceBinaryInput):
2122
"""
2223
Repacks the downloaded files into a uniform source archive, merging the
2324
referenced source packages into a single archive and optionally applying
@@ -49,11 +50,118 @@ def run(cls, args):
4950
)
5051
resolvers = cls.get_sbom_resolvers(args)
5152
for resolver in resolvers:
53+
filtered_pkgs = list(
54+
filter(lambda p: DownloadCmd._filter_pkg(p, args.sources, args.binaries), resolver)
55+
)
56+
if not (args.sources and args.binaries):
57+
if resolver.sbom_type() == SBOMType.CycloneDX:
58+
if args.sources:
59+
from cyclonedx.model.dependency import Dependency
60+
61+
resolver.document.components = [
62+
comp
63+
for comp in resolver.document.components
64+
if "arch=source" in str(comp.bom_ref.value)
65+
]
66+
67+
root_ref = resolver.document.metadata.component.bom_ref
68+
source_refs = [
69+
Dependency(ref=comp.bom_ref) for comp in resolver.document.components
70+
]
71+
if root_ref:
72+
resolver.document.dependencies = [
73+
Dependency(ref=root_ref, dependencies=source_refs)
74+
]
75+
else:
76+
resolver.document.dependencies = []
77+
78+
elif args.binaries:
79+
resolver.document.components = [
80+
comp
81+
for comp in resolver.document.components
82+
if "arch=source" not in str(comp.bom_ref.value)
83+
]
84+
85+
resolver.document.dependencies = [
86+
dep
87+
for dep in resolver.document.dependencies
88+
if "arch=source" not in str(dep.ref.value)
89+
]
90+
for dep in resolver.document.dependencies:
91+
dep.dependencies = [
92+
deps
93+
for deps in dep.dependencies
94+
if "arch=source" not in str(deps.ref.value)
95+
]
96+
97+
elif resolver.sbom_type() == SBOMType.SPDX:
98+
if args.sources:
99+
from spdx_tools.spdx.model.relationship import (
100+
Relationship,
101+
RelationshipType,
102+
)
103+
104+
resolver.document.packages = [
105+
pkg
106+
for pkg in resolver.document.packages
107+
if any(
108+
"arch=source" in ref.locator
109+
for ref in pkg.external_references
110+
if ref.reference_type == "purl"
111+
)
112+
]
113+
114+
src_pkg_ids = [pkg.spdx_id for pkg in resolver.document.packages]
115+
root_ref = None
116+
for rel in resolver.document.relationships:
117+
if rel.spdx_element_id == SPDX_REF_DOCUMENT:
118+
root_ref = rel.related_spdx_element_id
119+
break
120+
121+
new_relationships = []
122+
123+
if root_ref:
124+
new_relationships.append(
125+
Relationship(
126+
spdx_element_id=SPDX_REF_DOCUMENT,
127+
related_spdx_element_id=root_ref,
128+
relationship_type=RelationshipType.DESCRIBES,
129+
)
130+
)
131+
132+
for pkg_id in src_pkg_ids:
133+
new_relationships.append(
134+
Relationship(
135+
spdx_element_id=pkg_id,
136+
related_spdx_element_id=root_ref,
137+
relationship_type=RelationshipType.DEPENDS_ON,
138+
)
139+
)
140+
resolver.document.relationships = new_relationships
141+
142+
elif args.binaries:
143+
resolver.document.packages = [
144+
pkg
145+
for pkg in resolver.document.packages
146+
if any(
147+
"arch=source" not in ref.locator
148+
for ref in pkg.external_references
149+
if ref.reference_type == "purl"
150+
)
151+
]
152+
153+
binary_ids = {pkg.spdx_id: pkg for pkg in resolver.document.packages}
154+
resolver.document.relationships = [
155+
rel
156+
for rel in resolver.document.relationships
157+
if rel.spdx_element_id in binary_ids
158+
and rel.related_spdx_element_id in binary_ids
159+
]
52160
bt = BomTransformer.create(args.format, resolver.sbom_type(), resolver.document)
53161
if pkg_subset:
54-
pkgs = filter(lambda p: p in pkg_subset, resolver)
162+
pkgs = filter(lambda p: p in pkg_subset, filtered_pkgs)
55163
else:
56-
pkgs = resolver
164+
pkgs = filtered_pkgs
57165
repacked = filter(
58166
lambda p: p,
59167
map(
@@ -93,3 +201,4 @@ def setup_parser(cls, parser):
93201
help="validate generated SBOM (only for SPDX)",
94202
action="store_true",
95203
)
204+
cls.parser_add_source_binary_args(parser)

src/debsbom/repack/cdx.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ def transform(self, packages: Iterable[Package]) -> cdx_bom.Bom:
4848
for p in packages:
4949
# as we iterate the same set of packages, we must have it
5050
cdx_comp: cdx_component.Component = self._document.get_component_by_purl(p.purl())
51+
if not cdx_comp:
52+
continue
5153
if p.is_source():
5254
self._enhance(cdx_comp, p)
5355

src/debsbom/repack/spdx.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ def transform(self, packages: Iterable[Package]) -> spdx_document.Document:
5252
for p in packages:
5353
# as we iterate the same set of packages, we must have it
5454
spdx_pkg = self.pkgs_by_purl[str(p.purl())]
55+
if not spdx_pkg:
56+
continue
5557
if p.is_source():
5658
self._enhance(spdx_pkg, p)
5759

0 commit comments

Comments
 (0)