Skip to content
Merged
2 changes: 1 addition & 1 deletion internal/formats/common/cyclonedxhelpers/author.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/anchore/syft/syft/pkg"
)

func Author(p pkg.Package) string {
func encodeAuthor(p pkg.Package) string {
if hasMetadata(p) {
switch metadata := p.Metadata.(type) {
case pkg.NpmPackageJSONMetadata:
Expand Down
4 changes: 2 additions & 2 deletions internal/formats/common/cyclonedxhelpers/author_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
)

func Test_Author(t *testing.T) {
func Test_encodeAuthor(t *testing.T) {
tests := []struct {
name string
input pkg.Package
Expand Down Expand Up @@ -81,7 +81,7 @@ func Test_Author(t *testing.T) {
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
assert.Equal(t, test.expected, Author(test.input))
assert.Equal(t, test.expected, encodeAuthor(test.input))
})
}
}
97 changes: 88 additions & 9 deletions internal/formats/common/cyclonedxhelpers/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,102 @@ import (
"github.com/anchore/syft/syft/pkg"
)

func Component(p pkg.Package) cyclonedx.Component {
func encodeComponent(p pkg.Package) cyclonedx.Component {
return cyclonedx.Component{
Type: cyclonedx.ComponentTypeLibrary,
Name: p.Name,
Group: Group(p),
Group: encodeGroup(p),
Version: p.Version,
PackageURL: p.PURL,
Licenses: Licenses(p),
CPE: CPE(p),
Author: Author(p),
Publisher: Publisher(p),
Description: Description(p),
ExternalReferences: ExternalReferences(p),
Properties: Properties(p),
Licenses: encodeLicenses(p),
CPE: encodeCPE(p),
Author: encodeAuthor(p),
Publisher: encodePublisher(p),
Description: encodeDescription(p),
ExternalReferences: encodeExternalReferences(p),
Properties: encodeProperties(p),
}
}

func hasMetadata(p pkg.Package) bool {
return p.Metadata != nil
}

func decodeComponent(c *cyclonedx.Component) *pkg.Package {
typ := pkg.Type(prop(c, "type"))
purl := c.PackageURL
if typ == "" && purl != "" {
typ = pkg.TypeFromPURL(purl)
}

metaType, meta := decodePackageMetadata(c)

p := &pkg.Package{
Name: c.Name,
Version: c.Version,
FoundBy: prop(c, "foundBy"),
Locations: nil,
Licenses: decodeLicenses(c),
Language: pkg.Language(prop(c, "language")),
Type: typ,
CPEs: decodeCPEs(c),
PURL: purl,
MetadataType: metaType,
Metadata: meta,
}

return p
}

func decodePackageMetadata(c *cyclonedx.Component) (pkg.MetadataType, interface{}) {
if c.Properties != nil {
typ := prop(c, "metadataType")
if typ != "" {
switch typ {
case "ApkMetadata":
return pkg.ApkMetadataType, pkg.ApkMetadata{
Package: prop(c, "package"),
OriginPackage: prop(c, "originPackage"),
Maintainer: prop(c, "maintainer"),
Version: prop(c, "version"),
License: prop(c, "license"),
Architecture: prop(c, "architecture"),
URL: prop(c, "url"),
Description: prop(c, "description"),
Size: propInt(c, "size"),
InstalledSize: propInt(c, "installedSize"),
PullDependencies: prop(c, "pullDependencies"),
PullChecksum: prop(c, "pullChecksum"),
GitCommitOfAport: prop(c, "gitCommitOfAport"),
Files: []pkg.ApkFileRecord{},
}
case "DpkgMetadata":
return pkg.DpkgMetadataType, pkg.DpkgMetadata{
Package: prop(c, "package"),
Source: prop(c, "source"),
Version: prop(c, "version"),
SourceVersion: prop(c, "sourceVersion"),
Architecture: prop(c, "architecture"),
Maintainer: prop(c, "maintainer"),
InstalledSize: propInt(c, "installedSize"),
Files: []pkg.DpkgFileRecord{},
}
case "RpmdbMetadata":
return pkg.RpmdbMetadataType, pkg.RpmdbMetadata{
Name: prop(c, "name"),
Version: prop(c, "version"),
Epoch: propIntNil(c, "epoch"),
Arch: prop(c, "arch"),
Release: prop(c, "release"),
SourceRpm: prop(c, "sourceRpm"),
Size: propInt(c, "size"),
License: prop(c, "license"),
Vendor: prop(c, "vendor"),
Files: []pkg.RpmdbFileRecord{},
}
}
}
}

return pkg.UnknownMetadataType, nil
}
31 changes: 28 additions & 3 deletions internal/formats/common/cyclonedxhelpers/cpe.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,37 @@
package cyclonedxhelpers

import "github.com/anchore/syft/syft/pkg"
import (
"github.com/CycloneDX/cyclonedx-go"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/common/cpe"
)

func CPE(p pkg.Package) string {
func encodeCPE(p pkg.Package) string {
// Since the CPEs in a package are sorted by specificity
// we can extract the first CPE as the one to output in cyclonedx
// we can extract the first encodeCPE as the one to output in cyclonedx
if len(p.CPEs) > 0 {
return pkg.CPEString(p.CPEs[0])
}
return ""
}

func decodeCPEs(c *cyclonedx.Component) []pkg.CPE {
// FIXME -- why are we not encoding all the CPEs and what is the right behavior to decode them?
Comment thread
kzantow marked this conversation as resolved.
Outdated
cpes := cpe.Generate(pkg.Package{
Name: c.Name,
Version: c.Version,
PURL: c.PackageURL,
})

if c.CPE != "" {
cp, err := pkg.NewCPE(c.CPE)
if err != nil {
log.Warnf("invalid CPE: %s", c.CPE)
} else {
cpes = append(cpes, cp)
}
}

return cpes
}
4 changes: 2 additions & 2 deletions internal/formats/common/cyclonedxhelpers/cpe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
)

func Test_CPE(t *testing.T) {
func Test_encodeCPE(t *testing.T) {
testCPE := pkg.MustCPE("cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*")
testCPE2 := pkg.MustCPE("cpe:2.3:a:name:name2:3.2:*:*:*:*:*:*:*")
tests := []struct {
Expand Down Expand Up @@ -51,7 +51,7 @@ func Test_CPE(t *testing.T) {
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
assert.Equal(t, test.expected, CPE(test.input))
assert.Equal(t, test.expected, encodeCPE(test.input))
})
}
}
Loading