mirror of
https://github.com/anchore/syft.git
synced 2026-10-13 22:57:19 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f1aed4477 | ||
|
|
ddb338d834 | ||
|
|
354c72bbf4 | ||
|
|
d63a1f5f80 | ||
|
|
645206735e | ||
|
|
95a04cadea | ||
|
|
dd458a2b33 | ||
|
|
5f3d4d285b | ||
|
|
10c3cc27e8 | ||
|
|
a07bfe7dfa | ||
|
|
451cb9d5ca | ||
|
|
fd02bef0a3 | ||
|
|
02bd52728e | ||
|
|
c038f13d44 | ||
|
|
8102ad4edc | ||
|
|
13485ca5e7 | ||
|
|
b2b332e8b2 | ||
|
|
a42bac6fcc | ||
|
|
98a6c6efbe | ||
|
|
55a90a2ee0 | ||
|
|
6e835fd8fc | ||
|
|
ee80349ea0 | ||
|
|
52b54bbad9 | ||
|
|
66d9c5637b |
@@ -37,7 +37,7 @@ jobs:
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: syft/pkg/cataloger/java/test-fixtures/java-builds/packages
|
||||
key: ${{ runner.os }}-unit-java-cache-${{ hashFiles( 'syft/pkg/cataloger/java/test-fixtures/java-builds/packages.fingerprint' ) }}
|
||||
key: ${{ runner.os }}-unit-java-cache-${{ hashFiles( 'syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint' ) }}
|
||||
|
||||
- name: Restore RPM test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
|
||||
@@ -14,7 +14,7 @@ GOLANGCILINT_VERSION := v1.52.2
|
||||
GOSIMPORTS_VERSION := v0.3.8
|
||||
BOUNCER_VERSION := v0.4.0
|
||||
CHRONICLE_VERSION := v0.6.0
|
||||
GORELEASER_VERSION := v1.17.1
|
||||
GORELEASER_VERSION := v1.17.2
|
||||
YAJSV_VERSION := v1.4.1
|
||||
COSIGN_VERSION := v1.13.1
|
||||
QUILL_VERSION := v0.2.0
|
||||
@@ -199,7 +199,7 @@ fingerprints:
|
||||
|
||||
# for JAVA BUILD test fixtures
|
||||
cd syft/pkg/cataloger/java/test-fixtures/java-builds && \
|
||||
make packages.fingerprint
|
||||
make cache.fingerprint
|
||||
|
||||
# for GO BINARY test fixtures
|
||||
cd syft/pkg/cataloger/golang/test-fixtures/archs && \
|
||||
|
||||
@@ -152,39 +152,53 @@ This default behavior can be overridden with the `default-image-pull-source` con
|
||||
|
||||
##### Image Scanning:
|
||||
- alpmdb
|
||||
- rpmdb
|
||||
- dpkgdb
|
||||
- apkdb
|
||||
- portage
|
||||
- ruby-gemspec
|
||||
- python-package
|
||||
- php-composer-installed Cataloger
|
||||
- javascript-package
|
||||
- java
|
||||
- go-module-binary
|
||||
- binary
|
||||
- dotnet-deps
|
||||
- dpkgdb
|
||||
- go-module-binary
|
||||
- graalvm-native-image
|
||||
- java
|
||||
- javascript-package
|
||||
- linux-kernel
|
||||
- nix-store
|
||||
- php-composer-installed
|
||||
- portage
|
||||
- python-package
|
||||
- rpm-db
|
||||
- ruby-gemspec
|
||||
- sbom
|
||||
|
||||
##### Directory Scanning:
|
||||
- alpmdb
|
||||
- apkdb
|
||||
- dpkgdb
|
||||
- portage
|
||||
- rpmdb
|
||||
- ruby-gemfile
|
||||
- python-index
|
||||
- python-package
|
||||
- php-composer-lock
|
||||
- javascript-lock
|
||||
- java
|
||||
- java-pom
|
||||
- go-module-binary
|
||||
- go-mod-file
|
||||
- rust-cargo-lock
|
||||
- dartlang-lock
|
||||
- dotnet-deps
|
||||
- binary
|
||||
- cocoapods
|
||||
- conan
|
||||
- hackage
|
||||
- dartlang-lock
|
||||
- dotnet-deps
|
||||
- dpkgdb
|
||||
- elixir-mix-lock
|
||||
- erlang-rebar-lock
|
||||
- go-mod-file
|
||||
- go-module-binary
|
||||
- graalvm-native-image
|
||||
- haskell
|
||||
- java
|
||||
- java-gradle-lockfile
|
||||
- java-pom
|
||||
- javascript-lock
|
||||
- linux-kernel
|
||||
- nix-store
|
||||
- php-composer-lock
|
||||
- portage
|
||||
- python-index
|
||||
- python-package
|
||||
- rpm-db
|
||||
- rpm-file
|
||||
- ruby-gemfile
|
||||
- rust-cargo-lock
|
||||
- sbom
|
||||
|
||||
##### Non Default:
|
||||
- cargo-auditable-binary
|
||||
@@ -261,6 +275,8 @@ Which would produce output like:
|
||||
|
||||
Syft also includes a vast array of utility templating functions from [sprig](http://masterminds.github.io/sprig/) apart from the default Golang [text/template](https://pkg.go.dev/text/template#hdr-Functions) to allow users to customize the output format.
|
||||
|
||||
Lastly, Syft has custom templating functions defined in `./syft/format/template/encoder.go` to help parse the passed-in JSON structs.
|
||||
|
||||
## Multiple outputs
|
||||
|
||||
Syft can also output _multiple_ files in differing formats by appending
|
||||
@@ -460,26 +476,39 @@ platform: ""
|
||||
# set the list of package catalogers to use when generating the SBOM
|
||||
# default = empty (cataloger set determined automatically by the source type [image or file/directory])
|
||||
# catalogers:
|
||||
# - ruby-gemfile
|
||||
# - ruby-gemspec
|
||||
# - python-index
|
||||
# - python-package
|
||||
# - javascript-lock
|
||||
# - javascript-package
|
||||
# - php-composer-installed
|
||||
# - php-composer-lock
|
||||
# - alpmdb
|
||||
# - dpkgdb
|
||||
# - rpmdb
|
||||
# - java
|
||||
# - apkdb
|
||||
# - go-module-binary
|
||||
# - go-mod-file
|
||||
# - dartlang-lock
|
||||
# - rust
|
||||
# - dotnet-deps
|
||||
# rust-audit-binary scans Rust binaries built with https://github.com/Shnatsel/rust-audit
|
||||
# - rust-audit-binary
|
||||
# - alpmdb-cataloger
|
||||
# - apkdb-cataloger
|
||||
# - binary-cataloger
|
||||
# - cargo-auditable-binary-cataloger
|
||||
# - cocoapods-cataloger
|
||||
# - conan-cataloger
|
||||
# - dartlang-lock-cataloger
|
||||
# - dotnet-deps-cataloger
|
||||
# - dpkgdb-cataloger
|
||||
# - elixir-mix-lock-cataloger
|
||||
# - erlang-rebar-lock-cataloger
|
||||
# - go-mod-file-cataloger
|
||||
# - go-module-binary-cataloger
|
||||
# - graalvm-native-image-cataloger
|
||||
# - haskell-cataloger
|
||||
# - java-cataloger
|
||||
# - java-gradle-lockfile-cataloger
|
||||
# - java-pom-cataloger
|
||||
# - javascript-lock-cataloger
|
||||
# - javascript-package-cataloger
|
||||
# - linux-kernel-cataloger
|
||||
# - nix-store-cataloger
|
||||
# - php-composer-installed-cataloger
|
||||
# - php-composer-lock-cataloger
|
||||
# - portage-cataloger
|
||||
# - python-index-cataloger
|
||||
# - python-package-cataloger
|
||||
# - rpm-db-cataloger
|
||||
# - rpm-file-cataloger
|
||||
# - ruby-gemfile-cataloger
|
||||
# - ruby-gemspec-cataloger
|
||||
# - rust-cargo-lock-cataloger
|
||||
# - sbom-cataloger
|
||||
catalogers:
|
||||
|
||||
# cataloging packages is exposed through the packages and power-user subcommands
|
||||
|
||||
@@ -47,7 +47,7 @@ func generateCatalogPackagesTask(app *config.Application) (Task, error) {
|
||||
task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
|
||||
packageCatalog, relationships, theDistro, err := syft.CatalogPackages(src, app.ToCatalogerConfig())
|
||||
|
||||
results.PackageCatalog = packageCatalog
|
||||
results.Packages = packageCatalog
|
||||
results.LinuxDistribution = theDistro
|
||||
|
||||
return relationships, err
|
||||
|
||||
@@ -3,6 +3,8 @@ package main
|
||||
import (
|
||||
"log"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
|
||||
"github.com/anchore/syft/cmd/syft/cli"
|
||||
)
|
||||
|
||||
|
||||
@@ -49,23 +49,24 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.1-0.20221222100750-41a1ac565cce
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.1
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/anchore/go-logger v0.0.0-20220728155337-03b66a5207d8
|
||||
github.com/anchore/stereoscope v0.0.0-20230406143206-e95d60a265e3
|
||||
github.com/anchore/stereoscope v0.0.0-20230412183729-8602f1afc574
|
||||
github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da
|
||||
github.com/docker/docker v23.0.3+incompatible
|
||||
github.com/docker/docker v23.0.5+incompatible
|
||||
github.com/go-git/go-billy/v5 v5.4.1
|
||||
github.com/go-git/go-git/v5 v5.6.1
|
||||
github.com/google/go-containerregistry v0.14.0
|
||||
github.com/google/licensecheck v0.3.1
|
||||
github.com/invopop/jsonschema v0.7.0
|
||||
github.com/knqyf263/go-rpmdb v0.0.0-20221030135625-4082a22221ce
|
||||
github.com/knqyf263/go-rpmdb v0.0.0-20230301153543-ba94b245509b
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/sassoftware/go-rpmutils v0.2.0
|
||||
github.com/vbatts/go-mtree v0.5.3
|
||||
golang.org/x/exp v0.0.0-20230202163644-54bba9f4231b
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/sqlite v1.22.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -78,7 +79,7 @@ require (
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
|
||||
github.com/becheran/wildmatch-go v1.0.0 // indirect
|
||||
github.com/cloudflare/circl v1.1.0 // indirect
|
||||
github.com/containerd/containerd v1.6.18 // indirect
|
||||
github.com/containerd/containerd v1.7.0 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/docker/cli v23.0.1+incompatible // indirect
|
||||
@@ -104,23 +105,23 @@ require (
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.16.0 // indirect
|
||||
github.com/klauspost/compress v1.16.4 // indirect
|
||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.15 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.8.0 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
@@ -142,23 +143,22 @@ require (
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/tools v0.7.0 // indirect
|
||||
golang.org/x/tools v0.8.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect
|
||||
google.golang.org/grpc v1.52.0 // indirect
|
||||
google.golang.org/protobuf v1.29.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd // indirect
|
||||
google.golang.org/grpc v1.54.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
lukechampine.com/uint128 v1.1.1 // indirect
|
||||
modernc.org/cc/v3 v3.36.0 // indirect
|
||||
modernc.org/ccgo/v3 v3.16.6 // indirect
|
||||
modernc.org/libc v1.16.7 // indirect
|
||||
modernc.org/mathutil v1.4.1 // indirect
|
||||
modernc.org/memory v1.1.1 // indirect
|
||||
modernc.org/opt v0.1.1 // indirect
|
||||
modernc.org/sqlite v1.17.3 // indirect
|
||||
modernc.org/strutil v1.1.1 // indirect
|
||||
modernc.org/token v1.0.0 // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.40.0 // indirect
|
||||
modernc.org/ccgo/v3 v3.16.13 // indirect
|
||||
modernc.org/libc v1.22.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.5.0 // indirect
|
||||
modernc.org/opt v0.1.3 // indirect
|
||||
modernc.org/strutil v1.1.3 // indirect
|
||||
modernc.org/token v1.0.1 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
@@ -54,8 +54,8 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg6
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.1-0.20221222100750-41a1ac565cce h1:o5r3msApzvtE5LhcMkxWaKernD/PK0HpMccu7ywBj5Q=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.1-0.20221222100750-41a1ac565cce/go.mod h1:XURd0m8zvnLE5aIRqg6JOVRl7qZ/pWBtuFa9EHjQwFc=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.1 h1:5w1SxjGm9MTMNTuRbEPyw21ObdbaagTWF/KfF0qHTRE=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.1/go.mod h1:N/nrdWQI2SIjaACyyDs/u7+ddCkyl/zkNs8xFsHF2Ps=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
@@ -95,8 +95,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501 h1:AV7qjwMcM4r8wFhJq3jLRztew3ywIyPTRapl2T1s9o8=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4=
|
||||
github.com/anchore/stereoscope v0.0.0-20230406143206-e95d60a265e3 h1:F662TNGcpBfB1ZmCJJUot4EBHGxCKvTPvub01qaWxX0=
|
||||
github.com/anchore/stereoscope v0.0.0-20230406143206-e95d60a265e3/go.mod h1:u44RadbOJB103GwtYzJ2Kdad9J+SmZMW98jCYBJkSzs=
|
||||
github.com/anchore/stereoscope v0.0.0-20230412183729-8602f1afc574 h1:VFX+FD9EH6am+tfqwr1KeCAmabAknSJQX95aIY3QJJI=
|
||||
github.com/anchore/stereoscope v0.0.0-20230412183729-8602f1afc574/go.mod h1:2GGFHkHry/xDlEQgBrVGcarq+z7Z6hLnHdyhcKB2lfQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
@@ -144,8 +144,8 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/containerd/containerd v1.6.18 h1:qZbsLvmyu+Vlty0/Ex5xc0z2YtKpIsb5n45mAMI+2Ns=
|
||||
github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw=
|
||||
github.com/containerd/containerd v1.7.0 h1:G/ZQr3gMZs6ZT0qPUZ15znx5QSdQdASW11nXTLTM2Pg=
|
||||
github.com/containerd/containerd v1.7.0/go.mod h1:QfR7Efgb/6X2BDpTPJRvPTYDE9rsF0FsXX9J8sIs/sc=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@@ -165,8 +165,8 @@ github.com/docker/cli v23.0.1+incompatible h1:LRyWITpGzl2C9e9uGxzisptnxAn1zfZKXy
|
||||
github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
||||
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v23.0.3+incompatible h1:9GhVsShNWz1hO//9BNg/dpMnZW25KydO4wtVxWAIbho=
|
||||
github.com/docker/docker v23.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v23.0.5+incompatible h1:DaxtlTJjFSnLOXVNUBU1+6kXGz2lpDoEAH6QoxaSg8k=
|
||||
github.com/docker/docker v23.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
@@ -176,7 +176,6 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
@@ -207,6 +206,7 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS
|
||||
github.com/gabriel-vasile/mimetype v1.4.0 h1:Cn9dkdYsMIu56tGho+fqzh7XmvY2YyGU0FnbhiOsEro=
|
||||
github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
@@ -312,6 +312,7 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@@ -398,13 +399,13 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
|
||||
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU=
|
||||
github.com/klauspost/compress v1.16.4/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/knqyf263/go-rpmdb v0.0.0-20221030135625-4082a22221ce h1:/w0hAcauo/FBVaBvNMQdPZgKjTu5Ip3jvGIM1+VUE7o=
|
||||
github.com/knqyf263/go-rpmdb v0.0.0-20221030135625-4082a22221ce/go.mod h1:zp6SMcRd0GB+uwNJjr+DkrNZdQZ4er2HMO6KyD0vIGU=
|
||||
github.com/knqyf263/go-rpmdb v0.0.0-20230301153543-ba94b245509b h1:boYyvL3tbUuKcMN029mpCl7oYYJ7yIXujLj+fiW4Alc=
|
||||
github.com/knqyf263/go-rpmdb v0.0.0-20230301153543-ba94b245509b/go.mod h1:9LQcoMCMQ9vrF7HcDtXfvqGO4+ddxFQ8+YF/0CVGDww=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
@@ -438,13 +439,13 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0=
|
||||
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
@@ -489,8 +490,8 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
@@ -526,8 +527,9 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
@@ -964,7 +966,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
@@ -978,8 +979,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
|
||||
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1090,8 +1091,8 @@ google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ6
|
||||
google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY=
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd h1:sLpv7bNL1AsX3fdnWh9WVh7ejIzXdOc1RRHGeAmeStU=
|
||||
google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -1119,8 +1120,8 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk=
|
||||
google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
|
||||
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
|
||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
@@ -1135,8 +1136,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0=
|
||||
google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -1173,41 +1174,30 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
|
||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.36.0 h1:0kmRkTmqNidmu3c7BNDSdVHCxXCkWLmWmCIVX4LUboo=
|
||||
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
|
||||
modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=
|
||||
modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw=
|
||||
modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
|
||||
modernc.org/ccgo/v3 v3.16.6 h1:3l18poV+iUemQ98O3X5OMr97LOqlzis+ytivU4NqGhA=
|
||||
modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
|
||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
|
||||
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
||||
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
||||
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
|
||||
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
|
||||
modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A=
|
||||
modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU=
|
||||
modernc.org/libc v1.16.7 h1:qzQtHhsZNpVPpeCu+aMIQldXeV1P0vRhSqCL0nOIJOA=
|
||||
modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
|
||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
|
||||
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU=
|
||||
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
|
||||
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.17.3 h1:iE+coC5g17LtByDYDWKpR6m2Z9022YrSh3bumwOnIrI=
|
||||
modernc.org/sqlite v1.17.3/go.mod h1:10hPVYar9C0kfXuTWGz8s0XtB8uAGymUy51ZzStYe3k=
|
||||
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
|
||||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
|
||||
modernc.org/tcl v1.13.1 h1:npxzTwFTZYM8ghWicVIX1cRWzj7Nd8i6AqqX2p+IYao=
|
||||
modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw=
|
||||
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
|
||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.5.1 h1:RTNHdsrOpeoSeOF4FbzTo8gBYByaJ5xT7NgZ9ZqRiJM=
|
||||
modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=
|
||||
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
|
||||
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
||||
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.22.1 h1:P2+Dhp5FR1RlVRkQ3dDfCiv3Ok8XPxqpe70IjYVA9oE=
|
||||
modernc.org/sqlite v1.22.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||
modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
|
||||
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
|
||||
@@ -6,5 +6,5 @@ const (
|
||||
|
||||
// JSONSchemaVersion is the current schema version output by the JSON encoder
|
||||
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
|
||||
JSONSchemaVersion = "7.1.4"
|
||||
JSONSchemaVersion = "7.1.5"
|
||||
)
|
||||
|
||||
+29
-28
@@ -30,34 +30,35 @@ can be extended to include specific package metadata struct shapes in the future
|
||||
|
||||
// TODO: this should be generated from reflection of whats in the pkg package
|
||||
type artifactMetadataContainer struct {
|
||||
Alpm pkg.AlpmMetadata
|
||||
Apk pkg.ApkMetadata
|
||||
Binary pkg.BinaryMetadata
|
||||
Cocopods pkg.CocoapodsMetadata
|
||||
Conan pkg.ConanMetadata
|
||||
ConanLock pkg.ConanLockMetadata
|
||||
Dart pkg.DartPubMetadata
|
||||
Dotnet pkg.DotnetDepsMetadata
|
||||
Dpkg pkg.DpkgMetadata
|
||||
Gem pkg.GemMetadata
|
||||
GoBin pkg.GolangBinMetadata
|
||||
GoMod pkg.GolangModMetadata
|
||||
Hackage pkg.HackageMetadata
|
||||
Java pkg.JavaMetadata
|
||||
KbPackage pkg.KbPackageMetadata
|
||||
LinuxKernel pkg.LinuxKernelMetadata
|
||||
LinuxKernelModule pkg.LinuxKernelModuleMetadata
|
||||
Nix pkg.NixStoreMetadata
|
||||
NpmPackage pkg.NpmPackageJSONMetadata
|
||||
NpmPackageLock pkg.NpmPackageLockJSONMetadata
|
||||
MixLock pkg.MixLockMetadata
|
||||
Php pkg.PhpComposerJSONMetadata
|
||||
Portage pkg.PortageMetadata
|
||||
PythonPackage pkg.PythonPackageMetadata
|
||||
PythonPipfilelock pkg.PythonPipfileLockMetadata
|
||||
Rebar pkg.RebarLockMetadata
|
||||
Rpm pkg.RpmMetadata
|
||||
RustCargo pkg.CargoPackageMetadata
|
||||
Alpm pkg.AlpmMetadata
|
||||
Apk pkg.ApkMetadata
|
||||
Binary pkg.BinaryMetadata
|
||||
Cocopods pkg.CocoapodsMetadata
|
||||
Conan pkg.ConanMetadata
|
||||
ConanLock pkg.ConanLockMetadata
|
||||
Dart pkg.DartPubMetadata
|
||||
Dotnet pkg.DotnetDepsMetadata
|
||||
Dpkg pkg.DpkgMetadata
|
||||
Gem pkg.GemMetadata
|
||||
GoBin pkg.GolangBinMetadata
|
||||
GoMod pkg.GolangModMetadata
|
||||
Hackage pkg.HackageMetadata
|
||||
Java pkg.JavaMetadata
|
||||
KbPackage pkg.KbPackageMetadata
|
||||
LinuxKernel pkg.LinuxKernelMetadata
|
||||
LinuxKernelModule pkg.LinuxKernelModuleMetadata
|
||||
Nix pkg.NixStoreMetadata
|
||||
NpmPackage pkg.NpmPackageJSONMetadata
|
||||
NpmPackageLock pkg.NpmPackageLockJSONMetadata
|
||||
MixLock pkg.MixLockMetadata
|
||||
Php pkg.PhpComposerJSONMetadata
|
||||
Portage pkg.PortageMetadata
|
||||
PythonPackage pkg.PythonPackageMetadata
|
||||
PythonPipfilelock pkg.PythonPipfileLockMetadata
|
||||
PythonRequirements pkg.PythonRequirementsMetadata
|
||||
Rebar pkg.RebarLockMetadata
|
||||
Rpm pkg.RpmMetadata
|
||||
RustCargo pkg.CargoPackageMetadata
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ import (
|
||||
"flag"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -144,6 +145,12 @@ func TestFileMetadataCataloger(t *testing.T) {
|
||||
|
||||
l := source.NewLocationFromImage(test.path, *ref.Reference, img)
|
||||
|
||||
if _, ok := actual[l.Coordinates]; ok {
|
||||
redact := actual[l.Coordinates]
|
||||
redact.ModTime = time.Time{}
|
||||
actual[l.Coordinates] = redact
|
||||
}
|
||||
|
||||
assert.Equal(t, test.expected, actual[l.Coordinates], "mismatched metadata")
|
||||
|
||||
})
|
||||
|
||||
@@ -54,7 +54,7 @@ func ToSyftModel(bom *cyclonedx.BOM) (*sbom.SBOM, error) {
|
||||
|
||||
s := &sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
PackageCatalog: pkg.NewCatalog(),
|
||||
Packages: pkg.NewCollection(),
|
||||
LinuxDistribution: linuxReleaseFromComponents(*bom.Components),
|
||||
},
|
||||
Source: extractComponents(bom.Metadata),
|
||||
@@ -95,7 +95,7 @@ func collectPackages(component *cyclonedx.Component, s *sbom.SBOM, idMap map[str
|
||||
}
|
||||
// TODO there must be a better way than needing to call this manually:
|
||||
p.SetID()
|
||||
s.Artifacts.PackageCatalog.Add(*p)
|
||||
s.Artifacts.Packages.Add(*p)
|
||||
}
|
||||
|
||||
if component.Components != nil {
|
||||
|
||||
@@ -210,7 +210,7 @@ func Test_decode(t *testing.T) {
|
||||
assert.Equal(t, e.ver, sbom.Artifacts.LinuxDistribution.VersionID)
|
||||
}
|
||||
if e.pkg != "" {
|
||||
for p := range sbom.Artifacts.PackageCatalog.Enumerate() {
|
||||
for p := range sbom.Artifacts.Packages.Enumerate() {
|
||||
if e.pkg != p.Name {
|
||||
continue
|
||||
}
|
||||
@@ -238,7 +238,7 @@ func Test_decode(t *testing.T) {
|
||||
if e.relation != "" {
|
||||
foundRelation := false
|
||||
for _, r := range sbom.Relationships {
|
||||
p := sbom.Artifacts.PackageCatalog.Package(r.To.ID())
|
||||
p := sbom.Artifacts.Packages.Package(r.To.ID())
|
||||
if e.relation == p.Name {
|
||||
foundRelation = true
|
||||
break
|
||||
|
||||
@@ -25,7 +25,7 @@ func ToFormatModel(s sbom.SBOM) *cyclonedx.BOM {
|
||||
cdxBOM.SerialNumber = uuid.New().URN()
|
||||
cdxBOM.Metadata = toBomDescriptor(internal.ApplicationName, s.Descriptor.Version, s.Source)
|
||||
|
||||
packages := s.Artifacts.PackageCatalog.Sorted()
|
||||
packages := s.Artifacts.Packages.Sorted()
|
||||
components := make([]cyclonedx.Component, len(packages))
|
||||
for i, p := range packages {
|
||||
components[i] = encodeComponent(p)
|
||||
|
||||
@@ -4,6 +4,7 @@ package spdxhelpers
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -123,28 +124,45 @@ func ToFormatModel(s sbom.SBOM) *spdx.Document {
|
||||
// Cardinality: optional, one
|
||||
CreatorComment: "",
|
||||
},
|
||||
Packages: toPackages(s.Artifacts.PackageCatalog, s),
|
||||
Packages: toPackages(s.Artifacts.Packages, s),
|
||||
Files: toFiles(s),
|
||||
Relationships: relationships,
|
||||
OtherLicenses: toOtherLicenses(s.Artifacts.PackageCatalog),
|
||||
OtherLicenses: toOtherLicenses(s.Artifacts.Packages),
|
||||
}
|
||||
}
|
||||
|
||||
func toSPDXID(identifiable artifact.Identifiable) spdx.ElementID {
|
||||
maxLen := 40
|
||||
id := ""
|
||||
if p, ok := identifiable.(pkg.Package); ok {
|
||||
id = SanitizeElementID(fmt.Sprintf("Package-%+v-%s-%s", p.Type, p.Name, p.ID()))
|
||||
} else {
|
||||
switch it := identifiable.(type) {
|
||||
case pkg.Package:
|
||||
id = SanitizeElementID(fmt.Sprintf("Package-%s-%s-%s", it.Type, it.Name, it.ID()))
|
||||
case source.Coordinates:
|
||||
p := ""
|
||||
parts := strings.Split(it.RealPath, "/")
|
||||
for i := len(parts); i > 0; i-- {
|
||||
part := parts[i-1]
|
||||
if len(part) == 0 {
|
||||
continue
|
||||
}
|
||||
if i < len(parts) && len(p)+len(part)+3 > maxLen {
|
||||
p = "..." + p
|
||||
break
|
||||
}
|
||||
p = path.Join(part, p)
|
||||
}
|
||||
id = SanitizeElementID(fmt.Sprintf("File-%s-%s", p, it.ID()))
|
||||
default:
|
||||
id = string(identifiable.ID())
|
||||
}
|
||||
// NOTE: the spdx libraries prepend SPDXRef-, so we don't do it here
|
||||
// NOTE: the spdx library prepend SPDXRef-, so we don't do it here
|
||||
return spdx.ElementID(id)
|
||||
}
|
||||
|
||||
// packages populates all Package Information from the package Catalog (see https://spdx.github.io/spdx-spec/3-package-information/)
|
||||
// packages populates all Package Information from the package Collection (see https://spdx.github.io/spdx-spec/3-package-information/)
|
||||
//
|
||||
//nolint:funlen
|
||||
func toPackages(catalog *pkg.Catalog, sbom sbom.SBOM) (results []*spdx.Package) {
|
||||
func toPackages(catalog *pkg.Collection, sbom sbom.SBOM) (results []*spdx.Package) {
|
||||
for _, p := range catalog.Sorted() {
|
||||
// name should be guaranteed to be unique, but semantically useful and stable
|
||||
id := toSPDXID(p)
|
||||
@@ -516,7 +534,7 @@ func toFileTypes(metadata *source.FileMetadata) (ty []string) {
|
||||
return ty
|
||||
}
|
||||
|
||||
func toOtherLicenses(catalog *pkg.Catalog) []*spdx.OtherLicense {
|
||||
func toOtherLicenses(catalog *pkg.Collection) []*spdx.OtherLicense {
|
||||
licenses := map[string]bool{}
|
||||
for _, p := range catalog.Sorted() {
|
||||
for _, license := range parseLicenses(p.Licenses) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package spdxhelpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/spdx/tools-golang/spdx"
|
||||
@@ -421,7 +422,7 @@ func Test_H1Digest(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
catalog := pkg.NewCatalog(test.pkg)
|
||||
catalog := pkg.NewCollection(test.pkg)
|
||||
pkgs := toPackages(catalog, s)
|
||||
require.Len(t, pkgs, 1)
|
||||
for _, p := range pkgs {
|
||||
@@ -494,10 +495,50 @@ func Test_OtherLicenses(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
catalog := pkg.NewCatalog(test.pkg)
|
||||
catalog := pkg.NewCollection(test.pkg)
|
||||
otherLicenses := toOtherLicenses(catalog)
|
||||
require.Len(t, otherLicenses, len(test.expected))
|
||||
require.Equal(t, test.expected, otherLicenses)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_toSPDXID(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
it artifact.Identifiable
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "short filename",
|
||||
it: source.Coordinates{
|
||||
RealPath: "/short/path/file.txt",
|
||||
},
|
||||
expected: "File-short-path-file.txt",
|
||||
},
|
||||
{
|
||||
name: "long filename",
|
||||
it: source.Coordinates{
|
||||
RealPath: "/some/long/path/with/a/lot/of-text/that-contains-a/file.txt",
|
||||
},
|
||||
expected: "File-...a-lot-of-text-that-contains-a-file.txt",
|
||||
},
|
||||
{
|
||||
name: "package",
|
||||
it: pkg.Package{
|
||||
Type: pkg.NpmPkg,
|
||||
Name: "some-package",
|
||||
},
|
||||
expected: "Package-npm-some-package",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got := string(toSPDXID(test.it))
|
||||
// trim the hash
|
||||
got = regexp.MustCompile(`-[a-z0-9]*$`).ReplaceAllString(got, "")
|
||||
require.Equal(t, test.expected, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func ToSyftModel(doc *spdx.Document) (*sbom.SBOM, error) {
|
||||
s := &sbom.SBOM{
|
||||
Source: src,
|
||||
Artifacts: sbom.Artifacts{
|
||||
PackageCatalog: pkg.NewCatalog(),
|
||||
Packages: pkg.NewCollection(),
|
||||
FileMetadata: map[source.Coordinates]source.FileMetadata{},
|
||||
FileDigests: map[source.Coordinates][]file.Digest{},
|
||||
LinuxDistribution: findLinuxReleaseByPURL(doc),
|
||||
@@ -110,7 +110,7 @@ func collectSyftPackages(s *sbom.SBOM, spdxIDMap map[string]interface{}, doc *sp
|
||||
for _, p := range doc.Packages {
|
||||
syftPkg := toSyftPackage(p)
|
||||
spdxIDMap[string(p.PackageSPDXIdentifier)] = syftPkg
|
||||
s.Artifacts.PackageCatalog.Add(*syftPkg)
|
||||
s.Artifacts.Packages.Add(*syftPkg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ func TestToSyftModel(t *testing.T) {
|
||||
|
||||
assert.NotNil(t, sbom)
|
||||
|
||||
pkgs := sbom.Artifacts.PackageCatalog.Sorted()
|
||||
pkgs := sbom.Artifacts.Packages.Sorted()
|
||||
|
||||
assert.Len(t, pkgs, 2)
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ func Test_decodeJSON(t *testing.T) {
|
||||
split = strings.SplitN(pkg, ":", 2)
|
||||
name = split[0]
|
||||
version = split[1]
|
||||
for p := range bom.Artifacts.PackageCatalog.Enumerate() {
|
||||
for p := range bom.Artifacts.Packages.Enumerate() {
|
||||
if p.Name == name {
|
||||
assert.Equal(t, version, p.Version)
|
||||
continue pkgs
|
||||
|
||||
@@ -33,14 +33,18 @@ func TestCycloneDxImageEncoder(t *testing.T) {
|
||||
}
|
||||
|
||||
func cycloneDxRedactor(s []byte) []byte {
|
||||
serialPattern := regexp.MustCompile(`urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`)
|
||||
rfc3339Pattern := regexp.MustCompile(`([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))`)
|
||||
sha256Pattern := regexp.MustCompile(`sha256:[A-Fa-f0-9]{64}`)
|
||||
for _, pattern := range []*regexp.Regexp{serialPattern, rfc3339Pattern, sha256Pattern} {
|
||||
s = pattern.ReplaceAll(s, []byte(""))
|
||||
replacements := map[string]string{
|
||||
// UUIDs
|
||||
`urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`: `urn:uuid:redacted`,
|
||||
// timestamps
|
||||
`([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))`: `timestamp:redacted`,
|
||||
// image hashes
|
||||
`sha256:[A-Fa-f0-9]{64}`: `sha256:redacted`,
|
||||
// bom-refs
|
||||
`"bom-ref":\s*"[^"]+"`: `"bom-ref": "redacted"`,
|
||||
}
|
||||
for pattern, replacement := range replacements {
|
||||
s = regexp.MustCompile(pattern).ReplaceAll(s, []byte(replacement))
|
||||
}
|
||||
// the bom-ref will be autogenerated every time, the value here should not be directly tested in snapshot tests
|
||||
s = regexp.MustCompile(`\s+"bom-ref":\s*"[^"]+",?\n`).ReplaceAll(s, []byte(""))
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,10 +1,11 @@
|
||||
{
|
||||
"$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.4",
|
||||
"serialNumber": "urn:uuid:0b628da1-274e-4c24-821c-f9452f37db54",
|
||||
"serialNumber": "urn:uuid:redacted",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2022-12-22T18:33:51-05:00",
|
||||
"timestamp": "timestamp:redacted",
|
||||
"tools": [
|
||||
{
|
||||
"vendor": "anchore",
|
||||
@@ -13,14 +14,14 @@
|
||||
}
|
||||
],
|
||||
"component": {
|
||||
"bom-ref": "163686ac6e30c752",
|
||||
"bom-ref": "redacted",
|
||||
"type": "file",
|
||||
"name": "/some/path"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"bom-ref": "1b1d0be59ac59d2c",
|
||||
"bom-ref": "redacted",
|
||||
"type": "library",
|
||||
"name": "package-1",
|
||||
"version": "1.0.1",
|
||||
@@ -57,7 +58,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"bom-ref": "pkg:deb/debian/package-2@2.0.1?package-id=db4abfe497c180d3",
|
||||
"bom-ref": "redacted",
|
||||
"type": "library",
|
||||
"name": "package-2",
|
||||
"version": "2.0.1",
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
{
|
||||
"$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.4",
|
||||
"serialNumber": "urn:uuid:542fc1a1-81ac-4b76-b9e2-8e6b9d8c840a",
|
||||
"serialNumber": "urn:uuid:redacted",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2022-12-22T18:33:51-05:00",
|
||||
"timestamp": "timestamp:redacted",
|
||||
"tools": [
|
||||
{
|
||||
"vendor": "anchore",
|
||||
@@ -13,15 +14,15 @@
|
||||
}
|
||||
],
|
||||
"component": {
|
||||
"bom-ref": "ffd645a093c0fe70",
|
||||
"bom-ref": "redacted",
|
||||
"type": "container",
|
||||
"name": "user-image-input",
|
||||
"version": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368"
|
||||
"version": "sha256:redacted"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"bom-ref": "66ba429119b8bec6",
|
||||
"bom-ref": "redacted",
|
||||
"type": "library",
|
||||
"name": "package-1",
|
||||
"version": "1.0.1",
|
||||
@@ -53,7 +54,7 @@
|
||||
},
|
||||
{
|
||||
"name": "syft:location:0:layerID",
|
||||
"value": "sha256:62058900d4ce269c900160b8dd255fe310c3a459dda236d041102fa070f84406"
|
||||
"value": "sha256:redacted"
|
||||
},
|
||||
{
|
||||
"name": "syft:location:0:path",
|
||||
@@ -62,7 +63,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"bom-ref": "pkg:deb/debian/package-2@2.0.1?package-id=958443e2d9304af4",
|
||||
"bom-ref": "redacted",
|
||||
"type": "library",
|
||||
"name": "package-2",
|
||||
"version": "2.0.1",
|
||||
@@ -83,7 +84,7 @@
|
||||
},
|
||||
{
|
||||
"name": "syft:location:0:layerID",
|
||||
"value": "sha256:623ad97366f39ae279f1925673cdacb4851ddf2e3266f04e63010ec080a098c1"
|
||||
"value": "sha256:redacted"
|
||||
},
|
||||
{
|
||||
"name": "syft:location:0:path",
|
||||
|
||||
@@ -57,7 +57,7 @@ func Test_decodeXML(t *testing.T) {
|
||||
split = strings.SplitN(pkg, ":", 2)
|
||||
name = split[0]
|
||||
version = split[1]
|
||||
for p := range bom.Artifacts.PackageCatalog.Enumerate() {
|
||||
for p := range bom.Artifacts.Packages.Enumerate() {
|
||||
if p.Name == name {
|
||||
assert.Equal(t, version, p.Version)
|
||||
continue pkgs
|
||||
|
||||
@@ -107,7 +107,7 @@ func toPath(s source.Metadata, p pkg.Package) string {
|
||||
func toGithubManifests(s *sbom.SBOM) Manifests {
|
||||
manifests := map[string]*Manifest{}
|
||||
|
||||
for _, p := range s.Artifacts.PackageCatalog.Sorted() {
|
||||
for _, p := range s.Artifacts.Packages.Sorted() {
|
||||
path := toPath(s.Source, p)
|
||||
manifest, ok := manifests[path]
|
||||
if !ok {
|
||||
|
||||
@@ -28,7 +28,7 @@ func Test_toGithubModel(t *testing.T) {
|
||||
VersionID: "18.04",
|
||||
IDLike: []string{"debian"},
|
||||
},
|
||||
PackageCatalog: pkg.NewCatalog(),
|
||||
Packages: pkg.NewCollection(),
|
||||
},
|
||||
}
|
||||
for _, p := range []pkg.Package{
|
||||
@@ -71,7 +71,7 @@ func Test_toGithubModel(t *testing.T) {
|
||||
nil,
|
||||
"",
|
||||
).ToString()
|
||||
s.Artifacts.PackageCatalog.Add(p)
|
||||
s.Artifacts.Packages.Add(p)
|
||||
}
|
||||
|
||||
actual := toGithubModel(&s)
|
||||
|
||||
@@ -15,13 +15,11 @@ func Format() sbom.Format {
|
||||
func(writer io.Writer, sbom sbom.SBOM) error {
|
||||
bom := toGithubModel(&sbom)
|
||||
|
||||
bytes, err := json.MarshalIndent(bom, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.Write(bytes)
|
||||
encoder := json.NewEncoder(writer)
|
||||
encoder.SetEscapeHTML(false)
|
||||
encoder.SetIndent("", " ")
|
||||
|
||||
return err
|
||||
return encoder.Encode(bom)
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
|
||||
@@ -54,14 +54,8 @@ func AssertEncoderAgainstGoldenImageSnapshot(t *testing.T, format sbom.Format, s
|
||||
testutils.UpdateGoldenFileContents(t, actual)
|
||||
}
|
||||
|
||||
var expected = testutils.GetGoldenFileContents(t)
|
||||
|
||||
// remove dynamic values, which should be tested independently
|
||||
redactors = append(redactors, carriageRedactor)
|
||||
for _, r := range redactors {
|
||||
actual = r(actual)
|
||||
expected = r(expected)
|
||||
}
|
||||
actual = redact(actual, redactors...)
|
||||
expected := redact(testutils.GetGoldenFileContents(t), redactors...)
|
||||
|
||||
if json {
|
||||
require.JSONEq(t, string(expected), string(actual))
|
||||
@@ -85,14 +79,8 @@ func AssertEncoderAgainstGoldenSnapshot(t *testing.T, format sbom.Format, sbom s
|
||||
testutils.UpdateGoldenFileContents(t, actual)
|
||||
}
|
||||
|
||||
var expected = testutils.GetGoldenFileContents(t)
|
||||
|
||||
// remove dynamic values, which should be tested independently
|
||||
redactors = append(redactors, carriageRedactor)
|
||||
for _, r := range redactors {
|
||||
actual = r(actual)
|
||||
expected = r(expected)
|
||||
}
|
||||
actual = redact(actual, redactors...)
|
||||
expected := redact(testutils.GetGoldenFileContents(t), redactors...)
|
||||
|
||||
if json {
|
||||
require.JSONEq(t, string(expected), string(actual))
|
||||
@@ -107,7 +95,7 @@ func AssertEncoderAgainstGoldenSnapshot(t *testing.T, format sbom.Format, sbom s
|
||||
|
||||
func ImageInput(t testing.TB, testImage string, options ...ImageOption) sbom.SBOM {
|
||||
t.Helper()
|
||||
catalog := pkg.NewCatalog()
|
||||
catalog := pkg.NewCollection()
|
||||
var cfg imageCfg
|
||||
var img *image.Image
|
||||
for _, opt := range options {
|
||||
@@ -131,7 +119,7 @@ func ImageInput(t testing.TB, testImage string, options ...ImageOption) sbom.SBO
|
||||
|
||||
return sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
PackageCatalog: catalog,
|
||||
Packages: catalog,
|
||||
LinuxDistribution: &linux.Release{
|
||||
PrettyName: "debian",
|
||||
Name: "debian",
|
||||
@@ -159,7 +147,7 @@ func carriageRedactor(s []byte) []byte {
|
||||
return []byte(msg)
|
||||
}
|
||||
|
||||
func populateImageCatalog(catalog *pkg.Catalog, img *image.Image) {
|
||||
func populateImageCatalog(catalog *pkg.Collection, img *image.Image) {
|
||||
_, ref1, _ := img.SquashedTree().File("/somefile-1.txt", filetree.FollowBasenameLinks)
|
||||
_, ref2, _ := img.SquashedTree().File("/somefile-2.txt", filetree.FollowBasenameLinks)
|
||||
|
||||
@@ -212,7 +200,7 @@ func DirectoryInput(t testing.TB) sbom.SBOM {
|
||||
|
||||
return sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
PackageCatalog: catalog,
|
||||
Packages: catalog,
|
||||
LinuxDistribution: &linux.Release{
|
||||
PrettyName: "debian",
|
||||
Name: "debian",
|
||||
@@ -235,8 +223,39 @@ func DirectoryInput(t testing.TB) sbom.SBOM {
|
||||
}
|
||||
}
|
||||
|
||||
func newDirectoryCatalog() *pkg.Catalog {
|
||||
catalog := pkg.NewCatalog()
|
||||
func DirectoryInputWithAuthorField(t testing.TB) sbom.SBOM {
|
||||
catalog := newDirectoryCatalogWithAuthorField()
|
||||
|
||||
src, err := source.NewFromDirectory("/some/path")
|
||||
assert.NoError(t, err)
|
||||
|
||||
return sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
Packages: catalog,
|
||||
LinuxDistribution: &linux.Release{
|
||||
PrettyName: "debian",
|
||||
Name: "debian",
|
||||
ID: "debian",
|
||||
IDLike: []string{"like!"},
|
||||
Version: "1.2.3",
|
||||
VersionID: "1.2.3",
|
||||
},
|
||||
},
|
||||
Source: src.Metadata,
|
||||
Descriptor: sbom.Descriptor{
|
||||
Name: "syft",
|
||||
Version: "v0.42.0-bogus",
|
||||
// the application configuration should be persisted here, however, we do not want to import
|
||||
// the application configuration in this package (it's reserved only for ingestion by the cmd package)
|
||||
Configuration: map[string]string{
|
||||
"config-key": "config-value",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDirectoryCatalog() *pkg.Collection {
|
||||
catalog := pkg.NewCollection()
|
||||
|
||||
// populate catalog with test data
|
||||
catalog.Add(pkg.Package{
|
||||
@@ -286,9 +305,61 @@ func newDirectoryCatalog() *pkg.Catalog {
|
||||
return catalog
|
||||
}
|
||||
|
||||
func newDirectoryCatalogWithAuthorField() *pkg.Collection {
|
||||
catalog := pkg.NewCollection()
|
||||
|
||||
// populate catalog with test data
|
||||
catalog.Add(pkg.Package{
|
||||
Name: "package-1",
|
||||
Version: "1.0.1",
|
||||
Type: pkg.PythonPkg,
|
||||
FoundBy: "the-cataloger-1",
|
||||
Locations: source.NewLocationSet(
|
||||
source.NewLocation("/some/path/pkg1"),
|
||||
),
|
||||
Language: pkg.Python,
|
||||
MetadataType: pkg.PythonPackageMetadataType,
|
||||
Licenses: []string{"MIT"},
|
||||
Metadata: pkg.PythonPackageMetadata{
|
||||
Name: "package-1",
|
||||
Version: "1.0.1",
|
||||
Author: "test-author",
|
||||
Files: []pkg.PythonFileRecord{
|
||||
{
|
||||
Path: "/some/path/pkg1/dependencies/foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
PURL: "a-purl-2", // intentionally a bad pURL for test fixtures
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"),
|
||||
},
|
||||
})
|
||||
catalog.Add(pkg.Package{
|
||||
Name: "package-2",
|
||||
Version: "2.0.1",
|
||||
Type: pkg.DebPkg,
|
||||
FoundBy: "the-cataloger-2",
|
||||
Locations: source.NewLocationSet(
|
||||
source.NewLocation("/some/path/pkg1"),
|
||||
),
|
||||
MetadataType: pkg.DpkgMetadataType,
|
||||
Metadata: pkg.DpkgMetadata{
|
||||
Package: "package-2",
|
||||
Version: "2.0.1",
|
||||
},
|
||||
PURL: "pkg:deb/debian/package-2@2.0.1",
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"),
|
||||
},
|
||||
})
|
||||
|
||||
return catalog
|
||||
}
|
||||
|
||||
//nolint:gosec
|
||||
func AddSampleFileRelationships(s *sbom.SBOM) {
|
||||
catalog := s.Artifacts.PackageCatalog.Sorted()
|
||||
catalog := s.Artifacts.Packages.Sorted()
|
||||
s.Artifacts.FileMetadata = map[source.Coordinates]source.FileMetadata{}
|
||||
|
||||
files := []string{"/f1", "/f2", "/d1/f3", "/d2/f4", "/z1/f5", "/a1/f6"}
|
||||
@@ -307,3 +378,12 @@ func AddSampleFileRelationships(s *sbom.SBOM) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// remove dynamic values, which should be tested independently
|
||||
func redact(b []byte, redactors ...redactor) []byte {
|
||||
redactors = append(redactors, carriageRedactor)
|
||||
for _, r := range redactors {
|
||||
b = r(b)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -73,11 +73,11 @@ func TestSPDXJSONDecoder(t *testing.T) {
|
||||
}
|
||||
|
||||
if test.packages != nil {
|
||||
assert.Equal(t, sbom.Artifacts.PackageCatalog.PackageCount(), len(test.packages))
|
||||
assert.Equal(t, sbom.Artifacts.Packages.PackageCount(), len(test.packages))
|
||||
|
||||
packages:
|
||||
for _, pkgName := range test.packages {
|
||||
for _, p := range sbom.Artifacts.PackageCatalog.Sorted() {
|
||||
for _, p := range sbom.Artifacts.Packages.Sorted() {
|
||||
if p.Name == pkgName {
|
||||
continue packages
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
"dataLicense": "CC0-1.0",
|
||||
"SPDXID": "SPDXRef-DOCUMENT",
|
||||
"name": "/some/path",
|
||||
"documentNamespace": "https://anchore.com/syft/dir/some/path-1fe34646-a616-48c7-974b-3d1e27d406e3",
|
||||
"documentNamespace": "https://anchore.com/syft/dir/some/path-4029b5ec-6d70-4c0c-aedf-b61c8f5ea93c",
|
||||
"creationInfo": {
|
||||
"licenseListVersion": "3.19",
|
||||
"licenseListVersion": "3.20",
|
||||
"creators": [
|
||||
"Organization: Anchore, Inc",
|
||||
"Tool: syft-v0.42.0-bogus"
|
||||
],
|
||||
"created": "2023-01-20T21:41:03Z"
|
||||
"created": "2023-05-02T18:24:17Z"
|
||||
},
|
||||
"packages": [
|
||||
{
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
"dataLicense": "CC0-1.0",
|
||||
"SPDXID": "SPDXRef-DOCUMENT",
|
||||
"name": "user-image-input",
|
||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input-33759ac3-6006-4f2c-bdc4-f40b9287a7f0",
|
||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input-6b0c6ff8-0f5f-4d95-8c1b-eb966d400804",
|
||||
"creationInfo": {
|
||||
"licenseListVersion": "3.19",
|
||||
"licenseListVersion": "3.20",
|
||||
"creators": [
|
||||
"Organization: Anchore, Inc",
|
||||
"Tool: syft-v0.42.0-bogus"
|
||||
],
|
||||
"created": "2023-01-20T21:41:03Z"
|
||||
"created": "2023-05-02T18:24:18Z"
|
||||
},
|
||||
"packages": [
|
||||
{
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
"dataLicense": "CC0-1.0",
|
||||
"SPDXID": "SPDXRef-DOCUMENT",
|
||||
"name": "user-image-input",
|
||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input-ce98f51f-b483-4e93-9a15-5a8a16d35de6",
|
||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input-ec2f9b25-22ca-46b8-b7f4-484994fe126c",
|
||||
"creationInfo": {
|
||||
"licenseListVersion": "3.19",
|
||||
"licenseListVersion": "3.20",
|
||||
"creators": [
|
||||
"Organization: Anchore, Inc",
|
||||
"Tool: syft-v0.42.0-bogus"
|
||||
],
|
||||
"created": "2023-01-20T21:41:03Z"
|
||||
"created": "2023-05-02T18:24:18Z"
|
||||
},
|
||||
"packages": [
|
||||
{
|
||||
@@ -61,7 +61,7 @@
|
||||
"files": [
|
||||
{
|
||||
"fileName": "/a1/f6",
|
||||
"SPDXID": "SPDXRef-9c2f7510199b17f6",
|
||||
"SPDXID": "SPDXRef-File-a1-f6-9c2f7510199b17f6",
|
||||
"fileTypes": [
|
||||
"OTHER"
|
||||
],
|
||||
@@ -76,7 +76,7 @@
|
||||
},
|
||||
{
|
||||
"fileName": "/d1/f3",
|
||||
"SPDXID": "SPDXRef-c6f5b29dca12661f",
|
||||
"SPDXID": "SPDXRef-File-d1-f3-c6f5b29dca12661f",
|
||||
"fileTypes": [
|
||||
"OTHER"
|
||||
],
|
||||
@@ -91,7 +91,7 @@
|
||||
},
|
||||
{
|
||||
"fileName": "/d2/f4",
|
||||
"SPDXID": "SPDXRef-c641caa71518099f",
|
||||
"SPDXID": "SPDXRef-File-d2-f4-c641caa71518099f",
|
||||
"fileTypes": [
|
||||
"OTHER"
|
||||
],
|
||||
@@ -106,7 +106,7 @@
|
||||
},
|
||||
{
|
||||
"fileName": "/f1",
|
||||
"SPDXID": "SPDXRef-5265a4dde3edbf7c",
|
||||
"SPDXID": "SPDXRef-File-f1-5265a4dde3edbf7c",
|
||||
"fileTypes": [
|
||||
"OTHER"
|
||||
],
|
||||
@@ -121,7 +121,7 @@
|
||||
},
|
||||
{
|
||||
"fileName": "/f2",
|
||||
"SPDXID": "SPDXRef-f9e49132a4b96ccd",
|
||||
"SPDXID": "SPDXRef-File-f2-f9e49132a4b96ccd",
|
||||
"fileTypes": [
|
||||
"OTHER"
|
||||
],
|
||||
@@ -136,7 +136,7 @@
|
||||
},
|
||||
{
|
||||
"fileName": "/z1/f5",
|
||||
"SPDXID": "SPDXRef-839d99ee67d9d174",
|
||||
"SPDXID": "SPDXRef-File-z1-f5-839d99ee67d9d174",
|
||||
"fileTypes": [
|
||||
"OTHER"
|
||||
],
|
||||
@@ -153,32 +153,32 @@
|
||||
"relationships": [
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6",
|
||||
"relatedSpdxElement": "SPDXRef-5265a4dde3edbf7c",
|
||||
"relatedSpdxElement": "SPDXRef-File-f1-5265a4dde3edbf7c",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6",
|
||||
"relatedSpdxElement": "SPDXRef-839d99ee67d9d174",
|
||||
"relatedSpdxElement": "SPDXRef-File-z1-f5-839d99ee67d9d174",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6",
|
||||
"relatedSpdxElement": "SPDXRef-9c2f7510199b17f6",
|
||||
"relatedSpdxElement": "SPDXRef-File-a1-f6-9c2f7510199b17f6",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6",
|
||||
"relatedSpdxElement": "SPDXRef-c641caa71518099f",
|
||||
"relatedSpdxElement": "SPDXRef-File-d2-f4-c641caa71518099f",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6",
|
||||
"relatedSpdxElement": "SPDXRef-c6f5b29dca12661f",
|
||||
"relatedSpdxElement": "SPDXRef-File-d1-f3-c6f5b29dca12661f",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6",
|
||||
"relatedSpdxElement": "SPDXRef-f9e49132a4b96ccd",
|
||||
"relatedSpdxElement": "SPDXRef-File-f2-f9e49132a4b96ccd",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestSPDXJSONSPDXIDs(t *testing.T) {
|
||||
Format(),
|
||||
sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
PackageCatalog: pkg.NewCatalog(pkgs...),
|
||||
Packages: pkg.NewCollection(pkgs...),
|
||||
},
|
||||
Relationships: nil,
|
||||
Source: source.Metadata{
|
||||
|
||||
@@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.3
|
||||
DataLicense: CC0-1.0
|
||||
SPDXID: SPDXRef-DOCUMENT
|
||||
DocumentName: foobar/baz
|
||||
DocumentNamespace: https://anchore.com/syft/dir/foobar/baz-478e410d-7fad-472c-b4e9-a4068ef28160
|
||||
LicenseListVersion: 3.19
|
||||
DocumentNamespace: https://anchore.com/syft/dir/foobar/baz-9c1f31fb-7c72-40a6-8c81-3a08590000a2
|
||||
LicenseListVersion: 3.20
|
||||
Creator: Organization: Anchore, Inc
|
||||
Creator: Tool: syft-v0.42.0-bogus
|
||||
Created: 2022-12-21T03:39:05Z
|
||||
Created: 2023-05-02T18:24:33Z
|
||||
|
||||
##### Package: @at-sign
|
||||
|
||||
|
||||
@@ -2,46 +2,46 @@ SPDXVersion: SPDX-2.3
|
||||
DataLicense: CC0-1.0
|
||||
SPDXID: SPDXRef-DOCUMENT
|
||||
DocumentName: user-image-input
|
||||
DocumentNamespace: https://anchore.com/syft/image/user-image-input-73433e8c-364f-42b6-b5b7-9a4da8799868
|
||||
LicenseListVersion: 3.19
|
||||
DocumentNamespace: https://anchore.com/syft/image/user-image-input-5be37b11-b99a-47ff-8725-3984e323d129
|
||||
LicenseListVersion: 3.20
|
||||
Creator: Organization: Anchore, Inc
|
||||
Creator: Tool: syft-v0.42.0-bogus
|
||||
Created: 2022-12-21T03:39:05Z
|
||||
Created: 2023-05-02T18:24:33Z
|
||||
|
||||
##### Unpackaged files
|
||||
|
||||
FileName: /f1
|
||||
SPDXID: SPDXRef-5265a4dde3edbf7c
|
||||
FileType: OTHER
|
||||
FileChecksum: SHA1: 0000000000000000000000000000000000000000
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /z1/f5
|
||||
SPDXID: SPDXRef-839d99ee67d9d174
|
||||
FileType: OTHER
|
||||
FileChecksum: SHA1: 0000000000000000000000000000000000000000
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /a1/f6
|
||||
SPDXID: SPDXRef-9c2f7510199b17f6
|
||||
FileType: OTHER
|
||||
FileChecksum: SHA1: 0000000000000000000000000000000000000000
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /d2/f4
|
||||
SPDXID: SPDXRef-c641caa71518099f
|
||||
SPDXID: SPDXRef-File-a1-f6-9c2f7510199b17f6
|
||||
FileType: OTHER
|
||||
FileChecksum: SHA1: 0000000000000000000000000000000000000000
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /d1/f3
|
||||
SPDXID: SPDXRef-c6f5b29dca12661f
|
||||
SPDXID: SPDXRef-File-d1-f3-c6f5b29dca12661f
|
||||
FileType: OTHER
|
||||
FileChecksum: SHA1: 0000000000000000000000000000000000000000
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /d2/f4
|
||||
SPDXID: SPDXRef-File-d2-f4-c641caa71518099f
|
||||
FileType: OTHER
|
||||
FileChecksum: SHA1: 0000000000000000000000000000000000000000
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /f1
|
||||
SPDXID: SPDXRef-File-f1-5265a4dde3edbf7c
|
||||
FileType: OTHER
|
||||
FileChecksum: SHA1: 0000000000000000000000000000000000000000
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /f2
|
||||
SPDXID: SPDXRef-f9e49132a4b96ccd
|
||||
SPDXID: SPDXRef-File-f2-f9e49132a4b96ccd
|
||||
FileType: OTHER
|
||||
FileChecksum: SHA1: 0000000000000000000000000000000000000000
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /z1/f5
|
||||
SPDXID: SPDXRef-File-z1-f5-839d99ee67d9d174
|
||||
FileType: OTHER
|
||||
FileChecksum: SHA1: 0000000000000000000000000000000000000000
|
||||
LicenseConcluded: NOASSERTION
|
||||
@@ -76,11 +76,11 @@ ExternalRef: PACKAGE-MANAGER purl a-purl-1
|
||||
|
||||
##### Relationships
|
||||
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-5265a4dde3edbf7c
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-839d99ee67d9d174
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-9c2f7510199b17f6
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-c641caa71518099f
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-c6f5b29dca12661f
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-f9e49132a4b96ccd
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-File-f1-5265a4dde3edbf7c
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-File-z1-f5-839d99ee67d9d174
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-File-a1-f6-9c2f7510199b17f6
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-File-d2-f4-c641caa71518099f
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-File-d1-f3-c6f5b29dca12661f
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-File-f2-f9e49132a4b96ccd
|
||||
Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-DOCUMENT
|
||||
|
||||
|
||||
+3
-3
@@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.3
|
||||
DataLicense: CC0-1.0
|
||||
SPDXID: SPDXRef-DOCUMENT
|
||||
DocumentName: /some/path
|
||||
DocumentNamespace: https://anchore.com/syft/dir/some/path-1d303762-46d2-47b5-9c81-defa91387275
|
||||
LicenseListVersion: 3.19
|
||||
DocumentNamespace: https://anchore.com/syft/dir/some/path-0f346656-6d10-4dec-b549-a256468cbd35
|
||||
LicenseListVersion: 3.20
|
||||
Creator: Organization: Anchore, Inc
|
||||
Creator: Tool: syft-v0.42.0-bogus
|
||||
Created: 2022-12-21T03:39:05Z
|
||||
Created: 2023-05-02T18:24:33Z
|
||||
|
||||
##### Package: package-2
|
||||
|
||||
|
||||
+3
-3
@@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.3
|
||||
DataLicense: CC0-1.0
|
||||
SPDXID: SPDXRef-DOCUMENT
|
||||
DocumentName: user-image-input
|
||||
DocumentNamespace: https://anchore.com/syft/image/user-image-input-559af225-63af-4bc0-94fb-bce94913bcfa
|
||||
LicenseListVersion: 3.19
|
||||
DocumentNamespace: https://anchore.com/syft/image/user-image-input-4ce1e7c7-642f-4428-bb44-1b48b8edf74d
|
||||
LicenseListVersion: 3.20
|
||||
Creator: Organization: Anchore, Inc
|
||||
Creator: Tool: syft-v0.42.0-bogus
|
||||
Created: 2022-12-21T03:39:05Z
|
||||
Created: 2023-05-02T18:24:33Z
|
||||
|
||||
##### Package: package-2
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ func TestEncodeDecodeCycle(t *testing.T) {
|
||||
t.Errorf("metadata difference: %+v", d)
|
||||
}
|
||||
|
||||
actualPackages := actualSBOM.Artifacts.PackageCatalog.Sorted()
|
||||
for idx, p := range originalSBOM.Artifacts.PackageCatalog.Sorted() {
|
||||
actualPackages := actualSBOM.Artifacts.Packages.Sorted()
|
||||
for idx, p := range originalSBOM.Artifacts.Packages.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
|
||||
|
||||
@@ -47,7 +47,7 @@ func schemaVersionRedactor(s []byte) []byte {
|
||||
}
|
||||
|
||||
func TestEncodeFullJSONDocument(t *testing.T) {
|
||||
catalog := pkg.NewCatalog()
|
||||
catalog := pkg.NewCollection()
|
||||
|
||||
p1 := pkg.Package{
|
||||
Name: "package-1",
|
||||
@@ -100,7 +100,7 @@ func TestEncodeFullJSONDocument(t *testing.T) {
|
||||
|
||||
s := sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
PackageCatalog: catalog,
|
||||
Packages: catalog,
|
||||
FileMetadata: map[source.Coordinates]source.FileMetadata{
|
||||
source.NewLocation("/a/place").Coordinates: {
|
||||
Mode: 0775,
|
||||
|
||||
@@ -87,9 +87,5 @@
|
||||
"configuration": {
|
||||
"config-key": "config-value"
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"version": "7.1.4",
|
||||
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.4.json"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,9 +187,5 @@
|
||||
"configuration": {
|
||||
"config-key": "config-value"
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"version": "7.1.4",
|
||||
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.4.json"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"locations": [
|
||||
{
|
||||
"path": "/somefile-1.txt",
|
||||
"layerID": "sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59"
|
||||
"layerID": "sha256:7e139310bd6ce0956d65a70d26a6d31b240a4f47094a831638f05d381b6c424a"
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
@@ -40,7 +40,7 @@
|
||||
"locations": [
|
||||
{
|
||||
"path": "/somefile-2.txt",
|
||||
"layerID": "sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec"
|
||||
"layerID": "sha256:cc833bf31a480c064d65ca67ee37f77f0d0c8ab98eedde7b286ad1ef6f5bdcac"
|
||||
}
|
||||
],
|
||||
"licenses": [],
|
||||
@@ -64,11 +64,11 @@
|
||||
],
|
||||
"artifactRelationships": [],
|
||||
"source": {
|
||||
"id": "1a678f111c8ddc66fd82687bb024e0dd6af61314404937a80e810c0cf317b796",
|
||||
"id": "0af8fa79f5497297e4e32f3e03de14ac20ad695159df0ac8373e6543614b9a50",
|
||||
"type": "image",
|
||||
"target": {
|
||||
"userInput": "user-image-input",
|
||||
"imageID": "sha256:3c51b06feb0cda8ee62d0e3755ef2a8496a6b71f8a55b245f07f31c4bb813d31",
|
||||
"imageID": "sha256:0cb4395791986bda17562bd6f76811bb6f163f686e198397197ef8241bed58df",
|
||||
"manifestDigest": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"tags": [
|
||||
@@ -78,17 +78,17 @@
|
||||
"layers": [
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||
"digest": "sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59",
|
||||
"digest": "sha256:7e139310bd6ce0956d65a70d26a6d31b240a4f47094a831638f05d381b6c424a",
|
||||
"size": 22
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||
"digest": "sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec",
|
||||
"digest": "sha256:cc833bf31a480c064d65ca67ee37f77f0d0c8ab98eedde7b286ad1ef6f5bdcac",
|
||||
"size": 16
|
||||
}
|
||||
],
|
||||
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjo2NzMsImRpZ2VzdCI6InNoYTI1NjozYzUxYjA2ZmViMGNkYThlZTYyZDBlMzc1NWVmMmE4NDk2YTZiNzFmOGE1NWIyNDVmMDdmMzFjNGJiODEzZDMxIn0sImxheWVycyI6W3sibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjpmYjZiZWVjYjc1YjM5ZjRiYjgxM2RiZjE3N2U1MDFlZGQ1ZGRiM2U2OWJiNDVjZWRlYjc4YzY3NmVlMWI3YTU5In0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MjA0OCwiZGlnZXN0Ijoic2hhMjU2OjMxOWI1ODhjZTY0MjUzYTg3YjUzM2M4ZWQwMWNmMDAyNWUwZWFjOThlN2I1MTZlMTI1MzI5NTdlMTI0NGZkZWMifV19",
|
||||
"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiV29ya2luZ0RpciI6Ii8iLCJPbkJ1aWxkIjpudWxsfSwiY3JlYXRlZCI6IjIwMjItMDgtMDFUMjA6MDk6MjIuNTA5NDIxNzEyWiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDIyLTA4LTAxVDIwOjA5OjIyLjQ4Nzg5NTUxOVoiLCJjcmVhdGVkX2J5IjoiQUREIGZpbGUtMS50eHQgL3NvbWVmaWxlLTEudHh0ICMgYnVpbGRraXQiLCJjb21tZW50IjoiYnVpbGRraXQuZG9ja2VyZmlsZS52MCJ9LHsiY3JlYXRlZCI6IjIwMjItMDgtMDFUMjA6MDk6MjIuNTA5NDIxNzEyWiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0yLnR4dCAvc29tZWZpbGUtMi50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn1dLCJvcyI6ImxpbnV4Iiwicm9vdGZzIjp7InR5cGUiOiJsYXllcnMiLCJkaWZmX2lkcyI6WyJzaGEyNTY6ZmI2YmVlY2I3NWIzOWY0YmI4MTNkYmYxNzdlNTAxZWRkNWRkYjNlNjliYjQ1Y2VkZWI3OGM2NzZlZTFiN2E1OSIsInNoYTI1NjozMTliNTg4Y2U2NDI1M2E4N2I1MzNjOGVkMDFjZjAwMjVlMGVhYzk4ZTdiNTE2ZTEyNTMyOTU3ZTEyNDRmZGVjIl19fQ==",
|
||||
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjo2NzEsImRpZ2VzdCI6InNoYTI1NjowY2I0Mzk1NzkxOTg2YmRhMTc1NjJiZDZmNzY4MTFiYjZmMTYzZjY4NmUxOTgzOTcxOTdlZjgyNDFiZWQ1OGRmIn0sImxheWVycyI6W3sibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1Njo3ZTEzOTMxMGJkNmNlMDk1NmQ2NWE3MGQyNmE2ZDMxYjI0MGE0ZjQ3MDk0YTgzMTYzOGYwNWQzODFiNmM0MjRhIn0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MjA0OCwiZGlnZXN0Ijoic2hhMjU2OmNjODMzYmYzMWE0ODBjMDY0ZDY1Y2E2N2VlMzdmNzdmMGQwYzhhYjk4ZWVkZGU3YjI4NmFkMWVmNmY1YmRjYWMifV19",
|
||||
"config": "eyJhcmNoaXRlY3R1cmUiOiJhcm02NCIsImNvbmZpZyI6eyJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiV29ya2luZ0RpciI6Ii8iLCJPbkJ1aWxkIjpudWxsfSwiY3JlYXRlZCI6IjIwMjMtMDQtMThUMTQ6MDk6NDIuMzAxMDI2MzhaIiwiaGlzdG9yeSI6W3siY3JlYXRlZCI6IjIwMjMtMDQtMThUMTQ6MDk6NDIuMjg3OTQyNzEzWiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0xLnR4dCAvc29tZWZpbGUtMS50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn0seyJjcmVhdGVkIjoiMjAyMy0wNC0xOFQxNDowOTo0Mi4zMDEwMjYzOFoiLCJjcmVhdGVkX2J5IjoiQUREIGZpbGUtMi50eHQgL3NvbWVmaWxlLTIudHh0ICMgYnVpbGRraXQiLCJjb21tZW50IjoiYnVpbGRraXQuZG9ja2VyZmlsZS52MCJ9XSwib3MiOiJsaW51eCIsInJvb3RmcyI6eyJ0eXBlIjoibGF5ZXJzIiwiZGlmZl9pZHMiOlsic2hhMjU2OjdlMTM5MzEwYmQ2Y2UwOTU2ZDY1YTcwZDI2YTZkMzFiMjQwYTRmNDcwOTRhODMxNjM4ZjA1ZDM4MWI2YzQyNGEiLCJzaGEyNTY6Y2M4MzNiZjMxYTQ4MGMwNjRkNjVjYTY3ZWUzN2Y3N2YwZDBjOGFiOThlZWRkZTdiMjg2YWQxZWY2ZjViZGNhYyJdfX0=",
|
||||
"repoDigests": [],
|
||||
"architecture": "",
|
||||
"os": ""
|
||||
@@ -110,9 +110,5 @@
|
||||
"configuration": {
|
||||
"config-key": "config-value"
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"version": "7.1.4",
|
||||
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.4.json"
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -26,7 +26,7 @@ func ToFormatModel(s sbom.SBOM) model.Document {
|
||||
}
|
||||
|
||||
return model.Document{
|
||||
Artifacts: toPackageModels(s.Artifacts.PackageCatalog),
|
||||
Artifacts: toPackageModels(s.Artifacts.Packages),
|
||||
ArtifactRelationships: toRelationshipModel(s.Relationships),
|
||||
Files: toFile(s),
|
||||
Secrets: toSecrets(s.Artifacts.Secrets),
|
||||
@@ -173,7 +173,7 @@ func toFileType(ty stereoscopeFile.Type) string {
|
||||
}
|
||||
}
|
||||
|
||||
func toPackageModels(catalog *pkg.Catalog) []model.Package {
|
||||
func toPackageModels(catalog *pkg.Collection) []model.Package {
|
||||
artifacts := make([]model.Package, 0)
|
||||
if catalog == nil {
|
||||
return artifacts
|
||||
|
||||
@@ -28,7 +28,7 @@ func toSyftModel(doc model.Document) (*sbom.SBOM, error) {
|
||||
|
||||
return &sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
PackageCatalog: catalog,
|
||||
Packages: catalog,
|
||||
FileMetadata: fileArtifacts.FileMetadata,
|
||||
FileDigests: fileArtifacts.FileDigests,
|
||||
LinuxDistribution: toSyftLinuxRelease(doc.Distro),
|
||||
@@ -131,7 +131,7 @@ func toSyftLinuxRelease(d model.LinuxRelease) *linux.Release {
|
||||
}
|
||||
}
|
||||
|
||||
func toSyftRelationships(doc *model.Document, catalog *pkg.Catalog, relationships []model.Relationship, idAliases map[string]string) []artifact.Relationship {
|
||||
func toSyftRelationships(doc *model.Document, catalog *pkg.Collection, relationships []model.Relationship, idAliases map[string]string) []artifact.Relationship {
|
||||
idMap := make(map[string]interface{})
|
||||
|
||||
for _, p := range catalog.Sorted() {
|
||||
@@ -256,8 +256,8 @@ func toSyftSourceData(s model.Source) *source.Metadata {
|
||||
return nil
|
||||
}
|
||||
|
||||
func toSyftCatalog(pkgs []model.Package, idAliases map[string]string) *pkg.Catalog {
|
||||
catalog := pkg.NewCatalog()
|
||||
func toSyftCatalog(pkgs []model.Package, idAliases map[string]string) *pkg.Collection {
|
||||
catalog := pkg.NewCollection()
|
||||
for _, p := range pkgs {
|
||||
catalog.Add(toSyftPackage(p, idAliases))
|
||||
}
|
||||
|
||||
@@ -119,11 +119,11 @@ func Test_idsHaveChanged(t *testing.T) {
|
||||
|
||||
r := s.Relationships[0]
|
||||
|
||||
from := s.Artifacts.PackageCatalog.Package(r.From.ID())
|
||||
from := s.Artifacts.Packages.Package(r.From.ID())
|
||||
assert.NotNil(t, from)
|
||||
assert.Equal(t, "pkg-1", from.Name)
|
||||
|
||||
to := s.Artifacts.PackageCatalog.Package(r.To.ID())
|
||||
to := s.Artifacts.Packages.Package(r.To.ID())
|
||||
assert.NotNil(t, to)
|
||||
assert.Equal(t, "pkg-2", to.Name)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ func encoder(output io.Writer, s sbom.SBOM) error {
|
||||
var rows [][]string
|
||||
|
||||
columns := []string{"Name", "Version", "Type"}
|
||||
for _, p := range s.Artifacts.PackageCatalog.Sorted() {
|
||||
for _, p := range s.Artifacts.Packages.Sorted() {
|
||||
row := []string{
|
||||
p.Name,
|
||||
p.Version,
|
||||
|
||||
@@ -45,5 +45,11 @@ var funcMap = func() template.FuncMap {
|
||||
|
||||
return 0
|
||||
}
|
||||
// Checks if a field is defined
|
||||
f["hasField"] = func(obj interface{}, field string) bool {
|
||||
t := reflect.TypeOf(obj)
|
||||
_, ok := t.FieldByName(field)
|
||||
return ok
|
||||
}
|
||||
return f
|
||||
}()
|
||||
|
||||
@@ -24,6 +24,19 @@ func TestFormatWithOption(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestFormatWithOptionAndHasField(t *testing.T) {
|
||||
f := OutputFormat{}
|
||||
f.SetTemplatePath("test-fixtures/csv-hasField.template")
|
||||
|
||||
testutils.AssertEncoderAgainstGoldenSnapshot(t,
|
||||
f,
|
||||
testutils.DirectoryInputWithAuthorField(t),
|
||||
*updateTmpl,
|
||||
false,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
func TestFormatWithoutOptions(t *testing.T) {
|
||||
f := Format()
|
||||
err := f.Encode(nil, testutils.DirectoryInput(t))
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
"Package","Version Installed","Found by","Author"
|
||||
{{- range .Artifacts}}
|
||||
"{{.Name}}","{{.Version}}","{{.FoundBy}}","{{ if hasField .Metadata "Author" }}{{.Metadata.Author}}{{ else }}NO AUTHOR SUPPLIED{{end}}"
|
||||
{{- end}}
|
||||
@@ -0,0 +1,3 @@
|
||||
"Package","Version Installed","Found by","Author"
|
||||
"package-1","1.0.1","the-cataloger-1","test-author"
|
||||
"package-2","2.0.1","the-cataloger-2","NO AUTHOR SUPPLIED"
|
||||
@@ -34,7 +34,7 @@ func encoder(output io.Writer, s sbom.SBOM) error {
|
||||
|
||||
// populate artifacts...
|
||||
rows := 0
|
||||
for _, p := range s.Artifacts.PackageCatalog.Sorted() {
|
||||
for _, p := range s.Artifacts.Packages.Sorted() {
|
||||
fmt.Fprintf(w, "[%s]\n", p.Name)
|
||||
fmt.Fprintln(w, " Version:\t", p.Version)
|
||||
fmt.Fprintln(w, " Type:\t", string(p.Type))
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ import (
|
||||
// CatalogPackages takes an inventory of packages from the given image from a particular perspective
|
||||
// (e.g. squashed source, all-layers source). Returns the discovered set of packages, the identified Linux
|
||||
// distribution, and the source object used to wrap the data source.
|
||||
func CatalogPackages(src *source.Source, cfg cataloger.Config) (*pkg.Catalog, []artifact.Relationship, *linux.Release, error) {
|
||||
func CatalogPackages(src *source.Source, cfg cataloger.Config) (*pkg.Collection, []artifact.Relationship, *linux.Release, error) {
|
||||
resolver, err := src.FileResolver(cfg.Search.Scope)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("unable to determine resolver while cataloging packages: %w", err)
|
||||
@@ -76,7 +76,7 @@ func CatalogPackages(src *source.Source, cfg cataloger.Config) (*pkg.Catalog, []
|
||||
return catalog, relationships, release, err
|
||||
}
|
||||
|
||||
func newSourceRelationshipsFromCatalog(src *source.Source, c *pkg.Catalog) []artifact.Relationship {
|
||||
func newSourceRelationshipsFromCatalog(src *source.Source, c *pkg.Collection) []artifact.Relationship {
|
||||
relationships := make([]artifact.Relationship, 0) // Should we pre-allocate this by giving catalog a Len() method?
|
||||
for p := range c.Enumerate() {
|
||||
relationships = append(relationships, artifact.Relationship{
|
||||
|
||||
+12
-12
@@ -14,19 +14,19 @@ var _ FileOwner = (*AlpmMetadata)(nil)
|
||||
const AlpmDBGlob = "**/var/lib/pacman/local/**/desc"
|
||||
|
||||
type AlpmMetadata struct {
|
||||
BasePackage string `mapstructure:"base" json:"basepackage"`
|
||||
Package string `mapstructure:"name" json:"package"`
|
||||
Version string `mapstructure:"version" json:"version"`
|
||||
Description string `mapstructure:"desc" json:"description"`
|
||||
Architecture string `mapstructure:"arch" json:"architecture"`
|
||||
BasePackage string `mapstructure:"base" json:"basepackage" cyclonedx:"basepackage"`
|
||||
Package string `mapstructure:"name" json:"package" cyclonedx:"package"`
|
||||
Version string `mapstructure:"version" json:"version" cyclonedx:"version"`
|
||||
Description string `mapstructure:"desc" json:"description" cyclonedx:"description"`
|
||||
Architecture string `mapstructure:"arch" json:"architecture" cyclonedx:"architecture"`
|
||||
Size int `mapstructure:"size" json:"size" cyclonedx:"size"`
|
||||
Packager string `mapstructure:"packager" json:"packager"`
|
||||
License string `mapstructure:"license" json:"license"`
|
||||
URL string `mapstructure:"url" json:"url"`
|
||||
Validation string `mapstructure:"validation" json:"validation"`
|
||||
Reason int `mapstructure:"reason" json:"reason"`
|
||||
Files []AlpmFileRecord `mapstructure:"files" json:"files"`
|
||||
Backup []AlpmFileRecord `mapstructure:"backup" json:"backup"`
|
||||
Packager string `mapstructure:"packager" json:"packager" cyclonedx:"packager"`
|
||||
License string `mapstructure:"license" json:"license" cyclonedx:"license"`
|
||||
URL string `mapstructure:"url" json:"url" cyclonedx:"url"`
|
||||
Validation string `mapstructure:"validation" json:"validation" cyclonedx:"validation"`
|
||||
Reason int `mapstructure:"reason" json:"reason" cyclonedx:"reason"`
|
||||
Files []AlpmFileRecord `mapstructure:"files" json:"files" cyclonedx:"files"`
|
||||
Backup []AlpmFileRecord `mapstructure:"backup" json:"backup" cyclonedx:"backup"`
|
||||
}
|
||||
|
||||
type AlpmFileRecord struct {
|
||||
|
||||
+48
-48
@@ -10,33 +10,8 @@ import (
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
)
|
||||
|
||||
type orderedIDSet struct {
|
||||
slice []artifact.ID
|
||||
}
|
||||
|
||||
func (s *orderedIDSet) add(ids ...artifact.ID) {
|
||||
loopNewIDs:
|
||||
for _, newID := range ids {
|
||||
for _, existingID := range s.slice {
|
||||
if existingID == newID {
|
||||
continue loopNewIDs
|
||||
}
|
||||
}
|
||||
s.slice = append(s.slice, newID)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *orderedIDSet) delete(id artifact.ID) {
|
||||
for i, existingID := range s.slice {
|
||||
if existingID == id {
|
||||
s.slice = append(s.slice[:i], s.slice[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Catalog represents a collection of Packages.
|
||||
type Catalog struct {
|
||||
// Collection represents a collection of Packages.
|
||||
type Collection struct {
|
||||
byID map[artifact.ID]Package
|
||||
idsByName map[string]orderedIDSet
|
||||
idsByType map[Type]orderedIDSet
|
||||
@@ -44,9 +19,9 @@ type Catalog struct {
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
// NewCatalog returns a new empty Catalog
|
||||
func NewCatalog(pkgs ...Package) *Catalog {
|
||||
catalog := Catalog{
|
||||
// NewCollection returns a new empty Collection
|
||||
func NewCollection(pkgs ...Package) *Collection {
|
||||
catalog := Collection{
|
||||
byID: make(map[artifact.ID]Package),
|
||||
idsByName: make(map[string]orderedIDSet),
|
||||
idsByType: make(map[Type]orderedIDSet),
|
||||
@@ -61,12 +36,12 @@ func NewCatalog(pkgs ...Package) *Catalog {
|
||||
}
|
||||
|
||||
// PackageCount returns the total number of packages that have been added.
|
||||
func (c *Catalog) PackageCount() int {
|
||||
func (c *Collection) PackageCount() int {
|
||||
return len(c.byID)
|
||||
}
|
||||
|
||||
// Package returns the package with the given ID.
|
||||
func (c *Catalog) Package(id artifact.ID) *Package {
|
||||
func (c *Collection) Package(id artifact.ID) *Package {
|
||||
v, exists := c.byID[id]
|
||||
if !exists {
|
||||
return nil
|
||||
@@ -81,17 +56,17 @@ func (c *Catalog) Package(id artifact.ID) *Package {
|
||||
}
|
||||
|
||||
// PackagesByPath returns all packages that were discovered from the given path.
|
||||
func (c *Catalog) PackagesByPath(path string) []Package {
|
||||
func (c *Collection) PackagesByPath(path string) []Package {
|
||||
return c.Packages(c.idsByPath[path].slice)
|
||||
}
|
||||
|
||||
// PackagesByName returns all packages that were discovered with a matching name.
|
||||
func (c *Catalog) PackagesByName(name string) []Package {
|
||||
func (c *Collection) PackagesByName(name string) []Package {
|
||||
return c.Packages(c.idsByName[name].slice)
|
||||
}
|
||||
|
||||
// Packages returns all packages for the given ID.
|
||||
func (c *Catalog) Packages(ids []artifact.ID) (result []Package) {
|
||||
func (c *Collection) Packages(ids []artifact.ID) (result []Package) {
|
||||
for _, i := range ids {
|
||||
p, exists := c.byID[i]
|
||||
if exists {
|
||||
@@ -102,7 +77,7 @@ func (c *Catalog) Packages(ids []artifact.ID) (result []Package) {
|
||||
}
|
||||
|
||||
// Add n packages to the catalog.
|
||||
func (c *Catalog) Add(pkgs ...Package) {
|
||||
func (c *Collection) Add(pkgs ...Package) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
@@ -129,26 +104,26 @@ func (c *Catalog) Add(pkgs ...Package) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Catalog) addToIndex(p Package) {
|
||||
func (c *Collection) addToIndex(p Package) {
|
||||
c.byID[p.id] = p
|
||||
c.addNameToIndex(p)
|
||||
c.addTypeToIndex(p)
|
||||
c.addPathsToIndex(p)
|
||||
}
|
||||
|
||||
func (c *Catalog) addNameToIndex(p Package) {
|
||||
func (c *Collection) addNameToIndex(p Package) {
|
||||
nameIndex := c.idsByName[p.Name]
|
||||
nameIndex.add(p.id)
|
||||
c.idsByName[p.Name] = nameIndex
|
||||
}
|
||||
|
||||
func (c *Catalog) addTypeToIndex(p Package) {
|
||||
func (c *Collection) addTypeToIndex(p Package) {
|
||||
typeIndex := c.idsByType[p.Type]
|
||||
typeIndex.add(p.id)
|
||||
c.idsByType[p.Type] = typeIndex
|
||||
}
|
||||
|
||||
func (c *Catalog) addPathsToIndex(p Package) {
|
||||
func (c *Collection) addPathsToIndex(p Package) {
|
||||
observedPaths := internal.NewStringSet()
|
||||
for _, l := range p.Locations.ToSlice() {
|
||||
if l.RealPath != "" && !observedPaths.Contains(l.RealPath) {
|
||||
@@ -162,13 +137,13 @@ func (c *Catalog) addPathsToIndex(p Package) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Catalog) addPathToIndex(id artifact.ID, path string) {
|
||||
func (c *Collection) addPathToIndex(id artifact.ID, path string) {
|
||||
pathIndex := c.idsByPath[path]
|
||||
pathIndex.add(id)
|
||||
c.idsByPath[path] = pathIndex
|
||||
}
|
||||
|
||||
func (c *Catalog) Delete(ids ...artifact.ID) {
|
||||
func (c *Collection) Delete(ids ...artifact.ID) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
@@ -185,19 +160,19 @@ func (c *Catalog) Delete(ids ...artifact.ID) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Catalog) deleteNameFromIndex(p Package) {
|
||||
func (c *Collection) deleteNameFromIndex(p Package) {
|
||||
nameIndex := c.idsByName[p.Name]
|
||||
nameIndex.delete(p.id)
|
||||
c.idsByName[p.Name] = nameIndex
|
||||
}
|
||||
|
||||
func (c *Catalog) deleteTypeFromIndex(p Package) {
|
||||
func (c *Collection) deleteTypeFromIndex(p Package) {
|
||||
typeIndex := c.idsByType[p.Type]
|
||||
typeIndex.delete(p.id)
|
||||
c.idsByType[p.Type] = typeIndex
|
||||
}
|
||||
|
||||
func (c *Catalog) deletePathsFromIndex(p Package) {
|
||||
func (c *Collection) deletePathsFromIndex(p Package) {
|
||||
observedPaths := internal.NewStringSet()
|
||||
for _, l := range p.Locations.ToSlice() {
|
||||
if l.RealPath != "" && !observedPaths.Contains(l.RealPath) {
|
||||
@@ -211,7 +186,7 @@ func (c *Catalog) deletePathsFromIndex(p Package) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Catalog) deletePathFromIndex(id artifact.ID, path string) {
|
||||
func (c *Collection) deletePathFromIndex(id artifact.ID, path string) {
|
||||
pathIndex := c.idsByPath[path]
|
||||
pathIndex.delete(id)
|
||||
if len(pathIndex.slice) == 0 {
|
||||
@@ -222,7 +197,7 @@ func (c *Catalog) deletePathFromIndex(id artifact.ID, path string) {
|
||||
}
|
||||
|
||||
// Enumerate all packages for the given type(s), enumerating all packages if no type is specified.
|
||||
func (c *Catalog) Enumerate(types ...Type) <-chan Package {
|
||||
func (c *Collection) Enumerate(types ...Type) <-chan Package {
|
||||
channel := make(chan Package)
|
||||
go func() {
|
||||
defer close(channel)
|
||||
@@ -257,7 +232,7 @@ func (c *Catalog) Enumerate(types ...Type) <-chan Package {
|
||||
|
||||
// Sorted enumerates all packages for the given types sorted by package name. Enumerates all packages if no type
|
||||
// is specified.
|
||||
func (c *Catalog) Sorted(types ...Type) (pkgs []Package) {
|
||||
func (c *Collection) Sorted(types ...Type) (pkgs []Package) {
|
||||
for p := range c.Enumerate(types...) {
|
||||
pkgs = append(pkgs, p)
|
||||
}
|
||||
@@ -266,3 +241,28 @@ func (c *Catalog) Sorted(types ...Type) (pkgs []Package) {
|
||||
|
||||
return pkgs
|
||||
}
|
||||
|
||||
type orderedIDSet struct {
|
||||
slice []artifact.ID
|
||||
}
|
||||
|
||||
func (s *orderedIDSet) add(ids ...artifact.ID) {
|
||||
loopNewIDs:
|
||||
for _, newID := range ids {
|
||||
for _, existingID := range s.slice {
|
||||
if existingID == newID {
|
||||
continue loopNewIDs
|
||||
}
|
||||
}
|
||||
s.slice = append(s.slice, newID)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *orderedIDSet) delete(id artifact.ID) {
|
||||
for i, existingID := range s.slice {
|
||||
if existingID == id {
|
||||
s.slice = append(s.slice[:i], s.slice[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ func TestCatalogDeleteRemovesPackages(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
c := NewCatalog()
|
||||
c := NewCollection()
|
||||
for _, p := range test.pkgs {
|
||||
c.Add(p)
|
||||
}
|
||||
@@ -212,13 +212,13 @@ func TestCatalogAddPopulatesIndex(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
c := NewCatalog(pkgs...)
|
||||
c := NewCollection(pkgs...)
|
||||
assertIndexes(t, c, test.expectedIndexes)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func assertIndexes(t *testing.T, c *Catalog, expectedIndexes expectedIndexes) {
|
||||
func assertIndexes(t *testing.T, c *Collection, expectedIndexes expectedIndexes) {
|
||||
// assert path index
|
||||
assert.Len(t, c.idsByPath, len(expectedIndexes.byPath), "unexpected path index length")
|
||||
for path, expectedIds := range expectedIndexes.byPath {
|
||||
@@ -306,7 +306,7 @@ func TestCatalog_PathIndexDeduplicatesRealVsVirtualPaths(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
for _, path := range test.paths {
|
||||
actualPackages := NewCatalog(test.pkgs...).PackagesByPath(path)
|
||||
actualPackages := NewCollection(test.pkgs...).PackagesByPath(path)
|
||||
require.Len(t, actualPackages, 1)
|
||||
}
|
||||
})
|
||||
@@ -373,7 +373,7 @@ func TestCatalog_MergeRecords(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual := NewCatalog(tt.pkgs...).PackagesByPath("/b/path")
|
||||
actual := NewCollection(tt.pkgs...).PackagesByPath("/b/path")
|
||||
require.Len(t, actual, 1)
|
||||
assert.Equal(t, tt.expectedLocations, actual[0].Locations.ToSlice())
|
||||
require.Len(t, actual[0].CPEs, tt.expectedCPECount)
|
||||
@@ -382,7 +382,7 @@ func TestCatalog_MergeRecords(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCatalog_EnumerateNilCatalog(t *testing.T) {
|
||||
var c *Catalog
|
||||
var c *Collection
|
||||
assert.Empty(t, c.Enumerate())
|
||||
}
|
||||
|
||||
|
||||
@@ -105,8 +105,8 @@ func runCataloger(cataloger pkg.Cataloger, resolver source.FileResolver) (catalo
|
||||
// request.
|
||||
//
|
||||
//nolint:funlen
|
||||
func Catalog(resolver source.FileResolver, _ *linux.Release, parallelism int, catalogers ...pkg.Cataloger) (*pkg.Catalog, []artifact.Relationship, error) {
|
||||
catalog := pkg.NewCatalog()
|
||||
func Catalog(resolver source.FileResolver, _ *linux.Release, parallelism int, catalogers ...pkg.Cataloger) (*pkg.Collection, []artifact.Relationship, error) {
|
||||
catalog := pkg.NewCollection()
|
||||
var allRelationships []artifact.Relationship
|
||||
|
||||
filesProcessed, packagesDiscovered := newMonitor()
|
||||
|
||||
@@ -41,22 +41,21 @@ const AllCatalogersPattern = "all"
|
||||
func ImageCatalogers(cfg Config) []pkg.Cataloger {
|
||||
return filterCatalogers([]pkg.Cataloger{
|
||||
alpm.NewAlpmdbCataloger(),
|
||||
ruby.NewGemSpecCataloger(),
|
||||
python.NewPythonPackageCataloger(),
|
||||
php.NewComposerInstalledCataloger(),
|
||||
javascript.NewPackageCataloger(),
|
||||
apkdb.NewApkdbCataloger(),
|
||||
binary.NewCataloger(),
|
||||
deb.NewDpkgdbCataloger(),
|
||||
rpm.NewRpmDBCataloger(),
|
||||
dotnet.NewDotnetDepsCataloger(),
|
||||
golang.NewGoModuleBinaryCataloger(cfg.Go()),
|
||||
java.NewJavaCataloger(cfg.Java()),
|
||||
java.NewNativeImageCataloger(),
|
||||
apkdb.NewApkdbCataloger(),
|
||||
golang.NewGoModuleBinaryCataloger(cfg.Go()),
|
||||
dotnet.NewDotnetDepsCataloger(),
|
||||
portage.NewPortageCataloger(),
|
||||
javascript.NewPackageCataloger(),
|
||||
nix.NewStoreCataloger(),
|
||||
php.NewComposerInstalledCataloger(),
|
||||
portage.NewPortageCataloger(),
|
||||
python.NewPythonPackageCataloger(),
|
||||
rpm.NewRpmDBCataloger(),
|
||||
ruby.NewGemSpecCataloger(),
|
||||
sbom.NewSBOMCataloger(),
|
||||
binary.NewCataloger(),
|
||||
kernel.NewLinuxKernelCataloger(cfg.Kernel()),
|
||||
}, cfg.Catalogers)
|
||||
}
|
||||
|
||||
@@ -64,34 +63,33 @@ func ImageCatalogers(cfg Config) []pkg.Cataloger {
|
||||
func DirectoryCatalogers(cfg Config) []pkg.Cataloger {
|
||||
return filterCatalogers([]pkg.Cataloger{
|
||||
alpm.NewAlpmdbCataloger(),
|
||||
ruby.NewGemFileLockCataloger(),
|
||||
python.NewPythonIndexCataloger(),
|
||||
python.NewPythonPackageCataloger(),
|
||||
php.NewComposerLockCataloger(),
|
||||
javascript.NewLockCataloger(),
|
||||
deb.NewDpkgdbCataloger(),
|
||||
rpm.NewRpmDBCataloger(),
|
||||
rpm.NewFileCataloger(),
|
||||
java.NewJavaCataloger(cfg.Java()),
|
||||
java.NewJavaPomCataloger(),
|
||||
java.NewNativeImageCataloger(),
|
||||
java.NewJavaGradleLockfileCataloger(),
|
||||
apkdb.NewApkdbCataloger(),
|
||||
golang.NewGoModuleBinaryCataloger(cfg.Go()),
|
||||
golang.NewGoModFileCataloger(cfg.Go()),
|
||||
rust.NewCargoLockCataloger(),
|
||||
dart.NewPubspecLockCataloger(),
|
||||
dotnet.NewDotnetDepsCataloger(),
|
||||
swift.NewCocoapodsCataloger(),
|
||||
cpp.NewConanCataloger(),
|
||||
portage.NewPortageCataloger(),
|
||||
haskell.NewHackageCataloger(),
|
||||
sbom.NewSBOMCataloger(),
|
||||
binary.NewCataloger(),
|
||||
cpp.NewConanCataloger(),
|
||||
dart.NewPubspecLockCataloger(),
|
||||
deb.NewDpkgdbCataloger(),
|
||||
dotnet.NewDotnetDepsCataloger(),
|
||||
elixir.NewMixLockCataloger(),
|
||||
erlang.NewRebarLockCataloger(),
|
||||
kernel.NewLinuxKernelCataloger(cfg.Kernel()),
|
||||
golang.NewGoModFileCataloger(cfg.Go()),
|
||||
golang.NewGoModuleBinaryCataloger(cfg.Go()),
|
||||
haskell.NewHackageCataloger(),
|
||||
java.NewJavaCataloger(cfg.Java()),
|
||||
java.NewJavaGradleLockfileCataloger(),
|
||||
java.NewJavaPomCataloger(),
|
||||
java.NewNativeImageCataloger(),
|
||||
javascript.NewLockCataloger(),
|
||||
nix.NewStoreCataloger(),
|
||||
php.NewComposerLockCataloger(),
|
||||
portage.NewPortageCataloger(),
|
||||
python.NewPythonIndexCataloger(),
|
||||
python.NewPythonPackageCataloger(),
|
||||
rpm.NewFileCataloger(),
|
||||
rpm.NewRpmDBCataloger(),
|
||||
ruby.NewGemFileLockCataloger(),
|
||||
rust.NewCargoLockCataloger(),
|
||||
sbom.NewSBOMCataloger(),
|
||||
swift.NewCocoapodsCataloger(),
|
||||
}, cfg.Catalogers)
|
||||
}
|
||||
|
||||
@@ -99,38 +97,38 @@ func DirectoryCatalogers(cfg Config) []pkg.Cataloger {
|
||||
func AllCatalogers(cfg Config) []pkg.Cataloger {
|
||||
return filterCatalogers([]pkg.Cataloger{
|
||||
alpm.NewAlpmdbCataloger(),
|
||||
ruby.NewGemFileLockCataloger(),
|
||||
ruby.NewGemSpecCataloger(),
|
||||
python.NewPythonIndexCataloger(),
|
||||
python.NewPythonPackageCataloger(),
|
||||
javascript.NewLockCataloger(),
|
||||
javascript.NewPackageCataloger(),
|
||||
deb.NewDpkgdbCataloger(),
|
||||
rpm.NewRpmDBCataloger(),
|
||||
rpm.NewFileCataloger(),
|
||||
java.NewJavaCataloger(cfg.Java()),
|
||||
java.NewJavaPomCataloger(),
|
||||
java.NewNativeImageCataloger(),
|
||||
java.NewJavaGradleLockfileCataloger(),
|
||||
apkdb.NewApkdbCataloger(),
|
||||
golang.NewGoModuleBinaryCataloger(cfg.Go()),
|
||||
golang.NewGoModFileCataloger(cfg.Go()),
|
||||
rust.NewCargoLockCataloger(),
|
||||
rust.NewAuditBinaryCataloger(),
|
||||
dart.NewPubspecLockCataloger(),
|
||||
dotnet.NewDotnetDepsCataloger(),
|
||||
php.NewComposerInstalledCataloger(),
|
||||
php.NewComposerLockCataloger(),
|
||||
swift.NewCocoapodsCataloger(),
|
||||
cpp.NewConanCataloger(),
|
||||
portage.NewPortageCataloger(),
|
||||
haskell.NewHackageCataloger(),
|
||||
sbom.NewSBOMCataloger(),
|
||||
binary.NewCataloger(),
|
||||
cpp.NewConanCataloger(),
|
||||
dart.NewPubspecLockCataloger(),
|
||||
deb.NewDpkgdbCataloger(),
|
||||
dotnet.NewDotnetDepsCataloger(),
|
||||
elixir.NewMixLockCataloger(),
|
||||
erlang.NewRebarLockCataloger(),
|
||||
golang.NewGoModFileCataloger(cfg.Go()),
|
||||
golang.NewGoModuleBinaryCataloger(cfg.Go()),
|
||||
haskell.NewHackageCataloger(),
|
||||
java.NewJavaCataloger(cfg.Java()),
|
||||
java.NewJavaGradleLockfileCataloger(),
|
||||
java.NewJavaPomCataloger(),
|
||||
java.NewNativeImageCataloger(),
|
||||
javascript.NewLockCataloger(),
|
||||
javascript.NewPackageCataloger(),
|
||||
kernel.NewLinuxKernelCataloger(cfg.Kernel()),
|
||||
nix.NewStoreCataloger(),
|
||||
php.NewComposerInstalledCataloger(),
|
||||
php.NewComposerLockCataloger(),
|
||||
portage.NewPortageCataloger(),
|
||||
python.NewPythonIndexCataloger(),
|
||||
python.NewPythonPackageCataloger(),
|
||||
rpm.NewFileCataloger(),
|
||||
rpm.NewRpmDBCataloger(),
|
||||
ruby.NewGemFileLockCataloger(),
|
||||
ruby.NewGemSpecCataloger(),
|
||||
rust.NewAuditBinaryCataloger(),
|
||||
rust.NewCargoLockCataloger(),
|
||||
sbom.NewSBOMCataloger(),
|
||||
swift.NewCocoapodsCataloger(),
|
||||
}, cfg.Catalogers)
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,12 @@ var defaultCandidateAdditions = buildCandidateLookup(
|
||||
candidateKey{PkgName: "spring-core"},
|
||||
candidateAddition{AdditionalProducts: []string{"spring_framework", "springsource_spring_framework"}, AdditionalVendors: []string{"pivotal_software", "springsource", "vmware"}},
|
||||
},
|
||||
{
|
||||
// example image: docker.io/jenkins/jenkins:latest
|
||||
pkg.JavaPkg,
|
||||
candidateKey{PkgName: "spring-security-core"},
|
||||
candidateAddition{AdditionalProducts: []string{"spring_security"}, AdditionalVendors: []string{"vmware"}},
|
||||
},
|
||||
{
|
||||
// example image: docker.io/nuxeo:latest
|
||||
pkg.JavaPkg,
|
||||
|
||||
@@ -768,6 +768,14 @@ func TestCandidateProducts(t *testing.T) {
|
||||
},
|
||||
expected: []string{"spring_framework", "springsource_spring_framework" /* <-- known good names | default guess --> */, "springframework"},
|
||||
},
|
||||
{
|
||||
name: "spring-security-core",
|
||||
p: pkg.Package{
|
||||
Name: "spring-security-core",
|
||||
Type: pkg.JavaPkg,
|
||||
},
|
||||
expected: []string{"spring-security-core", "spring_security", "spring_security_core"},
|
||||
},
|
||||
{
|
||||
name: "java",
|
||||
p: pkg.Package{
|
||||
@@ -857,6 +865,14 @@ func TestCandidateVendor(t *testing.T) {
|
||||
},
|
||||
expected: []string{"elastic" /* <-- known good names | default guess --> */, "elasticsearch"},
|
||||
},
|
||||
{
|
||||
name: "spring-security",
|
||||
p: pkg.Package{
|
||||
Name: "spring-security-core",
|
||||
Type: pkg.JavaPkg,
|
||||
},
|
||||
expected: []string{"vmware" /* <-- known good names | default guess --> */, "spring", "spring-security", "spring-security-core", "spring_security_core", "spring_security"},
|
||||
},
|
||||
{
|
||||
name: "log4j",
|
||||
p: pkg.Package{
|
||||
|
||||
@@ -72,7 +72,7 @@ $(PKGSDIR)/gcc-amd64-darwin-exec-debug:
|
||||
./build-example-macho-binary.sh $(PKGSDIR)
|
||||
|
||||
# we need a way to determine if CI should bust the test cache based on the source material
|
||||
$(PKGSDIR).fingerprint: clean-examples
|
||||
mkdir -p $(PKGSDIR)
|
||||
find example-* build-* Makefile -type f -exec sha256sum {} \; | sort | tee /dev/stderr | tee $(PKGSDIR).fingerprint
|
||||
sha256sum $(PKGSDIR).fingerprint
|
||||
.PHONY: cache.fingerprint
|
||||
cache.fingerprint:
|
||||
find example* build* gradle* Makefile -type f -exec sha256sum {} \; | sort | tee /dev/stderr | tee cache.fingerprint
|
||||
sha256sum cache.fingerprint
|
||||
|
||||
@@ -3,6 +3,7 @@ package javascript
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
@@ -16,7 +17,8 @@ import (
|
||||
var _ generic.Parser = parsePnpmLock
|
||||
|
||||
type pnpmLockYaml struct {
|
||||
Dependencies map[string]string `json:"dependencies"`
|
||||
Dependencies map[string]string `json:"dependencies"`
|
||||
Packages map[string]interface{} `json:"packages"`
|
||||
}
|
||||
|
||||
func parsePnpmLock(resolver source.FileResolver, _ *generic.Environment, reader source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
@@ -36,6 +38,19 @@ func parsePnpmLock(resolver source.FileResolver, _ *generic.Environment, reader
|
||||
pkgs = append(pkgs, newPnpmPackage(resolver, reader.Location, name, version))
|
||||
}
|
||||
|
||||
// parse packages from packages section of pnpm-lock.yaml
|
||||
for nameVersion := range lockFile.Packages {
|
||||
nameVersionSplit := strings.Split(strings.TrimPrefix(nameVersion, "/"), "/")
|
||||
|
||||
// last element in split array is version
|
||||
version := nameVersionSplit[len(nameVersionSplit)-1]
|
||||
|
||||
// construct name from all array items other than last item (version)
|
||||
name := strings.Join(nameVersionSplit[:len(nameVersionSplit)-1], "/")
|
||||
|
||||
pkgs = append(pkgs, newPnpmPackage(resolver, reader.Location, name, version))
|
||||
}
|
||||
|
||||
pkg.Sort(pkgs)
|
||||
|
||||
return pkgs, nil, nil
|
||||
|
||||
@@ -40,6 +40,14 @@ func TestParsePnpmLock(t *testing.T) {
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
},
|
||||
{
|
||||
Name: "@bcoe/v8-coverage",
|
||||
Version: "0.2.3",
|
||||
PURL: "pkg:npm/%40bcoe/v8-coverage@0.2.3",
|
||||
Locations: locationSet,
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
},
|
||||
}
|
||||
|
||||
pkgtest.TestFileParser(t, fixture, parsePnpmLock, expectedPkgs, expectedRelationships)
|
||||
|
||||
@@ -40,6 +40,23 @@ func newPackageForIndexWithMetadata(name, version string, metadata pkg.PythonPip
|
||||
return p
|
||||
}
|
||||
|
||||
func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.PythonRequirementsMetadata, locations ...source.Location) pkg.Package {
|
||||
p := pkg.Package{
|
||||
Name: name,
|
||||
Version: version,
|
||||
Locations: source.NewLocationSet(locations...),
|
||||
PURL: packageURL(name, version, nil),
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
MetadataType: pkg.PythonRequirementsMetadataType,
|
||||
Metadata: metadata,
|
||||
}
|
||||
|
||||
p.SetID()
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func newPackageForPackage(m pkg.PythonPackageMetadata, sources ...source.Location) pkg.Package {
|
||||
var licenses []string
|
||||
if m.License != "" {
|
||||
|
||||
@@ -3,6 +3,7 @@ package python
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
@@ -15,6 +16,11 @@ import (
|
||||
|
||||
var _ generic.Parser = parseRequirementsTxt
|
||||
|
||||
var (
|
||||
extrasRegex = regexp.MustCompile(`\[.*\]`)
|
||||
urlRegex = regexp.MustCompile("@.*git.*")
|
||||
)
|
||||
|
||||
// parseRequirementsTxt takes a Python requirements.txt file, returning all Python packages that are locked to a
|
||||
// specific version.
|
||||
func parseRequirementsTxt(_ source.FileResolver, _ *generic.Environment, reader source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
@@ -23,6 +29,7 @@ func parseRequirementsTxt(_ source.FileResolver, _ *generic.Environment, reader
|
||||
scanner := bufio.NewScanner(reader)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
rawLineNoComments := removeTrailingComment(line)
|
||||
line = trimRequirementsTxtLine(line)
|
||||
|
||||
if line == "" {
|
||||
@@ -57,15 +64,25 @@ func parseRequirementsTxt(_ source.FileResolver, _ *generic.Environment, reader
|
||||
return !unicode.IsLetter(r) && !unicode.IsNumber(r)
|
||||
})
|
||||
|
||||
// TODO: Update to support more than only ==
|
||||
versionConstraint := fmt.Sprintf("== %s", version)
|
||||
|
||||
if name == "" || version == "" {
|
||||
log.WithFields("path", reader.RealPath).Debugf("found empty package in requirements.txt line: %q", line)
|
||||
continue
|
||||
}
|
||||
packages = append(
|
||||
packages,
|
||||
newPackageForIndex(
|
||||
newPackageForRequirementsWithMetadata(
|
||||
name,
|
||||
version,
|
||||
pkg.PythonRequirementsMetadata{
|
||||
Name: name,
|
||||
Extras: parseExtras(rawLineNoComments),
|
||||
VersionConstraint: versionConstraint,
|
||||
URL: parseURL(rawLineNoComments),
|
||||
Markers: parseMarkers(rawLineNoComments),
|
||||
},
|
||||
reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
||||
),
|
||||
)
|
||||
@@ -93,6 +110,7 @@ func trimRequirementsTxtLine(line string) string {
|
||||
line = strings.TrimSpace(line)
|
||||
line = removeTrailingComment(line)
|
||||
line = removeEnvironmentMarkers(line)
|
||||
line = checkForRegex(line) // remove extras and url from line if found
|
||||
|
||||
return line
|
||||
}
|
||||
@@ -121,3 +139,84 @@ func removeEnvironmentMarkers(line string) string {
|
||||
|
||||
return parts[0]
|
||||
}
|
||||
|
||||
func parseExtras(packageName string) []string {
|
||||
if extrasRegex.MatchString(packageName) {
|
||||
// Remove square brackets
|
||||
extras := strings.TrimFunc(extrasRegex.FindString(packageName), func(r rune) bool {
|
||||
return !unicode.IsLetter(r) && !unicode.IsNumber(r)
|
||||
})
|
||||
|
||||
// Remove any additional whitespace
|
||||
extras = strings.ReplaceAll(extras, " ", "")
|
||||
|
||||
return strings.Split(extras, ",")
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func parseMarkers(line string) map[string]string {
|
||||
markers := map[string]string{}
|
||||
parts := strings.SplitN(line, ";", 2)
|
||||
|
||||
if len(parts) == 2 {
|
||||
splittableMarkers := parts[1]
|
||||
|
||||
for _, combineString := range []string{" or ", " and "} {
|
||||
splittableMarkers = strings.TrimSpace(
|
||||
strings.ReplaceAll(splittableMarkers, combineString, ","),
|
||||
)
|
||||
}
|
||||
|
||||
splittableMarkers = strings.TrimSpace(splittableMarkers)
|
||||
|
||||
for _, mark := range strings.Split(splittableMarkers, ",") {
|
||||
markparts := strings.Split(mark, " ")
|
||||
markers[markparts[0]] = strings.Join(markparts[1:], " ")
|
||||
}
|
||||
}
|
||||
|
||||
return markers
|
||||
}
|
||||
|
||||
func parseURL(line string) string {
|
||||
parts := strings.Split(line, "@")
|
||||
|
||||
if len(parts) > 1 {
|
||||
desiredIndex := -1
|
||||
|
||||
for index, part := range parts {
|
||||
part := strings.TrimFunc(part, func(r rune) bool {
|
||||
return !unicode.IsLetter(r) && !unicode.IsNumber(r)
|
||||
})
|
||||
|
||||
if strings.HasPrefix(part, "git") {
|
||||
desiredIndex = index
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if desiredIndex != -1 {
|
||||
return strings.TrimSpace(strings.Join(parts[desiredIndex:], "@"))
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// function to check a string for all possilbe regex expressions, replacing it if found
|
||||
func checkForRegex(stringToCheck string) string {
|
||||
stringToReturn := stringToCheck
|
||||
|
||||
for _, r := range []*regexp.Regexp{
|
||||
urlRegex,
|
||||
extrasRegex,
|
||||
} {
|
||||
if r.MatchString(stringToCheck) {
|
||||
stringToReturn = r.ReplaceAllString(stringToCheck, "")
|
||||
}
|
||||
}
|
||||
|
||||
return stringToReturn
|
||||
}
|
||||
|
||||
@@ -14,44 +14,135 @@ func TestParseRequirementsTxt(t *testing.T) {
|
||||
locations := source.NewLocationSet(source.NewLocation(fixture))
|
||||
expectedPkgs := []pkg.Package{
|
||||
{
|
||||
Name: "flask",
|
||||
Version: "4.0.0",
|
||||
PURL: "pkg:pypi/flask@4.0.0",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
Name: "flask",
|
||||
Version: "4.0.0",
|
||||
PURL: "pkg:pypi/flask@4.0.0",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
MetadataType: pkg.PythonRequirementsMetadataType,
|
||||
Metadata: pkg.PythonRequirementsMetadata{
|
||||
Name: "flask",
|
||||
Extras: []string{},
|
||||
VersionConstraint: "== 4.0.0",
|
||||
URL: "",
|
||||
Markers: map[string]string{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
Version: "1.0.0",
|
||||
PURL: "pkg:pypi/foo@1.0.0",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
Name: "foo",
|
||||
Version: "1.0.0",
|
||||
PURL: "pkg:pypi/foo@1.0.0",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
MetadataType: pkg.PythonRequirementsMetadataType,
|
||||
Metadata: pkg.PythonRequirementsMetadata{
|
||||
Name: "foo",
|
||||
Extras: []string{},
|
||||
VersionConstraint: "== 1.0.0",
|
||||
URL: "",
|
||||
Markers: map[string]string{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "SomeProject",
|
||||
Version: "5.4",
|
||||
PURL: "pkg:pypi/SomeProject@5.4",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
Name: "SomeProject",
|
||||
Version: "5.4",
|
||||
PURL: "pkg:pypi/SomeProject@5.4",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
MetadataType: pkg.PythonRequirementsMetadataType,
|
||||
Metadata: pkg.PythonRequirementsMetadata{
|
||||
Name: "SomeProject",
|
||||
Extras: []string{},
|
||||
VersionConstraint: "== 5.4",
|
||||
URL: "",
|
||||
Markers: map[string]string{"python_version": "< '3.8'"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "argh",
|
||||
Version: "0.26.2",
|
||||
PURL: "pkg:pypi/argh@0.26.2",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
Name: "argh",
|
||||
Version: "0.26.2",
|
||||
PURL: "pkg:pypi/argh@0.26.2",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
MetadataType: pkg.PythonRequirementsMetadataType,
|
||||
Metadata: pkg.PythonRequirementsMetadata{
|
||||
Name: "argh",
|
||||
Extras: []string{},
|
||||
VersionConstraint: "== 0.26.2",
|
||||
URL: "",
|
||||
Markers: map[string]string{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "argh",
|
||||
Version: "0.26.3",
|
||||
PURL: "pkg:pypi/argh@0.26.3",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
Name: "argh",
|
||||
Version: "0.26.3",
|
||||
PURL: "pkg:pypi/argh@0.26.3",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
MetadataType: pkg.PythonRequirementsMetadataType,
|
||||
Metadata: pkg.PythonRequirementsMetadata{
|
||||
Name: "argh",
|
||||
Extras: []string{},
|
||||
VersionConstraint: "== 0.26.3",
|
||||
URL: "",
|
||||
Markers: map[string]string{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "celery",
|
||||
Version: "4.4.7",
|
||||
PURL: "pkg:pypi/celery@4.4.7",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
MetadataType: pkg.PythonRequirementsMetadataType,
|
||||
Metadata: pkg.PythonRequirementsMetadata{
|
||||
Name: "celery",
|
||||
Extras: []string{"redis", "pytest"},
|
||||
VersionConstraint: "== 4.4.7",
|
||||
URL: "",
|
||||
Markers: map[string]string{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "requests",
|
||||
Version: "2.8",
|
||||
PURL: "pkg:pypi/requests@2.8",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
MetadataType: pkg.PythonRequirementsMetadataType,
|
||||
Metadata: pkg.PythonRequirementsMetadata{
|
||||
Name: "requests",
|
||||
Extras: []string{"security"},
|
||||
VersionConstraint: "== 2.8",
|
||||
URL: "",
|
||||
Markers: map[string]string{
|
||||
"python_version": `< "2.7"`,
|
||||
"sys_platform": `== "linux"`,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "GithubSampleProject",
|
||||
Version: "3.7.1",
|
||||
PURL: "pkg:pypi/GithubSampleProject@3.7.1",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
MetadataType: pkg.PythonRequirementsMetadataType,
|
||||
Metadata: pkg.PythonRequirementsMetadata{
|
||||
Name: "GithubSampleProject",
|
||||
Extras: []string{},
|
||||
VersionConstraint: "== 3.7.1",
|
||||
URL: "git+https://github.com/owner/repo@releases/tag/v3.7.1",
|
||||
Markers: map[string]string{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -16,4 +16,7 @@ argh==0.26.2 \
|
||||
argh==0.26.3 --hash=sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3 --hash=sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65
|
||||
# CommentedOut == 1.2.3
|
||||
# maybe invalid, but found out in the wild
|
||||
==2.3.4
|
||||
==2.3.4
|
||||
celery[redis, pytest] == 4.4.7 # should remove [redis, pytest]
|
||||
requests[security] == 2.8.* ; python_version < "2.7" and sys_platform == "linux"
|
||||
GithubSampleProject == 3.7.1 @ git+https://github.com/owner/repo@releases/tag/v3.7.1
|
||||
|
||||
@@ -4,12 +4,20 @@ Package rpm provides a concrete DBCataloger implementation for RPM "Package" DB
|
||||
package rpm
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||
)
|
||||
|
||||
// NewRpmDBCataloger returns a new RPM DB cataloger object.
|
||||
func NewRpmDBCataloger() *generic.Cataloger {
|
||||
// check if a sqlite driver is available
|
||||
if !isSqliteDriverAvailable() {
|
||||
log.Warnf("sqlite driver is not available, newer RPM databases might not be cataloged")
|
||||
}
|
||||
|
||||
return generic.NewCataloger("rpm-db-cataloger").
|
||||
WithParserByGlobs(parseRpmDB, pkg.RpmDBGlob).
|
||||
WithParserByGlobs(parseRpmManifest, pkg.RpmManifestGlob)
|
||||
@@ -20,3 +28,8 @@ func NewFileCataloger() *generic.Cataloger {
|
||||
return generic.NewCataloger("rpm-file-cataloger").
|
||||
WithParserByGlobs(parseRpm, "**/*.rpm")
|
||||
}
|
||||
|
||||
func isSqliteDriverAvailable() bool {
|
||||
_, err := sql.Open("sqlite", ":memory:")
|
||||
return err == nil
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ func Test_DBCataloger_Globs(t *testing.T) {
|
||||
name: "obtain DB files",
|
||||
fixture: "test-fixtures/glob-paths",
|
||||
expected: []string{
|
||||
"usr/share/rpm/Packages",
|
||||
"usr/share/rpm/Packages.db",
|
||||
"usr/share/rpm/rpmdb.sqlite",
|
||||
"var/lib/rpm/Packages",
|
||||
"var/lib/rpm/Packages.db",
|
||||
"var/lib/rpm/rpmdb.sqlite",
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
bogus
|
||||
@@ -0,0 +1 @@
|
||||
bogus
|
||||
@@ -0,0 +1 @@
|
||||
bogus
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
var _ generic.Parser = parseGemFileLockEntries
|
||||
|
||||
var sectionsOfInterest = internal.NewStringSet("GEM")
|
||||
var sectionsOfInterest = internal.NewStringSet("GEM", "GIT", "PATH", "PLUGIN SOURCE")
|
||||
|
||||
// parseGemFileLockEntries is a parser function for Gemfile.lock contents, returning all Gems discovered.
|
||||
func parseGemFileLockEntries(_ source.FileResolver, _ *generic.Environment, reader source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
|
||||
@@ -26,6 +26,7 @@ func TestParseGemfileLockEntries(t *testing.T) {
|
||||
{Name: "coffee-script-source", Version: "1.7.0", PURL: "pkg:gem/coffee-script-source@1.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "erubis", Version: "2.7.0", PURL: "pkg:gem/erubis@2.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "execjs", Version: "2.0.2", PURL: "pkg:gem/execjs@2.0.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "google-cloud-errors", Version: "1.3.0", PURL: "pkg:gem/google-cloud-errors@1.3.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "hike", Version: "1.2.3", PURL: "pkg:gem/hike@1.2.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "i18n", Version: "0.6.9", PURL: "pkg:gem/i18n@0.6.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "jbuilder", Version: "2.0.7", PURL: "pkg:gem/jbuilder@2.0.7", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
@@ -59,7 +60,7 @@ func TestParseGemfileLockEntries(t *testing.T) {
|
||||
{Name: "thread_safe", Version: "0.3.3", PURL: "pkg:gem/thread_safe@0.3.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "tilt", Version: "1.4.1", PURL: "pkg:gem/tilt@1.4.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "treetop", Version: "1.4.15", PURL: "pkg:gem/treetop@1.4.15", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "turbolinks", Version: "2.2.2", PURL: "pkg:gem/turbolinks@2.2.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "turbolinks", Version: "3.0.0", PURL: "pkg:gem/turbolinks@3.0.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "tzinfo", Version: "1.2.0", PURL: "pkg:gem/tzinfo@1.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "uglifier", Version: "2.5.0", PURL: "pkg:gem/uglifier@2.5.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
{Name: "unicorn", Version: "4.8.3", PURL: "pkg:gem/unicorn@4.8.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
PATH
|
||||
remote: ../google-cloud-errors
|
||||
specs:
|
||||
google-cloud-errors (1.3.0)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/rails/turbolinks.git
|
||||
revision: 80216ce9d89920bf073709405e3fce6d0a3ccd9a
|
||||
specs:
|
||||
turbolinks (3.0.0)
|
||||
coffee-rails
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
@@ -111,8 +123,6 @@ GEM
|
||||
treetop (1.4.15)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
turbolinks (2.2.2)
|
||||
coffee-rails
|
||||
tzinfo (1.2.0)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (2.5.0)
|
||||
@@ -135,6 +145,7 @@ PLATFORMS
|
||||
DEPENDENCIES
|
||||
bootstrap-sass
|
||||
coffee-rails (~> 4.0.0)
|
||||
google-cloud-errors!
|
||||
jbuilder (~> 2.0)
|
||||
jquery-rails
|
||||
mysql2 (~> 0.3.16)
|
||||
@@ -144,6 +155,6 @@ DEPENDENCIES
|
||||
spring
|
||||
sqlite3
|
||||
therubyracer
|
||||
turbolinks
|
||||
turbolinks!
|
||||
uglifier (>= 1.3.0)
|
||||
unicorn
|
||||
@@ -42,7 +42,7 @@ func parseSBOM(_ source.FileResolver, _ *generic.Environment, reader source.Loca
|
||||
|
||||
var pkgs []pkg.Package
|
||||
var relationships []artifact.Relationship
|
||||
for _, p := range s.Artifacts.PackageCatalog.Sorted() {
|
||||
for _, p := range s.Artifacts.Packages.Sorted() {
|
||||
// replace all locations on the package with the location of the SBOM file.
|
||||
// Why not keep the original list of locations? Since the "locations" field is meant to capture
|
||||
// where there is evidence of this file, and the catalogers have not run against any file other than,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package pkg
|
||||
|
||||
// Deprecated: use Collection instead
|
||||
type Catalog = Collection
|
||||
|
||||
// Deprecated: use NewCollection() instead
|
||||
func NewCatalog(pkgs ...Package) *Catalog {
|
||||
return NewCollection(pkgs...)
|
||||
}
|
||||
@@ -36,6 +36,7 @@ const (
|
||||
PortageMetadataType MetadataType = "PortageMetadata"
|
||||
PythonPackageMetadataType MetadataType = "PythonPackageMetadata"
|
||||
PythonPipfileLockMetadataType MetadataType = "PythonPipfileLockMetadata"
|
||||
PythonRequirementsMetadataType MetadataType = "PythonRequirementsMetadata"
|
||||
RebarLockMetadataType MetadataType = "RebarLockMetadataType"
|
||||
RpmMetadataType MetadataType = "RpmMetadata"
|
||||
RustCargoPackageMetadataType MetadataType = "RustCargoPackageMetadata"
|
||||
@@ -67,6 +68,7 @@ var AllMetadataTypes = []MetadataType{
|
||||
PortageMetadataType,
|
||||
PythonPackageMetadataType,
|
||||
PythonPipfileLockMetadataType,
|
||||
PythonRequirementsMetadataType,
|
||||
RebarLockMetadataType,
|
||||
RpmMetadataType,
|
||||
RustCargoPackageMetadataType,
|
||||
@@ -98,6 +100,7 @@ var MetadataTypeByName = map[MetadataType]reflect.Type{
|
||||
PortageMetadataType: reflect.TypeOf(PortageMetadata{}),
|
||||
PythonPackageMetadataType: reflect.TypeOf(PythonPackageMetadata{}),
|
||||
PythonPipfileLockMetadataType: reflect.TypeOf(PythonPipfileLockMetadata{}),
|
||||
PythonRequirementsMetadataType: reflect.TypeOf(PythonRequirementsMetadata{}),
|
||||
RebarLockMetadataType: reflect.TypeOf(RebarLockMetadata{}),
|
||||
RpmMetadataType: reflect.TypeOf(RpmMetadata{}),
|
||||
RustCargoPackageMetadataType: reflect.TypeOf(CargoPackageMetadata{}),
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package pkg
|
||||
|
||||
type PythonRequirementsMetadata struct {
|
||||
Name string `json:"name" mapstruct:"Name"`
|
||||
Extras []string `json:"extras" mapstruct:"Extras"`
|
||||
VersionConstraint string `json:"versionConstraint" mapstruct:"VersionConstraint"`
|
||||
URL string `json:"url" mapstruct:"URL"`
|
||||
Markers map[string]string `json:"markers" mapstruct:"Markers"`
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package pkg
|
||||
|
||||
import "github.com/anchore/syft/syft/artifact"
|
||||
|
||||
func NewRelationships(catalog *Catalog) []artifact.Relationship {
|
||||
func NewRelationships(catalog *Collection) []artifact.Relationship {
|
||||
rels := RelationshipsByFileOwnership(catalog)
|
||||
rels = append(rels, RelationshipsEvidentBy(catalog)...)
|
||||
return rels
|
||||
|
||||
@@ -31,7 +31,7 @@ type ownershipByFilesMetadata struct {
|
||||
|
||||
// RelationshipsByFileOwnership creates a package-to-package relationship based on discovering which packages have
|
||||
// evidence locations that overlap with ownership claim from another package's package manager metadata.
|
||||
func RelationshipsByFileOwnership(catalog *Catalog) []artifact.Relationship {
|
||||
func RelationshipsByFileOwnership(catalog *Collection) []artifact.Relationship {
|
||||
var relationships = findOwnershipByFilesRelationships(catalog)
|
||||
|
||||
var edges []artifact.Relationship
|
||||
@@ -55,7 +55,7 @@ func RelationshipsByFileOwnership(catalog *Catalog) []artifact.Relationship {
|
||||
|
||||
// findOwnershipByFilesRelationships find overlaps in file ownership with a file that defines another package. Specifically, a .Location.Path of
|
||||
// a package is found to be owned by another (from the owner's .Metadata.Files[]).
|
||||
func findOwnershipByFilesRelationships(catalog *Catalog) map[artifact.ID]map[artifact.ID]*strset.Set {
|
||||
func findOwnershipByFilesRelationships(catalog *Collection) map[artifact.ID]map[artifact.ID]*strset.Set {
|
||||
var relationships = make(map[artifact.ID]map[artifact.ID]*strset.Set)
|
||||
|
||||
if catalog == nil {
|
||||
|
||||
@@ -139,7 +139,7 @@ func TestOwnershipByFilesRelationship(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
pkgs, expectedRelations := test.setup(t)
|
||||
c := NewCatalog(pkgs...)
|
||||
c := NewCollection(pkgs...)
|
||||
relationships := RelationshipsByFileOwnership(c)
|
||||
|
||||
assert.Len(t, relationships, len(expectedRelations))
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
)
|
||||
|
||||
func RelationshipsEvidentBy(catalog *Catalog) []artifact.Relationship {
|
||||
func RelationshipsEvidentBy(catalog *Collection) []artifact.Relationship {
|
||||
var edges []artifact.Relationship
|
||||
for _, p := range catalog.Sorted() {
|
||||
for _, l := range p.Locations.ToSlice() {
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
func TestRelationshipsEvidentBy(t *testing.T) {
|
||||
|
||||
c := NewCatalog()
|
||||
c := NewCollection()
|
||||
|
||||
coordA := source.Coordinates{
|
||||
RealPath: "/somewhere/real",
|
||||
@@ -53,7 +53,7 @@ func TestRelationshipsEvidentBy(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
catalog *Catalog
|
||||
catalog *Collection
|
||||
want []artifact.Relationship
|
||||
}{
|
||||
{
|
||||
|
||||
@@ -8,10 +8,12 @@ import (
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
|
||||
// /var/lib/rpm/... is the typical path for most distributions
|
||||
// /usr/share/rpm/... is common for rpm-ostree distributions (coreos-like)
|
||||
// Packages is the legacy Berkely db based format
|
||||
// Packages.db is the "ndb" format used in SUSE
|
||||
// rpmdb.sqlite is the sqlite format used in fedora + derivates
|
||||
const RpmDBGlob = "**/var/lib/rpm/{Packages,Packages.db,rpmdb.sqlite}"
|
||||
const RpmDBGlob = "**/{var/lib,usr/share}/rpm/{Packages,Packages.db,rpmdb.sqlite}"
|
||||
|
||||
// Used in CBL-Mariner distroless images
|
||||
const RpmManifestGlob = "**/var/lib/rpmmanifest/container-manifest-2"
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ type SBOM struct {
|
||||
}
|
||||
|
||||
type Artifacts struct {
|
||||
PackageCatalog *pkg.Catalog
|
||||
Packages *pkg.Collection
|
||||
FileMetadata map[source.Coordinates]source.FileMetadata
|
||||
FileDigests map[source.Coordinates][]file.Digest
|
||||
FileContents map[source.Coordinates]string
|
||||
|
||||
@@ -96,7 +96,7 @@ func TestPackagesCmdFlags(t *testing.T) {
|
||||
name: "squashed-scope-flag",
|
||||
args: []string{"packages", "-o", "json", "-s", "squashed", coverageImage},
|
||||
assertions: []traitAssertion{
|
||||
assertPackageCount(37),
|
||||
assertPackageCount(35),
|
||||
assertSuccessfulReturnCode,
|
||||
},
|
||||
},
|
||||
@@ -213,7 +213,7 @@ func TestPackagesCmdFlags(t *testing.T) {
|
||||
// the application config in the log matches that of what we expect to have been configured.
|
||||
assertInOutput("parallelism: 2"),
|
||||
assertInOutput("parallelism=2"),
|
||||
assertPackageCount(37),
|
||||
assertPackageCount(35),
|
||||
assertSuccessfulReturnCode,
|
||||
},
|
||||
},
|
||||
@@ -224,7 +224,7 @@ func TestPackagesCmdFlags(t *testing.T) {
|
||||
// the application config in the log matches that of what we expect to have been configured.
|
||||
assertInOutput("parallelism: 1"),
|
||||
assertInOutput("parallelism=1"),
|
||||
assertPackageCount(37),
|
||||
assertPackageCount(35),
|
||||
assertSuccessfulReturnCode,
|
||||
},
|
||||
},
|
||||
@@ -238,7 +238,7 @@ func TestPackagesCmdFlags(t *testing.T) {
|
||||
assertions: []traitAssertion{
|
||||
assertNotInOutput("secret_password"),
|
||||
assertNotInOutput("secret_key_path"),
|
||||
assertPackageCount(37),
|
||||
assertPackageCount(35),
|
||||
assertSuccessfulReturnCode,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -11,8 +11,8 @@ func Test_AllLayersIncludesSquashed(t *testing.T) {
|
||||
allLayers, _ := catalogFixtureImage(t, "image-suse-all-layers", source.AllLayersScope, nil)
|
||||
squashed, _ := catalogFixtureImage(t, "image-suse-all-layers", source.SquashedScope, nil)
|
||||
|
||||
lenAllLayers := len(allLayers.Artifacts.PackageCatalog.Sorted())
|
||||
lenSquashed := len(squashed.Artifacts.PackageCatalog.Sorted())
|
||||
lenAllLayers := len(allLayers.Artifacts.Packages.Sorted())
|
||||
lenSquashed := len(squashed.Artifacts.Packages.Sorted())
|
||||
|
||||
if lenAllLayers < lenSquashed {
|
||||
t.Errorf("squashed has more packages than all-layers: %d > %d", lenSquashed, lenAllLayers)
|
||||
|
||||
@@ -11,20 +11,6 @@ type testCase struct {
|
||||
}
|
||||
|
||||
var imageOnlyTestCases = []testCase{
|
||||
{
|
||||
name: "find kernel packages",
|
||||
pkgType: pkg.LinuxKernelPkg,
|
||||
pkgInfo: map[string]string{
|
||||
"linux-kernel": "6.0.7-301.fc37.x86_64",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find kernel module packages",
|
||||
pkgType: pkg.LinuxKernelModulePkg,
|
||||
pkgInfo: map[string]string{
|
||||
"ttynull": "",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find gemspec packages",
|
||||
pkgType: pkg.GemPkg,
|
||||
@@ -105,6 +91,7 @@ var dirOnlyTestCases = []testCase{
|
||||
"coffee-script-source": "1.7.0",
|
||||
"erubis": "2.7.0",
|
||||
"execjs": "2.0.2",
|
||||
"google-cloud-errors": "1.3.0",
|
||||
"hike": "1.2.3",
|
||||
"i18n": "0.6.9",
|
||||
"jbuilder": "2.0.7",
|
||||
@@ -138,7 +125,7 @@ var dirOnlyTestCases = []testCase{
|
||||
"thread_safe": "0.3.3",
|
||||
"tilt": "1.4.1",
|
||||
"treetop": "1.4.15",
|
||||
"turbolinks": "2.2.2",
|
||||
"turbolinks": "3.0.0",
|
||||
"tzinfo": "1.2.0",
|
||||
"uglifier": "2.5.0",
|
||||
"unicorn": "4.8.3",
|
||||
|
||||
@@ -22,7 +22,7 @@ func BenchmarkImagePackageCatalogers(b *testing.B) {
|
||||
imagetest.GetFixtureImage(b, "docker-archive", fixtureImageName)
|
||||
tarPath := imagetest.GetFixtureImageTarPath(b, fixtureImageName)
|
||||
|
||||
var pc *pkg.Catalog
|
||||
var pc *pkg.Collection
|
||||
for _, c := range cataloger.ImageCatalogers(cataloger.DefaultConfig()) {
|
||||
// in case of future alteration where state is persisted, assume no dependency is safe to reuse
|
||||
userInput := "docker-archive:" + tarPath
|
||||
@@ -91,6 +91,8 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
definedPkgs.Remove(string(pkg.HackagePkg))
|
||||
definedPkgs.Remove(string(pkg.BinaryPkg))
|
||||
definedPkgs.Remove(string(pkg.HexPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
||||
|
||||
var cases []testCase
|
||||
cases = append(cases, commonTestCases...)
|
||||
@@ -100,7 +102,7 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
pkgCount := 0
|
||||
|
||||
for a := range sbom.Artifacts.PackageCatalog.Enumerate(c.pkgType) {
|
||||
for a := range sbom.Artifacts.Packages.Enumerate(c.pkgType) {
|
||||
if a.Language.String() != "" {
|
||||
observedLanguages.Add(a.Language.String())
|
||||
}
|
||||
@@ -127,7 +129,7 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
|
||||
if pkgCount != len(c.pkgInfo)+c.duplicates {
|
||||
t.Logf("Discovered packages of type %+v", c.pkgType)
|
||||
for a := range sbom.Artifacts.PackageCatalog.Enumerate(c.pkgType) {
|
||||
for a := range sbom.Artifacts.Packages.Enumerate(c.pkgType) {
|
||||
t.Log(" ", a)
|
||||
}
|
||||
t.Fatalf("unexpected package count: %d!=%d", pkgCount, len(c.pkgInfo))
|
||||
@@ -176,7 +178,7 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
actualPkgCount := 0
|
||||
|
||||
for actualPkg := range sbom.Artifacts.PackageCatalog.Enumerate(test.pkgType) {
|
||||
for actualPkg := range sbom.Artifacts.Packages.Enumerate(test.pkgType) {
|
||||
observedLanguages.Add(actualPkg.Language.String())
|
||||
observedPkgs.Add(string(actualPkg.Type))
|
||||
|
||||
@@ -207,7 +209,7 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
||||
}
|
||||
|
||||
if actualPkgCount != len(test.pkgInfo)+test.duplicates {
|
||||
for actualPkg := range sbom.Artifacts.PackageCatalog.Enumerate(test.pkgType) {
|
||||
for actualPkg := range sbom.Artifacts.Packages.Enumerate(test.pkgType) {
|
||||
t.Log(" ", actualPkg)
|
||||
}
|
||||
t.Fatalf("unexpected package count: %d!=%d", actualPkgCount, len(test.pkgInfo))
|
||||
@@ -220,9 +222,9 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
||||
definedLanguages.Remove(pkg.UnknownLanguage.String())
|
||||
observedPkgs.Remove(string(pkg.UnknownPkg))
|
||||
definedPkgs.Remove(string(pkg.BinaryPkg))
|
||||
definedPkgs.Remove(string(pkg.UnknownPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
||||
definedPkgs.Remove(string(pkg.UnknownPkg))
|
||||
|
||||
// for directory scans we should not expect to see any of the following package types
|
||||
definedPkgs.Remove(string(pkg.KbPkg))
|
||||
@@ -246,7 +248,7 @@ func TestPkgCoverageCatalogerConfiguration(t *testing.T) {
|
||||
definedLanguages := internal.NewStringSet()
|
||||
definedLanguages.Add("rust")
|
||||
|
||||
for actualPkg := range sbom.Artifacts.PackageCatalog.Enumerate() {
|
||||
for actualPkg := range sbom.Artifacts.Packages.Enumerate() {
|
||||
observedLanguages.Add(actualPkg.Language.String())
|
||||
}
|
||||
|
||||
@@ -270,7 +272,7 @@ func TestPkgCoverageImage_HasEvidence(t *testing.T) {
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
|
||||
for a := range sbom.Artifacts.PackageCatalog.Enumerate(c.pkgType) {
|
||||
for a := range sbom.Artifacts.Packages.Enumerate(c.pkgType) {
|
||||
assert.NotEmpty(t, a.Locations.ToSlice(), "package %q has no locations (type=%q)", a.Name, a.Type)
|
||||
for _, l := range a.Locations.ToSlice() {
|
||||
if _, exists := l.Annotations[pkg.EvidenceAnnotationKey]; !exists {
|
||||
@@ -300,7 +302,7 @@ func TestPkgCoverageDirectory_HasEvidence(t *testing.T) {
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
|
||||
for a := range sbom.Artifacts.PackageCatalog.Enumerate(c.pkgType) {
|
||||
for a := range sbom.Artifacts.Packages.Enumerate(c.pkgType) {
|
||||
assert.NotEmpty(t, a.Locations.ToSlice(), "package %q has no locations (type=%q)", a.Name, a.Type)
|
||||
for _, l := range a.Locations.ToSlice() {
|
||||
if _, exists := l.Annotations[pkg.EvidenceAnnotationKey]; !exists {
|
||||
|
||||
@@ -12,7 +12,7 @@ func TestMarinerDistroless(t *testing.T) {
|
||||
|
||||
expectedPkgs := 12
|
||||
actualPkgs := 0
|
||||
for range sbom.Artifacts.PackageCatalog.Enumerate(pkg.RpmPkg) {
|
||||
for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) {
|
||||
actualPkgs += 1
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ func TestNpmPackageLockDirectory(t *testing.T) {
|
||||
|
||||
foundPackages := internal.NewStringSet()
|
||||
|
||||
for actualPkg := range sbom.Artifacts.PackageCatalog.Enumerate(pkg.NpmPkg) {
|
||||
for actualPkg := range sbom.Artifacts.Packages.Enumerate(pkg.NpmPkg) {
|
||||
for _, actualLocation := range actualPkg.Locations.ToSlice() {
|
||||
if strings.Contains(actualLocation.RealPath, "node_modules") {
|
||||
t.Errorf("found packages from package-lock.json in node_modules: %s", actualLocation)
|
||||
@@ -36,7 +36,7 @@ func TestYarnPackageLockDirectory(t *testing.T) {
|
||||
foundPackages := internal.NewStringSet()
|
||||
expectedPackages := internal.NewStringSet("async@0.9.2", "async@3.2.3", "merge-objects@1.0.5", "should-type@1.3.0", "@4lolo/resize-observer-polyfill@1.5.2")
|
||||
|
||||
for actualPkg := range sbom.Artifacts.PackageCatalog.Enumerate(pkg.NpmPkg) {
|
||||
for actualPkg := range sbom.Artifacts.Packages.Enumerate(pkg.NpmPkg) {
|
||||
for _, actualLocation := range actualPkg.Locations.ToSlice() {
|
||||
if strings.Contains(actualLocation.RealPath, "node_modules") {
|
||||
t.Errorf("found packages from yarn.lock in node_modules: %s", actualLocation)
|
||||
|
||||
@@ -65,15 +65,15 @@ func TestPackageDeduplication(t *testing.T) {
|
||||
t.Run(string(tt.scope), func(t *testing.T) {
|
||||
sbom, _ := catalogFixtureImage(t, "image-vertical-package-dups", tt.scope, nil)
|
||||
|
||||
for _, p := range sbom.Artifacts.PackageCatalog.Sorted() {
|
||||
for _, p := range sbom.Artifacts.Packages.Sorted() {
|
||||
if p.Type == pkg.BinaryPkg {
|
||||
assert.NotEmpty(t, p.Name)
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.packageCount, sbom.Artifacts.PackageCatalog.PackageCount())
|
||||
assert.Equal(t, tt.packageCount, sbom.Artifacts.Packages.PackageCount())
|
||||
for name, expectedInstanceCount := range tt.instanceCount {
|
||||
pkgs := sbom.Artifacts.PackageCatalog.PackagesByName(name)
|
||||
pkgs := sbom.Artifacts.Packages.PackagesByName(name)
|
||||
|
||||
// with multiple packages with the same name, something is wrong (or this is the wrong fixture)
|
||||
require.Len(t, pkgs, expectedInstanceCount)
|
||||
|
||||
@@ -14,7 +14,7 @@ func TestRegression212ApkBufferSize(t *testing.T) {
|
||||
|
||||
expectedPkgs := 58
|
||||
actualPkgs := 0
|
||||
for range sbom.Artifacts.PackageCatalog.Enumerate(pkg.ApkPkg) {
|
||||
for range sbom.Artifacts.Packages.Enumerate(pkg.ApkPkg) {
|
||||
actualPkgs += 1
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ func TestRegressionGoArchDiscovery(t *testing.T) {
|
||||
|
||||
var actualELF, actualWIN, actualMACOS int
|
||||
|
||||
for p := range sbom.Artifacts.PackageCatalog.Enumerate(pkg.GoModulePkg) {
|
||||
for p := range sbom.Artifacts.Packages.Enumerate(pkg.GoModulePkg) {
|
||||
for _, l := range p.Locations.ToSlice() {
|
||||
switch {
|
||||
case strings.Contains(l.RealPath, "elf"):
|
||||
|
||||
@@ -12,7 +12,7 @@ func TestRustAudit(t *testing.T) {
|
||||
|
||||
expectedPkgs := 2
|
||||
actualPkgs := 0
|
||||
for range sbom.Artifacts.PackageCatalog.Enumerate(pkg.RustPkg) {
|
||||
for range sbom.Artifacts.Packages.Enumerate(pkg.RustPkg) {
|
||||
actualPkgs += 1
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ func TestSbomCataloger(t *testing.T) {
|
||||
expectedGoModCatalogerPkgs := 2
|
||||
actualSbomPkgs := 0
|
||||
actualGoModPkgs := 0
|
||||
for pkg := range sbom.Artifacts.PackageCatalog.Enumerate(pkg.GoModulePkg) {
|
||||
for pkg := range sbom.Artifacts.Packages.Enumerate(pkg.GoModulePkg) {
|
||||
if pkg.FoundBy == "go-mod-file-cataloger" {
|
||||
actualGoModPkgs += 1
|
||||
} else if pkg.FoundBy == "sbom-cataloger" {
|
||||
|
||||
@@ -3,6 +3,8 @@ package integration
|
||||
import (
|
||||
"testing"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
@@ -14,7 +16,7 @@ func TestSqliteRpm(t *testing.T) {
|
||||
|
||||
expectedPkgs := 139
|
||||
actualPkgs := 0
|
||||
for range sbom.Artifacts.PackageCatalog.Enumerate(pkg.RpmPkg) {
|
||||
for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) {
|
||||
actualPkgs += 1
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
PATH
|
||||
remote: ../google-cloud-errors
|
||||
specs:
|
||||
google-cloud-errors (1.3.0)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/rails/turbolinks.git
|
||||
revision: 80216ce9d89920bf073709405e3fce6d0a3ccd9a
|
||||
specs:
|
||||
turbolinks (3.0.0)
|
||||
coffee-rails
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
@@ -111,8 +123,6 @@ GEM
|
||||
treetop (1.4.15)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
turbolinks (2.2.2)
|
||||
coffee-rails
|
||||
tzinfo (1.2.0)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (2.5.0)
|
||||
@@ -135,6 +145,7 @@ PLATFORMS
|
||||
DEPENDENCIES
|
||||
bootstrap-sass
|
||||
coffee-rails (~> 4.0.0)
|
||||
google-cloud-errors!
|
||||
jbuilder (~> 2.0)
|
||||
jquery-rails
|
||||
mysql2 (~> 0.3.16)
|
||||
@@ -144,6 +155,6 @@ DEPENDENCIES
|
||||
spring
|
||||
sqlite3
|
||||
therubyracer
|
||||
turbolinks
|
||||
turbolinks!
|
||||
uglifier (>= 1.3.0)
|
||||
unicorn
|
||||
@@ -33,7 +33,7 @@ func catalogFixtureImage(t *testing.T, fixtureImageName string, scope source.Sco
|
||||
|
||||
return sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
PackageCatalog: pkgCatalog,
|
||||
Packages: pkgCatalog,
|
||||
LinuxDistribution: actualDistro,
|
||||
},
|
||||
Relationships: relationships,
|
||||
@@ -68,7 +68,7 @@ func catalogDirectory(t *testing.T, dir string) (sbom.SBOM, *source.Source) {
|
||||
|
||||
return sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
PackageCatalog: pkgCatalog,
|
||||
Packages: pkgCatalog,
|
||||
LinuxDistribution: actualDistro,
|
||||
},
|
||||
Relationships: relationships,
|
||||
|
||||
Reference in New Issue
Block a user