Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: report unknowns in sbom #2998

Merged
merged 71 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
0b83585
feat: report unknowns in sbom
kzantow Jun 26, 2024
578bba3
chore: bump schema
kzantow Jun 26, 2024
de79c95
chore: fix test
kzantow Jun 26, 2024
36987cf
chore: update tests
kzantow Jun 26, 2024
73e32e6
chore: update tests
kzantow Jun 26, 2024
84ab50a
chore: properly report unscanned jars, remove duplicate errors
kzantow Jun 26, 2024
f51c166
chore: fix nested archive "glob" match
kzantow Jun 26, 2024
ac75cd7
chore: adjust a few error messages
kzantow Jun 26, 2024
0847460
fix: consider metadata FileOwners
kzantow Jun 26, 2024
8d04a36
chore: delete apk db
kzantow Jun 26, 2024
ffc7c9b
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Jul 1, 2024
9359810
chore: fix unknown coordinate lookups
kzantow Jul 8, 2024
5b772c7
chore: update test image for hidden packages test
kzantow Jul 8, 2024
f045222
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Jul 8, 2024
856cbec
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Jul 17, 2024
5b3c2a9
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Jul 18, 2024
2fd4f93
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Jul 25, 2024
22f6c43
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Jul 25, 2024
64c369e
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Jul 29, 2024
cec49e6
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Jul 30, 2024
1932f2f
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Jul 31, 2024
f88fb4a
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Aug 4, 2024
b388ceb
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Aug 5, 2024
8e600ed
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Aug 12, 2024
5b193e5
chore: alpine unknowns + test
kzantow Aug 12, 2024
84a2fa0
chore: alpm unknowns + test
kzantow Aug 12, 2024
c382c46
chore: elf unknowns + test
kzantow Aug 12, 2024
b0c0d42
chore: conan lock unknowns + test
kzantow Aug 12, 2024
9e40008
chore: dart unknowns + test
kzantow Aug 12, 2024
a0127f8
chore: debian unknowns + test
kzantow Aug 13, 2024
f7644b5
chore: dotnet unknowns + test
kzantow Aug 13, 2024
55deeb1
chore: erlang unknowns + test
kzantow Aug 13, 2024
dba43b8
chore: generic unknowns
kzantow Aug 13, 2024
488e5a1
chore: github action unknowns
kzantow Aug 13, 2024
f981dd2
chore: golang unknowns
kzantow Aug 13, 2024
8e64d0d
chore: unknowns configuration
kzantow Aug 13, 2024
a31f547
chore: haskell unknowns
kzantow Aug 13, 2024
036f0e6
chore: java unknowns
kzantow Aug 13, 2024
08047b3
chore: javascript unknowns
kzantow Aug 13, 2024
5357f93
chore: lua unknowns test
kzantow Aug 13, 2024
a18c70e
chore: php unknowns test
kzantow Aug 13, 2024
fbb4158
chore: python unknowns test
kzantow Aug 13, 2024
a5719b7
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Aug 13, 2024
3ec0800
chore: redhat unknowns test
kzantow Aug 13, 2024
22a17b8
chore: rust unknowns test
kzantow Aug 13, 2024
f4d02ce
chore: sbom unknowns test
kzantow Aug 13, 2024
0bda741
chore: swift unknowns test
kzantow Aug 13, 2024
e34a400
chore: update schema version
kzantow Aug 13, 2024
18422a8
chore: elf unknowns
kzantow Aug 14, 2024
a99d4a6
chore: fix elf unknowns
kzantow Aug 14, 2024
2c6e3d3
chore: comment
kzantow Aug 15, 2024
de339b6
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Aug 21, 2024
15f2244
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Aug 26, 2024
9bccf5d
chore: option to leave unknowns when packages found
kzantow Aug 26, 2024
0fce8be
chore: make package.json less noisy
kzantow Aug 27, 2024
4f30524
chore: reduce some logging
kzantow Aug 27, 2024
3477775
chore: reduce some more logging
kzantow Aug 27, 2024
cbe369b
chore: add more unknown detection
kzantow Aug 30, 2024
711c6e7
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Sep 1, 2024
63ea24a
chore: reduce logging level for unknown errors in generic cataloger
kzantow Sep 6, 2024
1f3231e
chore: lint-fix
kzantow Sep 7, 2024
7b1461b
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Sep 13, 2024
653677e
fix: performance issue in unknowns.Join checking for duplicates
kzantow Sep 13, 2024
3e8364d
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Sep 13, 2024
95caede
chore: lint-fix
kzantow Sep 13, 2024
c04dfde
chore: fix tests, generate new schema
kzantow Sep 13, 2024
113ffff
chore: update tests
kzantow Sep 13, 2024
36e8327
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Sep 20, 2024
9112f71
Merge remote-tracking branch 'upstream/main' into feat/known-unknowns
kzantow Oct 4, 2024
cd73516
chore: surface package.json files with no name or version
kzantow Oct 4, 2024
e9f5060
remove unknown usage from elf security feature cataloger
wagoodman Oct 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions cmd/syft/internal/options/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ type Catalog struct {
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
Source sourceConfig `yaml:"source" json:"source" mapstructure:"source"`
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`

// configuration for inclusion of unknown information within elements
Unknowns unknownsConfig `yaml:"unknowns" mapstructure:"unknowns"`
}

var _ interface {
Expand All @@ -67,6 +70,7 @@ func DefaultCatalog() Catalog {
Java: defaultJavaConfig(),
File: defaultFileConfig(),
Relationships: defaultRelationshipsConfig(),
Unknowns: defaultUnknowns(),
Source: defaultSourceConfig(),
Parallelism: 1,
}
Expand All @@ -77,6 +81,7 @@ func (cfg Catalog) ToSBOMConfig(id clio.Identification) *syft.CreateSBOMConfig {
WithTool(id.Name, id.Version).
WithParallelism(cfg.Parallelism).
WithRelationshipsConfig(cfg.ToRelationshipsConfig()).
WithUnknownsConfig(cfg.ToUnknownsConfig()).
WithSearchConfig(cfg.ToSearchConfig()).
WithPackagesConfig(cfg.ToPackagesConfig()).
WithFilesConfig(cfg.ToFilesConfig()).
Expand All @@ -102,6 +107,13 @@ func (cfg Catalog) ToRelationshipsConfig() cataloging.RelationshipsConfig {
}
}

func (cfg Catalog) ToUnknownsConfig() cataloging.UnknownsConfig {
return cataloging.UnknownsConfig{
IncludeExecutablesWithoutPackages: cfg.Unknowns.ExecutablesWithoutPackages,
IncludeUnexpandedArchives: cfg.Unknowns.UnexpandedArchives,
}
}

func (cfg Catalog) ToFilesConfig() filecataloging.Config {
hashers, err := intFile.Hashers(cfg.File.Metadata.Digests...)
if err != nil {
Expand Down
31 changes: 31 additions & 0 deletions cmd/syft/internal/options/unknowns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package options

import (
"github.com/anchore/clio"
"github.com/anchore/syft/syft/cataloging"
)

type unknownsConfig struct {
RemoveWhenPackagesDefined bool `json:"remove-when-packages-defined" yaml:"remove-when-packages-defined" mapstructure:"remove-when-packages-defined"`
ExecutablesWithoutPackages bool `json:"executables-without-packages" yaml:"executables-without-packages" mapstructure:"executables-without-packages"`
UnexpandedArchives bool `json:"unexpanded-archives" yaml:"unexpanded-archives" mapstructure:"unexpanded-archives"`
}

var _ interface {
clio.FieldDescriber
} = (*unknownsConfig)(nil)

func (o *unknownsConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
descriptions.Add(&o.RemoveWhenPackagesDefined, `remove unknown errors on files with discovered packages`)
descriptions.Add(&o.ExecutablesWithoutPackages, `include executables without any identified packages`)
descriptions.Add(&o.UnexpandedArchives, `include archives which were not expanded and searched`)
}

func defaultUnknowns() unknownsConfig {
def := cataloging.DefaultUnknownsConfig()
return unknownsConfig{
RemoveWhenPackagesDefined: def.RemoveWhenPackagesDefined,
ExecutablesWithoutPackages: def.IncludeExecutablesWithoutPackages,
UnexpandedArchives: def.IncludeUnexpandedArchives,
}
}
2 changes: 1 addition & 1 deletion internal/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package internal
const (
// JSONSchemaVersion is the current schema version output by the JSON encoder
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
JSONSchemaVersion = "16.0.15"
JSONSchemaVersion = "16.0.16"
)
6 changes: 3 additions & 3 deletions internal/file/zip_file_manifest.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package file

import (
"fmt"
"os"
"sort"
"strings"
Expand All @@ -19,12 +18,13 @@ func NewZipFileManifest(archivePath string) (ZipFileManifest, error) {
zipReader, err := OpenZip(archivePath)
manifest := make(ZipFileManifest)
if err != nil {
return manifest, fmt.Errorf("unable to open zip archive (%s): %w", archivePath, err)
log.Debugf("unable to open zip archive (%s): %v", archivePath, err)
return manifest, err
}
defer func() {
err = zipReader.Close()
if err != nil {
log.Warnf("unable to close zip archive (%s): %+v", archivePath, err)
log.Debugf("unable to close zip archive (%s): %+v", archivePath, err)
}
}()

Expand Down
8 changes: 6 additions & 2 deletions internal/file/zip_read_closer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"io"
"math"
"os"

"github.com/anchore/syft/internal/log"
)

// directoryEndLen, readByf, directoryEnd, and findSignatureInBlock were copied from the golang stdlib, specifically:
Expand Down Expand Up @@ -46,7 +48,8 @@ func OpenZip(filepath string) (*ZipReadCloser, error) {
// need to find the start of the archive and keep track of this offset.
offset, err := findArchiveStartOffset(f, fi.Size())
if err != nil {
return nil, fmt.Errorf("cannot find beginning of zip archive=%q : %w", filepath, err)
log.Debugf("cannot find beginning of zip archive=%q : %v", filepath, err)
return nil, err
}

if _, err := f.Seek(0, io.SeekStart); err != nil {
Expand All @@ -62,7 +65,8 @@ func OpenZip(filepath string) (*ZipReadCloser, error) {

r, err := zip.NewReader(io.NewSectionReader(f, offset64, size), size)
if err != nil {
return nil, fmt.Errorf("unable to open ZipReadCloser @ %q: %w", filepath, err)
log.Debugf("unable to open ZipReadCloser @ %q: %v", filepath, err)
return nil, err
}

return &ZipReadCloser{
Expand Down
36 changes: 32 additions & 4 deletions internal/task/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import (
"sync"
"time"

"github.com/anchore/syft/internal/log"
"github.com/hashicorp/go-multierror"

"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/sbomsync"
"github.com/anchore/syft/internal/unknown"
"github.com/anchore/syft/syft/event/monitor"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/sbom"
)

type Executor struct {
Expand All @@ -35,6 +37,12 @@ func NewTaskExecutor(tasks []Task, numWorkers int) *Executor {
}

func (p *Executor) Execute(ctx context.Context, resolver file.Resolver, s sbomsync.Builder, prog *monitor.CatalogerTaskProgress) error {
var lock sync.Mutex
withLock := func(fn func()) {
lock.Lock()
defer lock.Unlock()
fn()
}
var errs error
wg := &sync.WaitGroup{}
for i := 0; i < p.numWorkers; i++ {
Expand All @@ -48,9 +56,16 @@ func (p *Executor) Execute(ctx context.Context, resolver file.Resolver, s sbomsy
return
}

if err := runTaskSafely(ctx, tsk, resolver, s); err != nil {
errs = multierror.Append(errs, fmt.Errorf("failed to run task: %w", err))
prog.SetError(err)
err := runTaskSafely(ctx, tsk, resolver, s)
unknowns, err := unknown.ExtractCoordinateErrors(err)
if len(unknowns) > 0 {
appendUnknowns(s, tsk.Name(), unknowns)
}
if err != nil {
withLock(func() {
errs = multierror.Append(errs, fmt.Errorf("failed to run task: %w", err))
prog.SetError(err)
})
}
prog.Increment()
}
Expand All @@ -62,6 +77,19 @@ func (p *Executor) Execute(ctx context.Context, resolver file.Resolver, s sbomsy
return errs
}

func appendUnknowns(builder sbomsync.Builder, taskName string, unknowns []unknown.CoordinateError) {
if accessor, ok := builder.(sbomsync.Accessor); ok {
accessor.WriteToSBOM(func(sb *sbom.SBOM) {
for _, u := range unknowns {
if sb.Artifacts.Unknowns == nil {
sb.Artifacts.Unknowns = map[file.Coordinates][]string{}
}
sb.Artifacts.Unknowns[u.Coordinates] = append(sb.Artifacts.Unknowns[u.Coordinates], formatUnknown(u.Reason.Error(), taskName))
}
})
}
}

func runTaskSafely(ctx context.Context, t Task, resolver file.Resolver, s sbomsync.Builder) (err error) {
// handle individual cataloger panics
defer func() {
Expand Down
21 changes: 4 additions & 17 deletions internal/task/file_tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package task
import (
"context"
"crypto"
"fmt"

"github.com/anchore/syft/internal/sbomsync"
"github.com/anchore/syft/syft/artifact"
Expand Down Expand Up @@ -32,15 +31,12 @@ func NewFileDigestCatalogerTask(selection file.Selection, hashers ...crypto.Hash
}

result, err := digestsCataloger.Catalog(ctx, resolver, coordinates...)
if err != nil {
return fmt.Errorf("unable to catalog file digests: %w", err)
}

accessor.WriteToSBOM(func(sbom *sbom.SBOM) {
sbom.Artifacts.FileDigests = result
})

return nil
return err
}

return NewTask("file-digest-cataloger", fn)
Expand All @@ -62,15 +58,12 @@ func NewFileMetadataCatalogerTask(selection file.Selection) Task {
}

result, err := metadataCataloger.Catalog(ctx, resolver, coordinates...)
if err != nil {
return err
}

accessor.WriteToSBOM(func(sbom *sbom.SBOM) {
sbom.Artifacts.FileMetadata = result
})

return nil
return err
}

return NewTask("file-metadata-cataloger", fn)
Expand All @@ -87,15 +80,12 @@ func NewFileContentCatalogerTask(cfg filecontent.Config) Task {
accessor := builder.(sbomsync.Accessor)

result, err := cat.Catalog(ctx, resolver)
if err != nil {
return err
}

accessor.WriteToSBOM(func(sbom *sbom.SBOM) {
sbom.Artifacts.FileContents = result
})

return nil
return err
}

return NewTask("file-content-cataloger", fn)
Expand All @@ -112,15 +102,12 @@ func NewExecutableCatalogerTask(selection file.Selection, cfg executable.Config)
accessor := builder.(sbomsync.Accessor)

result, err := cat.Catalog(resolver)
if err != nil {
return err
}

accessor.WriteToSBOM(func(sbom *sbom.SBOM) {
sbom.Artifacts.Executables = result
})

return nil
return err
}

return NewTask("file-executable-cataloger", fn)
Expand Down
7 changes: 2 additions & 5 deletions internal/task/package_task_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (f PackageTaskFactories) Tasks(cfg CatalogingFactoryConfig) ([]Task, error)
}

// NewPackageTask creates a Task function for a generic pkg.Cataloger, honoring the common configuration options.
func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string) Task { //nolint: funlen
func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string) Task {
fn := func(ctx context.Context, resolver file.Resolver, sbom sbomsync.Builder) error {
catalogerName := c.Name()
log.WithFields("name", catalogerName).Trace("starting package cataloger")
Expand All @@ -100,9 +100,6 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string
t := bus.StartCatalogerTask(info, -1, "")

pkgs, relationships, err := c.Catalog(ctx, resolver)
if err != nil {
return fmt.Errorf("unable to catalog packages with %q: %w", catalogerName, err)
}

log.WithFields("cataloger", catalogerName).Debugf("discovered %d packages", len(pkgs))

Expand Down Expand Up @@ -150,7 +147,7 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string
t.SetCompleted()
log.WithFields("name", catalogerName).Trace("package cataloger completed")

return nil
return err
}
tags = append(tags, pkgcataloging.PackageTag)

Expand Down
Loading
Loading