mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +01:00
* add initial spdx support Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * expose FileOwner and use in SPDX presenter Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add initial json support for SPDX Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add remaining package fields Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add spdx license list generation + tests Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * keep fileOwner unexported from pkg Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * restore cli test util Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add external refs to spdx tag-value format Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add golang support to CPE generation Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * use tag-value format as default "spdx" format flavor Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add tests around spdx presenters + refactor presenter tests Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add bouncer exception for spdx tools-golang repo Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * remove spdx model questions Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
169 lines
4.9 KiB
Go
169 lines
4.9 KiB
Go
package packages
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/anchore/syft/internal/presenter/packages/model/spdx22"
|
|
"github.com/anchore/syft/internal/spdxlicense"
|
|
"github.com/anchore/syft/syft/pkg"
|
|
)
|
|
|
|
func getSPDXExternalRefs(p *pkg.Package) (externalRefs []spdx22.ExternalRef) {
|
|
externalRefs = make([]spdx22.ExternalRef, 0)
|
|
for _, c := range p.CPEs {
|
|
externalRefs = append(externalRefs, spdx22.ExternalRef{
|
|
ReferenceCategory: spdx22.SecurityReferenceCategory,
|
|
ReferenceLocator: c.BindToFmtString(),
|
|
ReferenceType: spdx22.Cpe23ExternalRefType,
|
|
})
|
|
}
|
|
|
|
if p.PURL != "" {
|
|
externalRefs = append(externalRefs, spdx22.ExternalRef{
|
|
ReferenceCategory: spdx22.PackageManagerReferenceCategory,
|
|
ReferenceLocator: p.PURL,
|
|
ReferenceType: spdx22.PurlExternalRefType,
|
|
})
|
|
}
|
|
return externalRefs
|
|
}
|
|
|
|
func getSPDXLicense(p *pkg.Package) string {
|
|
// source: https://spdx.github.io/spdx-spec/3-package-information/#313-concluded-license
|
|
// The options to populate this field are limited to:
|
|
// A valid SPDX License Expression as defined in Appendix IV;
|
|
// NONE, if the SPDX file creator concludes there is no license available for this package; or
|
|
// NOASSERTION if:
|
|
// (i) the SPDX file creator has attempted to but cannot reach a reasonable objective determination;
|
|
// (ii) the SPDX file creator has made no attempt to determine this field; or
|
|
// (iii) the SPDX file creator has intentionally provided no information (no meaning should be implied by doing so).
|
|
|
|
if len(p.Licenses) == 0 {
|
|
return "NONE"
|
|
}
|
|
|
|
// take all licenses and assume an AND expression; for information about license expressions see https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/
|
|
var parsedLicenses []string
|
|
for _, l := range p.Licenses {
|
|
if value, exists := spdxlicense.ID(l); exists {
|
|
parsedLicenses = append(parsedLicenses, value)
|
|
}
|
|
}
|
|
|
|
if len(parsedLicenses) == 0 {
|
|
return "NOASSERTION"
|
|
}
|
|
|
|
return strings.Join(parsedLicenses, " AND ")
|
|
}
|
|
|
|
func noneIfEmpty(value string) string {
|
|
if strings.TrimSpace(value) == "" {
|
|
return "NONE"
|
|
}
|
|
return value
|
|
}
|
|
|
|
func getSPDXDownloadLocation(p *pkg.Package) string {
|
|
// 3.7: Package Download Location
|
|
// Cardinality: mandatory, one
|
|
// NONE if there is no download location whatsoever.
|
|
// NOASSERTION if:
|
|
// (i) the SPDX file creator has attempted to but cannot reach a reasonable objective determination;
|
|
// (ii) the SPDX file creator has made no attempt to determine this field; or
|
|
// (iii) the SPDX file creator has intentionally provided no information (no meaning should be implied by doing so).
|
|
|
|
switch metadata := p.Metadata.(type) {
|
|
case pkg.ApkMetadata:
|
|
return noneIfEmpty(metadata.URL)
|
|
case pkg.NpmPackageJSONMetadata:
|
|
return noneIfEmpty(metadata.URL)
|
|
default:
|
|
return "NOASSERTION"
|
|
}
|
|
}
|
|
|
|
func getSPDXHomepage(p *pkg.Package) string {
|
|
switch metadata := p.Metadata.(type) {
|
|
case pkg.GemMetadata:
|
|
return metadata.Homepage
|
|
case pkg.NpmPackageJSONMetadata:
|
|
return metadata.Homepage
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func getSPDXSourceInfo(p *pkg.Package) string {
|
|
answer := ""
|
|
switch p.Type {
|
|
case pkg.RpmPkg:
|
|
answer = "acquired package info from RPM DB"
|
|
case pkg.ApkPkg:
|
|
answer = "acquired package info from APK DB"
|
|
case pkg.DebPkg:
|
|
answer = "acquired package info from DPKG DB"
|
|
case pkg.NpmPkg:
|
|
answer = "acquired package info from installed node module manifest file"
|
|
case pkg.PythonPkg:
|
|
answer = "acquired package info from installed python package manifest file"
|
|
case pkg.JavaPkg, pkg.JenkinsPluginPkg:
|
|
answer = "acquired package info from installed java archive"
|
|
case pkg.GemPkg:
|
|
answer = "acquired package info from installed gem metadata file"
|
|
case pkg.GoModulePkg:
|
|
answer = "acquired package info from go module information"
|
|
case pkg.RustPkg:
|
|
answer = "acquired package info from rust cargo manifest"
|
|
default:
|
|
answer = "acquired package info from the following paths"
|
|
}
|
|
var paths []string
|
|
for _, l := range p.Locations {
|
|
paths = append(paths, l.RealPath)
|
|
}
|
|
|
|
return answer + ": " + strings.Join(paths, ", ")
|
|
}
|
|
|
|
func getSPDXOriginator(p *pkg.Package) string {
|
|
switch metadata := p.Metadata.(type) {
|
|
case pkg.ApkMetadata:
|
|
return metadata.Maintainer
|
|
case pkg.NpmPackageJSONMetadata:
|
|
return metadata.Author
|
|
case pkg.PythonPackageMetadata:
|
|
author := metadata.Author
|
|
if author == "" {
|
|
return metadata.AuthorEmail
|
|
}
|
|
if metadata.AuthorEmail != "" {
|
|
author += fmt.Sprintf(" <%s>", metadata.AuthorEmail)
|
|
}
|
|
return author
|
|
case pkg.GemMetadata:
|
|
if len(metadata.Authors) > 0 {
|
|
return metadata.Authors[0]
|
|
}
|
|
return ""
|
|
case pkg.RpmdbMetadata:
|
|
return metadata.Vendor
|
|
case pkg.DpkgMetadata:
|
|
return metadata.Maintainer
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func getSPDXDescription(p *pkg.Package) string {
|
|
switch metadata := p.Metadata.(type) {
|
|
case pkg.ApkMetadata:
|
|
return metadata.Description
|
|
case pkg.NpmPackageJSONMetadata:
|
|
return metadata.Description
|
|
default:
|
|
return ""
|
|
}
|
|
}
|