diff --git a/cmd/syft/internal/options/catalog.go b/cmd/syft/internal/options/catalog.go index 22cb286a445..f11ec92d3bb 100644 --- a/cmd/syft/internal/options/catalog.go +++ b/cmd/syft/internal/options/catalog.go @@ -133,6 +133,7 @@ func (cfg Catalog) ToFilesConfig() filecataloging.Config { } return filecataloging.Config{ + Enabled: cfg.File.Enabled, Selection: cfg.File.Metadata.Selection, Hashers: hashers, Content: filecontent.Config{ diff --git a/cmd/syft/internal/options/file.go b/cmd/syft/internal/options/file.go index 6ac9c8d2ba3..b4830f86712 100644 --- a/cmd/syft/internal/options/file.go +++ b/cmd/syft/internal/options/file.go @@ -12,6 +12,7 @@ import ( ) type fileConfig struct { + Enabled bool `yaml:"enabled" json:"enabled" mapstructure:"enabled"` Metadata fileMetadata `yaml:"metadata" json:"metadata" mapstructure:"metadata"` Content fileContent `yaml:"content" json:"content" mapstructure:"content"` Executable fileExecutable `yaml:"executable" json:"executable" mapstructure:"executable"` @@ -33,6 +34,7 @@ type fileExecutable struct { func defaultFileConfig() fileConfig { return fileConfig{ + Enabled: true, Metadata: fileMetadata{ Selection: file.FilesOwnedByPackageSelection, Digests: []string{"sha1", "sha256"}, @@ -64,11 +66,12 @@ func (c *fileConfig) PostLoad() error { } func (c *fileConfig) DescribeFields(descriptions clio.FieldDescriptionSet) { + descriptions.Add(&c.Enabled, `enable or disable file cataloging entirely`) descriptions.Add(&c.Metadata.Selection, `select which files should be captured by the file-metadata cataloger and included in the SBOM. Options include: - - "all": capture all files from the search space - - "owned-by-package": capture only files owned by packages - - "none", "": do not capture any files`) + - "all": capture metadata for all files from the search space + - "owned-by-package": capture metadata only for files owned by packages + - "none", "": do not capture metadata for any files`) descriptions.Add(&c.Metadata.Digests, `the file digest algorithms to use when cataloging files (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")`) descriptions.Add(&c.Content.SkipFilesAboveSize, `skip searching a file entirely if it is above the given size (default = 1MB; unit = bytes)`) diff --git a/cmd/syft/internal/test/integration/files_test.go b/cmd/syft/internal/test/integration/files_test.go index 6794eed08eb..39750ee087f 100644 --- a/cmd/syft/internal/test/integration/files_test.go +++ b/cmd/syft/internal/test/integration/files_test.go @@ -36,6 +36,7 @@ func TestFileCataloging_Default(t *testing.T) { func TestFileCataloging_AllFiles(t *testing.T) { cfg := options.DefaultCatalog().ToSBOMConfig(clio.Identification{}) cfg = cfg.WithFilesConfig(filecataloging.Config{ + Enabled: true, Selection: file.AllFilesSelection, Hashers: []crypto.Hash{ crypto.SHA256, diff --git a/syft/cataloging/filecataloging/config.go b/syft/cataloging/filecataloging/config.go index cc639c2f17b..2dd37e84c11 100644 --- a/syft/cataloging/filecataloging/config.go +++ b/syft/cataloging/filecataloging/config.go @@ -14,6 +14,7 @@ import ( ) type Config struct { + Enabled bool `yaml:"enabled" json:"enabled" mapstructure:"enabled"` Selection file.Selection `yaml:"selection" json:"selection" mapstructure:"selection"` Hashers []crypto.Hash `yaml:"hashers" json:"hashers" mapstructure:"hashers"` Content filecontent.Config `yaml:"content" json:"content" mapstructure:"content"` @@ -21,6 +22,7 @@ type Config struct { } type configMarshaledForm struct { + Enabled bool `yaml:"enabled" json:"enabled" mapstructure:"enabled"` Selection file.Selection `yaml:"selection" json:"selection" mapstructure:"selection"` Hashers []string `yaml:"hashers" json:"hashers" mapstructure:"hashers"` Content filecontent.Config `yaml:"content" json:"content" mapstructure:"content"` @@ -32,6 +34,7 @@ func DefaultConfig() Config { log.WithFields("error", err).Warn("unable to create file hashers") } return Config{ + Enabled: true, Selection: file.FilesOwnedByPackageSelection, Hashers: hashers, Content: filecontent.DefaultConfig(), @@ -41,6 +44,7 @@ func DefaultConfig() Config { func (cfg Config) MarshalJSON() ([]byte, error) { marshaled := configMarshaledForm{ + Enabled: cfg.Enabled, Selection: cfg.Selection, Hashers: hashersToString(cfg.Hashers), } diff --git a/syft/cataloging/filecataloging/config_test.go b/syft/cataloging/filecataloging/config_test.go index ca62dccb1a1..0116320fc47 100644 --- a/syft/cataloging/filecataloging/config_test.go +++ b/syft/cataloging/filecataloging/config_test.go @@ -21,10 +21,11 @@ func TestConfig_MarshalJSON(t *testing.T) { { name: "converts hashers to strings", cfg: Config{ + Enabled: true, Selection: file.FilesOwnedByPackageSelection, Hashers: []crypto.Hash{crypto.SHA256}, }, - want: []byte(`{"selection":"owned-by-package","hashers":["sha-256"],"content":{"globs":null,"skip-files-above-size":0}}`), + want: []byte(`{"enabled":true,"selection":"owned-by-package","hashers":["sha-256"],"content":{"globs":null,"skip-files-above-size":0}}`), }, } for _, tt := range tests { diff --git a/syft/create_sbom_config.go b/syft/create_sbom_config.go index 8e9e76b5c3b..43bf501479c 100644 --- a/syft/create_sbom_config.go +++ b/syft/create_sbom_config.go @@ -222,18 +222,19 @@ func (c *CreateSBOMConfig) makeTaskGroups(src source.Description) ([][]task.Task // fileTasks returns the set of tasks that should be run to catalog files. func (c *CreateSBOMConfig) fileTasks() []task.Task { var tsks []task.Task - - if t := task.NewFileDigestCatalogerTask(c.Files.Selection, c.Files.Hashers...); t != nil { - tsks = append(tsks, t) - } - if t := task.NewFileMetadataCatalogerTask(c.Files.Selection); t != nil { - tsks = append(tsks, t) - } - if t := task.NewFileContentCatalogerTask(c.Files.Content); t != nil { - tsks = append(tsks, t) - } - if t := task.NewExecutableCatalogerTask(c.Files.Selection, c.Files.Executable); t != nil { - tsks = append(tsks, t) + if c.Files.Enabled { + if t := task.NewFileDigestCatalogerTask(c.Files.Selection, c.Files.Hashers...); t != nil { + tsks = append(tsks, t) + } + if t := task.NewFileMetadataCatalogerTask(c.Files.Selection); t != nil { + tsks = append(tsks, t) + } + if t := task.NewFileContentCatalogerTask(c.Files.Content); t != nil { + tsks = append(tsks, t) + } + if t := task.NewExecutableCatalogerTask(c.Files.Selection, c.Files.Executable); t != nil { + tsks = append(tsks, t) + } } return tsks diff --git a/syft/file/coordinate_set.go b/syft/file/coordinate_set.go index ba56005d302..4790fe41640 100644 --- a/syft/file/coordinate_set.go +++ b/syft/file/coordinate_set.go @@ -78,6 +78,10 @@ func (s CoordinateSet) ToSlice() []Coordinates { return coordinates } +func (s CoordinateSet) Size() int { + return len(s.set) +} + func (s CoordinateSet) Hash() (uint64, error) { return hashstructure.Hash(s.ToSlice(), hashstructure.FormatV2, &hashstructure.HashOptions{ ZeroNil: true, diff --git a/syft/sbom/sbom.go b/syft/sbom/sbom.go index 1c8cbc60ff2..2974be7be82 100644 --- a/syft/sbom/sbom.go +++ b/syft/sbom/sbom.go @@ -66,9 +66,11 @@ func (s SBOM) AllCoordinates() []file.Coordinates { for coordinates := range s.Artifacts.Unknowns { set.Add(coordinates) } - for _, relationship := range s.Relationships { - for _, coordinates := range extractCoordinates(relationship) { - set.Add(coordinates) + if set.Size() > 0 { + for _, relationship := range s.Relationships { + for _, coordinates := range extractCoordinates(relationship) { + set.Add(coordinates) + } } } return set.ToSlice()