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>
100 lines
3.3 KiB
Go
100 lines
3.3 KiB
Go
package packages
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
|
|
"github.com/anchore/syft/internal"
|
|
"github.com/anchore/syft/internal/presenter/packages/model/spdx22"
|
|
"github.com/anchore/syft/internal/spdxlicense"
|
|
"github.com/anchore/syft/internal/version"
|
|
"github.com/anchore/syft/syft/pkg"
|
|
"github.com/anchore/syft/syft/source"
|
|
)
|
|
|
|
// SPDXJsonPresenter is a SPDX presentation object for the syft results (see https://github.com/spdx/spdx-spec)
|
|
type SPDXJsonPresenter struct {
|
|
catalog *pkg.Catalog
|
|
srcMetadata source.Metadata
|
|
}
|
|
|
|
// NewSPDXJSONPresenter creates a new JSON presenter object for the given cataloging results.
|
|
func NewSPDXJSONPresenter(catalog *pkg.Catalog, srcMetadata source.Metadata) *SPDXJsonPresenter {
|
|
return &SPDXJsonPresenter{
|
|
catalog: catalog,
|
|
srcMetadata: srcMetadata,
|
|
}
|
|
}
|
|
|
|
// Present the catalog results to the given writer.
|
|
func (pres *SPDXJsonPresenter) Present(output io.Writer) error {
|
|
doc := newSPDXJsonDocument(pres.catalog, pres.srcMetadata)
|
|
|
|
enc := json.NewEncoder(output)
|
|
// prevent > and < from being escaped in the payload
|
|
enc.SetEscapeHTML(false)
|
|
enc.SetIndent("", " ")
|
|
return enc.Encode(&doc)
|
|
}
|
|
|
|
func newSPDXJsonDocument(catalog *pkg.Catalog, srcMetadata source.Metadata) spdx22.Document {
|
|
var name string
|
|
switch srcMetadata.Scheme {
|
|
case source.ImageScheme:
|
|
name = srcMetadata.ImageMetadata.UserInput
|
|
case source.DirectoryScheme:
|
|
name = srcMetadata.Path
|
|
}
|
|
|
|
return spdx22.Document{
|
|
Element: spdx22.Element{
|
|
SPDXID: spdx22.ElementID("DOCUMENT").String(),
|
|
Name: name,
|
|
},
|
|
SPDXVersion: spdx22.Version,
|
|
CreationInfo: spdx22.CreationInfo{
|
|
Created: time.Now().UTC(),
|
|
Creators: []string{
|
|
// note: key-value format derived from the JSON example document examples: https://github.com/spdx/spdx-spec/blob/v2.2/examples/SPDXJSONExample-v2.2.spdx.json
|
|
"Organization: Anchore, Inc",
|
|
"Tool: " + internal.ApplicationName + "-" + version.FromBuild().Version,
|
|
},
|
|
LicenseListVersion: spdxlicense.Version,
|
|
},
|
|
DataLicense: "CC0-1.0",
|
|
DocumentNamespace: fmt.Sprintf("https://anchore.com/syft/image/%s", srcMetadata.ImageMetadata.UserInput),
|
|
Packages: newSPDXJsonPackages(catalog),
|
|
}
|
|
}
|
|
|
|
func newSPDXJsonPackages(catalog *pkg.Catalog) []spdx22.Package {
|
|
results := make([]spdx22.Package, 0)
|
|
for _, p := range catalog.Sorted() {
|
|
license := getSPDXLicense(p)
|
|
|
|
// note: the license concluded and declared should be the same since we are collecting license information
|
|
// from the project data itself (the installed package files).
|
|
results = append(results, spdx22.Package{
|
|
Description: getSPDXDescription(p),
|
|
DownloadLocation: getSPDXDownloadLocation(p),
|
|
ExternalRefs: getSPDXExternalRefs(p),
|
|
FilesAnalyzed: false,
|
|
Homepage: getSPDXHomepage(p),
|
|
LicenseDeclared: license, // The Declared License is what the authors of a project believe govern the package
|
|
Originator: getSPDXOriginator(p),
|
|
SourceInfo: getSPDXSourceInfo(p),
|
|
VersionInfo: p.Version,
|
|
Item: spdx22.Item{
|
|
LicenseConcluded: license, // The Concluded License field is the license the SPDX file creator believes governs the package
|
|
Element: spdx22.Element{
|
|
SPDXID: spdx22.ElementID(fmt.Sprintf("Package-%+v-%s-%s", p.Type, p.Name, p.Version)).String(),
|
|
Name: p.Name,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
return results
|
|
}
|