mirror of
https://github.com/anchore/syft.git
synced 2026-11-04 00:16:38 +01:00
add sbom document import lib helper function
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
+118
-14
@@ -1,18 +1,36 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/scope"
|
||||
)
|
||||
|
||||
type Artifact struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Type string `json:"type"`
|
||||
FoundBy []string `json:"foundBy"`
|
||||
Locations Locations `json:"locations,omitempty"`
|
||||
Licenses []string `json:"licenses"`
|
||||
Metadata interface{} `json:"metadata,omitempty"`
|
||||
ArtifactBasicMetadata
|
||||
ArtifactCustomMetadata
|
||||
}
|
||||
|
||||
type ArtifactBasicMetadata struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Type string `json:"type"`
|
||||
FoundBy []string `json:"foundBy"`
|
||||
Locations Locations `json:"locations,omitempty"`
|
||||
Licenses []string `json:"licenses"`
|
||||
Language string `json:"language"`
|
||||
}
|
||||
|
||||
type ArtifactCustomMetadata struct {
|
||||
MetadataType pkg.MetadataType `json:"metadataType"`
|
||||
Metadata interface{} `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
type ArtifactMetadataUnpacker struct {
|
||||
MetadataType string `json:"metadataType"`
|
||||
Metadata json.RawMessage `json:"metadata"`
|
||||
}
|
||||
|
||||
func NewArtifact(p *pkg.Package, s scope.Scope) (Artifact, error) {
|
||||
@@ -22,12 +40,98 @@ func NewArtifact(p *pkg.Package, s scope.Scope) (Artifact, error) {
|
||||
}
|
||||
|
||||
return Artifact{
|
||||
Name: p.Name,
|
||||
Version: p.Version,
|
||||
Type: string(p.Type),
|
||||
FoundBy: []string{p.FoundBy},
|
||||
Locations: locations,
|
||||
Licenses: p.Licenses,
|
||||
Metadata: p.Metadata,
|
||||
ArtifactBasicMetadata: ArtifactBasicMetadata{
|
||||
Name: p.Name,
|
||||
Version: p.Version,
|
||||
Type: string(p.Type),
|
||||
FoundBy: []string{p.FoundBy},
|
||||
Locations: locations,
|
||||
Licenses: p.Licenses,
|
||||
Language: string(p.Language),
|
||||
},
|
||||
ArtifactCustomMetadata: ArtifactCustomMetadata{
|
||||
MetadataType: p.MetadataType,
|
||||
Metadata: p.Metadata,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a Artifact) ToPackage() pkg.Package {
|
||||
return pkg.Package{
|
||||
// does not include found-by and locations
|
||||
Name: a.Name,
|
||||
Version: a.Version,
|
||||
Licenses: a.Licenses,
|
||||
Language: pkg.Language(a.Language),
|
||||
Type: pkg.Type(a.Type),
|
||||
MetadataType: a.MetadataType,
|
||||
Metadata: a.Metadata,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Artifact) UnmarshalJSON(b []byte) error {
|
||||
var basic ArtifactBasicMetadata
|
||||
if err := json.Unmarshal(b, &basic); err != nil {
|
||||
return err
|
||||
}
|
||||
a.ArtifactBasicMetadata = basic
|
||||
|
||||
var unpacker ArtifactMetadataUnpacker
|
||||
if err := json.Unmarshal(b, &unpacker); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.MetadataType = pkg.MetadataType(unpacker.MetadataType)
|
||||
|
||||
switch a.MetadataType {
|
||||
case pkg.RpmdbMetadataType:
|
||||
var payload pkg.RpmdbMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Metadata = payload
|
||||
case pkg.PythonPackageMetadataType:
|
||||
var payload pkg.PythonPackageMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Metadata = payload
|
||||
case pkg.DpkgMetadataType:
|
||||
var payload pkg.DpkgMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Metadata = payload
|
||||
case pkg.ApkMetadataType:
|
||||
var payload pkg.ApkMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Metadata = payload
|
||||
case pkg.JavaMetadataType:
|
||||
var payload pkg.JavaMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Metadata = payload
|
||||
case pkg.NpmPackageJSONMetadataType:
|
||||
var payload pkg.NpmPackageJSONMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Metadata = payload
|
||||
case pkg.GemMetadataType:
|
||||
var payload pkg.GemMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Metadata = payload
|
||||
case "":
|
||||
// there may be packages with no metadata, which is OK
|
||||
default:
|
||||
return fmt.Errorf("unsupported package metadata type: %+v", a.MetadataType)
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,18 +1,31 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/version"
|
||||
"github.com/anchore/syft/syft/distro"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/scope"
|
||||
)
|
||||
|
||||
type Document struct {
|
||||
Artifacts []Artifact `json:"artifacts"`
|
||||
Source Source `json:"source"`
|
||||
Distro Distribution `json:"distro"`
|
||||
Artifacts []Artifact `json:"artifacts"`
|
||||
Source Source `json:"source"`
|
||||
Distro Distribution `json:"distro"`
|
||||
Descriptor Descriptor `json:"descriptor"`
|
||||
}
|
||||
|
||||
// Distritbution provides information about a detected Linux Distribution
|
||||
// Descriptor describes what created the document as well as surrounding metadata
|
||||
type Descriptor struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
ReportTimestamp string `json:"reportTimestamp"`
|
||||
// TODO: we should include scope option here as well (or in source)
|
||||
}
|
||||
|
||||
// Distribution provides information about a detected Linux Distribution
|
||||
type Distribution struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
@@ -20,23 +33,29 @@ type Distribution struct {
|
||||
}
|
||||
|
||||
func NewDocument(catalog *pkg.Catalog, s scope.Scope, d distro.Distro) (Document, error) {
|
||||
doc := Document{
|
||||
Artifacts: make([]Artifact, 0),
|
||||
}
|
||||
|
||||
src, err := NewSource(s)
|
||||
if err != nil {
|
||||
return Document{}, nil
|
||||
}
|
||||
doc.Source = src
|
||||
|
||||
distroName := d.Name()
|
||||
if distroName == "UnknownDistroType" {
|
||||
distroName = ""
|
||||
}
|
||||
doc.Distro = Distribution{
|
||||
Name: distroName,
|
||||
Version: d.FullVersion(),
|
||||
IDLike: d.IDLike,
|
||||
|
||||
doc := Document{
|
||||
Artifacts: make([]Artifact, 0),
|
||||
Source: src,
|
||||
Distro: Distribution{
|
||||
Name: distroName,
|
||||
Version: d.FullVersion(),
|
||||
IDLike: d.IDLike,
|
||||
},
|
||||
Descriptor: Descriptor{
|
||||
Name: internal.ApplicationName,
|
||||
Version: version.FromBuild().Version,
|
||||
ReportTimestamp: time.Now().Format(time.RFC3339),
|
||||
},
|
||||
}
|
||||
|
||||
for _, p := range catalog.Sorted() {
|
||||
|
||||
@@ -25,11 +25,18 @@ func TestJsonDirsPresenter(t *testing.T) {
|
||||
catalog.Add(pkg.Package{
|
||||
Name: "package-1",
|
||||
Version: "1.0.1",
|
||||
Type: pkg.DebPkg,
|
||||
Type: pkg.PythonPkg,
|
||||
FoundBy: "the-cataloger-1",
|
||||
Source: []file.Reference{
|
||||
{Path: "/some/path/pkg1"},
|
||||
},
|
||||
Language: pkg.Python,
|
||||
MetadataType: pkg.PythonPackageMetadataType,
|
||||
Licenses: []string{"MIT"},
|
||||
Metadata: pkg.PythonPackageMetadata{
|
||||
Name: "package-1",
|
||||
Version: "1.0.1",
|
||||
},
|
||||
})
|
||||
catalog.Add(pkg.Package{
|
||||
Name: "package-2",
|
||||
@@ -39,6 +46,11 @@ func TestJsonDirsPresenter(t *testing.T) {
|
||||
Source: []file.Reference{
|
||||
{Path: "/some/path/pkg1"},
|
||||
},
|
||||
MetadataType: pkg.DpkgMetadataType,
|
||||
Metadata: pkg.DpkgMetadata{
|
||||
Package: "package-2",
|
||||
Version: "2.0.1",
|
||||
},
|
||||
})
|
||||
d := distro.NewUnknownDistro()
|
||||
s, err := scope.NewScopeFromDir("/some/path")
|
||||
@@ -87,8 +99,15 @@ func TestJsonImgsPresenter(t *testing.T) {
|
||||
Source: []file.Reference{
|
||||
*img.SquashedTree().File("/somefile-1.txt"),
|
||||
},
|
||||
Type: pkg.DebPkg,
|
||||
FoundBy: "the-cataloger-1",
|
||||
Type: pkg.PythonPkg,
|
||||
FoundBy: "the-cataloger-1",
|
||||
Language: pkg.Python,
|
||||
MetadataType: pkg.PythonPackageMetadataType,
|
||||
Licenses: []string{"MIT"},
|
||||
Metadata: pkg.PythonPackageMetadata{
|
||||
Name: "package-1",
|
||||
Version: "1.0.1",
|
||||
},
|
||||
})
|
||||
catalog.Add(pkg.Package{
|
||||
Name: "package-2",
|
||||
@@ -96,8 +115,13 @@ func TestJsonImgsPresenter(t *testing.T) {
|
||||
Source: []file.Reference{
|
||||
*img.SquashedTree().File("/somefile-2.txt"),
|
||||
},
|
||||
Type: pkg.DebPkg,
|
||||
FoundBy: "the-cataloger-2",
|
||||
Type: pkg.DebPkg,
|
||||
FoundBy: "the-cataloger-2",
|
||||
MetadataType: pkg.DpkgMetadataType,
|
||||
Metadata: pkg.DpkgMetadata{
|
||||
Package: "package-2",
|
||||
Version: "2.0.1",
|
||||
},
|
||||
})
|
||||
|
||||
s, err := scope.NewScopeFromImage(img, scope.AllLayersScope)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/anchore/syft/syft/scope"
|
||||
@@ -11,6 +12,11 @@ type Source struct {
|
||||
Target interface{} `json:"target"`
|
||||
}
|
||||
|
||||
type SourceUnpacker struct {
|
||||
Type string `json:"type"`
|
||||
Target json.RawMessage `json:"target"`
|
||||
}
|
||||
|
||||
func NewSource(s scope.Scope) (Source, error) {
|
||||
switch src := s.Source.(type) {
|
||||
case scope.ImageSource:
|
||||
@@ -27,3 +33,26 @@ func NewSource(s scope.Scope) (Source, error) {
|
||||
return Source{}, fmt.Errorf("unsupported source: %T", src)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Source) UnmarshalJSON(b []byte) error {
|
||||
var unpacker SourceUnpacker
|
||||
if err := json.Unmarshal(b, &unpacker); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Type = unpacker.Type
|
||||
|
||||
switch s.Type {
|
||||
case "image":
|
||||
var payload Image
|
||||
if err := json.Unmarshal(unpacker.Target, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
s.Target = payload
|
||||
default:
|
||||
return fmt.Errorf("unsupported package metadata type: %+v", s.Type)
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user