mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +01:00
208 lines
5.9 KiB
Go
208 lines
5.9 KiB
Go
package packages
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"path/filepath"
|
|
"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 getSPDXFiles(packageSpdxID string, p *pkg.Package) (files []spdx22.File, fileIDs []string, relationships []spdx22.Relationship) {
|
|
files = make([]spdx22.File, 0)
|
|
fileIDs = make([]string, 0)
|
|
relationships = make([]spdx22.Relationship, 0)
|
|
|
|
pkgFileOwner, ok := p.Metadata.(pkg.FileOwner)
|
|
if !ok {
|
|
return files, fileIDs, relationships
|
|
}
|
|
|
|
for _, ownedFilePath := range pkgFileOwner.OwnedFiles() {
|
|
baseFileName := filepath.Base(ownedFilePath)
|
|
pathHash := sha256.Sum256([]byte(ownedFilePath))
|
|
fileSpdxID := spdx22.ElementID(fmt.Sprintf("File-%s-%x", p.Name, pathHash)).String()
|
|
|
|
fileIDs = append(fileIDs, fileSpdxID)
|
|
|
|
files = append(files, spdx22.File{
|
|
FileName: ownedFilePath,
|
|
Item: spdx22.Item{
|
|
Element: spdx22.Element{
|
|
SPDXID: fileSpdxID,
|
|
Name: baseFileName,
|
|
},
|
|
},
|
|
})
|
|
|
|
relationships = append(relationships, spdx22.Relationship{
|
|
SpdxElementID: packageSpdxID,
|
|
RelationshipType: spdx22.ContainsRelationship,
|
|
RelatedSpdxElement: fileSpdxID,
|
|
})
|
|
}
|
|
|
|
return files, fileIDs, relationships
|
|
}
|
|
|
|
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 {
|
|
var answer string
|
|
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 ""
|
|
}
|
|
}
|