From 9ded1c4c22c3c527e1b57e390ec53cb5ccc0a8b0 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:28:40 -0700 Subject: [PATCH 01/17] add basic format abstraction Signed-off-by: Alex Goodman --- syft/format/decoder.go | 12 ++++++++ syft/format/encoder.go | 22 ++++++++++++++ syft/format/format.go | 65 ++++++++++++++++++++++++++++++++++++++++ syft/format/option.go | 43 ++++++++++++++++++++++++++ syft/format/presenter.go | 30 +++++++++++++++++++ syft/format/validator.go | 5 ++++ 6 files changed, 177 insertions(+) create mode 100644 syft/format/decoder.go create mode 100644 syft/format/encoder.go create mode 100644 syft/format/format.go create mode 100644 syft/format/option.go create mode 100644 syft/format/presenter.go create mode 100644 syft/format/validator.go diff --git a/syft/format/decoder.go b/syft/format/decoder.go new file mode 100644 index 00000000000..149e3640047 --- /dev/null +++ b/syft/format/decoder.go @@ -0,0 +1,12 @@ +package format + +import ( + "io" + + "github.com/anchore/syft/syft/distro" + + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +type Decoder func(reader io.Reader) (*pkg.Catalog, *source.Metadata, *distro.Distro, error) diff --git a/syft/format/encoder.go b/syft/format/encoder.go new file mode 100644 index 00000000000..46e1d3b75d7 --- /dev/null +++ b/syft/format/encoder.go @@ -0,0 +1,22 @@ +package format + +import ( + "io" + + "github.com/anchore/syft/syft/distro" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +// TODO: this should probably be a helper function to return the bytes +//func using() { +// var buff bytes.Buffer +// var encoder Encoder // = ... +// +// _:=encoder(&buff, nil, nil, nil) +// +// bytes.NewReader(buff.Bytes()) +// +//} + +type Encoder func(io.Writer, *pkg.Catalog, *source.Metadata, *distro.Distro) error diff --git a/syft/format/format.go b/syft/format/format.go new file mode 100644 index 00000000000..6bb12bf1185 --- /dev/null +++ b/syft/format/format.go @@ -0,0 +1,65 @@ +package format + +import ( + "bytes" + "errors" + "io" + + "github.com/anchore/syft/syft/distro" + + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +var ( + ErrEncodingNotSupported = errors.New("encoding not supported") + ErrDecodingNotSupported = errors.New("decoding not supported") +) + +type Format struct { + Option Option + encoder Encoder + decoder Decoder + validator Validator +} + +func NewFormat(option Option, encoder Encoder, decoder Decoder, validator Validator) Format { + return Format{ + Option: option, + encoder: encoder, + decoder: decoder, + validator: validator, + } +} + +func (f Format) Encode(output io.Writer, catalog *pkg.Catalog, d *distro.Distro, metadata *source.Metadata) error { + if f.encoder == nil { + return ErrEncodingNotSupported + } + return f.encoder(output, catalog, metadata, d) +} + +func (f Format) Decode(reader io.Reader) (*pkg.Catalog, *source.Metadata, *distro.Distro, error) { + if f.decoder == nil { + return nil, nil, nil, ErrDecodingNotSupported + } + return f.decoder(reader) +} + +func (f Format) Detect(b []byte) bool { + if f.validator == nil { + return false + } + + if err := f.validator(bytes.NewReader(b)); err != nil { + return false + } + return true +} + +func (f Format) Presenter(catalog *pkg.Catalog, metadata *source.Metadata, d *distro.Distro) *Presenter { + if f.encoder == nil { + return nil + } + return NewPresenter(f.encoder, catalog, metadata, d) +} diff --git a/syft/format/option.go b/syft/format/option.go new file mode 100644 index 00000000000..805656c1193 --- /dev/null +++ b/syft/format/option.go @@ -0,0 +1,43 @@ +package format + +import "strings" + +const ( + UnknownOption Option = "UnknownFormatOption" + JSONOption Option = "json" + TextOption Option = "text" + TableOption Option = "table" + CycloneDxOption Option = "cyclonedx" + SPDXTagValueOption Option = "spdx-tag-value" + SPDXJSONOption Option = "spdx-json" +) + +var AllOptions = []Option{ + JSONOption, + TextOption, + TableOption, + CycloneDxOption, + SPDXTagValueOption, + SPDXJSONOption, +} + +type Option string + +func ParseOption(userStr string) Option { + switch strings.ToLower(userStr) { + case string(JSONOption), "syft-json": + return JSONOption + case string(TextOption): + return TextOption + case string(TableOption): + return TableOption + case string(CycloneDxOption), "cyclone", "cyclone-dx": + return CycloneDxOption + case string(SPDXTagValueOption), "spdx", "spdx-tagvalue", "spdxtagvalue", "spdx-tv", "spdxtv": + return SPDXTagValueOption + case string(SPDXJSONOption), "spdxjson": + return SPDXJSONOption + default: + return UnknownOption + } +} diff --git a/syft/format/presenter.go b/syft/format/presenter.go new file mode 100644 index 00000000000..3915f3cb74b --- /dev/null +++ b/syft/format/presenter.go @@ -0,0 +1,30 @@ +package format + +import ( + "io" + + "github.com/anchore/syft/syft/distro" + + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +type Presenter struct { + catalog *pkg.Catalog + srcMetadata *source.Metadata + distro *distro.Distro + encoder Encoder +} + +func NewPresenter(encoder Encoder, catalog *pkg.Catalog, srcMetadata *source.Metadata, d *distro.Distro) *Presenter { + return &Presenter{ + catalog: catalog, + srcMetadata: srcMetadata, + distro: d, + encoder: encoder, + } +} + +func (pres *Presenter) Present(output io.Writer) error { + return pres.encoder(output, pres.catalog, pres.srcMetadata, pres.distro) +} diff --git a/syft/format/validator.go b/syft/format/validator.go new file mode 100644 index 00000000000..59269e27125 --- /dev/null +++ b/syft/format/validator.go @@ -0,0 +1,5 @@ +package format + +import "io" + +type Validator func(reader io.Reader) error From c1346ad62c72e2d20637830c36bd753c09ac2eb2 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:30:04 -0700 Subject: [PATCH 02/17] migrate json presenter to json format object Signed-off-by: Alex Goodman --- internal/formats/syftjson/decoder.go | 24 +++ internal/formats/syftjson/decoder_test.go | 50 ++++++ internal/formats/syftjson/encoder.go | 23 +++ internal/formats/syftjson/format.go | 12 ++ internal/formats/syftjson/model/distro.go | 8 + internal/formats/syftjson/model/document.go | 23 +++ internal/formats/syftjson/model/package.go | 122 +++++++++++++++ .../formats/syftjson/model/relationship.go | 8 + internal/formats/syftjson/model/source.go | 45 ++++++ .../test-fixtures/image-simple/Dockerfile | 4 + .../test-fixtures/image-simple/file-1.txt | 1 + .../test-fixtures/image-simple/file-2.txt | 1 + .../TestSPDXJSONDirectoryPresenter.golden | 79 ++++++++++ .../TestSPDXJSONImagePresenter.golden | 61 ++++++++ .../stereoscope-fixture-image-simple.golden | Bin 0 -> 15360 bytes internal/formats/syftjson/to_format_model.go | 144 ++++++++++++++++++ internal/formats/syftjson/to_syft_model.go | 70 +++++++++ internal/formats/syftjson/validator.go | 31 ++++ 18 files changed, 706 insertions(+) create mode 100644 internal/formats/syftjson/decoder.go create mode 100644 internal/formats/syftjson/decoder_test.go create mode 100644 internal/formats/syftjson/encoder.go create mode 100644 internal/formats/syftjson/format.go create mode 100644 internal/formats/syftjson/model/distro.go create mode 100644 internal/formats/syftjson/model/document.go create mode 100644 internal/formats/syftjson/model/package.go create mode 100644 internal/formats/syftjson/model/relationship.go create mode 100644 internal/formats/syftjson/model/source.go create mode 100644 internal/formats/syftjson/test-fixtures/image-simple/Dockerfile create mode 100644 internal/formats/syftjson/test-fixtures/image-simple/file-1.txt create mode 100644 internal/formats/syftjson/test-fixtures/image-simple/file-2.txt create mode 100644 internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden create mode 100644 internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden create mode 100644 internal/formats/syftjson/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden create mode 100644 internal/formats/syftjson/to_format_model.go create mode 100644 internal/formats/syftjson/to_syft_model.go create mode 100644 internal/formats/syftjson/validator.go diff --git a/internal/formats/syftjson/decoder.go b/internal/formats/syftjson/decoder.go new file mode 100644 index 00000000000..f1ee7baa90b --- /dev/null +++ b/internal/formats/syftjson/decoder.go @@ -0,0 +1,24 @@ +package syftjson + +import ( + "encoding/json" + "fmt" + "io" + + "github.com/anchore/syft/internal/formats/syftjson/model" + "github.com/anchore/syft/syft/distro" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +func decoder(reader io.Reader) (*pkg.Catalog, *source.Metadata, *distro.Distro, error) { + dec := json.NewDecoder(reader) + + var doc model.Document + err := dec.Decode(&doc) + if err != nil { + return nil, nil, nil, fmt.Errorf("unable to decode syft-json: %w", err) + } + + return toSyftModel(doc) +} diff --git a/internal/formats/syftjson/decoder_test.go b/internal/formats/syftjson/decoder_test.go new file mode 100644 index 00000000000..f60ccb684cf --- /dev/null +++ b/internal/formats/syftjson/decoder_test.go @@ -0,0 +1,50 @@ +package syftjson + +import ( + "bytes" + "strings" + "testing" + + "github.com/anchore/syft/internal/formats/common/testutils" + "github.com/go-test/deep" + "github.com/stretchr/testify/assert" +) + +func TestEncodeDecodeCycle(t *testing.T) { + testImage := "image-simple" + originalCatalog, originalMetadata, _ := testutils.ImageInput(t, testImage) + + var buf bytes.Buffer + assert.NoError(t, encoder(&buf, originalCatalog, &originalMetadata, nil)) + + actualCatalog, actualMetadata, _, err := decoder(bytes.NewReader(buf.Bytes())) + assert.NoError(t, err) + + for _, d := range deep.Equal(originalMetadata, *actualMetadata) { + t.Errorf("metadata difference: %+v", d) + } + + actualPackages := actualCatalog.Sorted() + for idx, p := range originalCatalog.Sorted() { + if !assert.Equal(t, p.Name, actualPackages[idx].Name) { + t.Errorf("different package at idx=%d: %s vs %s", idx, p.Name, actualPackages[idx].Name) + continue + } + + // ids will never be equal + p.ID = "" + actualPackages[idx].ID = "" + + for _, d := range deep.Equal(*p, *actualPackages[idx]) { + if strings.Contains(d, ".VirtualPath: ") { + // location.Virtual path is not exposed in the json output + continue + } + if strings.HasSuffix(d, " != []") { + // semantically the same + continue + } + t.Errorf("package difference (%s): %+v", p.Name, d) + } + } +} diff --git a/internal/formats/syftjson/encoder.go b/internal/formats/syftjson/encoder.go new file mode 100644 index 00000000000..533961a1e49 --- /dev/null +++ b/internal/formats/syftjson/encoder.go @@ -0,0 +1,23 @@ +package syftjson + +import ( + "encoding/json" + "io" + + "github.com/anchore/syft/syft/distro" + + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +func encoder(output io.Writer, catalog *pkg.Catalog, srcMetadata *source.Metadata, d *distro.Distro) error { + // TODO: application config not available yet + doc := ToFormatModel(catalog, srcMetadata, d, nil) + + enc := json.NewEncoder(output) + // prevent > and < from being escaped in the payload + enc.SetEscapeHTML(false) + enc.SetIndent("", " ") + + return enc.Encode(&doc) +} diff --git a/internal/formats/syftjson/format.go b/internal/formats/syftjson/format.go new file mode 100644 index 00000000000..bc3f5164289 --- /dev/null +++ b/internal/formats/syftjson/format.go @@ -0,0 +1,12 @@ +package syftjson + +import "github.com/anchore/syft/syft/format" + +func Format() format.Format { + return format.NewFormat( + format.JSONOption, + encoder, + decoder, + validator, + ) +} diff --git a/internal/formats/syftjson/model/distro.go b/internal/formats/syftjson/model/distro.go new file mode 100644 index 00000000000..b136f2505a7 --- /dev/null +++ b/internal/formats/syftjson/model/distro.go @@ -0,0 +1,8 @@ +package model + +// Distro provides information about a detected Linux Distro. +type Distro struct { + Name string `json:"name"` // Name of the Linux distribution + Version string `json:"version"` // Version of the Linux distribution (major or major.minor version) + IDLike string `json:"idLike"` // the ID_LIKE field found within the /etc/os-release file +} diff --git a/internal/formats/syftjson/model/document.go b/internal/formats/syftjson/model/document.go new file mode 100644 index 00000000000..71e76f62de1 --- /dev/null +++ b/internal/formats/syftjson/model/document.go @@ -0,0 +1,23 @@ +package model + +// Document represents the syft cataloging findings as a JSON document +type Document struct { + Artifacts []Package `json:"artifacts"` // Artifacts is the list of packages discovered and placed into the catalog + ArtifactRelationships []Relationship `json:"artifactRelationships"` + Source Source `json:"source"` // Source represents the original object that was cataloged + Distro Distro `json:"distro"` // Distro represents the Linux distribution that was detected from the source + Descriptor Descriptor `json:"descriptor"` // Descriptor is a block containing self-describing information about syft + Schema Schema `json:"schema"` // Schema is a block reserved for defining the version for the shape of this JSON document and where to find the schema document to validate the shape +} + +// Descriptor describes what created the document as well as surrounding metadata +type Descriptor struct { + Name string `json:"name"` + Version string `json:"version"` + Configuration interface{} `json:"configuration,omitempty"` +} + +type Schema struct { + Version string `json:"version"` + URL string `json:"url"` +} diff --git a/internal/formats/syftjson/model/package.go b/internal/formats/syftjson/model/package.go new file mode 100644 index 00000000000..9ee46806246 --- /dev/null +++ b/internal/formats/syftjson/model/package.go @@ -0,0 +1,122 @@ +package model + +import ( + "encoding/json" + "fmt" + + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +// Package represents a pkg.Package object specialized for JSON marshaling and unmarshaling. +type Package struct { + PackageBasicData + PackageCustomData +} + +// PackageBasicData contains non-ambiguous values (type-wise) from pkg.Package. +type PackageBasicData struct { + ID string `json:"id"` + Name string `json:"name"` + Version string `json:"version"` + Type pkg.Type `json:"type"` + FoundBy string `json:"foundBy"` + Locations []source.Location `json:"locations"` + Licenses []string `json:"licenses"` + Language pkg.Language `json:"language"` + CPEs []string `json:"cpes"` + PURL string `json:"purl"` +} + +// PackageCustomData contains ambiguous values (type-wise) from pkg.Package. +type PackageCustomData struct { + MetadataType pkg.MetadataType `json:"metadataType"` + Metadata interface{} `json:"metadata"` +} + +// packageMetadataUnpacker is all values needed from Package to disambiguate ambiguous fields during json unmarshaling. +type packageMetadataUnpacker struct { + MetadataType pkg.MetadataType `json:"metadataType"` + Metadata json.RawMessage `json:"metadata"` +} + +func (p *packageMetadataUnpacker) String() string { + return fmt.Sprintf("metadataType: %s, metadata: %s", p.MetadataType, string(p.Metadata)) +} + +// UnmarshalJSON is a custom unmarshaller for handling basic values and values with ambiguous types. +func (p *Package) UnmarshalJSON(b []byte) error { + var basic PackageBasicData + if err := json.Unmarshal(b, &basic); err != nil { + return err + } + p.PackageBasicData = basic + + var unpacker packageMetadataUnpacker + if err := json.Unmarshal(b, &unpacker); err != nil { + log.Warnf("failed to unmarshall into packageMetadataUnpacker: %v", err) + return err + } + + p.MetadataType = unpacker.MetadataType + + switch p.MetadataType { + case pkg.ApkMetadataType: + var payload pkg.ApkMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.RpmdbMetadataType: + var payload pkg.RpmdbMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.DpkgMetadataType: + var payload pkg.DpkgMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.JavaMetadataType: + var payload pkg.JavaMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.RustCargoPackageMetadataType: + var payload pkg.CargoPackageMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.GemMetadataType: + var payload pkg.GemMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.KbPackageMetadataType: + var payload pkg.KbPackageMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.PythonPackageMetadataType: + var payload pkg.PythonPackageMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.NpmPackageJSONMetadataType: + var payload pkg.NpmPackageJSONMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + } + + return nil +} diff --git a/internal/formats/syftjson/model/relationship.go b/internal/formats/syftjson/model/relationship.go new file mode 100644 index 00000000000..8820156bdc8 --- /dev/null +++ b/internal/formats/syftjson/model/relationship.go @@ -0,0 +1,8 @@ +package model + +type Relationship struct { + Parent string `json:"parent"` + Child string `json:"child"` + Type string `json:"type"` + Metadata interface{} `json:"metadata"` +} diff --git a/internal/formats/syftjson/model/source.go b/internal/formats/syftjson/model/source.go new file mode 100644 index 00000000000..4e6de60dc5d --- /dev/null +++ b/internal/formats/syftjson/model/source.go @@ -0,0 +1,45 @@ +package model + +import ( + "encoding/json" + "fmt" + + "github.com/anchore/syft/syft/source" +) + +// Source object represents the thing that was cataloged +type Source struct { + Type string `json:"type"` + Target interface{} `json:"target"` +} + +// sourceUnpacker is used to unmarshal Source objects +type sourceUnpacker struct { + Type string `json:"type"` + Target json.RawMessage `json:"target"` +} + +// UnmarshalJSON populates a source object from JSON bytes. +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 "directory": + s.Target = string(unpacker.Target[:]) + case "image": + var payload source.ImageMetadata + 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 +} diff --git a/internal/formats/syftjson/test-fixtures/image-simple/Dockerfile b/internal/formats/syftjson/test-fixtures/image-simple/Dockerfile new file mode 100644 index 00000000000..79cfa759e35 --- /dev/null +++ b/internal/formats/syftjson/test-fixtures/image-simple/Dockerfile @@ -0,0 +1,4 @@ +# Note: changes to this file will result in updating several test values. Consider making a new image fixture instead of editing this one. +FROM scratch +ADD file-1.txt /somefile-1.txt +ADD file-2.txt /somefile-2.txt diff --git a/internal/formats/syftjson/test-fixtures/image-simple/file-1.txt b/internal/formats/syftjson/test-fixtures/image-simple/file-1.txt new file mode 100644 index 00000000000..985d3408e98 --- /dev/null +++ b/internal/formats/syftjson/test-fixtures/image-simple/file-1.txt @@ -0,0 +1 @@ +this file has contents \ No newline at end of file diff --git a/internal/formats/syftjson/test-fixtures/image-simple/file-2.txt b/internal/formats/syftjson/test-fixtures/image-simple/file-2.txt new file mode 100644 index 00000000000..396d08bbc72 --- /dev/null +++ b/internal/formats/syftjson/test-fixtures/image-simple/file-2.txt @@ -0,0 +1 @@ +file-2 contents! \ No newline at end of file diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden new file mode 100644 index 00000000000..249517449ad --- /dev/null +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden @@ -0,0 +1,79 @@ +{ + "SPDXID": "SPDXRef-DOCUMENT", + "name": "/some/path", + "spdxVersion": "SPDX-2.2", + "creationInfo": { + "created": "2021-09-16T20:44:35.198887Z", + "creators": [ + "Organization: Anchore, Inc", + "Tool: syft-[not provided]" + ], + "licenseListVersion": "3.14" + }, + "dataLicense": "CC0-1.0", + "documentNamespace": "https://anchore.com/syft/image/", + "packages": [ + { + "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", + "name": "package-1", + "licenseConcluded": "MIT", + "downloadLocation": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "a-purl-2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9" + ], + "licenseDeclared": "MIT", + "sourceInfo": "acquired package info from installed python package manifest file: /some/path/pkg1", + "versionInfo": "1.0.1" + }, + { + "SPDXID": "SPDXRef-Package-deb-package-2-2.0.1", + "name": "package-2", + "licenseConcluded": "NONE", + "downloadLocation": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "a-purl-2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseDeclared": "NONE", + "sourceInfo": "acquired package info from DPKG DB: /some/path/pkg1", + "versionInfo": "2.0.1" + } + ], + "files": [ + { + "SPDXID": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9", + "name": "foo", + "licenseConcluded": "", + "fileName": "/some/path/pkg1/depedencies/foo" + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-Package-python-package-1-1.0.1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9" + } + ] +} diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden new file mode 100644 index 00000000000..8906ef161ac --- /dev/null +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden @@ -0,0 +1,61 @@ +{ + "SPDXID": "SPDXRef-DOCUMENT", + "name": "user-image-input", + "spdxVersion": "SPDX-2.2", + "creationInfo": { + "created": "2021-09-16T20:44:35.203911Z", + "creators": [ + "Organization: Anchore, Inc", + "Tool: syft-[not provided]" + ], + "licenseListVersion": "3.14" + }, + "dataLicense": "CC0-1.0", + "documentNamespace": "https://anchore.com/syft/image/user-image-input", + "packages": [ + { + "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", + "name": "package-1", + "licenseConcluded": "MIT", + "downloadLocation": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "a-purl-1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseDeclared": "MIT", + "sourceInfo": "acquired package info from installed python package manifest file: /somefile-1.txt", + "versionInfo": "1.0.1" + }, + { + "SPDXID": "SPDXRef-Package-deb-package-2-2.0.1", + "name": "package-2", + "licenseConcluded": "NONE", + "downloadLocation": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "a-purl-2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseDeclared": "NONE", + "sourceInfo": "acquired package info from DPKG DB: /somefile-2.txt", + "versionInfo": "2.0.1" + } + ] +} diff --git a/internal/formats/syftjson/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden b/internal/formats/syftjson/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden new file mode 100644 index 0000000000000000000000000000000000000000..c1b1d2b797ecd34a5276a1aa2fb18c5b0a58c732 GIT binary patch literal 15360 zcmeHO+iu%N5Y=ZaKc z4r#BxuDkuJ7{OBcm#%FzyUOYr8lw^9HIDjR+4F_Fg0dOV`$VGKgH38I>Hgnpur)R2 zl)HY_XM^MD!m4A0dKhDcAS?&*f(4T;Kn>ke#l4gzVN` ze(?Rjwf#RFzkC1s- z9>CiEk8VKl|Mzk`OrxxEw%gtY==qIJx$uy+*ED8?qX(EcDL{I387Ngsb4dh?x$wg9 z*h*rg6@ZQ(w@kA*(GHyphO!?TNJz`YJ>fe4rt;(!W2awfa(sRRC68dzXajVE@y-n>o(^op5E2ZJDVs7 z4hRGU0s;YnXN7=m8LaJu|D{?6{&zpONo)J>g#RTf@W1=9f8c-jgY$EprS<=wcn6J zY-{-4@PCvC{%=1g#vT7ROM=?XoSXT-=K0?$|A*;W&6n z=@JS7fq+0jARzERL||m{EQP9mOdkK&{`^hnzm$9>7qof)M_D-kzZUPOjKl2tmy1l1 zh;8Ft5R3%h!MHdz7xT>W8cHZCSB&8>&90l53=Xp<>E*D>M<2Vo8*8l9D*K-ZL#y zZQ=xy1TbwlA*sSvk$`4t>Jlk6(avMSc$^Yo%t_n4Rq$q>(~gPk+Y4v#cWf^=0@K;g zetL>o_SUyVTU8mpNs&Rdt4TMle|Dc6KFbBi^{-S||GP5Biri^bZCIhryCba^=@v2! WZ*QOH3R;0P6aoSPfq=kwgTOxo35itz literal 0 HcmV?d00001 diff --git a/internal/formats/syftjson/to_format_model.go b/internal/formats/syftjson/to_format_model.go new file mode 100644 index 00000000000..eacce565ee8 --- /dev/null +++ b/internal/formats/syftjson/to_format_model.go @@ -0,0 +1,144 @@ +package syftjson + +import ( + "fmt" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/formats/syftjson/model" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/version" + "github.com/anchore/syft/syft/distro" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +//// NewJSONDocument creates and populates a new JSON document struct from the given cataloging results. +//func NewJSONDocument(catalog *pkg.Catalog, srcMetadata source.Metadata, d *distro.Distro, scope source.Scope, configuration interface{}) (Document, error) { +// +//} + +// TODO: this is export4ed for the use of the power-user command (temp) +func ToFormatModel(catalog *pkg.Catalog, srcMetadata *source.Metadata, d *distro.Distro, applicationConfig interface{}) model.Document { + src, err := toSourceModel(srcMetadata) + if err != nil { + log.Warnf("unable to create syft-json source object: %+v", err) + } + + artifacts, err := toPackageModels(catalog) + if err != nil { + return model.Document{} + } + + return model.Document{ + Artifacts: artifacts, + ArtifactRelationships: toRelationshipModel(pkg.NewRelationships(catalog)), + Source: src, + Distro: toDistroModel(d), + Descriptor: model.Descriptor{ + Name: internal.ApplicationName, + Version: version.FromBuild().Version, + Configuration: applicationConfig, + }, + Schema: model.Schema{ + Version: internal.JSONSchemaVersion, + URL: fmt.Sprintf("https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-%s.json", internal.JSONSchemaVersion), + }, + } +} + +func toPackageModels(catalog *pkg.Catalog) ([]model.Package, error) { + artifacts := make([]model.Package, 0) + if catalog == nil { + return artifacts, nil + } + for _, p := range catalog.Sorted() { + art, err := toPackageModel(p) + if err != nil { + return nil, err + } + artifacts = append(artifacts, art) + } + return artifacts, nil +} + +// toPackageModel crates a new Package from the given pkg.Package. +func toPackageModel(p *pkg.Package) (model.Package, error) { + var cpes = make([]string, len(p.CPEs)) + for i, c := range p.CPEs { + cpes[i] = c.BindToFmtString() + } + + // ensure collections are never nil for presentation reasons + var locations = make([]source.Location, 0) + if p.Locations != nil { + locations = p.Locations + } + + var licenses = make([]string, 0) + if p.Licenses != nil { + licenses = p.Licenses + } + + return model.Package{ + PackageBasicData: model.PackageBasicData{ + ID: string(p.ID), + Name: p.Name, + Version: p.Version, + Type: p.Type, + FoundBy: p.FoundBy, + Locations: locations, + Licenses: licenses, + Language: p.Language, + CPEs: cpes, + PURL: p.PURL, + }, + PackageCustomData: model.PackageCustomData{ + MetadataType: p.MetadataType, + Metadata: p.Metadata, + }, + }, nil +} + +func toRelationshipModel(relationships []pkg.Relationship) []model.Relationship { + result := make([]model.Relationship, len(relationships)) + for i, r := range relationships { + result[i] = model.Relationship{ + Parent: string(r.Parent), + Child: string(r.Child), + Type: string(r.Type), + Metadata: r.Metadata, + } + } + return result +} + +// toSourceModel creates a new source object to be represented into JSON. +func toSourceModel(src *source.Metadata) (model.Source, error) { + switch src.Scheme { + case source.ImageScheme: + return model.Source{ + Type: "image", + Target: src.ImageMetadata, + }, nil + case source.DirectoryScheme: + return model.Source{ + Type: "directory", + Target: src.Path, + }, nil + default: + return model.Source{}, fmt.Errorf("unsupported source: %q", src.Scheme) + } +} + +// toDistroModel creates a struct with the Linux distribution to be represented in JSON. +func toDistroModel(d *distro.Distro) model.Distro { + if d == nil { + return model.Distro{} + } + + return model.Distro{ + Name: d.Name(), + Version: d.FullVersion(), + IDLike: d.IDLike, + } +} diff --git a/internal/formats/syftjson/to_syft_model.go b/internal/formats/syftjson/to_syft_model.go new file mode 100644 index 00000000000..88dd12b1894 --- /dev/null +++ b/internal/formats/syftjson/to_syft_model.go @@ -0,0 +1,70 @@ +package syftjson + +import ( + "github.com/anchore/syft/internal/formats/syftjson/model" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/distro" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +func toSyftModel(doc model.Document) (*pkg.Catalog, *source.Metadata, *distro.Distro, error) { + dist, err := distro.NewDistro(distro.Type(doc.Distro.Name), doc.Distro.Version, doc.Distro.IDLike) + if err != nil { + return nil, nil, nil, err + } + + return toSyftCatalog(doc.Artifacts), toSyftSourceMetadata(doc.Source), &dist, nil +} + +func toSyftSourceMetadata(s model.Source) *source.Metadata { + switch s.Type { + case "directory": + return &source.Metadata{ + Scheme: source.DirectoryScheme, + Path: s.Target.(string), + } + case "image": + return &source.Metadata{ + Scheme: source.ImageScheme, + ImageMetadata: s.Target.(source.ImageMetadata), + } + } + return nil +} + +func toSyftCatalog(pkgs []model.Package) *pkg.Catalog { + catalog := pkg.NewCatalog() + for _, p := range pkgs { + catalog.Add(toSyftPackage(p)) + } + return catalog +} + +func toSyftPackage(p model.Package) pkg.Package { + var cpes []pkg.CPE + for _, c := range p.CPEs { + value, err := pkg.NewCPE(c) + if err != nil { + log.Warnf("excluding invalid CPE %q: %v", c, err) + continue + } + + cpes = append(cpes, value) + } + + return pkg.Package{ + ID: pkg.ID(p.ID), + Name: p.Name, + Version: p.Version, + FoundBy: p.FoundBy, + Locations: p.Locations, + Licenses: p.Licenses, + Language: p.Language, + Type: p.Type, + CPEs: cpes, + PURL: p.PURL, + MetadataType: p.MetadataType, + Metadata: p.Metadata, + } +} diff --git a/internal/formats/syftjson/validator.go b/internal/formats/syftjson/validator.go new file mode 100644 index 00000000000..1adcb90d461 --- /dev/null +++ b/internal/formats/syftjson/validator.go @@ -0,0 +1,31 @@ +package syftjson + +import ( + "encoding/json" + "fmt" + "io" + "strings" + + "github.com/anchore/syft/internal/formats/syftjson/model" +) + +func validator(reader io.Reader) error { + type Document struct { + Schema model.Schema `json:"schema"` + } + + dec := json.NewDecoder(reader) + + var doc Document + err := dec.Decode(&doc) + if err != nil { + return fmt.Errorf("unable to decode: %w", err) + } + + // note: we accept al schema versions + // TODO: add per-schema version parsing + if strings.Contains(doc.Schema.URL, "anchore/syft") { + return nil + } + return fmt.Errorf("could not extract syft schema") +} From f6cc0c86289f22b7ea73437327967c0c0143c068 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:30:30 -0700 Subject: [PATCH 03/17] migrate spdxjson presenter to spdxjson format object Signed-off-by: Alex Goodman --- internal/formats/spdx22json/decoder.go | 24 +++ internal/formats/spdx22json/decoder_test.go | 50 +++++ internal/formats/spdx22json/encoder.go | 24 +++ internal/formats/spdx22json/format.go | 12 ++ .../formats/spdx22json/model/annotation.go | 21 ++ internal/formats/spdx22json/model/checksum.go | 7 + .../formats/spdx22json/model/creation_info.go | 19 ++ internal/formats/spdx22json/model/document.go | 51 +++++ internal/formats/spdx22json/model/element.go | 12 ++ .../formats/spdx22json/model/element_id.go | 37 ++++ .../spdx22json/model/external_document_ref.go | 9 + .../formats/spdx22json/model/external_ref.go | 43 ++++ internal/formats/spdx22json/model/file.go | 41 ++++ .../model/has_extracted_licensing_info.go | 14 ++ internal/formats/spdx22json/model/item.go | 22 +++ internal/formats/spdx22json/model/package.go | 53 +++++ .../model/package_verification_code.go | 23 +++ .../formats/spdx22json/model/relationship.go | 183 ++++++++++++++++++ internal/formats/spdx22json/model/snippet.go | 32 +++ .../spdx22json/model/syft_distro_data.go | 7 + .../spdx22json/model/syft_package_data.go | 114 +++++++++++ internal/formats/spdx22json/model/version.go | 3 + .../test-fixtures/image-simple/Dockerfile | 4 + .../test-fixtures/image-simple/file-1.txt | 1 + .../test-fixtures/image-simple/file-2.txt | 1 + .../TestSPDXJSONDirectoryPresenter.golden | 79 ++++++++ .../TestSPDXJSONImagePresenter.golden | 61 ++++++ .../stereoscope-fixture-image-simple.golden | Bin 0 -> 15360 bytes .../formats/spdx22json/to_format_model.go | 164 ++++++++++++++++ internal/formats/spdx22json/to_syft_model.go | 64 ++++++ internal/formats/spdx22json/validator.go | 26 +++ 31 files changed, 1201 insertions(+) create mode 100644 internal/formats/spdx22json/decoder.go create mode 100644 internal/formats/spdx22json/decoder_test.go create mode 100644 internal/formats/spdx22json/encoder.go create mode 100644 internal/formats/spdx22json/format.go create mode 100644 internal/formats/spdx22json/model/annotation.go create mode 100644 internal/formats/spdx22json/model/checksum.go create mode 100644 internal/formats/spdx22json/model/creation_info.go create mode 100644 internal/formats/spdx22json/model/document.go create mode 100644 internal/formats/spdx22json/model/element.go create mode 100644 internal/formats/spdx22json/model/element_id.go create mode 100644 internal/formats/spdx22json/model/external_document_ref.go create mode 100644 internal/formats/spdx22json/model/external_ref.go create mode 100644 internal/formats/spdx22json/model/file.go create mode 100644 internal/formats/spdx22json/model/has_extracted_licensing_info.go create mode 100644 internal/formats/spdx22json/model/item.go create mode 100644 internal/formats/spdx22json/model/package.go create mode 100644 internal/formats/spdx22json/model/package_verification_code.go create mode 100644 internal/formats/spdx22json/model/relationship.go create mode 100644 internal/formats/spdx22json/model/snippet.go create mode 100644 internal/formats/spdx22json/model/syft_distro_data.go create mode 100644 internal/formats/spdx22json/model/syft_package_data.go create mode 100644 internal/formats/spdx22json/model/version.go create mode 100644 internal/formats/spdx22json/test-fixtures/image-simple/Dockerfile create mode 100644 internal/formats/spdx22json/test-fixtures/image-simple/file-1.txt create mode 100644 internal/formats/spdx22json/test-fixtures/image-simple/file-2.txt create mode 100644 internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden create mode 100644 internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden create mode 100644 internal/formats/spdx22json/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden create mode 100644 internal/formats/spdx22json/to_format_model.go create mode 100644 internal/formats/spdx22json/to_syft_model.go create mode 100644 internal/formats/spdx22json/validator.go diff --git a/internal/formats/spdx22json/decoder.go b/internal/formats/spdx22json/decoder.go new file mode 100644 index 00000000000..d67cd8cd410 --- /dev/null +++ b/internal/formats/spdx22json/decoder.go @@ -0,0 +1,24 @@ +package spdx22json + +import ( + "encoding/json" + "fmt" + "io" + + "github.com/anchore/syft/internal/formats/spdx22json/model" + "github.com/anchore/syft/syft/distro" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +func decoder(reader io.Reader) (*pkg.Catalog, *source.Metadata, *distro.Distro, error) { + dec := json.NewDecoder(reader) + + var doc model.Document + err := dec.Decode(&doc) + if err != nil { + return nil, nil, nil, fmt.Errorf("unable to decode spdx-json: %w", err) + } + + return toSyftModel(doc) +} diff --git a/internal/formats/spdx22json/decoder_test.go b/internal/formats/spdx22json/decoder_test.go new file mode 100644 index 00000000000..e6e52186f8b --- /dev/null +++ b/internal/formats/spdx22json/decoder_test.go @@ -0,0 +1,50 @@ +package spdx22json + +import ( + "bytes" + "strings" + "testing" + + "github.com/anchore/syft/internal/formats/common/testutils" + "github.com/go-test/deep" + "github.com/stretchr/testify/assert" +) + +func TestEncodeDecodeCycle(t *testing.T) { + testImage := "image-simple" + originalCatalog, originalMetadata, _ := testutils.ImageInput(t, testImage) + + var buf bytes.Buffer + assert.NoError(t, encoder(&buf, originalCatalog, &originalMetadata, nil)) + + actualCatalog, actualMetadata, _, err := decoder(bytes.NewReader(buf.Bytes())) + assert.NoError(t, err) + + for _, d := range deep.Equal(originalMetadata, *actualMetadata) { + t.Errorf("metadata difference: %+v", d) + } + + actualPackages := actualCatalog.Sorted() + for idx, p := range originalCatalog.Sorted() { + if !assert.Equal(t, p.Name, actualPackages[idx].Name) { + t.Errorf("different package at idx=%d: %s vs %s", idx, p.Name, actualPackages[idx].Name) + continue + } + + // ids will never be equal + p.ID = "" + actualPackages[idx].ID = "" + + for _, d := range deep.Equal(*p, *actualPackages[idx]) { + if strings.Contains(d, ".VirtualPath: ") { + // location.Virtual path is not exposed in the json output + continue + } + if strings.HasSuffix(d, " != []") { + // semantically the same + continue + } + t.Errorf("package difference (%s): %+v", p.Name, d) + } + } +} diff --git a/internal/formats/spdx22json/encoder.go b/internal/formats/spdx22json/encoder.go new file mode 100644 index 00000000000..d9737b3abe1 --- /dev/null +++ b/internal/formats/spdx22json/encoder.go @@ -0,0 +1,24 @@ +package spdx22json + +import ( + "encoding/json" + "io" + + "github.com/anchore/syft/syft/distro" + + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +const anchoreNamespace = "https://anchore.com/syft" + +func encoder(output io.Writer, catalog *pkg.Catalog, srcMetadata *source.Metadata, d *distro.Distro) error { + doc := toFormatModel(catalog, srcMetadata, d) + + enc := json.NewEncoder(output) + // prevent > and < from being escaped in the payload + enc.SetEscapeHTML(false) + enc.SetIndent("", " ") + + return enc.Encode(&doc) +} diff --git a/internal/formats/spdx22json/format.go b/internal/formats/spdx22json/format.go new file mode 100644 index 00000000000..88b4ee64156 --- /dev/null +++ b/internal/formats/spdx22json/format.go @@ -0,0 +1,12 @@ +package spdx22json + +import "github.com/anchore/syft/syft/format" + +func Format() format.Format { + return format.NewFormat( + format.SPDXJSONOption, + encoder, + decoder, + validator, + ) +} diff --git a/internal/formats/spdx22json/model/annotation.go b/internal/formats/spdx22json/model/annotation.go new file mode 100644 index 00000000000..e924cb7c678 --- /dev/null +++ b/internal/formats/spdx22json/model/annotation.go @@ -0,0 +1,21 @@ +package model + +import "time" + +type AnnotationType string + +const ( + ReviewerAnnotationType AnnotationType = "REVIEWER" + OtherAnnotationType AnnotationType = "OTHER" +) + +type Annotation struct { + // Identify when the comment was made. This is to be specified according to the combined date and time in the + // UTC format, as specified in the ISO 8601 standard. + AnnotationDate time.Time `json:"annotationDate"` + // Type of the annotation + AnnotationType AnnotationType `json:"annotationType"` + // This field identifies the person, organization or tool that has commented on a file, package, or the entire document. + Annotator string `json:"annotator"` + Comment string `json:"comment"` +} diff --git a/internal/formats/spdx22json/model/checksum.go b/internal/formats/spdx22json/model/checksum.go new file mode 100644 index 00000000000..b995a95fb9f --- /dev/null +++ b/internal/formats/spdx22json/model/checksum.go @@ -0,0 +1,7 @@ +package model + +type Checksum struct { + // Identifies the algorithm used to produce the subject Checksum. One of: "SHA256", "SHA1", "SHA384", "MD2", "MD4", "SHA512", "MD6", "MD5", "SHA224" + Algorithm string `json:"algorithm"` + ChecksumValue string `json:"checksumValue"` +} diff --git a/internal/formats/spdx22json/model/creation_info.go b/internal/formats/spdx22json/model/creation_info.go new file mode 100644 index 00000000000..2feb494fceb --- /dev/null +++ b/internal/formats/spdx22json/model/creation_info.go @@ -0,0 +1,19 @@ +package model + +import "time" + +type CreationInfo struct { + Comment string `json:"comment,omitempty"` + // Identify when the SPDX file was originally created. The date is to be specified according to combined date and + // time in UTC format as specified in ISO 8601 standard. This field is distinct from the fields in section 8, + // which involves the addition of information during a subsequent review. + Created time.Time `json:"created"` + // Identify who (or what, in the case of a tool) created the SPDX file. If the SPDX file was created by an + // individual, indicate the person's name. If the SPDX file was created on behalf of a company or organization, + //indicate the entity name. If the SPDX file was created using a software tool, indicate the name and version + // for that tool. If multiple participants or tools were involved, use multiple instances of this field. Person + // name or organization name may be designated as “anonymous” if appropriate. + Creators []string `json:"creators"` + // An optional field for creators of the SPDX file to provide the version of the SPDX License List used when the SPDX file was created. + LicenseListVersion string `json:"licenseListVersion"` +} diff --git a/internal/formats/spdx22json/model/document.go b/internal/formats/spdx22json/model/document.go new file mode 100644 index 00000000000..c7e9b9965ae --- /dev/null +++ b/internal/formats/spdx22json/model/document.go @@ -0,0 +1,51 @@ +package model + +import "github.com/anchore/syft/syft/source" + +// derived from: +// - https://spdx.github.io/spdx-spec/appendix-III-RDF-data-model-implementation-and-identifier-syntax/ +// - https://github.com/spdx/spdx-spec/blob/v2.2/schemas/spdx-schema.json +// - https://github.com/spdx/spdx-spec/tree/v2.2/ontology + +type Document struct { + Element + SPDXVersion string `json:"spdxVersion"` + // One instance is required for each SPDX file produced. It provides the necessary information for forward + // and backward compatibility for processing tools. + CreationInfo CreationInfo `json:"creationInfo"` + // SyftSourceData contains information about what is being described in this SPDX document (e.g. a container image, a directory, etc) + SyftSourceData *source.Metadata `json:"syftSourceData,omitempty"` + // SyftDistroData contains information about the linux distribution discovered + SyftDistroData *SyftDistroData `json:"syftDistroData,omitempty"` + // 2.2: Data License; should be "CC0-1.0" + // Cardinality: mandatory, one + // License expression for dataLicense. Compliance with the SPDX specification includes populating the SPDX + // fields therein with data related to such fields (\"SPDX-Metadata\"). The SPDX specification contains numerous + // fields where an SPDX document creator may provide relevant explanatory text in SPDX-Metadata. Without + // opining on the lawfulness of \"database rights\" (in jurisdictions where applicable), such explanatory text + // is copyrightable subject matter in most Berne Convention countries. By using the SPDX specification, or any + // portion hereof, you hereby agree that any copyright rights (as determined by your jurisdiction) in any + // SPDX-Metadata, including without limitation explanatory text, shall be subject to the terms of the Creative + // Commons CC0 1.0 Universal license. For SPDX-Metadata not containing any copyright rights, you hereby agree + // and acknowledge that the SPDX-Metadata is provided to you \"as-is\" and without any representations or + // warranties of any kind concerning the SPDX-Metadata, express, implied, statutory or otherwise, including + // without limitation warranties of title, merchantability, fitness for a particular purpose, non-infringement, + // or the absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not + // discoverable, all to the greatest extent permissible under applicable law. + DataLicense string `json:"dataLicense"` + // Information about an external SPDX document reference including the checksum. This allows for verification of the external references. + ExternalDocumentRefs []ExternalDocumentRef `json:"externalDocumentRefs,omitempty"` + // Indicates that a particular ExtractedLicensingInfo was defined in the subject SpdxDocument. + HasExtractedLicensingInfos []HasExtractedLicensingInfo `json:"hasExtractedLicensingInfos,omitempty"` + // note: found in example documents from SPDX, but not in the JSON schema. See https://spdx.github.io/spdx-spec/2-document-creation-information/#25-spdx-document-namespace + DocumentNamespace string `json:"documentNamespace"` + // note: found in example documents from SPDX, but not in the JSON schema + // DocumentDescribes []string `json:"documentDescribes"` + Packages []Package `json:"packages"` + // Files referenced in the SPDX document + Files []File `json:"files,omitempty"` + // Snippets referenced in the SPDX document + Snippets []Snippet `json:"snippets,omitempty"` + // Relationships referenced in the SPDX document + Relationships []Relationship `json:"relationships,omitempty"` +} diff --git a/internal/formats/spdx22json/model/element.go b/internal/formats/spdx22json/model/element.go new file mode 100644 index 00000000000..9c2a68bcbd0 --- /dev/null +++ b/internal/formats/spdx22json/model/element.go @@ -0,0 +1,12 @@ +package model + +type Element struct { + SPDXID string `json:"SPDXID"` + // Identify name of this SpdxElement. + Name string `json:"name"` + // Relationships referenced in the SPDX document + Relationships []Relationship `json:"relationships,omitempty"` + // Provide additional information about an SpdxElement. + Annotations []Annotation `json:"annotations,omitempty"` + Comment string `json:"comment,omitempty"` +} diff --git a/internal/formats/spdx22json/model/element_id.go b/internal/formats/spdx22json/model/element_id.go new file mode 100644 index 00000000000..50251fe37ce --- /dev/null +++ b/internal/formats/spdx22json/model/element_id.go @@ -0,0 +1,37 @@ +package model + +// ElementID represents the identifier string portion of an SPDX element +// identifier. DocElementID should be used for any attributes which can +// contain identifiers defined in a different SPDX document. +// ElementIDs should NOT contain the mandatory 'SPDXRef-' portion. +type ElementID string + +func (e ElementID) String() string { + return "SPDXRef-" + string(e) +} + +// DocElementID represents an SPDX element identifier that could be defined +// in a different SPDX document, and therefore could have a "DocumentRef-" +// portion, such as Relationship and Annotations. +// ElementID is used for attributes in which a "DocumentRef-" portion cannot +// appear, such as a Package or File definition (since it is necessarily +// being defined in the present document). +// DocumentRefID will be the empty string for elements defined in the +// present document. +// DocElementIDs should NOT contain the mandatory 'DocumentRef-' or +// 'SPDXRef-' portions. +type DocElementID struct { + DocumentRefID string + ElementRefID ElementID +} + +// RenderDocElementID takes a DocElementID and returns the string equivalent, +// with the SPDXRef- prefix (and, if applicable, the DocumentRef- prefix) +// reinserted. +func (d DocElementID) String() string { + prefix := "" + if d.DocumentRefID != "" { + prefix = "DocumentRef-" + d.DocumentRefID + ":" + } + return prefix + d.ElementRefID.String() +} diff --git a/internal/formats/spdx22json/model/external_document_ref.go b/internal/formats/spdx22json/model/external_document_ref.go new file mode 100644 index 00000000000..10e1d9ec3b1 --- /dev/null +++ b/internal/formats/spdx22json/model/external_document_ref.go @@ -0,0 +1,9 @@ +package model + +type ExternalDocumentRef struct { + // externalDocumentId is a string containing letters, numbers, ., - and/or + which uniquely identifies an external document within this document. + ExternalDocumentID string `json:"externalDocumentId"` + Checksum Checksum `json:"checksum"` + // SPDX ID for SpdxDocument. A propoerty containing an SPDX document. + SpdxDocument string `json:"spdxDocument"` +} diff --git a/internal/formats/spdx22json/model/external_ref.go b/internal/formats/spdx22json/model/external_ref.go new file mode 100644 index 00000000000..9dc49b3dd90 --- /dev/null +++ b/internal/formats/spdx22json/model/external_ref.go @@ -0,0 +1,43 @@ +package model + +type ReferenceCategory string + +const ( + SecurityReferenceCategory ReferenceCategory = "SECURITY" + PackageManagerReferenceCategory ReferenceCategory = "PACKAGE_MANAGER" + OtherReferenceCategory ReferenceCategory = "OTHER" +) + +// source: https://spdx.github.io/spdx-spec/appendix-VI-external-repository-identifiers/ + +type ExternalRefType string + +const ( + // see https://nvd.nist.gov/cpe + Cpe22ExternalRefType ExternalRefType = "cpe22Type" + // see https://nvd.nist.gov/cpe + Cpe23ExternalRefType ExternalRefType = "cpe23Type" + // see http://repo1.maven.org/maven2/ + MavenCentralExternalRefType ExternalRefType = "maven-central" + // see https://www.npmjs.com/ + NpmExternalRefType ExternalRefType = "npm" + // see https://www.nuget.org/ + NugetExternalRefType ExternalRefType = "nuget" + // see http://bower.io/ + BowerExternalRefType ExternalRefType = "bower" + // see https://github.com/package-url/purl-spec + PurlExternalRefType ExternalRefType = "purl" + // These point to objects present in the Software Heritage archive by the means of SoftWare Heritage persistent Identifiers (SWHID) + SwhExternalRefType ExternalRefType = "swh" +) + +type ExternalRef struct { + Comment string `json:"comment,omitempty"` + // Category for the external reference. + ReferenceCategory ReferenceCategory `json:"referenceCategory"` + // The unique string with no spaces necessary to access the package-specific information, metadata, or content + // within the target location. The format of the locator is subject to constraints defined by the . + ReferenceLocator string `json:"referenceLocator"` + // Type of the external reference. These are defined in an appendix in the SPDX specification. + ReferenceType ExternalRefType `json:"referenceType"` +} diff --git a/internal/formats/spdx22json/model/file.go b/internal/formats/spdx22json/model/file.go new file mode 100644 index 00000000000..970f369cc58 --- /dev/null +++ b/internal/formats/spdx22json/model/file.go @@ -0,0 +1,41 @@ +package model + +type FileType string + +const ( + DocumentationFileType FileType = "DOCUMENTATION" + ImageFileType FileType = "IMAGE" + VideoFileType FileType = "VIDEO" + ArchiveFileType FileType = "ARCHIVE" + SpdxFileType FileType = "SPDX" + ApplicationFileType FileType = "APPLICATION" + SourceFileType FileType = "SOURCE" + BinaryFileType FileType = "BINARY" + TextFileType FileType = "TEXT" + AudioFileType FileType = "AUDIO" + OtherFileType FileType = "OTHER" +) + +type File struct { + Item + // (At least one is required.) The checksum property provides a mechanism that can be used to verify that the + // contents of a File or Package have not changed. + Checksums []Checksum `json:"checksums,omitempty"` + // This field provides a place for the SPDX file creator to record file contributors. Contributors could include + // names of copyright holders and/or authors who may not be copyright holders yet contributed to the file content. + FileContributors []string `json:"fileContributors,omitempty"` + // Each element is a SPDX ID for a File. + FileDependencies []string `json:"fileDependencies,omitempty"` + // The name of the file relative to the root of the package. + FileName string `json:"fileName"` + // The type of the file + FileTypes []string `json:"fileTypes,omitempty"` + // This field provides a place for the SPDX file creator to record potential legal notices found in the file. + // This may or may not include copyright statements. + NoticeText string `json:"noticeText,omitempty"` + // Indicates the project in which the SpdxElement originated. Tools must preserve doap:homepage and doap:name + // properties and the URI (if one is known) of doap:Project resources that are values of this property. All other + // properties of doap:Projects are not directly supported by SPDX and may be dropped when translating to or + // from some SPDX formats(deprecated). + ArtifactOf []string `json:"artifactOf,omitempty"` +} diff --git a/internal/formats/spdx22json/model/has_extracted_licensing_info.go b/internal/formats/spdx22json/model/has_extracted_licensing_info.go new file mode 100644 index 00000000000..8c0748073b3 --- /dev/null +++ b/internal/formats/spdx22json/model/has_extracted_licensing_info.go @@ -0,0 +1,14 @@ +package model + +type HasExtractedLicensingInfo struct { + // Verbatim license or licensing notice text that was discovered. + ExtractedText string `json:"extractedText"` + // A human readable short form license identifier for a license. The license ID is iether on the standard license + // oist or the form \"LicenseRef-\"[idString] where [idString] is a unique string containing letters, + // numbers, \".\", \"-\" or \"+\". + LicenseID string `json:"licenseId"` + Comment string `json:"comment,omitempty"` + // Identify name of this SpdxElement. + Name string `json:"name,omitempty"` + SeeAlsos []string `json:"seeAlsos,omitempty"` +} diff --git a/internal/formats/spdx22json/model/item.go b/internal/formats/spdx22json/model/item.go new file mode 100644 index 00000000000..178fbf8421e --- /dev/null +++ b/internal/formats/spdx22json/model/item.go @@ -0,0 +1,22 @@ +package model + +type Item struct { + Element + // The licenseComments property allows the preparer of the SPDX document to describe why the licensing in + // spdx:licenseConcluded was chosen. + LicenseComments string `json:"licenseComments,omitempty"` + LicenseConcluded string `json:"licenseConcluded"` + // The licensing information that was discovered directly within the package. There will be an instance of this + // property for each distinct value of alllicenseInfoInFile properties of all files contained in the package. + LicenseInfoFromFiles []string `json:"licenseInfoFromFiles,omitempty"` + // Licensing information that was discovered directly in the subject file. This is also considered a declared license for the file. + LicenseInfoInFiles []string `json:"licenseInfoInFiles,omitempty"` + // The text of copyright declarations recited in the Package or File. + CopyrightText string `json:"copyrightText,omitempty"` + // This field provides a place for the SPDX data creator to record acknowledgements that may be required to be + // communicated in some contexts. This is not meant to include the actual complete license text (see + // licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). + // The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from + // license texts, which may be necessary or desirable to reproduce. + AttributionTexts []string `json:"attributionTexts,omitempty"` +} diff --git a/internal/formats/spdx22json/model/package.go b/internal/formats/spdx22json/model/package.go new file mode 100644 index 00000000000..5d303574f71 --- /dev/null +++ b/internal/formats/spdx22json/model/package.go @@ -0,0 +1,53 @@ +package model + +type Package struct { + Item + // The checksum property provides a mechanism that can be used to verify that the contents of a File or + // Package have not changed. + Checksums []Checksum `json:"checksums,omitempty"` + // Provides a detailed description of the package. + Description string `json:"description,omitempty"` + // The URI at which this package is available for download. Private (i.e., not publicly reachable) URIs are + // acceptable as values of this property. The values http://spdx.org/rdf/terms#none and http://spdx.org/rdf/terms#noassertion + // may be used to specify that the package is not downloadable or that no attempt was made to determine its + // download location, respectively. + DownloadLocation string `json:"downloadLocation,omitempty"` + // An External Reference allows a Package to reference an external source of additional information, metadata, + // enumerations, asset identifiers, or downloadable content believed to be relevant to the Package. + ExternalRefs []ExternalRef `json:"externalRefs,omitempty"` + // Indicates whether the file content of this package has been available for or subjected to analysis when + // creating the SPDX document. If false indicates packages that represent metadata or URI references to a + // project, product, artifact, distribution or a component. If set to false, the package must not contain any files + FilesAnalyzed bool `json:"filesAnalyzed"` + // Indicates that a particular file belongs to a package (elements are SPDX ID for a File). + HasFiles []string `json:"hasFiles,omitempty"` + // Provide a place for the SPDX file creator to record a web site that serves as the package's home page. + // This link can also be used to reference further information about the package referenced by the SPDX file creator. + Homepage string `json:"homepage,omitempty"` + // List the licenses that have been declared by the authors of the package. Any license information that does not + // originate from the package authors, e.g. license information from a third party repository, should not be included in this field. + LicenseDeclared string `json:"licenseDeclared"` + // The name and, optionally, contact information of the person or organization that originally created the package. + // Values of this property must conform to the agent and tool syntax. + Originator string `json:"originator,omitempty"` + // The base name of the package file name. For example, zlib-1.2.5.tar.gz. + PackageFileName string `json:"packageFileName,omitempty"` + // A manifest based verification code (the algorithm is defined in section 4.7 of the full specification) of the + // SPDX Item. This allows consumers of this data and/or database to determine if an SPDX item they have in hand + // is identical to the SPDX item from which the data was produced. This algorithm works even if the SPDX document + // is included in the SPDX item. + PackageVerificationCode *PackageVerificationCode `json:"packageVerificationCode,omitempty"` + // Allows the producer(s) of the SPDX document to describe how the package was acquired and/or changed from the original source. + SourceInfo string `json:"sourceInfo,omitempty"` + // Provides a short description of the package. + Summary string `json:"summary,omitempty"` + // The name and, optionally, contact information of the person or organization who was the immediate supplier + // of this package to the recipient. The supplier may be different than originator when the software has been + // repackaged. Values of this property must conform to the agent and tool syntax. + Supplier string `json:"supplier,omitempty"` + // Provides an indication of the version of the package that is described by this SpdxDocument. + VersionInfo string `json:"versionInfo,omitempty"` + // SyftPackageData provides a spot to add syft-specific data that is not available in-spec or is not easily decodable from + // other SPDX fields. + SyftPackageData *SyftPackageData `json:"syftPackageData,omitempty"` +} diff --git a/internal/formats/spdx22json/model/package_verification_code.go b/internal/formats/spdx22json/model/package_verification_code.go new file mode 100644 index 00000000000..508c9169ed0 --- /dev/null +++ b/internal/formats/spdx22json/model/package_verification_code.go @@ -0,0 +1,23 @@ +package model + +// Why are there two package identifier fields Package Checksum and Package Verification? +// Although the values of the two fields Package Checksum and Package Verification are similar, they each serve a +// different purpose. The Package Checksum provides a unique identifier of a software package which is computed by +// taking the SHA1 of the entire software package file. This enables one to quickly determine if two different copies +// of a package are the same. One disadvantage of this approach is that one cannot add an SPDX data file into the +// original package without changing the Package Checksum value. Alternatively, the Package Verification field enables +// the inclusion of an SPDX file. It enables one to quickly verify if one or more of the original package files has +// changed. The Package Verification field is a unique identifier that is based on SHAing only the original package +// files (e.g., excluding the SPDX file). This allows one to add an SPDX file to the original package without changing +// this unique identifier. +// source: https://wiki.spdx.org/view/SPDX_FAQ +type PackageVerificationCode struct { + // "A file that was excluded when calculating the package verification code. This is usually a file containing + // SPDX data regarding the package. If a package contains more than one SPDX file all SPDX files must be excluded + // from the package verification code. If this is not done it would be impossible to correctly calculate the + // verification codes in both files. + PackageVerificationCodeExcludedFiles []string `json:"packageVerificationCodeExcludedFiles"` + + // The actual package verification code as a hex encoded value. + PackageVerificationCodeValue string `json:"packageVerificationCodeValue"` +} diff --git a/internal/formats/spdx22json/model/relationship.go b/internal/formats/spdx22json/model/relationship.go new file mode 100644 index 00000000000..51c52233b14 --- /dev/null +++ b/internal/formats/spdx22json/model/relationship.go @@ -0,0 +1,183 @@ +package model + +type Relationship struct { + // Id to which the SPDX element is related + SpdxElementID string `json:"spdxElementId"` + // Describes the type of relationship between two SPDX elements. + RelationshipType RelationshipType `json:"relationshipType"` + // SPDX ID for SpdxElement. A related SpdxElement. + RelatedSpdxElement string `json:"relatedSpdxElement"` + Comment string `json:"comment,omitempty"` +} + +// source: https://spdx.github.io/spdx-spec/7-relationships-between-SPDX-elements/ +type RelationshipType string + +const ( + // DescribedByRelationship is to be used when SPDXRef-A is described by SPDXREF-Document. + // Example: The package 'WildFly' is described by SPDX document WildFly.spdx. + DescribedByRelationship RelationshipType = "DESCRIBED_BY" + + // ContainsRelationship is to be used when SPDXRef-A contains SPDXRef-B. + // Example: An ARCHIVE file bar.tgz contains a SOURCE file foo.c. + ContainsRelationship RelationshipType = "CONTAINS" + + // ContainedByRelationship is to be used when SPDXRef-A is contained by SPDXRef-B. + // Example: A SOURCE file foo.c is contained by ARCHIVE file bar.tgz + ContainedByRelationship RelationshipType = "CONTAINED_BY" + + // DependsOnRelationship is to be used when SPDXRef-A depends on SPDXRef-B. + // Example: Package A depends on the presence of package B in order to build and run + DependsOnRelationship RelationshipType = "DEPENDS_ON" + + // DependencyOfRelationship is to be used when SPDXRef-A is dependency of SPDXRef-B. + // Example: A is explicitly stated as a dependency of B in a machine-readable file. Use when a package manager does not define scopes. + DependencyOfRelationship RelationshipType = "DEPENDENCY_OF" + + // DependencyManifestOfRelationship is to be used when SPDXRef-A is a manifest file that lists a set of dependencies for SPDXRef-B. + // Example: A file package.json is the dependency manifest of a package foo. Note that only one manifest should be used to define the same dependency graph. + DependencyManifestOfRelationship RelationshipType = "DEPENDENCY_MANIFEST_OF" + + // BuildDependencyOfRelationship is to be used when SPDXRef-A is a build dependency of SPDXRef-B. + // Example: A is in the compile scope of B in a Maven project. + BuildDependencyOfRelationship RelationshipType = "BUILD_DEPENDENCY_OF" + + // DevDependencyOfRelationship is to be used when SPDXRef-A is a development dependency of SPDXRef-B. + // Example: A is in the devDependencies scope of B in a Maven project. + DevDependencyOfRelationship RelationshipType = "DEV_DEPENDENCY_OF" + + // OptionalDependencyOfRelationship is to be used when SPDXRef-A is an optional dependency of SPDXRef-B. + // Example: Use when building the code will proceed even if a dependency cannot be found, fails to install, or is only installed on a specific platform. For example, A is in the optionalDependencies scope of npm project B. + OptionalDependencyOfRelationship RelationshipType = "OPTIONAL_DEPENDENCY_OF" + + // ProvidedDependencyOfRelationship is to be used when SPDXRef-A is a to be provided dependency of SPDXRef-B. + // Example: A is in the provided scope of B in a Maven project, indicating that the project expects it to be provided, for instance, by the container or JDK. + ProvidedDependencyOfRelationship RelationshipType = "PROVIDED_DEPENDENCY_OF" + + // TestDependencyOfRelationship is to be used when SPDXRef-A is a test dependency of SPDXRef-B. + // Example: A is in the test scope of B in a Maven project. + TestDependencyOfRelationship RelationshipType = "TEST_DEPENDENCY_OF" + + // RuntimeDependencyOfRelationship is to be used when SPDXRef-A is a dependency required for the execution of SPDXRef-B. + // Example: A is in the runtime scope of B in a Maven project. + RuntimeDependencyOfRelationship RelationshipType = "RUNTIME_DEPENDENCY_OF" + + // ExampleOfRelationship is to be used when SPDXRef-A is an example of SPDXRef-B. + // Example: The file or snippet that illustrates how to use an application or library. + ExampleOfRelationship RelationshipType = "EXAMPLE_OF" + + // GeneratesRelationship is to be used when SPDXRef-A generates SPDXRef-B. + // Example: A SOURCE file makefile.mk generates a BINARY file a.out + GeneratesRelationship RelationshipType = "GENERATES" + + // GeneratedFromRelationship is to be used when SPDXRef-A was generated from SPDXRef-B. + // Example: A BINARY file a.out has been generated from a SOURCE file makefile.mk. A BINARY file foolib.a is generated from a SOURCE file bar.c. + GeneratedFromRelationship RelationshipType = "GENERATED_FROM" + + // AncestorOfRelationship is to be used when SPDXRef-A is an ancestor (same lineage but pre-dates) SPDXRef-B. + // Example: A SOURCE file makefile.mk is a version of the original ancestor SOURCE file 'makefile2.mk' + AncestorOfRelationship RelationshipType = "ANCESTOR_OF" + + // DescendantOfRelationship is to be used when SPDXRef-A is a descendant of (same lineage but postdates) SPDXRef-B. + // Example: A SOURCE file makefile2.mk is a descendant of the original SOURCE file 'makefile.mk' + DescendantOfRelationship RelationshipType = "DESCENDANT_OF" + + // VariantOfRelationship is to be used when SPDXRef-A is a variant of (same lineage but not clear which came first) SPDXRef-B. + // Example: A SOURCE file makefile2.mk is a variant of SOURCE file makefile.mk if they differ by some edit, but there is no way to tell which came first (no reliable date information). + VariantOfRelationship RelationshipType = "VARIANT_OF" + + // DistributionArtifactRelationship is to be used when distributing SPDXRef-A requires that SPDXRef-B also be distributed. + // Example: A BINARY file foo.o requires that the ARCHIVE file bar-sources.tgz be made available on distribution. + DistributionArtifactRelationship RelationshipType = "DISTRIBUTION_ARTIFACT" + + // PatchForRelationship is to be used when SPDXRef-A is a patch file for (to be applied to) SPDXRef-B. + // Example: A SOURCE file foo.diff is a patch file for SOURCE file foo.c. + PatchForRelationship RelationshipType = "PATCH_FOR" + + // PatchAppliedRelationship is to be used when SPDXRef-A is a patch file that has been applied to SPDXRef-B. + // Example: A SOURCE file foo.diff is a patch file that has been applied to SOURCE file 'foo-patched.c'. + PatchAppliedRelationship RelationshipType = "PATCH_APPLIED" + + // CopyOfRelationship is to be used when SPDXRef-A is an exact copy of SPDXRef-B. + // Example: A BINARY file alib.a is an exact copy of BINARY file a2lib.a. + CopyOfRelationship RelationshipType = "COPY_OF" + + // FileAddedRelationship is to be used when SPDXRef-A is a file that was added to SPDXRef-B. + // Example: A SOURCE file foo.c has been added to package ARCHIVE bar.tgz. + FileAddedRelationship RelationshipType = "FILE_ADDED" + + // FileDeletedRelationship is to be used when SPDXRef-A is a file that was deleted from SPDXRef-B. + // Example: A SOURCE file foo.diff has been deleted from package ARCHIVE bar.tgz. + FileDeletedRelationship RelationshipType = "FILE_DELETED" + + // FileModifiedRelationship is to be used when SPDXRef-A is a file that was modified from SPDXRef-B. + // Example: A SOURCE file foo.c has been modified from SOURCE file foo.orig.c. + FileModifiedRelationship RelationshipType = "FILE_MODIFIED" + + // ExpandedFromArchiveRelationship is to be used when SPDXRef-A is expanded from the archive SPDXRef-B. + // Example: A SOURCE file foo.c, has been expanded from the archive ARCHIVE file xyz.tgz. + ExpandedFromArchiveRelationship RelationshipType = "EXPANDED_FROM_ARCHIVE" + + // DynamicLinkRelationship is to be used when SPDXRef-A dynamically links to SPDXRef-B. + // Example: An APPLICATION file 'myapp' dynamically links to BINARY file zlib.so. + DynamicLinkRelationship RelationshipType = "DYNAMIC_LINK" + + // StaticLinkRelationship is to be used when SPDXRef-A statically links to SPDXRef-B. + // Example: An APPLICATION file 'myapp' statically links to BINARY zlib.a. + StaticLinkRelationship RelationshipType = "STATIC_LINK" + + // DataFileOfRelationship is to be used when SPDXRef-A is a data file used in SPDXRef-B. + // Example: An IMAGE file 'kitty.jpg' is a data file of an APPLICATION 'hellokitty'. + DataFileOfRelationship RelationshipType = "DATA_FILE_OF" + + // TestCaseOfRelationship is to be used when SPDXRef-A is a test case used in testing SPDXRef-B. + // Example: A SOURCE file testMyCode.java is a unit test file used to test an APPLICATION MyPackage. + TestCaseOfRelationship RelationshipType = "TEST_CASE_OF" + + // BuildToolOfRelationship is to be used when SPDXRef-A is used to build SPDXRef-B. + // Example: A SOURCE file makefile.mk is used to build an APPLICATION 'zlib'. + BuildToolOfRelationship RelationshipType = "BUILD_TOOL_OF" + + // DevToolOfRelationship is to be used when SPDXRef-A is used as a development tool for SPDXRef-B. + // Example: Any tool used for development such as a code debugger. + DevToolOfRelationship RelationshipType = "DEV_TOOL_OF" + + // TestOfRelationship is to be used when SPDXRef-A is used for testing SPDXRef-B. + // Example: Generic relationship for cases where it's clear that something is used for testing but unclear whether it's TEST_CASE_OF or TEST_TOOL_OF. + TestOfRelationship RelationshipType = "TEST_OF" + + // TestToolOfRelationship is to be used when SPDXRef-A is used as a test tool for SPDXRef-B. + // Example: Any tool used to test the code such as ESlint. + TestToolOfRelationship RelationshipType = "TEST_TOOL_OF" + + // DocumentationOfRelationship is to be used when SPDXRef-A provides documentation of SPDXRef-B. + // Example: A DOCUMENTATION file readme.txt documents the APPLICATION 'zlib'. + DocumentationOfRelationship RelationshipType = "DOCUMENTATION_OF" + + // OptionalComponentOfRelationship is to be used when SPDXRef-A is an optional component of SPDXRef-B. + // Example: A SOURCE file fool.c (which is in the contributors directory) may or may not be included in the build of APPLICATION 'atthebar'. + OptionalComponentOfRelationship RelationshipType = "OPTIONAL_COMPONENT_OF" + + // MetafileOfRelationship is to be used when SPDXRef-A is a metafile of SPDXRef-B. + // Example: A SOURCE file pom.xml is a metafile of the APPLICATION 'Apache Xerces'. + MetafileOfRelationship RelationshipType = "METAFILE_OF" + + // PackageOfRelationship is to be used when SPDXRef-A is used as a package as part of SPDXRef-B. + // Example: A Linux distribution contains an APPLICATION package gawk as part of the distribution MyLinuxDistro. + PackageOfRelationship RelationshipType = "PACKAGE_OF" + + // AmendsRelationship is to be used when (current) SPDXRef-DOCUMENT amends the SPDX information in SPDXRef-B. + // Example: (Current) SPDX document A version 2 contains a correction to a previous version of the SPDX document A version 1. Note the reserved identifier SPDXRef-DOCUMENT for the current document is required. + AmendsRelationship RelationshipType = "AMENDS" + + // PrerequisiteForRelationship is to be used when SPDXRef-A is a prerequisite for SPDXRef-B. + // Example: A library bar.dll is a prerequisite or dependency for APPLICATION foo.exe + PrerequisiteForRelationship RelationshipType = "PREREQUISITE_FOR" + + // HasPrerequisiteRelationship is to be used when SPDXRef-A has as a prerequisite SPDXRef-B. + // Example: An APPLICATION foo.exe has prerequisite or dependency on bar.dll + HasPrerequisiteRelationship RelationshipType = "HAS_PREREQUISITE" + + // OtherRelationship is to be used for a relationship which has not been defined in the formal SPDX specification. A description of the relationship should be included in the Relationship comments field. + OtherRelationship RelationshipType = "OTHER" +) diff --git a/internal/formats/spdx22json/model/snippet.go b/internal/formats/spdx22json/model/snippet.go new file mode 100644 index 00000000000..0d39e5dca39 --- /dev/null +++ b/internal/formats/spdx22json/model/snippet.go @@ -0,0 +1,32 @@ +package model + +type StartPointer struct { + Offset int `json:"offset,omitempty"` + LineNumber int `json:"lineNumber,omitempty"` + // SPDX ID for File + Reference string `json:"reference"` +} + +type EndPointer struct { + Offset int `json:"offset,omitempty"` + LineNumber int `json:"lineNumber,omitempty"` + // SPDX ID for File + Reference string `json:"reference"` +} + +type Range struct { + StartPointer StartPointer `json:"startPointer"` + EndPointer EndPointer `json:"endPointer"` +} + +type Snippet struct { + Item + // Licensing information that was discovered directly in the subject snippet. This is also considered a declared + // license for the snippet. (elements are license expressions) + LicenseInfoInSnippets []string `json:"licenseInfoInSnippets"` + // SPDX ID for File. File containing the SPDX element (e.g. the file contaning a snippet). + SnippetFromFile string `json:"snippetFromFile"` + // (At least 1 range is required). This field defines the byte range in the original host file (in X.2) that the + // snippet information applies to. + Ranges []Range `json:"ranges"` +} diff --git a/internal/formats/spdx22json/model/syft_distro_data.go b/internal/formats/spdx22json/model/syft_distro_data.go new file mode 100644 index 00000000000..8f985bf2661 --- /dev/null +++ b/internal/formats/spdx22json/model/syft_distro_data.go @@ -0,0 +1,7 @@ +package model + +type SyftDistroData struct { + Name string `json:"name"` // Name of the Linux distribution + Version string `json:"version"` // Version of the Linux distribution (major or major.minor version) + IDLike string `json:"idLike"` // the ID_LIKE field found within the /etc/os-release file +} diff --git a/internal/formats/spdx22json/model/syft_package_data.go b/internal/formats/spdx22json/model/syft_package_data.go new file mode 100644 index 00000000000..58efd69b15d --- /dev/null +++ b/internal/formats/spdx22json/model/syft_package_data.go @@ -0,0 +1,114 @@ +package model + +import ( + "encoding/json" + "fmt" + + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +type SyftPackageData struct { + SyftPackageBasicData + SyftPackageCustomData +} + +type SyftPackageCustomData struct { + MetadataType pkg.MetadataType `json:"metadataType"` + Metadata interface{} `json:"metadata"` +} + +type SyftPackageBasicData struct { + PackageType pkg.Type `json:"type"` + FoundBy string `json:"foundBy"` + Locations []source.Location `json:"locations"` + Licenses []string `json:"licenses"` + Language pkg.Language `json:"language"` +} + +// syftPackageMetadataUnpacker is all values needed from Package to disambiguate ambiguous fields during json unmarshaling. +type syftPackageMetadataUnpacker struct { + MetadataType pkg.MetadataType `json:"metadataType"` + Metadata json.RawMessage `json:"metadata"` +} + +func (p *syftPackageMetadataUnpacker) String() string { + return fmt.Sprintf("metadataType: %s, metadata: %s", p.MetadataType, string(p.Metadata)) +} + +// UnmarshalJSON is a custom unmarshaller for handling basic values and values with ambiguous types. +func (p *SyftPackageData) UnmarshalJSON(b []byte) error { + var basic SyftPackageBasicData + if err := json.Unmarshal(b, &basic); err != nil { + return err + } + p.SyftPackageBasicData = basic + + var unpacker syftPackageMetadataUnpacker + if err := json.Unmarshal(b, &unpacker); err != nil { + log.Warnf("failed to unmarshall into syftPackageMetadataUnpacker: %v", err) + return err + } + + p.MetadataType = unpacker.MetadataType + + switch p.MetadataType { + case pkg.ApkMetadataType: + var payload pkg.ApkMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.RpmdbMetadataType: + var payload pkg.RpmdbMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.DpkgMetadataType: + var payload pkg.DpkgMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.JavaMetadataType: + var payload pkg.JavaMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.RustCargoPackageMetadataType: + var payload pkg.CargoPackageMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.GemMetadataType: + var payload pkg.GemMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.KbPackageMetadataType: + var payload pkg.KbPackageMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.PythonPackageMetadataType: + var payload pkg.PythonPackageMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + case pkg.NpmPackageJSONMetadataType: + var payload pkg.NpmPackageJSONMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload + } + + return nil +} diff --git a/internal/formats/spdx22json/model/version.go b/internal/formats/spdx22json/model/version.go new file mode 100644 index 00000000000..8f105cbfa71 --- /dev/null +++ b/internal/formats/spdx22json/model/version.go @@ -0,0 +1,3 @@ +package model + +const Version = "SPDX-2.2" diff --git a/internal/formats/spdx22json/test-fixtures/image-simple/Dockerfile b/internal/formats/spdx22json/test-fixtures/image-simple/Dockerfile new file mode 100644 index 00000000000..79cfa759e35 --- /dev/null +++ b/internal/formats/spdx22json/test-fixtures/image-simple/Dockerfile @@ -0,0 +1,4 @@ +# Note: changes to this file will result in updating several test values. Consider making a new image fixture instead of editing this one. +FROM scratch +ADD file-1.txt /somefile-1.txt +ADD file-2.txt /somefile-2.txt diff --git a/internal/formats/spdx22json/test-fixtures/image-simple/file-1.txt b/internal/formats/spdx22json/test-fixtures/image-simple/file-1.txt new file mode 100644 index 00000000000..985d3408e98 --- /dev/null +++ b/internal/formats/spdx22json/test-fixtures/image-simple/file-1.txt @@ -0,0 +1 @@ +this file has contents \ No newline at end of file diff --git a/internal/formats/spdx22json/test-fixtures/image-simple/file-2.txt b/internal/formats/spdx22json/test-fixtures/image-simple/file-2.txt new file mode 100644 index 00000000000..396d08bbc72 --- /dev/null +++ b/internal/formats/spdx22json/test-fixtures/image-simple/file-2.txt @@ -0,0 +1 @@ +file-2 contents! \ No newline at end of file diff --git a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden new file mode 100644 index 00000000000..249517449ad --- /dev/null +++ b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden @@ -0,0 +1,79 @@ +{ + "SPDXID": "SPDXRef-DOCUMENT", + "name": "/some/path", + "spdxVersion": "SPDX-2.2", + "creationInfo": { + "created": "2021-09-16T20:44:35.198887Z", + "creators": [ + "Organization: Anchore, Inc", + "Tool: syft-[not provided]" + ], + "licenseListVersion": "3.14" + }, + "dataLicense": "CC0-1.0", + "documentNamespace": "https://anchore.com/syft/image/", + "packages": [ + { + "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", + "name": "package-1", + "licenseConcluded": "MIT", + "downloadLocation": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "a-purl-2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9" + ], + "licenseDeclared": "MIT", + "sourceInfo": "acquired package info from installed python package manifest file: /some/path/pkg1", + "versionInfo": "1.0.1" + }, + { + "SPDXID": "SPDXRef-Package-deb-package-2-2.0.1", + "name": "package-2", + "licenseConcluded": "NONE", + "downloadLocation": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "a-purl-2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseDeclared": "NONE", + "sourceInfo": "acquired package info from DPKG DB: /some/path/pkg1", + "versionInfo": "2.0.1" + } + ], + "files": [ + { + "SPDXID": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9", + "name": "foo", + "licenseConcluded": "", + "fileName": "/some/path/pkg1/depedencies/foo" + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-Package-python-package-1-1.0.1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9" + } + ] +} diff --git a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden new file mode 100644 index 00000000000..8906ef161ac --- /dev/null +++ b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden @@ -0,0 +1,61 @@ +{ + "SPDXID": "SPDXRef-DOCUMENT", + "name": "user-image-input", + "spdxVersion": "SPDX-2.2", + "creationInfo": { + "created": "2021-09-16T20:44:35.203911Z", + "creators": [ + "Organization: Anchore, Inc", + "Tool: syft-[not provided]" + ], + "licenseListVersion": "3.14" + }, + "dataLicense": "CC0-1.0", + "documentNamespace": "https://anchore.com/syft/image/user-image-input", + "packages": [ + { + "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", + "name": "package-1", + "licenseConcluded": "MIT", + "downloadLocation": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "a-purl-1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseDeclared": "MIT", + "sourceInfo": "acquired package info from installed python package manifest file: /somefile-1.txt", + "versionInfo": "1.0.1" + }, + { + "SPDXID": "SPDXRef-Package-deb-package-2-2.0.1", + "name": "package-2", + "licenseConcluded": "NONE", + "downloadLocation": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "a-purl-2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseDeclared": "NONE", + "sourceInfo": "acquired package info from DPKG DB: /somefile-2.txt", + "versionInfo": "2.0.1" + } + ] +} diff --git a/internal/formats/spdx22json/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden b/internal/formats/spdx22json/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden new file mode 100644 index 0000000000000000000000000000000000000000..c1b1d2b797ecd34a5276a1aa2fb18c5b0a58c732 GIT binary patch literal 15360 zcmeHO+iu%N5Y=ZaKc z4r#BxuDkuJ7{OBcm#%FzyUOYr8lw^9HIDjR+4F_Fg0dOV`$VGKgH38I>Hgnpur)R2 zl)HY_XM^MD!m4A0dKhDcAS?&*f(4T;Kn>ke#l4gzVN` ze(?Rjwf#RFzkC1s- z9>CiEk8VKl|Mzk`OrxxEw%gtY==qIJx$uy+*ED8?qX(EcDL{I387Ngsb4dh?x$wg9 z*h*rg6@ZQ(w@kA*(GHyphO!?TNJz`YJ>fe4rt;(!W2awfa(sRRC68dzXajVE@y-n>o(^op5E2ZJDVs7 z4hRGU0s;YnXN7=m8LaJu|D{?6{&zpONo)J>g#RTf@W1=9f8c-jgY$EprS<=wcn6J zY-{-4@PCvC{%=1g#vT7ROM=?XoSXT-=K0?$|A*;W&6n z=@JS7fq+0jARzERL||m{EQP9mOdkK&{`^hnzm$9>7qof)M_D-kzZUPOjKl2tmy1l1 zh;8Ft5R3%h!MHdz7xT>W8cHZCSB&8>&90l53=Xp<>E*D>M<2Vo8*8l9D*K-ZL#y zZQ=xy1TbwlA*sSvk$`4t>Jlk6(avMSc$^Yo%t_n4Rq$q>(~gPk+Y4v#cWf^=0@K;g zetL>o_SUyVTU8mpNs&Rdt4TMle|Dc6KFbBi^{-S||GP5Biri^bZCIhryCba^=@v2! WZ*QOH3R;0P6aoSPfq=kwgTOxo35itz literal 0 HcmV?d00001 diff --git a/internal/formats/spdx22json/to_format_model.go b/internal/formats/spdx22json/to_format_model.go new file mode 100644 index 00000000000..d465919a402 --- /dev/null +++ b/internal/formats/spdx22json/to_format_model.go @@ -0,0 +1,164 @@ +package spdx22json + +import ( + "fmt" + "path" + "strings" + "time" + + "github.com/anchore/syft/syft/distro" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/formats/common/spdxhelpers" + "github.com/anchore/syft/internal/formats/spdx22json/model" + "github.com/anchore/syft/internal/spdxlicense" + "github.com/anchore/syft/internal/version" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" + "github.com/google/uuid" +) + +// toFormatModel creates and populates a new JSON document struct that follows the SPDX 2.2 spec from the given cataloging results. +func toFormatModel(catalog *pkg.Catalog, srcMetadata *source.Metadata, d *distro.Distro) model.Document { + name := documentName(srcMetadata) + packages, files, relationships := extractFromCatalog(catalog) + + return model.Document{ + Element: model.Element{ + SPDXID: model.ElementID("DOCUMENT").String(), + Name: name, + }, + SPDXVersion: model.Version, + CreationInfo: model.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: documentNamespace(name, srcMetadata), + Packages: packages, + Files: files, + Relationships: relationships, + SyftSourceData: srcMetadata, + SyftDistroData: toSyftDistroData(d), + } +} + +func toSyftDistroData(d *distro.Distro) *model.SyftDistroData { + if d == nil { + return nil + } + return &model.SyftDistroData{ + Name: d.Name(), + Version: d.FullVersion(), + IDLike: d.IDLike, + } +} + +func documentName(srcMetadata *source.Metadata) string { + if srcMetadata != nil { + switch srcMetadata.Scheme { + case source.ImageScheme: + return cleanSPDXName(srcMetadata.ImageMetadata.UserInput) + case source.DirectoryScheme: + return cleanSPDXName(srcMetadata.Path) + } + } + // TODO: is this alright? + return uuid.Must(uuid.NewRandom()).String() +} + +func documentNamespace(name string, srcMetadata *source.Metadata) string { + input := "unknown-source-type" + if srcMetadata != nil { + switch srcMetadata.Scheme { + case source.ImageScheme: + input = "image" + case source.DirectoryScheme: + input = "dir" + } + } + + uniqueID := uuid.Must(uuid.NewRandom()) + identifier := path.Join(input, uniqueID.String()) + if name != "." { + identifier = path.Join(input, fmt.Sprintf("%s-%s", name, uniqueID.String())) + } + + return path.Join(anchoreNamespace, identifier) +} + +func extractFromCatalog(catalog *pkg.Catalog) ([]model.Package, []model.File, []model.Relationship) { + packages := make([]model.Package, 0) + relationships := make([]model.Relationship, 0) + files := make([]model.File, 0) + + for _, p := range catalog.Sorted() { + license := spdxhelpers.License(p) + packageSpdxID := model.ElementID(fmt.Sprintf("Package-%+v-%s-%s", p.Type, p.Name, p.Version)).String() + + packageFiles, fileIDs, packageFileRelationships := spdxhelpers.Files(packageSpdxID, p) + files = append(files, packageFiles...) + + relationships = append(relationships, packageFileRelationships...) + + // 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). + packages = append(packages, model.Package{ + Description: spdxhelpers.Description(p), + DownloadLocation: spdxhelpers.DownloadLocation(p), + ExternalRefs: spdxhelpers.ExternalRefs(p), + FilesAnalyzed: false, + HasFiles: fileIDs, + Homepage: spdxhelpers.Homepage(p), + LicenseDeclared: license, // The Declared License is what the authors of a project believe govern the package + Originator: spdxhelpers.Originator(p), + SourceInfo: spdxhelpers.SourceInfo(p), + VersionInfo: p.Version, + Item: model.Item{ + LicenseConcluded: license, // The Concluded License field is the license the SPDX file creator believes governs the package + Element: model.Element{ + SPDXID: packageSpdxID, + Name: p.Name, + }, + }, + SyftPackageData: toSyftPackageData(p), + }) + } + + return packages, files, relationships +} + +func toSyftPackageData(p *pkg.Package) *model.SyftPackageData { + if p == nil { + return nil + } + return &model.SyftPackageData{ + SyftPackageBasicData: model.SyftPackageBasicData{ + PackageType: p.Type, + FoundBy: p.FoundBy, + Locations: p.Locations, + Language: p.Language, + Licenses: p.Licenses, + }, + SyftPackageCustomData: model.SyftPackageCustomData{ + MetadataType: p.MetadataType, + Metadata: p.Metadata, + }, + } +} + +func cleanSPDXName(name string) string { + // remove # according to specification + name = strings.ReplaceAll(name, "#", "-") + + // remove : for url construction + name = strings.ReplaceAll(name, ":", "-") + + // clean relative pathing + return path.Clean(name) +} diff --git a/internal/formats/spdx22json/to_syft_model.go b/internal/formats/spdx22json/to_syft_model.go new file mode 100644 index 00000000000..b0a9edbd3d1 --- /dev/null +++ b/internal/formats/spdx22json/to_syft_model.go @@ -0,0 +1,64 @@ +package spdx22json + +import ( + "github.com/anchore/syft/internal/formats/common/spdxhelpers" + "github.com/anchore/syft/internal/formats/spdx22json/model" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/distro" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" +) + +func toSyftModel(doc model.Document) (*pkg.Catalog, *source.Metadata, *distro.Distro, error) { + d, err := toSyftDistro(doc.SyftDistroData) + if err != nil { + log.Warnf("unable to parse distro info=%+v: %+v", d, err) + d = nil + } + + return toSyftCatalog(doc.Packages), doc.SyftSourceData, d, nil +} + +func toSyftCatalog(pkgs []model.Package) *pkg.Catalog { + catalog := pkg.NewCatalog() + for _, p := range pkgs { + catalog.Add(toSyftPackage(p)) + } + return catalog +} + +func toSyftPackage(p model.Package) pkg.Package { + syftPkg := pkg.Package{ + Name: p.Name, + Version: p.VersionInfo, + CPEs: spdxhelpers.ExtractCPEs(p.ExternalRefs), + PURL: spdxhelpers.ExtractPURL(p.ExternalRefs), + } + + if extra := p.SyftPackageData; extra != nil { + syftPkg.Type = extra.PackageType + syftPkg.FoundBy = extra.FoundBy + syftPkg.Locations = extra.Locations + syftPkg.Language = extra.Language + syftPkg.Licenses = extra.Licenses + syftPkg.MetadataType = extra.MetadataType + syftPkg.Metadata = extra.Metadata + } + + //if syftPkg.Type == "" && syftPkg.PURL != "" { + // // TODO: extract package type from purl --this is useful for ingesting from tools other than syft and is important for grype + //} + + return syftPkg +} + +func toSyftDistro(d *model.SyftDistroData) (*distro.Distro, error) { + if d == nil { + return nil, nil + } + newDistro, err := distro.NewDistro(distro.Type(d.Name), d.Version, d.IDLike) + if err != nil { + return nil, err + } + return &newDistro, nil +} diff --git a/internal/formats/spdx22json/validator.go b/internal/formats/spdx22json/validator.go new file mode 100644 index 00000000000..5bcbc6f182f --- /dev/null +++ b/internal/formats/spdx22json/validator.go @@ -0,0 +1,26 @@ +package spdx22json + +import ( + "encoding/json" + "fmt" + "io" +) + +func validator(reader io.Reader) error { + type Document struct { + SPDXID string `json:"SPDXID"` + } + + dec := json.NewDecoder(reader) + + var doc Document + err := dec.Decode(&doc) + if err != nil { + return fmt.Errorf("unable to decode: %w", err) + } + + if doc.SPDXID != "" { + return nil + } + return fmt.Errorf("could not extract document SPDXID") +} From bcdebcadaf9cbbeab61fa0526ab96d128d9522e5 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:32:02 -0700 Subject: [PATCH 04/17] add internal.formats helper functions + identify tests Signed-off-by: Alex Goodman --- internal/formats/formats.go | 33 +++++++++++++++++++++++++++ internal/formats/formats_test.go | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 internal/formats/formats.go create mode 100644 internal/formats/formats_test.go diff --git a/internal/formats/formats.go b/internal/formats/formats.go new file mode 100644 index 00000000000..0022780bf59 --- /dev/null +++ b/internal/formats/formats.go @@ -0,0 +1,33 @@ +package formats + +import ( + "github.com/anchore/syft/internal/formats/spdx22json" + "github.com/anchore/syft/internal/formats/syftjson" + "github.com/anchore/syft/syft/format" +) + +// TODO: eventually this is the source of truth for all formatters +func All() []format.Format { + return []format.Format{ + spdx22json.Format(), + syftjson.Format(), + } +} + +func Identify(by []byte) (*format.Format, error) { + for _, f := range All() { + if f.Detect(by) { + return &f, nil + } + } + return nil, nil +} + +func ByOption(option format.Option) *format.Format { + for _, f := range All() { + if f.Option == option { + return &f + } + } + return nil +} diff --git a/internal/formats/formats_test.go b/internal/formats/formats_test.go new file mode 100644 index 00000000000..e1f082c0488 --- /dev/null +++ b/internal/formats/formats_test.go @@ -0,0 +1,39 @@ +package formats + +import ( + "io" + "os" + "testing" + + "github.com/anchore/syft/syft/format" + "github.com/stretchr/testify/assert" +) + +func TestIdentify(t *testing.T) { + + tests := []struct { + fixture string + expected format.Option + }{ + { + fixture: "test-fixtures/alpine-syft.json", + expected: format.JSONOption, + }, + { + fixture: "test-fixtures/alpine-syft-spdx.json", + expected: format.SPDXJSONOption, + }, + } + for _, test := range tests { + t.Run(test.fixture, func(t *testing.T) { + f, err := os.Open(test.fixture) + assert.NoError(t, err) + by, err := io.ReadAll(f) + assert.NoError(t, err) + frmt, err := Identify(by) + assert.NoError(t, err) + assert.NotNil(t, frmt) + assert.Equal(t, test.expected, frmt.Option) + }) + } +} From 12b44af471c77ae8b3d0ae537a29dec08fa1952c Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:32:42 -0700 Subject: [PATCH 05/17] add encode and decode to the syft lib interface Signed-off-by: Alex Goodman --- syft/lib.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/syft/lib.go b/syft/lib.go index 4b76a9900f2..3a074e6d8e8 100644 --- a/syft/lib.go +++ b/syft/lib.go @@ -17,11 +17,15 @@ Similar to the cataloging process, Linux distribution identification is also per package syft import ( + "bytes" "fmt" + "io" "github.com/anchore/syft/internal/bus" + "github.com/anchore/syft/internal/formats" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/distro" + "github.com/anchore/syft/syft/format" "github.com/anchore/syft/syft/logger" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger" @@ -67,6 +71,35 @@ func CatalogPackages(src *source.Source, scope source.Scope) (*pkg.Catalog, *dis return catalog, theDistro, nil } +// TODO: encapsulate input data into common sbom document object +func Encode(catalog *pkg.Catalog, metadata *source.Metadata, dist *distro.Distro, option format.Option) ([]byte, error) { + f := formats.ByOption(option) + if f == nil { + return nil, nil + } + buff := bytes.Buffer{} + + return buff.Bytes(), f.Encode(&buff, catalog, dist, metadata) +} + +// TODO: encapsulate return data into common sbom document object +func Decode(reader io.Reader) (*pkg.Catalog, *source.Metadata, *distro.Distro, format.Option, error) { + by, err := io.ReadAll(reader) + if err != nil { + return nil, nil, nil, format.UnknownOption, fmt.Errorf("unable to read sbom: %w", err) + } + + f, err := formats.Identify(by) + if err != nil { + return nil, nil, nil, format.UnknownOption, fmt.Errorf("unable to detect format: %w", err) + } + if f == nil { + return nil, nil, nil, format.UnknownOption, fmt.Errorf("unable to identify format") + } + c, m, d, err := f.Decode(bytes.NewReader(by)) + return c, m, d, f.Option, err +} + // SetLogger sets the logger object used for all syft logging calls. func SetLogger(logger logger.Logger) { log.Log = logger From 124cfd86c71d457d8b6246df7a2a0b0ce2be7080 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:35:02 -0700 Subject: [PATCH 06/17] replace presenter.Option with format.Option Signed-off-by: Alex Goodman --- cmd/packages.go | 14 +++--- .../{presenter_config.go => config.go} | 2 +- syft/presenter/packages/presenter.go | 26 ++++++----- syft/presenter/packages/presenter_option.go | 43 ------------------- syft/presenter/presenter.go | 4 +- 5 files changed, 27 insertions(+), 62 deletions(-) rename syft/presenter/packages/{presenter_config.go => config.go} (89%) delete mode 100644 syft/presenter/packages/presenter_option.go diff --git a/cmd/packages.go b/cmd/packages.go index 4078b66c753..2c785607261 100644 --- a/cmd/packages.go +++ b/cmd/packages.go @@ -6,6 +6,8 @@ import ( "io/ioutil" "os" + "github.com/anchore/syft/syft/format" + "github.com/anchore/stereoscope" "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/anchore" @@ -48,7 +50,7 @@ const ( ) var ( - packagesPresenterOpt packages.PresenterOption + packagesPresenterOpt format.Option packagesArgs = cobra.MaximumNArgs(1) packagesCmd = &cobra.Command{ Use: "packages [SOURCE]", @@ -71,8 +73,8 @@ var ( } // set the presenter - presenterOption := packages.ParsePresenterOption(appConfig.Output) - if presenterOption == packages.UnknownPresenterOption { + presenterOption := format.ParseOption(appConfig.Output) + if presenterOption == format.UnknownOption { return fmt.Errorf("bad --output value '%s'", appConfig.Output) } packagesPresenterOpt = presenterOption @@ -109,8 +111,8 @@ func setPackageFlags(flags *pflag.FlagSet) { fmt.Sprintf("selection of layers to catalog, options=%v", source.AllScopes)) flags.StringP( - "output", "o", string(packages.TablePresenterOption), - fmt.Sprintf("report output formatter, options=%v", packages.AllPresenters), + "output", "o", string(format.TableOption), + fmt.Sprintf("report output formatter, options=%v", format.AllOptions), ) flags.StringP( @@ -247,7 +249,7 @@ func packagesExecWorker(userInput string) <-chan error { bus.Publish(partybus.Event{ Type: event.PresenterReady, - Value: packages.Presenter(packagesPresenterOpt, packages.PresenterConfig{ + Value: packages.Presenter(packagesPresenterOpt, packages.Config{ SourceMetadata: src.Metadata, Catalog: catalog, Distro: d, diff --git a/syft/presenter/packages/presenter_config.go b/syft/presenter/packages/config.go similarity index 89% rename from syft/presenter/packages/presenter_config.go rename to syft/presenter/packages/config.go index d318e428862..8c988d1e868 100644 --- a/syft/presenter/packages/presenter_config.go +++ b/syft/presenter/packages/config.go @@ -6,7 +6,7 @@ import ( "github.com/anchore/syft/syft/source" ) -type PresenterConfig struct { +type Config struct { SourceMetadata source.Metadata Catalog *pkg.Catalog Distro *distro.Distro diff --git a/syft/presenter/packages/presenter.go b/syft/presenter/packages/presenter.go index 6d0d594efd4..d26f727fc33 100644 --- a/syft/presenter/packages/presenter.go +++ b/syft/presenter/packages/presenter.go @@ -5,26 +5,30 @@ a specific Presenter implementation given user configuration. package packages import ( + "github.com/anchore/syft/internal/formats" "github.com/anchore/syft/internal/presenter/packages" + "github.com/anchore/syft/syft/format" "github.com/anchore/syft/syft/presenter" ) // Presenter returns a presenter for images or directories -func Presenter(option PresenterOption, config PresenterConfig) presenter.Presenter { - switch option { - case JSONPresenterOption: - return packages.NewJSONPresenter(config.Catalog, config.SourceMetadata, config.Distro, config.Scope) - case TextPresenterOption: +func Presenter(o format.Option, config Config) presenter.Presenter { + // TODO: This function will be removed in the future + switch o { + case format.TextOption: return packages.NewTextPresenter(config.Catalog, config.SourceMetadata) - case TablePresenterOption: + case format.TableOption: return packages.NewTablePresenter(config.Catalog) - case CycloneDxPresenterOption: + case format.CycloneDxOption: return packages.NewCycloneDxPresenter(config.Catalog, config.SourceMetadata) - case SPDXTagValuePresenterOption: + case format.SPDXTagValueOption: return packages.NewSPDXTagValuePresenter(config.Catalog, config.SourceMetadata) - case SPDXJSONPresenterOption: - return packages.NewSPDXJSONPresenter(config.Catalog, config.SourceMetadata) default: - return nil + // TODO: this is the new way of getting presenters from formats + f := formats.ByOption(o) + if f == nil { + return nil + } + return f.Presenter(config.Catalog, &config.SourceMetadata, config.Distro) } } diff --git a/syft/presenter/packages/presenter_option.go b/syft/presenter/packages/presenter_option.go deleted file mode 100644 index 7bdcbc07572..00000000000 --- a/syft/presenter/packages/presenter_option.go +++ /dev/null @@ -1,43 +0,0 @@ -package packages - -import "strings" - -const ( - UnknownPresenterOption PresenterOption = "UnknownPresenterOption" - JSONPresenterOption PresenterOption = "json" - TextPresenterOption PresenterOption = "text" - TablePresenterOption PresenterOption = "table" - CycloneDxPresenterOption PresenterOption = "cyclonedx" - SPDXTagValuePresenterOption PresenterOption = "spdx-tag-value" - SPDXJSONPresenterOption PresenterOption = "spdx-json" -) - -var AllPresenters = []PresenterOption{ - JSONPresenterOption, - TextPresenterOption, - TablePresenterOption, - CycloneDxPresenterOption, - SPDXTagValuePresenterOption, - SPDXJSONPresenterOption, -} - -type PresenterOption string - -func ParsePresenterOption(userStr string) PresenterOption { - switch strings.ToLower(userStr) { - case string(JSONPresenterOption): - return JSONPresenterOption - case string(TextPresenterOption): - return TextPresenterOption - case string(TablePresenterOption): - return TablePresenterOption - case string(CycloneDxPresenterOption), "cyclone", "cyclone-dx": - return CycloneDxPresenterOption - case string(SPDXTagValuePresenterOption), "spdx", "spdx-tagvalue", "spdxtagvalue", "spdx-tv": - return SPDXTagValuePresenterOption - case string(SPDXJSONPresenterOption), "spdxjson": - return SPDXJSONPresenterOption - default: - return UnknownPresenterOption - } -} diff --git a/syft/presenter/presenter.go b/syft/presenter/presenter.go index 823a2e38dfb..45710e1f494 100644 --- a/syft/presenter/presenter.go +++ b/syft/presenter/presenter.go @@ -1,6 +1,8 @@ package presenter -import "io" +import ( + "io" +) // Presenter defines the expected behavior for an object responsible for displaying arbitrary input and processed data // to a given io.Writer. From 8d522efcf651a0441e7c16e15abd49924d77fdec Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:36:23 -0700 Subject: [PATCH 07/17] remove json presenter Signed-off-by: Alex Goodman --- .../presenter/packages/json_distribution.go | 23 ------ internal/presenter/packages/json_document.go | 62 ---------------- internal/presenter/packages/json_package.go | 71 ------------------- internal/presenter/packages/json_presenter.go | 43 ----------- .../presenter/packages/json_presenter_test.go | 37 ---------- .../presenter/packages/json_relationship.go | 23 ------ internal/presenter/packages/json_source.go | 39 ---------- 7 files changed, 298 deletions(-) delete mode 100644 internal/presenter/packages/json_distribution.go delete mode 100644 internal/presenter/packages/json_document.go delete mode 100644 internal/presenter/packages/json_package.go delete mode 100644 internal/presenter/packages/json_presenter.go delete mode 100644 internal/presenter/packages/json_presenter_test.go delete mode 100644 internal/presenter/packages/json_relationship.go delete mode 100644 internal/presenter/packages/json_source.go diff --git a/internal/presenter/packages/json_distribution.go b/internal/presenter/packages/json_distribution.go deleted file mode 100644 index 5ba939c03ec..00000000000 --- a/internal/presenter/packages/json_distribution.go +++ /dev/null @@ -1,23 +0,0 @@ -package packages - -import "github.com/anchore/syft/syft/distro" - -// JSONDistribution provides information about a detected Linux JSONDistribution. -type JSONDistribution struct { - Name string `json:"name"` // Name of the Linux distribution - Version string `json:"version"` // Version of the Linux distribution (major or major.minor version) - IDLike string `json:"idLike"` // the ID_LIKE field found within the /etc/os-release file -} - -// NewJSONDistribution creates a struct with the Linux distribution to be represented in JSON. -func NewJSONDistribution(d *distro.Distro) JSONDistribution { - if d == nil { - return JSONDistribution{} - } - - return JSONDistribution{ - Name: d.Name(), - Version: d.FullVersion(), - IDLike: d.IDLike, - } -} diff --git a/internal/presenter/packages/json_document.go b/internal/presenter/packages/json_document.go deleted file mode 100644 index 399d037ae45..00000000000 --- a/internal/presenter/packages/json_document.go +++ /dev/null @@ -1,62 +0,0 @@ -package packages - -import ( - "fmt" - - "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/source" -) - -// JSONDocument represents the syft cataloging findings as a JSON document -type JSONDocument struct { - Artifacts []JSONPackage `json:"artifacts"` // Artifacts is the list of packages discovered and placed into the catalog - ArtifactRelationships []JSONRelationship `json:"artifactRelationships"` - Source JSONSource `json:"source"` // Source represents the original object that was cataloged - Distro JSONDistribution `json:"distro"` // Distro represents the Linux distribution that was detected from the source - Descriptor JSONDescriptor `json:"descriptor"` // Descriptor is a block containing self-describing information about syft - Schema JSONSchema `json:"schema"` // Schema is a block reserved for defining the version for the shape of this JSON document and where to find the schema document to validate the shape -} - -// NewJSONDocument creates and populates a new JSON document struct from the given cataloging results. -func NewJSONDocument(catalog *pkg.Catalog, srcMetadata source.Metadata, d *distro.Distro, scope source.Scope, configuration interface{}) (JSONDocument, error) { - src, err := NewJSONSource(srcMetadata, scope) - if err != nil { - return JSONDocument{}, err - } - - artifacts, err := NewJSONPackages(catalog) - if err != nil { - return JSONDocument{}, err - } - - return JSONDocument{ - Artifacts: artifacts, - ArtifactRelationships: newJSONRelationships(pkg.NewRelationships(catalog)), - Source: src, - Distro: NewJSONDistribution(d), - Descriptor: JSONDescriptor{ - Name: internal.ApplicationName, - Version: version.FromBuild().Version, - Configuration: configuration, - }, - Schema: JSONSchema{ - Version: internal.JSONSchemaVersion, - URL: fmt.Sprintf("https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-%s.json", internal.JSONSchemaVersion), - }, - }, nil -} - -// JSONDescriptor describes what created the document as well as surrounding metadata -type JSONDescriptor struct { - Name string `json:"name"` - Version string `json:"version"` - Configuration interface{} `json:"configuration,omitempty"` -} - -type JSONSchema struct { - Version string `json:"version"` - URL string `json:"url"` -} diff --git a/internal/presenter/packages/json_package.go b/internal/presenter/packages/json_package.go deleted file mode 100644 index a2ea899dd3e..00000000000 --- a/internal/presenter/packages/json_package.go +++ /dev/null @@ -1,71 +0,0 @@ -package packages - -import ( - "github.com/anchore/syft/syft/pkg" - "github.com/anchore/syft/syft/source" -) - -// JSONPackage represents a pkg.Package object specialized for JSON marshaling and unmarshaling. -type JSONPackage struct { - ID string `json:"id"` - Name string `json:"name"` - Version string `json:"version"` - Type string `json:"type"` - FoundBy string `json:"foundBy"` - Locations []source.Location `json:"locations"` - Licenses []string `json:"licenses"` - Language string `json:"language"` - CPEs []string `json:"cpes"` - PURL string `json:"purl"` - MetadataType string `json:"metadataType"` - Metadata interface{} `json:"metadata"` -} - -func NewJSONPackages(catalog *pkg.Catalog) ([]JSONPackage, error) { - artifacts := make([]JSONPackage, 0) - if catalog == nil { - return artifacts, nil - } - for _, p := range catalog.Sorted() { - art, err := NewJSONPackage(p) - if err != nil { - return nil, err - } - artifacts = append(artifacts, art) - } - return artifacts, nil -} - -// NewJSONPackage crates a new JSONPackage from the given pkg.Package. -func NewJSONPackage(p *pkg.Package) (JSONPackage, error) { - var cpes = make([]string, len(p.CPEs)) - for i, c := range p.CPEs { - cpes[i] = c.BindToFmtString() - } - - // ensure collections are never nil for presentation reasons - var locations = make([]source.Location, 0) - if p.Locations != nil { - locations = p.Locations - } - - var licenses = make([]string, 0) - if p.Licenses != nil { - licenses = p.Licenses - } - - return JSONPackage{ - ID: string(p.ID), - Name: p.Name, - Version: p.Version, - Type: string(p.Type), - FoundBy: p.FoundBy, - Locations: locations, - Licenses: licenses, - Language: string(p.Language), - CPEs: cpes, - PURL: p.PURL, - MetadataType: string(p.MetadataType), - Metadata: p.Metadata, - }, nil -} diff --git a/internal/presenter/packages/json_presenter.go b/internal/presenter/packages/json_presenter.go deleted file mode 100644 index cbdc4d107d3..00000000000 --- a/internal/presenter/packages/json_presenter.go +++ /dev/null @@ -1,43 +0,0 @@ -package packages - -import ( - "encoding/json" - "io" - - "github.com/anchore/syft/syft/distro" - "github.com/anchore/syft/syft/pkg" - "github.com/anchore/syft/syft/source" -) - -// JSONPresenter is a JSON presentation object for the syft results -type JSONPresenter struct { - catalog *pkg.Catalog - srcMetadata source.Metadata - distro *distro.Distro - scope source.Scope -} - -// NewJSONPresenter creates a new JSON presenter object for the given cataloging results. -func NewJSONPresenter(catalog *pkg.Catalog, s source.Metadata, d *distro.Distro, scope source.Scope) *JSONPresenter { - return &JSONPresenter{ - catalog: catalog, - srcMetadata: s, - distro: d, - scope: scope, - } -} - -// Present the catalog results to the given writer. -func (pres *JSONPresenter) Present(output io.Writer) error { - // we do not pass in configuration for backwards compatibility - doc, err := NewJSONDocument(pres.catalog, pres.srcMetadata, pres.distro, pres.scope, nil) - if err != nil { - return err - } - - enc := json.NewEncoder(output) - // prevent > and < from being escaped in the payload - enc.SetEscapeHTML(false) - enc.SetIndent("", " ") - return enc.Encode(&doc) -} diff --git a/internal/presenter/packages/json_presenter_test.go b/internal/presenter/packages/json_presenter_test.go deleted file mode 100644 index 9620c2da725..00000000000 --- a/internal/presenter/packages/json_presenter_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package packages - -import ( - "flag" - "testing" - - "github.com/anchore/syft/syft/pkg" - "github.com/anchore/syft/syft/source" -) - -var updateJSONGoldenFiles = flag.Bool("update-json", false, "update the *.golden files for json presenters") - -func must(c pkg.CPE, e error) pkg.CPE { - if e != nil { - panic(e) - } - return c -} - -func TestJSONDirectoryPresenter(t *testing.T) { - catalog, metadata, dist := presenterDirectoryInput(t) - assertPresenterAgainstGoldenSnapshot(t, - NewJSONPresenter(catalog, metadata, dist, source.SquashedScope), - *updateJSONGoldenFiles, - ) - -} - -func TestJSONImagePresenter(t *testing.T) { - testImage := "image-simple" - catalog, metadata, dist := presenterImageInput(t, testImage) - assertPresenterAgainstGoldenImageSnapshot(t, - NewJSONPresenter(catalog, metadata, dist, source.SquashedScope), - testImage, - *updateJSONGoldenFiles, - ) -} diff --git a/internal/presenter/packages/json_relationship.go b/internal/presenter/packages/json_relationship.go deleted file mode 100644 index 326e4a4a570..00000000000 --- a/internal/presenter/packages/json_relationship.go +++ /dev/null @@ -1,23 +0,0 @@ -package packages - -import "github.com/anchore/syft/syft/pkg" - -type JSONRelationship struct { - Parent string `json:"parent"` - Child string `json:"child"` - Type string `json:"type"` - Metadata interface{} `json:"metadata"` -} - -func newJSONRelationships(relationships []pkg.Relationship) []JSONRelationship { - result := make([]JSONRelationship, len(relationships)) - for i, r := range relationships { - result[i] = JSONRelationship{ - Parent: string(r.Parent), - Child: string(r.Child), - Type: string(r.Type), - Metadata: r.Metadata, - } - } - return result -} diff --git a/internal/presenter/packages/json_source.go b/internal/presenter/packages/json_source.go deleted file mode 100644 index d0c2a477f1e..00000000000 --- a/internal/presenter/packages/json_source.go +++ /dev/null @@ -1,39 +0,0 @@ -package packages - -import ( - "fmt" - - "github.com/anchore/syft/syft/source" -) - -// JSONSource object represents the thing that was cataloged -type JSONSource struct { - Type string `json:"type"` - Target interface{} `json:"target"` -} - -type JSONImageSource struct { - source.ImageMetadata - Scope source.Scope `json:"scope"` -} - -// NewJSONSource creates a new source object to be represented into JSON. -func NewJSONSource(src source.Metadata, scope source.Scope) (JSONSource, error) { - switch src.Scheme { - case source.ImageScheme: - return JSONSource{ - Type: "image", - Target: JSONImageSource{ - Scope: scope, - ImageMetadata: src.ImageMetadata, - }, - }, nil - case source.DirectoryScheme: - return JSONSource{ - Type: "directory", - Target: src.Path, - }, nil - default: - return JSONSource{}, fmt.Errorf("unsupported source: %q", src.Scheme) - } -} From 0c0890ef44f4e97c804a5fd4b9ee34ce854ae76b Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:38:28 -0700 Subject: [PATCH 08/17] remove spdx json presenter + model Signed-off-by: Alex Goodman --- .../packages/model/spdx22/annotation.go | 21 -- .../packages/model/spdx22/checksum.go | 7 - .../packages/model/spdx22/creation_info.go | 19 -- .../packages/model/spdx22/document.go | 45 ---- .../packages/model/spdx22/element.go | 12 - .../packages/model/spdx22/element_id.go | 37 ---- .../model/spdx22/external_document_ref.go | 9 - .../packages/model/spdx22/external_ref.go | 43 ---- .../presenter/packages/model/spdx22/file.go | 41 ---- .../spdx22/has_extracted_licensing_info.go | 14 -- .../presenter/packages/model/spdx22/item.go | 22 -- .../packages/model/spdx22/package.go | 50 ----- .../model/spdx22/package_verification_code.go | 23 -- .../packages/model/spdx22/relationship.go | 183 ---------------- .../packages/model/spdx22/snippet.go | 32 --- .../packages/model/spdx22/version.go | 3 - internal/presenter/packages/spdx_helpers.go | 207 ------------------ .../presenter/packages/spdx_json_presenter.go | 142 ------------ .../packages/spdx_json_presenter_test.go | 40 ---- 19 files changed, 950 deletions(-) delete mode 100644 internal/presenter/packages/model/spdx22/annotation.go delete mode 100644 internal/presenter/packages/model/spdx22/checksum.go delete mode 100644 internal/presenter/packages/model/spdx22/creation_info.go delete mode 100644 internal/presenter/packages/model/spdx22/document.go delete mode 100644 internal/presenter/packages/model/spdx22/element.go delete mode 100644 internal/presenter/packages/model/spdx22/element_id.go delete mode 100644 internal/presenter/packages/model/spdx22/external_document_ref.go delete mode 100644 internal/presenter/packages/model/spdx22/external_ref.go delete mode 100644 internal/presenter/packages/model/spdx22/file.go delete mode 100644 internal/presenter/packages/model/spdx22/has_extracted_licensing_info.go delete mode 100644 internal/presenter/packages/model/spdx22/item.go delete mode 100644 internal/presenter/packages/model/spdx22/package.go delete mode 100644 internal/presenter/packages/model/spdx22/package_verification_code.go delete mode 100644 internal/presenter/packages/model/spdx22/relationship.go delete mode 100644 internal/presenter/packages/model/spdx22/snippet.go delete mode 100644 internal/presenter/packages/model/spdx22/version.go delete mode 100644 internal/presenter/packages/spdx_helpers.go delete mode 100644 internal/presenter/packages/spdx_json_presenter.go delete mode 100644 internal/presenter/packages/spdx_json_presenter_test.go diff --git a/internal/presenter/packages/model/spdx22/annotation.go b/internal/presenter/packages/model/spdx22/annotation.go deleted file mode 100644 index 048d4c31e0a..00000000000 --- a/internal/presenter/packages/model/spdx22/annotation.go +++ /dev/null @@ -1,21 +0,0 @@ -package spdx22 - -import "time" - -type AnnotationType string - -const ( - ReviewerAnnotationType AnnotationType = "REVIEWER" - OtherAnnotationType AnnotationType = "OTHER" -) - -type Annotation struct { - // Identify when the comment was made. This is to be specified according to the combined date and time in the - // UTC format, as specified in the ISO 8601 standard. - AnnotationDate time.Time `json:"annotationDate"` - // Type of the annotation - AnnotationType AnnotationType `json:"annotationType"` - // This field identifies the person, organization or tool that has commented on a file, package, or the entire document. - Annotator string `json:"annotator"` - Comment string `json:"comment"` -} diff --git a/internal/presenter/packages/model/spdx22/checksum.go b/internal/presenter/packages/model/spdx22/checksum.go deleted file mode 100644 index e137343c988..00000000000 --- a/internal/presenter/packages/model/spdx22/checksum.go +++ /dev/null @@ -1,7 +0,0 @@ -package spdx22 - -type Checksum struct { - // Identifies the algorithm used to produce the subject Checksum. One of: "SHA256", "SHA1", "SHA384", "MD2", "MD4", "SHA512", "MD6", "MD5", "SHA224" - Algorithm string `json:"algorithm"` - ChecksumValue string `json:"checksumValue"` -} diff --git a/internal/presenter/packages/model/spdx22/creation_info.go b/internal/presenter/packages/model/spdx22/creation_info.go deleted file mode 100644 index 9e1f51080e1..00000000000 --- a/internal/presenter/packages/model/spdx22/creation_info.go +++ /dev/null @@ -1,19 +0,0 @@ -package spdx22 - -import "time" - -type CreationInfo struct { - Comment string `json:"comment,omitempty"` - // Identify when the SPDX file was originally created. The date is to be specified according to combined date and - // time in UTC format as specified in ISO 8601 standard. This field is distinct from the fields in section 8, - // which involves the addition of information during a subsequent review. - Created time.Time `json:"created"` - // Identify who (or what, in the case of a tool) created the SPDX file. If the SPDX file was created by an - // individual, indicate the person's name. If the SPDX file was created on behalf of a company or organization, - //indicate the entity name. If the SPDX file was created using a software tool, indicate the name and version - // for that tool. If multiple participants or tools were involved, use multiple instances of this field. Person - // name or organization name may be designated as “anonymous” if appropriate. - Creators []string `json:"creators"` - // An optional field for creators of the SPDX file to provide the version of the SPDX License List used when the SPDX file was created. - LicenseListVersion string `json:"licenseListVersion"` -} diff --git a/internal/presenter/packages/model/spdx22/document.go b/internal/presenter/packages/model/spdx22/document.go deleted file mode 100644 index 1c9ab1f2a21..00000000000 --- a/internal/presenter/packages/model/spdx22/document.go +++ /dev/null @@ -1,45 +0,0 @@ -package spdx22 - -// derived from: -// - https://spdx.github.io/spdx-spec/appendix-III-RDF-data-model-implementation-and-identifier-syntax/ -// - https://github.com/spdx/spdx-spec/blob/v2.2/schemas/spdx-schema.json -// - https://github.com/spdx/spdx-spec/tree/v2.2/ontology - -type Document struct { - Element - SPDXVersion string `json:"spdxVersion"` - // One instance is required for each SPDX file produced. It provides the necessary information for forward - // and backward compatibility for processing tools. - CreationInfo CreationInfo `json:"creationInfo"` - // 2.2: Data License; should be "CC0-1.0" - // Cardinality: mandatory, one - // License expression for dataLicense. Compliance with the SPDX specification includes populating the SPDX - // fields therein with data related to such fields (\"SPDX-Metadata\"). The SPDX specification contains numerous - // fields where an SPDX document creator may provide relevant explanatory text in SPDX-Metadata. Without - // opining on the lawfulness of \"database rights\" (in jurisdictions where applicable), such explanatory text - // is copyrightable subject matter in most Berne Convention countries. By using the SPDX specification, or any - // portion hereof, you hereby agree that any copyright rights (as determined by your jurisdiction) in any - // SPDX-Metadata, including without limitation explanatory text, shall be subject to the terms of the Creative - // Commons CC0 1.0 Universal license. For SPDX-Metadata not containing any copyright rights, you hereby agree - // and acknowledge that the SPDX-Metadata is provided to you \"as-is\" and without any representations or - // warranties of any kind concerning the SPDX-Metadata, express, implied, statutory or otherwise, including - // without limitation warranties of title, merchantability, fitness for a particular purpose, non-infringement, - // or the absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not - // discoverable, all to the greatest extent permissible under applicable law. - DataLicense string `json:"dataLicense"` - // Information about an external SPDX document reference including the checksum. This allows for verification of the external references. - ExternalDocumentRefs []ExternalDocumentRef `json:"externalDocumentRefs,omitempty"` - // Indicates that a particular ExtractedLicensingInfo was defined in the subject SpdxDocument. - HasExtractedLicensingInfos []HasExtractedLicensingInfo `json:"hasExtractedLicensingInfos,omitempty"` - // note: found in example documents from SPDX, but not in the JSON schema. See https://spdx.github.io/spdx-spec/2-document-creation-information/#25-spdx-document-namespace - DocumentNamespace string `json:"documentNamespace"` - // note: found in example documents from SPDX, but not in the JSON schema - // DocumentDescribes []string `json:"documentDescribes"` - Packages []Package `json:"packages"` - // Files referenced in the SPDX document - Files []File `json:"files,omitempty"` - // Snippets referenced in the SPDX document - Snippets []Snippet `json:"snippets,omitempty"` - // Relationships referenced in the SPDX document - Relationships []Relationship `json:"relationships,omitempty"` -} diff --git a/internal/presenter/packages/model/spdx22/element.go b/internal/presenter/packages/model/spdx22/element.go deleted file mode 100644 index 65f3ae756cc..00000000000 --- a/internal/presenter/packages/model/spdx22/element.go +++ /dev/null @@ -1,12 +0,0 @@ -package spdx22 - -type Element struct { - SPDXID string `json:"SPDXID"` - // Identify name of this SpdxElement. - Name string `json:"name"` - // Relationships referenced in the SPDX document - Relationships []Relationship `json:"relationships,omitempty"` - // Provide additional information about an SpdxElement. - Annotations []Annotation `json:"annotations,omitempty"` - Comment string `json:"comment,omitempty"` -} diff --git a/internal/presenter/packages/model/spdx22/element_id.go b/internal/presenter/packages/model/spdx22/element_id.go deleted file mode 100644 index bf2f871f37a..00000000000 --- a/internal/presenter/packages/model/spdx22/element_id.go +++ /dev/null @@ -1,37 +0,0 @@ -package spdx22 - -// ElementID represents the identifier string portion of an SPDX element -// identifier. DocElementID should be used for any attributes which can -// contain identifiers defined in a different SPDX document. -// ElementIDs should NOT contain the mandatory 'SPDXRef-' portion. -type ElementID string - -func (e ElementID) String() string { - return "SPDXRef-" + string(e) -} - -// DocElementID represents an SPDX element identifier that could be defined -// in a different SPDX document, and therefore could have a "DocumentRef-" -// portion, such as Relationship and Annotations. -// ElementID is used for attributes in which a "DocumentRef-" portion cannot -// appear, such as a Package or File definition (since it is necessarily -// being defined in the present document). -// DocumentRefID will be the empty string for elements defined in the -// present document. -// DocElementIDs should NOT contain the mandatory 'DocumentRef-' or -// 'SPDXRef-' portions. -type DocElementID struct { - DocumentRefID string - ElementRefID ElementID -} - -// RenderDocElementID takes a DocElementID and returns the string equivalent, -// with the SPDXRef- prefix (and, if applicable, the DocumentRef- prefix) -// reinserted. -func (d DocElementID) String() string { - prefix := "" - if d.DocumentRefID != "" { - prefix = "DocumentRef-" + d.DocumentRefID + ":" - } - return prefix + d.ElementRefID.String() -} diff --git a/internal/presenter/packages/model/spdx22/external_document_ref.go b/internal/presenter/packages/model/spdx22/external_document_ref.go deleted file mode 100644 index 3aa830f5b01..00000000000 --- a/internal/presenter/packages/model/spdx22/external_document_ref.go +++ /dev/null @@ -1,9 +0,0 @@ -package spdx22 - -type ExternalDocumentRef struct { - // externalDocumentId is a string containing letters, numbers, ., - and/or + which uniquely identifies an external document within this document. - ExternalDocumentID string `json:"externalDocumentId"` - Checksum Checksum `json:"checksum"` - // SPDX ID for SpdxDocument. A propoerty containing an SPDX document. - SpdxDocument string `json:"spdxDocument"` -} diff --git a/internal/presenter/packages/model/spdx22/external_ref.go b/internal/presenter/packages/model/spdx22/external_ref.go deleted file mode 100644 index e34e4f64bc6..00000000000 --- a/internal/presenter/packages/model/spdx22/external_ref.go +++ /dev/null @@ -1,43 +0,0 @@ -package spdx22 - -type ReferenceCategory string - -const ( - SecurityReferenceCategory ReferenceCategory = "SECURITY" - PackageManagerReferenceCategory ReferenceCategory = "PACKAGE_MANAGER" - OtherReferenceCategory ReferenceCategory = "OTHER" -) - -// source: https://spdx.github.io/spdx-spec/appendix-VI-external-repository-identifiers/ - -type ExternalRefType string - -const ( - // see https://nvd.nist.gov/cpe - Cpe22ExternalRefType ExternalRefType = "cpe22Type" - // see https://nvd.nist.gov/cpe - Cpe23ExternalRefType ExternalRefType = "cpe23Type" - // see http://repo1.maven.org/maven2/ - MavenCentralExternalRefType ExternalRefType = "maven-central" - // see https://www.npmjs.com/ - NpmExternalRefType ExternalRefType = "npm" - // see https://www.nuget.org/ - NugetExternalRefType ExternalRefType = "nuget" - // see http://bower.io/ - BowerExternalRefType ExternalRefType = "bower" - // see https://github.com/package-url/purl-spec - PurlExternalRefType ExternalRefType = "purl" - // These point to objects present in the Software Heritage archive by the means of SoftWare Heritage persistent Identifiers (SWHID) - SwhExternalRefType ExternalRefType = "swh" -) - -type ExternalRef struct { - Comment string `json:"comment,omitempty"` - // Category for the external reference. - ReferenceCategory ReferenceCategory `json:"referenceCategory"` - // The unique string with no spaces necessary to access the package-specific information, metadata, or content - // within the target location. The format of the locator is subject to constraints defined by the . - ReferenceLocator string `json:"referenceLocator"` - // Type of the external reference. These are defined in an appendix in the SPDX specification. - ReferenceType ExternalRefType `json:"referenceType"` -} diff --git a/internal/presenter/packages/model/spdx22/file.go b/internal/presenter/packages/model/spdx22/file.go deleted file mode 100644 index eefe054721f..00000000000 --- a/internal/presenter/packages/model/spdx22/file.go +++ /dev/null @@ -1,41 +0,0 @@ -package spdx22 - -type FileType string - -const ( - DocumentationFileType FileType = "DOCUMENTATION" - ImageFileType FileType = "IMAGE" - VideoFileType FileType = "VIDEO" - ArchiveFileType FileType = "ARCHIVE" - SpdxFileType FileType = "SPDX" - ApplicationFileType FileType = "APPLICATION" - SourceFileType FileType = "SOURCE" - BinaryFileType FileType = "BINARY" - TextFileType FileType = "TEXT" - AudioFileType FileType = "AUDIO" - OtherFileType FileType = "OTHER" -) - -type File struct { - Item - // (At least one is required.) The checksum property provides a mechanism that can be used to verify that the - // contents of a File or Package have not changed. - Checksums []Checksum `json:"checksums,omitempty"` - // This field provides a place for the SPDX file creator to record file contributors. Contributors could include - // names of copyright holders and/or authors who may not be copyright holders yet contributed to the file content. - FileContributors []string `json:"fileContributors,omitempty"` - // Each element is a SPDX ID for a File. - FileDependencies []string `json:"fileDependencies,omitempty"` - // The name of the file relative to the root of the package. - FileName string `json:"fileName"` - // The type of the file - FileTypes []string `json:"fileTypes,omitempty"` - // This field provides a place for the SPDX file creator to record potential legal notices found in the file. - // This may or may not include copyright statements. - NoticeText string `json:"noticeText,omitempty"` - // Indicates the project in which the SpdxElement originated. Tools must preserve doap:homepage and doap:name - // properties and the URI (if one is known) of doap:Project resources that are values of this property. All other - // properties of doap:Projects are not directly supported by SPDX and may be dropped when translating to or - // from some SPDX formats(deprecated). - ArtifactOf []string `json:"artifactOf,omitempty"` -} diff --git a/internal/presenter/packages/model/spdx22/has_extracted_licensing_info.go b/internal/presenter/packages/model/spdx22/has_extracted_licensing_info.go deleted file mode 100644 index acf73ab4d15..00000000000 --- a/internal/presenter/packages/model/spdx22/has_extracted_licensing_info.go +++ /dev/null @@ -1,14 +0,0 @@ -package spdx22 - -type HasExtractedLicensingInfo struct { - // Verbatim license or licensing notice text that was discovered. - ExtractedText string `json:"extractedText"` - // A human readable short form license identifier for a license. The license ID is iether on the standard license - // oist or the form \"LicenseRef-\"[idString] where [idString] is a unique string containing letters, - // numbers, \".\", \"-\" or \"+\". - LicenseID string `json:"licenseId"` - Comment string `json:"comment,omitempty"` - // Identify name of this SpdxElement. - Name string `json:"name,omitempty"` - SeeAlsos []string `json:"seeAlsos,omitempty"` -} diff --git a/internal/presenter/packages/model/spdx22/item.go b/internal/presenter/packages/model/spdx22/item.go deleted file mode 100644 index ce42f2ad245..00000000000 --- a/internal/presenter/packages/model/spdx22/item.go +++ /dev/null @@ -1,22 +0,0 @@ -package spdx22 - -type Item struct { - Element - // The licenseComments property allows the preparer of the SPDX document to describe why the licensing in - // spdx:licenseConcluded was chosen. - LicenseComments string `json:"licenseComments,omitempty"` - LicenseConcluded string `json:"licenseConcluded"` - // The licensing information that was discovered directly within the package. There will be an instance of this - // property for each distinct value of alllicenseInfoInFile properties of all files contained in the package. - LicenseInfoFromFiles []string `json:"licenseInfoFromFiles,omitempty"` - // Licensing information that was discovered directly in the subject file. This is also considered a declared license for the file. - LicenseInfoInFiles []string `json:"licenseInfoInFiles,omitempty"` - // The text of copyright declarations recited in the Package or File. - CopyrightText string `json:"copyrightText,omitempty"` - // This field provides a place for the SPDX data creator to record acknowledgements that may be required to be - // communicated in some contexts. This is not meant to include the actual complete license text (see - // licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). - // The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from - // license texts, which may be necessary or desirable to reproduce. - AttributionTexts []string `json:"attributionTexts,omitempty"` -} diff --git a/internal/presenter/packages/model/spdx22/package.go b/internal/presenter/packages/model/spdx22/package.go deleted file mode 100644 index b35b83c2fd2..00000000000 --- a/internal/presenter/packages/model/spdx22/package.go +++ /dev/null @@ -1,50 +0,0 @@ -package spdx22 - -type Package struct { - Item - // The checksum property provides a mechanism that can be used to verify that the contents of a File or - // Package have not changed. - Checksums []Checksum `json:"checksums,omitempty"` - // Provides a detailed description of the package. - Description string `json:"description,omitempty"` - // The URI at which this package is available for download. Private (i.e., not publicly reachable) URIs are - // acceptable as values of this property. The values http://spdx.org/rdf/terms#none and http://spdx.org/rdf/terms#noassertion - // may be used to specify that the package is not downloadable or that no attempt was made to determine its - // download location, respectively. - DownloadLocation string `json:"downloadLocation,omitempty"` - // An External Reference allows a Package to reference an external source of additional information, metadata, - // enumerations, asset identifiers, or downloadable content believed to be relevant to the Package. - ExternalRefs []ExternalRef `json:"externalRefs,omitempty"` - // Indicates whether the file content of this package has been available for or subjected to analysis when - // creating the SPDX document. If false indicates packages that represent metadata or URI references to a - // project, product, artifact, distribution or a component. If set to false, the package must not contain any files - FilesAnalyzed bool `json:"filesAnalyzed"` - // Indicates that a particular file belongs to a package (elements are SPDX ID for a File). - HasFiles []string `json:"hasFiles,omitempty"` - // Provide a place for the SPDX file creator to record a web site that serves as the package's home page. - // This link can also be used to reference further information about the package referenced by the SPDX file creator. - Homepage string `json:"homepage,omitempty"` - // List the licenses that have been declared by the authors of the package. Any license information that does not - // originate from the package authors, e.g. license information from a third party repository, should not be included in this field. - LicenseDeclared string `json:"licenseDeclared"` - // The name and, optionally, contact information of the person or organization that originally created the package. - // Values of this property must conform to the agent and tool syntax. - Originator string `json:"originator,omitempty"` - // The base name of the package file name. For example, zlib-1.2.5.tar.gz. - PackageFileName string `json:"packageFileName,omitempty"` - // A manifest based verification code (the algorithm is defined in section 4.7 of the full specification) of the - // SPDX Item. This allows consumers of this data and/or database to determine if an SPDX item they have in hand - // is identical to the SPDX item from which the data was produced. This algorithm works even if the SPDX document - // is included in the SPDX item. - PackageVerificationCode *PackageVerificationCode `json:"packageVerificationCode,omitempty"` - // Allows the producer(s) of the SPDX document to describe how the package was acquired and/or changed from the original source. - SourceInfo string `json:"sourceInfo,omitempty"` - // Provides a short description of the package. - Summary string `json:"summary,omitempty"` - // The name and, optionally, contact information of the person or organization who was the immediate supplier - // of this package to the recipient. The supplier may be different than originator when the software has been - // repackaged. Values of this property must conform to the agent and tool syntax. - Supplier string `json:"supplier,omitempty"` - // Provides an indication of the version of the package that is described by this SpdxDocument. - VersionInfo string `json:"versionInfo,omitempty"` -} diff --git a/internal/presenter/packages/model/spdx22/package_verification_code.go b/internal/presenter/packages/model/spdx22/package_verification_code.go deleted file mode 100644 index 603fcb15820..00000000000 --- a/internal/presenter/packages/model/spdx22/package_verification_code.go +++ /dev/null @@ -1,23 +0,0 @@ -package spdx22 - -// Why are there two package identifier fields Package Checksum and Package Verification? -// Although the values of the two fields Package Checksum and Package Verification are similar, they each serve a -// different purpose. The Package Checksum provides a unique identifier of a software package which is computed by -// taking the SHA1 of the entire software package file. This enables one to quickly determine if two different copies -// of a package are the same. One disadvantage of this approach is that one cannot add an SPDX data file into the -// original package without changing the Package Checksum value. Alternatively, the Package Verification field enables -// the inclusion of an SPDX file. It enables one to quickly verify if one or more of the original package files has -// changed. The Package Verification field is a unique identifier that is based on SHAing only the original package -// files (e.g., excluding the SPDX file). This allows one to add an SPDX file to the original package without changing -// this unique identifier. -// source: https://wiki.spdx.org/view/SPDX_FAQ -type PackageVerificationCode struct { - // "A file that was excluded when calculating the package verification code. This is usually a file containing - // SPDX data regarding the package. If a package contains more than one SPDX file all SPDX files must be excluded - // from the package verification code. If this is not done it would be impossible to correctly calculate the - // verification codes in both files. - PackageVerificationCodeExcludedFiles []string `json:"packageVerificationCodeExcludedFiles"` - - // The actual package verification code as a hex encoded value. - PackageVerificationCodeValue string `json:"packageVerificationCodeValue"` -} diff --git a/internal/presenter/packages/model/spdx22/relationship.go b/internal/presenter/packages/model/spdx22/relationship.go deleted file mode 100644 index ca99a879e1b..00000000000 --- a/internal/presenter/packages/model/spdx22/relationship.go +++ /dev/null @@ -1,183 +0,0 @@ -package spdx22 - -type Relationship struct { - // Id to which the SPDX element is related - SpdxElementID string `json:"spdxElementId"` - // Describes the type of relationship between two SPDX elements. - RelationshipType RelationshipType `json:"relationshipType"` - // SPDX ID for SpdxElement. A related SpdxElement. - RelatedSpdxElement string `json:"relatedSpdxElement"` - Comment string `json:"comment,omitempty"` -} - -// source: https://spdx.github.io/spdx-spec/7-relationships-between-SPDX-elements/ -type RelationshipType string - -const ( - // DescribedByRelationship is to be used when SPDXRef-A is described by SPDXREF-Document. - // Example: The package 'WildFly' is described by SPDX document WildFly.spdx. - DescribedByRelationship RelationshipType = "DESCRIBED_BY" - - // ContainsRelationship is to be used when SPDXRef-A contains SPDXRef-B. - // Example: An ARCHIVE file bar.tgz contains a SOURCE file foo.c. - ContainsRelationship RelationshipType = "CONTAINS" - - // ContainedByRelationship is to be used when SPDXRef-A is contained by SPDXRef-B. - // Example: A SOURCE file foo.c is contained by ARCHIVE file bar.tgz - ContainedByRelationship RelationshipType = "CONTAINED_BY" - - // DependsOnRelationship is to be used when SPDXRef-A depends on SPDXRef-B. - // Example: Package A depends on the presence of package B in order to build and run - DependsOnRelationship RelationshipType = "DEPENDS_ON" - - // DependencyOfRelationship is to be used when SPDXRef-A is dependency of SPDXRef-B. - // Example: A is explicitly stated as a dependency of B in a machine-readable file. Use when a package manager does not define scopes. - DependencyOfRelationship RelationshipType = "DEPENDENCY_OF" - - // DependencyManifestOfRelationship is to be used when SPDXRef-A is a manifest file that lists a set of dependencies for SPDXRef-B. - // Example: A file package.json is the dependency manifest of a package foo. Note that only one manifest should be used to define the same dependency graph. - DependencyManifestOfRelationship RelationshipType = "DEPENDENCY_MANIFEST_OF" - - // BuildDependencyOfRelationship is to be used when SPDXRef-A is a build dependency of SPDXRef-B. - // Example: A is in the compile scope of B in a Maven project. - BuildDependencyOfRelationship RelationshipType = "BUILD_DEPENDENCY_OF" - - // DevDependencyOfRelationship is to be used when SPDXRef-A is a development dependency of SPDXRef-B. - // Example: A is in the devDependencies scope of B in a Maven project. - DevDependencyOfRelationship RelationshipType = "DEV_DEPENDENCY_OF" - - // OptionalDependencyOfRelationship is to be used when SPDXRef-A is an optional dependency of SPDXRef-B. - // Example: Use when building the code will proceed even if a dependency cannot be found, fails to install, or is only installed on a specific platform. For example, A is in the optionalDependencies scope of npm project B. - OptionalDependencyOfRelationship RelationshipType = "OPTIONAL_DEPENDENCY_OF" - - // ProvidedDependencyOfRelationship is to be used when SPDXRef-A is a to be provided dependency of SPDXRef-B. - // Example: A is in the provided scope of B in a Maven project, indicating that the project expects it to be provided, for instance, by the container or JDK. - ProvidedDependencyOfRelationship RelationshipType = "PROVIDED_DEPENDENCY_OF" - - // TestDependencyOfRelationship is to be used when SPDXRef-A is a test dependency of SPDXRef-B. - // Example: A is in the test scope of B in a Maven project. - TestDependencyOfRelationship RelationshipType = "TEST_DEPENDENCY_OF" - - // RuntimeDependencyOfRelationship is to be used when SPDXRef-A is a dependency required for the execution of SPDXRef-B. - // Example: A is in the runtime scope of B in a Maven project. - RuntimeDependencyOfRelationship RelationshipType = "RUNTIME_DEPENDENCY_OF" - - // ExampleOfRelationship is to be used when SPDXRef-A is an example of SPDXRef-B. - // Example: The file or snippet that illustrates how to use an application or library. - ExampleOfRelationship RelationshipType = "EXAMPLE_OF" - - // GeneratesRelationship is to be used when SPDXRef-A generates SPDXRef-B. - // Example: A SOURCE file makefile.mk generates a BINARY file a.out - GeneratesRelationship RelationshipType = "GENERATES" - - // GeneratedFromRelationship is to be used when SPDXRef-A was generated from SPDXRef-B. - // Example: A BINARY file a.out has been generated from a SOURCE file makefile.mk. A BINARY file foolib.a is generated from a SOURCE file bar.c. - GeneratedFromRelationship RelationshipType = "GENERATED_FROM" - - // AncestorOfRelationship is to be used when SPDXRef-A is an ancestor (same lineage but pre-dates) SPDXRef-B. - // Example: A SOURCE file makefile.mk is a version of the original ancestor SOURCE file 'makefile2.mk' - AncestorOfRelationship RelationshipType = "ANCESTOR_OF" - - // DescendantOfRelationship is to be used when SPDXRef-A is a descendant of (same lineage but postdates) SPDXRef-B. - // Example: A SOURCE file makefile2.mk is a descendant of the original SOURCE file 'makefile.mk' - DescendantOfRelationship RelationshipType = "DESCENDANT_OF" - - // VariantOfRelationship is to be used when SPDXRef-A is a variant of (same lineage but not clear which came first) SPDXRef-B. - // Example: A SOURCE file makefile2.mk is a variant of SOURCE file makefile.mk if they differ by some edit, but there is no way to tell which came first (no reliable date information). - VariantOfRelationship RelationshipType = "VARIANT_OF" - - // DistributionArtifactRelationship is to be used when distributing SPDXRef-A requires that SPDXRef-B also be distributed. - // Example: A BINARY file foo.o requires that the ARCHIVE file bar-sources.tgz be made available on distribution. - DistributionArtifactRelationship RelationshipType = "DISTRIBUTION_ARTIFACT" - - // PatchForRelationship is to be used when SPDXRef-A is a patch file for (to be applied to) SPDXRef-B. - // Example: A SOURCE file foo.diff is a patch file for SOURCE file foo.c. - PatchForRelationship RelationshipType = "PATCH_FOR" - - // PatchAppliedRelationship is to be used when SPDXRef-A is a patch file that has been applied to SPDXRef-B. - // Example: A SOURCE file foo.diff is a patch file that has been applied to SOURCE file 'foo-patched.c'. - PatchAppliedRelationship RelationshipType = "PATCH_APPLIED" - - // CopyOfRelationship is to be used when SPDXRef-A is an exact copy of SPDXRef-B. - // Example: A BINARY file alib.a is an exact copy of BINARY file a2lib.a. - CopyOfRelationship RelationshipType = "COPY_OF" - - // FileAddedRelationship is to be used when SPDXRef-A is a file that was added to SPDXRef-B. - // Example: A SOURCE file foo.c has been added to package ARCHIVE bar.tgz. - FileAddedRelationship RelationshipType = "FILE_ADDED" - - // FileDeletedRelationship is to be used when SPDXRef-A is a file that was deleted from SPDXRef-B. - // Example: A SOURCE file foo.diff has been deleted from package ARCHIVE bar.tgz. - FileDeletedRelationship RelationshipType = "FILE_DELETED" - - // FileModifiedRelationship is to be used when SPDXRef-A is a file that was modified from SPDXRef-B. - // Example: A SOURCE file foo.c has been modified from SOURCE file foo.orig.c. - FileModifiedRelationship RelationshipType = "FILE_MODIFIED" - - // ExpandedFromArchiveRelationship is to be used when SPDXRef-A is expanded from the archive SPDXRef-B. - // Example: A SOURCE file foo.c, has been expanded from the archive ARCHIVE file xyz.tgz. - ExpandedFromArchiveRelationship RelationshipType = "EXPANDED_FROM_ARCHIVE" - - // DynamicLinkRelationship is to be used when SPDXRef-A dynamically links to SPDXRef-B. - // Example: An APPLICATION file 'myapp' dynamically links to BINARY file zlib.so. - DynamicLinkRelationship RelationshipType = "DYNAMIC_LINK" - - // StaticLinkRelationship is to be used when SPDXRef-A statically links to SPDXRef-B. - // Example: An APPLICATION file 'myapp' statically links to BINARY zlib.a. - StaticLinkRelationship RelationshipType = "STATIC_LINK" - - // DataFileOfRelationship is to be used when SPDXRef-A is a data file used in SPDXRef-B. - // Example: An IMAGE file 'kitty.jpg' is a data file of an APPLICATION 'hellokitty'. - DataFileOfRelationship RelationshipType = "DATA_FILE_OF" - - // TestCaseOfRelationship is to be used when SPDXRef-A is a test case used in testing SPDXRef-B. - // Example: A SOURCE file testMyCode.java is a unit test file used to test an APPLICATION MyPackage. - TestCaseOfRelationship RelationshipType = "TEST_CASE_OF" - - // BuildToolOfRelationship is to be used when SPDXRef-A is used to build SPDXRef-B. - // Example: A SOURCE file makefile.mk is used to build an APPLICATION 'zlib'. - BuildToolOfRelationship RelationshipType = "BUILD_TOOL_OF" - - // DevToolOfRelationship is to be used when SPDXRef-A is used as a development tool for SPDXRef-B. - // Example: Any tool used for development such as a code debugger. - DevToolOfRelationship RelationshipType = "DEV_TOOL_OF" - - // TestOfRelationship is to be used when SPDXRef-A is used for testing SPDXRef-B. - // Example: Generic relationship for cases where it's clear that something is used for testing but unclear whether it's TEST_CASE_OF or TEST_TOOL_OF. - TestOfRelationship RelationshipType = "TEST_OF" - - // TestToolOfRelationship is to be used when SPDXRef-A is used as a test tool for SPDXRef-B. - // Example: Any tool used to test the code such as ESlint. - TestToolOfRelationship RelationshipType = "TEST_TOOL_OF" - - // DocumentationOfRelationship is to be used when SPDXRef-A provides documentation of SPDXRef-B. - // Example: A DOCUMENTATION file readme.txt documents the APPLICATION 'zlib'. - DocumentationOfRelationship RelationshipType = "DOCUMENTATION_OF" - - // OptionalComponentOfRelationship is to be used when SPDXRef-A is an optional component of SPDXRef-B. - // Example: A SOURCE file fool.c (which is in the contributors directory) may or may not be included in the build of APPLICATION 'atthebar'. - OptionalComponentOfRelationship RelationshipType = "OPTIONAL_COMPONENT_OF" - - // MetafileOfRelationship is to be used when SPDXRef-A is a metafile of SPDXRef-B. - // Example: A SOURCE file pom.xml is a metafile of the APPLICATION 'Apache Xerces'. - MetafileOfRelationship RelationshipType = "METAFILE_OF" - - // PackageOfRelationship is to be used when SPDXRef-A is used as a package as part of SPDXRef-B. - // Example: A Linux distribution contains an APPLICATION package gawk as part of the distribution MyLinuxDistro. - PackageOfRelationship RelationshipType = "PACKAGE_OF" - - // AmendsRelationship is to be used when (current) SPDXRef-DOCUMENT amends the SPDX information in SPDXRef-B. - // Example: (Current) SPDX document A version 2 contains a correction to a previous version of the SPDX document A version 1. Note the reserved identifier SPDXRef-DOCUMENT for the current document is required. - AmendsRelationship RelationshipType = "AMENDS" - - // PrerequisiteForRelationship is to be used when SPDXRef-A is a prerequisite for SPDXRef-B. - // Example: A library bar.dll is a prerequisite or dependency for APPLICATION foo.exe - PrerequisiteForRelationship RelationshipType = "PREREQUISITE_FOR" - - // HasPrerequisiteRelationship is to be used when SPDXRef-A has as a prerequisite SPDXRef-B. - // Example: An APPLICATION foo.exe has prerequisite or dependency on bar.dll - HasPrerequisiteRelationship RelationshipType = "HAS_PREREQUISITE" - - // OtherRelationship is to be used for a relationship which has not been defined in the formal SPDX specification. A description of the relationship should be included in the Relationship comments field. - OtherRelationship RelationshipType = "OTHER" -) diff --git a/internal/presenter/packages/model/spdx22/snippet.go b/internal/presenter/packages/model/spdx22/snippet.go deleted file mode 100644 index 5b9ae639e3a..00000000000 --- a/internal/presenter/packages/model/spdx22/snippet.go +++ /dev/null @@ -1,32 +0,0 @@ -package spdx22 - -type StartPointer struct { - Offset int `json:"offset,omitempty"` - LineNumber int `json:"lineNumber,omitempty"` - // SPDX ID for File - Reference string `json:"reference"` -} - -type EndPointer struct { - Offset int `json:"offset,omitempty"` - LineNumber int `json:"lineNumber,omitempty"` - // SPDX ID for File - Reference string `json:"reference"` -} - -type Range struct { - StartPointer StartPointer `json:"startPointer"` - EndPointer EndPointer `json:"endPointer"` -} - -type Snippet struct { - Item - // Licensing information that was discovered directly in the subject snippet. This is also considered a declared - // license for the snippet. (elements are license expressions) - LicenseInfoInSnippets []string `json:"licenseInfoInSnippets"` - // SPDX ID for File. File containing the SPDX element (e.g. the file contaning a snippet). - SnippetFromFile string `json:"snippetFromFile"` - // (At least 1 range is required). This field defines the byte range in the original host file (in X.2) that the - // snippet information applies to. - Ranges []Range `json:"ranges"` -} diff --git a/internal/presenter/packages/model/spdx22/version.go b/internal/presenter/packages/model/spdx22/version.go deleted file mode 100644 index 492d3ff1f0f..00000000000 --- a/internal/presenter/packages/model/spdx22/version.go +++ /dev/null @@ -1,3 +0,0 @@ -package spdx22 - -const Version = "SPDX-2.2" diff --git a/internal/presenter/packages/spdx_helpers.go b/internal/presenter/packages/spdx_helpers.go deleted file mode 100644 index c175e0da9ff..00000000000 --- a/internal/presenter/packages/spdx_helpers.go +++ /dev/null @@ -1,207 +0,0 @@ -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 { - 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 "" - } -} diff --git a/internal/presenter/packages/spdx_json_presenter.go b/internal/presenter/packages/spdx_json_presenter.go deleted file mode 100644 index ded9a4a65dc..00000000000 --- a/internal/presenter/packages/spdx_json_presenter.go +++ /dev/null @@ -1,142 +0,0 @@ -package packages - -import ( - "encoding/json" - "fmt" - "io" - "path" - "strings" - "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" - "github.com/google/uuid" -) - -const anchoreNamespace = "https://anchore.com/syft" - -// 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) -} - -// newSPDXJsonDocument creates and populates a new JSON document struct that follows the SPDX 2.2 spec from the given cataloging results. -func newSPDXJsonDocument(catalog *pkg.Catalog, srcMetadata source.Metadata) spdx22.Document { - uniqueID := uuid.Must(uuid.NewRandom()) - - var name, input, identifier string - switch srcMetadata.Scheme { - case source.ImageScheme: - name = cleanSPDXName(srcMetadata.ImageMetadata.UserInput) - input = "image" - case source.DirectoryScheme: - name = cleanSPDXName(srcMetadata.Path) - input = "dir" - } - - if name != "." { - identifier = path.Join(input, fmt.Sprintf("%s-%s", name, uniqueID.String())) - } else { - identifier = path.Join(input, uniqueID.String()) - } - - namespace := path.Join(anchoreNamespace, identifier) - packages, files, relationships := newSPDXJsonElements(catalog) - - 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: namespace, - Packages: packages, - Files: files, - Relationships: relationships, - } -} - -func newSPDXJsonElements(catalog *pkg.Catalog) ([]spdx22.Package, []spdx22.File, []spdx22.Relationship) { - packages := make([]spdx22.Package, 0) - relationships := make([]spdx22.Relationship, 0) - files := make([]spdx22.File, 0) - - for _, p := range catalog.Sorted() { - license := getSPDXLicense(p) - packageSpdxID := spdx22.ElementID(fmt.Sprintf("Package-%+v-%s-%s", p.Type, p.Name, p.Version)).String() - - packageFiles, fileIDs, packageFileRelationships := getSPDXFiles(packageSpdxID, p) - files = append(files, packageFiles...) - - relationships = append(relationships, packageFileRelationships...) - - // 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). - packages = append(packages, spdx22.Package{ - Description: getSPDXDescription(p), - DownloadLocation: getSPDXDownloadLocation(p), - ExternalRefs: getSPDXExternalRefs(p), - FilesAnalyzed: false, - HasFiles: fileIDs, - 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: packageSpdxID, - Name: p.Name, - }, - }, - }) - } - - return packages, files, relationships -} - -func cleanSPDXName(name string) string { - // remove # according to specification - name = strings.Replace(name, "#", "-", -1) - - // remove : for url construction - name = strings.Replace(name, ":", "-", -1) - - // clean relative pathing - return path.Clean(name) -} diff --git a/internal/presenter/packages/spdx_json_presenter_test.go b/internal/presenter/packages/spdx_json_presenter_test.go deleted file mode 100644 index 7d6a7f7381d..00000000000 --- a/internal/presenter/packages/spdx_json_presenter_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package packages - -import ( - "flag" - "regexp" - "testing" -) - -var updateSpdxJson = flag.Bool("update-spdx-json", false, "update the *.golden files for spdx-json presenters") - -func TestSPDXJSONDirectoryPresenter(t *testing.T) { - catalog, metadata, _ := presenterDirectoryInput(t) - assertPresenterAgainstGoldenSnapshot(t, - NewSPDXJSONPresenter(catalog, metadata), - *updateSpdxJson, - spdxJsonRedactor, - ) -} - -func TestSPDXJSONImagePresenter(t *testing.T) { - testImage := "image-simple" - catalog, metadata, _ := presenterImageInput(t, testImage) - assertPresenterAgainstGoldenImageSnapshot(t, - NewSPDXJSONPresenter(catalog, metadata), - testImage, - *updateSpdxJson, - spdxJsonRedactor, - ) -} - -func spdxJsonRedactor(s []byte) []byte { - // each SBOM reports the time it was generated, which is not useful during snapshot testing - s = regexp.MustCompile(`"created": .*`).ReplaceAll(s, []byte("redacted")) - - // each SBOM reports a unique documentNamespace when generated, this is not useful for snapshot testing - s = regexp.MustCompile(`"documentNamespace": .*`).ReplaceAll(s, []byte("redacted")) - - // the license list will be updated periodically, the value here should not be directly tested in snapshot tests - return regexp.MustCompile(`"licenseListVersion": .*`).ReplaceAll(s, []byte("redacted")) -} From d47428173148e5f56b279a4a96261d89c4ef5edb Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:40:27 -0700 Subject: [PATCH 09/17] migrate and split common spdx format helpers Signed-off-by: Alex Goodman --- .../formats/common/spdxhelpers/description.go | 14 ++ .../common/spdxhelpers/description_test.go | 56 +++++++ .../common/spdxhelpers/download_location.go | 22 +++ .../spdxhelpers/download_location_test.go | 54 +++++++ .../common/spdxhelpers/external_refs.go | 50 +++++++ .../common/spdxhelpers/external_refs_test.go | 46 ++++++ internal/formats/common/spdxhelpers/files.go | 47 ++++++ .../formats/common/spdxhelpers/homepage.go | 14 ++ .../common/spdxhelpers/homepage_test.go | 56 +++++++ .../formats/common/spdxhelpers/license.go | 37 +++++ .../common/spdxhelpers/license_test.go | 73 +++++++++ .../common/spdxhelpers/none_if_empty.go | 12 ++ .../common/spdxhelpers/none_if_empty_test.go | 41 +++++ .../common/spdxhelpers/originator_test.go | 114 ++++++++++++++ .../formats/common/spdxhelpers/origintor.go | 36 +++++ .../formats/common/spdxhelpers/source_info.go | 39 +++++ .../common/spdxhelpers/source_info_test.go | 141 ++++++++++++++++++ 17 files changed, 852 insertions(+) create mode 100644 internal/formats/common/spdxhelpers/description.go create mode 100644 internal/formats/common/spdxhelpers/description_test.go create mode 100644 internal/formats/common/spdxhelpers/download_location.go create mode 100644 internal/formats/common/spdxhelpers/download_location_test.go create mode 100644 internal/formats/common/spdxhelpers/external_refs.go create mode 100644 internal/formats/common/spdxhelpers/external_refs_test.go create mode 100644 internal/formats/common/spdxhelpers/files.go create mode 100644 internal/formats/common/spdxhelpers/homepage.go create mode 100644 internal/formats/common/spdxhelpers/homepage_test.go create mode 100644 internal/formats/common/spdxhelpers/license.go create mode 100644 internal/formats/common/spdxhelpers/license_test.go create mode 100644 internal/formats/common/spdxhelpers/none_if_empty.go create mode 100644 internal/formats/common/spdxhelpers/none_if_empty_test.go create mode 100644 internal/formats/common/spdxhelpers/originator_test.go create mode 100644 internal/formats/common/spdxhelpers/origintor.go create mode 100644 internal/formats/common/spdxhelpers/source_info.go create mode 100644 internal/formats/common/spdxhelpers/source_info_test.go diff --git a/internal/formats/common/spdxhelpers/description.go b/internal/formats/common/spdxhelpers/description.go new file mode 100644 index 00000000000..8b8783a26ea --- /dev/null +++ b/internal/formats/common/spdxhelpers/description.go @@ -0,0 +1,14 @@ +package spdxhelpers + +import "github.com/anchore/syft/syft/pkg" + +func Description(p *pkg.Package) string { + switch metadata := p.Metadata.(type) { + case pkg.ApkMetadata: + return metadata.Description + case pkg.NpmPackageJSONMetadata: + return metadata.Description + default: + return "" + } +} diff --git a/internal/formats/common/spdxhelpers/description_test.go b/internal/formats/common/spdxhelpers/description_test.go new file mode 100644 index 00000000000..77bc424edd1 --- /dev/null +++ b/internal/formats/common/spdxhelpers/description_test.go @@ -0,0 +1,56 @@ +package spdxhelpers + +import ( + "testing" + + "github.com/anchore/syft/syft/pkg" + "github.com/stretchr/testify/assert" +) + +func Test_Description(t *testing.T) { + tests := []struct { + name string + input pkg.Package + expected string + }{ + { + // note: since this is an optional field, no value is preferred over NONE or NOASSERTION + name: "no metadata", + input: pkg.Package{}, + expected: "", + }, + { + name: "from apk", + input: pkg.Package{ + Metadata: pkg.ApkMetadata{ + Description: "a description!", + }, + }, + expected: "a description!", + }, + { + name: "from npm", + input: pkg.Package{ + Metadata: pkg.NpmPackageJSONMetadata{ + Description: "a description!", + }, + }, + expected: "a description!", + }, + { + // note: since this is an optional field, no value is preferred over NONE or NOASSERTION + name: "empty", + input: pkg.Package{ + Metadata: pkg.NpmPackageJSONMetadata{ + Homepage: "", + }, + }, + expected: "", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, Description(&test.input)) + }) + } +} diff --git a/internal/formats/common/spdxhelpers/download_location.go b/internal/formats/common/spdxhelpers/download_location.go new file mode 100644 index 00000000000..fea6b9d908b --- /dev/null +++ b/internal/formats/common/spdxhelpers/download_location.go @@ -0,0 +1,22 @@ +package spdxhelpers + +import "github.com/anchore/syft/syft/pkg" + +func DownloadLocation(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" + } +} diff --git a/internal/formats/common/spdxhelpers/download_location_test.go b/internal/formats/common/spdxhelpers/download_location_test.go new file mode 100644 index 00000000000..3636c7c7707 --- /dev/null +++ b/internal/formats/common/spdxhelpers/download_location_test.go @@ -0,0 +1,54 @@ +package spdxhelpers + +import ( + "testing" + + "github.com/anchore/syft/syft/pkg" + "github.com/stretchr/testify/assert" +) + +func Test_DownloadLocation(t *testing.T) { + tests := []struct { + name string + input pkg.Package + expected string + }{ + { + name: "no metadata", + input: pkg.Package{}, + expected: "NOASSERTION", + }, + { + name: "from apk", + input: pkg.Package{ + Metadata: pkg.ApkMetadata{ + URL: "http://a-place.gov", + }, + }, + expected: "http://a-place.gov", + }, + { + name: "from npm", + input: pkg.Package{ + Metadata: pkg.NpmPackageJSONMetadata{ + URL: "http://a-place.gov", + }, + }, + expected: "http://a-place.gov", + }, + { + name: "empty", + input: pkg.Package{ + Metadata: pkg.NpmPackageJSONMetadata{ + URL: "", + }, + }, + expected: "NONE", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, DownloadLocation(&test.input)) + }) + } +} diff --git a/internal/formats/common/spdxhelpers/external_refs.go b/internal/formats/common/spdxhelpers/external_refs.go new file mode 100644 index 00000000000..dc2ea273514 --- /dev/null +++ b/internal/formats/common/spdxhelpers/external_refs.go @@ -0,0 +1,50 @@ +package spdxhelpers + +import ( + "github.com/anchore/syft/internal/formats/spdx22json/model" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/pkg" +) + +func ExternalRefs(p *pkg.Package) (externalRefs []model.ExternalRef) { + externalRefs = make([]model.ExternalRef, 0) + for _, c := range p.CPEs { + externalRefs = append(externalRefs, model.ExternalRef{ + ReferenceCategory: model.SecurityReferenceCategory, + ReferenceLocator: c.BindToFmtString(), + ReferenceType: model.Cpe23ExternalRefType, + }) + } + + if p.PURL != "" { + externalRefs = append(externalRefs, model.ExternalRef{ + ReferenceCategory: model.PackageManagerReferenceCategory, + ReferenceLocator: p.PURL, + ReferenceType: model.PurlExternalRefType, + }) + } + return externalRefs +} + +func ExtractPURL(refs []model.ExternalRef) string { + for _, r := range refs { + if r.ReferenceType == model.PurlExternalRefType { + return r.ReferenceLocator + } + } + return "" +} + +func ExtractCPEs(refs []model.ExternalRef) (cpes []pkg.CPE) { + for _, r := range refs { + if r.ReferenceType == model.Cpe23ExternalRefType { + cpe, err := pkg.NewCPE(r.ReferenceLocator) + if err != nil { + log.Warnf("unable to extract SPDX CPE=%q: %+v", r.ReferenceLocator, err) + continue + } + cpes = append(cpes, cpe) + } + } + return cpes +} diff --git a/internal/formats/common/spdxhelpers/external_refs_test.go b/internal/formats/common/spdxhelpers/external_refs_test.go new file mode 100644 index 00000000000..ba966311865 --- /dev/null +++ b/internal/formats/common/spdxhelpers/external_refs_test.go @@ -0,0 +1,46 @@ +package spdxhelpers + +import ( + "testing" + + "github.com/anchore/syft/internal/formats/common/testutils" + "github.com/anchore/syft/internal/formats/spdx22json/model" + "github.com/anchore/syft/syft/pkg" + "github.com/stretchr/testify/assert" +) + +func Test_ExternalRefs(t *testing.T) { + testCPE := testutils.MustCPE(pkg.NewCPE("cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*")) + tests := []struct { + name string + input pkg.Package + expected []model.ExternalRef + }{ + { + name: "cpe + purl", + input: pkg.Package{ + CPEs: []pkg.CPE{ + testCPE, + }, + PURL: "a-purl", + }, + expected: []model.ExternalRef{ + { + ReferenceCategory: model.SecurityReferenceCategory, + ReferenceLocator: testCPE.BindToFmtString(), + ReferenceType: model.Cpe23ExternalRefType, + }, + { + ReferenceCategory: model.PackageManagerReferenceCategory, + ReferenceLocator: "a-purl", + ReferenceType: model.PurlExternalRefType, + }, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.ElementsMatch(t, test.expected, ExternalRefs(&test.input)) + }) + } +} diff --git a/internal/formats/common/spdxhelpers/files.go b/internal/formats/common/spdxhelpers/files.go new file mode 100644 index 00000000000..0e05e321cda --- /dev/null +++ b/internal/formats/common/spdxhelpers/files.go @@ -0,0 +1,47 @@ +package spdxhelpers + +import ( + "crypto/sha256" + "fmt" + "path/filepath" + + "github.com/anchore/syft/internal/formats/spdx22json/model" + "github.com/anchore/syft/syft/pkg" +) + +func Files(packageSpdxID string, p *pkg.Package) (files []model.File, fileIDs []string, relationships []model.Relationship) { + files = make([]model.File, 0) + fileIDs = make([]string, 0) + relationships = make([]model.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 := model.ElementID(fmt.Sprintf("File-%s-%x", p.Name, pathHash)).String() + + fileIDs = append(fileIDs, fileSpdxID) + + files = append(files, model.File{ + FileName: ownedFilePath, + Item: model.Item{ + Element: model.Element{ + SPDXID: fileSpdxID, + Name: baseFileName, + }, + }, + }) + + relationships = append(relationships, model.Relationship{ + SpdxElementID: packageSpdxID, + RelationshipType: model.ContainsRelationship, + RelatedSpdxElement: fileSpdxID, + }) + } + + return files, fileIDs, relationships +} diff --git a/internal/formats/common/spdxhelpers/homepage.go b/internal/formats/common/spdxhelpers/homepage.go new file mode 100644 index 00000000000..8ea1ad75337 --- /dev/null +++ b/internal/formats/common/spdxhelpers/homepage.go @@ -0,0 +1,14 @@ +package spdxhelpers + +import "github.com/anchore/syft/syft/pkg" + +func Homepage(p *pkg.Package) string { + switch metadata := p.Metadata.(type) { + case pkg.GemMetadata: + return metadata.Homepage + case pkg.NpmPackageJSONMetadata: + return metadata.Homepage + default: + return "" + } +} diff --git a/internal/formats/common/spdxhelpers/homepage_test.go b/internal/formats/common/spdxhelpers/homepage_test.go new file mode 100644 index 00000000000..781873f7a26 --- /dev/null +++ b/internal/formats/common/spdxhelpers/homepage_test.go @@ -0,0 +1,56 @@ +package spdxhelpers + +import ( + "testing" + + "github.com/anchore/syft/syft/pkg" + "github.com/stretchr/testify/assert" +) + +func Test_Homepage(t *testing.T) { + tests := []struct { + name string + input pkg.Package + expected string + }{ + { + // note: since this is an optional field, no value is preferred over NONE or NOASSERTION + name: "no metadata", + input: pkg.Package{}, + expected: "", + }, + { + name: "from gem", + input: pkg.Package{ + Metadata: pkg.GemMetadata{ + Homepage: "http://a-place.gov", + }, + }, + expected: "http://a-place.gov", + }, + { + name: "from npm", + input: pkg.Package{ + Metadata: pkg.NpmPackageJSONMetadata{ + Homepage: "http://a-place.gov", + }, + }, + expected: "http://a-place.gov", + }, + { + // note: since this is an optional field, no value is preferred over NONE or NOASSERTION + name: "empty", + input: pkg.Package{ + Metadata: pkg.NpmPackageJSONMetadata{ + Homepage: "", + }, + }, + expected: "", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, Homepage(&test.input)) + }) + } +} diff --git a/internal/formats/common/spdxhelpers/license.go b/internal/formats/common/spdxhelpers/license.go new file mode 100644 index 00000000000..f2e4307ad7e --- /dev/null +++ b/internal/formats/common/spdxhelpers/license.go @@ -0,0 +1,37 @@ +package spdxhelpers + +import ( + "strings" + + "github.com/anchore/syft/internal/spdxlicense" + "github.com/anchore/syft/syft/pkg" +) + +func License(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 ") +} diff --git a/internal/formats/common/spdxhelpers/license_test.go b/internal/formats/common/spdxhelpers/license_test.go new file mode 100644 index 00000000000..c4762ee1873 --- /dev/null +++ b/internal/formats/common/spdxhelpers/license_test.go @@ -0,0 +1,73 @@ +package spdxhelpers + +import ( + "testing" + + "github.com/anchore/syft/syft/pkg" + "github.com/stretchr/testify/assert" +) + +func Test_License(t *testing.T) { + tests := []struct { + name string + input pkg.Package + expected string + }{ + { + name: "no licenses", + input: pkg.Package{}, + expected: "NONE", + }, + { + name: "no SPDX licenses", + input: pkg.Package{ + Licenses: []string{ + "made-up", + }, + }, + expected: "NOASSERTION", + }, + { + name: "with SPDX license", + input: pkg.Package{ + Licenses: []string{ + "MIT", + }, + }, + expected: "MIT", + }, + { + name: "with SPDX license expression", + input: pkg.Package{ + Licenses: []string{ + "MIT", + "GPL-3.0", + }, + }, + expected: "MIT AND GPL-3.0", + }, + { + name: "cap insensitive", + input: pkg.Package{ + Licenses: []string{ + "gpl-3.0", + }, + }, + expected: "GPL-3.0", + }, + { + name: "debian to spdx conversion", + input: pkg.Package{ + Licenses: []string{ + "GPL-2", + }, + }, + expected: "GPL-2.0", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, License(&test.input)) + }) + } +} diff --git a/internal/formats/common/spdxhelpers/none_if_empty.go b/internal/formats/common/spdxhelpers/none_if_empty.go new file mode 100644 index 00000000000..fa97a0d7e59 --- /dev/null +++ b/internal/formats/common/spdxhelpers/none_if_empty.go @@ -0,0 +1,12 @@ +package spdxhelpers + +import ( + "strings" +) + +func NoneIfEmpty(value string) string { + if strings.TrimSpace(value) == "" { + return "NONE" + } + return value +} diff --git a/internal/formats/common/spdxhelpers/none_if_empty_test.go b/internal/formats/common/spdxhelpers/none_if_empty_test.go new file mode 100644 index 00000000000..4c447f1220a --- /dev/null +++ b/internal/formats/common/spdxhelpers/none_if_empty_test.go @@ -0,0 +1,41 @@ +package spdxhelpers + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_noneIfEmpty(t *testing.T) { + tests := []struct { + name string + value string + expected string + }{ + { + name: "non-zero value", + value: "something", + expected: "something", + }, + { + name: "empty", + value: "", + expected: "NONE", + }, + { + name: "space", + value: " ", + expected: "NONE", + }, + { + name: "tab", + value: "\t", + expected: "NONE", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, NoneIfEmpty(test.value)) + }) + } +} diff --git a/internal/formats/common/spdxhelpers/originator_test.go b/internal/formats/common/spdxhelpers/originator_test.go new file mode 100644 index 00000000000..7e3ec04ed92 --- /dev/null +++ b/internal/formats/common/spdxhelpers/originator_test.go @@ -0,0 +1,114 @@ +package spdxhelpers + +import ( + "testing" + + "github.com/anchore/syft/syft/pkg" + "github.com/stretchr/testify/assert" +) + +func Test_Originator(t *testing.T) { + tests := []struct { + name string + input pkg.Package + expected string + }{ + { + // note: since this is an optional field, no value is preferred over NONE or NOASSERTION + name: "no metadata", + input: pkg.Package{}, + expected: "", + }, + { + name: "from gem", + input: pkg.Package{ + Metadata: pkg.GemMetadata{ + Authors: []string{ + "auth1", + "auth2", + }, + }, + }, + expected: "auth1", + }, + { + name: "from npm", + input: pkg.Package{ + Metadata: pkg.NpmPackageJSONMetadata{ + Author: "auth", + }, + }, + expected: "auth", + }, + { + name: "from apk", + input: pkg.Package{ + Metadata: pkg.ApkMetadata{ + Maintainer: "auth", + }, + }, + expected: "auth", + }, + { + name: "from python - just name", + input: pkg.Package{ + Metadata: pkg.PythonPackageMetadata{ + Author: "auth", + }, + }, + expected: "auth", + }, + { + name: "from python - just email", + input: pkg.Package{ + Metadata: pkg.PythonPackageMetadata{ + AuthorEmail: "auth@auth.gov", + }, + }, + expected: "auth@auth.gov", + }, + { + name: "from python - both name and email", + input: pkg.Package{ + Metadata: pkg.PythonPackageMetadata{ + Author: "auth", + AuthorEmail: "auth@auth.gov", + }, + }, + expected: "auth ", + }, + { + name: "from rpm", + input: pkg.Package{ + Metadata: pkg.RpmdbMetadata{ + Vendor: "auth", + }, + }, + expected: "auth", + }, + { + name: "from dpkg", + input: pkg.Package{ + Metadata: pkg.DpkgMetadata{ + Maintainer: "auth", + }, + }, + expected: "auth", + }, + { + // note: since this is an optional field, no value is preferred over NONE or NOASSERTION + name: "empty", + input: pkg.Package{ + Metadata: pkg.NpmPackageJSONMetadata{ + Author: "", + }, + }, + expected: "", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, Originator(&test.input)) + }) + } +} diff --git a/internal/formats/common/spdxhelpers/origintor.go b/internal/formats/common/spdxhelpers/origintor.go new file mode 100644 index 00000000000..f9ecbe2be7d --- /dev/null +++ b/internal/formats/common/spdxhelpers/origintor.go @@ -0,0 +1,36 @@ +package spdxhelpers + +import ( + "fmt" + + "github.com/anchore/syft/syft/pkg" +) + +func Originator(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 "" + } +} diff --git a/internal/formats/common/spdxhelpers/source_info.go b/internal/formats/common/spdxhelpers/source_info.go new file mode 100644 index 00000000000..7c77696f0c3 --- /dev/null +++ b/internal/formats/common/spdxhelpers/source_info.go @@ -0,0 +1,39 @@ +package spdxhelpers + +import ( + "strings" + + "github.com/anchore/syft/syft/pkg" +) + +func SourceInfo(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, ", ") +} diff --git a/internal/formats/common/spdxhelpers/source_info_test.go b/internal/formats/common/spdxhelpers/source_info_test.go new file mode 100644 index 00000000000..0faec15484c --- /dev/null +++ b/internal/formats/common/spdxhelpers/source_info_test.go @@ -0,0 +1,141 @@ +package spdxhelpers + +import ( + "testing" + + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" + "github.com/stretchr/testify/assert" +) + +func Test_SourceInfo(t *testing.T) { + tests := []struct { + name string + input pkg.Package + expected []string + }{ + { + name: "locations are captured", + input: pkg.Package{ + // note: no type given + Locations: []source.Location{ + { + RealPath: "/a-place", + VirtualPath: "/b-place", + }, + { + RealPath: "/c-place", + VirtualPath: "/d-place", + }, + }, + }, + expected: []string{ + "from the following paths", + "/a-place", + "/c-place", + }, + }, + { + // note: no specific support for this + input: pkg.Package{ + Type: pkg.KbPkg, + }, + expected: []string{ + "from the following paths", + }, + }, + { + input: pkg.Package{ + Type: pkg.RpmPkg, + }, + expected: []string{ + "from RPM DB", + }, + }, + { + input: pkg.Package{ + Type: pkg.ApkPkg, + }, + expected: []string{ + "from APK DB", + }, + }, + { + input: pkg.Package{ + Type: pkg.DebPkg, + }, + expected: []string{ + "from DPKG DB", + }, + }, + { + input: pkg.Package{ + Type: pkg.NpmPkg, + }, + expected: []string{ + "from installed node module manifest file", + }, + }, + { + input: pkg.Package{ + Type: pkg.PythonPkg, + }, + expected: []string{ + "from installed python package manifest file", + }, + }, + { + input: pkg.Package{ + Type: pkg.JavaPkg, + }, + expected: []string{ + "from installed java archive", + }, + }, + { + input: pkg.Package{ + Type: pkg.JenkinsPluginPkg, + }, + expected: []string{ + "from installed java archive", + }, + }, + { + input: pkg.Package{ + Type: pkg.GemPkg, + }, + expected: []string{ + "from installed gem metadata file", + }, + }, + { + input: pkg.Package{ + Type: pkg.GoModulePkg, + }, + expected: []string{ + "from go module information", + }, + }, + { + input: pkg.Package{ + Type: pkg.RustPkg, + }, + expected: []string{ + "from rust cargo manifest", + }, + }, + } + var pkgTypes []pkg.Type + for _, test := range tests { + t.Run(test.name+" "+string(test.input.Type), func(t *testing.T) { + if test.input.Type != "" { + pkgTypes = append(pkgTypes, test.input.Type) + } + actual := SourceInfo(&test.input) + for _, expected := range test.expected { + assert.Contains(t, actual, expected) + } + }) + } + assert.ElementsMatch(t, pkg.AllPkgs, pkgTypes, "missing one or more package types to test against (maybe a package type was added?)") +} From 4a82e4843a6a351e455f091f2208fb78d27a1c9b Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:56:16 -0700 Subject: [PATCH 10/17] add encoder tests for spdx-json and syft json Signed-off-by: Alex Goodman --- internal/formats/common/testutils/utils.go | 207 ++++++++++++++++++ internal/formats/spdx22json/encoder_test.go | 43 ++++ .../spdx22json/model/syft_package_data.go | 14 +- .../TestSPDXJSONDirectoryPresenter.golden | 77 ++++++- .../TestSPDXJSONImagePresenter.golden | 87 +++++++- internal/formats/syftjson/encoder_test.go | 29 +++ .../TestJSONDirectoryPresenter.golden | 86 ++++++++ .../snapshot/TestJSONImagePresenter.golden | 108 +++++++++ .../TestSPDXJSONDirectoryPresenter.golden | 79 ------- .../TestSPDXJSONImagePresenter.golden | 61 ------ 10 files changed, 636 insertions(+), 155 deletions(-) create mode 100644 internal/formats/common/testutils/utils.go create mode 100644 internal/formats/spdx22json/encoder_test.go create mode 100644 internal/formats/syftjson/encoder_test.go create mode 100644 internal/formats/syftjson/test-fixtures/snapshot/TestJSONDirectoryPresenter.golden create mode 100644 internal/formats/syftjson/test-fixtures/snapshot/TestJSONImagePresenter.golden delete mode 100644 internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden delete mode 100644 internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden diff --git a/internal/formats/common/testutils/utils.go b/internal/formats/common/testutils/utils.go new file mode 100644 index 00000000000..db5f2d78c62 --- /dev/null +++ b/internal/formats/common/testutils/utils.go @@ -0,0 +1,207 @@ +package testutils + +import ( + "bytes" + "testing" + + "github.com/anchore/syft/syft/presenter" + + "github.com/anchore/go-testutils" + "github.com/anchore/stereoscope/pkg/filetree" + "github.com/anchore/stereoscope/pkg/imagetest" + "github.com/anchore/syft/syft/distro" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" + "github.com/sergi/go-diff/diffmatchpatch" + "github.com/stretchr/testify/assert" +) + +type redactor func(s []byte) []byte + +func MustCPE(c pkg.CPE, e error) pkg.CPE { + if e != nil { + panic(e) + } + return c +} + +func AssertPresenterAgainstGoldenImageSnapshot(t *testing.T, pres presenter.Presenter, testImage string, updateSnapshot bool, redactors ...redactor) { + var buffer bytes.Buffer + + // grab the latest image contents and persist + if updateSnapshot { + imagetest.UpdateGoldenFixtureImage(t, testImage) + } + + err := pres.Present(&buffer) + assert.NoError(t, err) + actual := buffer.Bytes() + + // replace the expected snapshot contents with the current presenter contents + if updateSnapshot { + testutils.UpdateGoldenFileContents(t, actual) + } + + var expected = testutils.GetGoldenFileContents(t) + + // remove dynamic values, which should be tested independently + for _, r := range redactors { + actual = r(actual) + expected = r(expected) + } + + // assert that the golden file snapshot matches the actual contents + if !bytes.Equal(expected, actual) { + dmp := diffmatchpatch.New() + diffs := dmp.DiffMain(string(expected), string(actual), true) + t.Errorf("mismatched output:\n%s", dmp.DiffPrettyText(diffs)) + } +} + +func AssertPresenterAgainstGoldenSnapshot(t *testing.T, pres presenter.Presenter, updateSnapshot bool, redactors ...redactor) { + var buffer bytes.Buffer + + err := pres.Present(&buffer) + assert.NoError(t, err) + actual := buffer.Bytes() + + // replace the expected snapshot contents with the current presenter contents + if updateSnapshot { + testutils.UpdateGoldenFileContents(t, actual) + } + + var expected = testutils.GetGoldenFileContents(t) + + // remove dynamic values, which should be tested independently + for _, r := range redactors { + actual = r(actual) + expected = r(expected) + } + + if !bytes.Equal(expected, actual) { + dmp := diffmatchpatch.New() + diffs := dmp.DiffMain(string(expected), string(actual), true) + t.Errorf("mismatched output:\n%s", dmp.DiffPrettyText(diffs)) + } +} + +func ImageInput(t testing.TB, testImage string) (*pkg.Catalog, source.Metadata, *distro.Distro) { + t.Helper() + catalog := pkg.NewCatalog() + img := imagetest.GetGoldenFixtureImage(t, testImage) + + _, ref1, _ := img.SquashedTree().File("/somefile-1.txt", filetree.FollowBasenameLinks) + _, ref2, _ := img.SquashedTree().File("/somefile-2.txt", filetree.FollowBasenameLinks) + + // populate catalog with test data + catalog.Add(pkg.Package{ + ID: "package-1-id", + Name: "package-1", + Version: "1.0.1", + Locations: []source.Location{ + source.NewLocationFromImage(string(ref1.RealPath), *ref1, img), + }, + 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", + }, + PURL: "a-purl-1", + CPEs: []pkg.CPE{ + MustCPE(pkg.NewCPE("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*")), + }, + }) + catalog.Add(pkg.Package{ + ID: "package-2-id", + Name: "package-2", + Version: "2.0.1", + Locations: []source.Location{ + source.NewLocationFromImage(string(ref2.RealPath), *ref2, img), + }, + Type: pkg.DebPkg, + FoundBy: "the-cataloger-2", + MetadataType: pkg.DpkgMetadataType, + Metadata: pkg.DpkgMetadata{ + Package: "package-2", + Version: "2.0.1", + }, + PURL: "a-purl-2", + CPEs: []pkg.CPE{ + MustCPE(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")), + }, + }) + + // this is a hard coded value that is not given by the fixture helper and must be provided manually + img.Metadata.ManifestDigest = "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368" + + src, err := source.NewFromImage(img, "user-image-input") + assert.NoError(t, err) + + dist, err := distro.NewDistro(distro.Debian, "1.2.3", "like!") + assert.NoError(t, err) + + return catalog, src.Metadata, &dist +} + +func DirectoryInput(t testing.TB) (*pkg.Catalog, source.Metadata, *distro.Distro) { + catalog := pkg.NewCatalog() + + // populate catalog with test data + catalog.Add(pkg.Package{ + ID: "package-1-id", + Name: "package-1", + Version: "1.0.1", + Type: pkg.PythonPkg, + FoundBy: "the-cataloger-1", + Locations: []source.Location{ + {RealPath: "/some/path/pkg1"}, + }, + Language: pkg.Python, + MetadataType: pkg.PythonPackageMetadataType, + Licenses: []string{"MIT"}, + Metadata: pkg.PythonPackageMetadata{ + Name: "package-1", + Version: "1.0.1", + Files: []pkg.PythonFileRecord{ + { + Path: "/some/path/pkg1/depedencies/foo", + }, + }, + }, + PURL: "a-purl-2", + CPEs: []pkg.CPE{ + MustCPE(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")), + }, + }) + catalog.Add(pkg.Package{ + ID: "package-2-id", + Name: "package-2", + Version: "2.0.1", + Type: pkg.DebPkg, + FoundBy: "the-cataloger-2", + Locations: []source.Location{ + {RealPath: "/some/path/pkg1"}, + }, + MetadataType: pkg.DpkgMetadataType, + Metadata: pkg.DpkgMetadata{ + Package: "package-2", + Version: "2.0.1", + }, + PURL: "a-purl-2", + CPEs: []pkg.CPE{ + MustCPE(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")), + }, + }) + + dist, err := distro.NewDistro(distro.Debian, "1.2.3", "like!") + assert.NoError(t, err) + + src, err := source.NewFromDirectory("/some/path") + assert.NoError(t, err) + + return catalog, src.Metadata, &dist +} diff --git a/internal/formats/spdx22json/encoder_test.go b/internal/formats/spdx22json/encoder_test.go new file mode 100644 index 00000000000..53b10c91283 --- /dev/null +++ b/internal/formats/spdx22json/encoder_test.go @@ -0,0 +1,43 @@ +package spdx22json + +import ( + "flag" + "regexp" + "testing" + + "github.com/anchore/syft/internal/formats/common/testutils" + "github.com/anchore/syft/syft/format" +) + +var updateSpdxJson = flag.Bool("update-spdx-json", false, "update the *.golden files for spdx-json presenters") + +func TestSPDXJSONDirectoryPresenter(t *testing.T) { + catalog, metadata, distro := testutils.DirectoryInput(t) + testutils.AssertPresenterAgainstGoldenSnapshot(t, + format.NewPresenter(encoder, catalog, &metadata, distro), + *updateSpdxJson, + spdxJsonRedactor, + ) +} + +func TestSPDXJSONImagePresenter(t *testing.T) { + testImage := "image-simple" + catalog, metadata, distro := testutils.ImageInput(t, testImage) + testutils.AssertPresenterAgainstGoldenImageSnapshot(t, + format.NewPresenter(encoder, catalog, &metadata, distro), + testImage, + *updateSpdxJson, + spdxJsonRedactor, + ) +} + +func spdxJsonRedactor(s []byte) []byte { + // each SBOM reports the time it was generated, which is not useful during snapshot testing + s = regexp.MustCompile(`"created": .*`).ReplaceAll(s, []byte("redacted")) + + // each SBOM reports a unique documentNamespace when generated, this is not useful for snapshot testing + s = regexp.MustCompile(`"documentNamespace": .*`).ReplaceAll(s, []byte("redacted")) + + // the license list will be updated periodically, the value here should not be directly tested in snapshot tests + return regexp.MustCompile(`"licenseListVersion": .*`).ReplaceAll(s, []byte("redacted")) +} diff --git a/internal/formats/spdx22json/model/syft_package_data.go b/internal/formats/spdx22json/model/syft_package_data.go index 58efd69b15d..1b33db57545 100644 --- a/internal/formats/spdx22json/model/syft_package_data.go +++ b/internal/formats/spdx22json/model/syft_package_data.go @@ -15,16 +15,16 @@ type SyftPackageData struct { } type SyftPackageCustomData struct { - MetadataType pkg.MetadataType `json:"metadataType"` - Metadata interface{} `json:"metadata"` + MetadataType pkg.MetadataType `json:"metadataType,omitempty"` + Metadata interface{} `json:"metadata,omitempty"` } type SyftPackageBasicData struct { - PackageType pkg.Type `json:"type"` - FoundBy string `json:"foundBy"` - Locations []source.Location `json:"locations"` - Licenses []string `json:"licenses"` - Language pkg.Language `json:"language"` + PackageType pkg.Type `json:"type,omitempty"` + FoundBy string `json:"foundBy,omitempty"` + Locations []source.Location `json:"locations,omitempty"` + Licenses []string `json:"licenses,omitempty"` + Language pkg.Language `json:"language,omitempty"` } // syftPackageMetadataUnpacker is all values needed from Package to disambiguate ambiguous fields during json unmarshaling. diff --git a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden index 249517449ad..8b7ed575697 100644 --- a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden +++ b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden @@ -3,15 +3,36 @@ "name": "/some/path", "spdxVersion": "SPDX-2.2", "creationInfo": { - "created": "2021-09-16T20:44:35.198887Z", + "created": "2021-10-11T01:54:40.609143Z", "creators": [ "Organization: Anchore, Inc", "Tool: syft-[not provided]" ], "licenseListVersion": "3.14" }, + "syftSourceData": { + "Scheme": "DirectoryScheme", + "ImageMetadata": { + "userInput": "", + "imageID": "", + "manifestDigest": "", + "mediaType": "", + "tags": null, + "imageSize": 0, + "layers": null, + "manifest": null, + "config": null, + "repoDigests": null + }, + "Path": "/some/path" + }, + "syftDistroData": { + "name": "debian", + "version": "1.2.3", + "idLike": "like!" + }, "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/image/", + "documentNamespace": "https:/anchore.com/syft/dir/some/path-e94d6e43-5de5-4849-8e21-983ada9103c5", "packages": [ { "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", @@ -36,7 +57,35 @@ ], "licenseDeclared": "MIT", "sourceInfo": "acquired package info from installed python package manifest file: /some/path/pkg1", - "versionInfo": "1.0.1" + "versionInfo": "1.0.1", + "syftPackageData": { + "type": "python", + "foundBy": "the-cataloger-1", + "locations": [ + { + "path": "/some/path/pkg1" + } + ], + "licenses": [ + "MIT" + ], + "language": "python", + "metadataType": "PythonPackageMetadata", + "metadata": { + "name": "package-1", + "version": "1.0.1", + "license": "", + "author": "", + "authorEmail": "", + "platform": "", + "files": [ + { + "path": "/some/path/pkg1/depedencies/foo" + } + ], + "sitePackagesRootPath": "" + } + } }, { "SPDXID": "SPDXRef-Package-deb-package-2-2.0.1", @@ -58,7 +107,27 @@ "filesAnalyzed": false, "licenseDeclared": "NONE", "sourceInfo": "acquired package info from DPKG DB: /some/path/pkg1", - "versionInfo": "2.0.1" + "versionInfo": "2.0.1", + "syftPackageData": { + "type": "deb", + "foundBy": "the-cataloger-2", + "locations": [ + { + "path": "/some/path/pkg1" + } + ], + "metadataType": "DpkgMetadata", + "metadata": { + "package": "package-2", + "source": "", + "version": "2.0.1", + "sourceVersion": "", + "architecture": "", + "maintainer": "", + "installedSize": 0, + "files": null + } + } } ], "files": [ diff --git a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden index 8906ef161ac..cba9d5d0659 100644 --- a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden +++ b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden @@ -3,15 +3,49 @@ "name": "user-image-input", "spdxVersion": "SPDX-2.2", "creationInfo": { - "created": "2021-09-16T20:44:35.203911Z", + "created": "2021-10-11T01:54:40.61361Z", "creators": [ "Organization: Anchore, Inc", "Tool: syft-[not provided]" ], "licenseListVersion": "3.14" }, + "syftSourceData": { + "Scheme": "ImageScheme", + "ImageMetadata": { + "userInput": "user-image-input", + "imageID": "sha256:2480160b55bec40c44d3b145c7b2c1c47160db8575c3dcae086d76b9370ae7ca", + "manifestDigest": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "tags": [ + "stereoscope-fixture-image-simple:85066c51088bdd274f7a89e99e00490f666c49e72ffc955707cd6e18f0e22c5b" + ], + "imageSize": 38, + "layers": [ + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "digest": "sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59", + "size": 22 + }, + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "digest": "sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec", + "size": 16 + } + ], + "manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjo2NjcsImRpZ2VzdCI6InNoYTI1NjoyNDgwMTYwYjU1YmVjNDBjNDRkM2IxNDVjN2IyYzFjNDcxNjBkYjg1NzVjM2RjYWUwODZkNzZiOTM3MGFlN2NhIn0sImxheWVycyI6W3sibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjpmYjZiZWVjYjc1YjM5ZjRiYjgxM2RiZjE3N2U1MDFlZGQ1ZGRiM2U2OWJiNDVjZWRlYjc4YzY3NmVlMWI3YTU5In0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MjA0OCwiZGlnZXN0Ijoic2hhMjU2OjMxOWI1ODhjZTY0MjUzYTg3YjUzM2M4ZWQwMWNmMDAyNWUwZWFjOThlN2I1MTZlMTI1MzI5NTdlMTI0NGZkZWMifV19", + "config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiV29ya2luZ0RpciI6Ii8iLCJPbkJ1aWxkIjpudWxsfSwiY3JlYXRlZCI6IjIwMjEtMTAtMDRUMTE6NDA6MDAuNjM4Mzk0NVoiLCJoaXN0b3J5IjpbeyJjcmVhdGVkIjoiMjAyMS0xMC0wNFQxMTo0MDowMC41OTA3MzE2WiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0xLnR4dCAvc29tZWZpbGUtMS50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn0seyJjcmVhdGVkIjoiMjAyMS0xMC0wNFQxMTo0MDowMC42MzgzOTQ1WiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0yLnR4dCAvc29tZWZpbGUtMi50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn1dLCJvcyI6ImxpbnV4Iiwicm9vdGZzIjp7InR5cGUiOiJsYXllcnMiLCJkaWZmX2lkcyI6WyJzaGEyNTY6ZmI2YmVlY2I3NWIzOWY0YmI4MTNkYmYxNzdlNTAxZWRkNWRkYjNlNjliYjQ1Y2VkZWI3OGM2NzZlZTFiN2E1OSIsInNoYTI1NjozMTliNTg4Y2U2NDI1M2E4N2I1MzNjOGVkMDFjZjAwMjVlMGVhYzk4ZTdiNTE2ZTEyNTMyOTU3ZTEyNDRmZGVjIl19fQ==", + "repoDigests": [] + }, + "Path": "" + }, + "syftDistroData": { + "name": "debian", + "version": "1.2.3", + "idLike": "like!" + }, "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/image/user-image-input", + "documentNamespace": "https:/anchore.com/syft/image/user-image-input-9badd1fb-a067-4207-addf-243c5b7705fe", "packages": [ { "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", @@ -33,7 +67,31 @@ "filesAnalyzed": false, "licenseDeclared": "MIT", "sourceInfo": "acquired package info from installed python package manifest file: /somefile-1.txt", - "versionInfo": "1.0.1" + "versionInfo": "1.0.1", + "syftPackageData": { + "type": "python", + "foundBy": "the-cataloger-1", + "locations": [ + { + "path": "/somefile-1.txt", + "layerID": "sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59" + } + ], + "licenses": [ + "MIT" + ], + "language": "python", + "metadataType": "PythonPackageMetadata", + "metadata": { + "name": "package-1", + "version": "1.0.1", + "license": "", + "author": "", + "authorEmail": "", + "platform": "", + "sitePackagesRootPath": "" + } + } }, { "SPDXID": "SPDXRef-Package-deb-package-2-2.0.1", @@ -55,7 +113,28 @@ "filesAnalyzed": false, "licenseDeclared": "NONE", "sourceInfo": "acquired package info from DPKG DB: /somefile-2.txt", - "versionInfo": "2.0.1" + "versionInfo": "2.0.1", + "syftPackageData": { + "type": "deb", + "foundBy": "the-cataloger-2", + "locations": [ + { + "path": "/somefile-2.txt", + "layerID": "sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec" + } + ], + "metadataType": "DpkgMetadata", + "metadata": { + "package": "package-2", + "source": "", + "version": "2.0.1", + "sourceVersion": "", + "architecture": "", + "maintainer": "", + "installedSize": 0, + "files": null + } + } } ] } diff --git a/internal/formats/syftjson/encoder_test.go b/internal/formats/syftjson/encoder_test.go new file mode 100644 index 00000000000..69fda8a661d --- /dev/null +++ b/internal/formats/syftjson/encoder_test.go @@ -0,0 +1,29 @@ +package syftjson + +import ( + "flag" + "testing" + + "github.com/anchore/syft/internal/formats/common/testutils" + "github.com/anchore/syft/syft/format" +) + +var updateJson = flag.Bool("update-json", false, "update the *.golden files for json presenters") + +func TestJSONDirectoryPresenter(t *testing.T) { + catalog, metadata, distro := testutils.DirectoryInput(t) + testutils.AssertPresenterAgainstGoldenSnapshot(t, + format.NewPresenter(encoder, catalog, &metadata, distro), + *updateJson, + ) +} + +func TestJSONImagePresenter(t *testing.T) { + testImage := "image-simple" + catalog, metadata, distro := testutils.ImageInput(t, testImage) + testutils.AssertPresenterAgainstGoldenImageSnapshot(t, + format.NewPresenter(encoder, catalog, &metadata, distro), + testImage, + *updateJson, + ) +} diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestJSONDirectoryPresenter.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestJSONDirectoryPresenter.golden new file mode 100644 index 00000000000..2abdef222e4 --- /dev/null +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestJSONDirectoryPresenter.golden @@ -0,0 +1,86 @@ +{ + "artifacts": [ + { + "id": "package-1-id", + "name": "package-1", + "version": "1.0.1", + "type": "python", + "foundBy": "the-cataloger-1", + "locations": [ + { + "path": "/some/path/pkg1" + } + ], + "licenses": [ + "MIT" + ], + "language": "python", + "cpes": [ + "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*" + ], + "purl": "a-purl-2", + "metadataType": "PythonPackageMetadata", + "metadata": { + "name": "package-1", + "version": "1.0.1", + "license": "", + "author": "", + "authorEmail": "", + "platform": "", + "files": [ + { + "path": "/some/path/pkg1/depedencies/foo" + } + ], + "sitePackagesRootPath": "" + } + }, + { + "id": "package-2-id", + "name": "package-2", + "version": "2.0.1", + "type": "deb", + "foundBy": "the-cataloger-2", + "locations": [ + { + "path": "/some/path/pkg1" + } + ], + "licenses": [], + "language": "", + "cpes": [ + "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*" + ], + "purl": "a-purl-2", + "metadataType": "DpkgMetadata", + "metadata": { + "package": "package-2", + "source": "", + "version": "2.0.1", + "sourceVersion": "", + "architecture": "", + "maintainer": "", + "installedSize": 0, + "files": null + } + } + ], + "artifactRelationships": [], + "source": { + "type": "directory", + "target": "/some/path" + }, + "distro": { + "name": "debian", + "version": "1.2.3", + "idLike": "like!" + }, + "descriptor": { + "name": "syft", + "version": "[not provided]" + }, + "schema": { + "version": "1.1.0", + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-1.1.0.json" + } +} diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestJSONImagePresenter.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestJSONImagePresenter.golden new file mode 100644 index 00000000000..abcda45b522 --- /dev/null +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestJSONImagePresenter.golden @@ -0,0 +1,108 @@ +{ + "artifacts": [ + { + "id": "package-1-id", + "name": "package-1", + "version": "1.0.1", + "type": "python", + "foundBy": "the-cataloger-1", + "locations": [ + { + "path": "/somefile-1.txt", + "layerID": "sha256:ffb5e9eaa453a002110719d12c294960117ca2903953d1faa40f01dc3f77045c" + } + ], + "licenses": [ + "MIT" + ], + "language": "python", + "cpes": [ + "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*" + ], + "purl": "a-purl-1", + "metadataType": "PythonPackageMetadata", + "metadata": { + "name": "package-1", + "version": "1.0.1", + "license": "", + "author": "", + "authorEmail": "", + "platform": "", + "sitePackagesRootPath": "" + } + }, + { + "id": "package-2-id", + "name": "package-2", + "version": "2.0.1", + "type": "deb", + "foundBy": "the-cataloger-2", + "locations": [ + { + "path": "/somefile-2.txt", + "layerID": "sha256:8463854829fc53d47b9dcdf7ee79fe7eb4ca7933c910f67f8521412f7a2f5c21" + } + ], + "licenses": [], + "language": "", + "cpes": [ + "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*" + ], + "purl": "a-purl-2", + "metadataType": "DpkgMetadata", + "metadata": { + "package": "package-2", + "source": "", + "version": "2.0.1", + "sourceVersion": "", + "architecture": "", + "maintainer": "", + "installedSize": 0, + "files": null + } + } + ], + "artifactRelationships": [], + "source": { + "type": "image", + "target": { + "userInput": "user-image-input", + "imageID": "sha256:112851310e48e604f7379e2a3acddab50e91ce926edacb598a532e60ff6b776a", + "manifestDigest": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "tags": [ + "stereoscope-fixture-image-simple:85066c51088bdd274f7a89e99e00490f666c49e72ffc955707cd6e18f0e22c5b" + ], + "imageSize": 38, + "layers": [ + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "digest": "sha256:ffb5e9eaa453a002110719d12c294960117ca2903953d1faa40f01dc3f77045c", + "size": 22 + }, + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "digest": "sha256:8463854829fc53d47b9dcdf7ee79fe7eb4ca7933c910f67f8521412f7a2f5c21", + "size": 16 + } + ], + "manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjo2NzMsImRpZ2VzdCI6InNoYTI1NjoxMTI4NTEzMTBlNDhlNjA0ZjczNzllMmEzYWNkZGFiNTBlOTFjZTkyNmVkYWNiNTk4YTUzMmU2MGZmNmI3NzZhIn0sImxheWVycyI6W3sibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjpmZmI1ZTllYWE0NTNhMDAyMTEwNzE5ZDEyYzI5NDk2MDExN2NhMjkwMzk1M2QxZmFhNDBmMDFkYzNmNzcwNDVjIn0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MjA0OCwiZGlnZXN0Ijoic2hhMjU2Ojg0NjM4NTQ4MjlmYzUzZDQ3YjlkY2RmN2VlNzlmZTdlYjRjYTc5MzNjOTEwZjY3Zjg1MjE0MTJmN2EyZjVjMjEifV19", + "config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiV29ya2luZ0RpciI6Ii8iLCJPbkJ1aWxkIjpudWxsfSwiY3JlYXRlZCI6IjIwMjEtMDktMDhUMTc6MjE6NTguODk2NTI5MTkyWiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDIxLTA5LTA4VDE3OjIxOjU4Ljg3OTY5MDgyNFoiLCJjcmVhdGVkX2J5IjoiQUREIGZpbGUtMS50eHQgL3NvbWVmaWxlLTEudHh0ICMgYnVpbGRraXQiLCJjb21tZW50IjoiYnVpbGRraXQuZG9ja2VyZmlsZS52MCJ9LHsiY3JlYXRlZCI6IjIwMjEtMDktMDhUMTc6MjE6NTguODk2NTI5MTkyWiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0yLnR4dCAvc29tZWZpbGUtMi50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn1dLCJvcyI6ImxpbnV4Iiwicm9vdGZzIjp7InR5cGUiOiJsYXllcnMiLCJkaWZmX2lkcyI6WyJzaGEyNTY6ZmZiNWU5ZWFhNDUzYTAwMjExMDcxOWQxMmMyOTQ5NjAxMTdjYTI5MDM5NTNkMWZhYTQwZjAxZGMzZjc3MDQ1YyIsInNoYTI1Njo4NDYzODU0ODI5ZmM1M2Q0N2I5ZGNkZjdlZTc5ZmU3ZWI0Y2E3OTMzYzkxMGY2N2Y4NTIxNDEyZjdhMmY1YzIxIl19fQ==", + "repoDigests": [], + "scope": "Squashed" + } + }, + "distro": { + "name": "debian", + "version": "1.2.3", + "idLike": "like!" + }, + "descriptor": { + "name": "syft", + "version": "[not provided]" + }, + "schema": { + "version": "1.1.0", + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-1.1.0.json" + } +} diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden deleted file mode 100644 index 249517449ad..00000000000 --- a/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden +++ /dev/null @@ -1,79 +0,0 @@ -{ - "SPDXID": "SPDXRef-DOCUMENT", - "name": "/some/path", - "spdxVersion": "SPDX-2.2", - "creationInfo": { - "created": "2021-09-16T20:44:35.198887Z", - "creators": [ - "Organization: Anchore, Inc", - "Tool: syft-[not provided]" - ], - "licenseListVersion": "3.14" - }, - "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/image/", - "packages": [ - { - "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", - "name": "package-1", - "licenseConcluded": "MIT", - "downloadLocation": "NOASSERTION", - "externalRefs": [ - { - "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", - "referenceType": "cpe23Type" - }, - { - "referenceCategory": "PACKAGE_MANAGER", - "referenceLocator": "a-purl-2", - "referenceType": "purl" - } - ], - "filesAnalyzed": false, - "hasFiles": [ - "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9" - ], - "licenseDeclared": "MIT", - "sourceInfo": "acquired package info from installed python package manifest file: /some/path/pkg1", - "versionInfo": "1.0.1" - }, - { - "SPDXID": "SPDXRef-Package-deb-package-2-2.0.1", - "name": "package-2", - "licenseConcluded": "NONE", - "downloadLocation": "NOASSERTION", - "externalRefs": [ - { - "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", - "referenceType": "cpe23Type" - }, - { - "referenceCategory": "PACKAGE_MANAGER", - "referenceLocator": "a-purl-2", - "referenceType": "purl" - } - ], - "filesAnalyzed": false, - "licenseDeclared": "NONE", - "sourceInfo": "acquired package info from DPKG DB: /some/path/pkg1", - "versionInfo": "2.0.1" - } - ], - "files": [ - { - "SPDXID": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9", - "name": "foo", - "licenseConcluded": "", - "fileName": "/some/path/pkg1/depedencies/foo" - } - ], - "relationships": [ - { - "spdxElementId": "SPDXRef-Package-python-package-1-1.0.1", - "relationshipType": "CONTAINS", - "relatedSpdxElement": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9" - } - ] -} diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden deleted file mode 100644 index 8906ef161ac..00000000000 --- a/internal/formats/syftjson/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden +++ /dev/null @@ -1,61 +0,0 @@ -{ - "SPDXID": "SPDXRef-DOCUMENT", - "name": "user-image-input", - "spdxVersion": "SPDX-2.2", - "creationInfo": { - "created": "2021-09-16T20:44:35.203911Z", - "creators": [ - "Organization: Anchore, Inc", - "Tool: syft-[not provided]" - ], - "licenseListVersion": "3.14" - }, - "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/image/user-image-input", - "packages": [ - { - "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", - "name": "package-1", - "licenseConcluded": "MIT", - "downloadLocation": "NOASSERTION", - "externalRefs": [ - { - "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*", - "referenceType": "cpe23Type" - }, - { - "referenceCategory": "PACKAGE_MANAGER", - "referenceLocator": "a-purl-1", - "referenceType": "purl" - } - ], - "filesAnalyzed": false, - "licenseDeclared": "MIT", - "sourceInfo": "acquired package info from installed python package manifest file: /somefile-1.txt", - "versionInfo": "1.0.1" - }, - { - "SPDXID": "SPDXRef-Package-deb-package-2-2.0.1", - "name": "package-2", - "licenseConcluded": "NONE", - "downloadLocation": "NOASSERTION", - "externalRefs": [ - { - "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", - "referenceType": "cpe23Type" - }, - { - "referenceCategory": "PACKAGE_MANAGER", - "referenceLocator": "a-purl-2", - "referenceType": "purl" - } - ], - "filesAnalyzed": false, - "licenseDeclared": "NONE", - "sourceInfo": "acquired package info from DPKG DB: /somefile-2.txt", - "versionInfo": "2.0.1" - } - ] -} From c00afc7fa949d023000370134eb0bc238b7e2d66 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:56:43 -0700 Subject: [PATCH 11/17] add formats helper test fixtures Signed-off-by: Alex Goodman --- .../test-fixtures/alpine-syft-spdx.json | 5059 +++++++++++++++++ .../formats/test-fixtures/alpine-syft.json | 1846 ++++++ 2 files changed, 6905 insertions(+) create mode 100644 internal/formats/test-fixtures/alpine-syft-spdx.json create mode 100644 internal/formats/test-fixtures/alpine-syft.json diff --git a/internal/formats/test-fixtures/alpine-syft-spdx.json b/internal/formats/test-fixtures/alpine-syft-spdx.json new file mode 100644 index 00000000000..60e703cd86f --- /dev/null +++ b/internal/formats/test-fixtures/alpine-syft-spdx.json @@ -0,0 +1,5059 @@ +{ + "SPDXID": "SPDXRef-DOCUMENT", + "name": "alpine-latest", + "spdxVersion": "SPDX-2.2", + "creationInfo": { + "created": "2021-10-11T01:10:39.898684Z", + "creators": [ + "Organization: Anchore, Inc", + "Tool: syft-[not provided]" + ], + "licenseListVersion": "3.14" + }, + "syftSourceData": { + "Scheme": "ImageScheme", + "ImageMetadata": { + "userInput": "alpine:latest", + "imageID": "sha256:14119a10abf4669e8cdbdff324a9f9605d99697215a0d21c360fe8dfa8471bab", + "manifestDigest": "sha256:69704ef328d05a9f806b6b8502915e6a0a4faa4d72018dc42343f511490daf8a", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "tags": [], + "imageSize": 5590942, + "layers": [ + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "digest": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68", + "size": 5590942 + } + ], + "manifest": "ewogICAic2NoZW1hVmVyc2lvbiI6IDIsCiAgICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRvY2tlci5kaXN0cmlidXRpb24ubWFuaWZlc3QudjIranNvbiIsCiAgICJjb25maWciOiB7CiAgICAgICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRvY2tlci5jb250YWluZXIuaW1hZ2UudjEranNvbiIsCiAgICAgICJzaXplIjogMTQ3MSwKICAgICAgImRpZ2VzdCI6ICJzaGEyNTY6MTQxMTlhMTBhYmY0NjY5ZThjZGJkZmYzMjRhOWY5NjA1ZDk5Njk3MjE1YTBkMjFjMzYwZmU4ZGZhODQ3MWJhYiIKICAgfSwKICAgImxheWVycyI6IFsKICAgICAgewogICAgICAgICAibWVkaWFUeXBlIjogImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLAogICAgICAgICAic2l6ZSI6IDI4MTQ0NDYsCiAgICAgICAgICJkaWdlc3QiOiAic2hhMjU2OmEwZDBhMGQ0NmY4YjUyNDczOTgyYTNjNDY2MzE4ZjQ3OTc2NzU3NzU1MWE1M2ZmYzkwNzRjOWZhNzAzNTk4MmUiCiAgICAgIH0KICAgXQp9", + "config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJIb3N0bmFtZSI6IiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpbIi9iaW4vc2giXSwiSW1hZ2UiOiJzaGEyNTY6ZDNlMGI2MjU4ZWMyZjcyNWMxOTY2OGYxMWFlNTMyM2MzYjAyNDVlMTk3ZWM0Nzg0MjRlYzZhODc5MzU2OTBlYiIsIlZvbHVtZXMiOm51bGwsIldvcmtpbmdEaXIiOiIiLCJFbnRyeXBvaW50IjpudWxsLCJPbkJ1aWxkIjpudWxsLCJMYWJlbHMiOm51bGx9LCJjb250YWluZXIiOiIzMzAyODljNjQ5ZGI4NmY1ZmIxYWU1YmZlZjE4NTAxMDEyYjU1MGFkYjA2MzhiOTE5M2Q0YTNhNGI2NWEyZjliIiwiY29udGFpbmVyX2NvbmZpZyI6eyJIb3N0bmFtZSI6IjMzMDI4OWM2NDlkYiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpbIi9iaW4vc2giLCItYyIsIiMobm9wKSAiLCJDTUQgW1wiL2Jpbi9zaFwiXSJdLCJJbWFnZSI6InNoYTI1NjpkM2UwYjYyNThlYzJmNzI1YzE5NjY4ZjExYWU1MzIzYzNiMDI0NWUxOTdlYzQ3ODQyNGVjNmE4NzkzNTY5MGViIiwiVm9sdW1lcyI6bnVsbCwiV29ya2luZ0RpciI6IiIsIkVudHJ5cG9pbnQiOm51bGwsIk9uQnVpbGQiOm51bGwsIkxhYmVscyI6e319LCJjcmVhdGVkIjoiMjAyMS0wOC0yN1QxNzoxOTo0NS43NTg2MTE1MjNaIiwiZG9ja2VyX3ZlcnNpb24iOiIyMC4xMC43IiwiaGlzdG9yeSI6W3siY3JlYXRlZCI6IjIwMjEtMDgtMjdUMTc6MTk6NDUuNTUzMDkyMzYzWiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jICMobm9wKSBBREQgZmlsZTphYWQ0MjkwZDI3NTgwY2MxYTA5NGZmYWY5OGMzY2EyZmM1ZDY5OWZlNjk1ZGZiOGU2ZTlmYWMyMGYxMTI5NDUwIGluIC8gIn0seyJjcmVhdGVkIjoiMjAyMS0wOC0yN1QxNzoxOTo0NS43NTg2MTE1MjNaIiwiY3JlYXRlZF9ieSI6Ii9iaW4vc2ggLWMgIyhub3ApICBDTUQgW1wiL2Jpbi9zaFwiXSIsImVtcHR5X2xheWVyIjp0cnVlfV0sIm9zIjoibGludXgiLCJyb290ZnMiOnsidHlwZSI6ImxheWVycyIsImRpZmZfaWRzIjpbInNoYTI1NjplMmViMDZkOGFmODIxOGNmZWM4MjEwMTQ3MzU3YTY4YjdlMTNmN2M0ODViOTkxYzI4OGMyZDAxZGMyMjhiYjY4Il19fQ==", + "repoDigests": [ + "index.docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a" + ] + }, + "Path": "" + }, + "syftDistroData": { + "name": "alpine", + "version": "3.14.2", + "idLike": "" + }, + "dataLicense": "CC0-1.0", + "documentNamespace": "https:/anchore.com/syft/image/alpine-latest-3d3e29a8-1b32-4a8b-83f1-e0dadadb2851", + "packages": [ + { + "SPDXID": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "name": "alpine-baselayout", + "licenseConcluded": "GPL-2.0-only", + "description": "Alpine base dir structure and init scripts", + "downloadLocation": "https://git.alpinelinux.org/cgit/aports/tree/main/alpine-baselayout", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine_baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine_baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/alpine-baselayout@3.2.0-r16?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-alpine-baselayout-938b99e3330802a9290b64452b1b303a7efa94dd8f5fc86b6c941cf0644ce220", + "SPDXRef-File-alpine-baselayout-fa713d04af6279efba07299265ea838d01677e1c24dabf3a50ae355b2aec78c4", + "SPDXRef-File-alpine-baselayout-0850a74c4deea14a0b23ba1ba46c970bddd720b268a72cdf7f2dec4215ffcc88", + "SPDXRef-File-alpine-baselayout-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "SPDXRef-File-alpine-baselayout-87c4547311a1d5b80f46214960e323acf8fb7a533c6e74d7b98fab4fcf750949", + "SPDXRef-File-alpine-baselayout-ad87237a59f1d0e1b380dee393ccb396e853c9593702ea6c514d7b741a98e222", + "SPDXRef-File-alpine-baselayout-5240593a13ae1d67ac532cec0a648571ab373c64a6d970c7ebd26ada1aef4731", + "SPDXRef-File-alpine-baselayout-0c63107ca91d223780ca2bf9ff28f4ad1aee951dc0861a731385c67124c87095", + "SPDXRef-File-alpine-baselayout-cf54dfacf32eec1c86e0406e395f1251d4e359a523cf6ea7f5e68d45cf692b59", + "SPDXRef-File-alpine-baselayout-ed448de483a77a745f150b021c026ae468a0d3374c0b5fe4cb40b94e9b5e4ca5", + "SPDXRef-File-alpine-baselayout-7b7e873d82462e4ede4cfa5ce873291b077ec45277cf9bd3d2750179c8397475", + "SPDXRef-File-alpine-baselayout-4a666ea3a3b04a24f574974df10592d51bd191614ee41b02d09f6d13c0c2f52a", + "SPDXRef-File-alpine-baselayout-c55a296bf4896c08e82f6c8dd17e4bbd2454dceffaf498a8669683b3345055dc", + "SPDXRef-File-alpine-baselayout-96c68e4af671cd64c58948f11f9d1e36cd2c1c3c70c2bf2576d261a429d7d088", + "SPDXRef-File-alpine-baselayout-5fe2a603a207a0be32f23c83597684317308df475d5f502263265feec7112b9c", + "SPDXRef-File-alpine-baselayout-7bab811be3ba6d8226afa29755291a86c01584ae520a5da1852b17bcd0ee9ee6", + "SPDXRef-File-alpine-baselayout-7a594e2d43b74c5df07778b24879e71858d79fe7921b2229dbd29d2e39f0fee7", + "SPDXRef-File-alpine-baselayout-adb462163022f3c4b134df078362eb91c3df2b74d181d330e64a4d228e342ee0", + "SPDXRef-File-alpine-baselayout-87d9dd3c2e7d25d92e9ef89551e068f46640f02f94251a7643b6c4cda22e047c", + "SPDXRef-File-alpine-baselayout-0c6df1408e5a475087f6cdfb71f67cb53a6cf67207ba2d6cfe3a82b73a809e32", + "SPDXRef-File-alpine-baselayout-1cfbc5a57d10970e212f768e066e5365709375db3faf4e5ab3e0a28b712efbfc", + "SPDXRef-File-alpine-baselayout-a5017c23a9f6ed2d1b4e08408fedf24e39aab24bacd1d1597c1432e80497614b", + "SPDXRef-File-alpine-baselayout-646d2b8cd720c24ee781a443805d178d859cdac40a21b73b75f2a3178dc8bf82", + "SPDXRef-File-alpine-baselayout-3cb4ecfa96c3717bf40df048eb527ae369def49fd83f58883951116e1fa1670a", + "SPDXRef-File-alpine-baselayout-164f2d1bdb81aec3400edda6615ea6006559786396f358d2128101fdde23e79e", + "SPDXRef-File-alpine-baselayout-f5067a79d8e5ded77c953ca3af252eca521f8c03c9fec20c85c42cab427f98d8", + "SPDXRef-File-alpine-baselayout-03e028932ed7076cd6db28b85a5700ca88bd0ae00410f61429ed3925ffee2e4a", + "SPDXRef-File-alpine-baselayout-8755c6b849aa8fb7e20c7b5172abcfe0c2c19e897f0ad2ef7ebab9e8acecc307", + "SPDXRef-File-alpine-baselayout-1c9fc3f14a82b56f4065a167c41510738e453de442b83161a13c86ffd812a4a1", + "SPDXRef-File-alpine-baselayout-74acf31844532670be412c65b8251ee55d072549080b1cffdbea6b1a192230a0", + "SPDXRef-File-alpine-baselayout-f6431e60b7311a5b22e920dbf75ca12019da3db364b557e8c71655b492fdc7ca", + "SPDXRef-File-alpine-baselayout-bc6c9197ed374198c8829fa6f41c47b81b09379e4f7e5b17441f602ddff1dd60", + "SPDXRef-File-alpine-baselayout-b35ee3dd7805325c05e5c24f0aff6715bce46b5df6f13be16406a7d74665fd94", + "SPDXRef-File-alpine-baselayout-9ec401f0bfd3ee5ac23dd036d3d73cc1fa85deacf8efbf8f5faaf6952d9b711a", + "SPDXRef-File-alpine-baselayout-5bd7409d3a6e5558758391624191bfb7bd293408a8cf0874d04c70b3d77cc961", + "SPDXRef-File-alpine-baselayout-270a90055881581dd978776bc42c89194d5a38ddf3bf7196f9cdb30fac606196", + "SPDXRef-File-alpine-baselayout-421918ef7d7b0bfab6fec5e5111c5fd490c94e9d72e6575a5b1d9a7b94746483", + "SPDXRef-File-alpine-baselayout-25ec93c60dd059453797da12f697089684f9a16cb5ce47a5cd3ec1dc0b3c78ea", + "SPDXRef-File-alpine-baselayout-ee224e9d960e60ffee86d25ddb811378f657fe9c0c7241b3957031c81e09fa9d", + "SPDXRef-File-alpine-baselayout-d939b13506024f3afa5ce5b1bc91a82269c689173ac4ce4fff8b50915c516527", + "SPDXRef-File-alpine-baselayout-acffca3302affa520554207b61b05b0e6574ff0df5d52f1a0f417326d7981e8b", + "SPDXRef-File-alpine-baselayout-85fc9f0c9441a4e56af19c77267ed688b3716982d62faf88df797483299fbcbf", + "SPDXRef-File-alpine-baselayout-35c691835ff71f7c4e09fbca9e18a41fd926109c981ece63249e54eea6da3175", + "SPDXRef-File-alpine-baselayout-7b5ddf499844cf05866927513cf62fee9af8c281812def040b964146b0ea87d6", + "SPDXRef-File-alpine-baselayout-bf4911c4172a7de2e23458b30cea8ee81763eedd5f640d04de6341a61b7965d9", + "SPDXRef-File-alpine-baselayout-4645c3ce010ad9d6a98566235a0f8d1d13b6e41215efcd5db4c61adf3aacb274", + "SPDXRef-File-alpine-baselayout-9bf64c539a30b158186b5317f7e672b5491c435676e4ca5b3f1329fa860544b3", + "SPDXRef-File-alpine-baselayout-2cc974af6afc822c42a4e914df05c697348b80420941f6b27561b2bf688587b7", + "SPDXRef-File-alpine-baselayout-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "SPDXRef-File-alpine-baselayout-62fe5b620acf2330b7803289d102c09ec1d19f1b42def629be88fec0d6b76911", + "SPDXRef-File-alpine-baselayout-d8c416b3e20d54c8c21a5ab64f02a4507a674336f5fd8e9fed933cc78bec68a2", + "SPDXRef-File-alpine-baselayout-66a88450899099626d6882b37b4fcd93082df152658108d62c6d871f3058c948", + "SPDXRef-File-alpine-baselayout-7d87b2622e3b5da184511fc3b569785b116e3d06cf2a0369913ae767eafc0ced", + "SPDXRef-File-alpine-baselayout-e3dc3458bcfe5ffc3905d1a59a310190d16eb61a4a8262b256dc1618e3e8475a", + "SPDXRef-File-alpine-baselayout-67f049743ef3707f138cd3aad15858fe185a01278c7681c35468403deafa29f8", + "SPDXRef-File-alpine-baselayout-9a7019b3ec26c4992312cbf0ad51f5679549c9af382ef8f979e139383f3fcbd7", + "SPDXRef-File-alpine-baselayout-5d135c43adc1d1967a0cd473c659dffdaa33f7b61a85249bba675c329e8cf447", + "SPDXRef-File-alpine-baselayout-4b28a584089adbef86ab91e83be7c091a9a635a67276bc26e4f5a8f1f084d9f7", + "SPDXRef-File-alpine-baselayout-fdeace0c97c37e435605c4867be6a665446a517252e505ab6a2b1207e75ae9a7", + "SPDXRef-File-alpine-baselayout-cbcdfaeb37659981a3e96b9ec2000c67c9fa42b452cb26c41db886fca95f6ed0", + "SPDXRef-File-alpine-baselayout-71ad1dfa1de556decbd6d7314196552e349d66067b49ab6bf8d4865faa663441", + "SPDXRef-File-alpine-baselayout-94a6b447580330f9f2b609422537b04239ff3a39df9137e32efd559f1a2935cb", + "SPDXRef-File-alpine-baselayout-b3d46fe883f343fe8d86cceea5141710f5cf97ab3b21a0d813982e1155d4c717", + "SPDXRef-File-alpine-baselayout-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73", + "SPDXRef-File-alpine-baselayout-7b6a323b0f7a6639345fb765860984dee6d6a9c8407f43342503c257f2065ed4", + "SPDXRef-File-alpine-baselayout-a3d9ac4fdee9c2424e2fe95742f45f7d5134426aee734e778201f5db161741cc", + "SPDXRef-File-alpine-baselayout-0bb7b4e45ea451fc58b3444bace01ea87ad00efe015a186bf5bc90a2e830f32e", + "SPDXRef-File-alpine-baselayout-e9671acd244849c57167c658fa2f969752048f7ab184a3dcf5c46cb4d56ae124", + "SPDXRef-File-alpine-baselayout-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "SPDXRef-File-alpine-baselayout-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8", + "SPDXRef-File-alpine-baselayout-274cc9c977b9825b211b0434883f37ec82c06258ba8e250767fdf467f95d3556", + "SPDXRef-File-alpine-baselayout-0885fcf5b23ee3ef7768fa611f596cc2d3209368cacceaf245fc80c3c6ff0b58", + "SPDXRef-File-alpine-baselayout-f696103f605ed61cc94a21b71ae3105f01f65f01a9f116d1cc60617d44205729", + "SPDXRef-File-alpine-baselayout-4553160a715f677baf2c0a2454c1e5e2b9598226e765a3c3fbe58bee7b25ad9e", + "SPDXRef-File-alpine-baselayout-1e3238fb9e3778665629ddf1407c26c21e28646996c76433805701ad85c8ac74", + "SPDXRef-File-alpine-baselayout-829eb242159232e7d47951730a06f83f7be1c901fa7f990c33e8b7c1c8173b79", + "SPDXRef-File-alpine-baselayout-10b2079988256c145bab6b179d480509efb438bf10d508150b59cc3ffc009ab3", + "SPDXRef-File-alpine-baselayout-9821d8ddb1dbec3b2a76c1a968d45701421459b9bf7752af24bfca1a0670bf15", + "SPDXRef-File-alpine-baselayout-de0cf4b047c1eda28543bcf2a9a248eb742e7ddee5259d639e5fe7e24def31b5", + "SPDXRef-File-alpine-baselayout-c309689ef6f2432e55b81fdb6e139e2857ba1aba16ea4270daa3f5ab68181cd3", + "SPDXRef-File-alpine-baselayout-b79f7b1a48aea6d3205a9a3ae1dd44f4f5a60c3b243c672230d25b46c527ef40", + "SPDXRef-File-alpine-baselayout-57bc3277a6135981afff45d68e8740aaa312055223095d2211808b09a7965fba", + "SPDXRef-File-alpine-baselayout-218bcd8d738d0f2d1444fb7b9300a6aca9403cde242852c7f442f7aa4f607482", + "SPDXRef-File-alpine-baselayout-018076f20178b3bf76d8270b980ca52fcb8d4d20b397e43df5db5d59874fbf58", + "SPDXRef-File-alpine-baselayout-9542f47d115504311f26c800a9bbb31c9f3532e2e8d3b5d25fd34ec425234596", + "SPDXRef-File-alpine-baselayout-7eb6299ed20af1ba33f42fc43e7e73f1093977631c7536766eca19006e763642", + "SPDXRef-File-alpine-baselayout-03760b268e887197c8a9215d4daed2db64b368b2b5816ad1bba715bea307026b", + "SPDXRef-File-alpine-baselayout-a459ad271310c24e7041dce53331250633351d6e2df7e26b2b0842bdd5fa8e29", + "SPDXRef-File-alpine-baselayout-9a6a409e26d4fd90b43d526e1d61dcfbc287a72f952784d9d26331d6aaf25624", + "SPDXRef-File-alpine-baselayout-d65d76739220351968989bb4b05a589049beb21135b5a5ad21d0fb447da39889", + "SPDXRef-File-alpine-baselayout-c1dc6ea3b918faed81b4f6111f0e00277a26474a45a0c65d6a7b15ebcfc0550d", + "SPDXRef-File-alpine-baselayout-10bf2897b33acd74002e5ed9fcf668e393fcabd332a94cc32b6c329df1da155a", + "SPDXRef-File-alpine-baselayout-01f1d631e7df830b9536b561faf66e65058dba8732ba5be875e06479c91fe429", + "SPDXRef-File-alpine-baselayout-1d776d20b63c81a21618a8318dd70a6a1d2f0c433229a1fd6ceb69a2f1ef7b6c", + "SPDXRef-File-alpine-baselayout-7c33841e2b572a90b23bdafc3ca2bd76c2b93a009ca068206678b1fa2462ab4f", + "SPDXRef-File-alpine-baselayout-fcbb68056f8a06f14a56e6a778b9808b49036ea2b05fcb0ae83b99090d1d5ae9", + "SPDXRef-File-alpine-baselayout-7ad74bcab7b847385cac1c0dd039265c3a63fd744ee6f77c62cd016a706c8c3a" + ], + "licenseDeclared": "GPL-2.0-only", + "originator": "Natanael Copa ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "3.2.0-r16", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "GPL-2.0-only" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "alpine-baselayout", + "originPackage": "alpine-baselayout", + "maintainer": "Natanael Copa ", + "version": "3.2.0-r16", + "license": "GPL-2.0-only", + "architecture": "x86_64", + "url": "https://git.alpinelinux.org/cgit/aports/tree/main/alpine-baselayout", + "description": "Alpine base dir structure and init scripts", + "size": 20716, + "installedSize": 413696, + "pullDependencies": "/bin/sh so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1UJtB9cNV4r+/VbxySkEei++qbho=", + "gitCommitOfApkPort": "8a8c96a0ea2fcd824c361aa4438763fa33ee8ca0", + "files": [ + { + "path": "/dev" + }, + { + "path": "/dev/pts" + }, + { + "path": "/dev/shm" + }, + { + "path": "/etc" + }, + { + "path": "/etc/fstab", + "digest": { + "algorithm": "sha1", + "value": "Q11Q7hNe8QpDS531guqCdrXBzoA/o=" + } + }, + { + "path": "/etc/group", + "digest": { + "algorithm": "sha1", + "value": "Q13K+olJg5ayzHSVNUkggZJXuB+9Y=" + } + }, + { + "path": "/etc/hostname", + "digest": { + "algorithm": "sha1", + "value": "Q16nVwYVXP/tChvUPdukVD2ifXOmc=" + } + }, + { + "path": "/etc/hosts", + "digest": { + "algorithm": "sha1", + "value": "Q1BD6zJKZTRWyqGnPi4tSfd3krsMU=" + } + }, + { + "path": "/etc/inittab", + "digest": { + "algorithm": "sha1", + "value": "Q1TsthbhW7QzWRe1E/NKwTOuD4pHc=" + } + }, + { + "path": "/etc/modules", + "digest": { + "algorithm": "sha1", + "value": "Q1toogjUipHGcMgECgPJX64SwUT1M=" + } + }, + { + "path": "/etc/motd", + "digest": { + "algorithm": "sha1", + "value": "Q1XmduVVNURHQ27TvYp1Lr5TMtFcA=" + } + }, + { + "path": "/etc/mtab", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1kiljhXXH1LlQroHsEJIkPZg2eiw=" + } + }, + { + "path": "/etc/passwd", + "digest": { + "algorithm": "sha1", + "value": "Q1TchuuLUfur0izvfZQZxgN/LJhB8=" + } + }, + { + "path": "/etc/profile", + "digest": { + "algorithm": "sha1", + "value": "Q1VmHPWPjjvz4oCsbmYCUB4uWpSkc=" + } + }, + { + "path": "/etc/protocols", + "digest": { + "algorithm": "sha1", + "value": "Q1omKlp3vgGq2ZqYzyD/KHNdo8rDc=" + } + }, + { + "path": "/etc/services", + "digest": { + "algorithm": "sha1", + "value": "Q19WLCv5ItKg4MH7RWfNRh1I7byQc=" + } + }, + { + "path": "/etc/shadow", + "ownerUid": "0", + "ownerGid": "42", + "permissions": "640", + "digest": { + "algorithm": "sha1", + "value": "Q1ltrPIAW2zHeDiajsex2Bdmq3uqA=" + } + }, + { + "path": "/etc/shells", + "digest": { + "algorithm": "sha1", + "value": "Q1ojm2YdpCJ6B/apGDaZ/Sdb2xJkA=" + } + }, + { + "path": "/etc/sysctl.conf", + "digest": { + "algorithm": "sha1", + "value": "Q14upz3tfnNxZkIEsUhWn7Xoiw96g=" + } + }, + { + "path": "/etc/apk" + }, + { + "path": "/etc/conf.d" + }, + { + "path": "/etc/crontabs" + }, + { + "path": "/etc/crontabs/root", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "600", + "digest": { + "algorithm": "sha1", + "value": "Q1vfk1apUWI4yLJGhhNRd0kJixfvY=" + } + }, + { + "path": "/etc/init.d" + }, + { + "path": "/etc/modprobe.d" + }, + { + "path": "/etc/modprobe.d/aliases.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1WUbh6TBYNVK7e4Y+uUvLs/7viqk=" + } + }, + { + "path": "/etc/modprobe.d/blacklist.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1xxYGU6S6TLQvb7ervPrWWwAWqMg=" + } + }, + { + "path": "/etc/modprobe.d/i386.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1pnay/njn6ol9cCssL7KiZZ8etlc=" + } + }, + { + "path": "/etc/modprobe.d/kms.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1ynbLn3GYDpvajba/ldp1niayeog=" + } + }, + { + "path": "/etc/modules-load.d" + }, + { + "path": "/etc/network" + }, + { + "path": "/etc/network/if-down.d" + }, + { + "path": "/etc/network/if-post-down.d" + }, + { + "path": "/etc/network/if-pre-up.d" + }, + { + "path": "/etc/network/if-up.d" + }, + { + "path": "/etc/opt" + }, + { + "path": "/etc/periodic" + }, + { + "path": "/etc/periodic/15min" + }, + { + "path": "/etc/periodic/daily" + }, + { + "path": "/etc/periodic/hourly" + }, + { + "path": "/etc/periodic/monthly" + }, + { + "path": "/etc/periodic/weekly" + }, + { + "path": "/etc/profile.d" + }, + { + "path": "/etc/profile.d/README", + "digest": { + "algorithm": "sha1", + "value": "Q135OWsCzzvnB2fmFx62kbqm1Ax1k=" + } + }, + { + "path": "/etc/profile.d/color_prompt.sh.disabled", + "digest": { + "algorithm": "sha1", + "value": "Q10wL23GuSCVfumMRgakabUI6EsSk=" + } + }, + { + "path": "/etc/profile.d/locale.sh", + "digest": { + "algorithm": "sha1", + "value": "Q1S8j+WW71mWxfVy8ythqU7HUVoBw=" + } + }, + { + "path": "/etc/sysctl.d" + }, + { + "path": "/home" + }, + { + "path": "/lib" + }, + { + "path": "/lib/firmware" + }, + { + "path": "/lib/mdev" + }, + { + "path": "/lib/modules-load.d" + }, + { + "path": "/lib/sysctl.d" + }, + { + "path": "/lib/sysctl.d/00-alpine.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1HpElzW1xEgmKfERtTy7oommnq6c=" + } + }, + { + "path": "/media" + }, + { + "path": "/media/cdrom" + }, + { + "path": "/media/floppy" + }, + { + "path": "/media/usb" + }, + { + "path": "/mnt" + }, + { + "path": "/opt" + }, + { + "path": "/proc" + }, + { + "path": "/root", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "700" + }, + { + "path": "/run" + }, + { + "path": "/sbin" + }, + { + "path": "/sbin/mkmntdirs", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1VcFI6coRl6HWWVShMW+G5Sb3JH8=" + } + }, + { + "path": "/srv" + }, + { + "path": "/sys" + }, + { + "path": "/tmp", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "1777" + }, + { + "path": "/usr" + }, + { + "path": "/usr/lib" + }, + { + "path": "/usr/lib/modules-load.d" + }, + { + "path": "/usr/local" + }, + { + "path": "/usr/local/bin" + }, + { + "path": "/usr/local/lib" + }, + { + "path": "/usr/local/share" + }, + { + "path": "/usr/sbin" + }, + { + "path": "/usr/share" + }, + { + "path": "/usr/share/man" + }, + { + "path": "/usr/share/misc" + }, + { + "path": "/var" + }, + { + "path": "/var/run", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q11/SNZz/8cK2dSKK+cJpVrZIuF4Q=" + } + }, + { + "path": "/var/cache" + }, + { + "path": "/var/cache/misc" + }, + { + "path": "/var/empty", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "555" + }, + { + "path": "/var/lib" + }, + { + "path": "/var/lib/misc" + }, + { + "path": "/var/local" + }, + { + "path": "/var/lock" + }, + { + "path": "/var/lock/subsys" + }, + { + "path": "/var/log" + }, + { + "path": "/var/mail" + }, + { + "path": "/var/opt" + }, + { + "path": "/var/spool" + }, + { + "path": "/var/spool/mail", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1dzbdazYZA2nTzSIG3YyNw7d4Juc=" + } + }, + { + "path": "/var/spool/cron" + }, + { + "path": "/var/spool/cron/crontabs", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1OFZt+ZMp7j0Gny0rqSKuWJyqYmA=" + } + }, + { + "path": "/var/tmp", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "1777" + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "name": "alpine-keys", + "licenseConcluded": "MIT", + "description": "Public keys for Alpine Linux packages", + "downloadLocation": "https://alpinelinux.org", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine:alpine-keys:2.3-r1:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/alpine-keys@2.3-r1?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-alpine-keys-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "SPDXRef-File-alpine-keys-87c4547311a1d5b80f46214960e323acf8fb7a533c6e74d7b98fab4fcf750949", + "SPDXRef-File-alpine-keys-3f4157f9078d158b7e396177d85c8fb53f29a76545f2d340eb3adf4a9e7a1885", + "SPDXRef-File-alpine-keys-8e7ef118b5fed742d8afa54480a3fb0f6eab7955ea112c816bdbde328d4e640c", + "SPDXRef-File-alpine-keys-3ce1c6dd80b327840547860ef1034cb0f7adccdc95d3f561c99f1c1b55362cfe", + "SPDXRef-File-alpine-keys-2f9df767164cd310915bb577b7b3c995d50d5ffef92461cc00950925775ac895", + "SPDXRef-File-alpine-keys-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "SPDXRef-File-alpine-keys-10b2079988256c145bab6b179d480509efb438bf10d508150b59cc3ffc009ab3", + "SPDXRef-File-alpine-keys-349a3439300fcd4715a93a5c325b66ef844c31ac555093144c3581c1911b92e0", + "SPDXRef-File-alpine-keys-31bc62f17e79698b7d3602d622ccb3564a28a6d72501c336ed65ba22ba56c1f3", + "SPDXRef-File-alpine-keys-70424b52d02f5c066fe7ef302f8c429ff2baa8a2046952e8b3845c75847ab4fd", + "SPDXRef-File-alpine-keys-e64a4e2eb91dfce2784b56f812d260a693f2b4df747673684c2ed555b61f5946", + "SPDXRef-File-alpine-keys-68b6c908c50d7de9101b4eb6e878b6f1286a6656670eafa23d9412bd5f0c25c6", + "SPDXRef-File-alpine-keys-746532709f9a9c47d2ea7255b81ec12d78285495b42c3ae0bbc9d8d2a1934087", + "SPDXRef-File-alpine-keys-cf76eec6f2c4542d8e2cc5728a401c6ca16a431be13552a5bd1d688a217a7620", + "SPDXRef-File-alpine-keys-fc9d085ce2c164b5b2c75b14a81d07d34ca3728adb2b1f1add59e7462b5c86d1", + "SPDXRef-File-alpine-keys-f7a61b828205cc47efa2b5dfe729cd3cec1369df9606183471bff3f997f3020b", + "SPDXRef-File-alpine-keys-c4509f751c2d6a794c17af44174d5d94006c9f796046ccacf78e6a1562f464d2", + "SPDXRef-File-alpine-keys-70f3fad60f7becec73a9a1cc1d4c26cff30809cec5ea241ae10716367f64dff2", + "SPDXRef-File-alpine-keys-cfc0930eafccf8732e92f44e4d226bd64746e0f59f1055e7731b65b582cee5ba", + "SPDXRef-File-alpine-keys-f762ad8d2fa621c55664ae10aa50f8da6b7200b31ba70605ebbb2d0f9ed9f272", + "SPDXRef-File-alpine-keys-1e5fd156158d1cdcf396afbca2881729e56248a0a90c978686ff0e42408a9a72", + "SPDXRef-File-alpine-keys-9cbcfdfb36800327d9f5a09ddcfb9d3c516bda7370b014c8379e61076e020f2d", + "SPDXRef-File-alpine-keys-0e37de6688a294aa4369a2429af2bc7a03fcb4c5a553c87455a81a46099eab7e", + "SPDXRef-File-alpine-keys-f80ec3be3474099a63b3dd3da566965dbfee4dd6f820733f9d4d1571f652b505", + "SPDXRef-File-alpine-keys-8891b28cfb822f4d4fc6c3d16e9d5c6be93860304e39e927ad33fa59ec273412", + "SPDXRef-File-alpine-keys-dd58af88dc076558fac411437289d9e8fdd2d5b9203a16506351202701886ab8", + "SPDXRef-File-alpine-keys-0125cfa9decc9d138026e19d82b0d825123aa6498c813d39f0a0c0276e501a95", + "SPDXRef-File-alpine-keys-05f9458494ebe3f01d7c668f14b9bc94386d771c3408834a2ff4d6d8199fb0d8", + "SPDXRef-File-alpine-keys-490e2dbd984f1fe3e33b065b33a1189ba7d77024e3fc6817eb4dec00f6b6bb3b", + "SPDXRef-File-alpine-keys-89e9bb3c796f4d3e70d534458f372f61607049d1a28ccb0e6bd0ab6ce9e278b5", + "SPDXRef-File-alpine-keys-faa9eee3d033096e147baf97cd7f5300545ece5d833a9fee95e41bda631e4965", + "SPDXRef-File-alpine-keys-ef16eb46ee4c77f8f5431cf5d5f69299cd96145ac4fd34308946781d3793bd7c", + "SPDXRef-File-alpine-keys-6f54d5945a1770fd582051241b606e273e62d10ee546ed27512a312dd12553da", + "SPDXRef-File-alpine-keys-871a4ad07e1d31a29b10e6129393236395b148d199c52350aa8ec4652543b522", + "SPDXRef-File-alpine-keys-6347ab100d9ed7da25ae4a85d3af5e696c0b879a967833641d19446bd9bd0a2a", + "SPDXRef-File-alpine-keys-09ecbceb074898be958e9a7ac482230d3ada42dc3db94792c829d0a8dcc9ed83", + "SPDXRef-File-alpine-keys-9f5fdaf7c7a37ab72c777463690eeed9daf9cbff710a0b1d2ac146fc94df4c9b", + "SPDXRef-File-alpine-keys-efa8032a4839ecc3a9a121576cd74cd088ba82ea4e57bb4121e607cd0b8ed936" + ], + "licenseDeclared": "MIT", + "originator": "Natanael Copa ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "2.3-r1", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "MIT" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "alpine-keys", + "originPackage": "alpine-keys", + "maintainer": "Natanael Copa ", + "version": "2.3-r1", + "license": "MIT", + "architecture": "x86_64", + "url": "https://alpinelinux.org", + "description": "Public keys for Alpine Linux packages", + "size": 5988, + "installedSize": 118784, + "pullDependencies": "", + "pullChecksum": "Q1ZV5wTtRXerQz0CBrwtKcvErpPeY=", + "gitCommitOfApkPort": "0972396a79fd723a429e518120fdf7ab48407468", + "files": [ + { + "path": "/etc" + }, + { + "path": "/etc/apk" + }, + { + "path": "/etc/apk/keys" + }, + { + "path": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1OvCFSO94z97c80mIDCxqGkh2Og4=" + } + }, + { + "path": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1v7YWZYzAWoclaLDI45jEguI7YN0=" + } + }, + { + "path": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1NnGuDsdQOx4ZNYfB3N97eLyGPkI=" + } + }, + { + "path": "/usr" + }, + { + "path": "/usr/share" + }, + { + "path": "/usr/share/apk" + }, + { + "path": "/usr/share/apk/keys" + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1OvCFSO94z97c80mIDCxqGkh2Og4=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1v7YWZYzAWoclaLDI45jEguI7YN0=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1BTqS+H/UUyhQuzHwiBl47+BTKuU=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1NnGuDsdQOx4ZNYfB3N97eLyGPkI=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1Oaxdcsa6AYoPdLi0U4lO3J2we18=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1yPq+su65ksNox3uXB+DR7P18+QU=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1MpZDNX0LeLHvSOwVUyXiXx11NN0=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1glCQ/eJbvA5xqcswdjFrWv5Fnk0=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1XUdDEoNTtjlvrS+iunk6ziFgIpU=" + } + }, + { + "path": "/usr/share/apk/keys/aarch64" + }, + { + "path": "/usr/share/apk/keys/aarch64/alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q17j9nWJkQ+wfIuVQzIFrmFZ7fSOc=" + } + }, + { + "path": "/usr/share/apk/keys/armhf" + }, + { + "path": "/usr/share/apk/keys/armhf/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1U9QtsdN+rYZ9Zh76EfXy00JZHMg=" + } + }, + { + "path": "/usr/share/apk/keys/armv7" + }, + { + "path": "/usr/share/apk/keys/armv7/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1U9QtsdN+rYZ9Zh76EfXy00JZHMg=" + } + }, + { + "path": "/usr/share/apk/keys/mips64" + }, + { + "path": "/usr/share/apk/keys/mips64/alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1hCZdFx+LvzbLtPs753je78gEEBQ=" + } + }, + { + "path": "/usr/share/apk/keys/ppc64le" + }, + { + "path": "/usr/share/apk/keys/ppc64le/alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1t21dhCLbTJmAHXSCeOMq/2vfSgo=" + } + }, + { + "path": "/usr/share/apk/keys/riscv64" + }, + { + "path": "/usr/share/apk/keys/riscv64/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1NVPbZavaXpsItFwQYDWbpor7yYE=" + } + }, + { + "path": "/usr/share/apk/keys/s390x" + }, + { + "path": "/usr/share/apk/keys/s390x/alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1sjbV2r2w0Ih2vwdzC4Jq6UI7cMQ=" + } + }, + { + "path": "/usr/share/apk/keys/x86" + }, + { + "path": "/usr/share/apk/keys/x86/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1Ii51i7Nrc4uft14HhqugaUqdH64=" + } + }, + { + "path": "/usr/share/apk/keys/x86/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1Y49eVxhpvftbQ3yAdvlLfcrPLTU=" + } + }, + { + "path": "/usr/share/apk/keys/x86_64" + }, + { + "path": "/usr/share/apk/keys/x86_64/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1Ii51i7Nrc4uft14HhqugaUqdH64=" + } + }, + { + "path": "/usr/share/apk/keys/x86_64/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1AUFY+fwSBTcrYetjT7NHvafrSQc=" + } + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "name": "apk-tools", + "licenseConcluded": "GPL-2.0-only", + "description": "Alpine Package Keeper - package manager for alpine", + "downloadLocation": "https://gitlab.alpinelinux.org/alpine/apk-tools", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:apk-tools:apk-tools:2.12.7-r0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:apk-tools:apk_tools:2.12.7-r0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:apk_tools:apk-tools:2.12.7-r0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:apk_tools:apk_tools:2.12.7-r0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:apk:apk-tools:2.12.7-r0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:apk:apk_tools:2.12.7-r0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/apk-tools@2.12.7-r0?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-apk-tools-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "SPDXRef-File-apk-tools-87c4547311a1d5b80f46214960e323acf8fb7a533c6e74d7b98fab4fcf750949", + "SPDXRef-File-apk-tools-3f4157f9078d158b7e396177d85c8fb53f29a76545f2d340eb3adf4a9e7a1885", + "SPDXRef-File-apk-tools-bb9c6bc3fb34848a938fd0f2a7ef7ebb8c713a31a87c66fd12b5ce6264bd3ab4", + "SPDXRef-File-apk-tools-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "SPDXRef-File-apk-tools-2bf2700ffc065ab6321946f53d462f79fed08a36e9f96721282cb7e0b0d798a4", + "SPDXRef-File-apk-tools-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73", + "SPDXRef-File-apk-tools-896ed65f3b54897b064db7577043fb6a62eae8c02e5a57e51fb7ef352d5b616a", + "SPDXRef-File-apk-tools-c309689ef6f2432e55b81fdb6e139e2857ba1aba16ea4270daa3f5ab68181cd3", + "SPDXRef-File-apk-tools-b79f7b1a48aea6d3205a9a3ae1dd44f4f5a60c3b243c672230d25b46c527ef40", + "SPDXRef-File-apk-tools-57bc3277a6135981afff45d68e8740aaa312055223095d2211808b09a7965fba", + "SPDXRef-File-apk-tools-018076f20178b3bf76d8270b980ca52fcb8d4d20b397e43df5db5d59874fbf58", + "SPDXRef-File-apk-tools-a321a876b1cd473d1d97451f2820363efc7ab8ee27a81dff25fe6657d797677c" + ], + "licenseDeclared": "GPL-2.0-only", + "originator": "Natanael Copa ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "2.12.7-r0", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "GPL-2.0-only" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "apk-tools", + "originPackage": "apk-tools", + "maintainer": "Natanael Copa ", + "version": "2.12.7-r0", + "license": "GPL-2.0-only", + "architecture": "x86_64", + "url": "https://gitlab.alpinelinux.org/alpine/apk-tools", + "description": "Alpine Package Keeper - package manager for alpine", + "size": 119979, + "installedSize": 311296, + "pullDependencies": "musl>=1.2 so:libc.musl-x86_64.so.1 so:libcrypto.so.1.1 so:libssl.so.1.1 so:libz.so.1", + "pullChecksum": "Q1VnSoy5XasRtvFODOZ9P0pZG4Hxs=", + "gitCommitOfApkPort": "03c6b1b0ec20f417cee0f3c1d56795b27871b1c5", + "files": [ + { + "path": "/etc" + }, + { + "path": "/etc/apk" + }, + { + "path": "/etc/apk/keys" + }, + { + "path": "/etc/apk/protected_paths.d" + }, + { + "path": "/lib" + }, + { + "path": "/lib/libapk.so.3.12.0", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1fg+B1BJHpxBSS5dRPU+3zeeuFI4=" + } + }, + { + "path": "/sbin" + }, + { + "path": "/sbin/apk", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1LugZocafK9LifJwfELs3VqdEIxw=" + } + }, + { + "path": "/var" + }, + { + "path": "/var/cache" + }, + { + "path": "/var/cache/misc" + }, + { + "path": "/var/lib" + }, + { + "path": "/var/lib/apk" + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "name": "busybox", + "licenseConcluded": "GPL-2.0-only", + "description": "Size optimized toolbox of many common UNIX utilities", + "downloadLocation": "https://busybox.net/", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:busybox:busybox:1.33.1-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/busybox@1.33.1-r3?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-busybox-808dd192d3243666b6f1ad4f9bfeca4877ee059456c40851a93937331b26014c", + "SPDXRef-File-busybox-720be4f35da16d0da39268d0059b7e8334a1010c212ec8f1175540669a40f61f", + "SPDXRef-File-busybox-77bafa9e3a8a092afc4f1dd84e6e1cc58b68f42eb934bf0f6b73deb2518f78a3", + "SPDXRef-File-busybox-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "SPDXRef-File-busybox-7534754c804f9d940a7292f91accecd4c8db85ae63115ebf2ac11a0ca5605de2", + "SPDXRef-File-busybox-1295836f682f19d49120419ca2e00407bcae6b1637415cf0c7ee6a6864b8020d", + "SPDXRef-File-busybox-3cb4ecfa96c3717bf40df048eb527ae369def49fd83f58883951116e1fa1670a", + "SPDXRef-File-busybox-164f2d1bdb81aec3400edda6615ea6006559786396f358d2128101fdde23e79e", + "SPDXRef-File-busybox-f5067a79d8e5ded77c953ca3af252eca521f8c03c9fec20c85c42cab427f98d8", + "SPDXRef-File-busybox-3d5a22b80f0bdb989db1b36ca2e5b6025cf4c3e297ff2798a5c05a2c254eb19e", + "SPDXRef-File-busybox-14e352a2ba6dbb578d0c1f896a954208ee7dbf4614bde867f93103b95545e54f", + "SPDXRef-File-busybox-03e028932ed7076cd6db28b85a5700ca88bd0ae00410f61429ed3925ffee2e4a", + "SPDXRef-File-busybox-8755c6b849aa8fb7e20c7b5172abcfe0c2c19e897f0ad2ef7ebab9e8acecc307", + "SPDXRef-File-busybox-50b7b0a21325d57043679d2206e62c26ec02b73128a9a0dffc53e52885d039c2", + "SPDXRef-File-busybox-586c7ec4b9fbcf6ea0c92dee4ec8b71575ed9529d0c0213684297010e81d7da3", + "SPDXRef-File-busybox-d057a0120ff2ab94243ad477a65ae645ab92259a1cacd1b0cbf78d76346ccd12", + "SPDXRef-File-busybox-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73", + "SPDXRef-File-busybox-e9671acd244849c57167c658fa2f969752048f7ab184a3dcf5c46cb4d56ae124", + "SPDXRef-File-busybox-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "SPDXRef-File-busybox-829eb242159232e7d47951730a06f83f7be1c901fa7f990c33e8b7c1c8173b79", + "SPDXRef-File-busybox-10b2079988256c145bab6b179d480509efb438bf10d508150b59cc3ffc009ab3", + "SPDXRef-File-busybox-4cf116134c8172c74ce330c5923f36b95f95a8823fe5824d17a8e10f7990d372", + "SPDXRef-File-busybox-80c6e9799c5a801c8c18ac72900403b677899f126d0f681bc6cfb5b29813cda2", + "SPDXRef-File-busybox-c309689ef6f2432e55b81fdb6e139e2857ba1aba16ea4270daa3f5ab68181cd3", + "SPDXRef-File-busybox-b79f7b1a48aea6d3205a9a3ae1dd44f4f5a60c3b243c672230d25b46c527ef40", + "SPDXRef-File-busybox-57bc3277a6135981afff45d68e8740aaa312055223095d2211808b09a7965fba", + "SPDXRef-File-busybox-018076f20178b3bf76d8270b980ca52fcb8d4d20b397e43df5db5d59874fbf58", + "SPDXRef-File-busybox-0c20a49b2af2956d6540baa5865787a8dd9947410aab18eaa80098ff75a6757b" + ], + "licenseDeclared": "GPL-2.0-only", + "originator": "Natanael Copa ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "1.33.1-r3", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "GPL-2.0-only" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "busybox", + "originPackage": "busybox", + "maintainer": "Natanael Copa ", + "version": "1.33.1-r3", + "license": "GPL-2.0-only", + "architecture": "x86_64", + "url": "https://busybox.net/", + "description": "Size optimized toolbox of many common UNIX utilities", + "size": 499368, + "installedSize": 950272, + "pullDependencies": "so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1rGvmeXEbASEg01DqEqMbxV0fts4=", + "gitCommitOfApkPort": "98710256acf90e670e79f32f1f0350b830979d24", + "files": [ + { + "path": "/bin" + }, + { + "path": "/bin/busybox", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q135CE+2ocG61L7La8CI3kfLURucU=" + } + }, + { + "path": "/bin/sh", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1pcfTfDNEbNKQc2s1tia7da05M8Q=" + } + }, + { + "path": "/etc" + }, + { + "path": "/etc/securetty", + "digest": { + "algorithm": "sha1", + "value": "Q1mB95Hq2NUTZ599RDiSsj9w5FrOU=" + } + }, + { + "path": "/etc/udhcpd.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1UAiPZcDIW1ClRzobfggcCQ77V28=" + } + }, + { + "path": "/etc/logrotate.d" + }, + { + "path": "/etc/logrotate.d/acpid", + "digest": { + "algorithm": "sha1", + "value": "Q1TylyCINVmnS+A/Tead4vZhE7Bks=" + } + }, + { + "path": "/etc/network" + }, + { + "path": "/etc/network/if-down.d" + }, + { + "path": "/etc/network/if-post-down.d" + }, + { + "path": "/etc/network/if-post-up.d" + }, + { + "path": "/etc/network/if-pre-down.d" + }, + { + "path": "/etc/network/if-pre-up.d" + }, + { + "path": "/etc/network/if-up.d" + }, + { + "path": "/etc/network/if-up.d/dad", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "775", + "digest": { + "algorithm": "sha1", + "value": "Q1ORf+lPRKuYgdkBBcKoevR1t60Q4=" + } + }, + { + "path": "/sbin" + }, + { + "path": "/tmp", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "1777" + }, + { + "path": "/usr" + }, + { + "path": "/usr/sbin" + }, + { + "path": "/usr/share" + }, + { + "path": "/usr/share/udhcpc" + }, + { + "path": "/usr/share/udhcpc/default.script", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1t9vir/ZrX3nbSIYT9BDLWZenkVQ=" + } + }, + { + "path": "/var" + }, + { + "path": "/var/cache" + }, + { + "path": "/var/cache/misc" + }, + { + "path": "/var/lib" + }, + { + "path": "/var/lib/udhcpd" + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-ca-certificates-bundle-20191127-r5", + "name": "ca-certificates-bundle", + "licenseConcluded": "MPL-2.0 AND MIT", + "description": "Pre generated bundle of Mozilla certificates", + "downloadLocation": "https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ca-certificates-bundle:ca-certificates-bundle:20191127-r5:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ca-certificates-bundle:ca_certificates_bundle:20191127-r5:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ca_certificates_bundle:ca-certificates-bundle:20191127-r5:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ca_certificates_bundle:ca_certificates_bundle:20191127-r5:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ca-certificates:ca-certificates-bundle:20191127-r5:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ca-certificates:ca_certificates_bundle:20191127-r5:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ca_certificates:ca-certificates-bundle:20191127-r5:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ca_certificates:ca_certificates_bundle:20191127-r5:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ca:ca-certificates-bundle:20191127-r5:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ca:ca_certificates_bundle:20191127-r5:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/ca-certificates-bundle@20191127-r5?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-ca-certificates-bundle-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "SPDXRef-File-ca-certificates-bundle-8b6554cf4168c3e562d168c8a781a831294b6cc9872eb7165b234b334fc80ff1", + "SPDXRef-File-ca-certificates-bundle-a9abc3ef3bbbabdce6468df2ab5ed25caab150df4beefd65c246fdf6b15a7677", + "SPDXRef-File-ca-certificates-bundle-bd8ae46e651cb3986dd212d98d6b746022a56c6d62f441adefd1898265c30f6e", + "SPDXRef-File-ca-certificates-bundle-b583d63728636e5fa4b2ec89e062e655992406c08430f1b44b12e33fc357b80e" + ], + "licenseDeclared": "MPL-2.0 AND MIT", + "originator": "Natanael Copa ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "20191127-r5", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "MPL-2.0", + "AND", + "MIT" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "ca-certificates-bundle", + "originPackage": "ca-certificates", + "maintainer": "Natanael Copa ", + "version": "20191127-r5", + "license": "MPL-2.0 AND MIT", + "architecture": "x86_64", + "url": "https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/", + "description": "Pre generated bundle of Mozilla certificates", + "size": 124473, + "installedSize": 233472, + "pullDependencies": "", + "pullChecksum": "Q1bQ4InxwFIUUNl11tjOwqrqAeAIA=", + "gitCommitOfApkPort": "51999ab9304ec11c68c4ea9e99350ac7570e7f21", + "files": [ + { + "path": "/etc" + }, + { + "path": "/etc/ssl" + }, + { + "path": "/etc/ssl/cert.pem", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1Nj6gTBdkZpTFW/obJGdpfvK0StA=" + } + }, + { + "path": "/etc/ssl/certs" + }, + { + "path": "/etc/ssl/certs/ca-certificates.crt", + "digest": { + "algorithm": "sha1", + "value": "Q1yxhc/Gjt/YEWliIZBXQz/RBrszU=" + } + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-libc-utils-0.7.2-r3", + "name": "libc-utils", + "licenseConcluded": "BSD-2-Clause AND BSD-3-Clause", + "description": "Meta package to pull in correct libc", + "downloadLocation": "https://alpinelinux.org", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:libc-utils:libc-utils:0.7.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:libc-utils:libc_utils:0.7.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:libc_utils:libc-utils:0.7.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:libc_utils:libc_utils:0.7.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:libc:libc-utils:0.7.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:libc:libc_utils:0.7.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/libc-utils@0.7.2-r3?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseDeclared": "BSD-2-Clause AND BSD-3-Clause", + "originator": "Natanael Copa ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "0.7.2-r3", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "BSD-2-Clause", + "AND", + "BSD-3-Clause" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "libc-utils", + "originPackage": "libc-dev", + "maintainer": "Natanael Copa ", + "version": "0.7.2-r3", + "license": "BSD-2-Clause AND BSD-3-Clause", + "architecture": "x86_64", + "url": "https://alpinelinux.org", + "description": "Meta package to pull in correct libc", + "size": 1228, + "installedSize": 4096, + "pullDependencies": "musl-utils", + "pullChecksum": "Q1UsLZaz0/Go44hd4Vw49UCt40Vp8=", + "gitCommitOfApkPort": "60424133be2e79bbfeff3d58147a22886f817ce2", + "files": [] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "name": "libcrypto1.1", + "licenseConcluded": "OpenSSL", + "description": "Crypto library from openssl", + "downloadLocation": "https://www.openssl.org/", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:libcrypto1.1:libcrypto1.1:1.1.1l-r0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/libcrypto1.1@1.1.1l-r0?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-libcrypto1.1-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "SPDXRef-File-libcrypto1.1-8b6554cf4168c3e562d168c8a781a831294b6cc9872eb7165b234b334fc80ff1", + "SPDXRef-File-libcrypto1.1-bd8ae46e651cb3986dd212d98d6b746022a56c6d62f441adefd1898265c30f6e", + "SPDXRef-File-libcrypto1.1-1b5d1aceec5c5574bdb154f02ba90f0065943419ec0c9637ea673a7b72ba8ae8", + "SPDXRef-File-libcrypto1.1-bf105812bacf051dd9c91886610bd0f59139c04f5051964c57c880ce66a1dc20", + "SPDXRef-File-libcrypto1.1-b04e1932acec52946ff06d74ea56dcb848c449688d9d2a87c27277c0143edb35", + "SPDXRef-File-libcrypto1.1-bc5cfefdcd1dc36b26b32bb31673f11c97559b78280bde82b89f6c5baed66cfd", + "SPDXRef-File-libcrypto1.1-86ba9a02fbedfecd54600b4498844eb8b61fb6679c33b9dd1d6a8c585622bfe8", + "SPDXRef-File-libcrypto1.1-86e61f466a55cfb1c7807c66cf9d6aef8eeb4345b47ae30e81c30e809763baaa", + "SPDXRef-File-libcrypto1.1-d0a581b15648f37d1e89a70c47bca5a4ffc9bd533c3c5f747326e19496fe23bb", + "SPDXRef-File-libcrypto1.1-6f4eba22515a1cc75dc8022b7327f3cd9cd6ce9ef89dda2712d3db9be3c3c6b2", + "SPDXRef-File-libcrypto1.1-9d348aef994196518b59ced347de2b81b3df16f83f384d7a17fd642513a0996e", + "SPDXRef-File-libcrypto1.1-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "SPDXRef-File-libcrypto1.1-01f1138a2d006757fb5698dd8e786f9b8cfe5326ca9855ed0b7df858571af416", + "SPDXRef-File-libcrypto1.1-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "SPDXRef-File-libcrypto1.1-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8", + "SPDXRef-File-libcrypto1.1-d434b4074bf223c1efb9e41014702b9baeb1e80465eed74b77f3b2530d2a997f", + "SPDXRef-File-libcrypto1.1-61b7c086a62c6c726097636440eefea271494726621c661732f9482155658e59", + "SPDXRef-File-libcrypto1.1-9a2742b9a89ab1e1be6bda2dce46432e19112e05c7026161ecfec01c1fcea2d0", + "SPDXRef-File-libcrypto1.1-aa621774a15e27ad774c187bc60c0b9acf4ab096b50419ed45b7867eba9e78bd", + "SPDXRef-File-libcrypto1.1-dc16029d3f8ba2ba44b8eecefcc60be56e29fd757df2d465c2ef802544c3b154" + ], + "licenseDeclared": "OpenSSL", + "originator": "Timo Teras ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "1.1.1l-r0", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "OpenSSL" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "libcrypto1.1", + "originPackage": "openssl", + "maintainer": "Timo Teras ", + "version": "1.1.1l-r0", + "license": "OpenSSL", + "architecture": "x86_64", + "url": "https://www.openssl.org/", + "description": "Crypto library from openssl", + "size": 1211998, + "installedSize": 2768896, + "pullDependencies": "so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1Sywj1TEYEdvX0+MuqC+ea+zXxR0=", + "gitCommitOfApkPort": "3ef1965150d5b1de4af88dc51cf407e11b20b848", + "files": [ + { + "path": "/etc" + }, + { + "path": "/etc/ssl" + }, + { + "path": "/etc/ssl/ct_log_list.cnf", + "digest": { + "algorithm": "sha1", + "value": "Q1olh8TpdAi2QnTl4FK3TjdUiSwTo=" + } + }, + { + "path": "/etc/ssl/ct_log_list.cnf.dist", + "digest": { + "algorithm": "sha1", + "value": "Q1olh8TpdAi2QnTl4FK3TjdUiSwTo=" + } + }, + { + "path": "/etc/ssl/openssl.cnf", + "digest": { + "algorithm": "sha1", + "value": "Q1wGuxVEOK9iGLj1i8D3BSBnT7MJA=" + } + }, + { + "path": "/etc/ssl/openssl.cnf.dist", + "digest": { + "algorithm": "sha1", + "value": "Q1wGuxVEOK9iGLj1i8D3BSBnT7MJA=" + } + }, + { + "path": "/etc/ssl/certs" + }, + { + "path": "/etc/ssl/misc" + }, + { + "path": "/etc/ssl/misc/CA.pl", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1IACevKhK93GYBHp96Ie26jgZ17s=" + } + }, + { + "path": "/etc/ssl/misc/tsget", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q13NVgfr7dQUuGYxur0tNalH6EIjU=" + } + }, + { + "path": "/etc/ssl/misc/tsget.pl", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1ufKVrFftKLv8K/vullp/2reEDdo=" + } + }, + { + "path": "/etc/ssl/private" + }, + { + "path": "/lib" + }, + { + "path": "/lib/libcrypto.so.1.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1p0rHZXV1yOM1jGs0zuNSpi951t8=" + } + }, + { + "path": "/usr" + }, + { + "path": "/usr/lib" + }, + { + "path": "/usr/lib/libcrypto.so.1.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1T2si+c7ts7sgDxQYve4B3i1Dgo0=" + } + }, + { + "path": "/usr/lib/engines-1.1" + }, + { + "path": "/usr/lib/engines-1.1/afalg.so", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q13GvceRRzjQ6bnB5laIGCkDOHTM0=" + } + }, + { + "path": "/usr/lib/engines-1.1/capi.so", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1h8YLf+3MhbqdHUhGNEabdH5MooA=" + } + }, + { + "path": "/usr/lib/engines-1.1/padlock.so", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1TzNLJ3/GEmO9XW9XuZ/Izoy7zPk=" + } + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-libretls-3.3.3p1-r2", + "name": "libretls", + "licenseConcluded": "ISC", + "description": "port of libtls from libressl to openssl", + "downloadLocation": "https://git.causal.agency/libretls/", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:libretls:libretls:3.3.3p1-r2:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/libretls@3.3.3p1-r2?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-libretls-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "SPDXRef-File-libretls-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8", + "SPDXRef-File-libretls-5e6485633ddf6bd002b8f23aa797bc1d0a96a988ce9b5cc8620b03a97eff8504", + "SPDXRef-File-libretls-8b174b2ffa244d547e25a8e162f826756c918cd488d99fe354d28005ffac6eae" + ], + "licenseDeclared": "ISC", + "originator": "Ariadne Conill ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "3.3.3p1-r2", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "ISC", + "AND", + "(BSD-3-Clause", + "OR", + "MIT)" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "libretls", + "originPackage": "libretls", + "maintainer": "Ariadne Conill ", + "version": "3.3.3p1-r2", + "license": "ISC AND (BSD-3-Clause OR MIT)", + "architecture": "x86_64", + "url": "https://git.causal.agency/libretls/", + "description": "port of libtls from libressl to openssl", + "size": 28872, + "installedSize": 86016, + "pullDependencies": "ca-certificates-bundle so:libc.musl-x86_64.so.1 so:libcrypto.so.1.1 so:libssl.so.1.1", + "pullChecksum": "Q1mKL75PNQ3352oQUtXLS8GfI+37M=", + "gitCommitOfApkPort": "161d02ee8c48f3c3cae1d2b4b5d008fa318da0e1", + "files": [ + { + "path": "/usr" + }, + { + "path": "/usr/lib" + }, + { + "path": "/usr/lib/libtls.so.2", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1nNEC9T/t6W+Ecm0DxqMUnRvcT6k=" + } + }, + { + "path": "/usr/lib/libtls.so.2.0.3", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1t1MtXTHs0kMZ9+GCPJLriysmtA8=" + } + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-libssl1.1-1.1.1l-r0", + "name": "libssl1.1", + "licenseConcluded": "OpenSSL", + "description": "SSL shared libraries", + "downloadLocation": "https://www.openssl.org/", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:libssl1.1:libssl1.1:1.1.1l-r0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/libssl1.1@1.1.1l-r0?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-libssl1.1-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "SPDXRef-File-libssl1.1-58b41aa51e3d489042433ea7106d75bae94f893cbb12c96f626b29f6ed319d11", + "SPDXRef-File-libssl1.1-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "SPDXRef-File-libssl1.1-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8", + "SPDXRef-File-libssl1.1-bbe61f6803028095b80deafe7cadce3a79dfd0dca1edeba92904d28acbf827bb" + ], + "licenseDeclared": "OpenSSL", + "originator": "Timo Teras ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "1.1.1l-r0", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "OpenSSL" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "libssl1.1", + "originPackage": "openssl", + "maintainer": "Timo Teras ", + "version": "1.1.1l-r0", + "license": "OpenSSL", + "architecture": "x86_64", + "url": "https://www.openssl.org/", + "description": "SSL shared libraries", + "size": 212918, + "installedSize": 540672, + "pullDependencies": "so:libc.musl-x86_64.so.1 so:libcrypto.so.1.1", + "pullChecksum": "Q1Fgsc0DiapwjaJHbihB9ZrLQhr7Q=", + "gitCommitOfApkPort": "3ef1965150d5b1de4af88dc51cf407e11b20b848", + "files": [ + { + "path": "/lib" + }, + { + "path": "/lib/libssl.so.1.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1qaeh6oI3hVHuFty7JD5ASOu8S8k=" + } + }, + { + "path": "/usr" + }, + { + "path": "/usr/lib" + }, + { + "path": "/usr/lib/libssl.so.1.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q18j35pe3yp6HOgMih1wlGP1/mm2c=" + } + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-musl-1.2.2-r3", + "name": "musl", + "licenseConcluded": "MIT", + "description": "the musl c library (libc) implementation", + "downloadLocation": "https://musl.libc.org/", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:musl:musl:1.2.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/musl@1.2.2-r3?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-musl-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "SPDXRef-File-musl-65468fa8c77bfff2cb7856a0282b85183408468a121e145652772ca706a5dc25", + "SPDXRef-File-musl-e47e360e16a817e5eedb97ff32694c95649853533f4b1ceff862a18e7bb39372" + ], + "licenseDeclared": "MIT", + "originator": "Timo Teräs ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "1.2.2-r3", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "MIT" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "musl", + "originPackage": "musl", + "maintainer": "Timo Teräs ", + "version": "1.2.2-r3", + "license": "MIT", + "architecture": "x86_64", + "url": "https://musl.libc.org/", + "description": "the musl c library (libc) implementation", + "size": 382765, + "installedSize": 622592, + "pullDependencies": "", + "pullChecksum": "Q1n4yypJ4tpU5g+jxI7oHT0Bm4Xjo=", + "gitCommitOfApkPort": "1e9cba35059e3bb4635f12ee7e10dfe687df31ad", + "files": [ + { + "path": "/lib" + }, + { + "path": "/lib/ld-musl-x86_64.so.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1cZei2MQS2nixN1UwDj0FT9qWO4U=" + } + }, + { + "path": "/lib/libc.musl-x86_64.so.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q17yJ3JFNypA4mxhJJr0ou6CzsJVI=" + } + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-musl-utils-1.2.2-r3", + "name": "musl-utils", + "licenseConcluded": "MIT", + "description": "the musl c library (libc) implementation", + "downloadLocation": "https://musl.libc.org/", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:musl-utils:musl-utils:1.2.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:musl-utils:musl_utils:1.2.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:musl_utils:musl-utils:1.2.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:musl_utils:musl_utils:1.2.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:musl:musl-utils:1.2.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:musl:musl_utils:1.2.2-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/musl-utils@1.2.2-r3?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-musl-utils-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73", + "SPDXRef-File-musl-utils-8f48ac85f462686b419ebe87755d0d1fcf018f47d88c2c29f99b1d92dfe9de7d", + "SPDXRef-File-musl-utils-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "SPDXRef-File-musl-utils-33629c0e654360bfd8ab5089302a26e27dce5044d624b22f51fcbc66f1e0d19c", + "SPDXRef-File-musl-utils-8b7b11929b7ad4b8d3f64f327f89ddc2f3c118d2d05dd132c82764532ddce438", + "SPDXRef-File-musl-utils-9129db0a5e4e1bdc7665e5150d0ed1f60b7bf22898c4242d393705f1f047f7b2", + "SPDXRef-File-musl-utils-b9a8ae5bfbc0f7ca06b7d1ad3cb18f45eefb88bf0ff88d0f0b00b9c21da4ec6e", + "SPDXRef-File-musl-utils-3c7dc4450288ac204d7ec8350cf59d457e73b3c577c39ad1ffc22fa3b95c4c27" + ], + "licenseDeclared": "MIT", + "originator": "Timo Teräs ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "1.2.2-r3", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "MIT", + "BSD", + "GPL2+" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "musl-utils", + "originPackage": "musl", + "maintainer": "Timo Teräs ", + "version": "1.2.2-r3", + "license": "MIT BSD GPL2+", + "architecture": "x86_64", + "url": "https://musl.libc.org/", + "description": "the musl c library (libc) implementation", + "size": 36662, + "installedSize": 147456, + "pullDependencies": "scanelf so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1WNvvoHVxRySUmjgvqQie71lLRd8=", + "gitCommitOfApkPort": "1e9cba35059e3bb4635f12ee7e10dfe687df31ad", + "files": [ + { + "path": "/sbin" + }, + { + "path": "/sbin/ldconfig", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1Kja2+POZKxEkUOZqwSjC6kmaED4=" + } + }, + { + "path": "/usr" + }, + { + "path": "/usr/bin" + }, + { + "path": "/usr/bin/getconf", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1ENetcQcXKEGU2b0TD1S+WDuwAOE=" + } + }, + { + "path": "/usr/bin/getent", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1AtbzfYTO6GHhaimM7wXWuLGcECI=" + } + }, + { + "path": "/usr/bin/iconv", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1y+KPYlKOaOdDtMOapc2sTDsPKSU=" + } + }, + { + "path": "/usr/bin/ldd", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1yFAhGggmL7ERgbIA7KQxyTzf3ks=" + } + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-scanelf-1.3.2-r0", + "name": "scanelf", + "licenseConcluded": "GPL-2.0-only", + "description": "Scan ELF binaries for stuff", + "downloadLocation": "https://wiki.gentoo.org/wiki/Hardened/PaX_Utilities", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:scanelf:scanelf:1.3.2-r0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/scanelf@1.3.2-r0?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-scanelf-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "SPDXRef-File-scanelf-33629c0e654360bfd8ab5089302a26e27dce5044d624b22f51fcbc66f1e0d19c", + "SPDXRef-File-scanelf-ef9b1f801da4d431c07d16d8a519cebb8372e455698701c070e4b3ab746ddbff" + ], + "licenseDeclared": "GPL-2.0-only", + "originator": "Natanael Copa ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "1.3.2-r0", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "GPL-2.0-only" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "scanelf", + "originPackage": "pax-utils", + "maintainer": "Natanael Copa ", + "version": "1.3.2-r0", + "license": "GPL-2.0-only", + "architecture": "x86_64", + "url": "https://wiki.gentoo.org/wiki/Hardened/PaX_Utilities", + "description": "Scan ELF binaries for stuff", + "size": 36511, + "installedSize": 94208, + "pullDependencies": "so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1OWKo0fmUbClrhW0CPNjwA8AMLWo=", + "gitCommitOfApkPort": "4c7f72840f5052bc63af1796c3ad0021f97949f2", + "files": [ + { + "path": "/usr" + }, + { + "path": "/usr/bin" + }, + { + "path": "/usr/bin/scanelf", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1LhDyQrsweSqYTuRcjhG2d0pxhrE=" + } + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-ssl_client-1.33.1-r3", + "name": "ssl_client", + "licenseConcluded": "GPL-2.0-only", + "description": "EXternal ssl_client for busybox wget", + "downloadLocation": "https://busybox.net/", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ssl-client:ssl-client:1.33.1-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ssl-client:ssl_client:1.33.1-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ssl_client:ssl-client:1.33.1-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ssl_client:ssl_client:1.33.1-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ssl:ssl-client:1.33.1-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:ssl:ssl_client:1.33.1-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/ssl_client@1.33.1-r3?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-ssl_client-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "SPDXRef-File-ssl_client-33629c0e654360bfd8ab5089302a26e27dce5044d624b22f51fcbc66f1e0d19c", + "SPDXRef-File-ssl_client-c4c6145958cc1be35e3d13487ec423cdf20e95c24b14eed9bf424f78b84beb66" + ], + "licenseDeclared": "GPL-2.0-only", + "originator": "Natanael Copa ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "1.33.1-r3", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "GPL-2.0-only" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "ssl_client", + "originPackage": "busybox", + "maintainer": "Natanael Copa ", + "version": "1.33.1-r3", + "license": "GPL-2.0-only", + "architecture": "x86_64", + "url": "https://busybox.net/", + "description": "EXternal ssl_client for busybox wget", + "size": 4381, + "installedSize": 28672, + "pullDependencies": "so:libc.musl-x86_64.so.1 so:libtls.so.2", + "pullChecksum": "Q1d7WkMOIKXIk3qxexUxSo60HOofY=", + "gitCommitOfApkPort": "98710256acf90e670e79f32f1f0350b830979d24", + "files": [ + { + "path": "/usr" + }, + { + "path": "/usr/bin" + }, + { + "path": "/usr/bin/ssl_client", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1gPKQTCzC1isM7R89HFwb+A1XmM4=" + } + } + ] + } + } + }, + { + "SPDXID": "SPDXRef-Package-apk-zlib-1.2.11-r3", + "name": "zlib", + "licenseConcluded": "Zlib", + "description": "A compression/decompression Library", + "downloadLocation": "https://zlib.net/", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:zlib:zlib:1.2.11-r3:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:alpine/zlib@1.2.11-r3?arch=x86_64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-zlib-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "SPDXRef-File-zlib-a61bff49f837ddc87212fb7514e9daa60f221148f83ae4860f2803d62f8ba769", + "SPDXRef-File-zlib-cd0bd4fb5333d3da7dd14777edebc5b789b31d402b8c08a35f505cb60112f286" + ], + "licenseDeclared": "Zlib", + "originator": "Natanael Copa ", + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "versionInfo": "1.2.11-r3", + "syftPackageData": { + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "Zlib" + ], + "language": "", + "metadataType": "ApkMetadata", + "metadata": { + "package": "zlib", + "originPackage": "zlib", + "maintainer": "Natanael Copa ", + "version": "1.2.11-r3", + "license": "Zlib", + "architecture": "x86_64", + "url": "https://zlib.net/", + "description": "A compression/decompression Library", + "size": 51398, + "installedSize": 110592, + "pullDependencies": "so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1Sc/5gG4ey/zvnyPPQ/Au7bXqc08=", + "gitCommitOfApkPort": "388a4fb3640f8ccbd18e105df3ad741dca4247e1", + "files": [ + { + "path": "/lib" + }, + { + "path": "/lib/libz.so.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1a2H8hP24ryCAGf8fnc1Nha9IIHc=" + } + }, + { + "path": "/lib/libz.so.1.2.11", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q19Iml1N+v08tnk1ZtqGEVIEtIFJI=" + } + } + ] + } + } + } + ], + "files": [ + { + "SPDXID": "SPDXRef-File-alpine-baselayout-938b99e3330802a9290b64452b1b303a7efa94dd8f5fc86b6c941cf0644ce220", + "name": "dev", + "licenseConcluded": "", + "fileName": "/dev" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-fa713d04af6279efba07299265ea838d01677e1c24dabf3a50ae355b2aec78c4", + "name": "pts", + "licenseConcluded": "", + "fileName": "/dev/pts" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-0850a74c4deea14a0b23ba1ba46c970bddd720b268a72cdf7f2dec4215ffcc88", + "name": "shm", + "licenseConcluded": "", + "fileName": "/dev/shm" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "name": "etc", + "licenseConcluded": "", + "fileName": "/etc" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-87c4547311a1d5b80f46214960e323acf8fb7a533c6e74d7b98fab4fcf750949", + "name": "apk", + "licenseConcluded": "", + "fileName": "/etc/apk" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-ad87237a59f1d0e1b380dee393ccb396e853c9593702ea6c514d7b741a98e222", + "name": "conf.d", + "licenseConcluded": "", + "fileName": "/etc/conf.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-5240593a13ae1d67ac532cec0a648571ab373c64a6d970c7ebd26ada1aef4731", + "name": "crontabs", + "licenseConcluded": "", + "fileName": "/etc/crontabs" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-0c63107ca91d223780ca2bf9ff28f4ad1aee951dc0861a731385c67124c87095", + "name": "root", + "licenseConcluded": "", + "fileName": "/etc/crontabs/root" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-cf54dfacf32eec1c86e0406e395f1251d4e359a523cf6ea7f5e68d45cf692b59", + "name": "fstab", + "licenseConcluded": "", + "fileName": "/etc/fstab" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-ed448de483a77a745f150b021c026ae468a0d3374c0b5fe4cb40b94e9b5e4ca5", + "name": "group", + "licenseConcluded": "", + "fileName": "/etc/group" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-7b7e873d82462e4ede4cfa5ce873291b077ec45277cf9bd3d2750179c8397475", + "name": "hostname", + "licenseConcluded": "", + "fileName": "/etc/hostname" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-4a666ea3a3b04a24f574974df10592d51bd191614ee41b02d09f6d13c0c2f52a", + "name": "hosts", + "licenseConcluded": "", + "fileName": "/etc/hosts" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-c55a296bf4896c08e82f6c8dd17e4bbd2454dceffaf498a8669683b3345055dc", + "name": "init.d", + "licenseConcluded": "", + "fileName": "/etc/init.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-96c68e4af671cd64c58948f11f9d1e36cd2c1c3c70c2bf2576d261a429d7d088", + "name": "inittab", + "licenseConcluded": "", + "fileName": "/etc/inittab" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-5fe2a603a207a0be32f23c83597684317308df475d5f502263265feec7112b9c", + "name": "modprobe.d", + "licenseConcluded": "", + "fileName": "/etc/modprobe.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-7bab811be3ba6d8226afa29755291a86c01584ae520a5da1852b17bcd0ee9ee6", + "name": "aliases.conf", + "licenseConcluded": "", + "fileName": "/etc/modprobe.d/aliases.conf" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-7a594e2d43b74c5df07778b24879e71858d79fe7921b2229dbd29d2e39f0fee7", + "name": "blacklist.conf", + "licenseConcluded": "", + "fileName": "/etc/modprobe.d/blacklist.conf" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-adb462163022f3c4b134df078362eb91c3df2b74d181d330e64a4d228e342ee0", + "name": "i386.conf", + "licenseConcluded": "", + "fileName": "/etc/modprobe.d/i386.conf" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-87d9dd3c2e7d25d92e9ef89551e068f46640f02f94251a7643b6c4cda22e047c", + "name": "kms.conf", + "licenseConcluded": "", + "fileName": "/etc/modprobe.d/kms.conf" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-0c6df1408e5a475087f6cdfb71f67cb53a6cf67207ba2d6cfe3a82b73a809e32", + "name": "modules", + "licenseConcluded": "", + "fileName": "/etc/modules" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-1cfbc5a57d10970e212f768e066e5365709375db3faf4e5ab3e0a28b712efbfc", + "name": "modules-load.d", + "licenseConcluded": "", + "fileName": "/etc/modules-load.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-a5017c23a9f6ed2d1b4e08408fedf24e39aab24bacd1d1597c1432e80497614b", + "name": "motd", + "licenseConcluded": "", + "fileName": "/etc/motd" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-646d2b8cd720c24ee781a443805d178d859cdac40a21b73b75f2a3178dc8bf82", + "name": "mtab", + "licenseConcluded": "", + "fileName": "/etc/mtab" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-3cb4ecfa96c3717bf40df048eb527ae369def49fd83f58883951116e1fa1670a", + "name": "network", + "licenseConcluded": "", + "fileName": "/etc/network" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-164f2d1bdb81aec3400edda6615ea6006559786396f358d2128101fdde23e79e", + "name": "if-down.d", + "licenseConcluded": "", + "fileName": "/etc/network/if-down.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-f5067a79d8e5ded77c953ca3af252eca521f8c03c9fec20c85c42cab427f98d8", + "name": "if-post-down.d", + "licenseConcluded": "", + "fileName": "/etc/network/if-post-down.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-03e028932ed7076cd6db28b85a5700ca88bd0ae00410f61429ed3925ffee2e4a", + "name": "if-pre-up.d", + "licenseConcluded": "", + "fileName": "/etc/network/if-pre-up.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-8755c6b849aa8fb7e20c7b5172abcfe0c2c19e897f0ad2ef7ebab9e8acecc307", + "name": "if-up.d", + "licenseConcluded": "", + "fileName": "/etc/network/if-up.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-1c9fc3f14a82b56f4065a167c41510738e453de442b83161a13c86ffd812a4a1", + "name": "opt", + "licenseConcluded": "", + "fileName": "/etc/opt" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-74acf31844532670be412c65b8251ee55d072549080b1cffdbea6b1a192230a0", + "name": "passwd", + "licenseConcluded": "", + "fileName": "/etc/passwd" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-f6431e60b7311a5b22e920dbf75ca12019da3db364b557e8c71655b492fdc7ca", + "name": "periodic", + "licenseConcluded": "", + "fileName": "/etc/periodic" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-bc6c9197ed374198c8829fa6f41c47b81b09379e4f7e5b17441f602ddff1dd60", + "name": "15min", + "licenseConcluded": "", + "fileName": "/etc/periodic/15min" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-b35ee3dd7805325c05e5c24f0aff6715bce46b5df6f13be16406a7d74665fd94", + "name": "daily", + "licenseConcluded": "", + "fileName": "/etc/periodic/daily" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-9ec401f0bfd3ee5ac23dd036d3d73cc1fa85deacf8efbf8f5faaf6952d9b711a", + "name": "hourly", + "licenseConcluded": "", + "fileName": "/etc/periodic/hourly" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-5bd7409d3a6e5558758391624191bfb7bd293408a8cf0874d04c70b3d77cc961", + "name": "monthly", + "licenseConcluded": "", + "fileName": "/etc/periodic/monthly" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-270a90055881581dd978776bc42c89194d5a38ddf3bf7196f9cdb30fac606196", + "name": "weekly", + "licenseConcluded": "", + "fileName": "/etc/periodic/weekly" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-421918ef7d7b0bfab6fec5e5111c5fd490c94e9d72e6575a5b1d9a7b94746483", + "name": "profile", + "licenseConcluded": "", + "fileName": "/etc/profile" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-25ec93c60dd059453797da12f697089684f9a16cb5ce47a5cd3ec1dc0b3c78ea", + "name": "profile.d", + "licenseConcluded": "", + "fileName": "/etc/profile.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-ee224e9d960e60ffee86d25ddb811378f657fe9c0c7241b3957031c81e09fa9d", + "name": "README", + "licenseConcluded": "", + "fileName": "/etc/profile.d/README" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-d939b13506024f3afa5ce5b1bc91a82269c689173ac4ce4fff8b50915c516527", + "name": "color_prompt.sh.disabled", + "licenseConcluded": "", + "fileName": "/etc/profile.d/color_prompt.sh.disabled" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-acffca3302affa520554207b61b05b0e6574ff0df5d52f1a0f417326d7981e8b", + "name": "locale.sh", + "licenseConcluded": "", + "fileName": "/etc/profile.d/locale.sh" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-85fc9f0c9441a4e56af19c77267ed688b3716982d62faf88df797483299fbcbf", + "name": "protocols", + "licenseConcluded": "", + "fileName": "/etc/protocols" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-35c691835ff71f7c4e09fbca9e18a41fd926109c981ece63249e54eea6da3175", + "name": "services", + "licenseConcluded": "", + "fileName": "/etc/services" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-7b5ddf499844cf05866927513cf62fee9af8c281812def040b964146b0ea87d6", + "name": "shadow", + "licenseConcluded": "", + "fileName": "/etc/shadow" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-bf4911c4172a7de2e23458b30cea8ee81763eedd5f640d04de6341a61b7965d9", + "name": "shells", + "licenseConcluded": "", + "fileName": "/etc/shells" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-4645c3ce010ad9d6a98566235a0f8d1d13b6e41215efcd5db4c61adf3aacb274", + "name": "sysctl.conf", + "licenseConcluded": "", + "fileName": "/etc/sysctl.conf" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-9bf64c539a30b158186b5317f7e672b5491c435676e4ca5b3f1329fa860544b3", + "name": "sysctl.d", + "licenseConcluded": "", + "fileName": "/etc/sysctl.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-2cc974af6afc822c42a4e914df05c697348b80420941f6b27561b2bf688587b7", + "name": "home", + "licenseConcluded": "", + "fileName": "/home" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "name": "lib", + "licenseConcluded": "", + "fileName": "/lib" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-62fe5b620acf2330b7803289d102c09ec1d19f1b42def629be88fec0d6b76911", + "name": "firmware", + "licenseConcluded": "", + "fileName": "/lib/firmware" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-d8c416b3e20d54c8c21a5ab64f02a4507a674336f5fd8e9fed933cc78bec68a2", + "name": "mdev", + "licenseConcluded": "", + "fileName": "/lib/mdev" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-66a88450899099626d6882b37b4fcd93082df152658108d62c6d871f3058c948", + "name": "modules-load.d", + "licenseConcluded": "", + "fileName": "/lib/modules-load.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-7d87b2622e3b5da184511fc3b569785b116e3d06cf2a0369913ae767eafc0ced", + "name": "sysctl.d", + "licenseConcluded": "", + "fileName": "/lib/sysctl.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-e3dc3458bcfe5ffc3905d1a59a310190d16eb61a4a8262b256dc1618e3e8475a", + "name": "00-alpine.conf", + "licenseConcluded": "", + "fileName": "/lib/sysctl.d/00-alpine.conf" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-67f049743ef3707f138cd3aad15858fe185a01278c7681c35468403deafa29f8", + "name": "media", + "licenseConcluded": "", + "fileName": "/media" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-9a7019b3ec26c4992312cbf0ad51f5679549c9af382ef8f979e139383f3fcbd7", + "name": "cdrom", + "licenseConcluded": "", + "fileName": "/media/cdrom" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-5d135c43adc1d1967a0cd473c659dffdaa33f7b61a85249bba675c329e8cf447", + "name": "floppy", + "licenseConcluded": "", + "fileName": "/media/floppy" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-4b28a584089adbef86ab91e83be7c091a9a635a67276bc26e4f5a8f1f084d9f7", + "name": "usb", + "licenseConcluded": "", + "fileName": "/media/usb" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-fdeace0c97c37e435605c4867be6a665446a517252e505ab6a2b1207e75ae9a7", + "name": "mnt", + "licenseConcluded": "", + "fileName": "/mnt" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-cbcdfaeb37659981a3e96b9ec2000c67c9fa42b452cb26c41db886fca95f6ed0", + "name": "opt", + "licenseConcluded": "", + "fileName": "/opt" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-71ad1dfa1de556decbd6d7314196552e349d66067b49ab6bf8d4865faa663441", + "name": "proc", + "licenseConcluded": "", + "fileName": "/proc" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-94a6b447580330f9f2b609422537b04239ff3a39df9137e32efd559f1a2935cb", + "name": "root", + "licenseConcluded": "", + "fileName": "/root" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-b3d46fe883f343fe8d86cceea5141710f5cf97ab3b21a0d813982e1155d4c717", + "name": "run", + "licenseConcluded": "", + "fileName": "/run" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73", + "name": "sbin", + "licenseConcluded": "", + "fileName": "/sbin" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-7b6a323b0f7a6639345fb765860984dee6d6a9c8407f43342503c257f2065ed4", + "name": "mkmntdirs", + "licenseConcluded": "", + "fileName": "/sbin/mkmntdirs" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-a3d9ac4fdee9c2424e2fe95742f45f7d5134426aee734e778201f5db161741cc", + "name": "srv", + "licenseConcluded": "", + "fileName": "/srv" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-0bb7b4e45ea451fc58b3444bace01ea87ad00efe015a186bf5bc90a2e830f32e", + "name": "sys", + "licenseConcluded": "", + "fileName": "/sys" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-e9671acd244849c57167c658fa2f969752048f7ab184a3dcf5c46cb4d56ae124", + "name": "tmp", + "licenseConcluded": "", + "fileName": "/tmp" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "name": "usr", + "licenseConcluded": "", + "fileName": "/usr" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8", + "name": "lib", + "licenseConcluded": "", + "fileName": "/usr/lib" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-274cc9c977b9825b211b0434883f37ec82c06258ba8e250767fdf467f95d3556", + "name": "modules-load.d", + "licenseConcluded": "", + "fileName": "/usr/lib/modules-load.d" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-0885fcf5b23ee3ef7768fa611f596cc2d3209368cacceaf245fc80c3c6ff0b58", + "name": "local", + "licenseConcluded": "", + "fileName": "/usr/local" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-f696103f605ed61cc94a21b71ae3105f01f65f01a9f116d1cc60617d44205729", + "name": "bin", + "licenseConcluded": "", + "fileName": "/usr/local/bin" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-4553160a715f677baf2c0a2454c1e5e2b9598226e765a3c3fbe58bee7b25ad9e", + "name": "lib", + "licenseConcluded": "", + "fileName": "/usr/local/lib" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-1e3238fb9e3778665629ddf1407c26c21e28646996c76433805701ad85c8ac74", + "name": "share", + "licenseConcluded": "", + "fileName": "/usr/local/share" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-829eb242159232e7d47951730a06f83f7be1c901fa7f990c33e8b7c1c8173b79", + "name": "sbin", + "licenseConcluded": "", + "fileName": "/usr/sbin" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-10b2079988256c145bab6b179d480509efb438bf10d508150b59cc3ffc009ab3", + "name": "share", + "licenseConcluded": "", + "fileName": "/usr/share" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-9821d8ddb1dbec3b2a76c1a968d45701421459b9bf7752af24bfca1a0670bf15", + "name": "man", + "licenseConcluded": "", + "fileName": "/usr/share/man" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-de0cf4b047c1eda28543bcf2a9a248eb742e7ddee5259d639e5fe7e24def31b5", + "name": "misc", + "licenseConcluded": "", + "fileName": "/usr/share/misc" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-c309689ef6f2432e55b81fdb6e139e2857ba1aba16ea4270daa3f5ab68181cd3", + "name": "var", + "licenseConcluded": "", + "fileName": "/var" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-b79f7b1a48aea6d3205a9a3ae1dd44f4f5a60c3b243c672230d25b46c527ef40", + "name": "cache", + "licenseConcluded": "", + "fileName": "/var/cache" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-57bc3277a6135981afff45d68e8740aaa312055223095d2211808b09a7965fba", + "name": "misc", + "licenseConcluded": "", + "fileName": "/var/cache/misc" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-218bcd8d738d0f2d1444fb7b9300a6aca9403cde242852c7f442f7aa4f607482", + "name": "empty", + "licenseConcluded": "", + "fileName": "/var/empty" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-018076f20178b3bf76d8270b980ca52fcb8d4d20b397e43df5db5d59874fbf58", + "name": "lib", + "licenseConcluded": "", + "fileName": "/var/lib" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-9542f47d115504311f26c800a9bbb31c9f3532e2e8d3b5d25fd34ec425234596", + "name": "misc", + "licenseConcluded": "", + "fileName": "/var/lib/misc" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-7eb6299ed20af1ba33f42fc43e7e73f1093977631c7536766eca19006e763642", + "name": "local", + "licenseConcluded": "", + "fileName": "/var/local" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-03760b268e887197c8a9215d4daed2db64b368b2b5816ad1bba715bea307026b", + "name": "lock", + "licenseConcluded": "", + "fileName": "/var/lock" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-a459ad271310c24e7041dce53331250633351d6e2df7e26b2b0842bdd5fa8e29", + "name": "subsys", + "licenseConcluded": "", + "fileName": "/var/lock/subsys" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-9a6a409e26d4fd90b43d526e1d61dcfbc287a72f952784d9d26331d6aaf25624", + "name": "log", + "licenseConcluded": "", + "fileName": "/var/log" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-d65d76739220351968989bb4b05a589049beb21135b5a5ad21d0fb447da39889", + "name": "mail", + "licenseConcluded": "", + "fileName": "/var/mail" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-c1dc6ea3b918faed81b4f6111f0e00277a26474a45a0c65d6a7b15ebcfc0550d", + "name": "opt", + "licenseConcluded": "", + "fileName": "/var/opt" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-10bf2897b33acd74002e5ed9fcf668e393fcabd332a94cc32b6c329df1da155a", + "name": "run", + "licenseConcluded": "", + "fileName": "/var/run" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-01f1d631e7df830b9536b561faf66e65058dba8732ba5be875e06479c91fe429", + "name": "spool", + "licenseConcluded": "", + "fileName": "/var/spool" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-1d776d20b63c81a21618a8318dd70a6a1d2f0c433229a1fd6ceb69a2f1ef7b6c", + "name": "cron", + "licenseConcluded": "", + "fileName": "/var/spool/cron" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-7c33841e2b572a90b23bdafc3ca2bd76c2b93a009ca068206678b1fa2462ab4f", + "name": "crontabs", + "licenseConcluded": "", + "fileName": "/var/spool/cron/crontabs" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-fcbb68056f8a06f14a56e6a778b9808b49036ea2b05fcb0ae83b99090d1d5ae9", + "name": "mail", + "licenseConcluded": "", + "fileName": "/var/spool/mail" + }, + { + "SPDXID": "SPDXRef-File-alpine-baselayout-7ad74bcab7b847385cac1c0dd039265c3a63fd744ee6f77c62cd016a706c8c3a", + "name": "tmp", + "licenseConcluded": "", + "fileName": "/var/tmp" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "name": "etc", + "licenseConcluded": "", + "fileName": "/etc" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-87c4547311a1d5b80f46214960e323acf8fb7a533c6e74d7b98fab4fcf750949", + "name": "apk", + "licenseConcluded": "", + "fileName": "/etc/apk" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-3f4157f9078d158b7e396177d85c8fb53f29a76545f2d340eb3adf4a9e7a1885", + "name": "keys", + "licenseConcluded": "", + "fileName": "/etc/apk/keys" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-8e7ef118b5fed742d8afa54480a3fb0f6eab7955ea112c816bdbde328d4e640c", + "name": "alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "licenseConcluded": "", + "fileName": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-3ce1c6dd80b327840547860ef1034cb0f7adccdc95d3f561c99f1c1b55362cfe", + "name": "alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "licenseConcluded": "", + "fileName": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-2f9df767164cd310915bb577b7b3c995d50d5ffef92461cc00950925775ac895", + "name": "alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "licenseConcluded": "", + "fileName": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "name": "usr", + "licenseConcluded": "", + "fileName": "/usr" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-10b2079988256c145bab6b179d480509efb438bf10d508150b59cc3ffc009ab3", + "name": "share", + "licenseConcluded": "", + "fileName": "/usr/share" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-349a3439300fcd4715a93a5c325b66ef844c31ac555093144c3581c1911b92e0", + "name": "apk", + "licenseConcluded": "", + "fileName": "/usr/share/apk" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-31bc62f17e79698b7d3602d622ccb3564a28a6d72501c336ed65ba22ba56c1f3", + "name": "keys", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-70424b52d02f5c066fe7ef302f8c429ff2baa8a2046952e8b3845c75847ab4fd", + "name": "aarch64", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/aarch64" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-e64a4e2eb91dfce2784b56f812d260a693f2b4df747673684c2ed555b61f5946", + "name": "alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/aarch64/alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-68b6c908c50d7de9101b4eb6e878b6f1286a6656670eafa23d9412bd5f0c25c6", + "name": "alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-746532709f9a9c47d2ea7255b81ec12d78285495b42c3ae0bbc9d8d2a1934087", + "name": "alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-cf76eec6f2c4542d8e2cc5728a401c6ca16a431be13552a5bd1d688a217a7620", + "name": "alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-fc9d085ce2c164b5b2c75b14a81d07d34ca3728adb2b1f1add59e7462b5c86d1", + "name": "alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-f7a61b828205cc47efa2b5dfe729cd3cec1369df9606183471bff3f997f3020b", + "name": "alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-c4509f751c2d6a794c17af44174d5d94006c9f796046ccacf78e6a1562f464d2", + "name": "alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-70f3fad60f7becec73a9a1cc1d4c26cff30809cec5ea241ae10716367f64dff2", + "name": "alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-cfc0930eafccf8732e92f44e4d226bd64746e0f59f1055e7731b65b582cee5ba", + "name": "alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-f762ad8d2fa621c55664ae10aa50f8da6b7200b31ba70605ebbb2d0f9ed9f272", + "name": "alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-1e5fd156158d1cdcf396afbca2881729e56248a0a90c978686ff0e42408a9a72", + "name": "armhf", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/armhf" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-9cbcfdfb36800327d9f5a09ddcfb9d3c516bda7370b014c8379e61076e020f2d", + "name": "alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/armhf/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-0e37de6688a294aa4369a2429af2bc7a03fcb4c5a553c87455a81a46099eab7e", + "name": "armv7", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/armv7" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-f80ec3be3474099a63b3dd3da566965dbfee4dd6f820733f9d4d1571f652b505", + "name": "alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/armv7/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-8891b28cfb822f4d4fc6c3d16e9d5c6be93860304e39e927ad33fa59ec273412", + "name": "mips64", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/mips64" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-dd58af88dc076558fac411437289d9e8fdd2d5b9203a16506351202701886ab8", + "name": "alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/mips64/alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-0125cfa9decc9d138026e19d82b0d825123aa6498c813d39f0a0c0276e501a95", + "name": "ppc64le", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/ppc64le" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-05f9458494ebe3f01d7c668f14b9bc94386d771c3408834a2ff4d6d8199fb0d8", + "name": "alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/ppc64le/alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-490e2dbd984f1fe3e33b065b33a1189ba7d77024e3fc6817eb4dec00f6b6bb3b", + "name": "riscv64", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/riscv64" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-89e9bb3c796f4d3e70d534458f372f61607049d1a28ccb0e6bd0ab6ce9e278b5", + "name": "alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/riscv64/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-faa9eee3d033096e147baf97cd7f5300545ece5d833a9fee95e41bda631e4965", + "name": "s390x", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/s390x" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-ef16eb46ee4c77f8f5431cf5d5f69299cd96145ac4fd34308946781d3793bd7c", + "name": "alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/s390x/alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-6f54d5945a1770fd582051241b606e273e62d10ee546ed27512a312dd12553da", + "name": "x86", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/x86" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-871a4ad07e1d31a29b10e6129393236395b148d199c52350aa8ec4652543b522", + "name": "alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/x86/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-6347ab100d9ed7da25ae4a85d3af5e696c0b879a967833641d19446bd9bd0a2a", + "name": "alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/x86/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-09ecbceb074898be958e9a7ac482230d3ada42dc3db94792c829d0a8dcc9ed83", + "name": "x86_64", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/x86_64" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-9f5fdaf7c7a37ab72c777463690eeed9daf9cbff710a0b1d2ac146fc94df4c9b", + "name": "alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/x86_64/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-alpine-keys-efa8032a4839ecc3a9a121576cd74cd088ba82ea4e57bb4121e607cd0b8ed936", + "name": "alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "licenseConcluded": "", + "fileName": "/usr/share/apk/keys/x86_64/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "name": "etc", + "licenseConcluded": "", + "fileName": "/etc" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-87c4547311a1d5b80f46214960e323acf8fb7a533c6e74d7b98fab4fcf750949", + "name": "apk", + "licenseConcluded": "", + "fileName": "/etc/apk" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-3f4157f9078d158b7e396177d85c8fb53f29a76545f2d340eb3adf4a9e7a1885", + "name": "keys", + "licenseConcluded": "", + "fileName": "/etc/apk/keys" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-bb9c6bc3fb34848a938fd0f2a7ef7ebb8c713a31a87c66fd12b5ce6264bd3ab4", + "name": "protected_paths.d", + "licenseConcluded": "", + "fileName": "/etc/apk/protected_paths.d" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "name": "lib", + "licenseConcluded": "", + "fileName": "/lib" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-2bf2700ffc065ab6321946f53d462f79fed08a36e9f96721282cb7e0b0d798a4", + "name": "libapk.so.3.12.0", + "licenseConcluded": "", + "fileName": "/lib/libapk.so.3.12.0" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73", + "name": "sbin", + "licenseConcluded": "", + "fileName": "/sbin" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-896ed65f3b54897b064db7577043fb6a62eae8c02e5a57e51fb7ef352d5b616a", + "name": "apk", + "licenseConcluded": "", + "fileName": "/sbin/apk" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-c309689ef6f2432e55b81fdb6e139e2857ba1aba16ea4270daa3f5ab68181cd3", + "name": "var", + "licenseConcluded": "", + "fileName": "/var" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-b79f7b1a48aea6d3205a9a3ae1dd44f4f5a60c3b243c672230d25b46c527ef40", + "name": "cache", + "licenseConcluded": "", + "fileName": "/var/cache" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-57bc3277a6135981afff45d68e8740aaa312055223095d2211808b09a7965fba", + "name": "misc", + "licenseConcluded": "", + "fileName": "/var/cache/misc" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-018076f20178b3bf76d8270b980ca52fcb8d4d20b397e43df5db5d59874fbf58", + "name": "lib", + "licenseConcluded": "", + "fileName": "/var/lib" + }, + { + "SPDXID": "SPDXRef-File-apk-tools-a321a876b1cd473d1d97451f2820363efc7ab8ee27a81dff25fe6657d797677c", + "name": "apk", + "licenseConcluded": "", + "fileName": "/var/lib/apk" + }, + { + "SPDXID": "SPDXRef-File-busybox-808dd192d3243666b6f1ad4f9bfeca4877ee059456c40851a93937331b26014c", + "name": "bin", + "licenseConcluded": "", + "fileName": "/bin" + }, + { + "SPDXID": "SPDXRef-File-busybox-720be4f35da16d0da39268d0059b7e8334a1010c212ec8f1175540669a40f61f", + "name": "busybox", + "licenseConcluded": "", + "fileName": "/bin/busybox" + }, + { + "SPDXID": "SPDXRef-File-busybox-77bafa9e3a8a092afc4f1dd84e6e1cc58b68f42eb934bf0f6b73deb2518f78a3", + "name": "sh", + "licenseConcluded": "", + "fileName": "/bin/sh" + }, + { + "SPDXID": "SPDXRef-File-busybox-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "name": "etc", + "licenseConcluded": "", + "fileName": "/etc" + }, + { + "SPDXID": "SPDXRef-File-busybox-7534754c804f9d940a7292f91accecd4c8db85ae63115ebf2ac11a0ca5605de2", + "name": "logrotate.d", + "licenseConcluded": "", + "fileName": "/etc/logrotate.d" + }, + { + "SPDXID": "SPDXRef-File-busybox-1295836f682f19d49120419ca2e00407bcae6b1637415cf0c7ee6a6864b8020d", + "name": "acpid", + "licenseConcluded": "", + "fileName": "/etc/logrotate.d/acpid" + }, + { + "SPDXID": "SPDXRef-File-busybox-3cb4ecfa96c3717bf40df048eb527ae369def49fd83f58883951116e1fa1670a", + "name": "network", + "licenseConcluded": "", + "fileName": "/etc/network" + }, + { + "SPDXID": "SPDXRef-File-busybox-164f2d1bdb81aec3400edda6615ea6006559786396f358d2128101fdde23e79e", + "name": "if-down.d", + "licenseConcluded": "", + "fileName": "/etc/network/if-down.d" + }, + { + "SPDXID": "SPDXRef-File-busybox-f5067a79d8e5ded77c953ca3af252eca521f8c03c9fec20c85c42cab427f98d8", + "name": "if-post-down.d", + "licenseConcluded": "", + "fileName": "/etc/network/if-post-down.d" + }, + { + "SPDXID": "SPDXRef-File-busybox-3d5a22b80f0bdb989db1b36ca2e5b6025cf4c3e297ff2798a5c05a2c254eb19e", + "name": "if-post-up.d", + "licenseConcluded": "", + "fileName": "/etc/network/if-post-up.d" + }, + { + "SPDXID": "SPDXRef-File-busybox-14e352a2ba6dbb578d0c1f896a954208ee7dbf4614bde867f93103b95545e54f", + "name": "if-pre-down.d", + "licenseConcluded": "", + "fileName": "/etc/network/if-pre-down.d" + }, + { + "SPDXID": "SPDXRef-File-busybox-03e028932ed7076cd6db28b85a5700ca88bd0ae00410f61429ed3925ffee2e4a", + "name": "if-pre-up.d", + "licenseConcluded": "", + "fileName": "/etc/network/if-pre-up.d" + }, + { + "SPDXID": "SPDXRef-File-busybox-8755c6b849aa8fb7e20c7b5172abcfe0c2c19e897f0ad2ef7ebab9e8acecc307", + "name": "if-up.d", + "licenseConcluded": "", + "fileName": "/etc/network/if-up.d" + }, + { + "SPDXID": "SPDXRef-File-busybox-50b7b0a21325d57043679d2206e62c26ec02b73128a9a0dffc53e52885d039c2", + "name": "dad", + "licenseConcluded": "", + "fileName": "/etc/network/if-up.d/dad" + }, + { + "SPDXID": "SPDXRef-File-busybox-586c7ec4b9fbcf6ea0c92dee4ec8b71575ed9529d0c0213684297010e81d7da3", + "name": "securetty", + "licenseConcluded": "", + "fileName": "/etc/securetty" + }, + { + "SPDXID": "SPDXRef-File-busybox-d057a0120ff2ab94243ad477a65ae645ab92259a1cacd1b0cbf78d76346ccd12", + "name": "udhcpd.conf", + "licenseConcluded": "", + "fileName": "/etc/udhcpd.conf" + }, + { + "SPDXID": "SPDXRef-File-busybox-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73", + "name": "sbin", + "licenseConcluded": "", + "fileName": "/sbin" + }, + { + "SPDXID": "SPDXRef-File-busybox-e9671acd244849c57167c658fa2f969752048f7ab184a3dcf5c46cb4d56ae124", + "name": "tmp", + "licenseConcluded": "", + "fileName": "/tmp" + }, + { + "SPDXID": "SPDXRef-File-busybox-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "name": "usr", + "licenseConcluded": "", + "fileName": "/usr" + }, + { + "SPDXID": "SPDXRef-File-busybox-829eb242159232e7d47951730a06f83f7be1c901fa7f990c33e8b7c1c8173b79", + "name": "sbin", + "licenseConcluded": "", + "fileName": "/usr/sbin" + }, + { + "SPDXID": "SPDXRef-File-busybox-10b2079988256c145bab6b179d480509efb438bf10d508150b59cc3ffc009ab3", + "name": "share", + "licenseConcluded": "", + "fileName": "/usr/share" + }, + { + "SPDXID": "SPDXRef-File-busybox-4cf116134c8172c74ce330c5923f36b95f95a8823fe5824d17a8e10f7990d372", + "name": "udhcpc", + "licenseConcluded": "", + "fileName": "/usr/share/udhcpc" + }, + { + "SPDXID": "SPDXRef-File-busybox-80c6e9799c5a801c8c18ac72900403b677899f126d0f681bc6cfb5b29813cda2", + "name": "default.script", + "licenseConcluded": "", + "fileName": "/usr/share/udhcpc/default.script" + }, + { + "SPDXID": "SPDXRef-File-busybox-c309689ef6f2432e55b81fdb6e139e2857ba1aba16ea4270daa3f5ab68181cd3", + "name": "var", + "licenseConcluded": "", + "fileName": "/var" + }, + { + "SPDXID": "SPDXRef-File-busybox-b79f7b1a48aea6d3205a9a3ae1dd44f4f5a60c3b243c672230d25b46c527ef40", + "name": "cache", + "licenseConcluded": "", + "fileName": "/var/cache" + }, + { + "SPDXID": "SPDXRef-File-busybox-57bc3277a6135981afff45d68e8740aaa312055223095d2211808b09a7965fba", + "name": "misc", + "licenseConcluded": "", + "fileName": "/var/cache/misc" + }, + { + "SPDXID": "SPDXRef-File-busybox-018076f20178b3bf76d8270b980ca52fcb8d4d20b397e43df5db5d59874fbf58", + "name": "lib", + "licenseConcluded": "", + "fileName": "/var/lib" + }, + { + "SPDXID": "SPDXRef-File-busybox-0c20a49b2af2956d6540baa5865787a8dd9947410aab18eaa80098ff75a6757b", + "name": "udhcpd", + "licenseConcluded": "", + "fileName": "/var/lib/udhcpd" + }, + { + "SPDXID": "SPDXRef-File-ca-certificates-bundle-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "name": "etc", + "licenseConcluded": "", + "fileName": "/etc" + }, + { + "SPDXID": "SPDXRef-File-ca-certificates-bundle-8b6554cf4168c3e562d168c8a781a831294b6cc9872eb7165b234b334fc80ff1", + "name": "ssl", + "licenseConcluded": "", + "fileName": "/etc/ssl" + }, + { + "SPDXID": "SPDXRef-File-ca-certificates-bundle-a9abc3ef3bbbabdce6468df2ab5ed25caab150df4beefd65c246fdf6b15a7677", + "name": "cert.pem", + "licenseConcluded": "", + "fileName": "/etc/ssl/cert.pem" + }, + { + "SPDXID": "SPDXRef-File-ca-certificates-bundle-bd8ae46e651cb3986dd212d98d6b746022a56c6d62f441adefd1898265c30f6e", + "name": "certs", + "licenseConcluded": "", + "fileName": "/etc/ssl/certs" + }, + { + "SPDXID": "SPDXRef-File-ca-certificates-bundle-b583d63728636e5fa4b2ec89e062e655992406c08430f1b44b12e33fc357b80e", + "name": "ca-certificates.crt", + "licenseConcluded": "", + "fileName": "/etc/ssl/certs/ca-certificates.crt" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08", + "name": "etc", + "licenseConcluded": "", + "fileName": "/etc" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-8b6554cf4168c3e562d168c8a781a831294b6cc9872eb7165b234b334fc80ff1", + "name": "ssl", + "licenseConcluded": "", + "fileName": "/etc/ssl" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-bd8ae46e651cb3986dd212d98d6b746022a56c6d62f441adefd1898265c30f6e", + "name": "certs", + "licenseConcluded": "", + "fileName": "/etc/ssl/certs" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-1b5d1aceec5c5574bdb154f02ba90f0065943419ec0c9637ea673a7b72ba8ae8", + "name": "ct_log_list.cnf", + "licenseConcluded": "", + "fileName": "/etc/ssl/ct_log_list.cnf" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-bf105812bacf051dd9c91886610bd0f59139c04f5051964c57c880ce66a1dc20", + "name": "ct_log_list.cnf.dist", + "licenseConcluded": "", + "fileName": "/etc/ssl/ct_log_list.cnf.dist" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-b04e1932acec52946ff06d74ea56dcb848c449688d9d2a87c27277c0143edb35", + "name": "misc", + "licenseConcluded": "", + "fileName": "/etc/ssl/misc" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-bc5cfefdcd1dc36b26b32bb31673f11c97559b78280bde82b89f6c5baed66cfd", + "name": "CA.pl", + "licenseConcluded": "", + "fileName": "/etc/ssl/misc/CA.pl" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-86ba9a02fbedfecd54600b4498844eb8b61fb6679c33b9dd1d6a8c585622bfe8", + "name": "tsget", + "licenseConcluded": "", + "fileName": "/etc/ssl/misc/tsget" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-86e61f466a55cfb1c7807c66cf9d6aef8eeb4345b47ae30e81c30e809763baaa", + "name": "tsget.pl", + "licenseConcluded": "", + "fileName": "/etc/ssl/misc/tsget.pl" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-d0a581b15648f37d1e89a70c47bca5a4ffc9bd533c3c5f747326e19496fe23bb", + "name": "openssl.cnf", + "licenseConcluded": "", + "fileName": "/etc/ssl/openssl.cnf" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-6f4eba22515a1cc75dc8022b7327f3cd9cd6ce9ef89dda2712d3db9be3c3c6b2", + "name": "openssl.cnf.dist", + "licenseConcluded": "", + "fileName": "/etc/ssl/openssl.cnf.dist" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-9d348aef994196518b59ced347de2b81b3df16f83f384d7a17fd642513a0996e", + "name": "private", + "licenseConcluded": "", + "fileName": "/etc/ssl/private" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "name": "lib", + "licenseConcluded": "", + "fileName": "/lib" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-01f1138a2d006757fb5698dd8e786f9b8cfe5326ca9855ed0b7df858571af416", + "name": "libcrypto.so.1.1", + "licenseConcluded": "", + "fileName": "/lib/libcrypto.so.1.1" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "name": "usr", + "licenseConcluded": "", + "fileName": "/usr" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8", + "name": "lib", + "licenseConcluded": "", + "fileName": "/usr/lib" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-d434b4074bf223c1efb9e41014702b9baeb1e80465eed74b77f3b2530d2a997f", + "name": "engines-1.1", + "licenseConcluded": "", + "fileName": "/usr/lib/engines-1.1" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-61b7c086a62c6c726097636440eefea271494726621c661732f9482155658e59", + "name": "afalg.so", + "licenseConcluded": "", + "fileName": "/usr/lib/engines-1.1/afalg.so" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-9a2742b9a89ab1e1be6bda2dce46432e19112e05c7026161ecfec01c1fcea2d0", + "name": "capi.so", + "licenseConcluded": "", + "fileName": "/usr/lib/engines-1.1/capi.so" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-aa621774a15e27ad774c187bc60c0b9acf4ab096b50419ed45b7867eba9e78bd", + "name": "padlock.so", + "licenseConcluded": "", + "fileName": "/usr/lib/engines-1.1/padlock.so" + }, + { + "SPDXID": "SPDXRef-File-libcrypto1.1-dc16029d3f8ba2ba44b8eecefcc60be56e29fd757df2d465c2ef802544c3b154", + "name": "libcrypto.so.1.1", + "licenseConcluded": "", + "fileName": "/usr/lib/libcrypto.so.1.1" + }, + { + "SPDXID": "SPDXRef-File-libretls-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "name": "usr", + "licenseConcluded": "", + "fileName": "/usr" + }, + { + "SPDXID": "SPDXRef-File-libretls-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8", + "name": "lib", + "licenseConcluded": "", + "fileName": "/usr/lib" + }, + { + "SPDXID": "SPDXRef-File-libretls-5e6485633ddf6bd002b8f23aa797bc1d0a96a988ce9b5cc8620b03a97eff8504", + "name": "libtls.so.2", + "licenseConcluded": "", + "fileName": "/usr/lib/libtls.so.2" + }, + { + "SPDXID": "SPDXRef-File-libretls-8b174b2ffa244d547e25a8e162f826756c918cd488d99fe354d28005ffac6eae", + "name": "libtls.so.2.0.3", + "licenseConcluded": "", + "fileName": "/usr/lib/libtls.so.2.0.3" + }, + { + "SPDXID": "SPDXRef-File-libssl1.1-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "name": "lib", + "licenseConcluded": "", + "fileName": "/lib" + }, + { + "SPDXID": "SPDXRef-File-libssl1.1-58b41aa51e3d489042433ea7106d75bae94f893cbb12c96f626b29f6ed319d11", + "name": "libssl.so.1.1", + "licenseConcluded": "", + "fileName": "/lib/libssl.so.1.1" + }, + { + "SPDXID": "SPDXRef-File-libssl1.1-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "name": "usr", + "licenseConcluded": "", + "fileName": "/usr" + }, + { + "SPDXID": "SPDXRef-File-libssl1.1-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8", + "name": "lib", + "licenseConcluded": "", + "fileName": "/usr/lib" + }, + { + "SPDXID": "SPDXRef-File-libssl1.1-bbe61f6803028095b80deafe7cadce3a79dfd0dca1edeba92904d28acbf827bb", + "name": "libssl.so.1.1", + "licenseConcluded": "", + "fileName": "/usr/lib/libssl.so.1.1" + }, + { + "SPDXID": "SPDXRef-File-musl-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "name": "lib", + "licenseConcluded": "", + "fileName": "/lib" + }, + { + "SPDXID": "SPDXRef-File-musl-65468fa8c77bfff2cb7856a0282b85183408468a121e145652772ca706a5dc25", + "name": "ld-musl-x86_64.so.1", + "licenseConcluded": "", + "fileName": "/lib/ld-musl-x86_64.so.1" + }, + { + "SPDXID": "SPDXRef-File-musl-e47e360e16a817e5eedb97ff32694c95649853533f4b1ceff862a18e7bb39372", + "name": "libc.musl-x86_64.so.1", + "licenseConcluded": "", + "fileName": "/lib/libc.musl-x86_64.so.1" + }, + { + "SPDXID": "SPDXRef-File-musl-utils-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73", + "name": "sbin", + "licenseConcluded": "", + "fileName": "/sbin" + }, + { + "SPDXID": "SPDXRef-File-musl-utils-8f48ac85f462686b419ebe87755d0d1fcf018f47d88c2c29f99b1d92dfe9de7d", + "name": "ldconfig", + "licenseConcluded": "", + "fileName": "/sbin/ldconfig" + }, + { + "SPDXID": "SPDXRef-File-musl-utils-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "name": "usr", + "licenseConcluded": "", + "fileName": "/usr" + }, + { + "SPDXID": "SPDXRef-File-musl-utils-33629c0e654360bfd8ab5089302a26e27dce5044d624b22f51fcbc66f1e0d19c", + "name": "bin", + "licenseConcluded": "", + "fileName": "/usr/bin" + }, + { + "SPDXID": "SPDXRef-File-musl-utils-8b7b11929b7ad4b8d3f64f327f89ddc2f3c118d2d05dd132c82764532ddce438", + "name": "getconf", + "licenseConcluded": "", + "fileName": "/usr/bin/getconf" + }, + { + "SPDXID": "SPDXRef-File-musl-utils-9129db0a5e4e1bdc7665e5150d0ed1f60b7bf22898c4242d393705f1f047f7b2", + "name": "getent", + "licenseConcluded": "", + "fileName": "/usr/bin/getent" + }, + { + "SPDXID": "SPDXRef-File-musl-utils-b9a8ae5bfbc0f7ca06b7d1ad3cb18f45eefb88bf0ff88d0f0b00b9c21da4ec6e", + "name": "iconv", + "licenseConcluded": "", + "fileName": "/usr/bin/iconv" + }, + { + "SPDXID": "SPDXRef-File-musl-utils-3c7dc4450288ac204d7ec8350cf59d457e73b3c577c39ad1ffc22fa3b95c4c27", + "name": "ldd", + "licenseConcluded": "", + "fileName": "/usr/bin/ldd" + }, + { + "SPDXID": "SPDXRef-File-scanelf-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "name": "usr", + "licenseConcluded": "", + "fileName": "/usr" + }, + { + "SPDXID": "SPDXRef-File-scanelf-33629c0e654360bfd8ab5089302a26e27dce5044d624b22f51fcbc66f1e0d19c", + "name": "bin", + "licenseConcluded": "", + "fileName": "/usr/bin" + }, + { + "SPDXID": "SPDXRef-File-scanelf-ef9b1f801da4d431c07d16d8a519cebb8372e455698701c070e4b3ab746ddbff", + "name": "scanelf", + "licenseConcluded": "", + "fileName": "/usr/bin/scanelf" + }, + { + "SPDXID": "SPDXRef-File-ssl_client-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961", + "name": "usr", + "licenseConcluded": "", + "fileName": "/usr" + }, + { + "SPDXID": "SPDXRef-File-ssl_client-33629c0e654360bfd8ab5089302a26e27dce5044d624b22f51fcbc66f1e0d19c", + "name": "bin", + "licenseConcluded": "", + "fileName": "/usr/bin" + }, + { + "SPDXID": "SPDXRef-File-ssl_client-c4c6145958cc1be35e3d13487ec423cdf20e95c24b14eed9bf424f78b84beb66", + "name": "ssl_client", + "licenseConcluded": "", + "fileName": "/usr/bin/ssl_client" + }, + { + "SPDXID": "SPDXRef-File-zlib-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37", + "name": "lib", + "licenseConcluded": "", + "fileName": "/lib" + }, + { + "SPDXID": "SPDXRef-File-zlib-a61bff49f837ddc87212fb7514e9daa60f221148f83ae4860f2803d62f8ba769", + "name": "libz.so.1", + "licenseConcluded": "", + "fileName": "/lib/libz.so.1" + }, + { + "SPDXID": "SPDXRef-File-zlib-cd0bd4fb5333d3da7dd14777edebc5b789b31d402b8c08a35f505cb60112f286", + "name": "libz.so.1.2.11", + "licenseConcluded": "", + "fileName": "/lib/libz.so.1.2.11" + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-938b99e3330802a9290b64452b1b303a7efa94dd8f5fc86b6c941cf0644ce220" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-fa713d04af6279efba07299265ea838d01677e1c24dabf3a50ae355b2aec78c4" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-0850a74c4deea14a0b23ba1ba46c970bddd720b268a72cdf7f2dec4215ffcc88" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-87c4547311a1d5b80f46214960e323acf8fb7a533c6e74d7b98fab4fcf750949" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-ad87237a59f1d0e1b380dee393ccb396e853c9593702ea6c514d7b741a98e222" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-5240593a13ae1d67ac532cec0a648571ab373c64a6d970c7ebd26ada1aef4731" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-0c63107ca91d223780ca2bf9ff28f4ad1aee951dc0861a731385c67124c87095" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-cf54dfacf32eec1c86e0406e395f1251d4e359a523cf6ea7f5e68d45cf692b59" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-ed448de483a77a745f150b021c026ae468a0d3374c0b5fe4cb40b94e9b5e4ca5" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-7b7e873d82462e4ede4cfa5ce873291b077ec45277cf9bd3d2750179c8397475" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-4a666ea3a3b04a24f574974df10592d51bd191614ee41b02d09f6d13c0c2f52a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-c55a296bf4896c08e82f6c8dd17e4bbd2454dceffaf498a8669683b3345055dc" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-96c68e4af671cd64c58948f11f9d1e36cd2c1c3c70c2bf2576d261a429d7d088" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-5fe2a603a207a0be32f23c83597684317308df475d5f502263265feec7112b9c" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-7bab811be3ba6d8226afa29755291a86c01584ae520a5da1852b17bcd0ee9ee6" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-7a594e2d43b74c5df07778b24879e71858d79fe7921b2229dbd29d2e39f0fee7" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-adb462163022f3c4b134df078362eb91c3df2b74d181d330e64a4d228e342ee0" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-87d9dd3c2e7d25d92e9ef89551e068f46640f02f94251a7643b6c4cda22e047c" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-0c6df1408e5a475087f6cdfb71f67cb53a6cf67207ba2d6cfe3a82b73a809e32" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-1cfbc5a57d10970e212f768e066e5365709375db3faf4e5ab3e0a28b712efbfc" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-a5017c23a9f6ed2d1b4e08408fedf24e39aab24bacd1d1597c1432e80497614b" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-646d2b8cd720c24ee781a443805d178d859cdac40a21b73b75f2a3178dc8bf82" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-3cb4ecfa96c3717bf40df048eb527ae369def49fd83f58883951116e1fa1670a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-164f2d1bdb81aec3400edda6615ea6006559786396f358d2128101fdde23e79e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-f5067a79d8e5ded77c953ca3af252eca521f8c03c9fec20c85c42cab427f98d8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-03e028932ed7076cd6db28b85a5700ca88bd0ae00410f61429ed3925ffee2e4a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-8755c6b849aa8fb7e20c7b5172abcfe0c2c19e897f0ad2ef7ebab9e8acecc307" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-1c9fc3f14a82b56f4065a167c41510738e453de442b83161a13c86ffd812a4a1" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-74acf31844532670be412c65b8251ee55d072549080b1cffdbea6b1a192230a0" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-f6431e60b7311a5b22e920dbf75ca12019da3db364b557e8c71655b492fdc7ca" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-bc6c9197ed374198c8829fa6f41c47b81b09379e4f7e5b17441f602ddff1dd60" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-b35ee3dd7805325c05e5c24f0aff6715bce46b5df6f13be16406a7d74665fd94" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-9ec401f0bfd3ee5ac23dd036d3d73cc1fa85deacf8efbf8f5faaf6952d9b711a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-5bd7409d3a6e5558758391624191bfb7bd293408a8cf0874d04c70b3d77cc961" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-270a90055881581dd978776bc42c89194d5a38ddf3bf7196f9cdb30fac606196" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-421918ef7d7b0bfab6fec5e5111c5fd490c94e9d72e6575a5b1d9a7b94746483" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-25ec93c60dd059453797da12f697089684f9a16cb5ce47a5cd3ec1dc0b3c78ea" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-ee224e9d960e60ffee86d25ddb811378f657fe9c0c7241b3957031c81e09fa9d" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-d939b13506024f3afa5ce5b1bc91a82269c689173ac4ce4fff8b50915c516527" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-acffca3302affa520554207b61b05b0e6574ff0df5d52f1a0f417326d7981e8b" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-85fc9f0c9441a4e56af19c77267ed688b3716982d62faf88df797483299fbcbf" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-35c691835ff71f7c4e09fbca9e18a41fd926109c981ece63249e54eea6da3175" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-7b5ddf499844cf05866927513cf62fee9af8c281812def040b964146b0ea87d6" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-bf4911c4172a7de2e23458b30cea8ee81763eedd5f640d04de6341a61b7965d9" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-4645c3ce010ad9d6a98566235a0f8d1d13b6e41215efcd5db4c61adf3aacb274" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-9bf64c539a30b158186b5317f7e672b5491c435676e4ca5b3f1329fa860544b3" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-2cc974af6afc822c42a4e914df05c697348b80420941f6b27561b2bf688587b7" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-62fe5b620acf2330b7803289d102c09ec1d19f1b42def629be88fec0d6b76911" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-d8c416b3e20d54c8c21a5ab64f02a4507a674336f5fd8e9fed933cc78bec68a2" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-66a88450899099626d6882b37b4fcd93082df152658108d62c6d871f3058c948" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-7d87b2622e3b5da184511fc3b569785b116e3d06cf2a0369913ae767eafc0ced" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-e3dc3458bcfe5ffc3905d1a59a310190d16eb61a4a8262b256dc1618e3e8475a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-67f049743ef3707f138cd3aad15858fe185a01278c7681c35468403deafa29f8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-9a7019b3ec26c4992312cbf0ad51f5679549c9af382ef8f979e139383f3fcbd7" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-5d135c43adc1d1967a0cd473c659dffdaa33f7b61a85249bba675c329e8cf447" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-4b28a584089adbef86ab91e83be7c091a9a635a67276bc26e4f5a8f1f084d9f7" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-fdeace0c97c37e435605c4867be6a665446a517252e505ab6a2b1207e75ae9a7" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-cbcdfaeb37659981a3e96b9ec2000c67c9fa42b452cb26c41db886fca95f6ed0" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-71ad1dfa1de556decbd6d7314196552e349d66067b49ab6bf8d4865faa663441" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-94a6b447580330f9f2b609422537b04239ff3a39df9137e32efd559f1a2935cb" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-b3d46fe883f343fe8d86cceea5141710f5cf97ab3b21a0d813982e1155d4c717" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-7b6a323b0f7a6639345fb765860984dee6d6a9c8407f43342503c257f2065ed4" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-a3d9ac4fdee9c2424e2fe95742f45f7d5134426aee734e778201f5db161741cc" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-0bb7b4e45ea451fc58b3444bace01ea87ad00efe015a186bf5bc90a2e830f32e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-e9671acd244849c57167c658fa2f969752048f7ab184a3dcf5c46cb4d56ae124" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-274cc9c977b9825b211b0434883f37ec82c06258ba8e250767fdf467f95d3556" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-0885fcf5b23ee3ef7768fa611f596cc2d3209368cacceaf245fc80c3c6ff0b58" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-f696103f605ed61cc94a21b71ae3105f01f65f01a9f116d1cc60617d44205729" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-4553160a715f677baf2c0a2454c1e5e2b9598226e765a3c3fbe58bee7b25ad9e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-1e3238fb9e3778665629ddf1407c26c21e28646996c76433805701ad85c8ac74" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-829eb242159232e7d47951730a06f83f7be1c901fa7f990c33e8b7c1c8173b79" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-10b2079988256c145bab6b179d480509efb438bf10d508150b59cc3ffc009ab3" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-9821d8ddb1dbec3b2a76c1a968d45701421459b9bf7752af24bfca1a0670bf15" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-de0cf4b047c1eda28543bcf2a9a248eb742e7ddee5259d639e5fe7e24def31b5" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-c309689ef6f2432e55b81fdb6e139e2857ba1aba16ea4270daa3f5ab68181cd3" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-b79f7b1a48aea6d3205a9a3ae1dd44f4f5a60c3b243c672230d25b46c527ef40" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-57bc3277a6135981afff45d68e8740aaa312055223095d2211808b09a7965fba" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-218bcd8d738d0f2d1444fb7b9300a6aca9403cde242852c7f442f7aa4f607482" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-018076f20178b3bf76d8270b980ca52fcb8d4d20b397e43df5db5d59874fbf58" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-9542f47d115504311f26c800a9bbb31c9f3532e2e8d3b5d25fd34ec425234596" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-7eb6299ed20af1ba33f42fc43e7e73f1093977631c7536766eca19006e763642" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-03760b268e887197c8a9215d4daed2db64b368b2b5816ad1bba715bea307026b" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-a459ad271310c24e7041dce53331250633351d6e2df7e26b2b0842bdd5fa8e29" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-9a6a409e26d4fd90b43d526e1d61dcfbc287a72f952784d9d26331d6aaf25624" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-d65d76739220351968989bb4b05a589049beb21135b5a5ad21d0fb447da39889" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-c1dc6ea3b918faed81b4f6111f0e00277a26474a45a0c65d6a7b15ebcfc0550d" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-10bf2897b33acd74002e5ed9fcf668e393fcabd332a94cc32b6c329df1da155a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-01f1d631e7df830b9536b561faf66e65058dba8732ba5be875e06479c91fe429" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-1d776d20b63c81a21618a8318dd70a6a1d2f0c433229a1fd6ceb69a2f1ef7b6c" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-7c33841e2b572a90b23bdafc3ca2bd76c2b93a009ca068206678b1fa2462ab4f" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-fcbb68056f8a06f14a56e6a778b9808b49036ea2b05fcb0ae83b99090d1d5ae9" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-3.2.0-r16", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-baselayout-7ad74bcab7b847385cac1c0dd039265c3a63fd744ee6f77c62cd016a706c8c3a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-87c4547311a1d5b80f46214960e323acf8fb7a533c6e74d7b98fab4fcf750949" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-3f4157f9078d158b7e396177d85c8fb53f29a76545f2d340eb3adf4a9e7a1885" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-8e7ef118b5fed742d8afa54480a3fb0f6eab7955ea112c816bdbde328d4e640c" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-3ce1c6dd80b327840547860ef1034cb0f7adccdc95d3f561c99f1c1b55362cfe" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-2f9df767164cd310915bb577b7b3c995d50d5ffef92461cc00950925775ac895" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-10b2079988256c145bab6b179d480509efb438bf10d508150b59cc3ffc009ab3" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-349a3439300fcd4715a93a5c325b66ef844c31ac555093144c3581c1911b92e0" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-31bc62f17e79698b7d3602d622ccb3564a28a6d72501c336ed65ba22ba56c1f3" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-70424b52d02f5c066fe7ef302f8c429ff2baa8a2046952e8b3845c75847ab4fd" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-e64a4e2eb91dfce2784b56f812d260a693f2b4df747673684c2ed555b61f5946" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-68b6c908c50d7de9101b4eb6e878b6f1286a6656670eafa23d9412bd5f0c25c6" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-746532709f9a9c47d2ea7255b81ec12d78285495b42c3ae0bbc9d8d2a1934087" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-cf76eec6f2c4542d8e2cc5728a401c6ca16a431be13552a5bd1d688a217a7620" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-fc9d085ce2c164b5b2c75b14a81d07d34ca3728adb2b1f1add59e7462b5c86d1" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-f7a61b828205cc47efa2b5dfe729cd3cec1369df9606183471bff3f997f3020b" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-c4509f751c2d6a794c17af44174d5d94006c9f796046ccacf78e6a1562f464d2" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-70f3fad60f7becec73a9a1cc1d4c26cff30809cec5ea241ae10716367f64dff2" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-cfc0930eafccf8732e92f44e4d226bd64746e0f59f1055e7731b65b582cee5ba" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-f762ad8d2fa621c55664ae10aa50f8da6b7200b31ba70605ebbb2d0f9ed9f272" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-1e5fd156158d1cdcf396afbca2881729e56248a0a90c978686ff0e42408a9a72" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-9cbcfdfb36800327d9f5a09ddcfb9d3c516bda7370b014c8379e61076e020f2d" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-0e37de6688a294aa4369a2429af2bc7a03fcb4c5a553c87455a81a46099eab7e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-f80ec3be3474099a63b3dd3da566965dbfee4dd6f820733f9d4d1571f652b505" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-8891b28cfb822f4d4fc6c3d16e9d5c6be93860304e39e927ad33fa59ec273412" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-dd58af88dc076558fac411437289d9e8fdd2d5b9203a16506351202701886ab8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-0125cfa9decc9d138026e19d82b0d825123aa6498c813d39f0a0c0276e501a95" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-05f9458494ebe3f01d7c668f14b9bc94386d771c3408834a2ff4d6d8199fb0d8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-490e2dbd984f1fe3e33b065b33a1189ba7d77024e3fc6817eb4dec00f6b6bb3b" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-89e9bb3c796f4d3e70d534458f372f61607049d1a28ccb0e6bd0ab6ce9e278b5" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-faa9eee3d033096e147baf97cd7f5300545ece5d833a9fee95e41bda631e4965" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-ef16eb46ee4c77f8f5431cf5d5f69299cd96145ac4fd34308946781d3793bd7c" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-6f54d5945a1770fd582051241b606e273e62d10ee546ed27512a312dd12553da" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-871a4ad07e1d31a29b10e6129393236395b148d199c52350aa8ec4652543b522" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-6347ab100d9ed7da25ae4a85d3af5e696c0b879a967833641d19446bd9bd0a2a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-09ecbceb074898be958e9a7ac482230d3ada42dc3db94792c829d0a8dcc9ed83" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-9f5fdaf7c7a37ab72c777463690eeed9daf9cbff710a0b1d2ac146fc94df4c9b" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-2.3-r1", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-alpine-keys-efa8032a4839ecc3a9a121576cd74cd088ba82ea4e57bb4121e607cd0b8ed936" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-87c4547311a1d5b80f46214960e323acf8fb7a533c6e74d7b98fab4fcf750949" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-3f4157f9078d158b7e396177d85c8fb53f29a76545f2d340eb3adf4a9e7a1885" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-bb9c6bc3fb34848a938fd0f2a7ef7ebb8c713a31a87c66fd12b5ce6264bd3ab4" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-2bf2700ffc065ab6321946f53d462f79fed08a36e9f96721282cb7e0b0d798a4" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-896ed65f3b54897b064db7577043fb6a62eae8c02e5a57e51fb7ef352d5b616a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-c309689ef6f2432e55b81fdb6e139e2857ba1aba16ea4270daa3f5ab68181cd3" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-b79f7b1a48aea6d3205a9a3ae1dd44f4f5a60c3b243c672230d25b46c527ef40" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-57bc3277a6135981afff45d68e8740aaa312055223095d2211808b09a7965fba" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-018076f20178b3bf76d8270b980ca52fcb8d4d20b397e43df5db5d59874fbf58" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-2.12.7-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-apk-tools-a321a876b1cd473d1d97451f2820363efc7ab8ee27a81dff25fe6657d797677c" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-808dd192d3243666b6f1ad4f9bfeca4877ee059456c40851a93937331b26014c" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-720be4f35da16d0da39268d0059b7e8334a1010c212ec8f1175540669a40f61f" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-77bafa9e3a8a092afc4f1dd84e6e1cc58b68f42eb934bf0f6b73deb2518f78a3" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-7534754c804f9d940a7292f91accecd4c8db85ae63115ebf2ac11a0ca5605de2" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-1295836f682f19d49120419ca2e00407bcae6b1637415cf0c7ee6a6864b8020d" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-3cb4ecfa96c3717bf40df048eb527ae369def49fd83f58883951116e1fa1670a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-164f2d1bdb81aec3400edda6615ea6006559786396f358d2128101fdde23e79e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-f5067a79d8e5ded77c953ca3af252eca521f8c03c9fec20c85c42cab427f98d8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-3d5a22b80f0bdb989db1b36ca2e5b6025cf4c3e297ff2798a5c05a2c254eb19e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-14e352a2ba6dbb578d0c1f896a954208ee7dbf4614bde867f93103b95545e54f" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-03e028932ed7076cd6db28b85a5700ca88bd0ae00410f61429ed3925ffee2e4a" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-8755c6b849aa8fb7e20c7b5172abcfe0c2c19e897f0ad2ef7ebab9e8acecc307" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-50b7b0a21325d57043679d2206e62c26ec02b73128a9a0dffc53e52885d039c2" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-586c7ec4b9fbcf6ea0c92dee4ec8b71575ed9529d0c0213684297010e81d7da3" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-d057a0120ff2ab94243ad477a65ae645ab92259a1cacd1b0cbf78d76346ccd12" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-e9671acd244849c57167c658fa2f969752048f7ab184a3dcf5c46cb4d56ae124" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-829eb242159232e7d47951730a06f83f7be1c901fa7f990c33e8b7c1c8173b79" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-10b2079988256c145bab6b179d480509efb438bf10d508150b59cc3ffc009ab3" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-4cf116134c8172c74ce330c5923f36b95f95a8823fe5824d17a8e10f7990d372" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-80c6e9799c5a801c8c18ac72900403b677899f126d0f681bc6cfb5b29813cda2" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-c309689ef6f2432e55b81fdb6e139e2857ba1aba16ea4270daa3f5ab68181cd3" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-b79f7b1a48aea6d3205a9a3ae1dd44f4f5a60c3b243c672230d25b46c527ef40" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-57bc3277a6135981afff45d68e8740aaa312055223095d2211808b09a7965fba" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-018076f20178b3bf76d8270b980ca52fcb8d4d20b397e43df5db5d59874fbf58" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-busybox-0c20a49b2af2956d6540baa5865787a8dd9947410aab18eaa80098ff75a6757b" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ca-certificates-bundle-20191127-r5", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-ca-certificates-bundle-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ca-certificates-bundle-20191127-r5", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-ca-certificates-bundle-8b6554cf4168c3e562d168c8a781a831294b6cc9872eb7165b234b334fc80ff1" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ca-certificates-bundle-20191127-r5", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-ca-certificates-bundle-a9abc3ef3bbbabdce6468df2ab5ed25caab150df4beefd65c246fdf6b15a7677" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ca-certificates-bundle-20191127-r5", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-ca-certificates-bundle-bd8ae46e651cb3986dd212d98d6b746022a56c6d62f441adefd1898265c30f6e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ca-certificates-bundle-20191127-r5", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-ca-certificates-bundle-b583d63728636e5fa4b2ec89e062e655992406c08430f1b44b12e33fc357b80e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-2824684de3d1a19390ca88cf826e77c6f750657e552edb83d466666c37521a08" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-8b6554cf4168c3e562d168c8a781a831294b6cc9872eb7165b234b334fc80ff1" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-bd8ae46e651cb3986dd212d98d6b746022a56c6d62f441adefd1898265c30f6e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-1b5d1aceec5c5574bdb154f02ba90f0065943419ec0c9637ea673a7b72ba8ae8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-bf105812bacf051dd9c91886610bd0f59139c04f5051964c57c880ce66a1dc20" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-b04e1932acec52946ff06d74ea56dcb848c449688d9d2a87c27277c0143edb35" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-bc5cfefdcd1dc36b26b32bb31673f11c97559b78280bde82b89f6c5baed66cfd" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-86ba9a02fbedfecd54600b4498844eb8b61fb6679c33b9dd1d6a8c585622bfe8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-86e61f466a55cfb1c7807c66cf9d6aef8eeb4345b47ae30e81c30e809763baaa" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-d0a581b15648f37d1e89a70c47bca5a4ffc9bd533c3c5f747326e19496fe23bb" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-6f4eba22515a1cc75dc8022b7327f3cd9cd6ce9ef89dda2712d3db9be3c3c6b2" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-9d348aef994196518b59ced347de2b81b3df16f83f384d7a17fd642513a0996e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-01f1138a2d006757fb5698dd8e786f9b8cfe5326ca9855ed0b7df858571af416" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-d434b4074bf223c1efb9e41014702b9baeb1e80465eed74b77f3b2530d2a997f" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-61b7c086a62c6c726097636440eefea271494726621c661732f9482155658e59" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-9a2742b9a89ab1e1be6bda2dce46432e19112e05c7026161ecfec01c1fcea2d0" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-aa621774a15e27ad774c187bc60c0b9acf4ab096b50419ed45b7867eba9e78bd" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libcrypto1.1-dc16029d3f8ba2ba44b8eecefcc60be56e29fd757df2d465c2ef802544c3b154" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libretls-3.3.3p1-r2", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libretls-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libretls-3.3.3p1-r2", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libretls-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libretls-3.3.3p1-r2", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libretls-5e6485633ddf6bd002b8f23aa797bc1d0a96a988ce9b5cc8620b03a97eff8504" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libretls-3.3.3p1-r2", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libretls-8b174b2ffa244d547e25a8e162f826756c918cd488d99fe354d28005ffac6eae" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libssl1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libssl1.1-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libssl1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libssl1.1-58b41aa51e3d489042433ea7106d75bae94f893cbb12c96f626b29f6ed319d11" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libssl1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libssl1.1-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libssl1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libssl1.1-5289cd0f221ee1de420da77318a67f1263ad9bd146c64a9b41544e06ed6678f8" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libssl1.1-1.1.1l-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-libssl1.1-bbe61f6803028095b80deafe7cadce3a79dfd0dca1edeba92904d28acbf827bb" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-65468fa8c77bfff2cb7856a0282b85183408468a121e145652772ca706a5dc25" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-e47e360e16a817e5eedb97ff32694c95649853533f4b1ceff862a18e7bb39372" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-utils-af686b9ed0603971c45065a1ff21b215c6b29858af059f4f98fd9f91c36fad73" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-utils-8f48ac85f462686b419ebe87755d0d1fcf018f47d88c2c29f99b1d92dfe9de7d" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-utils-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-utils-33629c0e654360bfd8ab5089302a26e27dce5044d624b22f51fcbc66f1e0d19c" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-utils-8b7b11929b7ad4b8d3f64f327f89ddc2f3c118d2d05dd132c82764532ddce438" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-utils-9129db0a5e4e1bdc7665e5150d0ed1f60b7bf22898c4242d393705f1f047f7b2" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-utils-b9a8ae5bfbc0f7ca06b7d1ad3cb18f45eefb88bf0ff88d0f0b00b9c21da4ec6e" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-1.2.2-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-musl-utils-3c7dc4450288ac204d7ec8350cf59d457e73b3c577c39ad1ffc22fa3b95c4c27" + }, + { + "spdxElementId": "SPDXRef-Package-apk-scanelf-1.3.2-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-scanelf-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961" + }, + { + "spdxElementId": "SPDXRef-Package-apk-scanelf-1.3.2-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-scanelf-33629c0e654360bfd8ab5089302a26e27dce5044d624b22f51fcbc66f1e0d19c" + }, + { + "spdxElementId": "SPDXRef-Package-apk-scanelf-1.3.2-r0", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-scanelf-ef9b1f801da4d431c07d16d8a519cebb8372e455698701c070e4b3ab746ddbff" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ssl_client-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-ssl_client-894d731f69bb61966f9ca61d0762a37bc542e0bbe4ba7c931fc75129c2229961" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ssl_client-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-ssl_client-33629c0e654360bfd8ab5089302a26e27dce5044d624b22f51fcbc66f1e0d19c" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ssl_client-1.33.1-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-ssl_client-c4c6145958cc1be35e3d13487ec423cdf20e95c24b14eed9bf424f78b84beb66" + }, + { + "spdxElementId": "SPDXRef-Package-apk-zlib-1.2.11-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-zlib-4b2f4473e24574e8f7e12b6eaeb2210f9987d5836ca53404b80edb821c973b37" + }, + { + "spdxElementId": "SPDXRef-Package-apk-zlib-1.2.11-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-zlib-a61bff49f837ddc87212fb7514e9daa60f221148f83ae4860f2803d62f8ba769" + }, + { + "spdxElementId": "SPDXRef-Package-apk-zlib-1.2.11-r3", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-File-zlib-cd0bd4fb5333d3da7dd14777edebc5b789b31d402b8c08a35f505cb60112f286" + } + ] +} diff --git a/internal/formats/test-fixtures/alpine-syft.json b/internal/formats/test-fixtures/alpine-syft.json new file mode 100644 index 00000000000..936f6d5150e --- /dev/null +++ b/internal/formats/test-fixtures/alpine-syft.json @@ -0,0 +1,1846 @@ +{ + "artifacts": [ + { + "id": "880965c7-95ff-483c-80bb-22799bbbee63", + "name": "alpine-baselayout", + "version": "3.2.0-r16", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "GPL-2.0-only" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "cpe:2.3:a:alpine_baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "cpe:2.3:a:alpine_baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "cpe:2.3:a:alpine:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*", + "cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/alpine-baselayout@3.2.0-r16?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "alpine-baselayout", + "originPackage": "alpine-baselayout", + "maintainer": "Natanael Copa ", + "version": "3.2.0-r16", + "license": "GPL-2.0-only", + "architecture": "x86_64", + "url": "https://git.alpinelinux.org/cgit/aports/tree/main/alpine-baselayout", + "description": "Alpine base dir structure and init scripts", + "size": 20716, + "installedSize": 413696, + "pullDependencies": "/bin/sh so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1UJtB9cNV4r+/VbxySkEei++qbho=", + "gitCommitOfApkPort": "8a8c96a0ea2fcd824c361aa4438763fa33ee8ca0", + "files": [ + { + "path": "/dev" + }, + { + "path": "/dev/pts" + }, + { + "path": "/dev/shm" + }, + { + "path": "/etc" + }, + { + "path": "/etc/fstab", + "digest": { + "algorithm": "sha1", + "value": "Q11Q7hNe8QpDS531guqCdrXBzoA/o=" + } + }, + { + "path": "/etc/group", + "digest": { + "algorithm": "sha1", + "value": "Q13K+olJg5ayzHSVNUkggZJXuB+9Y=" + } + }, + { + "path": "/etc/hostname", + "digest": { + "algorithm": "sha1", + "value": "Q16nVwYVXP/tChvUPdukVD2ifXOmc=" + } + }, + { + "path": "/etc/hosts", + "digest": { + "algorithm": "sha1", + "value": "Q1BD6zJKZTRWyqGnPi4tSfd3krsMU=" + } + }, + { + "path": "/etc/inittab", + "digest": { + "algorithm": "sha1", + "value": "Q1TsthbhW7QzWRe1E/NKwTOuD4pHc=" + } + }, + { + "path": "/etc/modules", + "digest": { + "algorithm": "sha1", + "value": "Q1toogjUipHGcMgECgPJX64SwUT1M=" + } + }, + { + "path": "/etc/motd", + "digest": { + "algorithm": "sha1", + "value": "Q1XmduVVNURHQ27TvYp1Lr5TMtFcA=" + } + }, + { + "path": "/etc/mtab", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1kiljhXXH1LlQroHsEJIkPZg2eiw=" + } + }, + { + "path": "/etc/passwd", + "digest": { + "algorithm": "sha1", + "value": "Q1TchuuLUfur0izvfZQZxgN/LJhB8=" + } + }, + { + "path": "/etc/profile", + "digest": { + "algorithm": "sha1", + "value": "Q1VmHPWPjjvz4oCsbmYCUB4uWpSkc=" + } + }, + { + "path": "/etc/protocols", + "digest": { + "algorithm": "sha1", + "value": "Q1omKlp3vgGq2ZqYzyD/KHNdo8rDc=" + } + }, + { + "path": "/etc/services", + "digest": { + "algorithm": "sha1", + "value": "Q19WLCv5ItKg4MH7RWfNRh1I7byQc=" + } + }, + { + "path": "/etc/shadow", + "ownerUid": "0", + "ownerGid": "42", + "permissions": "640", + "digest": { + "algorithm": "sha1", + "value": "Q1ltrPIAW2zHeDiajsex2Bdmq3uqA=" + } + }, + { + "path": "/etc/shells", + "digest": { + "algorithm": "sha1", + "value": "Q1ojm2YdpCJ6B/apGDaZ/Sdb2xJkA=" + } + }, + { + "path": "/etc/sysctl.conf", + "digest": { + "algorithm": "sha1", + "value": "Q14upz3tfnNxZkIEsUhWn7Xoiw96g=" + } + }, + { + "path": "/etc/apk" + }, + { + "path": "/etc/conf.d" + }, + { + "path": "/etc/crontabs" + }, + { + "path": "/etc/crontabs/root", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "600", + "digest": { + "algorithm": "sha1", + "value": "Q1vfk1apUWI4yLJGhhNRd0kJixfvY=" + } + }, + { + "path": "/etc/init.d" + }, + { + "path": "/etc/modprobe.d" + }, + { + "path": "/etc/modprobe.d/aliases.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1WUbh6TBYNVK7e4Y+uUvLs/7viqk=" + } + }, + { + "path": "/etc/modprobe.d/blacklist.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1xxYGU6S6TLQvb7ervPrWWwAWqMg=" + } + }, + { + "path": "/etc/modprobe.d/i386.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1pnay/njn6ol9cCssL7KiZZ8etlc=" + } + }, + { + "path": "/etc/modprobe.d/kms.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1ynbLn3GYDpvajba/ldp1niayeog=" + } + }, + { + "path": "/etc/modules-load.d" + }, + { + "path": "/etc/network" + }, + { + "path": "/etc/network/if-down.d" + }, + { + "path": "/etc/network/if-post-down.d" + }, + { + "path": "/etc/network/if-pre-up.d" + }, + { + "path": "/etc/network/if-up.d" + }, + { + "path": "/etc/opt" + }, + { + "path": "/etc/periodic" + }, + { + "path": "/etc/periodic/15min" + }, + { + "path": "/etc/periodic/daily" + }, + { + "path": "/etc/periodic/hourly" + }, + { + "path": "/etc/periodic/monthly" + }, + { + "path": "/etc/periodic/weekly" + }, + { + "path": "/etc/profile.d" + }, + { + "path": "/etc/profile.d/README", + "digest": { + "algorithm": "sha1", + "value": "Q135OWsCzzvnB2fmFx62kbqm1Ax1k=" + } + }, + { + "path": "/etc/profile.d/color_prompt.sh.disabled", + "digest": { + "algorithm": "sha1", + "value": "Q10wL23GuSCVfumMRgakabUI6EsSk=" + } + }, + { + "path": "/etc/profile.d/locale.sh", + "digest": { + "algorithm": "sha1", + "value": "Q1S8j+WW71mWxfVy8ythqU7HUVoBw=" + } + }, + { + "path": "/etc/sysctl.d" + }, + { + "path": "/home" + }, + { + "path": "/lib" + }, + { + "path": "/lib/firmware" + }, + { + "path": "/lib/mdev" + }, + { + "path": "/lib/modules-load.d" + }, + { + "path": "/lib/sysctl.d" + }, + { + "path": "/lib/sysctl.d/00-alpine.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1HpElzW1xEgmKfERtTy7oommnq6c=" + } + }, + { + "path": "/media" + }, + { + "path": "/media/cdrom" + }, + { + "path": "/media/floppy" + }, + { + "path": "/media/usb" + }, + { + "path": "/mnt" + }, + { + "path": "/opt" + }, + { + "path": "/proc" + }, + { + "path": "/root", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "700" + }, + { + "path": "/run" + }, + { + "path": "/sbin" + }, + { + "path": "/sbin/mkmntdirs", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1VcFI6coRl6HWWVShMW+G5Sb3JH8=" + } + }, + { + "path": "/srv" + }, + { + "path": "/sys" + }, + { + "path": "/tmp", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "1777" + }, + { + "path": "/usr" + }, + { + "path": "/usr/lib" + }, + { + "path": "/usr/lib/modules-load.d" + }, + { + "path": "/usr/local" + }, + { + "path": "/usr/local/bin" + }, + { + "path": "/usr/local/lib" + }, + { + "path": "/usr/local/share" + }, + { + "path": "/usr/sbin" + }, + { + "path": "/usr/share" + }, + { + "path": "/usr/share/man" + }, + { + "path": "/usr/share/misc" + }, + { + "path": "/var" + }, + { + "path": "/var/run", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q11/SNZz/8cK2dSKK+cJpVrZIuF4Q=" + } + }, + { + "path": "/var/cache" + }, + { + "path": "/var/cache/misc" + }, + { + "path": "/var/empty", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "555" + }, + { + "path": "/var/lib" + }, + { + "path": "/var/lib/misc" + }, + { + "path": "/var/local" + }, + { + "path": "/var/lock" + }, + { + "path": "/var/lock/subsys" + }, + { + "path": "/var/log" + }, + { + "path": "/var/mail" + }, + { + "path": "/var/opt" + }, + { + "path": "/var/spool" + }, + { + "path": "/var/spool/mail", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1dzbdazYZA2nTzSIG3YyNw7d4Juc=" + } + }, + { + "path": "/var/spool/cron" + }, + { + "path": "/var/spool/cron/crontabs", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1OFZt+ZMp7j0Gny0rqSKuWJyqYmA=" + } + }, + { + "path": "/var/tmp", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "1777" + } + ] + } + }, + { + "id": "8dbd8f4d-c13f-4120-8c2b-4596e5c46fce", + "name": "alpine-keys", + "version": "2.3-r1", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "MIT" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*", + "cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*", + "cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*", + "cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*", + "cpe:2.3:a:alpine:alpine-keys:2.3-r1:*:*:*:*:*:*:*", + "cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/alpine-keys@2.3-r1?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "alpine-keys", + "originPackage": "alpine-keys", + "maintainer": "Natanael Copa ", + "version": "2.3-r1", + "license": "MIT", + "architecture": "x86_64", + "url": "https://alpinelinux.org", + "description": "Public keys for Alpine Linux packages", + "size": 5988, + "installedSize": 118784, + "pullDependencies": "", + "pullChecksum": "Q1ZV5wTtRXerQz0CBrwtKcvErpPeY=", + "gitCommitOfApkPort": "0972396a79fd723a429e518120fdf7ab48407468", + "files": [ + { + "path": "/etc" + }, + { + "path": "/etc/apk" + }, + { + "path": "/etc/apk/keys" + }, + { + "path": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1OvCFSO94z97c80mIDCxqGkh2Og4=" + } + }, + { + "path": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1v7YWZYzAWoclaLDI45jEguI7YN0=" + } + }, + { + "path": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1NnGuDsdQOx4ZNYfB3N97eLyGPkI=" + } + }, + { + "path": "/usr" + }, + { + "path": "/usr/share" + }, + { + "path": "/usr/share/apk" + }, + { + "path": "/usr/share/apk/keys" + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1OvCFSO94z97c80mIDCxqGkh2Og4=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1v7YWZYzAWoclaLDI45jEguI7YN0=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1BTqS+H/UUyhQuzHwiBl47+BTKuU=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1NnGuDsdQOx4ZNYfB3N97eLyGPkI=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1Oaxdcsa6AYoPdLi0U4lO3J2we18=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1yPq+su65ksNox3uXB+DR7P18+QU=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1MpZDNX0LeLHvSOwVUyXiXx11NN0=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1glCQ/eJbvA5xqcswdjFrWv5Fnk0=" + } + }, + { + "path": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub", + "digest": { + "algorithm": "sha1", + "value": "Q1XUdDEoNTtjlvrS+iunk6ziFgIpU=" + } + }, + { + "path": "/usr/share/apk/keys/aarch64" + }, + { + "path": "/usr/share/apk/keys/aarch64/alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q17j9nWJkQ+wfIuVQzIFrmFZ7fSOc=" + } + }, + { + "path": "/usr/share/apk/keys/armhf" + }, + { + "path": "/usr/share/apk/keys/armhf/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1U9QtsdN+rYZ9Zh76EfXy00JZHMg=" + } + }, + { + "path": "/usr/share/apk/keys/armv7" + }, + { + "path": "/usr/share/apk/keys/armv7/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1U9QtsdN+rYZ9Zh76EfXy00JZHMg=" + } + }, + { + "path": "/usr/share/apk/keys/mips64" + }, + { + "path": "/usr/share/apk/keys/mips64/alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1hCZdFx+LvzbLtPs753je78gEEBQ=" + } + }, + { + "path": "/usr/share/apk/keys/ppc64le" + }, + { + "path": "/usr/share/apk/keys/ppc64le/alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1t21dhCLbTJmAHXSCeOMq/2vfSgo=" + } + }, + { + "path": "/usr/share/apk/keys/riscv64" + }, + { + "path": "/usr/share/apk/keys/riscv64/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1NVPbZavaXpsItFwQYDWbpor7yYE=" + } + }, + { + "path": "/usr/share/apk/keys/s390x" + }, + { + "path": "/usr/share/apk/keys/s390x/alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1sjbV2r2w0Ih2vwdzC4Jq6UI7cMQ=" + } + }, + { + "path": "/usr/share/apk/keys/x86" + }, + { + "path": "/usr/share/apk/keys/x86/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1Ii51i7Nrc4uft14HhqugaUqdH64=" + } + }, + { + "path": "/usr/share/apk/keys/x86/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1Y49eVxhpvftbQ3yAdvlLfcrPLTU=" + } + }, + { + "path": "/usr/share/apk/keys/x86_64" + }, + { + "path": "/usr/share/apk/keys/x86_64/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1Ii51i7Nrc4uft14HhqugaUqdH64=" + } + }, + { + "path": "/usr/share/apk/keys/x86_64/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1AUFY+fwSBTcrYetjT7NHvafrSQc=" + } + } + ] + } + }, + { + "id": "b03a5cd0-e8e4-4a0c-b283-86b4942b4cfc", + "name": "apk-tools", + "version": "2.12.7-r0", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "GPL-2.0-only" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:apk-tools:apk-tools:2.12.7-r0:*:*:*:*:*:*:*", + "cpe:2.3:a:apk-tools:apk_tools:2.12.7-r0:*:*:*:*:*:*:*", + "cpe:2.3:a:apk_tools:apk-tools:2.12.7-r0:*:*:*:*:*:*:*", + "cpe:2.3:a:apk_tools:apk_tools:2.12.7-r0:*:*:*:*:*:*:*", + "cpe:2.3:a:apk:apk-tools:2.12.7-r0:*:*:*:*:*:*:*", + "cpe:2.3:a:apk:apk_tools:2.12.7-r0:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/apk-tools@2.12.7-r0?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "apk-tools", + "originPackage": "apk-tools", + "maintainer": "Natanael Copa ", + "version": "2.12.7-r0", + "license": "GPL-2.0-only", + "architecture": "x86_64", + "url": "https://gitlab.alpinelinux.org/alpine/apk-tools", + "description": "Alpine Package Keeper - package manager for alpine", + "size": 119979, + "installedSize": 311296, + "pullDependencies": "musl>=1.2 so:libc.musl-x86_64.so.1 so:libcrypto.so.1.1 so:libssl.so.1.1 so:libz.so.1", + "pullChecksum": "Q1VnSoy5XasRtvFODOZ9P0pZG4Hxs=", + "gitCommitOfApkPort": "03c6b1b0ec20f417cee0f3c1d56795b27871b1c5", + "files": [ + { + "path": "/etc" + }, + { + "path": "/etc/apk" + }, + { + "path": "/etc/apk/keys" + }, + { + "path": "/etc/apk/protected_paths.d" + }, + { + "path": "/lib" + }, + { + "path": "/lib/libapk.so.3.12.0", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1fg+B1BJHpxBSS5dRPU+3zeeuFI4=" + } + }, + { + "path": "/sbin" + }, + { + "path": "/sbin/apk", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1LugZocafK9LifJwfELs3VqdEIxw=" + } + }, + { + "path": "/var" + }, + { + "path": "/var/cache" + }, + { + "path": "/var/cache/misc" + }, + { + "path": "/var/lib" + }, + { + "path": "/var/lib/apk" + } + ] + } + }, + { + "id": "cb3f3296-98d8-4e88-bf0a-3bdc53f817fb", + "name": "busybox", + "version": "1.33.1-r3", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "GPL-2.0-only" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:busybox:busybox:1.33.1-r3:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/busybox@1.33.1-r3?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "busybox", + "originPackage": "busybox", + "maintainer": "Natanael Copa ", + "version": "1.33.1-r3", + "license": "GPL-2.0-only", + "architecture": "x86_64", + "url": "https://busybox.net/", + "description": "Size optimized toolbox of many common UNIX utilities", + "size": 499368, + "installedSize": 950272, + "pullDependencies": "so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1rGvmeXEbASEg01DqEqMbxV0fts4=", + "gitCommitOfApkPort": "98710256acf90e670e79f32f1f0350b830979d24", + "files": [ + { + "path": "/bin" + }, + { + "path": "/bin/busybox", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q135CE+2ocG61L7La8CI3kfLURucU=" + } + }, + { + "path": "/bin/sh", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1pcfTfDNEbNKQc2s1tia7da05M8Q=" + } + }, + { + "path": "/etc" + }, + { + "path": "/etc/securetty", + "digest": { + "algorithm": "sha1", + "value": "Q1mB95Hq2NUTZ599RDiSsj9w5FrOU=" + } + }, + { + "path": "/etc/udhcpd.conf", + "digest": { + "algorithm": "sha1", + "value": "Q1UAiPZcDIW1ClRzobfggcCQ77V28=" + } + }, + { + "path": "/etc/logrotate.d" + }, + { + "path": "/etc/logrotate.d/acpid", + "digest": { + "algorithm": "sha1", + "value": "Q1TylyCINVmnS+A/Tead4vZhE7Bks=" + } + }, + { + "path": "/etc/network" + }, + { + "path": "/etc/network/if-down.d" + }, + { + "path": "/etc/network/if-post-down.d" + }, + { + "path": "/etc/network/if-post-up.d" + }, + { + "path": "/etc/network/if-pre-down.d" + }, + { + "path": "/etc/network/if-pre-up.d" + }, + { + "path": "/etc/network/if-up.d" + }, + { + "path": "/etc/network/if-up.d/dad", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "775", + "digest": { + "algorithm": "sha1", + "value": "Q1ORf+lPRKuYgdkBBcKoevR1t60Q4=" + } + }, + { + "path": "/sbin" + }, + { + "path": "/tmp", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "1777" + }, + { + "path": "/usr" + }, + { + "path": "/usr/sbin" + }, + { + "path": "/usr/share" + }, + { + "path": "/usr/share/udhcpc" + }, + { + "path": "/usr/share/udhcpc/default.script", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1t9vir/ZrX3nbSIYT9BDLWZenkVQ=" + } + }, + { + "path": "/var" + }, + { + "path": "/var/cache" + }, + { + "path": "/var/cache/misc" + }, + { + "path": "/var/lib" + }, + { + "path": "/var/lib/udhcpd" + } + ] + } + }, + { + "id": "bdac28cf-4448-43d1-bdb6-1b6e8df0a2d3", + "name": "ca-certificates-bundle", + "version": "20191127-r5", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "MPL-2.0", + "AND", + "MIT" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:ca-certificates-bundle:ca-certificates-bundle:20191127-r5:*:*:*:*:*:*:*", + "cpe:2.3:a:ca-certificates-bundle:ca_certificates_bundle:20191127-r5:*:*:*:*:*:*:*", + "cpe:2.3:a:ca_certificates_bundle:ca-certificates-bundle:20191127-r5:*:*:*:*:*:*:*", + "cpe:2.3:a:ca_certificates_bundle:ca_certificates_bundle:20191127-r5:*:*:*:*:*:*:*", + "cpe:2.3:a:ca-certificates:ca-certificates-bundle:20191127-r5:*:*:*:*:*:*:*", + "cpe:2.3:a:ca-certificates:ca_certificates_bundle:20191127-r5:*:*:*:*:*:*:*", + "cpe:2.3:a:ca_certificates:ca-certificates-bundle:20191127-r5:*:*:*:*:*:*:*", + "cpe:2.3:a:ca_certificates:ca_certificates_bundle:20191127-r5:*:*:*:*:*:*:*", + "cpe:2.3:a:ca:ca-certificates-bundle:20191127-r5:*:*:*:*:*:*:*", + "cpe:2.3:a:ca:ca_certificates_bundle:20191127-r5:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/ca-certificates-bundle@20191127-r5?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "ca-certificates-bundle", + "originPackage": "ca-certificates", + "maintainer": "Natanael Copa ", + "version": "20191127-r5", + "license": "MPL-2.0 AND MIT", + "architecture": "x86_64", + "url": "https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/", + "description": "Pre generated bundle of Mozilla certificates", + "size": 124473, + "installedSize": 233472, + "pullDependencies": "", + "pullChecksum": "Q1bQ4InxwFIUUNl11tjOwqrqAeAIA=", + "gitCommitOfApkPort": "51999ab9304ec11c68c4ea9e99350ac7570e7f21", + "files": [ + { + "path": "/etc" + }, + { + "path": "/etc/ssl" + }, + { + "path": "/etc/ssl/cert.pem", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1Nj6gTBdkZpTFW/obJGdpfvK0StA=" + } + }, + { + "path": "/etc/ssl/certs" + }, + { + "path": "/etc/ssl/certs/ca-certificates.crt", + "digest": { + "algorithm": "sha1", + "value": "Q1yxhc/Gjt/YEWliIZBXQz/RBrszU=" + } + } + ] + } + }, + { + "id": "ef75a96d-f7be-45fa-abf0-a66c2779cfee", + "name": "libc-utils", + "version": "0.7.2-r3", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "BSD-2-Clause", + "AND", + "BSD-3-Clause" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:libc-utils:libc-utils:0.7.2-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:libc-utils:libc_utils:0.7.2-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:libc_utils:libc-utils:0.7.2-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:libc_utils:libc_utils:0.7.2-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:libc:libc-utils:0.7.2-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:libc:libc_utils:0.7.2-r3:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/libc-utils@0.7.2-r3?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "libc-utils", + "originPackage": "libc-dev", + "maintainer": "Natanael Copa ", + "version": "0.7.2-r3", + "license": "BSD-2-Clause AND BSD-3-Clause", + "architecture": "x86_64", + "url": "https://alpinelinux.org", + "description": "Meta package to pull in correct libc", + "size": 1228, + "installedSize": 4096, + "pullDependencies": "musl-utils", + "pullChecksum": "Q1UsLZaz0/Go44hd4Vw49UCt40Vp8=", + "gitCommitOfApkPort": "60424133be2e79bbfeff3d58147a22886f817ce2", + "files": [] + } + }, + { + "id": "bb1fd421-fb64-499b-bc59-fe67b8553c1d", + "name": "libcrypto1.1", + "version": "1.1.1l-r0", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "OpenSSL" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:libcrypto1.1:libcrypto1.1:1.1.1l-r0:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/libcrypto1.1@1.1.1l-r0?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "libcrypto1.1", + "originPackage": "openssl", + "maintainer": "Timo Teras ", + "version": "1.1.1l-r0", + "license": "OpenSSL", + "architecture": "x86_64", + "url": "https://www.openssl.org/", + "description": "Crypto library from openssl", + "size": 1211998, + "installedSize": 2768896, + "pullDependencies": "so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1Sywj1TEYEdvX0+MuqC+ea+zXxR0=", + "gitCommitOfApkPort": "3ef1965150d5b1de4af88dc51cf407e11b20b848", + "files": [ + { + "path": "/etc" + }, + { + "path": "/etc/ssl" + }, + { + "path": "/etc/ssl/ct_log_list.cnf", + "digest": { + "algorithm": "sha1", + "value": "Q1olh8TpdAi2QnTl4FK3TjdUiSwTo=" + } + }, + { + "path": "/etc/ssl/ct_log_list.cnf.dist", + "digest": { + "algorithm": "sha1", + "value": "Q1olh8TpdAi2QnTl4FK3TjdUiSwTo=" + } + }, + { + "path": "/etc/ssl/openssl.cnf", + "digest": { + "algorithm": "sha1", + "value": "Q1wGuxVEOK9iGLj1i8D3BSBnT7MJA=" + } + }, + { + "path": "/etc/ssl/openssl.cnf.dist", + "digest": { + "algorithm": "sha1", + "value": "Q1wGuxVEOK9iGLj1i8D3BSBnT7MJA=" + } + }, + { + "path": "/etc/ssl/certs" + }, + { + "path": "/etc/ssl/misc" + }, + { + "path": "/etc/ssl/misc/CA.pl", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1IACevKhK93GYBHp96Ie26jgZ17s=" + } + }, + { + "path": "/etc/ssl/misc/tsget", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q13NVgfr7dQUuGYxur0tNalH6EIjU=" + } + }, + { + "path": "/etc/ssl/misc/tsget.pl", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1ufKVrFftKLv8K/vullp/2reEDdo=" + } + }, + { + "path": "/etc/ssl/private" + }, + { + "path": "/lib" + }, + { + "path": "/lib/libcrypto.so.1.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1p0rHZXV1yOM1jGs0zuNSpi951t8=" + } + }, + { + "path": "/usr" + }, + { + "path": "/usr/lib" + }, + { + "path": "/usr/lib/libcrypto.so.1.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1T2si+c7ts7sgDxQYve4B3i1Dgo0=" + } + }, + { + "path": "/usr/lib/engines-1.1" + }, + { + "path": "/usr/lib/engines-1.1/afalg.so", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q13GvceRRzjQ6bnB5laIGCkDOHTM0=" + } + }, + { + "path": "/usr/lib/engines-1.1/capi.so", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1h8YLf+3MhbqdHUhGNEabdH5MooA=" + } + }, + { + "path": "/usr/lib/engines-1.1/padlock.so", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1TzNLJ3/GEmO9XW9XuZ/Izoy7zPk=" + } + } + ] + } + }, + { + "id": "114e7b49-1001-4d72-9f2e-086e0aa5a8b7", + "name": "libretls", + "version": "3.3.3p1-r2", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "ISC", + "AND", + "(BSD-3-Clause", + "OR", + "MIT)" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:libretls:libretls:3.3.3p1-r2:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/libretls@3.3.3p1-r2?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "libretls", + "originPackage": "libretls", + "maintainer": "Ariadne Conill ", + "version": "3.3.3p1-r2", + "license": "ISC AND (BSD-3-Clause OR MIT)", + "architecture": "x86_64", + "url": "https://git.causal.agency/libretls/", + "description": "port of libtls from libressl to openssl", + "size": 28872, + "installedSize": 86016, + "pullDependencies": "ca-certificates-bundle so:libc.musl-x86_64.so.1 so:libcrypto.so.1.1 so:libssl.so.1.1", + "pullChecksum": "Q1mKL75PNQ3352oQUtXLS8GfI+37M=", + "gitCommitOfApkPort": "161d02ee8c48f3c3cae1d2b4b5d008fa318da0e1", + "files": [ + { + "path": "/usr" + }, + { + "path": "/usr/lib" + }, + { + "path": "/usr/lib/libtls.so.2", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1nNEC9T/t6W+Ecm0DxqMUnRvcT6k=" + } + }, + { + "path": "/usr/lib/libtls.so.2.0.3", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1t1MtXTHs0kMZ9+GCPJLriysmtA8=" + } + } + ] + } + }, + { + "id": "ed01e864-9235-4b28-b69a-4c95a3c0457b", + "name": "libssl1.1", + "version": "1.1.1l-r0", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "OpenSSL" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:libssl1.1:libssl1.1:1.1.1l-r0:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/libssl1.1@1.1.1l-r0?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "libssl1.1", + "originPackage": "openssl", + "maintainer": "Timo Teras ", + "version": "1.1.1l-r0", + "license": "OpenSSL", + "architecture": "x86_64", + "url": "https://www.openssl.org/", + "description": "SSL shared libraries", + "size": 212918, + "installedSize": 540672, + "pullDependencies": "so:libc.musl-x86_64.so.1 so:libcrypto.so.1.1", + "pullChecksum": "Q1Fgsc0DiapwjaJHbihB9ZrLQhr7Q=", + "gitCommitOfApkPort": "3ef1965150d5b1de4af88dc51cf407e11b20b848", + "files": [ + { + "path": "/lib" + }, + { + "path": "/lib/libssl.so.1.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1qaeh6oI3hVHuFty7JD5ASOu8S8k=" + } + }, + { + "path": "/usr" + }, + { + "path": "/usr/lib" + }, + { + "path": "/usr/lib/libssl.so.1.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q18j35pe3yp6HOgMih1wlGP1/mm2c=" + } + } + ] + } + }, + { + "id": "2df82ce2-fc7f-40ce-a39b-6bac545cbba8", + "name": "musl", + "version": "1.2.2-r3", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "MIT" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:musl:musl:1.2.2-r3:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/musl@1.2.2-r3?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "musl", + "originPackage": "musl", + "maintainer": "Timo Teräs ", + "version": "1.2.2-r3", + "license": "MIT", + "architecture": "x86_64", + "url": "https://musl.libc.org/", + "description": "the musl c library (libc) implementation", + "size": 382765, + "installedSize": 622592, + "pullDependencies": "", + "pullChecksum": "Q1n4yypJ4tpU5g+jxI7oHT0Bm4Xjo=", + "gitCommitOfApkPort": "1e9cba35059e3bb4635f12ee7e10dfe687df31ad", + "files": [ + { + "path": "/lib" + }, + { + "path": "/lib/ld-musl-x86_64.so.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1cZei2MQS2nixN1UwDj0FT9qWO4U=" + } + }, + { + "path": "/lib/libc.musl-x86_64.so.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q17yJ3JFNypA4mxhJJr0ou6CzsJVI=" + } + } + ] + } + }, + { + "id": "d8ed04e1-eccd-4441-b937-e960bfffe114", + "name": "musl-utils", + "version": "1.2.2-r3", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "MIT", + "BSD", + "GPL2+" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:musl-utils:musl-utils:1.2.2-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:musl-utils:musl_utils:1.2.2-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:musl_utils:musl-utils:1.2.2-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:musl_utils:musl_utils:1.2.2-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:musl:musl-utils:1.2.2-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:musl:musl_utils:1.2.2-r3:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/musl-utils@1.2.2-r3?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "musl-utils", + "originPackage": "musl", + "maintainer": "Timo Teräs ", + "version": "1.2.2-r3", + "license": "MIT BSD GPL2+", + "architecture": "x86_64", + "url": "https://musl.libc.org/", + "description": "the musl c library (libc) implementation", + "size": 36662, + "installedSize": 147456, + "pullDependencies": "scanelf so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1WNvvoHVxRySUmjgvqQie71lLRd8=", + "gitCommitOfApkPort": "1e9cba35059e3bb4635f12ee7e10dfe687df31ad", + "files": [ + { + "path": "/sbin" + }, + { + "path": "/sbin/ldconfig", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1Kja2+POZKxEkUOZqwSjC6kmaED4=" + } + }, + { + "path": "/usr" + }, + { + "path": "/usr/bin" + }, + { + "path": "/usr/bin/getconf", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1ENetcQcXKEGU2b0TD1S+WDuwAOE=" + } + }, + { + "path": "/usr/bin/getent", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1AtbzfYTO6GHhaimM7wXWuLGcECI=" + } + }, + { + "path": "/usr/bin/iconv", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1y+KPYlKOaOdDtMOapc2sTDsPKSU=" + } + }, + { + "path": "/usr/bin/ldd", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1yFAhGggmL7ERgbIA7KQxyTzf3ks=" + } + } + ] + } + }, + { + "id": "96bf3afe-d927-4daa-91c5-7178e9462ac5", + "name": "scanelf", + "version": "1.3.2-r0", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "GPL-2.0-only" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:scanelf:scanelf:1.3.2-r0:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/scanelf@1.3.2-r0?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "scanelf", + "originPackage": "pax-utils", + "maintainer": "Natanael Copa ", + "version": "1.3.2-r0", + "license": "GPL-2.0-only", + "architecture": "x86_64", + "url": "https://wiki.gentoo.org/wiki/Hardened/PaX_Utilities", + "description": "Scan ELF binaries for stuff", + "size": 36511, + "installedSize": 94208, + "pullDependencies": "so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1OWKo0fmUbClrhW0CPNjwA8AMLWo=", + "gitCommitOfApkPort": "4c7f72840f5052bc63af1796c3ad0021f97949f2", + "files": [ + { + "path": "/usr" + }, + { + "path": "/usr/bin" + }, + { + "path": "/usr/bin/scanelf", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1LhDyQrsweSqYTuRcjhG2d0pxhrE=" + } + } + ] + } + }, + { + "id": "562ec670-5625-4c25-b8a7-ebaacf04d06c", + "name": "ssl_client", + "version": "1.33.1-r3", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "GPL-2.0-only" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:ssl-client:ssl-client:1.33.1-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:ssl-client:ssl_client:1.33.1-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:ssl_client:ssl-client:1.33.1-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:ssl_client:ssl_client:1.33.1-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:ssl:ssl-client:1.33.1-r3:*:*:*:*:*:*:*", + "cpe:2.3:a:ssl:ssl_client:1.33.1-r3:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/ssl_client@1.33.1-r3?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "ssl_client", + "originPackage": "busybox", + "maintainer": "Natanael Copa ", + "version": "1.33.1-r3", + "license": "GPL-2.0-only", + "architecture": "x86_64", + "url": "https://busybox.net/", + "description": "EXternal ssl_client for busybox wget", + "size": 4381, + "installedSize": 28672, + "pullDependencies": "so:libc.musl-x86_64.so.1 so:libtls.so.2", + "pullChecksum": "Q1d7WkMOIKXIk3qxexUxSo60HOofY=", + "gitCommitOfApkPort": "98710256acf90e670e79f32f1f0350b830979d24", + "files": [ + { + "path": "/usr" + }, + { + "path": "/usr/bin" + }, + { + "path": "/usr/bin/ssl_client", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q1gPKQTCzC1isM7R89HFwb+A1XmM4=" + } + } + ] + } + }, + { + "id": "52382e1a-320b-4e62-8103-39baa39d85b3", + "name": "zlib", + "version": "1.2.11-r3", + "type": "apk", + "foundBy": "apkdb-cataloger", + "locations": [ + { + "path": "/lib/apk/db/installed", + "layerID": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68" + } + ], + "licenses": [ + "Zlib" + ], + "language": "", + "cpes": [ + "cpe:2.3:a:zlib:zlib:1.2.11-r3:*:*:*:*:*:*:*" + ], + "purl": "pkg:alpine/zlib@1.2.11-r3?arch=x86_64", + "metadataType": "ApkMetadata", + "metadata": { + "package": "zlib", + "originPackage": "zlib", + "maintainer": "Natanael Copa ", + "version": "1.2.11-r3", + "license": "Zlib", + "architecture": "x86_64", + "url": "https://zlib.net/", + "description": "A compression/decompression Library", + "size": 51398, + "installedSize": 110592, + "pullDependencies": "so:libc.musl-x86_64.so.1", + "pullChecksum": "Q1Sc/5gG4ey/zvnyPPQ/Au7bXqc08=", + "gitCommitOfApkPort": "388a4fb3640f8ccbd18e105df3ad741dca4247e1", + "files": [ + { + "path": "/lib" + }, + { + "path": "/lib/libz.so.1", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "777", + "digest": { + "algorithm": "sha1", + "value": "Q1a2H8hP24ryCAGf8fnc1Nha9IIHc=" + } + }, + { + "path": "/lib/libz.so.1.2.11", + "ownerUid": "0", + "ownerGid": "0", + "permissions": "755", + "digest": { + "algorithm": "sha1", + "value": "Q19Iml1N+v08tnk1ZtqGEVIEtIFJI=" + } + } + ] + } + } + ], + "artifactRelationships": [], + "source": { + "type": "image", + "target": { + "userInput": "alpine:latest", + "imageID": "sha256:14119a10abf4669e8cdbdff324a9f9605d99697215a0d21c360fe8dfa8471bab", + "manifestDigest": "sha256:69704ef328d05a9f806b6b8502915e6a0a4faa4d72018dc42343f511490daf8a", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "tags": [], + "imageSize": 5590942, + "layers": [ + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "digest": "sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68", + "size": 5590942 + } + ], + "manifest": "ewogICAic2NoZW1hVmVyc2lvbiI6IDIsCiAgICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRvY2tlci5kaXN0cmlidXRpb24ubWFuaWZlc3QudjIranNvbiIsCiAgICJjb25maWciOiB7CiAgICAgICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRvY2tlci5jb250YWluZXIuaW1hZ2UudjEranNvbiIsCiAgICAgICJzaXplIjogMTQ3MSwKICAgICAgImRpZ2VzdCI6ICJzaGEyNTY6MTQxMTlhMTBhYmY0NjY5ZThjZGJkZmYzMjRhOWY5NjA1ZDk5Njk3MjE1YTBkMjFjMzYwZmU4ZGZhODQ3MWJhYiIKICAgfSwKICAgImxheWVycyI6IFsKICAgICAgewogICAgICAgICAibWVkaWFUeXBlIjogImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLAogICAgICAgICAic2l6ZSI6IDI4MTQ0NDYsCiAgICAgICAgICJkaWdlc3QiOiAic2hhMjU2OmEwZDBhMGQ0NmY4YjUyNDczOTgyYTNjNDY2MzE4ZjQ3OTc2NzU3NzU1MWE1M2ZmYzkwNzRjOWZhNzAzNTk4MmUiCiAgICAgIH0KICAgXQp9", + "config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJIb3N0bmFtZSI6IiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpbIi9iaW4vc2giXSwiSW1hZ2UiOiJzaGEyNTY6ZDNlMGI2MjU4ZWMyZjcyNWMxOTY2OGYxMWFlNTMyM2MzYjAyNDVlMTk3ZWM0Nzg0MjRlYzZhODc5MzU2OTBlYiIsIlZvbHVtZXMiOm51bGwsIldvcmtpbmdEaXIiOiIiLCJFbnRyeXBvaW50IjpudWxsLCJPbkJ1aWxkIjpudWxsLCJMYWJlbHMiOm51bGx9LCJjb250YWluZXIiOiIzMzAyODljNjQ5ZGI4NmY1ZmIxYWU1YmZlZjE4NTAxMDEyYjU1MGFkYjA2MzhiOTE5M2Q0YTNhNGI2NWEyZjliIiwiY29udGFpbmVyX2NvbmZpZyI6eyJIb3N0bmFtZSI6IjMzMDI4OWM2NDlkYiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpbIi9iaW4vc2giLCItYyIsIiMobm9wKSAiLCJDTUQgW1wiL2Jpbi9zaFwiXSJdLCJJbWFnZSI6InNoYTI1NjpkM2UwYjYyNThlYzJmNzI1YzE5NjY4ZjExYWU1MzIzYzNiMDI0NWUxOTdlYzQ3ODQyNGVjNmE4NzkzNTY5MGViIiwiVm9sdW1lcyI6bnVsbCwiV29ya2luZ0RpciI6IiIsIkVudHJ5cG9pbnQiOm51bGwsIk9uQnVpbGQiOm51bGwsIkxhYmVscyI6e319LCJjcmVhdGVkIjoiMjAyMS0wOC0yN1QxNzoxOTo0NS43NTg2MTE1MjNaIiwiZG9ja2VyX3ZlcnNpb24iOiIyMC4xMC43IiwiaGlzdG9yeSI6W3siY3JlYXRlZCI6IjIwMjEtMDgtMjdUMTc6MTk6NDUuNTUzMDkyMzYzWiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jICMobm9wKSBBREQgZmlsZTphYWQ0MjkwZDI3NTgwY2MxYTA5NGZmYWY5OGMzY2EyZmM1ZDY5OWZlNjk1ZGZiOGU2ZTlmYWMyMGYxMTI5NDUwIGluIC8gIn0seyJjcmVhdGVkIjoiMjAyMS0wOC0yN1QxNzoxOTo0NS43NTg2MTE1MjNaIiwiY3JlYXRlZF9ieSI6Ii9iaW4vc2ggLWMgIyhub3ApICBDTUQgW1wiL2Jpbi9zaFwiXSIsImVtcHR5X2xheWVyIjp0cnVlfV0sIm9zIjoibGludXgiLCJyb290ZnMiOnsidHlwZSI6ImxheWVycyIsImRpZmZfaWRzIjpbInNoYTI1NjplMmViMDZkOGFmODIxOGNmZWM4MjEwMTQ3MzU3YTY4YjdlMTNmN2M0ODViOTkxYzI4OGMyZDAxZGMyMjhiYjY4Il19fQ==", + "repoDigests": [ + "index.docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a" + ] + } + }, + "distro": { + "name": "alpine", + "version": "3.14.2", + "idLike": "" + }, + "descriptor": { + "name": "syft", + "version": "[not provided]" + }, + "schema": { + "version": "1.1.0", + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-1.1.0.json" + } +} From 50408b52d196133ed3cd66baeeaca1cfd04185f3 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:57:44 -0700 Subject: [PATCH 12/17] update integration test to reference new format options Signed-off-by: Alex Goodman --- .../package_ownership_relationship_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/integration/package_ownership_relationship_test.go b/test/integration/package_ownership_relationship_test.go index 67dfb3499c3..b2651ad9729 100644 --- a/test/integration/package_ownership_relationship_test.go +++ b/test/integration/package_ownership_relationship_test.go @@ -3,10 +3,13 @@ package integration import ( "bytes" "encoding/json" - exportedPackages "github.com/anchore/syft/syft/presenter/packages" "testing" - internalPackages "github.com/anchore/syft/internal/presenter/packages" + "github.com/anchore/syft/internal/formats/syftjson/model" + + "github.com/anchore/syft/syft/format" + + exportedPackages "github.com/anchore/syft/syft/presenter/packages" ) func TestPackageOwnershipRelationships(t *testing.T) { @@ -24,7 +27,7 @@ func TestPackageOwnershipRelationships(t *testing.T) { t.Run(test.fixture, func(t *testing.T) { catalog, d, src := catalogFixtureImage(t, test.fixture) - p := exportedPackages.Presenter(exportedPackages.JSONPresenterOption, exportedPackages.PresenterConfig{ + p := exportedPackages.Presenter(format.JSONOption, exportedPackages.Config{ SourceMetadata: src.Metadata, Catalog: catalog, Distro: d, @@ -39,7 +42,7 @@ func TestPackageOwnershipRelationships(t *testing.T) { t.Fatalf("unable to present: %+v", err) } - var doc internalPackages.JSONDocument + var doc model.Document decoder := json.NewDecoder(output) if err := decoder.Decode(&doc); err != nil { t.Fatalf("unable to decode json doc: %+v", err) From 3ca797dc53226878317247d88de9849cd659d6ec Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:58:34 -0700 Subject: [PATCH 13/17] update existing presenter tests to use the shared format test helpers Signed-off-by: Alex Goodman --- .../packages/cyclonedx_presenter_test.go | 10 +- .../presenter/packages/spdx_helpers_test.go | 527 ------------------ .../packages/spdx_tag_value_presenter.go | 6 +- .../packages/spdx_tag_value_presenter_test.go | 10 +- .../packages/table_presenter_test.go | 6 +- .../TestSPDXJSONDirectoryPresenter.golden | 79 --- .../TestSPDXJSONImagePresenter.golden | 61 -- .../presenter/packages/text_presenter_test.go | 10 +- internal/presenter/packages/utils_test.go | 199 ------- 9 files changed, 26 insertions(+), 882 deletions(-) delete mode 100644 internal/presenter/packages/spdx_helpers_test.go delete mode 100644 internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden delete mode 100644 internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden delete mode 100644 internal/presenter/packages/utils_test.go diff --git a/internal/presenter/packages/cyclonedx_presenter_test.go b/internal/presenter/packages/cyclonedx_presenter_test.go index 4914edbb445..083a72022b9 100644 --- a/internal/presenter/packages/cyclonedx_presenter_test.go +++ b/internal/presenter/packages/cyclonedx_presenter_test.go @@ -4,13 +4,15 @@ import ( "flag" "regexp" "testing" + + "github.com/anchore/syft/internal/formats/common/testutils" ) var updateCycloneDx = flag.Bool("update-cyclonedx", false, "update the *.golden files for cyclone-dx presenters") func TestCycloneDxDirectoryPresenter(t *testing.T) { - catalog, metadata, _ := presenterDirectoryInput(t) - assertPresenterAgainstGoldenSnapshot(t, + catalog, metadata, _ := testutils.DirectoryInput(t) + testutils.AssertPresenterAgainstGoldenSnapshot(t, NewCycloneDxPresenter(catalog, metadata), *updateCycloneDx, cycloneDxRedactor, @@ -19,8 +21,8 @@ func TestCycloneDxDirectoryPresenter(t *testing.T) { func TestCycloneDxImagePresenter(t *testing.T) { testImage := "image-simple" - catalog, metadata, _ := presenterImageInput(t, testImage) - assertPresenterAgainstGoldenImageSnapshot(t, + catalog, metadata, _ := testutils.ImageInput(t, testImage) + testutils.AssertPresenterAgainstGoldenImageSnapshot(t, NewCycloneDxPresenter(catalog, metadata), testImage, *updateCycloneDx, diff --git a/internal/presenter/packages/spdx_helpers_test.go b/internal/presenter/packages/spdx_helpers_test.go deleted file mode 100644 index 985e26fed4c..00000000000 --- a/internal/presenter/packages/spdx_helpers_test.go +++ /dev/null @@ -1,527 +0,0 @@ -package packages - -import ( - "testing" - - "github.com/anchore/syft/syft/source" - - "github.com/stretchr/testify/assert" - - "github.com/anchore/syft/internal/presenter/packages/model/spdx22" - "github.com/anchore/syft/syft/pkg" -) - -func Test_getSPDXExternalRefs(t *testing.T) { - testCPE := must(pkg.NewCPE("cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*")) - tests := []struct { - name string - input pkg.Package - expected []spdx22.ExternalRef - }{ - { - name: "cpe + purl", - input: pkg.Package{ - CPEs: []pkg.CPE{ - testCPE, - }, - PURL: "a-purl", - }, - expected: []spdx22.ExternalRef{ - { - ReferenceCategory: spdx22.SecurityReferenceCategory, - ReferenceLocator: testCPE.BindToFmtString(), - ReferenceType: spdx22.Cpe23ExternalRefType, - }, - { - ReferenceCategory: spdx22.PackageManagerReferenceCategory, - ReferenceLocator: "a-purl", - ReferenceType: spdx22.PurlExternalRefType, - }, - }, - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - assert.ElementsMatch(t, test.expected, getSPDXExternalRefs(&test.input)) - }) - } -} - -func Test_getSPDXLicense(t *testing.T) { - tests := []struct { - name string - input pkg.Package - expected string - }{ - { - name: "no licenses", - input: pkg.Package{}, - expected: "NONE", - }, - { - name: "no SPDX licenses", - input: pkg.Package{ - Licenses: []string{ - "made-up", - }, - }, - expected: "NOASSERTION", - }, - { - name: "with SPDX license", - input: pkg.Package{ - Licenses: []string{ - "MIT", - }, - }, - expected: "MIT", - }, - { - name: "with SPDX license expression", - input: pkg.Package{ - Licenses: []string{ - "MIT", - "GPL-3.0", - }, - }, - expected: "MIT AND GPL-3.0", - }, - { - name: "cap insensitive", - input: pkg.Package{ - Licenses: []string{ - "gpl-3.0", - }, - }, - expected: "GPL-3.0", - }, - { - name: "debian to spdx conversion", - input: pkg.Package{ - Licenses: []string{ - "GPL-2", - }, - }, - expected: "GPL-2.0", - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, getSPDXLicense(&test.input)) - }) - } -} - -func Test_noneIfEmpty(t *testing.T) { - tests := []struct { - name string - value string - expected string - }{ - { - name: "non-zero value", - value: "something", - expected: "something", - }, - { - name: "empty", - value: "", - expected: "NONE", - }, - { - name: "space", - value: " ", - expected: "NONE", - }, - { - name: "tab", - value: "\t", - expected: "NONE", - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, noneIfEmpty(test.value)) - }) - } -} - -func Test_getSPDXDownloadLocation(t *testing.T) { - tests := []struct { - name string - input pkg.Package - expected string - }{ - { - name: "no metadata", - input: pkg.Package{}, - expected: "NOASSERTION", - }, - { - name: "from apk", - input: pkg.Package{ - Metadata: pkg.ApkMetadata{ - URL: "http://a-place.gov", - }, - }, - expected: "http://a-place.gov", - }, - { - name: "from npm", - input: pkg.Package{ - Metadata: pkg.NpmPackageJSONMetadata{ - URL: "http://a-place.gov", - }, - }, - expected: "http://a-place.gov", - }, - { - name: "empty", - input: pkg.Package{ - Metadata: pkg.NpmPackageJSONMetadata{ - URL: "", - }, - }, - expected: "NONE", - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, getSPDXDownloadLocation(&test.input)) - }) - } -} - -func Test_getSPDXHomepage(t *testing.T) { - tests := []struct { - name string - input pkg.Package - expected string - }{ - { - // note: since this is an optional field, no value is preferred over NONE or NOASSERTION - name: "no metadata", - input: pkg.Package{}, - expected: "", - }, - { - name: "from gem", - input: pkg.Package{ - Metadata: pkg.GemMetadata{ - Homepage: "http://a-place.gov", - }, - }, - expected: "http://a-place.gov", - }, - { - name: "from npm", - input: pkg.Package{ - Metadata: pkg.NpmPackageJSONMetadata{ - Homepage: "http://a-place.gov", - }, - }, - expected: "http://a-place.gov", - }, - { - // note: since this is an optional field, no value is preferred over NONE or NOASSERTION - name: "empty", - input: pkg.Package{ - Metadata: pkg.NpmPackageJSONMetadata{ - Homepage: "", - }, - }, - expected: "", - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, getSPDXHomepage(&test.input)) - }) - } -} - -func Test_getSPDXSourceInfo(t *testing.T) { - tests := []struct { - name string - input pkg.Package - expected []string - }{ - { - name: "locations are captured", - input: pkg.Package{ - // note: no type given - Locations: []source.Location{ - { - RealPath: "/a-place", - VirtualPath: "/b-place", - }, - { - RealPath: "/c-place", - VirtualPath: "/d-place", - }, - }, - }, - expected: []string{ - "from the following paths", - "/a-place", - "/c-place", - }, - }, - { - // note: no specific support for this - input: pkg.Package{ - Type: pkg.KbPkg, - }, - expected: []string{ - "from the following paths", - }, - }, - { - input: pkg.Package{ - Type: pkg.RpmPkg, - }, - expected: []string{ - "from RPM DB", - }, - }, - { - input: pkg.Package{ - Type: pkg.ApkPkg, - }, - expected: []string{ - "from APK DB", - }, - }, - { - input: pkg.Package{ - Type: pkg.DebPkg, - }, - expected: []string{ - "from DPKG DB", - }, - }, - { - input: pkg.Package{ - Type: pkg.NpmPkg, - }, - expected: []string{ - "from installed node module manifest file", - }, - }, - { - input: pkg.Package{ - Type: pkg.PythonPkg, - }, - expected: []string{ - "from installed python package manifest file", - }, - }, - { - input: pkg.Package{ - Type: pkg.JavaPkg, - }, - expected: []string{ - "from installed java archive", - }, - }, - { - input: pkg.Package{ - Type: pkg.JenkinsPluginPkg, - }, - expected: []string{ - "from installed java archive", - }, - }, - { - input: pkg.Package{ - Type: pkg.GemPkg, - }, - expected: []string{ - "from installed gem metadata file", - }, - }, - { - input: pkg.Package{ - Type: pkg.GoModulePkg, - }, - expected: []string{ - "from go module information", - }, - }, - { - input: pkg.Package{ - Type: pkg.RustPkg, - }, - expected: []string{ - "from rust cargo manifest", - }, - }, - } - var pkgTypes []pkg.Type - for _, test := range tests { - t.Run(test.name+" "+string(test.input.Type), func(t *testing.T) { - if test.input.Type != "" { - pkgTypes = append(pkgTypes, test.input.Type) - } - actual := getSPDXSourceInfo(&test.input) - for _, expected := range test.expected { - assert.Contains(t, actual, expected) - } - }) - } - assert.ElementsMatch(t, pkg.AllPkgs, pkgTypes, "missing one or more package types to test against (maybe a package type was added?)") -} - -func Test_getSPDXOriginator(t *testing.T) { - tests := []struct { - name string - input pkg.Package - expected string - }{ - { - // note: since this is an optional field, no value is preferred over NONE or NOASSERTION - name: "no metadata", - input: pkg.Package{}, - expected: "", - }, - { - name: "from gem", - input: pkg.Package{ - Metadata: pkg.GemMetadata{ - Authors: []string{ - "auth1", - "auth2", - }, - }, - }, - expected: "auth1", - }, - { - name: "from npm", - input: pkg.Package{ - Metadata: pkg.NpmPackageJSONMetadata{ - Author: "auth", - }, - }, - expected: "auth", - }, - { - name: "from apk", - input: pkg.Package{ - Metadata: pkg.ApkMetadata{ - Maintainer: "auth", - }, - }, - expected: "auth", - }, - { - name: "from python - just name", - input: pkg.Package{ - Metadata: pkg.PythonPackageMetadata{ - Author: "auth", - }, - }, - expected: "auth", - }, - { - name: "from python - just email", - input: pkg.Package{ - Metadata: pkg.PythonPackageMetadata{ - AuthorEmail: "auth@auth.gov", - }, - }, - expected: "auth@auth.gov", - }, - { - name: "from python - both name and email", - input: pkg.Package{ - Metadata: pkg.PythonPackageMetadata{ - Author: "auth", - AuthorEmail: "auth@auth.gov", - }, - }, - expected: "auth ", - }, - { - name: "from rpm", - input: pkg.Package{ - Metadata: pkg.RpmdbMetadata{ - Vendor: "auth", - }, - }, - expected: "auth", - }, - { - name: "from dpkg", - input: pkg.Package{ - Metadata: pkg.DpkgMetadata{ - Maintainer: "auth", - }, - }, - expected: "auth", - }, - { - // note: since this is an optional field, no value is preferred over NONE or NOASSERTION - name: "empty", - input: pkg.Package{ - Metadata: pkg.NpmPackageJSONMetadata{ - Author: "", - }, - }, - expected: "", - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, getSPDXOriginator(&test.input)) - }) - } -} - -func Test_getSPDXDescription(t *testing.T) { - tests := []struct { - name string - input pkg.Package - expected string - }{ - { - // note: since this is an optional field, no value is preferred over NONE or NOASSERTION - name: "no metadata", - input: pkg.Package{}, - expected: "", - }, - { - name: "from apk", - input: pkg.Package{ - Metadata: pkg.ApkMetadata{ - Description: "a description!", - }, - }, - expected: "a description!", - }, - { - name: "from npm", - input: pkg.Package{ - Metadata: pkg.NpmPackageJSONMetadata{ - Description: "a description!", - }, - }, - expected: "a description!", - }, - { - // note: since this is an optional field, no value is preferred over NONE or NOASSERTION - name: "empty", - input: pkg.Package{ - Metadata: pkg.NpmPackageJSONMetadata{ - Homepage: "", - }, - }, - expected: "", - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, getSPDXDescription(&test.input)) - }) - } -} diff --git a/internal/presenter/packages/spdx_tag_value_presenter.go b/internal/presenter/packages/spdx_tag_value_presenter.go index 5f66fdf4aa9..19974ecb8f4 100644 --- a/internal/presenter/packages/spdx_tag_value_presenter.go +++ b/internal/presenter/packages/spdx_tag_value_presenter.go @@ -5,6 +5,8 @@ import ( "io" "time" + "github.com/anchore/syft/internal/formats/common/spdxhelpers" + "github.com/anchore/syft/internal/spdxlicense" "github.com/anchore/syft/internal" @@ -114,7 +116,7 @@ func (pres *SPDXTagValuePresenter) packages() map[spdx.ElementID]*spdx.Package2_ // If the Concluded License is not the same as the Declared License, a written explanation should be provided // in the Comments on License field (section 3.16). With respect to NOASSERTION, a written explanation in // the Comments on License field (section 3.16) is preferred. - license := getSPDXLicense(p) + license := spdxhelpers.License(p) results[spdx.ElementID(id)] = &spdx.Package2_2{ @@ -274,7 +276,7 @@ func (pres *SPDXTagValuePresenter) packages() map[spdx.ElementID]*spdx.Package2_ } func formatSPDXExternalRefs(p *pkg.Package) (refs []*spdx.PackageExternalReference2_2) { - for _, ref := range getSPDXExternalRefs(p) { + for _, ref := range spdxhelpers.ExternalRefs(p) { refs = append(refs, &spdx.PackageExternalReference2_2{ Category: string(ref.ReferenceCategory), RefType: string(ref.ReferenceType), diff --git a/internal/presenter/packages/spdx_tag_value_presenter_test.go b/internal/presenter/packages/spdx_tag_value_presenter_test.go index 8ffff1d6207..95dd4a793b2 100644 --- a/internal/presenter/packages/spdx_tag_value_presenter_test.go +++ b/internal/presenter/packages/spdx_tag_value_presenter_test.go @@ -4,13 +4,15 @@ import ( "flag" "regexp" "testing" + + "github.com/anchore/syft/internal/formats/common/testutils" ) var updateSpdxTagValue = flag.Bool("update-spdx-tv", false, "update the *.golden files for spdx-tv presenters") func TestSPDXTagValueDirectoryPresenter(t *testing.T) { - catalog, metadata, _ := presenterDirectoryInput(t) - assertPresenterAgainstGoldenSnapshot(t, + catalog, metadata, _ := testutils.DirectoryInput(t) + testutils.AssertPresenterAgainstGoldenSnapshot(t, NewSPDXTagValuePresenter(catalog, metadata), *updateSpdxTagValue, spdxTagValueRedactor, @@ -19,8 +21,8 @@ func TestSPDXTagValueDirectoryPresenter(t *testing.T) { func TestSPDXTagValueImagePresenter(t *testing.T) { testImage := "image-simple" - catalog, metadata, _ := presenterImageInput(t, testImage) - assertPresenterAgainstGoldenImageSnapshot(t, + catalog, metadata, _ := testutils.ImageInput(t, testImage) + testutils.AssertPresenterAgainstGoldenImageSnapshot(t, NewSPDXTagValuePresenter(catalog, metadata), testImage, *updateSpdxTagValue, diff --git a/internal/presenter/packages/table_presenter_test.go b/internal/presenter/packages/table_presenter_test.go index 7d59fb1badb..01ebdaca8ae 100644 --- a/internal/presenter/packages/table_presenter_test.go +++ b/internal/presenter/packages/table_presenter_test.go @@ -4,6 +4,8 @@ import ( "flag" "testing" + "github.com/anchore/syft/internal/formats/common/testutils" + "github.com/go-test/deep" ) @@ -11,8 +13,8 @@ var updateTablePresenterGoldenFiles = flag.Bool("update-table", false, "update t func TestTablePresenter(t *testing.T) { testImage := "image-simple" - catalog, _, _ := presenterImageInput(t, testImage) - assertPresenterAgainstGoldenImageSnapshot(t, + catalog, _, _ := testutils.ImageInput(t, testImage) + testutils.AssertPresenterAgainstGoldenImageSnapshot(t, NewTablePresenter(catalog), testImage, *updateTablePresenterGoldenFiles, diff --git a/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden b/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden deleted file mode 100644 index 249517449ad..00000000000 --- a/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden +++ /dev/null @@ -1,79 +0,0 @@ -{ - "SPDXID": "SPDXRef-DOCUMENT", - "name": "/some/path", - "spdxVersion": "SPDX-2.2", - "creationInfo": { - "created": "2021-09-16T20:44:35.198887Z", - "creators": [ - "Organization: Anchore, Inc", - "Tool: syft-[not provided]" - ], - "licenseListVersion": "3.14" - }, - "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/image/", - "packages": [ - { - "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", - "name": "package-1", - "licenseConcluded": "MIT", - "downloadLocation": "NOASSERTION", - "externalRefs": [ - { - "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", - "referenceType": "cpe23Type" - }, - { - "referenceCategory": "PACKAGE_MANAGER", - "referenceLocator": "a-purl-2", - "referenceType": "purl" - } - ], - "filesAnalyzed": false, - "hasFiles": [ - "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9" - ], - "licenseDeclared": "MIT", - "sourceInfo": "acquired package info from installed python package manifest file: /some/path/pkg1", - "versionInfo": "1.0.1" - }, - { - "SPDXID": "SPDXRef-Package-deb-package-2-2.0.1", - "name": "package-2", - "licenseConcluded": "NONE", - "downloadLocation": "NOASSERTION", - "externalRefs": [ - { - "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", - "referenceType": "cpe23Type" - }, - { - "referenceCategory": "PACKAGE_MANAGER", - "referenceLocator": "a-purl-2", - "referenceType": "purl" - } - ], - "filesAnalyzed": false, - "licenseDeclared": "NONE", - "sourceInfo": "acquired package info from DPKG DB: /some/path/pkg1", - "versionInfo": "2.0.1" - } - ], - "files": [ - { - "SPDXID": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9", - "name": "foo", - "licenseConcluded": "", - "fileName": "/some/path/pkg1/depedencies/foo" - } - ], - "relationships": [ - { - "spdxElementId": "SPDXRef-Package-python-package-1-1.0.1", - "relationshipType": "CONTAINS", - "relatedSpdxElement": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9" - } - ] -} diff --git a/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden b/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden deleted file mode 100644 index 8906ef161ac..00000000000 --- a/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden +++ /dev/null @@ -1,61 +0,0 @@ -{ - "SPDXID": "SPDXRef-DOCUMENT", - "name": "user-image-input", - "spdxVersion": "SPDX-2.2", - "creationInfo": { - "created": "2021-09-16T20:44:35.203911Z", - "creators": [ - "Organization: Anchore, Inc", - "Tool: syft-[not provided]" - ], - "licenseListVersion": "3.14" - }, - "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/image/user-image-input", - "packages": [ - { - "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", - "name": "package-1", - "licenseConcluded": "MIT", - "downloadLocation": "NOASSERTION", - "externalRefs": [ - { - "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*", - "referenceType": "cpe23Type" - }, - { - "referenceCategory": "PACKAGE_MANAGER", - "referenceLocator": "a-purl-1", - "referenceType": "purl" - } - ], - "filesAnalyzed": false, - "licenseDeclared": "MIT", - "sourceInfo": "acquired package info from installed python package manifest file: /somefile-1.txt", - "versionInfo": "1.0.1" - }, - { - "SPDXID": "SPDXRef-Package-deb-package-2-2.0.1", - "name": "package-2", - "licenseConcluded": "NONE", - "downloadLocation": "NOASSERTION", - "externalRefs": [ - { - "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", - "referenceType": "cpe23Type" - }, - { - "referenceCategory": "PACKAGE_MANAGER", - "referenceLocator": "a-purl-2", - "referenceType": "purl" - } - ], - "filesAnalyzed": false, - "licenseDeclared": "NONE", - "sourceInfo": "acquired package info from DPKG DB: /somefile-2.txt", - "versionInfo": "2.0.1" - } - ] -} diff --git a/internal/presenter/packages/text_presenter_test.go b/internal/presenter/packages/text_presenter_test.go index 2a2164285ea..a6533d356af 100644 --- a/internal/presenter/packages/text_presenter_test.go +++ b/internal/presenter/packages/text_presenter_test.go @@ -3,13 +3,15 @@ package packages import ( "flag" "testing" + + "github.com/anchore/syft/internal/formats/common/testutils" ) var updateTextPresenterGoldenFiles = flag.Bool("update-text", false, "update the *.golden files for text presenters") func TestTextDirectoryPresenter(t *testing.T) { - catalog, metadata, _ := presenterDirectoryInput(t) - assertPresenterAgainstGoldenSnapshot(t, + catalog, metadata, _ := testutils.DirectoryInput(t) + testutils.AssertPresenterAgainstGoldenSnapshot(t, NewTextPresenter(catalog, metadata), *updateTextPresenterGoldenFiles, ) @@ -17,8 +19,8 @@ func TestTextDirectoryPresenter(t *testing.T) { func TestTextImagePresenter(t *testing.T) { testImage := "image-simple" - catalog, metadata, _ := presenterImageInput(t, testImage) - assertPresenterAgainstGoldenImageSnapshot(t, + catalog, metadata, _ := testutils.ImageInput(t, testImage) + testutils.AssertPresenterAgainstGoldenImageSnapshot(t, NewTextPresenter(catalog, metadata), testImage, *updateTextPresenterGoldenFiles, diff --git a/internal/presenter/packages/utils_test.go b/internal/presenter/packages/utils_test.go deleted file mode 100644 index 9c6a88242a4..00000000000 --- a/internal/presenter/packages/utils_test.go +++ /dev/null @@ -1,199 +0,0 @@ -package packages - -import ( - "bytes" - "testing" - - "github.com/anchore/go-testutils" - "github.com/anchore/stereoscope/pkg/filetree" - "github.com/anchore/stereoscope/pkg/imagetest" - "github.com/anchore/syft/syft/distro" - "github.com/anchore/syft/syft/pkg" - "github.com/anchore/syft/syft/presenter" - "github.com/anchore/syft/syft/source" - "github.com/sergi/go-diff/diffmatchpatch" - "github.com/stretchr/testify/assert" -) - -type redactor func(s []byte) []byte - -func assertPresenterAgainstGoldenImageSnapshot(t *testing.T, pres presenter.Presenter, testImage string, updateSnapshot bool, redactors ...redactor) { - var buffer bytes.Buffer - - // grab the latest image contents and persist - if updateSnapshot { - imagetest.UpdateGoldenFixtureImage(t, testImage) - } - - err := pres.Present(&buffer) - assert.NoError(t, err) - actual := buffer.Bytes() - - // replace the expected snapshot contents with the current presenter contents - if updateSnapshot { - testutils.UpdateGoldenFileContents(t, actual) - } - - var expected = testutils.GetGoldenFileContents(t) - - // remove dynamic values, which should be tested independently - for _, r := range redactors { - actual = r(actual) - expected = r(expected) - } - - // assert that the golden file snapshot matches the actual contents - if !bytes.Equal(expected, actual) { - dmp := diffmatchpatch.New() - diffs := dmp.DiffMain(string(expected), string(actual), true) - t.Errorf("mismatched output:\n%s", dmp.DiffPrettyText(diffs)) - } -} - -func assertPresenterAgainstGoldenSnapshot(t *testing.T, pres presenter.Presenter, updateSnapshot bool, redactors ...redactor) { - var buffer bytes.Buffer - - err := pres.Present(&buffer) - assert.NoError(t, err) - actual := buffer.Bytes() - - // replace the expected snapshot contents with the current presenter contents - if updateSnapshot { - testutils.UpdateGoldenFileContents(t, actual) - } - - var expected = testutils.GetGoldenFileContents(t) - - // remove dynamic values, which should be tested independently - for _, r := range redactors { - actual = r(actual) - expected = r(expected) - } - - if !bytes.Equal(expected, actual) { - dmp := diffmatchpatch.New() - diffs := dmp.DiffMain(string(expected), string(actual), true) - t.Errorf("mismatched output:\n%s", dmp.DiffPrettyText(diffs)) - } -} - -func presenterImageInput(t testing.TB, testImage string) (*pkg.Catalog, source.Metadata, *distro.Distro) { - t.Helper() - catalog := pkg.NewCatalog() - img := imagetest.GetGoldenFixtureImage(t, testImage) - - _, ref1, _ := img.SquashedTree().File("/somefile-1.txt", filetree.FollowBasenameLinks) - _, ref2, _ := img.SquashedTree().File("/somefile-2.txt", filetree.FollowBasenameLinks) - - // populate catalog with test data - catalog.Add(pkg.Package{ - ID: "package-1-id", - Name: "package-1", - Version: "1.0.1", - Locations: []source.Location{ - source.NewLocationFromImage(string(ref1.RealPath), *ref1, img), - }, - 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", - }, - PURL: "a-purl-1", - CPEs: []pkg.CPE{ - must(pkg.NewCPE("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*")), - }, - }) - catalog.Add(pkg.Package{ - ID: "package-2-id", - Name: "package-2", - Version: "2.0.1", - Locations: []source.Location{ - source.NewLocationFromImage(string(ref2.RealPath), *ref2, img), - }, - Type: pkg.DebPkg, - FoundBy: "the-cataloger-2", - MetadataType: pkg.DpkgMetadataType, - Metadata: pkg.DpkgMetadata{ - Package: "package-2", - Version: "2.0.1", - }, - PURL: "a-purl-2", - CPEs: []pkg.CPE{ - must(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")), - }, - }) - - // this is a hard coded value that is not given by the fixture helper and must be provided manually - img.Metadata.ManifestDigest = "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368" - - src, err := source.NewFromImage(img, "user-image-input") - assert.NoError(t, err) - - dist, err := distro.NewDistro(distro.Debian, "1.2.3", "like!") - assert.NoError(t, err) - - return catalog, src.Metadata, &dist -} - -func presenterDirectoryInput(t testing.TB) (*pkg.Catalog, source.Metadata, *distro.Distro) { - catalog := pkg.NewCatalog() - - // populate catalog with test data - catalog.Add(pkg.Package{ - ID: "package-1-id", - Name: "package-1", - Version: "1.0.1", - Type: pkg.PythonPkg, - FoundBy: "the-cataloger-1", - Locations: []source.Location{ - {RealPath: "/some/path/pkg1"}, - }, - Language: pkg.Python, - MetadataType: pkg.PythonPackageMetadataType, - Licenses: []string{"MIT"}, - Metadata: pkg.PythonPackageMetadata{ - Name: "package-1", - Version: "1.0.1", - Files: []pkg.PythonFileRecord{ - { - Path: "/some/path/pkg1/depedencies/foo", - }, - }, - }, - PURL: "a-purl-2", - CPEs: []pkg.CPE{ - must(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")), - }, - }) - catalog.Add(pkg.Package{ - ID: "package-2-id", - Name: "package-2", - Version: "2.0.1", - Type: pkg.DebPkg, - FoundBy: "the-cataloger-2", - Locations: []source.Location{ - {RealPath: "/some/path/pkg1"}, - }, - MetadataType: pkg.DpkgMetadataType, - Metadata: pkg.DpkgMetadata{ - Package: "package-2", - Version: "2.0.1", - }, - PURL: "a-purl-2", - CPEs: []pkg.CPE{ - must(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")), - }, - }) - - dist, err := distro.NewDistro(distro.Debian, "1.2.3", "like!") - assert.NoError(t, err) - - src, err := source.NewFromDirectory("/some/path") - assert.NoError(t, err) - - return catalog, src.Metadata, &dist -} From bd89e22fe5478a27011f6cae593b68080e71eaef Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:59:13 -0700 Subject: [PATCH 14/17] update the power-user JSON document to use the format model directory Signed-off-by: Alex Goodman --- internal/presenter/poweruser/json_document.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/internal/presenter/poweruser/json_document.go b/internal/presenter/poweruser/json_document.go index d468bfaf5c5..b9b62b2c8bf 100644 --- a/internal/presenter/poweruser/json_document.go +++ b/internal/presenter/poweruser/json_document.go @@ -1,11 +1,12 @@ package poweruser import ( - "github.com/anchore/syft/internal/presenter/packages" + "github.com/anchore/syft/internal/formats/syftjson" + "github.com/anchore/syft/internal/formats/syftjson/model" ) type JSONDocument struct { - // note: poweruser.JSONDocument is meant to always be a superset of packages.JSONDocument, any additional fields + // note: poweruser.JSONDocument is meant to always be a superset of packages.Document, any additional fields // here should be optional by supplying "omitempty" on these fields hint to the jsonschema generator to not // require these fields. As an accepted rule in this repo all collections should still be initialized in the // context of being used in a JSON document. @@ -13,15 +14,12 @@ type JSONDocument struct { FileContents []JSONFileContents `json:"fileContents,omitempty"` // note: must have omitempty FileMetadata []JSONFileMetadata `json:"fileMetadata,omitempty"` // note: must have omitempty Secrets []JSONSecrets `json:"secrets,omitempty"` // note: must have omitempty - packages.JSONDocument + model.Document } // NewJSONDocument creates and populates a new JSON document struct from the given cataloging results. func NewJSONDocument(config JSONDocumentConfig) (JSONDocument, error) { - pkgsDoc, err := packages.NewJSONDocument(config.PackageCatalog, config.SourceMetadata, config.Distro, config.ApplicationConfig.Package.Cataloger.ScopeOpt, config.ApplicationConfig) - if err != nil { - return JSONDocument{}, err - } + pkgsDoc := syftjson.ToFormatModel(config.PackageCatalog, &config.SourceMetadata, config.Distro, config.ApplicationConfig) fileMetadata, err := NewJSONFileMetadata(config.FileMetadata, config.FileDigests) if err != nil { @@ -33,6 +31,6 @@ func NewJSONDocument(config JSONDocumentConfig) (JSONDocument, error) { FileContents: NewJSONFileContents(config.FileContents), FileMetadata: fileMetadata, Secrets: NewJSONSecrets(config.Secrets), - JSONDocument: pkgsDoc, + Document: pkgsDoc, }, nil } From c6447cb62b9ea2a196aa33b6a1a0e4ed27cbb3b4 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 18:59:46 -0700 Subject: [PATCH 15/17] update anchore import to use the new format option Signed-off-by: Alex Goodman --- internal/anchore/import_package_sbom.go | 5 +++-- internal/anchore/import_package_sbom_test.go | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/anchore/import_package_sbom.go b/internal/anchore/import_package_sbom.go index 02b832e7eaa..858eef77dba 100644 --- a/internal/anchore/import_package_sbom.go +++ b/internal/anchore/import_package_sbom.go @@ -8,7 +8,8 @@ import ( "fmt" "net/http" - "github.com/anchore/syft/internal/presenter/packages" + "github.com/anchore/syft/internal/formats" + "github.com/anchore/syft/syft/format" "github.com/wagoodman/go-progress" @@ -26,7 +27,7 @@ type packageSBOMImportAPI interface { func packageSbomModel(s source.Metadata, catalog *pkg.Catalog, d *distro.Distro, scope source.Scope) (*external.ImagePackageManifest, error) { var buf bytes.Buffer - pres := packages.NewJSONPresenter(catalog, s, d, scope) + pres := formats.ByOption(format.JSONOption).Presenter(catalog, &s, d) err := pres.Present(&buf) if err != nil { return nil, fmt.Errorf("unable to serialize results: %w", err) diff --git a/internal/anchore/import_package_sbom_test.go b/internal/anchore/import_package_sbom_test.go index cf97899ead6..80e5055c289 100644 --- a/internal/anchore/import_package_sbom_test.go +++ b/internal/anchore/import_package_sbom_test.go @@ -9,6 +9,8 @@ import ( "strings" "testing" + model2 "github.com/anchore/syft/internal/formats/syftjson/model" + "github.com/anchore/syft/internal/presenter/packages" "github.com/wagoodman/go-progress" @@ -94,13 +96,13 @@ func TestPackageSbomToModel(t *testing.T) { } // unmarshal expected result - var expectedDoc packages.JSONDocument + var expectedDoc model2.Document if err := json.Unmarshal(buf.Bytes(), &expectedDoc); err != nil { t.Fatalf("unable to parse json doc: %+v", err) } // unmarshal actual result - var actualDoc packages.JSONDocument + var actualDoc model2.Document if err := json.Unmarshal(modelJSON, &actualDoc); err != nil { t.Fatalf("unable to parse json doc: %+v", err) } From 055542694f9e823bb72b6c67f9e4676a538542c2 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 19:02:00 -0700 Subject: [PATCH 16/17] remove encoder notes (have already been incorporated into lib interface) Signed-off-by: Alex Goodman --- syft/format/encoder.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/syft/format/encoder.go b/syft/format/encoder.go index 46e1d3b75d7..ab712c6546b 100644 --- a/syft/format/encoder.go +++ b/syft/format/encoder.go @@ -8,15 +8,4 @@ import ( "github.com/anchore/syft/syft/source" ) -// TODO: this should probably be a helper function to return the bytes -//func using() { -// var buff bytes.Buffer -// var encoder Encoder // = ... -// -// _:=encoder(&buff, nil, nil, nil) -// -// bytes.NewReader(buff.Bytes()) -// -//} - type Encoder func(io.Writer, *pkg.Catalog, *source.Metadata, *distro.Distro) error From fdc1effd6e17e56e71dd040f3d74a14703c8e362 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 10 Oct 2021 19:50:50 -0700 Subject: [PATCH 17/17] add test and linting fixes Signed-off-by: Alex Goodman --- internal/anchore/import_package_sbom.go | 2 +- internal/anchore/import_package_sbom_test.go | 28 ++++++++----------- internal/formats/common/testutils/utils.go | 2 +- .../spdx22json/model/syft_package_data.go | 1 + internal/formats/syftjson/model/package.go | 1 + internal/formats/syftjson/to_format_model.go | 23 +++++---------- syft/lib.go | 2 +- syft/pkg/cataloger/deb/cataloger.go | 2 +- 8 files changed, 24 insertions(+), 37 deletions(-) diff --git a/internal/anchore/import_package_sbom.go b/internal/anchore/import_package_sbom.go index 858eef77dba..870fc77e189 100644 --- a/internal/anchore/import_package_sbom.go +++ b/internal/anchore/import_package_sbom.go @@ -25,7 +25,7 @@ type packageSBOMImportAPI interface { ImportImagePackages(context.Context, string, external.ImagePackageManifest) (external.ImageImportContentResponse, *http.Response, error) } -func packageSbomModel(s source.Metadata, catalog *pkg.Catalog, d *distro.Distro, scope source.Scope) (*external.ImagePackageManifest, error) { +func packageSbomModel(s source.Metadata, catalog *pkg.Catalog, d *distro.Distro, _ source.Scope) (*external.ImagePackageManifest, error) { var buf bytes.Buffer pres := formats.ByOption(format.JSONOption).Presenter(catalog, &s, d) err := pres.Present(&buf) diff --git a/internal/anchore/import_package_sbom_test.go b/internal/anchore/import_package_sbom_test.go index 80e5055c289..63a0b2c4dfc 100644 --- a/internal/anchore/import_package_sbom_test.go +++ b/internal/anchore/import_package_sbom_test.go @@ -1,7 +1,6 @@ package anchore import ( - "bytes" "context" "encoding/json" "fmt" @@ -9,20 +8,16 @@ import ( "strings" "testing" - model2 "github.com/anchore/syft/internal/formats/syftjson/model" - - "github.com/anchore/syft/internal/presenter/packages" - - "github.com/wagoodman/go-progress" - - "github.com/anchore/syft/syft/distro" - - "github.com/docker/docker/pkg/ioutils" - "github.com/anchore/client-go/pkg/external" + syftjsonModel "github.com/anchore/syft/internal/formats/syftjson/model" + "github.com/anchore/syft/syft" + "github.com/anchore/syft/syft/distro" + "github.com/anchore/syft/syft/format" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/source" + "github.com/docker/docker/pkg/ioutils" "github.com/go-test/deep" + "github.com/wagoodman/go-progress" ) func must(c pkg.CPE, e error) pkg.CPE { @@ -89,20 +84,19 @@ func TestPackageSbomToModel(t *testing.T) { t.Fatalf("unable to marshal model: %+v", err) } - var buf bytes.Buffer - pres := packages.NewJSONPresenter(c, m, &d, source.AllLayersScope) - if err := pres.Present(&buf); err != nil { + by, err := syft.Encode(c, &m, &d, format.JSONOption) + if err != nil { t.Fatalf("unable to get expected json: %+v", err) } // unmarshal expected result - var expectedDoc model2.Document - if err := json.Unmarshal(buf.Bytes(), &expectedDoc); err != nil { + var expectedDoc syftjsonModel.Document + if err := json.Unmarshal(by, &expectedDoc); err != nil { t.Fatalf("unable to parse json doc: %+v", err) } // unmarshal actual result - var actualDoc model2.Document + var actualDoc syftjsonModel.Document if err := json.Unmarshal(modelJSON, &actualDoc); err != nil { t.Fatalf("unable to parse json doc: %+v", err) } diff --git a/internal/formats/common/testutils/utils.go b/internal/formats/common/testutils/utils.go index db5f2d78c62..dc5a8bad31e 100644 --- a/internal/formats/common/testutils/utils.go +++ b/internal/formats/common/testutils/utils.go @@ -168,7 +168,7 @@ func DirectoryInput(t testing.TB) (*pkg.Catalog, source.Metadata, *distro.Distro Version: "1.0.1", Files: []pkg.PythonFileRecord{ { - Path: "/some/path/pkg1/depedencies/foo", + Path: "/some/path/pkg1/dependencies/foo", }, }, }, diff --git a/internal/formats/spdx22json/model/syft_package_data.go b/internal/formats/spdx22json/model/syft_package_data.go index 1b33db57545..92d99509cf1 100644 --- a/internal/formats/spdx22json/model/syft_package_data.go +++ b/internal/formats/spdx22json/model/syft_package_data.go @@ -38,6 +38,7 @@ func (p *syftPackageMetadataUnpacker) String() string { } // UnmarshalJSON is a custom unmarshaller for handling basic values and values with ambiguous types. +// nolint:funlen func (p *SyftPackageData) UnmarshalJSON(b []byte) error { var basic SyftPackageBasicData if err := json.Unmarshal(b, &basic); err != nil { diff --git a/internal/formats/syftjson/model/package.go b/internal/formats/syftjson/model/package.go index 9ee46806246..4078d3101a3 100644 --- a/internal/formats/syftjson/model/package.go +++ b/internal/formats/syftjson/model/package.go @@ -46,6 +46,7 @@ func (p *packageMetadataUnpacker) String() string { } // UnmarshalJSON is a custom unmarshaller for handling basic values and values with ambiguous types. +// nolint:funlen func (p *Package) UnmarshalJSON(b []byte) error { var basic PackageBasicData if err := json.Unmarshal(b, &basic); err != nil { diff --git a/internal/formats/syftjson/to_format_model.go b/internal/formats/syftjson/to_format_model.go index eacce565ee8..260cedeadd8 100644 --- a/internal/formats/syftjson/to_format_model.go +++ b/internal/formats/syftjson/to_format_model.go @@ -24,13 +24,8 @@ func ToFormatModel(catalog *pkg.Catalog, srcMetadata *source.Metadata, d *distro log.Warnf("unable to create syft-json source object: %+v", err) } - artifacts, err := toPackageModels(catalog) - if err != nil { - return model.Document{} - } - return model.Document{ - Artifacts: artifacts, + Artifacts: toPackageModels(catalog), ArtifactRelationships: toRelationshipModel(pkg.NewRelationships(catalog)), Source: src, Distro: toDistroModel(d), @@ -46,23 +41,19 @@ func ToFormatModel(catalog *pkg.Catalog, srcMetadata *source.Metadata, d *distro } } -func toPackageModels(catalog *pkg.Catalog) ([]model.Package, error) { +func toPackageModels(catalog *pkg.Catalog) []model.Package { artifacts := make([]model.Package, 0) if catalog == nil { - return artifacts, nil + return artifacts } for _, p := range catalog.Sorted() { - art, err := toPackageModel(p) - if err != nil { - return nil, err - } - artifacts = append(artifacts, art) + artifacts = append(artifacts, toPackageModel(p)) } - return artifacts, nil + return artifacts } // toPackageModel crates a new Package from the given pkg.Package. -func toPackageModel(p *pkg.Package) (model.Package, error) { +func toPackageModel(p *pkg.Package) model.Package { var cpes = make([]string, len(p.CPEs)) for i, c := range p.CPEs { cpes[i] = c.BindToFmtString() @@ -96,7 +87,7 @@ func toPackageModel(p *pkg.Package) (model.Package, error) { MetadataType: p.MetadataType, Metadata: p.Metadata, }, - }, nil + } } func toRelationshipModel(relationships []pkg.Relationship) []model.Relationship { diff --git a/syft/lib.go b/syft/lib.go index 3a074e6d8e8..872b73acf63 100644 --- a/syft/lib.go +++ b/syft/lib.go @@ -75,7 +75,7 @@ func CatalogPackages(src *source.Source, scope source.Scope) (*pkg.Catalog, *dis func Encode(catalog *pkg.Catalog, metadata *source.Metadata, dist *distro.Distro, option format.Option) ([]byte, error) { f := formats.ByOption(option) if f == nil { - return nil, nil + return nil, fmt.Errorf("unsupported format: %+v", option) } buff := bytes.Buffer{} diff --git a/syft/pkg/cataloger/deb/cataloger.go b/syft/pkg/cataloger/deb/cataloger.go index 1cd0007075f..f86666e9448 100644 --- a/syft/pkg/cataloger/deb/cataloger.go +++ b/syft/pkg/cataloger/deb/cataloger.go @@ -36,7 +36,7 @@ func (c *Cataloger) Name() string { } // Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing dpkg support files. -// nolint:funlen + func (c *Cataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, error) { dbFileMatches, err := resolver.FilesByGlob(pkg.DpkgDbGlob) if err != nil {