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

fix: read direct package files when decoding SPDX tag-value #2014

Merged
merged 2 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
43 changes: 42 additions & 1 deletion syft/formats/common/spdxhelpers/to_syft_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,16 @@ func collectSyftPackages(s *sbom.SBOM, spdxIDMap map[string]any, packages []*spd
}

func collectSyftFiles(s *sbom.SBOM, spdxIDMap map[string]any, doc *spdx.Document) {
for _, p := range doc.Packages {
for _, f := range p.Files {
l := toSyftLocation(f)
spdxIDMap[string(f.FileSPDXIdentifier)] = l

s.Artifacts.FileMetadata[l.Coordinates] = toFileMetadata(f)
s.Artifacts.FileDigests[l.Coordinates] = toFileDigests(f)
}
}

for _, f := range doc.Files {
l := toSyftLocation(f)
spdxIDMap[string(f.FileSPDXIdentifier)] = l
Expand Down Expand Up @@ -332,7 +342,14 @@ func toFileMetadata(f *spdx.File) (meta file.Metadata) {
}

func toSyftRelationships(spdxIDMap map[string]any, doc *spdx.Document) []artifact.Relationship {
var out []artifact.Relationship
out := collectDocRelationships(spdxIDMap, doc)

out = append(out, collectPackageFileRelationships(spdxIDMap, doc)...)

return out
}

func collectDocRelationships(spdxIDMap map[string]any, doc *spdx.Document) (out []artifact.Relationship) {
for _, r := range doc.Relationships {
// FIXME what to do with r.RefA.DocumentRefID and r.RefA.SpecialID
if r.RefA.DocumentRefID != "" && requireAndTrimPrefix(r.RefA.DocumentRefID, "DocumentRef-") != string(doc.SPDXIdentifier) {
Expand Down Expand Up @@ -386,6 +403,30 @@ func toSyftRelationships(spdxIDMap map[string]any, doc *spdx.Document) []artifac
return out
}

// collectPackageFileRelationships add relationships for direct files
func collectPackageFileRelationships(spdxIDMap map[string]any, doc *spdx.Document) (out []artifact.Relationship) {
for _, p := range doc.Packages {
a := spdxIDMap[string(p.PackageSPDXIdentifier)]
from, fromOk := a.(pkg.Package)
if !fromOk {
continue
}
for _, f := range p.Files {
b := spdxIDMap[string(f.FileSPDXIdentifier)]
to, toLocationOk := b.(file.Location)
if !toLocationOk {
continue
}
out = append(out, artifact.Relationship{
From: from,
To: to,
Type: artifact.ContainsRelationship,
})
}
}
return out
}

func toSyftCoordinates(f *spdx.File) file.Coordinates {
const layerIDPrefix = "layerID: "
var fileSystemID string
Expand Down
74 changes: 74 additions & 0 deletions syft/formats/common/spdxhelpers/to_syft_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -608,3 +608,77 @@ func Test_purlValue(t *testing.T) {
})
}
}

func Test_directPackageFiles(t *testing.T) {
doc := &spdx.Document{
SPDXVersion: "SPDX-2.3",
Packages: []*spdx.Package{
{
PackageName: "some-package",
PackageSPDXIdentifier: "1",
PackageVersion: "1.0.5",
Files: []*spdx.File{
{
FileName: "some-file",
FileSPDXIdentifier: "2",
Checksums: []spdx.Checksum{
{
Algorithm: "SHA1",
Value: "a8d733c64f9123",
},
},
},
},
},
},
}

got, err := ToSyftModel(doc)
require.NoError(t, err)

p := pkg.Package{
Name: "some-package",
Version: "1.0.5",
MetadataType: pkg.UnknownMetadataType,
}
p.SetID()
f := file.Location{
LocationData: file.LocationData{
Coordinates: file.Coordinates{
RealPath: "some-file",
FileSystemID: "",
},
VirtualPath: "some-file",
},
LocationMetadata: file.LocationMetadata{
Annotations: map[string]string{},
},
}
s := &sbom.SBOM{
Artifacts: sbom.Artifacts{
Packages: pkg.NewCollection(p),
FileMetadata: map[file.Coordinates]file.Metadata{
f.Coordinates: {},
},
FileDigests: map[file.Coordinates][]file.Digest{
f.Coordinates: {
{
Algorithm: "sha1",
Value: "a8d733c64f9123",
},
},
},
},
Relationships: []artifact.Relationship{
{
From: p,
To: f,
Type: artifact.ContainsRelationship,
},
},
Source: source.Description{},
Descriptor: sbom.Descriptor{},
}

require.Equal(t, s, got)
}
60 changes: 60 additions & 0 deletions syft/formats/spdxtagvalue/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ package spdxtagvalue

import (
"os"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/anchore/syft/syft/file"
)

// TODO: this is a temporary coverage see below
Expand Down Expand Up @@ -34,3 +38,59 @@ func TestSPDXTagValueDecoder(t *testing.T) {
})
}
}

func Test_packageDirectFiles(t *testing.T) {
contents := `
SPDXVersion: SPDX-2.2
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: Some-SBOM
DocumentNamespace: https://example.org/some/namespace
Creator: Organization: Some-organization
Creator: Tool: Some-tool Version: 1.0
Created: 2021-12-29T17:02:21Z
PackageName: Some-package
PackageVersion: 5.1.2
SPDXID: SPDXRef-Package-43c51b08-cc7e-406d-8ad9-34aa292d1157
PackageSupplier: Organization: Some-organization
PackageDownloadLocation: https://example.org/download/location
FilesAnalyzed: true
PackageLicenseInfoFromFiles: NOASSERTION
PackageVerificationCode: 23460C5559C8D4DE3F6504E0E84E844CAC8B1D95
PackageLicenseConcluded: NOASSERTION
PackageLicenseDeclared: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageChecksum: SHA1: 23460C5559C8D4DE3F6504E0E84E844CAC8B1D95
FileName: Some-file-name
SPDXID: SPDXRef-99545d55-933d-4e08-9eb5-9d826111cb79
FileContributor: Some-file-contributor
FileType: BINARY
FileChecksum: SHA1: 23460C5559C8D4DE3F6504E0E84E844CAC8B1D95
LicenseConcluded: NOASSERTION
LicenseInfoInFile: NOASSERTION
FileCopyrightText: NOASSERTION
`

s, err := decoder(strings.NewReader(contents))
require.NoError(t, err)

pkgs := s.Artifacts.Packages.Sorted()
assert.Len(t, pkgs, 1)
assert.Len(t, s.Artifacts.FileMetadata, 1)
assert.Len(t, s.Relationships, 1)
p := pkgs[0]
r := s.Relationships[0]
f := file.Location{}
for c := range s.Artifacts.FileMetadata {
f = file.Location{
LocationData: file.LocationData{
Coordinates: c,
VirtualPath: "",
},
LocationMetadata: file.LocationMetadata{},
}
break // there should only be 1
}
assert.Equal(t, p.ID(), r.From.ID())
assert.Equal(t, f.ID(), r.To.ID())
}
Loading