From 64c6244ecfe964ad4658de6410fa1afa21c31a9a Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 20 Oct 2021 17:36:34 -0400 Subject: [PATCH] Introduce new format pattern + port json processing (#550) * add new format pattern Signed-off-by: Alex Goodman * add syftjson format Signed-off-by: Alex Goodman * add internal formats helper Signed-off-by: Alex Goodman * add SBOM encode/decode to lib API Signed-off-by: Alex Goodman * remove json presenter + update presenter tests to use common utils Signed-off-by: Alex Goodman * remove presenter format enum type + add formats shim in presenter helper Signed-off-by: Alex Goodman * add MustCPE helper for tests Signed-off-by: Alex Goodman * update usage of format enum Signed-off-by: Alex Goodman * add test fixtures for encode/decode tests Signed-off-by: Alex Goodman * fix integration test Signed-off-by: Alex Goodman * migrate format detection to use reader Signed-off-by: Alex Goodman * address review comments Signed-off-by: Alex Goodman --- cmd/packages.go | 12 +- internal/anchore/import_package_sbom.go | 6 +- internal/anchore/import_package_sbom_test.go | 19 +- .../common/testutils/utils.go} | 23 +- internal/formats/formats.go | 34 + internal/formats/formats_test.go | 34 + internal/formats/syftjson/decoder.go | 24 + internal/formats/syftjson/decoder_test.go | 52 + internal/formats/syftjson/encoder.go | 23 + internal/formats/syftjson/encoder_test.go | 31 + 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 | 123 ++ .../formats/syftjson/model/relationship.go | 8 + internal/formats/syftjson/model/source.go | 57 + .../test-fixtures/image-simple/Dockerfile | 4 + .../test-fixtures/image-simple/file-1.txt | 1 + .../test-fixtures/image-simple/file-2.txt | 1 + .../snapshot/TestDirectoryPresenter.golden | 86 + .../snapshot/TestImagePresenter.golden | 108 + .../stereoscope-fixture-image-simple.golden} | Bin 16896 -> 15360 bytes internal/formats/syftjson/to_format_model.go | 133 ++ internal/formats/syftjson/to_syft_model.go | 73 + internal/formats/syftjson/validator.go | 31 + .../formats/test-fixtures/alpine-syft.json | 1846 +++++++++++++++++ .../packages/cyclonedx_presenter_test.go | 10 +- .../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 - .../presenter/packages/spdx_helpers_test.go | 2 +- .../packages/spdx_json_presenter_test.go | 10 +- .../packages/spdx_tag_value_presenter_test.go | 10 +- .../packages/table_presenter_test.go | 6 +- .../TestSPDXJSONDirectoryPresenter.golden | 12 +- .../TestSPDXJSONImagePresenter.golden | 4 +- .../snapshot/TestTextImagePresenter.golden | 4 +- .../stereoscope-fixture-image-simple.golden | Bin 15360 -> 15360 bytes .../presenter/packages/text_presenter_test.go | 10 +- internal/presenter/poweruser/json_document.go | 12 +- syft/encode_decode.go | 48 + syft/encode_decode_test.go | 53 + syft/format/decoder.go | 13 + syft/format/encoder.go | 12 + syft/format/format.go | 62 + syft/format/option.go | 43 + syft/format/presenter.go | 32 + syft/format/validator.go | 12 + syft/pkg/cpe.go | 8 + syft/presenter/packages/presenter.go | 23 +- syft/presenter/packages/presenter_option.go | 43 - .../pkgs/project/package-lock.json | 52 + .../package_ownership_relationship_test.go | 9 +- 57 files changed, 3139 insertions(+), 421 deletions(-) rename internal/{presenter/packages/utils_test.go => formats/common/testutils/utils.go} (88%) create mode 100644 internal/formats/formats.go create mode 100644 internal/formats/formats_test.go 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/encoder_test.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/TestDirectoryPresenter.golden create mode 100644 internal/formats/syftjson/test-fixtures/snapshot/TestImagePresenter.golden rename internal/{presenter/packages/test-fixtures/snapshot/stereoscope-fixture-packages-image-simple.golden => formats/syftjson/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden} (69%) 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 create mode 100644 internal/formats/test-fixtures/alpine-syft.json 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 create mode 100644 syft/encode_decode.go create mode 100644 syft/encode_decode_test.go 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 delete mode 100644 syft/presenter/packages/presenter_option.go create mode 100644 syft/test-fixtures/pkgs/project/package-lock.json diff --git a/cmd/packages.go b/cmd/packages.go index 47d55eb3ca4..81af8daca91 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 packagesCmd = &cobra.Command{ Use: "packages [SOURCE]", Short: "Generate a package SBOM", @@ -62,8 +64,8 @@ var ( SilenceErrors: true, PreRunE: func(cmd *cobra.Command, args []string) error { // set the presenter - presenterOption := packages.ParsePresenterOption(appConfig.Output) - if presenterOption == packages.UnknownPresenterOption { + presenterOption := format.ParseOption(appConfig.Output) + if presenterOption == format.UnknownFormatOption { return fmt.Errorf("bad --output value '%s'", appConfig.Output) } packagesPresenterOpt = presenterOption @@ -100,8 +102,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.AllPresenters), ) flags.StringP( diff --git a/internal/anchore/import_package_sbom.go b/internal/anchore/import_package_sbom.go index 02b832e7eaa..5fb014b0f20 100644 --- a/internal/anchore/import_package_sbom.go +++ b/internal/anchore/import_package_sbom.go @@ -8,7 +8,7 @@ import ( "fmt" "net/http" - "github.com/anchore/syft/internal/presenter/packages" + "github.com/anchore/syft/internal/formats/syftjson" "github.com/wagoodman/go-progress" @@ -26,8 +26,8 @@ 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) - err := pres.Present(&buf) + + err := syftjson.Format().Presenter(catalog, &s, d, scope).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..1d727a55539 100644 --- a/internal/anchore/import_package_sbom_test.go +++ b/internal/anchore/import_package_sbom_test.go @@ -9,18 +9,15 @@ import ( "strings" "testing" - "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" + "github.com/anchore/syft/internal/formats/syftjson" + syftjsonModel "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" + "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 { @@ -88,19 +85,19 @@ func TestPackageSbomToModel(t *testing.T) { } var buf bytes.Buffer - pres := packages.NewJSONPresenter(c, m, &d, source.AllLayersScope) + pres := syftjson.Format().Presenter(c, &m, &d, source.AllLayersScope) if err := pres.Present(&buf); err != nil { t.Fatalf("unable to get expected json: %+v", err) } // unmarshal expected result - var expectedDoc packages.JSONDocument + var expectedDoc syftjsonModel.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 syftjsonModel.Document if err := json.Unmarshal(modelJSON, &actualDoc); err != nil { t.Fatalf("unable to parse json doc: %+v", err) } diff --git a/internal/presenter/packages/utils_test.go b/internal/formats/common/testutils/utils.go similarity index 88% rename from internal/presenter/packages/utils_test.go rename to internal/formats/common/testutils/utils.go index 9c6a88242a4..b8ca909a73f 100644 --- a/internal/presenter/packages/utils_test.go +++ b/internal/formats/common/testutils/utils.go @@ -1,15 +1,16 @@ -package packages +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/presenter" "github.com/anchore/syft/syft/source" "github.com/sergi/go-diff/diffmatchpatch" "github.com/stretchr/testify/assert" @@ -17,7 +18,7 @@ import ( type redactor func(s []byte) []byte -func assertPresenterAgainstGoldenImageSnapshot(t *testing.T, pres presenter.Presenter, testImage string, updateSnapshot bool, redactors ...redactor) { +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 @@ -50,7 +51,7 @@ func assertPresenterAgainstGoldenImageSnapshot(t *testing.T, pres presenter.Pres } } -func assertPresenterAgainstGoldenSnapshot(t *testing.T, pres presenter.Presenter, updateSnapshot bool, redactors ...redactor) { +func AssertPresenterAgainstGoldenSnapshot(t *testing.T, pres presenter.Presenter, updateSnapshot bool, redactors ...redactor) { var buffer bytes.Buffer err := pres.Present(&buffer) @@ -77,7 +78,7 @@ func assertPresenterAgainstGoldenSnapshot(t *testing.T, pres presenter.Presenter } } -func presenterImageInput(t testing.TB, testImage string) (*pkg.Catalog, source.Metadata, *distro.Distro) { +func ImageInput(t testing.TB, testImage string) (*pkg.Catalog, source.Metadata, *distro.Distro) { t.Helper() catalog := pkg.NewCatalog() img := imagetest.GetGoldenFixtureImage(t, testImage) @@ -104,7 +105,7 @@ func presenterImageInput(t testing.TB, testImage string) (*pkg.Catalog, source.M }, PURL: "a-purl-1", CPEs: []pkg.CPE{ - must(pkg.NewCPE("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*")), + pkg.MustCPE("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*"), }, }) catalog.Add(pkg.Package{ @@ -123,7 +124,7 @@ func presenterImageInput(t testing.TB, testImage string) (*pkg.Catalog, source.M }, PURL: "a-purl-2", CPEs: []pkg.CPE{ - must(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")), + pkg.MustCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"), }, }) @@ -139,7 +140,7 @@ func presenterImageInput(t testing.TB, testImage string) (*pkg.Catalog, source.M return catalog, src.Metadata, &dist } -func presenterDirectoryInput(t testing.TB) (*pkg.Catalog, source.Metadata, *distro.Distro) { +func DirectoryInput(t testing.TB) (*pkg.Catalog, source.Metadata, *distro.Distro) { catalog := pkg.NewCatalog() // populate catalog with test data @@ -160,13 +161,13 @@ func presenterDirectoryInput(t testing.TB) (*pkg.Catalog, source.Metadata, *dist Version: "1.0.1", Files: []pkg.PythonFileRecord{ { - Path: "/some/path/pkg1/depedencies/foo", + Path: "/some/path/pkg1/dependencies/foo", }, }, }, PURL: "a-purl-2", CPEs: []pkg.CPE{ - must(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")), + pkg.MustCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"), }, }) catalog.Add(pkg.Package{ @@ -185,7 +186,7 @@ func presenterDirectoryInput(t testing.TB) (*pkg.Catalog, source.Metadata, *dist }, PURL: "a-purl-2", CPEs: []pkg.CPE{ - must(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")), + pkg.MustCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"), }, }) diff --git a/internal/formats/formats.go b/internal/formats/formats.go new file mode 100644 index 00000000000..5c82bd6533a --- /dev/null +++ b/internal/formats/formats.go @@ -0,0 +1,34 @@ +package formats + +import ( + "bytes" + + "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{ + syftjson.Format(), + } +} + +func Identify(by []byte) (*format.Format, error) { + for _, f := range All() { + if err := f.Validate(bytes.NewReader(by)); err != nil { + continue + } + 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..3df97558c5f --- /dev/null +++ b/internal/formats/formats_test.go @@ -0,0 +1,34 @@ +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, + }, + } + 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) + }) + } +} diff --git a/internal/formats/syftjson/decoder.go b/internal/formats/syftjson/decoder.go new file mode 100644 index 00000000000..46e4c47d3d9 --- /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, source.Scope, error) { + dec := json.NewDecoder(reader) + + var doc model.Document + err := dec.Decode(&doc) + if err != nil { + return nil, nil, nil, source.UnknownScope, 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..ac3ba44e932 --- /dev/null +++ b/internal/formats/syftjson/decoder_test.go @@ -0,0 +1,52 @@ +package syftjson + +import ( + "bytes" + "strings" + "testing" + + "github.com/anchore/syft/syft/source" + + "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, source.SquashedScope)) + + 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..64f8ca08f1a --- /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, scope source.Scope) error { + // TODO: application config not available yet + doc := ToFormatModel(catalog, srcMetadata, d, scope, 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/encoder_test.go b/internal/formats/syftjson/encoder_test.go new file mode 100644 index 00000000000..7376451ac92 --- /dev/null +++ b/internal/formats/syftjson/encoder_test.go @@ -0,0 +1,31 @@ +package syftjson + +import ( + "flag" + "testing" + + "github.com/anchore/syft/syft/source" + + "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 TestDirectoryPresenter(t *testing.T) { + catalog, metadata, distro := testutils.DirectoryInput(t) + testutils.AssertPresenterAgainstGoldenSnapshot(t, + format.NewPresenter(encoder, catalog, &metadata, distro, source.SquashedScope), + *updateJson, + ) +} + +func TestImagePresenter(t *testing.T) { + testImage := "image-simple" + catalog, metadata, distro := testutils.ImageInput(t, testImage) + testutils.AssertPresenterAgainstGoldenImageSnapshot(t, + format.NewPresenter(encoder, catalog, &metadata, distro, source.SquashedScope), + testImage, + *updateJson, + ) +} 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..4078d3101a3 --- /dev/null +++ b/internal/formats/syftjson/model/package.go @@ -0,0 +1,123 @@ +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. +// nolint:funlen +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..5f7ef47b5e7 --- /dev/null +++ b/internal/formats/syftjson/model/source.go @@ -0,0 +1,57 @@ +package model + +import ( + "encoding/json" + "fmt" + "strconv" + + "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"` +} + +type ImageSource struct { + source.ImageMetadata + Scope source.Scope `json:"scope"` +} + +// 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": + if target, err := strconv.Unquote(string(unpacker.Target)); err == nil { + s.Target = target + } else { + s.Target = string(unpacker.Target[:]) + } + + case "image": + var payload ImageSource + 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/TestDirectoryPresenter.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryPresenter.golden new file mode 100644 index 00000000000..7289b4213ac --- /dev/null +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryPresenter.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/dependencies/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/TestImagePresenter.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestImagePresenter.golden new file mode 100644 index 00000000000..a3b69cdab0b --- /dev/null +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestImagePresenter.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:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59" + } + ], + "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:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec" + } + ], + "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: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": [], + "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/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-packages-image-simple.golden b/internal/formats/syftjson/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden similarity index 69% rename from internal/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-packages-image-simple.golden rename to internal/formats/syftjson/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden index b7d3fed18e8c2efc507f7b86b944f53536efe37a..c1b1d2b797ecd34a5276a1aa2fb18c5b0a58c732 100644 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 16896 zcmeHOS#R4$5Y}^lh04CPfF=I zmJ>>{Q&SLZlDnK;esgeUG=sg35=CNJbVM`lB}bkGZW)P&N#?w^0%KyW4oZ3IwICcb zDPfifGW7o~^Q?3G2VsN+V;!{ktpBG-kPc>u2nJuwJBVP!QKyS;C%c`|X<3;9w$zl` z`olG)x2O9r6H~aevHM!U z6pN83Rb|}So64tIGK^+ahJ$2vEuU6jUJM1?x}14jU966eCL#Nr&iw2sbFhi!{Abz6 zWO$PN`Q-Td?}KSs3`V&#qd{rYYRU7^pRT0SmexTi-pxzo8TD=G-&0uGhpU)TQCMG;IDKx7gE#NySy;fP4ogkeI1r$}oQER86FF2QTYvxqDbjxc!RSna6L{BzFW z1!raln|6Bb$?v+;oygD(geV6cPDW`qJqNIhJg*{LxJ;^xNo{XN<^p(9b104Red=NC z4A>z#&`z|29mwHHQ0*BcE+; zrKNKZ2sGCJ=J7v-|9DORkrZJ6_ad2(-2PuCX&p8+6$5ZFKgA4KOVmRUhTvm_hVyS7 zdqBMUBSo%@VEiko0eF-x$Mn}igMGW#O&LF!2QK|Ohj!yHlGgSgZdx0=mV4 zRkmXuQ*V**HBuY+k0A5Au>Y7qOe#B&S*yc^*8X3^a94*FqWTY|wca#4kxb^?{!TwI0|Jw`94|b8p`rkbNM+k50f9^{_mifP? zVgNa@i76m-+;%Q;Lp{R}mQ&njy;55Zb5n`bEk!Pmu4d{7scO5S2=N{h3Q8`)|(jj0lKWpURpO>^~!WSf#w~>k${?WjG(!} zdm>qsM(Ln+fckNbqJUARgCsFJ&ACLUE>e%S9Ijv`%cVt_dD!dqEO3 zP`vx;+c>n_*#+>bOrh~74Lhs)*rfkNh^yX!EBzN>659B0x2&I2zf8)zYG~c9)L2P} ajg={x%^s8n?SV<{5-kEP0xbeNK;S", + "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" + } +} 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/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) - } -} diff --git a/internal/presenter/packages/spdx_helpers_test.go b/internal/presenter/packages/spdx_helpers_test.go index 985e26fed4c..5002dc62147 100644 --- a/internal/presenter/packages/spdx_helpers_test.go +++ b/internal/presenter/packages/spdx_helpers_test.go @@ -12,7 +12,7 @@ import ( ) func Test_getSPDXExternalRefs(t *testing.T) { - testCPE := must(pkg.NewCPE("cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*")) + testCPE := pkg.MustCPE("cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*") tests := []struct { name string input pkg.Package diff --git a/internal/presenter/packages/spdx_json_presenter_test.go b/internal/presenter/packages/spdx_json_presenter_test.go index 7d6a7f7381d..98d8377593d 100644 --- a/internal/presenter/packages/spdx_json_presenter_test.go +++ b/internal/presenter/packages/spdx_json_presenter_test.go @@ -4,13 +4,15 @@ import ( "flag" "regexp" "testing" + + "github.com/anchore/syft/internal/formats/common/testutils" ) 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, + catalog, metadata, _ := testutils.DirectoryInput(t) + testutils.AssertPresenterAgainstGoldenSnapshot(t, NewSPDXJSONPresenter(catalog, metadata), *updateSpdxJson, spdxJsonRedactor, @@ -19,8 +21,8 @@ func TestSPDXJSONDirectoryPresenter(t *testing.T) { func TestSPDXJSONImagePresenter(t *testing.T) { testImage := "image-simple" - catalog, metadata, _ := presenterImageInput(t, testImage) - assertPresenterAgainstGoldenImageSnapshot(t, + catalog, metadata, _ := testutils.ImageInput(t, testImage) + testutils.AssertPresenterAgainstGoldenImageSnapshot(t, NewSPDXJSONPresenter(catalog, metadata), testImage, *updateSpdxJson, 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 index 249517449ad..a9fa1b587b7 100644 --- a/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden +++ b/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONDirectoryPresenter.golden @@ -3,7 +3,7 @@ "name": "/some/path", "spdxVersion": "SPDX-2.2", "creationInfo": { - "created": "2021-09-16T20:44:35.198887Z", + "created": "2021-10-12T18:40:22.948394Z", "creators": [ "Organization: Anchore, Inc", "Tool: syft-[not provided]" @@ -11,7 +11,7 @@ "licenseListVersion": "3.14" }, "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/image/", + "documentNamespace": "https:/anchore.com/syft/dir/some/path-98ae71fb-f276-4c5c-acf7-25770bf7bca2", "packages": [ { "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", @@ -32,7 +32,7 @@ ], "filesAnalyzed": false, "hasFiles": [ - "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9" + "SPDXRef-File-package-1-efae7fecc76ca25da40f79d7ef5b8933510434914835832c7976f3e866aa756a" ], "licenseDeclared": "MIT", "sourceInfo": "acquired package info from installed python package manifest file: /some/path/pkg1", @@ -63,17 +63,17 @@ ], "files": [ { - "SPDXID": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9", + "SPDXID": "SPDXRef-File-package-1-efae7fecc76ca25da40f79d7ef5b8933510434914835832c7976f3e866aa756a", "name": "foo", "licenseConcluded": "", - "fileName": "/some/path/pkg1/depedencies/foo" + "fileName": "/some/path/pkg1/dependencies/foo" } ], "relationships": [ { "spdxElementId": "SPDXRef-Package-python-package-1-1.0.1", "relationshipType": "CONTAINS", - "relatedSpdxElement": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9" + "relatedSpdxElement": "SPDXRef-File-package-1-efae7fecc76ca25da40f79d7ef5b8933510434914835832c7976f3e866aa756a" } ] } diff --git a/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden b/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden index 8906ef161ac..5d345603101 100644 --- a/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden +++ b/internal/presenter/packages/test-fixtures/snapshot/TestSPDXJSONImagePresenter.golden @@ -3,7 +3,7 @@ "name": "user-image-input", "spdxVersion": "SPDX-2.2", "creationInfo": { - "created": "2021-09-16T20:44:35.203911Z", + "created": "2021-10-12T18:40:22.953633Z", "creators": [ "Organization: Anchore, Inc", "Tool: syft-[not provided]" @@ -11,7 +11,7 @@ "licenseListVersion": "3.14" }, "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/image/user-image-input", + "documentNamespace": "https:/anchore.com/syft/image/user-image-input-149edbad-3c01-4ee0-b3a0-75232312bf51", "packages": [ { "SPDXID": "SPDXRef-Package-python-package-1-1.0.1", diff --git a/internal/presenter/packages/test-fixtures/snapshot/TestTextImagePresenter.golden b/internal/presenter/packages/test-fixtures/snapshot/TestTextImagePresenter.golden index eb23e8bca73..4ab3a446e0c 100644 --- a/internal/presenter/packages/test-fixtures/snapshot/TestTextImagePresenter.golden +++ b/internal/presenter/packages/test-fixtures/snapshot/TestTextImagePresenter.golden @@ -1,11 +1,11 @@ [Image] Layer: 0 - Digest: sha256:ffb5e9eaa453a002110719d12c294960117ca2903953d1faa40f01dc3f77045c + Digest: sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59 Size: 22 MediaType: application/vnd.docker.image.rootfs.diff.tar.gzip Layer: 1 - Digest: sha256:8463854829fc53d47b9dcdf7ee79fe7eb4ca7933c910f67f8521412f7a2f5c21 + Digest: sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec Size: 16 MediaType: application/vnd.docker.image.rootfs.diff.tar.gzip diff --git a/internal/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden b/internal/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden index 249e2544c8e3eceb179648aed525d18d1cadff14..a5985f95c4f36dfec9b67737ea614680187f8ae7 100644 GIT binary patch literal 15360 zcmeHOZExE)5ccQ&icI?&+kB^JU>~}sKno1Z&}JR5qA2)sO0?RNA<0F9Apd`9 z%^%lQ-hujGCARVxc>}(gRgjDlI|)i8$B8eCEI&_1SIM*DLo#}k{Ql(Z`Om{yT@A;j zx8q^$@?vzWd{bOi%x^7z za>8&L^oi&bbwQusTE{gNjqCr4R6 zhCUrMADg3LT~6Ru`KKe-D)v5a=3q=FP&C-<)6GFB{d=g|4ucOQxjx>e#!B`7)`D$l zu_!-K3q-iAQOj{&%s!&tRarI}-ndGd%V}%fvAu+<#+s04*}FVo-J7JouuQ5^=9B~Q zPD{s4CY(zt4=$rxgCrC}kRdn@$~Y&ahX78eUTFnDowm}T)TJa&jgx8WK?x?gO|_Gp z`xFB1AsHb|0s-qy3RpoEP;A7E)OaC87QiQOudfd@|G)QP6v?D@R@>Bhow*=@8lzJu zm~&_f|pAS^IE2OP7I(&0S-Bt#G`<>tQssod_I8~Z;|68C?3580iY zeCPXrXZyc?_VU$>)8Fp0!!n{J#s+UDeS+XU}I>szfk=_2c(Df-+TeL&--02y4clq#jUB!Z<}1YvpV zBthCK09`-sm}aTbp1HtK)_qw3l9a~g1yt`=bme(jH-(+F-Y!ZyDJR%qRsN%fmU>{# zlcur$;#CunnT#?!uHn|ba)!?S=1r)u>+g^4ZT8|4;ne|7SwQ{r|Ig?y}-0 z>M@Tu>{9Yd))xC?Kw!@Qn4%a7pt?sW)jZmN1>hd9<`FM;)E=aGde=Yhai}OdA`lUX z2t))P5dy9wS=&qemulIb|1ti%|B2Gs{(Fi45~*d3|LouTyIm`QKXn57Px>{@;Ggu_m>_M7ntz+|h-tZ^D3U zO=2M;5D|z7LaahpTF(=my)mLg0|29V*cNkqW!Rbm_Gk>nJSXV zUAzl|OzmsWiQ`vV%XYhCIE;j-b+TZ^0 zFvA?Eb%nO7b9|K|hk9Q_Zd?Csl^Z_K1;_QTROEmAGRK7ukjYY)T%rC1ou*$={|owXeE#n(sY9aTqf!IbVdX^2+0XWBY$T{rKtK*`JTuVZ;3&%pa`TpI|Qi{r@qY?rM&78)rVd62d7i|ut z^NZ&tsR1G8YwC)pDoBpdo8i1RIYRG-`f4ud=WH+@T1c8_i&m-{ zkoGh!^Se=&RK>z<#Y&lTgx>4O4(8-g^epA-ht7AK8opOo65XnXe(rQX?SkYhAPOkz+;UKA|{zos=|Q$}=zIe3HABk zbM?Iq9rVt>nRoglvWs^?psf06N7=c)n)Q^IHn&+}vXSk$e^;W_ASvNbh zus6jX7Uc~5j@{Kp(8zxA%Qj{?*xDRyRV45pMPm2%)PIxz(?xH1-3t!>FNF91gPeg0 kDmHj%_0~vZC+#