mirror of
https://github.com/anchore/grype
synced 2024-11-10 06:34:13 +00:00
add package provider abstraction and update json document input
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
137be60f28
commit
0699e6a6ca
19 changed files with 1068 additions and 104 deletions
12
cmd/root.go
12
cmd/root.go
|
@ -21,7 +21,6 @@ import (
|
|||
"github.com/anchore/grype/internal/format"
|
||||
"github.com/anchore/grype/internal/ui"
|
||||
"github.com/anchore/grype/internal/version"
|
||||
"github.com/anchore/syft/syft/distro"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
|
@ -177,8 +176,7 @@ func startWorker(userInput string, failOnSeverity *vulnerability.Severity) <-cha
|
|||
var provider vulnerability.Provider
|
||||
var metadataProvider vulnerability.MetadataProvider
|
||||
var packages []pkg.Package
|
||||
var srcMetadata source.Metadata
|
||||
var theDistro *distro.Distro
|
||||
var context pkg.Context
|
||||
var err error
|
||||
var wg = &sync.WaitGroup{}
|
||||
|
||||
|
@ -186,6 +184,7 @@ func startWorker(userInput string, failOnSeverity *vulnerability.Severity) <-cha
|
|||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
log.Debug("loading DB")
|
||||
provider, metadataProvider, err = grype.LoadVulnerabilityDb(appConfig.Db.ToCuratorConfig(), appConfig.Db.AutoUpdate)
|
||||
if err != nil {
|
||||
errs <- fmt.Errorf("failed to load vulnerability db: %w", err)
|
||||
|
@ -194,7 +193,8 @@ func startWorker(userInput string, failOnSeverity *vulnerability.Severity) <-cha
|
|||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srcMetadata, packages, theDistro, err = grype.Catalog(userInput, appConfig.ScopeOpt)
|
||||
log.Debugf("gathering packages")
|
||||
packages, context, err = pkg.Provide(userInput, appConfig.ScopeOpt)
|
||||
if err != nil {
|
||||
errs <- fmt.Errorf("failed to catalog: %w", err)
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ func startWorker(userInput string, failOnSeverity *vulnerability.Severity) <-cha
|
|||
return
|
||||
}
|
||||
|
||||
matches := grype.FindVulnerabilitiesForPackage(provider, theDistro, packages...)
|
||||
matches := grype.FindVulnerabilitiesForPackage(provider, context.Distro, packages...)
|
||||
|
||||
// determine if there are any severities >= to the max allowable severity (which is optional).
|
||||
// note: until the shared file lock in sqlittle is fixed the sqlite DB cannot be access concurrently,
|
||||
|
@ -216,7 +216,7 @@ func startWorker(userInput string, failOnSeverity *vulnerability.Severity) <-cha
|
|||
|
||||
bus.Publish(partybus.Event{
|
||||
Type: event.VulnerabilityScanningFinished,
|
||||
Value: presenter.GetPresenter(appConfig.PresenterOpt, matches, packages, theDistro, srcMetadata, metadataProvider),
|
||||
Value: presenter.GetPresenter(appConfig.PresenterOpt, matches, packages, context, metadataProvider),
|
||||
})
|
||||
}()
|
||||
return errs
|
||||
|
|
4
go.mod
4
go.mod
|
@ -7,8 +7,8 @@ require (
|
|||
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
|
||||
github.com/anchore/go-version v1.2.2-0.20200810141238-330bef18dbca
|
||||
github.com/anchore/grype-db v0.0.0-20200929200644-6d1c82acc95e
|
||||
github.com/anchore/stereoscope v0.0.0-20201203153145-3f9a05a624d7
|
||||
github.com/anchore/syft v0.9.3-0.20201204184855-2d0c127419a3
|
||||
github.com/anchore/stereoscope v0.0.0-20201210022249-091f9bddb42e
|
||||
github.com/anchore/syft v0.10.0
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/facebookincubator/nvdtools v0.1.4
|
||||
|
|
9
go.sum
9
go.sum
|
@ -114,6 +114,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
|
|||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/alicebob/sqlittle v1.4.0 h1:vgYt0nAjhdf/hg52MjKJ84g/uTzBPfrvI+VUBrIghxA=
|
||||
github.com/alicebob/sqlittle v1.4.0/go.mod h1:Co1L1qxHqCwf41puWhk2HOodojR0mcsAV4BIt8byZh8=
|
||||
github.com/anchore/client-go v0.0.0-20201210022459-59e7a0749c74 h1:9kkKTIyXJC+/syUcY6KWxFoJZJ+GWwrIscF+gBY067k=
|
||||
github.com/anchore/client-go v0.0.0-20201210022459-59e7a0749c74/go.mod h1:FaODhIA06mxO1E6R32JE0TL1JWZZkmjRIAd4ULvHUKk=
|
||||
github.com/anchore/go-rpmdb v0.0.0-20201106153645-0043963c2e12 h1:xbeIbn5F52JVx3RUIajxCj8b0y+9lywspql4sFhcxWQ=
|
||||
github.com/anchore/go-rpmdb v0.0.0-20201106153645-0043963c2e12/go.mod h1:juoyWXIj7sJ1IDl4E/KIfyLtovbs5XQVSIdaQifFQT8=
|
||||
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0vW0nnNKJfJieyH/TZ9UYAnTZs5/gHTdAe8=
|
||||
|
@ -126,14 +128,21 @@ github.com/anchore/grype-db v0.0.0-20200929200644-6d1c82acc95e h1:s0HmxxDuJyvgGB
|
|||
github.com/anchore/grype-db v0.0.0-20200929200644-6d1c82acc95e/go.mod h1:LINmipRzG88vnJEWvgMMDVCFH1qZsj7+bjmpERlSyaA=
|
||||
github.com/anchore/stereoscope v0.0.0-20201203153145-3f9a05a624d7 h1:G3LnRqHL/IIeQZTAMtDOJNYfSYsXLNCZX4DCiS0R0FY=
|
||||
github.com/anchore/stereoscope v0.0.0-20201203153145-3f9a05a624d7/go.mod h1:2Jja/4l0zYggW52og+nn0rut4i+OYjCf9vTyrM8RT4E=
|
||||
github.com/anchore/stereoscope v0.0.0-20201210022249-091f9bddb42e h1:vHUqHTvH9/oxdDDh1fxS9Ls9gWGytKO7XbbzcQ9MBwI=
|
||||
github.com/anchore/stereoscope v0.0.0-20201210022249-091f9bddb42e/go.mod h1:/dHAFjYflH/1tzhdHAcnMCjprMch+YzHJKi59m/1KCM=
|
||||
github.com/anchore/syft v0.9.2 h1:kRmquh8qOqH+/84S3/kOzj0cnGiqtW4f38Iz3TGrzXQ=
|
||||
github.com/anchore/syft v0.9.2/go.mod h1:1vZpPrvAhEnpUsi4/+V3c9W0eGgSZLesStiKt/ujf6E=
|
||||
github.com/anchore/syft v0.9.3-0.20201204184855-2d0c127419a3 h1:kJFcZZlhP5spei7uRon+2QzFTABjmzcJfeYh2Hje8KQ=
|
||||
github.com/anchore/syft v0.9.3-0.20201204184855-2d0c127419a3/go.mod h1:1vZpPrvAhEnpUsi4/+V3c9W0eGgSZLesStiKt/ujf6E=
|
||||
github.com/anchore/syft v0.10.0 h1:fN7wUauj560M6rjaRYBobpTDxciYQT9f1JQTJvyBRuQ=
|
||||
github.com/anchore/syft v0.10.0/go.mod h1:U+cGFs4UkMRxkVgiJ1OtQHfemdDkk2Mpaq5Rw3rqHnI=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ=
|
||||
github.com/apex/log v1.3.0 h1:1fyfbPvUwD10nMoh3hY6MXzvZShJQn9/ck7ATgAt5pA=
|
||||
github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs=
|
||||
github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
|
||||
github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE=
|
||||
|
|
53
grype/lib.go
53
grype/lib.go
|
@ -1,71 +1,26 @@
|
|||
package grype
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/grype/grype/db"
|
||||
"github.com/anchore/grype/grype/logger"
|
||||
"github.com/anchore/grype/grype/match"
|
||||
"github.com/anchore/grype/grype/matcher"
|
||||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/grype/internal"
|
||||
"github.com/anchore/grype/internal/bus"
|
||||
"github.com/anchore/grype/internal/log"
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/distro"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
"github.com/wagoodman/go-partybus"
|
||||
)
|
||||
|
||||
func Catalog(userImageStr string, scopeOpt source.Scope) (source.Metadata, []pkg.Package, *distro.Distro, error) {
|
||||
// handle explicit sbom input first
|
||||
if strings.HasPrefix(userImageStr, "sbom:") {
|
||||
// the user has explicitly hinted this is an sbom, if there is an issue return the error
|
||||
filepath := strings.TrimPrefix(userImageStr, "sbom:")
|
||||
sbomReader, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
return source.Metadata{}, nil, nil, fmt.Errorf("unable to read sbom: %w", err)
|
||||
}
|
||||
sourceMetadata, catalog, theDistro, err := syft.CatalogFromJSON(sbomReader)
|
||||
if err != nil {
|
||||
return source.Metadata{}, nil, nil, err
|
||||
}
|
||||
return sourceMetadata, pkg.FromCatalog(catalog), theDistro, err
|
||||
} else if internal.IsPipedInput() && userImageStr == "" {
|
||||
// the user has not provided an image and stdin is a pipe, assume this to be an explicit sbom case
|
||||
sourceMetadata, catalog, theDistro, err := syft.CatalogFromJSON(os.Stdin)
|
||||
if err != nil {
|
||||
return source.Metadata{}, nil, nil, err
|
||||
}
|
||||
return sourceMetadata, pkg.FromCatalog(catalog), theDistro, err
|
||||
}
|
||||
|
||||
// the user has not hinted that this may be a sbom, but lets try that first... ignore failures and fallback to syft
|
||||
if sbomReader, err := os.Open(userImageStr); err == nil {
|
||||
sourceMetadata, catalog, theDistro, err := syft.CatalogFromJSON(sbomReader)
|
||||
if err == nil {
|
||||
return sourceMetadata, pkg.FromCatalog(catalog), theDistro, nil
|
||||
}
|
||||
}
|
||||
|
||||
// attempt to parse as an image (left syft handle this)
|
||||
theSource, catalog, theDistro, err := syft.Catalog(userImageStr, scopeOpt)
|
||||
func FindVulnerabilities(provider vulnerability.Provider, userImageStr string, scopeOpt source.Scope) (match.Matches, pkg.Context, []pkg.Package, error) {
|
||||
packages, context, err := pkg.Provide(userImageStr, scopeOpt)
|
||||
if err != nil {
|
||||
return source.Metadata{}, nil, nil, err
|
||||
}
|
||||
return theSource.Metadata, pkg.FromCatalog(catalog), theDistro, nil
|
||||
}
|
||||
|
||||
func FindVulnerabilities(provider vulnerability.Provider, userImageStr string, scopeOpt source.Scope) (match.Matches, source.Metadata, []pkg.Package, error) {
|
||||
sourceMetadata, packages, theDistro, err := Catalog(userImageStr, scopeOpt)
|
||||
if err != nil {
|
||||
return match.Matches{}, source.Metadata{}, nil, err
|
||||
return match.Matches{}, pkg.Context{}, nil, err
|
||||
}
|
||||
|
||||
return FindVulnerabilitiesForPackage(provider, theDistro, packages...), sourceMetadata, packages, nil
|
||||
return FindVulnerabilitiesForPackage(provider, context.Distro, packages...), context, packages, nil
|
||||
}
|
||||
|
||||
func FindVulnerabilitiesForPackage(provider vulnerability.Provider, d *distro.Distro, packages ...pkg.Package) match.Matches {
|
||||
|
|
11
grype/pkg/context.go
Normal file
11
grype/pkg/context.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package pkg
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/distro"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
Source *source.Metadata
|
||||
Distro *distro.Distro
|
||||
}
|
56
grype/pkg/provider.go
Normal file
56
grype/pkg/provider.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package pkg
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/anchore/grype/internal"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
var errDoesNotProvide = fmt.Errorf("cannot provide packages from the given source")
|
||||
|
||||
type providerConfig struct {
|
||||
userInput string
|
||||
scopeOpt *source.Scope
|
||||
reader io.Reader
|
||||
}
|
||||
|
||||
type provider func(cfg providerConfig) ([]Package, Context, error)
|
||||
|
||||
// Provide a set of packages and context metadata describing where they were sourced from.
|
||||
func Provide(userInput string, scopeOpt source.Scope) ([]Package, Context, error) {
|
||||
providers := []provider{
|
||||
syftJSONProvider,
|
||||
syftProvider, // important: we should try syft last
|
||||
}
|
||||
|
||||
// aggregate stdin into a buffer that can be used across multiple providers dynamically
|
||||
var previousStdin bytes.Buffer
|
||||
|
||||
for _, p := range providers {
|
||||
cfg := providerConfig{
|
||||
userInput: userInput,
|
||||
scopeOpt: &scopeOpt,
|
||||
}
|
||||
|
||||
if internal.IsPipedInput() && userInput == "" {
|
||||
// this is a hint to all providers that there is already a reader available, don't try and derive one from user input
|
||||
// however, the user input may be useful in situations where the reader isn't provided
|
||||
|
||||
// this reader is a combination of previous bytes read from stdin by other providers as well as what still is
|
||||
// available from stdin. The Tee reader is to ensure that any read bytes from stdin are preserved.
|
||||
cfg.reader = io.MultiReader(&previousStdin, io.TeeReader(os.Stdin, &previousStdin))
|
||||
}
|
||||
|
||||
packages, ctx, err := p(cfg)
|
||||
if !errors.Is(err, errDoesNotProvide) {
|
||||
return packages, ctx, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil, Context{}, errDoesNotProvide
|
||||
}
|
213
grype/pkg/syft_json_provider.go
Normal file
213
grype/pkg/syft_json_provider.go
Normal file
|
@ -0,0 +1,213 @@
|
|||
package pkg
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/grype/grype/cpe"
|
||||
"github.com/anchore/syft/syft/distro"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
syftJson "github.com/anchore/syft/syft/presenter/json"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func syftJSONProvider(config providerConfig) ([]Package, Context, error) {
|
||||
var reader io.Reader
|
||||
if config.reader != nil {
|
||||
// the caller is explicitly hinting to use the given reader as input
|
||||
reader = config.reader
|
||||
} else {
|
||||
// try and get a reader from the description
|
||||
if strings.HasPrefix(config.userInput, "sbom:") {
|
||||
// the user has explicitly hinted this is an sbom, if there is an issue return the error
|
||||
filepath := strings.TrimPrefix(config.userInput, "sbom:")
|
||||
sbomReader, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
return nil, Context{}, fmt.Errorf("user hinted 'sbom:' but could read SBOM file: %w", err)
|
||||
}
|
||||
reader = sbomReader
|
||||
}
|
||||
|
||||
// the user has not hinted that this may be a sbom, but lets try that first...
|
||||
if sbomReader, err := os.Open(config.userInput); err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, Context{}, errDoesNotProvide
|
||||
}
|
||||
} else {
|
||||
reader = sbomReader
|
||||
}
|
||||
}
|
||||
|
||||
return parseSyftJSON(reader)
|
||||
}
|
||||
|
||||
// partialSyftDoc is the final package shape for a select elements from a syft JSON document.
|
||||
type partialSyftDoc struct {
|
||||
Source syftJson.Source `json:"source"`
|
||||
Artifacts []partialSyftPackage `json:"artifacts"`
|
||||
Distro syftJson.Distribution `json:"distro"`
|
||||
}
|
||||
|
||||
// partialSyftPackage is the final package shape for a select elements from a syft JSON package.
|
||||
type partialSyftPackage struct {
|
||||
packageBasicMetadata
|
||||
packageCustomMetadata
|
||||
}
|
||||
|
||||
// packageBasicMetadata contains non-ambiguous values (type-wise) from pkg.Package.
|
||||
type packageBasicMetadata struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Type pkg.Type `json:"type"`
|
||||
Locations []source.Location `json:"locations"`
|
||||
Licenses []string `json:"licenses"`
|
||||
Language pkg.Language `json:"language"`
|
||||
CPEs []string `json:"cpes"`
|
||||
PURL string `json:"purl"`
|
||||
}
|
||||
|
||||
// packageCustomMetadata contains ambiguous values (type-wise) from pkg.Package.
|
||||
type packageCustomMetadata struct {
|
||||
MetadataType pkg.MetadataType `json:"metadataType"`
|
||||
Metadata interface{} `json:"metadata"`
|
||||
}
|
||||
|
||||
// packageMetadataUnpacker is all values needed from Package to disambiguate ambiguous fields during json unmarshaling.
|
||||
type packageMetadataUnpacker struct {
|
||||
MetadataType pkg.MetadataType `json:"metadataType"`
|
||||
Metadata json.RawMessage `json:"metadata"`
|
||||
}
|
||||
|
||||
// JavaMetadata encapsulates all Java ecosystem metadata for a package as well as an (optional) parent relationship.
|
||||
type partialSyftJavaMetadata struct {
|
||||
VirtualPath string `json:"virtualPath"`
|
||||
Manifest *partialSyftJavaManifest `mapstructure:"Manifest" json:"manifest,omitempty"`
|
||||
PomProperties *partialSyftPomProperties `mapstructure:"PomProperties" json:"pomProperties,omitempty"`
|
||||
}
|
||||
|
||||
// PomProperties represents the fields of interest extracted from a Java archive's pom.xml file.
|
||||
type partialSyftPomProperties struct {
|
||||
GroupID string `mapstructure:"groupId" json:"groupId"`
|
||||
ArtifactID string `mapstructure:"artifactId" json:"artifactId"`
|
||||
}
|
||||
|
||||
// JavaManifest represents the fields of interest extracted from a Java archive's META-INF/MANIFEST.MF file.
|
||||
type partialSyftJavaManifest struct {
|
||||
Main map[string]string `json:"main,omitempty"`
|
||||
}
|
||||
|
||||
// String returns the stringer representation for a syft package.
|
||||
func (p partialSyftPackage) String() string {
|
||||
return fmt.Sprintf("Pkg(type=%s, name=%s, version=%s)", p.Type, p.Name, p.Version)
|
||||
}
|
||||
|
||||
// UnmarshalJSON is a custom unmarshaller for handling basic values and values with ambiguous types.
|
||||
func (p *partialSyftPackage) UnmarshalJSON(b []byte) error {
|
||||
var basic packageBasicMetadata
|
||||
if err := json.Unmarshal(b, &basic); err != nil {
|
||||
return err
|
||||
}
|
||||
p.packageBasicMetadata = basic
|
||||
|
||||
var unpacker packageMetadataUnpacker
|
||||
if err := json.Unmarshal(b, &unpacker); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.MetadataType = unpacker.MetadataType
|
||||
|
||||
switch p.MetadataType {
|
||||
case pkg.RpmdbMetadataType:
|
||||
var payload RpmdbMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
p.Metadata = payload
|
||||
case pkg.DpkgMetadataType:
|
||||
var payload DpkgMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
p.Metadata = payload
|
||||
case pkg.JavaMetadataType:
|
||||
var partialPayload partialSyftJavaMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &partialPayload); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var artifact, group, name string
|
||||
if partialPayload.PomProperties != nil {
|
||||
artifact = partialPayload.PomProperties.ArtifactID
|
||||
group = partialPayload.PomProperties.GroupID
|
||||
}
|
||||
|
||||
if partialPayload.Manifest != nil {
|
||||
if n, ok := partialPayload.Manifest.Main["Name"]; ok {
|
||||
name = n
|
||||
}
|
||||
}
|
||||
|
||||
p.Metadata = JavaMetadata{
|
||||
PomArtifactID: artifact,
|
||||
PomGroupID: group,
|
||||
ManifestName: name,
|
||||
}
|
||||
case "":
|
||||
// there may be packages with no metadata, which is OK
|
||||
default:
|
||||
return fmt.Errorf("unsupported package metadata type: %+v", p.MetadataType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseSyftJson attempts to loosely parse the available JSON for only the fields needed, not the exact syft JSON shape.
|
||||
// This allows for some resiliency as the syft document shape changes over time (but not fool-proof).
|
||||
func parseSyftJSON(reader io.Reader) ([]Package, Context, error) {
|
||||
var doc partialSyftDoc
|
||||
decoder := json.NewDecoder(reader)
|
||||
if err := decoder.Decode(&doc); err != nil {
|
||||
return nil, Context{}, errDoesNotProvide
|
||||
}
|
||||
|
||||
var packages = make([]Package, len(doc.Artifacts))
|
||||
for i, a := range doc.Artifacts {
|
||||
cpes, err := cpe.NewSlice(a.CPEs...)
|
||||
if err != nil {
|
||||
return nil, Context{}, err
|
||||
}
|
||||
|
||||
packages[i] = Package{
|
||||
id: ID(i),
|
||||
Name: a.Name,
|
||||
Version: a.Version,
|
||||
Locations: a.Locations,
|
||||
Language: a.Language,
|
||||
Licenses: a.Licenses,
|
||||
Type: a.Type,
|
||||
CPEs: cpes,
|
||||
PURL: a.PURL,
|
||||
Metadata: a.Metadata,
|
||||
}
|
||||
}
|
||||
|
||||
var theDistro *distro.Distro
|
||||
if doc.Distro.Name != "" {
|
||||
d, err := distro.NewDistro(distro.Type(doc.Distro.Name), doc.Distro.Version, doc.Distro.IDLike)
|
||||
if err != nil {
|
||||
return nil, Context{}, err
|
||||
}
|
||||
theDistro = &d
|
||||
}
|
||||
|
||||
srcMetadata := doc.Source.ToSourceMetadata()
|
||||
|
||||
return packages, Context{
|
||||
Source: &srcMetadata,
|
||||
Distro: theDistro,
|
||||
}, nil
|
||||
}
|
160
grype/pkg/syft_json_provider_test.go
Normal file
160
grype/pkg/syft_json_provider_test.go
Normal file
|
@ -0,0 +1,160 @@
|
|||
package pkg
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/syft/syft/distro"
|
||||
|
||||
"github.com/go-test/deep"
|
||||
|
||||
"github.com/anchore/syft/syft/source"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
func must(c pkg.CPE, e error) pkg.CPE {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func TestParseSyftJSON(t *testing.T) {
|
||||
tests := []struct {
|
||||
Fixture string
|
||||
Packages []Package
|
||||
Context Context
|
||||
}{
|
||||
{
|
||||
Fixture: "test-fixtures/syft-alpine.json",
|
||||
Packages: []Package{
|
||||
{
|
||||
id: 0,
|
||||
Name: "alpine-baselayout",
|
||||
Version: "3.2.0-r6",
|
||||
Locations: []source.Location{
|
||||
{
|
||||
Path: "/lib/apk/db/installed",
|
||||
FileSystemID: "sha256:93cf4cfb673c7e16a9e74f731d6767b70b92a0b7c9f59d06efd72fbff535371c",
|
||||
},
|
||||
},
|
||||
Language: "",
|
||||
Licenses: []string{
|
||||
"GPL-2.0-only",
|
||||
},
|
||||
Type: "rpm",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:a:*:alpine-baselayout:3.2.0-r6:*:*:*:*:*:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r6:*:*:*:*:*:*:*")),
|
||||
},
|
||||
PURL: "pkg:alpine/alpine-baselayout@3.2.0-r6?arch=x86_64",
|
||||
Metadata: RpmdbMetadata{SourceRpm: "a-source.srpm"},
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
Name: "fake",
|
||||
Version: "1.2.0-r0",
|
||||
Locations: []source.Location{
|
||||
{
|
||||
Path: "/lib/apk/db/installed",
|
||||
FileSystemID: "sha256:93cf4cfb673c7e16a9e74f731d6767b70b92a0b7c9f59d06efd72fbff535371c",
|
||||
},
|
||||
},
|
||||
Language: "lang",
|
||||
Licenses: []string{
|
||||
"LGPL-3.0-or-later",
|
||||
},
|
||||
Type: "dpkg",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:a:*:gmp:6.2.0-r0:*:*:*:*:*:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:a:gmp:gmp:6.2.0-r0:*:*:*:*:*:*:*")),
|
||||
},
|
||||
PURL: "pkg:alpine/gmp@6.2.0-r0?arch=x86_64",
|
||||
Metadata: DpkgMetadata{Source: "a-source"},
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
Name: "gmp",
|
||||
Version: "6.2.0-r0",
|
||||
Locations: []source.Location{
|
||||
{
|
||||
Path: "/lib/apk/db/installed",
|
||||
FileSystemID: "sha256:93cf4cfb673c7e16a9e74f731d6767b70b92a0b7c9f59d06efd72fbff535371c",
|
||||
},
|
||||
},
|
||||
Language: "the-lang",
|
||||
Licenses: []string{
|
||||
"LGPL-3.0-or-later",
|
||||
},
|
||||
Type: "java-archive",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:a:*:gmp:6.2.0-r0:*:*:*:*:*:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:a:gmp:gmp:6.2.0-r0:*:*:*:*:*:*:*")),
|
||||
},
|
||||
PURL: "pkg:alpine/gmp@6.2.0-r0?arch=x86_64",
|
||||
Metadata: JavaMetadata{
|
||||
PomArtifactID: "aid",
|
||||
PomGroupID: "gid",
|
||||
ManifestName: "a-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
Context: Context{
|
||||
Source: &source.Metadata{
|
||||
Scheme: source.ImageScheme,
|
||||
ImageMetadata: source.ImageMetadata{
|
||||
UserInput: "alpine:fake",
|
||||
Scope: "Squashed",
|
||||
Layers: []source.LayerMetadata{
|
||||
{
|
||||
MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||
Digest: "sha256:50644c29ef5a27c9a40c393a73ece2479de78325cae7d762ef3cdc19bf42dd0a",
|
||||
Size: 5570176,
|
||||
},
|
||||
},
|
||||
Size: 15879684,
|
||||
ID: "sha256:fadf1294c09213b20d4d6fc84109584e1c102d185c2cae15144a87d29de65c6d",
|
||||
ManifestDigest: "sha256:1f6495428fb363e2d233e5df078b2b200635c4e51f0a3be34ecf09d44b547590",
|
||||
MediaType: "application/vnd.docker.distribution.manifest.v2+json",
|
||||
Tags: []string{
|
||||
"alpine:fake",
|
||||
},
|
||||
//RawManifest: []byte("eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjoyMTE2LCJkaWdlc3QiOiJzaGEyNTY6ZmFkZjEyOTRjMDkyMTNiMjBkNGQ2ZmM4NDEwOTU4NGUxYzEwMmQxODVjMmNhZTE1MTQ0YTg3ZDI5ZGU2NWM2ZCJ9LCJsYXllcnMiOlt7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjo1ODQ0OTkyLCJkaWdlc3QiOiJzaGEyNTY6NTA2NDRjMjllZjVhMjdjOWE0MGMzOTNhNzNlY2UyNDc5ZGU3ODMyNWNhZTdkNzYyZWYzY2RjMTliZjQyZGQwYSJ9LHsibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjE2NzkzNiwiZGlnZXN0Ijoic2hhMjU2OmNjMGZmMWRkYWQ2ZmU0OTc4ZDgzMjYzMGE5MzAzODgzYWRjNTZlZGZjNzdjYWEzNjkyMjM5YzJkODFjZjVkMDAifSx7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjoxMDE2Njc4NCwiZGlnZXN0Ijoic2hhMjU2OjNkZDJkYjQ4M2JjOWQ2YjU2MWNlNWNjMTEwNWUwYjZkMTk2MWNhMjQ5YTczNmJiYTgzNzFhYjI4ZWEzMDRmODQifSx7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjoyMjUyOCwiZGlnZXN0Ijoic2hhMjU2OjkzY2Y0Y2ZiNjczYzdlMTZhOWU3NGY3MzFkNjc2N2I3MGI5MmEwYjdjOWY1OWQwNmVmZDcyZmJmZjUzNTM3MWMifV19"),
|
||||
//RawConfig: []byte("eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJIb3N0bmFtZSI6IiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpbIi9iaW4vc2giXSwiQXJnc0VzY2FwZWQiOnRydWUsIkltYWdlIjoic2hhMjU2OjJjOWQ1MzNiMmI2NGFiMTI4MmFlYTE2ZGYwZjlkYmYwYjNjZDQ3YWMxZTAyYjc1YTM3NjNiMmY0M2NjOWRlNWUiLCJWb2x1bWVzIjpudWxsLCJXb3JraW5nRGlyIjoiIiwiRW50cnlwb2ludCI6bnVsbCwiT25CdWlsZCI6bnVsbCwiTGFiZWxzIjpudWxsfSwiY29udGFpbmVyIjoiYzJlMTM3OTEyYWU2MzdkNzBlMDJhMDVhYWEyM2U3N2JlY2I3Mzg5MDJmZDNjYWMyMjdkNDRlYjdlYzEwMmQ0OCIsImNvbnRhaW5lcl9jb25maWciOnsiSG9zdG5hbWUiOiIiLCJEb21haW5uYW1lIjoiIiwiVXNlciI6IiIsIkF0dGFjaFN0ZGluIjpmYWxzZSwiQXR0YWNoU3Rkb3V0IjpmYWxzZSwiQXR0YWNoU3RkZXJyIjpmYWxzZSwiVHR5IjpmYWxzZSwiT3BlblN0ZGluIjpmYWxzZSwiU3RkaW5PbmNlIjpmYWxzZSwiRW52IjpbIlBBVEg9L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluIl0sIkNtZCI6WyIvYmluL3NoIiwiLWMiLCJzZWQgLWkgJ3MvVjowLjkuMTEtcjMvVjowLjkuOS1yMC8nIC9saWIvYXBrL2RiL2luc3RhbGxlZCJdLCJJbWFnZSI6InNoYTI1NjoyYzlkNTMzYjJiNjRhYjEyODJhZWExNmRmMGY5ZGJmMGIzY2Q0N2FjMWUwMmI3NWEzNzYzYjJmNDNjYzlkZTVlIiwiVm9sdW1lcyI6bnVsbCwiV29ya2luZ0RpciI6IiIsIkVudHJ5cG9pbnQiOm51bGwsIk9uQnVpbGQiOm51bGwsIkxhYmVscyI6bnVsbH0sImNyZWF0ZWQiOiIyMDIwLTA5LTI0VDIyOjI2OjQ2LjE2NzYxOTRaIiwiZG9ja2VyX3ZlcnNpb24iOiIxOS4wMy4xMiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDIwLTA1LTI5VDIxOjE5OjQ2LjE5MjA0NTk3MloiLCJjcmVhdGVkX2J5IjoiL2Jpbi9zaCAtYyAjKG5vcCkgQUREIGZpbGU6YzkyYzI0ODIzOWY4YzdiOWIzYzA2NzY1MDk1NDgxNWYzOTFiN2JjYjA5MDIzZjk4NDk3MmMwODJhY2UyYThkMCBpbiAvICJ9LHsiY3JlYXRlZCI6IjIwMjAtMDUtMjlUMjE6MTk6NDYuMzYzNTE4MzQ1WiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jICMobm9wKSAgQ01EIFtcIi9iaW4vc2hcIl0iLCJlbXB0eV9sYXllciI6dHJ1ZX0seyJjcmVhdGVkIjoiMjAyMC0wOS0yNFQyMjoyNjo0NC4zMjk1NTc4WiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jIHdnZXQgaHR0cDovL2RsLWNkbi5hbHBpbmVsaW51eC5vcmcvYWxwaW5lL3YzLjkvbWFpbi94ODZfNjQvbGlidm5jc2VydmVyLTAuOS4xMS1yMy5hcGsifSx7ImNyZWF0ZWQiOiIyMDIwLTA5LTI0VDIyOjI2OjQ1LjY3MDg1MzhaIiwiY3JlYXRlZF9ieSI6Ii9iaW4vc2ggLWMgYXBrIGFkZCAgbGlidm5jc2VydmVyLTAuOS4xMS1yMy5hcGsifSx7ImNyZWF0ZWQiOiIyMDIwLTA5LTI0VDIyOjI2OjQ2LjE2NzYxOTRaIiwiY3JlYXRlZF9ieSI6Ii9iaW4vc2ggLWMgc2VkIC1pICdzL1Y6MC45LjExLXIzL1Y6MC45LjktcjAvJyAvbGliL2Fway9kYi9pbnN0YWxsZWQifV0sIm9zIjoibGludXgiLCJyb290ZnMiOnsidHlwZSI6ImxheWVycyIsImRpZmZfaWRzIjpbInNoYTI1Njo1MDY0NGMyOWVmNWEyN2M5YTQwYzM5M2E3M2VjZTI0NzlkZTc4MzI1Y2FlN2Q3NjJlZjNjZGMxOWJmNDJkZDBhIiwic2hhMjU2OmNjMGZmMWRkYWQ2ZmU0OTc4ZDgzMjYzMGE5MzAzODgzYWRjNTZlZGZjNzdjYWEzNjkyMjM5YzJkODFjZjVkMDAiLCJzaGEyNTY6M2RkMmRiNDgzYmM5ZDZiNTYxY2U1Y2MxMTA1ZTBiNmQxOTYxY2EyNDlhNzM2YmJhODM3MWFiMjhlYTMwNGY4NCIsInNoYTI1Njo5M2NmNGNmYjY3M2M3ZTE2YTllNzRmNzMxZDY3NjdiNzBiOTJhMGI3YzlmNTlkMDZlZmQ3MmZiZmY1MzUzNzFjIl19fQ=="),
|
||||
},
|
||||
Path: "",
|
||||
},
|
||||
Distro: func() *distro.Distro {
|
||||
d, _ := distro.NewDistro(distro.Alpine, "3.12.0", "")
|
||||
return &d
|
||||
}(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.Fixture, func(t *testing.T) {
|
||||
fh, err := os.Open(test.Fixture)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open fixture: %+v", err)
|
||||
}
|
||||
|
||||
pkgs, context, err := parseSyftJSON(fh)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse: %+v", err)
|
||||
}
|
||||
|
||||
context.Source.ImageMetadata.RawConfig = nil
|
||||
context.Source.ImageMetadata.RawManifest = nil
|
||||
|
||||
for _, d := range deep.Equal(test.Packages, pkgs) {
|
||||
t.Errorf("pkg diff: %s", d)
|
||||
}
|
||||
|
||||
for _, d := range deep.Equal(test.Context, context) {
|
||||
t.Errorf("ctx diff: %s", d)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
21
grype/pkg/syft_provider.go
Normal file
21
grype/pkg/syft_provider.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package pkg
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft"
|
||||
)
|
||||
|
||||
func syftProvider(config providerConfig) ([]Package, Context, error) {
|
||||
if config.scopeOpt == nil {
|
||||
return nil, Context{}, errDoesNotProvide
|
||||
}
|
||||
|
||||
theSource, catalog, theDistro, err := syft.Catalog(config.userInput, *config.scopeOpt)
|
||||
if err != nil {
|
||||
return nil, Context{}, err
|
||||
}
|
||||
|
||||
return FromCatalog(catalog), Context{
|
||||
Source: &theSource.Metadata,
|
||||
Distro: theDistro,
|
||||
}, nil
|
||||
}
|
521
grype/pkg/test-fixtures/syft-alpine.json
Normal file
521
grype/pkg/test-fixtures/syft-alpine.json
Normal file
|
@ -0,0 +1,521 @@
|
|||
{
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "alpine-baselayout",
|
||||
"version": "3.2.0-r6",
|
||||
"type": "rpm",
|
||||
"foundBy": "apkdb-cataloger",
|
||||
"locations": [
|
||||
{
|
||||
"path": "/lib/apk/db/installed",
|
||||
"layerID": "sha256:93cf4cfb673c7e16a9e74f731d6767b70b92a0b7c9f59d06efd72fbff535371c"
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
"GPL-2.0-only"
|
||||
],
|
||||
"language": "",
|
||||
"cpes": [
|
||||
"cpe:2.3:a:*:alpine-baselayout:3.2.0-r6:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r6:*:*:*:*:*:*:*"
|
||||
],
|
||||
"purl": "pkg:alpine/alpine-baselayout@3.2.0-r6?arch=x86_64",
|
||||
"metadataType": "RpmdbMetadata",
|
||||
"metadata": {
|
||||
"sourceRpm": "a-source.srpm",
|
||||
"package": "alpine-baselayout",
|
||||
"originPackage": "alpine-baselayout",
|
||||
"maintainer": "Natanael Copa <ncopa@alpinelinux.org>",
|
||||
"version": "3.2.0-r6",
|
||||
"license": "GPL-2.0-only",
|
||||
"architecture": "x86_64",
|
||||
"url": "https://git.alpinelinux.org/cgit/aports/tree/main/alpine-baselayout",
|
||||
"description": "Alpine base dir structure and init scripts",
|
||||
"size": 19917,
|
||||
"installedSize": 409600,
|
||||
"pullDependencies": "/bin/sh so:libc.musl-x86_64.so.1",
|
||||
"pullChecksum": "Q1myMNfd7u5v5UTgNHeq1e31qTjZU=",
|
||||
"gitCommitOfApkPort": "e1c51734fa96fa4bac92e9f14a474324c67916fc",
|
||||
"files": [
|
||||
{
|
||||
"path": "/dev"
|
||||
},
|
||||
{
|
||||
"path": "/dev/pts"
|
||||
},
|
||||
{
|
||||
"path": "/dev/shm"
|
||||
},
|
||||
{
|
||||
"path": "/etc"
|
||||
},
|
||||
{
|
||||
"path": "/etc/fstab",
|
||||
"checksum": "Q11Q7hNe8QpDS531guqCdrXBzoA/o="
|
||||
},
|
||||
{
|
||||
"path": "/etc/group",
|
||||
"checksum": "Q1oJ16xWudgKOrXIEquEDzlF2Lsm4="
|
||||
},
|
||||
{
|
||||
"path": "/etc/hostname",
|
||||
"checksum": "Q16nVwYVXP/tChvUPdukVD2ifXOmc="
|
||||
},
|
||||
{
|
||||
"path": "/etc/hosts",
|
||||
"checksum": "Q1BD6zJKZTRWyqGnPi4tSfd3krsMU="
|
||||
},
|
||||
{
|
||||
"path": "/etc/inittab",
|
||||
"checksum": "Q1TsthbhW7QzWRe1E/NKwTOuD4pHc="
|
||||
},
|
||||
{
|
||||
"path": "/etc/modules",
|
||||
"checksum": "Q1toogjUipHGcMgECgPJX64SwUT1M="
|
||||
},
|
||||
{
|
||||
"path": "/etc/motd",
|
||||
"checksum": "Q1XmduVVNURHQ27TvYp1Lr5TMtFcA="
|
||||
},
|
||||
{
|
||||
"path": "/etc/mtab",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "777",
|
||||
"checksum": "Q1kiljhXXH1LlQroHsEJIkPZg2eiw="
|
||||
},
|
||||
{
|
||||
"path": "/etc/passwd",
|
||||
"checksum": "Q1TchuuLUfur0izvfZQZxgN/LJhB8="
|
||||
},
|
||||
{
|
||||
"path": "/etc/profile",
|
||||
"checksum": "Q1KpFb8kl5LvwXWlY3e58FNsjrI34="
|
||||
},
|
||||
{
|
||||
"path": "/etc/protocols",
|
||||
"checksum": "Q13FqXUnvuOpMDrH/6rehxuYAEE34="
|
||||
},
|
||||
{
|
||||
"path": "/etc/services",
|
||||
"checksum": "Q1C6HJNgQvLWqt5VY+n7MZJ1rsDuY="
|
||||
},
|
||||
{
|
||||
"path": "/etc/shadow",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "42",
|
||||
"permissions": "640",
|
||||
"checksum": "Q1ltrPIAW2zHeDiajsex2Bdmq3uqA="
|
||||
},
|
||||
{
|
||||
"path": "/etc/shells",
|
||||
"checksum": "Q1ojm2YdpCJ6B/apGDaZ/Sdb2xJkA="
|
||||
},
|
||||
{
|
||||
"path": "/etc/sysctl.conf",
|
||||
"checksum": "Q14upz3tfnNxZkIEsUhWn7Xoiw96g="
|
||||
},
|
||||
{
|
||||
"path": "/etc/apk"
|
||||
},
|
||||
{
|
||||
"path": "/etc/conf.d"
|
||||
},
|
||||
{
|
||||
"path": "/etc/crontabs"
|
||||
},
|
||||
{
|
||||
"path": "/etc/crontabs/root",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "600",
|
||||
"checksum": "Q1vfk1apUWI4yLJGhhNRd0kJixfvY="
|
||||
},
|
||||
{
|
||||
"path": "/etc/init.d"
|
||||
},
|
||||
{
|
||||
"path": "/etc/modprobe.d"
|
||||
},
|
||||
{
|
||||
"path": "/etc/modprobe.d/aliases.conf",
|
||||
"checksum": "Q1WUbh6TBYNVK7e4Y+uUvLs/7viqk="
|
||||
},
|
||||
{
|
||||
"path": "/etc/modprobe.d/blacklist.conf",
|
||||
"checksum": "Q1xxYGU6S6TLQvb7ervPrWWwAWqMg="
|
||||
},
|
||||
{
|
||||
"path": "/etc/modprobe.d/i386.conf",
|
||||
"checksum": "Q1pnay/njn6ol9cCssL7KiZZ8etlc="
|
||||
},
|
||||
{
|
||||
"path": "/etc/modprobe.d/kms.conf",
|
||||
"checksum": "Q1ynbLn3GYDpvajba/ldp1niayeog="
|
||||
},
|
||||
{
|
||||
"path": "/etc/modules-load.d"
|
||||
},
|
||||
{
|
||||
"path": "/etc/network"
|
||||
},
|
||||
{
|
||||
"path": "/etc/network/if-down.d"
|
||||
},
|
||||
{
|
||||
"path": "/etc/network/if-post-down.d"
|
||||
},
|
||||
{
|
||||
"path": "/etc/network/if-pre-up.d"
|
||||
},
|
||||
{
|
||||
"path": "/etc/network/if-up.d"
|
||||
},
|
||||
{
|
||||
"path": "/etc/opt"
|
||||
},
|
||||
{
|
||||
"path": "/etc/periodic"
|
||||
},
|
||||
{
|
||||
"path": "/etc/periodic/15min"
|
||||
},
|
||||
{
|
||||
"path": "/etc/periodic/daily"
|
||||
},
|
||||
{
|
||||
"path": "/etc/periodic/hourly"
|
||||
},
|
||||
{
|
||||
"path": "/etc/periodic/monthly"
|
||||
},
|
||||
{
|
||||
"path": "/etc/periodic/weekly"
|
||||
},
|
||||
{
|
||||
"path": "/etc/profile.d"
|
||||
},
|
||||
{
|
||||
"path": "/etc/profile.d/color_prompt",
|
||||
"checksum": "Q10wL23GuSCVfumMRgakabUI6EsSk="
|
||||
},
|
||||
{
|
||||
"path": "/etc/profile.d/locale",
|
||||
"checksum": "Q1R4bIEpnKxxOSrlnZy9AoawqZ5DU="
|
||||
},
|
||||
{
|
||||
"path": "/etc/sysctl.d"
|
||||
},
|
||||
{
|
||||
"path": "/home"
|
||||
},
|
||||
{
|
||||
"path": "/lib"
|
||||
},
|
||||
{
|
||||
"path": "/lib/firmware"
|
||||
},
|
||||
{
|
||||
"path": "/lib/mdev"
|
||||
},
|
||||
{
|
||||
"path": "/lib/modules-load.d"
|
||||
},
|
||||
{
|
||||
"path": "/lib/sysctl.d"
|
||||
},
|
||||
{
|
||||
"path": "/lib/sysctl.d/00-alpine.conf",
|
||||
"checksum": "Q1HpElzW1xEgmKfERtTy7oommnq6c="
|
||||
},
|
||||
{
|
||||
"path": "/media"
|
||||
},
|
||||
{
|
||||
"path": "/media/cdrom"
|
||||
},
|
||||
{
|
||||
"path": "/media/floppy"
|
||||
},
|
||||
{
|
||||
"path": "/media/usb"
|
||||
},
|
||||
{
|
||||
"path": "/mnt"
|
||||
},
|
||||
{
|
||||
"path": "/opt"
|
||||
},
|
||||
{
|
||||
"path": "/proc"
|
||||
},
|
||||
{
|
||||
"path": "/root",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "700"
|
||||
},
|
||||
{
|
||||
"path": "/run"
|
||||
},
|
||||
{
|
||||
"path": "/sbin"
|
||||
},
|
||||
{
|
||||
"path": "/sbin/mkmntdirs",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "755",
|
||||
"checksum": "Q1YeuSmC7iDbEWrusPzA/zUQF6YSg="
|
||||
},
|
||||
{
|
||||
"path": "/srv"
|
||||
},
|
||||
{
|
||||
"path": "/sys"
|
||||
},
|
||||
{
|
||||
"path": "/tmp",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "1777"
|
||||
},
|
||||
{
|
||||
"path": "/usr"
|
||||
},
|
||||
{
|
||||
"path": "/usr/lib"
|
||||
},
|
||||
{
|
||||
"path": "/usr/lib/modules-load.d"
|
||||
},
|
||||
{
|
||||
"path": "/usr/local"
|
||||
},
|
||||
{
|
||||
"path": "/usr/local/bin"
|
||||
},
|
||||
{
|
||||
"path": "/usr/local/lib"
|
||||
},
|
||||
{
|
||||
"path": "/usr/local/share"
|
||||
},
|
||||
{
|
||||
"path": "/usr/sbin"
|
||||
},
|
||||
{
|
||||
"path": "/usr/share"
|
||||
},
|
||||
{
|
||||
"path": "/usr/share/man"
|
||||
},
|
||||
{
|
||||
"path": "/usr/share/misc"
|
||||
},
|
||||
{
|
||||
"path": "/var"
|
||||
},
|
||||
{
|
||||
"path": "/var/run",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "777",
|
||||
"checksum": "Q11/SNZz/8cK2dSKK+cJpVrZIuF4Q="
|
||||
},
|
||||
{
|
||||
"path": "/var/cache"
|
||||
},
|
||||
{
|
||||
"path": "/var/cache/misc"
|
||||
},
|
||||
{
|
||||
"path": "/var/empty",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "555"
|
||||
},
|
||||
{
|
||||
"path": "/var/lib"
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/misc"
|
||||
},
|
||||
{
|
||||
"path": "/var/local"
|
||||
},
|
||||
{
|
||||
"path": "/var/lock"
|
||||
},
|
||||
{
|
||||
"path": "/var/lock/subsys"
|
||||
},
|
||||
{
|
||||
"path": "/var/log"
|
||||
},
|
||||
{
|
||||
"path": "/var/mail"
|
||||
},
|
||||
{
|
||||
"path": "/var/opt"
|
||||
},
|
||||
{
|
||||
"path": "/var/spool"
|
||||
},
|
||||
{
|
||||
"path": "/var/spool/mail",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "777",
|
||||
"checksum": "Q1dzbdazYZA2nTzSIG3YyNw7d4Juc="
|
||||
},
|
||||
{
|
||||
"path": "/var/spool/cron"
|
||||
},
|
||||
{
|
||||
"path": "/var/spool/cron/crontabs",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "777",
|
||||
"checksum": "Q1OFZt+ZMp7j0Gny0rqSKuWJyqYmA="
|
||||
},
|
||||
{
|
||||
"path": "/var/tmp",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "1777"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "fake",
|
||||
"version": "1.2.0-r0",
|
||||
"type": "dpkg",
|
||||
"foundBy": "apkdb-cataloger",
|
||||
"locations": [
|
||||
{
|
||||
"path": "/lib/apk/db/installed",
|
||||
"layerID": "sha256:93cf4cfb673c7e16a9e74f731d6767b70b92a0b7c9f59d06efd72fbff535371c"
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
"LGPL-3.0-or-later"
|
||||
],
|
||||
"language": "lang",
|
||||
"cpes": [
|
||||
"cpe:2.3:a:*:gmp:6.2.0-r0:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:gmp:gmp:6.2.0-r0:*:*:*:*:*:*:*"
|
||||
],
|
||||
"purl": "pkg:alpine/gmp@6.2.0-r0?arch=x86_64",
|
||||
"metadataType": "DpkgMetadata",
|
||||
"metadata": {
|
||||
"source": "a-source"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "gmp",
|
||||
"version": "6.2.0-r0",
|
||||
"type": "java-archive",
|
||||
"foundBy": "apkdb-cataloger",
|
||||
"locations": [
|
||||
{
|
||||
"path": "/lib/apk/db/installed",
|
||||
"layerID": "sha256:93cf4cfb673c7e16a9e74f731d6767b70b92a0b7c9f59d06efd72fbff535371c"
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
"LGPL-3.0-or-later"
|
||||
],
|
||||
"language": "the-lang",
|
||||
"cpes": [
|
||||
"cpe:2.3:a:*:gmp:6.2.0-r0:*:*:*:*:*:*:*",
|
||||
"cpe:2.3:a:gmp:gmp:6.2.0-r0:*:*:*:*:*:*:*"
|
||||
],
|
||||
"purl": "pkg:alpine/gmp@6.2.0-r0?arch=x86_64",
|
||||
"metadataType": "JavaMetadata",
|
||||
"metadata": {
|
||||
"pomProperties": {
|
||||
"groupId": "gid",
|
||||
"artifactId": "aid"
|
||||
},
|
||||
"manifest": {
|
||||
"main": {
|
||||
"Name": "a-name"
|
||||
}
|
||||
},
|
||||
"package": "gmp",
|
||||
"originPackage": "gmp",
|
||||
"maintainer": "Natanael Copa <ncopa@alpinelinux.org>",
|
||||
"version": "6.2.0-r0",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"architecture": "x86_64",
|
||||
"url": "https://gmplib.org/",
|
||||
"description": "A free library for arbitrary precision arithmetic",
|
||||
"size": 220040,
|
||||
"installedSize": 430080,
|
||||
"pullDependencies": "so:libc.musl-x86_64.so.1",
|
||||
"pullChecksum": "Q1IdUBW9Q7DiKxqItRI93JTPsylgg=",
|
||||
"gitCommitOfApkPort": "238b6bccbab3b844079fa109d5cee096b81756d3",
|
||||
"files": [
|
||||
{
|
||||
"path": "/usr"
|
||||
},
|
||||
{
|
||||
"path": "/usr/lib"
|
||||
},
|
||||
{
|
||||
"path": "/usr/lib/libgmp.so.10",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "777",
|
||||
"checksum": "Q15mdJR0bVgCzxA6EspemNzt2PxJ0="
|
||||
},
|
||||
{
|
||||
"path": "/usr/lib/libgmp.so.10.4.0",
|
||||
"ownerUid": "0",
|
||||
"ownerGid": "0",
|
||||
"permissions": "755",
|
||||
"checksum": "Q1hT4sjrKisl0oLyq41UhDM+5q2Z4="
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"source": {
|
||||
"type": "image",
|
||||
"target": {
|
||||
"userInput": "alpine:fake",
|
||||
"imageID": "sha256:fadf1294c09213b20d4d6fc84109584e1c102d185c2cae15144a87d29de65c6d",
|
||||
"manifestDigest": "sha256:1f6495428fb363e2d233e5df078b2b200635c4e51f0a3be34ecf09d44b547590",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"tags": [
|
||||
"alpine:fake"
|
||||
],
|
||||
"imageSize": 15879684,
|
||||
"scope": "Squashed",
|
||||
"layers": [
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||
"digest": "sha256:50644c29ef5a27c9a40c393a73ece2479de78325cae7d762ef3cdc19bf42dd0a",
|
||||
"size": 5570176
|
||||
}
|
||||
],
|
||||
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjoyMTE2LCJkaWdlc3QiOiJzaGEyNTY6ZmFkZjEyOTRjMDkyMTNiMjBkNGQ2ZmM4NDEwOTU4NGUxYzEwMmQxODVjMmNhZTE1MTQ0YTg3ZDI5ZGU2NWM2ZCJ9LCJsYXllcnMiOlt7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjo1ODQ0OTkyLCJkaWdlc3QiOiJzaGEyNTY6NTA2NDRjMjllZjVhMjdjOWE0MGMzOTNhNzNlY2UyNDc5ZGU3ODMyNWNhZTdkNzYyZWYzY2RjMTliZjQyZGQwYSJ9LHsibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjE2NzkzNiwiZGlnZXN0Ijoic2hhMjU2OmNjMGZmMWRkYWQ2ZmU0OTc4ZDgzMjYzMGE5MzAzODgzYWRjNTZlZGZjNzdjYWEzNjkyMjM5YzJkODFjZjVkMDAifSx7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjoxMDE2Njc4NCwiZGlnZXN0Ijoic2hhMjU2OjNkZDJkYjQ4M2JjOWQ2YjU2MWNlNWNjMTEwNWUwYjZkMTk2MWNhMjQ5YTczNmJiYTgzNzFhYjI4ZWEzMDRmODQifSx7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjoyMjUyOCwiZGlnZXN0Ijoic2hhMjU2OjkzY2Y0Y2ZiNjczYzdlMTZhOWU3NGY3MzFkNjc2N2I3MGI5MmEwYjdjOWY1OWQwNmVmZDcyZmJmZjUzNTM3MWMifV19",
|
||||
"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJIb3N0bmFtZSI6IiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpbIi9iaW4vc2giXSwiQXJnc0VzY2FwZWQiOnRydWUsIkltYWdlIjoic2hhMjU2OjJjOWQ1MzNiMmI2NGFiMTI4MmFlYTE2ZGYwZjlkYmYwYjNjZDQ3YWMxZTAyYjc1YTM3NjNiMmY0M2NjOWRlNWUiLCJWb2x1bWVzIjpudWxsLCJXb3JraW5nRGlyIjoiIiwiRW50cnlwb2ludCI6bnVsbCwiT25CdWlsZCI6bnVsbCwiTGFiZWxzIjpudWxsfSwiY29udGFpbmVyIjoiYzJlMTM3OTEyYWU2MzdkNzBlMDJhMDVhYWEyM2U3N2JlY2I3Mzg5MDJmZDNjYWMyMjdkNDRlYjdlYzEwMmQ0OCIsImNvbnRhaW5lcl9jb25maWciOnsiSG9zdG5hbWUiOiIiLCJEb21haW5uYW1lIjoiIiwiVXNlciI6IiIsIkF0dGFjaFN0ZGluIjpmYWxzZSwiQXR0YWNoU3Rkb3V0IjpmYWxzZSwiQXR0YWNoU3RkZXJyIjpmYWxzZSwiVHR5IjpmYWxzZSwiT3BlblN0ZGluIjpmYWxzZSwiU3RkaW5PbmNlIjpmYWxzZSwiRW52IjpbIlBBVEg9L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluIl0sIkNtZCI6WyIvYmluL3NoIiwiLWMiLCJzZWQgLWkgJ3MvVjowLjkuMTEtcjMvVjowLjkuOS1yMC8nIC9saWIvYXBrL2RiL2luc3RhbGxlZCJdLCJJbWFnZSI6InNoYTI1NjoyYzlkNTMzYjJiNjRhYjEyODJhZWExNmRmMGY5ZGJmMGIzY2Q0N2FjMWUwMmI3NWEzNzYzYjJmNDNjYzlkZTVlIiwiVm9sdW1lcyI6bnVsbCwiV29ya2luZ0RpciI6IiIsIkVudHJ5cG9pbnQiOm51bGwsIk9uQnVpbGQiOm51bGwsIkxhYmVscyI6bnVsbH0sImNyZWF0ZWQiOiIyMDIwLTA5LTI0VDIyOjI2OjQ2LjE2NzYxOTRaIiwiZG9ja2VyX3ZlcnNpb24iOiIxOS4wMy4xMiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDIwLTA1LTI5VDIxOjE5OjQ2LjE5MjA0NTk3MloiLCJjcmVhdGVkX2J5IjoiL2Jpbi9zaCAtYyAjKG5vcCkgQUREIGZpbGU6YzkyYzI0ODIzOWY4YzdiOWIzYzA2NzY1MDk1NDgxNWYzOTFiN2JjYjA5MDIzZjk4NDk3MmMwODJhY2UyYThkMCBpbiAvICJ9LHsiY3JlYXRlZCI6IjIwMjAtMDUtMjlUMjE6MTk6NDYuMzYzNTE4MzQ1WiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jICMobm9wKSAgQ01EIFtcIi9iaW4vc2hcIl0iLCJlbXB0eV9sYXllciI6dHJ1ZX0seyJjcmVhdGVkIjoiMjAyMC0wOS0yNFQyMjoyNjo0NC4zMjk1NTc4WiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jIHdnZXQgaHR0cDovL2RsLWNkbi5hbHBpbmVsaW51eC5vcmcvYWxwaW5lL3YzLjkvbWFpbi94ODZfNjQvbGlidm5jc2VydmVyLTAuOS4xMS1yMy5hcGsifSx7ImNyZWF0ZWQiOiIyMDIwLTA5LTI0VDIyOjI2OjQ1LjY3MDg1MzhaIiwiY3JlYXRlZF9ieSI6Ii9iaW4vc2ggLWMgYXBrIGFkZCAgbGlidm5jc2VydmVyLTAuOS4xMS1yMy5hcGsifSx7ImNyZWF0ZWQiOiIyMDIwLTA5LTI0VDIyOjI2OjQ2LjE2NzYxOTRaIiwiY3JlYXRlZF9ieSI6Ii9iaW4vc2ggLWMgc2VkIC1pICdzL1Y6MC45LjExLXIzL1Y6MC45LjktcjAvJyAvbGliL2Fway9kYi9pbnN0YWxsZWQifV0sIm9zIjoibGludXgiLCJyb290ZnMiOnsidHlwZSI6ImxheWVycyIsImRpZmZfaWRzIjpbInNoYTI1Njo1MDY0NGMyOWVmNWEyN2M5YTQwYzM5M2E3M2VjZTI0NzlkZTc4MzI1Y2FlN2Q3NjJlZjNjZGMxOWJmNDJkZDBhIiwic2hhMjU2OmNjMGZmMWRkYWQ2ZmU0OTc4ZDgzMjYzMGE5MzAzODgzYWRjNTZlZGZjNzdjYWEzNjkyMjM5YzJkODFjZjVkMDAiLCJzaGEyNTY6M2RkMmRiNDgzYmM5ZDZiNTYxY2U1Y2MxMTA1ZTBiNmQxOTYxY2EyNDlhNzM2YmJhODM3MWFiMjhlYTMwNGY4NCIsInNoYTI1Njo5M2NmNGNmYjY3M2M3ZTE2YTllNzRmNzMxZDY3NjdiNzBiOTJhMGI3YzlmNTlkMDZlZmQ3MmZiZmY1MzUzNzFjIl19fQ=="
|
||||
}
|
||||
},
|
||||
"distro": {
|
||||
"name": "alpine",
|
||||
"version": "3.12.0",
|
||||
"idLike": ""
|
||||
},
|
||||
"descriptor": {
|
||||
"name": "syft",
|
||||
"version": "[not provided]"
|
||||
},
|
||||
"schema": {
|
||||
"version": "1.0.0",
|
||||
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-1.0.0.json"
|
||||
}
|
||||
}
|
|
@ -28,15 +28,18 @@ type Document struct {
|
|||
}
|
||||
|
||||
// NewDocument returns a CycloneDX Document object populated with the SBOM and vulnerability findings.
|
||||
func NewDocument(packages []pkg.Package, matches match.Matches, srcMetadata source.Metadata, provider vulnerability.MetadataProvider) (Document, error) {
|
||||
func NewDocument(packages []pkg.Package, matches match.Matches, srcMetadata *source.Metadata, provider vulnerability.MetadataProvider) (Document, error) {
|
||||
versionInfo := version.FromBuild()
|
||||
|
||||
doc := Document{
|
||||
XMLNs: "http://cyclonedx.org/schema/bom/1.2",
|
||||
XMLNsV: "http://cyclonedx.org/schema/ext/vulnerability/1.0",
|
||||
Version: 1,
|
||||
SerialNumber: uuid.New().URN(),
|
||||
BomDescriptor: syftCDX.NewBomDescriptor(internal.ApplicationName, versionInfo.Version, srcMetadata),
|
||||
XMLNs: "http://cyclonedx.org/schema/bom/1.2",
|
||||
XMLNsV: "http://cyclonedx.org/schema/ext/vulnerability/1.0",
|
||||
Version: 1,
|
||||
SerialNumber: uuid.New().URN(),
|
||||
}
|
||||
|
||||
if srcMetadata != nil {
|
||||
doc.BomDescriptor = syftCDX.NewBomDescriptor(internal.ApplicationName, versionInfo.Version, *srcMetadata)
|
||||
}
|
||||
|
||||
// attach matches
|
||||
|
|
|
@ -14,12 +14,12 @@ import (
|
|||
type Presenter struct {
|
||||
results match.Matches
|
||||
packages []pkg.Package
|
||||
srcMetadata source.Metadata
|
||||
srcMetadata *source.Metadata
|
||||
metadataProvider vulnerability.MetadataProvider
|
||||
}
|
||||
|
||||
// NewPresenter is a *Presenter constructor
|
||||
func NewPresenter(results match.Matches, packages []pkg.Package, srcMetadata source.Metadata, metadataProvider vulnerability.MetadataProvider) *Presenter {
|
||||
func NewPresenter(results match.Matches, packages []pkg.Package, srcMetadata *source.Metadata, metadataProvider vulnerability.MetadataProvider) *Presenter {
|
||||
return &Presenter{
|
||||
results: results,
|
||||
packages: packages,
|
||||
|
|
|
@ -130,9 +130,9 @@ func TestCycloneDxPresenterImage(t *testing.T) {
|
|||
// testing. At that time, this line will no longer be necessary.
|
||||
//
|
||||
// This value is sourced from the "version" node in "./test-fixtures/snapshot/TestCycloneDxImgsPresenter.golden"
|
||||
s.Metadata.ImageMetadata.Digest = "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368"
|
||||
s.Metadata.ImageMetadata.ManifestDigest = "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368"
|
||||
|
||||
pres := NewPresenter(matches, packages, s.Metadata, newMetadataMock())
|
||||
pres := NewPresenter(matches, packages, &s.Metadata, newMetadataMock())
|
||||
// run presenter
|
||||
err = pres.Present(&buffer)
|
||||
if err != nil {
|
||||
|
@ -167,7 +167,7 @@ func TestCycloneDxPresenterDir(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pres := NewPresenter(matches, packages, s.Metadata, newMetadataMock())
|
||||
pres := NewPresenter(matches, packages, &s.Metadata, newMetadataMock())
|
||||
|
||||
// run presenter
|
||||
err = pres.Present(&buffer)
|
||||
|
|
|
@ -8,15 +8,13 @@ import (
|
|||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/grype/internal"
|
||||
"github.com/anchore/grype/internal/version"
|
||||
"github.com/anchore/syft/syft/distro"
|
||||
syftJson "github.com/anchore/syft/syft/presenter/json"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
// Document represents the JSON document to be presented
|
||||
type Document struct {
|
||||
Matches []Match `json:"matches"`
|
||||
Source syftJson.Source `json:"source"`
|
||||
Source *syftJson.Source `json:"source"`
|
||||
Distro syftJson.Distribution `json:"distro"`
|
||||
Descriptor Descriptor `json:"descriptor"`
|
||||
}
|
||||
|
@ -36,7 +34,7 @@ type MatchDetails struct {
|
|||
}
|
||||
|
||||
// NewDocument creates and populates a new Document struct, representing the populated JSON document.
|
||||
func NewDocument(packages []pkg.Package, d *distro.Distro, srcMetadata source.Metadata, matches match.Matches, metadataProvider vulnerability.MetadataProvider) (Document, error) {
|
||||
func NewDocument(packages []pkg.Package, context pkg.Context, matches match.Matches, metadataProvider vulnerability.MetadataProvider) (Document, error) {
|
||||
// we must preallocate the findings to ensure the JSON document does not show "null" when no matches are found
|
||||
var findings = make([]Match, 0)
|
||||
for m := range matches.Enumerate() {
|
||||
|
@ -64,15 +62,19 @@ func NewDocument(packages []pkg.Package, d *distro.Distro, srcMetadata source.Me
|
|||
)
|
||||
}
|
||||
|
||||
src, err := syftJson.NewSource(srcMetadata)
|
||||
if err != nil {
|
||||
return Document{}, err
|
||||
var src *syftJson.Source
|
||||
if context.Source != nil {
|
||||
theSrc, err := syftJson.NewSource(*context.Source)
|
||||
if err != nil {
|
||||
return Document{}, err
|
||||
}
|
||||
src = &theSrc
|
||||
}
|
||||
|
||||
return Document{
|
||||
Matches: findings,
|
||||
Source: src,
|
||||
Distro: syftJson.NewDistribution(d),
|
||||
Distro: syftJson.NewDistribution(context.Distro),
|
||||
Descriptor: Descriptor{
|
||||
Name: internal.ApplicationName,
|
||||
Version: version.FromBuild().Version,
|
||||
|
|
|
@ -7,33 +7,29 @@ import (
|
|||
"github.com/anchore/grype/grype/match"
|
||||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/syft/syft/distro"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
// Presenter is a generic struct for holding fields needed for reporting
|
||||
type Presenter struct {
|
||||
matches match.Matches
|
||||
packages []pkg.Package
|
||||
distro *distro.Distro
|
||||
srcMetadata source.Metadata
|
||||
context pkg.Context
|
||||
metadataProvider vulnerability.MetadataProvider
|
||||
}
|
||||
|
||||
// NewPresenter is a *Presenter constructor
|
||||
func NewPresenter(matches match.Matches, packages []pkg.Package, d *distro.Distro, srcMetadata source.Metadata, metadataProvider vulnerability.MetadataProvider) *Presenter {
|
||||
func NewPresenter(matches match.Matches, packages []pkg.Package, context pkg.Context, metadataProvider vulnerability.MetadataProvider) *Presenter {
|
||||
return &Presenter{
|
||||
matches: matches,
|
||||
packages: packages,
|
||||
distro: d,
|
||||
metadataProvider: metadataProvider,
|
||||
srcMetadata: srcMetadata,
|
||||
context: context,
|
||||
}
|
||||
}
|
||||
|
||||
// Present creates a JSON-based reporting
|
||||
func (pres *Presenter) Present(output io.Writer) error {
|
||||
doc, err := NewDocument(pres.packages, pres.distro, pres.srcMetadata, pres.matches, pres.metadataProvider)
|
||||
doc, err := NewDocument(pres.packages, pres.context, pres.matches, pres.metadataProvider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -155,7 +155,11 @@ func TestJsonImgsPresenter(t *testing.T) {
|
|||
t.Fatalf("failed to create scope: %+v", err)
|
||||
}
|
||||
|
||||
pres := NewPresenter(matches, packages, &d, theSource.Metadata, newMetadataMock())
|
||||
ctx := pkg.Context{
|
||||
Source: &theSource.Metadata,
|
||||
Distro: &d,
|
||||
}
|
||||
pres := NewPresenter(matches, packages, ctx, newMetadataMock())
|
||||
|
||||
// TODO: add a constructor for a match.Match when the data is better shaped
|
||||
|
||||
|
@ -271,7 +275,11 @@ func TestJsonDirsPresenter(t *testing.T) {
|
|||
t.Fatalf("could not make distro: %+v", err)
|
||||
}
|
||||
|
||||
pres := NewPresenter(matches, pkg.FromCatalog(catalog), &d, s.Metadata, newMetadataMock())
|
||||
ctx := pkg.Context{
|
||||
Source: &s.Metadata,
|
||||
Distro: &d,
|
||||
}
|
||||
pres := NewPresenter(matches, pkg.FromCatalog(catalog), ctx, newMetadataMock())
|
||||
|
||||
// TODO: add a constructor for a match.Match when the data is better shaped
|
||||
|
||||
|
@ -321,7 +329,12 @@ func TestEmptyJsonPresenter(t *testing.T) {
|
|||
t.Fatalf("could not make distro: %+v", err)
|
||||
}
|
||||
|
||||
pres := NewPresenter(matches, []pkg.Package{}, &d, theSource.Metadata, nil)
|
||||
ctx := pkg.Context{
|
||||
Source: &theSource.Metadata,
|
||||
Distro: &d,
|
||||
}
|
||||
|
||||
pres := NewPresenter(matches, []pkg.Package{}, ctx, nil)
|
||||
|
||||
// run presenter
|
||||
if err = pres.Present(&buffer); err != nil {
|
||||
|
|
|
@ -4,6 +4,13 @@
|
|||
"type": "image",
|
||||
"target": {
|
||||
"userInput": "user-input",
|
||||
"imageID": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
|
||||
"manifestDigest": "sha256:79f5982abf18af54158ed48386c3bc18dcba70a2b0de6f75ed583505d4de673a",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"tags": [
|
||||
"stereoscope-fixture-image-simple:04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7"
|
||||
],
|
||||
"imageSize": 65,
|
||||
"scope": "AllLayers",
|
||||
"layers": [
|
||||
{
|
||||
|
@ -22,12 +29,8 @@
|
|||
"size": 27
|
||||
}
|
||||
],
|
||||
"size": 65,
|
||||
"digest": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"tags": [
|
||||
"stereoscope-fixture-image-simple:04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7"
|
||||
]
|
||||
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjoxODAxLCJkaWdlc3QiOiJzaGEyNTY6MjczMTI1MWRjMzQ5NTFjMGU1MGZjYzY0M2I0YzVmNzQ5MjJkYWQxYTVkOThmMzAyYjUwNGNmNDZjZDVkOTM2OCJ9LCJsYXllcnMiOlt7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjoyMDQ4LCJkaWdlc3QiOiJzaGEyNTY6ZTE1OGI1N2Q2ZjVhOTZlZjVmZDIyZjJmZTc2YzcwYjViYTZmZjViMjYxOWY5ZDgzMTI1YjJhYWQwNDkyYWM3YiJ9LHsibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjpkYTIxMDU2ZTdiZjQzMDhlY2VhMGMwODM2ODQ4YTdmZTkyZjM4ZmRjZjM1YmMwOWVlNmQ5OGU3YWI3YmVlZWJmIn0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MzU4NCwiZGlnZXN0Ijoic2hhMjU2OmYwZTE4YWE2MDMyYzI0NjU5YTljNzQxZmMzNmNhNTZmNTg5NzgyZWExMzIwNjFjY2Y2ZjUyYjk1MjQwM2RhOTQifV19",
|
||||
"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJIb3N0bmFtZSI6IiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpudWxsLCJJbWFnZSI6InNoYTI1NjpiMjQ5NTQwZjc4NDFlMmQxYTVjOTA2NzBkODhhOTgzYmI2Njc3NDNlNTc1N2FmZWI3MzBkMTQ1ZjQyOGEwN2M0IiwiVm9sdW1lcyI6bnVsbCwiV29ya2luZ0RpciI6IiIsIkVudHJ5cG9pbnQiOm51bGwsIk9uQnVpbGQiOm51bGwsIkxhYmVscyI6bnVsbH0sImNvbnRhaW5lcl9jb25maWciOnsiSG9zdG5hbWUiOiIiLCJEb21haW5uYW1lIjoiIiwiVXNlciI6IiIsIkF0dGFjaFN0ZGluIjpmYWxzZSwiQXR0YWNoU3Rkb3V0IjpmYWxzZSwiQXR0YWNoU3RkZXJyIjpmYWxzZSwiVHR5IjpmYWxzZSwiT3BlblN0ZGluIjpmYWxzZSwiU3RkaW5PbmNlIjpmYWxzZSwiRW52IjpbIlBBVEg9L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluIl0sIkNtZCI6WyIvYmluL3NoIiwiLWMiLCIjKG5vcCkgQUREIGRpcjpjOTM3YzZhYTUwODkwN2UyODUwOWI2NDRhMTJmOGQ2YzY3ZDM0ZTk2OWY4M2IxNGRlZTkzZWExN2Q3NjkwMjhhIGluIC8gIl0sIkltYWdlIjoic2hhMjU2OmIyNDk1NDBmNzg0MWUyZDFhNWM5MDY3MGQ4OGE5ODNiYjY2Nzc0M2U1NzU3YWZlYjczMGQxNDVmNDI4YTA3YzQiLCJWb2x1bWVzIjpudWxsLCJXb3JraW5nRGlyIjoiIiwiRW50cnlwb2ludCI6bnVsbCwiT25CdWlsZCI6bnVsbCwiTGFiZWxzIjpudWxsfSwiY3JlYXRlZCI6IjIwMjAtMDktMjNUMTE6NTI6NDMuMTI0NjY2OFoiLCJkb2NrZXJfdmVyc2lvbiI6IjE5LjAzLjEyIiwiaGlzdG9yeSI6W3siY3JlYXRlZCI6IjIwMjAtMDktMjNUMTE6NTI6NDIuODczMDEyNloiLCJjcmVhdGVkX2J5IjoiL2Jpbi9zaCAtYyAjKG5vcCkgQUREIGZpbGU6YWMzMmRhMjNkNTFlODAxZjAyZjkyNDEyM2VkMzA5OTBlYjNmMGZlYzFiOWVkNGYwYjA2YzI0ZTg4YjljMzY5NSBpbiAvc29tZWZpbGUtMS50eHQgIn0seyJjcmVhdGVkIjoiMjAyMC0wOS0yM1QxMTo1Mjo0Mi45ODY1OTg5WiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jICMobm9wKSBBREQgZmlsZTpkZjNiNzQ0ZjU0YTliMTZiOWI5YWVkNDBlM2U5OGQ5Y2EyYjQ5ZjVhNzdkOWZhOGE5NzY5MGQ3YmFmNTg4ODIwIGluIC9zb21lZmlsZS0yLnR4dCAifSx7ImNyZWF0ZWQiOiIyMDIwLTA5LTIzVDExOjUyOjQzLjEyNDY2NjhaIiwiY3JlYXRlZF9ieSI6Ii9iaW4vc2ggLWMgIyhub3ApIEFERCBkaXI6YzkzN2M2YWE1MDg5MDdlMjg1MDliNjQ0YTEyZjhkNmM2N2QzNGU5NjlmODNiMTRkZWU5M2VhMTdkNzY5MDI4YSBpbiAvICJ9XSwib3MiOiJsaW51eCIsInJvb3RmcyI6eyJ0eXBlIjoibGF5ZXJzIiwiZGlmZl9pZHMiOlsic2hhMjU2OmUxNThiNTdkNmY1YTk2ZWY1ZmQyMmYyZmU3NmM3MGI1YmE2ZmY1YjI2MTlmOWQ4MzEyNWIyYWFkMDQ5MmFjN2IiLCJzaGEyNTY6ZGEyMTA1NmU3YmY0MzA4ZWNlYTBjMDgzNjg0OGE3ZmU5MmYzOGZkY2YzNWJjMDllZTZkOThlN2FiN2JlZWViZiIsInNoYTI1NjpmMGUxOGFhNjAzMmMyNDY1OWE5Yzc0MWZjMzZjYTU2ZjU4OTc4MmVhMTMyMDYxY2NmNmY1MmI5NTI0MDNkYTk0Il19fQ=="
|
||||
}
|
||||
},
|
||||
"distro": {
|
||||
|
|
|
@ -110,6 +110,13 @@
|
|||
"type": "image",
|
||||
"target": {
|
||||
"userInput": "user-input",
|
||||
"imageID": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
|
||||
"manifestDigest": "sha256:79f5982abf18af54158ed48386c3bc18dcba70a2b0de6f75ed583505d4de673a",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"tags": [
|
||||
"stereoscope-fixture-image-simple:04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7"
|
||||
],
|
||||
"imageSize": 65,
|
||||
"scope": "AllLayers",
|
||||
"layers": [
|
||||
{
|
||||
|
@ -128,12 +135,8 @@
|
|||
"size": 27
|
||||
}
|
||||
],
|
||||
"size": 65,
|
||||
"digest": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"tags": [
|
||||
"stereoscope-fixture-image-simple:04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7"
|
||||
]
|
||||
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjoxODAxLCJkaWdlc3QiOiJzaGEyNTY6MjczMTI1MWRjMzQ5NTFjMGU1MGZjYzY0M2I0YzVmNzQ5MjJkYWQxYTVkOThmMzAyYjUwNGNmNDZjZDVkOTM2OCJ9LCJsYXllcnMiOlt7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjoyMDQ4LCJkaWdlc3QiOiJzaGEyNTY6ZTE1OGI1N2Q2ZjVhOTZlZjVmZDIyZjJmZTc2YzcwYjViYTZmZjViMjYxOWY5ZDgzMTI1YjJhYWQwNDkyYWM3YiJ9LHsibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjpkYTIxMDU2ZTdiZjQzMDhlY2VhMGMwODM2ODQ4YTdmZTkyZjM4ZmRjZjM1YmMwOWVlNmQ5OGU3YWI3YmVlZWJmIn0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MzU4NCwiZGlnZXN0Ijoic2hhMjU2OmYwZTE4YWE2MDMyYzI0NjU5YTljNzQxZmMzNmNhNTZmNTg5NzgyZWExMzIwNjFjY2Y2ZjUyYjk1MjQwM2RhOTQifV19",
|
||||
"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJIb3N0bmFtZSI6IiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpudWxsLCJJbWFnZSI6InNoYTI1NjpiMjQ5NTQwZjc4NDFlMmQxYTVjOTA2NzBkODhhOTgzYmI2Njc3NDNlNTc1N2FmZWI3MzBkMTQ1ZjQyOGEwN2M0IiwiVm9sdW1lcyI6bnVsbCwiV29ya2luZ0RpciI6IiIsIkVudHJ5cG9pbnQiOm51bGwsIk9uQnVpbGQiOm51bGwsIkxhYmVscyI6bnVsbH0sImNvbnRhaW5lcl9jb25maWciOnsiSG9zdG5hbWUiOiIiLCJEb21haW5uYW1lIjoiIiwiVXNlciI6IiIsIkF0dGFjaFN0ZGluIjpmYWxzZSwiQXR0YWNoU3Rkb3V0IjpmYWxzZSwiQXR0YWNoU3RkZXJyIjpmYWxzZSwiVHR5IjpmYWxzZSwiT3BlblN0ZGluIjpmYWxzZSwiU3RkaW5PbmNlIjpmYWxzZSwiRW52IjpbIlBBVEg9L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluIl0sIkNtZCI6WyIvYmluL3NoIiwiLWMiLCIjKG5vcCkgQUREIGRpcjpjOTM3YzZhYTUwODkwN2UyODUwOWI2NDRhMTJmOGQ2YzY3ZDM0ZTk2OWY4M2IxNGRlZTkzZWExN2Q3NjkwMjhhIGluIC8gIl0sIkltYWdlIjoic2hhMjU2OmIyNDk1NDBmNzg0MWUyZDFhNWM5MDY3MGQ4OGE5ODNiYjY2Nzc0M2U1NzU3YWZlYjczMGQxNDVmNDI4YTA3YzQiLCJWb2x1bWVzIjpudWxsLCJXb3JraW5nRGlyIjoiIiwiRW50cnlwb2ludCI6bnVsbCwiT25CdWlsZCI6bnVsbCwiTGFiZWxzIjpudWxsfSwiY3JlYXRlZCI6IjIwMjAtMDktMjNUMTE6NTI6NDMuMTI0NjY2OFoiLCJkb2NrZXJfdmVyc2lvbiI6IjE5LjAzLjEyIiwiaGlzdG9yeSI6W3siY3JlYXRlZCI6IjIwMjAtMDktMjNUMTE6NTI6NDIuODczMDEyNloiLCJjcmVhdGVkX2J5IjoiL2Jpbi9zaCAtYyAjKG5vcCkgQUREIGZpbGU6YWMzMmRhMjNkNTFlODAxZjAyZjkyNDEyM2VkMzA5OTBlYjNmMGZlYzFiOWVkNGYwYjA2YzI0ZTg4YjljMzY5NSBpbiAvc29tZWZpbGUtMS50eHQgIn0seyJjcmVhdGVkIjoiMjAyMC0wOS0yM1QxMTo1Mjo0Mi45ODY1OTg5WiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jICMobm9wKSBBREQgZmlsZTpkZjNiNzQ0ZjU0YTliMTZiOWI5YWVkNDBlM2U5OGQ5Y2EyYjQ5ZjVhNzdkOWZhOGE5NzY5MGQ3YmFmNTg4ODIwIGluIC9zb21lZmlsZS0yLnR4dCAifSx7ImNyZWF0ZWQiOiIyMDIwLTA5LTIzVDExOjUyOjQzLjEyNDY2NjhaIiwiY3JlYXRlZF9ieSI6Ii9iaW4vc2ggLWMgIyhub3ApIEFERCBkaXI6YzkzN2M2YWE1MDg5MDdlMjg1MDliNjQ0YTEyZjhkNmM2N2QzNGU5NjlmODNiMTRkZWU5M2VhMTdkNzY5MDI4YSBpbiAvICJ9XSwib3MiOiJsaW51eCIsInJvb3RmcyI6eyJ0eXBlIjoibGF5ZXJzIiwiZGlmZl9pZHMiOlsic2hhMjU2OmUxNThiNTdkNmY1YTk2ZWY1ZmQyMmYyZmU3NmM3MGI1YmE2ZmY1YjI2MTlmOWQ4MzEyNWIyYWFkMDQ5MmFjN2IiLCJzaGEyNTY6ZGEyMTA1NmU3YmY0MzA4ZWNlYTBjMDgzNjg0OGE3ZmU5MmYzOGZkY2YzNWJjMDllZTZkOThlN2FiN2JlZWViZiIsInNoYTI1NjpmMGUxOGFhNjAzMmMyNDY1OWE5Yzc0MWZjMzZjYTU2ZjU4OTc4MmVhMTMyMDYxY2NmNmY1MmI5NTI0MDNkYTk0Il19fQ=="
|
||||
}
|
||||
},
|
||||
"distro": {
|
||||
|
|
|
@ -9,8 +9,6 @@ import (
|
|||
"github.com/anchore/grype/grype/presenter/json"
|
||||
"github.com/anchore/grype/grype/presenter/table"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/syft/syft/distro"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
// Presenter is the main interface other Presenters need to implement
|
||||
|
@ -19,14 +17,14 @@ type Presenter interface {
|
|||
}
|
||||
|
||||
// GetPresenter retrieves a Presenter that matches a CLI option
|
||||
func GetPresenter(option Option, matches match.Matches, packages []pkg.Package, d *distro.Distro, srcMetadata source.Metadata, metadataProvider vulnerability.MetadataProvider) Presenter {
|
||||
func GetPresenter(option Option, matches match.Matches, packages []pkg.Package, context pkg.Context, metadataProvider vulnerability.MetadataProvider) Presenter {
|
||||
switch option {
|
||||
case JSONPresenter:
|
||||
return json.NewPresenter(matches, packages, d, srcMetadata, metadataProvider)
|
||||
return json.NewPresenter(matches, packages, context, metadataProvider)
|
||||
case TablePresenter:
|
||||
return table.NewPresenter(matches, packages, metadataProvider)
|
||||
case CycloneDxPresenter:
|
||||
return cyclonedx.NewPresenter(matches, packages, srcMetadata, metadataProvider)
|
||||
return cyclonedx.NewPresenter(matches, packages, context.Source, metadataProvider)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue