summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2026-07-16 21:01:50 +0200
committerChristian Breunig <christian@breunig.cc>2026-07-16 22:52:17 +0200
commit3db21e81c99ae1e8bf8f24450046c18f53d78d74 (patch)
tree75be7eff51be43ac1fa6b72ddf9ac9be0bd8b6a4 /scripts
parent5e2e9a3375a0ec3845822702fb255ac03e2b661f (diff)
downloadvyos-build-3db21e81c99ae1e8bf8f24450046c18f53d78d74.tar.gz
vyos-build-3db21e81c99ae1e8bf8f24450046c18f53d78d74.zip
sbom: T9098: syft should run un squashfs instead of unpacked chroot
lb (live-build) binary runs binary_rootfs first, then binary_grub-efi. binary_grub-efi temporarily installs EFI tooling and then runs: "apt remove --auto-remove --purge --allow-remove-essential" That cleanup is safe for the already-generated squashfs, but it mutates build/chroot and can remove vyos-1x, breaking subsequent work that expects chroot to remain intact for SBOM generation. But why unpacking the squashfs? In an ideal world we could call syft on the compressed squashfs file which is supported. In our world, we do use a BCJ pre-filter chained with LZMA2 for compressing the squashfs, which will increase the compression ratio without a decompression penalty. Difference: ~14.3 MB, ~2.7% smaller This is unsupported by fyft which means we do need to unpack the squashfs first before checking the files and generating the SBOM file.
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/image-build/build-vyos-image51
1 files changed, 32 insertions, 19 deletions
diff --git a/scripts/image-build/build-vyos-image b/scripts/image-build/build-vyos-image
index b181a6e4..a1458d99 100755
--- a/scripts/image-build/build-vyos-image
+++ b/scripts/image-build/build-vyos-image
@@ -31,6 +31,7 @@ import datetime
import functools
import string
import subprocess
+import tempfile
class ImageBuildError(Exception):
pass
@@ -156,6 +157,7 @@ def build():
'qemu-utils',
'gdisk',
'kpartx',
+ 'squashfs-tools',
'dosfstools'
],
'binaries': []
@@ -727,26 +729,37 @@ Pin-Priority: 600
manifest['artifacts'].append(iso_file)
# Now create SBOM
- syft_target_dir = 'chroot'
- syft_base_path = os.getcwd() + f'/{syft_target_dir}'
base_filename = iso_file.rstrip('.iso')
- syft_cmd = [['syft', syft_target_dir,
- '--source-name', 'VyOS', '--source-version', version,
- '-o', f'cyclonedx-json={base_filename}.cdx.json',
- '-o', f'spdx-json={base_filename}.spdx.json']]
-
- # syft bug for CycloneDX https://github.com/anchore/syft/issues/4592#issuecomment-4567247328
- syft_cmd.append(['sed', '-i', '-e', f's@{syft_base_path}@@g', f'{base_filename}.cdx.json'])
- syft_cmd.append(['sed', '-i', '-e', f's@{syft_base_path}@//@g', f'{base_filename}.spdx.json'])
-
- for c in syft_cmd:
- with subprocess.Popen(c, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
- text=True, bufsize=1) as p:
- for line in p.stdout:
- sys.stdout.write(line)
- sys.stdout.flush()
- p.wait()
- print("I: Finished SBOM generation")
+ syft_target_dir = tempfile.mkdtemp(prefix='unsquashfs_rootfs-', dir=os.getcwd())
+ syft_base_path = syft_target_dir
+ try:
+ # lb config builds the amd64 squashfs as xz with -Xbcj x86 (a BCJ pre-filter
+ # chained with LZMA2. Real unsquashfs/mksquashfs fully support multi-filter
+ # xz streams; syft's own Go-based squashfs/xz decoder apparently only handles
+ # plain single-filter. Extract squashfs first
+ print("I: Unpack squashfs for SBOM generation")
+ syft_cmd = [['unsquashfs', '-quiet', '-no-progress', '-force', '-dest', syft_target_dir, 'binary/live/filesystem.squashfs']]
+ # run syft on extracted content
+ syft_cmd.append(['syft', syft_target_dir,
+ '--source-name', 'VyOS', '--source-version', version,
+ '-o', f'cyclonedx-json={base_filename}.cdx.json',
+ '-o', f'spdx-json={base_filename}.spdx.json'])
+
+ # syft bug for CycloneDX https://github.com/anchore/syft/issues/4592#issuecomment-4567247328
+ syft_cmd.append(['sed', '-i', '-e', f's@{syft_base_path}@@g', f'{base_filename}.cdx.json'])
+ syft_cmd.append(['sed', '-i', '-e', f's@{syft_base_path}@//@g', f'{base_filename}.spdx.json'])
+
+ for c in syft_cmd:
+ with subprocess.Popen(c, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ text=True, bufsize=1) as p:
+ for line in p.stdout:
+ sys.stdout.write(line)
+ sys.stdout.flush()
+ p.wait()
+ print("I: Finished SBOM generation")
+ finally:
+ # remove temporary unpacked squashfs, even on failure/interruption
+ shutil.rmtree(syft_target_dir, ignore_errors=True)
# If the flavor has `image_format = "iso"`, then the work is done.