@@ -31,6 +31,7 @@ import datetime
3131import functools
3232import string
3333import subprocess
34+ import tempfile
3435
3536class ImageBuildError (Exception ):
3637 pass
@@ -156,6 +157,7 @@ def build():
156157 'qemu-utils' ,
157158 'gdisk' ,
158159 'kpartx' ,
160+ 'squashfs-tools' ,
159161 'dosfstools'
160162 ],
161163 'binaries' : []
@@ -727,26 +729,37 @@ Pin-Priority: 600
727729 manifest ['artifacts' ].append (iso_file )
728730
729731 # Now create SBOM
730- syft_target_dir = 'chroot'
731- syft_base_path = os .getcwd () + f'/{ syft_target_dir } '
732732 base_filename = iso_file .rstrip ('.iso' )
733- syft_cmd = [['syft' , syft_target_dir ,
734- '--source-name' , 'VyOS' , '--source-version' , version ,
735- '-o' , f'cyclonedx-json={ base_filename } .cdx.json' ,
736- '-o' , f'spdx-json={ base_filename } .spdx.json' ]]
737-
738- # syft bug for CycloneDX https://github.com/anchore/syft/issues/4592#issuecomment-4567247328
739- syft_cmd .append (['sed' , '-i' , '-e' , f's@{ syft_base_path } @@g' , f'{ base_filename } .cdx.json' ])
740- syft_cmd .append (['sed' , '-i' , '-e' , f's@{ syft_base_path } @//@g' , f'{ base_filename } .spdx.json' ])
741-
742- for c in syft_cmd :
743- with subprocess .Popen (c , stdout = subprocess .PIPE , stderr = subprocess .STDOUT ,
744- text = True , bufsize = 1 ) as p :
745- for line in p .stdout :
746- sys .stdout .write (line )
747- sys .stdout .flush ()
748- p .wait ()
749- print ("I: Finished SBOM generation" )
733+ syft_target_dir = tempfile .mkdtemp (prefix = 'unsquashfs_rootfs-' , dir = os .getcwd ())
734+ syft_base_path = syft_target_dir
735+ try :
736+ # lb config builds the amd64 squashfs as xz with -Xbcj x86 (a BCJ pre-filter
737+ # chained with LZMA2. Real unsquashfs/mksquashfs fully support multi-filter
738+ # xz streams; syft's own Go-based squashfs/xz decoder apparently only handles
739+ # plain single-filter. Extract squashfs first
740+ print ("I: Unpack squashfs for SBOM generation" )
741+ syft_cmd = [['unsquashfs' , '-quiet' , '-no-progress' , '-force' , '-dest' , syft_target_dir , 'binary/live/filesystem.squashfs' ]]
742+ # run syft on extracted content
743+ syft_cmd .append (['syft' , syft_target_dir ,
744+ '--source-name' , 'VyOS' , '--source-version' , version ,
745+ '-o' , f'cyclonedx-json={ base_filename } .cdx.json' ,
746+ '-o' , f'spdx-json={ base_filename } .spdx.json' ])
747+
748+ # syft bug for CycloneDX https://github.com/anchore/syft/issues/4592#issuecomment-4567247328
749+ syft_cmd .append (['sed' , '-i' , '-e' , f's@{ syft_base_path } @@g' , f'{ base_filename } .cdx.json' ])
750+ syft_cmd .append (['sed' , '-i' , '-e' , f's@{ syft_base_path } @//@g' , f'{ base_filename } .spdx.json' ])
751+
752+ for c in syft_cmd :
753+ with subprocess .Popen (c , stdout = subprocess .PIPE , stderr = subprocess .STDOUT ,
754+ text = True , bufsize = 1 ) as p :
755+ for line in p .stdout :
756+ sys .stdout .write (line )
757+ sys .stdout .flush ()
758+ p .wait ()
759+ print ("I: Finished SBOM generation" )
760+ finally :
761+ # remove temporary unpacked squashfs, even on failure/interruption
762+ shutil .rmtree (syft_target_dir , ignore_errors = True )
750763
751764
752765 # If the flavor has `image_format = "iso"`, then the work is done.
0 commit comments