github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/internal/task/file_tasks.go (about) 1 package task 2 3 import ( 4 "context" 5 "crypto" 6 "fmt" 7 8 "github.com/anchore/syft/internal/sbomsync" 9 "github.com/anchore/syft/syft/artifact" 10 "github.com/anchore/syft/syft/file" 11 "github.com/anchore/syft/syft/file/cataloger/executable" 12 "github.com/anchore/syft/syft/file/cataloger/filecontent" 13 "github.com/anchore/syft/syft/file/cataloger/filedigest" 14 "github.com/anchore/syft/syft/file/cataloger/filemetadata" 15 "github.com/anchore/syft/syft/pkg" 16 "github.com/anchore/syft/syft/sbom" 17 ) 18 19 func NewFileDigestCatalogerTask(selection file.Selection, hashers ...crypto.Hash) Task { 20 if selection == file.NoFilesSelection || len(hashers) == 0 { 21 return nil 22 } 23 24 digestsCataloger := filedigest.NewCataloger(hashers) 25 26 fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error { 27 accessor := builder.(sbomsync.Accessor) 28 29 coordinates, ok := coordinatesForSelection(selection, builder.(sbomsync.Accessor)) 30 if !ok { 31 return nil 32 } 33 34 result, err := digestsCataloger.Catalog(ctx, resolver, coordinates...) 35 if err != nil { 36 return fmt.Errorf("unable to catalog file digests: %w", err) 37 } 38 39 accessor.WriteToSBOM(func(sbom *sbom.SBOM) { 40 sbom.Artifacts.FileDigests = result 41 }) 42 43 return nil 44 } 45 46 return NewTask("file-digest-cataloger", fn) 47 } 48 49 func NewFileMetadataCatalogerTask(selection file.Selection) Task { 50 if selection == file.NoFilesSelection { 51 return nil 52 } 53 54 metadataCataloger := filemetadata.NewCataloger() 55 56 fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error { 57 accessor := builder.(sbomsync.Accessor) 58 59 coordinates, ok := coordinatesForSelection(selection, builder.(sbomsync.Accessor)) 60 if !ok { 61 return nil 62 } 63 64 result, err := metadataCataloger.Catalog(ctx, resolver, coordinates...) 65 if err != nil { 66 return err 67 } 68 69 accessor.WriteToSBOM(func(sbom *sbom.SBOM) { 70 sbom.Artifacts.FileMetadata = result 71 }) 72 73 return nil 74 } 75 76 return NewTask("file-metadata-cataloger", fn) 77 } 78 79 func NewFileContentCatalogerTask(cfg filecontent.Config) Task { 80 if len(cfg.Globs) == 0 { 81 return nil 82 } 83 84 cat := filecontent.NewCataloger(cfg) 85 86 fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error { 87 accessor := builder.(sbomsync.Accessor) 88 89 result, err := cat.Catalog(ctx, resolver) 90 if err != nil { 91 return err 92 } 93 94 accessor.WriteToSBOM(func(sbom *sbom.SBOM) { 95 sbom.Artifacts.FileContents = result 96 }) 97 98 return nil 99 } 100 101 return NewTask("file-content-cataloger", fn) 102 } 103 104 func NewExecutableCatalogerTask(selection file.Selection, cfg executable.Config) Task { 105 if selection == file.NoFilesSelection { 106 return nil 107 } 108 109 cat := executable.NewCataloger(cfg) 110 111 fn := func(_ context.Context, resolver file.Resolver, builder sbomsync.Builder) error { 112 accessor := builder.(sbomsync.Accessor) 113 114 result, err := cat.Catalog(resolver) 115 if err != nil { 116 return err 117 } 118 119 accessor.WriteToSBOM(func(sbom *sbom.SBOM) { 120 sbom.Artifacts.Executables = result 121 }) 122 123 return nil 124 } 125 126 return NewTask("file-executable-cataloger", fn) 127 } 128 129 // TODO: this should be replaced with a fix that allows passing a coordinate or location iterator to the cataloger 130 // Today internal to both cataloger this functions differently: a slice of coordinates vs a channel of locations 131 func coordinatesForSelection(selection file.Selection, accessor sbomsync.Accessor) ([]file.Coordinates, bool) { 132 if selection == file.AllFilesSelection { 133 return nil, true 134 } 135 136 if selection == file.FilesOwnedByPackageSelection { 137 var coordinates []file.Coordinates 138 139 accessor.ReadFromSBOM(func(sbom *sbom.SBOM) { 140 for _, r := range sbom.Relationships { 141 if r.Type != artifact.ContainsRelationship { 142 continue 143 } 144 if _, ok := r.From.(pkg.Package); !ok { 145 continue 146 } 147 if c, ok := r.To.(file.Coordinates); ok { 148 coordinates = append(coordinates, c) 149 } 150 } 151 }) 152 153 if len(coordinates) == 0 { 154 return nil, false 155 } 156 157 return coordinates, true 158 } 159 160 return nil, false 161 }