Skip to content

Commit

Permalink
refactor(sbom): add sbom prefix + filepaths for decode log messages (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitriyLewen authored Jul 3, 2024
1 parent 1f5f348 commit 266d9b1
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 25 deletions.
6 changes: 4 additions & 2 deletions pkg/fanal/analyzer/sbom/sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/sbom"
"github.com/aquasecurity/trivy/pkg/types"
)
Expand All @@ -29,14 +30,15 @@ var requiredSuffixes = []string{

type sbomAnalyzer struct{}

func (a sbomAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) {
func (a sbomAnalyzer) Analyze(ctx context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) {
// Format auto-detection
format, err := sbom.DetectFormat(input.Content)
if err != nil {
return nil, xerrors.Errorf("failed to detect SBOM format: %w", err)
}

bom, err := sbom.Decode(input.Content, format)
ctx = log.WithContextAttrs(ctx, log.FilePath(input.FilePath))
bom, err := sbom.Decode(ctx, input.Content, format)
if err != nil {
return nil, xerrors.Errorf("SBOM decode error: %w", err)
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/fanal/artifact/sbom/sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func NewArtifact(filePath string, c cache.ArtifactCache, opt artifact.Option) (a
}, nil
}

func (a Artifact) Inspect(_ context.Context) (artifact.Reference, error) {
func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) {
f, err := os.Open(a.filePath)
if err != nil {
return artifact.Reference{}, xerrors.Errorf("failed to open sbom file error: %w", err)
Expand All @@ -51,7 +51,8 @@ func (a Artifact) Inspect(_ context.Context) (artifact.Reference, error) {
}
log.Info("Detected SBOM format", log.String("format", string(format)))

bom, err := sbom.Decode(f, format)
ctx = log.WithContextAttrs(ctx, log.FilePath(a.filePath))
bom, err := sbom.Decode(ctx, f, format)
if err != nil {
return artifact.Reference{}, xerrors.Errorf("SBOM decode error: %w", err)
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/fanal/handler/unpackaged/unpackaged.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ func (h unpackagedHook) Handle(ctx context.Context, res *analyzer.AnalysisResult
}

// Parse the fetched SBOM
bom, err := sbom.Decode(bytes.NewReader(raw), format)
ctx = log.WithContextAttrs(ctx, log.FilePath(filePath))
bom, err := sbom.Decode(ctx, bytes.NewReader(raw), format)
if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/sbom/cyclonedx/unmarshal_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cyclonedx_test

import (
"context"
"encoding/json"
"os"
"testing"
Expand Down Expand Up @@ -757,7 +758,7 @@ func TestUnmarshaler_Unmarshal(t *testing.T) {
require.NoError(t, err)

var got types.SBOM
err = sbomio.NewDecoder(cdx.BOM).Decode(&got)
err = sbomio.NewDecoder(cdx.BOM).Decode(context.Background(), &got)
require.NoError(t, err)

got.BOM = nil
Expand Down
33 changes: 17 additions & 16 deletions pkg/sbom/io/decode.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io

import (
"context"
"errors"
"slices"
"sort"
Expand Down Expand Up @@ -46,14 +47,14 @@ func NewDecoder(bom *core.BOM) *Decoder {
}
}

func (m *Decoder) Decode(sbom *types.SBOM) error {
func (m *Decoder) Decode(ctx context.Context, sbom *types.SBOM) error {
// Parse the root component
if err := m.decodeRoot(sbom); err != nil {
return xerrors.Errorf("failed to decode root component: %w", err)
}

// Parse all components
if err := m.decodeComponents(sbom); err != nil {
if err := m.decodeComponents(ctx, sbom); err != nil {
return xerrors.Errorf("failed to decode components: %w", err)
}

Expand All @@ -67,7 +68,7 @@ func (m *Decoder) Decode(sbom *types.SBOM) error {
m.addLangPkgs(sbom)

// Add remaining packages
if err := m.addOrphanPkgs(sbom); err != nil {
if err := m.addOrphanPkgs(ctx, sbom); err != nil {
return xerrors.Errorf("failed to aggregate packages: %w", err)
}

Expand Down Expand Up @@ -109,9 +110,9 @@ func (m *Decoder) decodeRoot(s *types.SBOM) error {
return nil
}

func (m *Decoder) decodeComponents(sbom *types.SBOM) error {
func (m *Decoder) decodeComponents(ctx context.Context, sbom *types.SBOM) error {
onceMultiOSWarn := sync.OnceFunc(func() {
m.logger.Warn("Multiple OS components are not supported, taking the first one and ignoring the rest")
m.logger.WarnContext(ctx, "Multiple OS components are not supported, taking the first one and ignoring the rest")
})

for id, c := range m.bom.Components() {
Expand All @@ -136,7 +137,7 @@ func (m *Decoder) decodeComponents(sbom *types.SBOM) error {

// Third-party SBOMs may contain packages in types other than "Library"
if c.Type == core.TypeLibrary || c.PkgIdentifier.PURL != nil {
pkg, err := m.decodeLibrary(c)
pkg, err := m.decodeLibrary(ctx, c)
if errors.Is(err, ErrUnsupportedType) || errors.Is(err, ErrPURLEmpty) {
continue
} else if err != nil {
Expand Down Expand Up @@ -183,17 +184,17 @@ func (m *Decoder) decodeApplication(c *core.Component) *ftypes.Application {
return &app
}

func (m *Decoder) decodeLibrary(c *core.Component) (*ftypes.Package, error) {
func (m *Decoder) decodeLibrary(ctx context.Context, c *core.Component) (*ftypes.Package, error) {
p := (*purl.PackageURL)(c.PkgIdentifier.PURL)
if p == nil {
log.Debug("Skipping a component without PURL",
m.logger.DebugContext(ctx, "Skipping a component without PURL",
log.String("name", c.Name), log.String("version", c.Version))
return nil, ErrPURLEmpty
}

pkg := p.Package()
if p.Class() == types.ClassUnknown {
log.Debug("Skipping a component with an unsupported type",
m.logger.DebugContext(ctx, "Skipping a component with an unsupported type",
log.String("name", c.Name), log.String("version", c.Version), log.String("type", p.Type))
return nil, ErrUnsupportedType
}
Expand Down Expand Up @@ -240,7 +241,7 @@ func (m *Decoder) decodeLibrary(c *core.Component) (*ftypes.Package, error) {
}

if p.Class() == types.ClassOSPkg {
m.fillSrcPkg(c, pkg)
m.fillSrcPkg(ctx, c, pkg)
}

return pkg, nil
Expand Down Expand Up @@ -278,11 +279,11 @@ func (m *Decoder) pkgName(pkg *ftypes.Package, c *core.Component) string {
return c.Name
}

func (m *Decoder) fillSrcPkg(c *core.Component, pkg *ftypes.Package) {
func (m *Decoder) fillSrcPkg(ctx context.Context, c *core.Component, pkg *ftypes.Package) {
if c.SrcName != "" && pkg.SrcName == "" {
pkg.SrcName = c.SrcName
}
m.parseSrcVersion(pkg, c.SrcVersion)
m.parseSrcVersion(ctx, pkg, c.SrcVersion)

// Source info was added from component or properties
if pkg.SrcName != "" && pkg.SrcVersion != "" {
Expand All @@ -305,7 +306,7 @@ func (m *Decoder) fillSrcPkg(c *core.Component, pkg *ftypes.Package) {
}

// parseSrcVersion parses the version of the source package.
func (m *Decoder) parseSrcVersion(pkg *ftypes.Package, ver string) {
func (m *Decoder) parseSrcVersion(ctx context.Context, pkg *ftypes.Package, ver string) {
if ver == "" {
return
}
Expand All @@ -318,7 +319,7 @@ func (m *Decoder) parseSrcVersion(pkg *ftypes.Package, ver string) {
case packageurl.TypeDebian:
v, err := debver.NewVersion(ver)
if err != nil {
log.Debug("Failed to parse Debian version", log.Err(err))
m.logger.DebugContext(ctx, "Failed to parse Debian version", log.Err(err))
return
}
pkg.SrcEpoch = v.Epoch()
Expand Down Expand Up @@ -361,7 +362,7 @@ func (m *Decoder) addLangPkgs(sbom *types.SBOM) {

// addOrphanPkgs adds orphan packages.
// Orphan packages are packages that are not related to any components.
func (m *Decoder) addOrphanPkgs(sbom *types.SBOM) error {
func (m *Decoder) addOrphanPkgs(ctx context.Context, sbom *types.SBOM) error {
osPkgMap := make(map[string]ftypes.Packages)
langPkgMap := make(map[ftypes.LangType]ftypes.Packages)
for _, pkg := range m.pkgs {
Expand All @@ -382,7 +383,7 @@ func (m *Decoder) addOrphanPkgs(sbom *types.SBOM) error {
// Add OS packages only when OS is detected.
for _, pkgs := range osPkgMap {
if sbom.Metadata.OS == nil || !sbom.Metadata.OS.Detected() {
log.Warn("Ignore the OS package as no OS is detected.")
m.logger.WarnContext(ctx, "Ignore the OS package as no OS is detected.")
break
}

Expand Down
5 changes: 3 additions & 2 deletions pkg/sbom/sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sbom

import (
"bufio"
"context"
"encoding/json"
"encoding/xml"
"io"
Expand Down Expand Up @@ -180,7 +181,7 @@ func decodeAttestCycloneDXJSONFormat(r io.ReadSeeker) (Format, bool) {
return FormatAttestCycloneDXJSON, true
}

func Decode(f io.Reader, format Format) (types.SBOM, error) {
func Decode(ctx context.Context, f io.Reader, format Format) (types.SBOM, error) {
var (
v any
bom = core.NewBOM(core.Options{})
Expand Down Expand Up @@ -227,7 +228,7 @@ func Decode(f io.Reader, format Format) (types.SBOM, error) {
}

var sbom types.SBOM
if err := sbomio.NewDecoder(bom).Decode(&sbom); err != nil {
if err := sbomio.NewDecoder(bom).Decode(ctx, &sbom); err != nil {
return types.SBOM{}, xerrors.Errorf("failed to decode: %w", err)
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/sbom/spdx/unmarshal_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package spdx_test

import (
"context"
"encoding/json"
"os"
"sort"
Expand Down Expand Up @@ -357,7 +358,7 @@ func TestUnmarshaler_Unmarshal(t *testing.T) {
}

var got types.SBOM
err = sbomio.NewDecoder(v.BOM).Decode(&got)
err = sbomio.NewDecoder(v.BOM).Decode(context.Background(), &got)
require.NoError(t, err)

// Not compare BOM
Expand Down

0 comments on commit 266d9b1

Please sign in to comment.