Skip to content

Commit

Permalink
fix: read direct package files when decoding SPDX tag-value (#2014)
Browse files Browse the repository at this point in the history
* fix: read direct package files when decoding SPDX tag-value

---------

Signed-off-by: Keith Zantow <[email protected]>
  • Loading branch information
kzantow authored Aug 14, 2023
1 parent c7fe586 commit b3d7ba5
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 1 deletion.
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())
}

0 comments on commit b3d7ba5

Please sign in to comment.