Compare commits

...
24 Commits
Author SHA1 Message Date
Josh Bressers 0f1aed4477 Update the CPE generation for spring-security-core (#1789)
* Update the CPE generation for spring-security-core
* Add vendor test for spring-security

Signed-off-by: Josh Bressers <josh@bress.net>

---------

Signed-off-by: Josh Bressers <josh@bress.net>
2023-05-05 15:41:41 +00:00
Keith Zantow ddb338d834 chore: do not HTML escape PackageURLs (#1782)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-05-05 10:08:04 -04:00
Keith Zantow 354c72bbf4 chore: do not include kernel module cataloger by default (#1784) 2023-05-05 09:54:24 -04:00
Jeff Squyres d63a1f5f80 chore(docs): Update lists of catalogers (#1780)
Signed-off-by: Jeff Squyres <jeff@squyres.com>
2023-05-04 15:36:22 -04:00
Keith Zantow 645206735e chore: add more detail on SPDX file IDs (#1769) 2023-05-02 16:52:18 -04:00
Filip PytlounandAlex Goodman 95a04cadea Search /usr/share for rpmdb to fix scan on ostree-managed images (#1756)
Fixes: https://github.com/anchore/syft/issues/1755

Signed-off-by: Filip Pytloun <filip@pytloun.cz>
Co-authored-by: Alex Goodman <alex.goodman@anchore.com>
2023-05-02 16:43:52 -04:00
dependabot[bot] dd458a2b33 chore(deps): bump github.com/docker/docker (#1767)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 23.0.4+incompatible to 23.0.5+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v23.0.4...v23.0.5)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-02 16:43:16 -04:00
Alex Goodman 5f3d4d285b rename sbom.PackageCatalog to sbom.Packages (#1773)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-05-01 10:19:58 -04:00
dependabot[bot] 10c3cc27e8 chore(deps): bump modernc.org/sqlite from 1.22.0 to 1.22.1 (#1768)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.22.0 to 1.22.1.
- [Release notes](https://gitlab.com/cznic/sqlite/tags)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.22.0...v1.22.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-27 11:58:59 -04:00
Shane Dell a07bfe7dfa Create python requirements metadata (#1759)
- Create new metadata struct and type for python requirements.
- Update parsing of python requirements to use python requirements metadata.
- Remove extras and url from line. Add them to metadata instead.
- Add unit test to test that extras are removed from package name.
- Update test to look at requirements metadata.
- Will need updated in future to support more than just == for the version constraint.
- Update JSON schema data

Closes anchore/grype#1246
Closes anchore/grype#1251

Signed-off-by: Shane Dell <shanedell100@gmail.com>
2023-04-27 09:04:30 -04:00
Keith Zantow 451cb9d5ca chore: update test redactor ordering (#1765)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-04-26 20:42:43 +00:00
Alex Goodman fd02bef0a3 rename pkg.Catalog to pkg.Collection (#1764)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-04-26 13:56:33 -04:00
dependabot[bot] 02bd52728e chore(deps): bump modernc.org/sqlite from 1.21.2 to 1.22.0 (#1758)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.21.2 to 1.22.0.
- [Release notes](https://gitlab.com/cznic/sqlite/tags)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.21.2...v1.22.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-26 10:37:49 -04:00
Christopher Angelo PhillipsandAlex Goodman c038f13d44 chore: go-rpmdb update (#1757)
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
Co-authored-by: Alex Goodman <alex.goodman@anchore.com>
2023-04-24 10:34:13 -04:00
dependabot[bot] 8102ad4edc chore(deps): bump github.com/CycloneDX/cyclonedx-go from 0.7.1-0.20221222100750-41a1ac565cce to 0.7.1 (#1706) 2023-04-24 10:20:12 -04:00
Shane Dell 13485ca5e7 fix: Improve pnpm support (#1752)
Signed-off-by: Shane Dell <shanedell100@gmail.com>
2023-04-21 17:58:23 +00:00
Alex Lehman b2b332e8b2 feat: Add template func hasField (#1754)
Signed-off-by: Lehman, Alex <alex.lehman@gtri.gatech.edu>
2023-04-21 09:34:06 -04:00
Christopher Angelo Phillips a42bac6fcc fix: only cache java packages and not source content (#1750)
* fix: only cache java packages and not source content

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* fix: add gradle to matched files for ci checksum

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-04-19 16:07:34 -04:00
Shane Dell 98a6c6efbe Add sections of interest for Gemfile.lock cataloger (#1749)
- Updated tests to reflect the new sections being added to show they function properly.

Closes #1660

Signed-off-by: Shane Dell <shanedell100@gmail.com>
2023-04-19 12:18:17 -04:00
Christopher Angelo Phillips 55a90a2ee0 fix: update cache.fingerprint file to java-builds dir (#1748)
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-04-19 12:17:07 -04:00
Shane Dell 6e835fd8fc Add ALPM Metadata to CYCLONEDX and SPDX output formats (#1747)
Signed-off-by: Shane Dell <shanedell100@gmail.com>
2023-04-18 11:53:02 -04:00
Weston Steimel ee80349ea0 chore: bump stereoscope to latest version (#1741)
Resolves reporting of GHSA-hw7c-3rfg-p46j

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-04-18 15:44:03 +00:00
anchore-actions-token-generator[bot]andspiffcs 52b54bbad9 chore(deps): update bootstrap tools to latest versions (#1744)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: spiffcs <spiffcs@users.noreply.github.com>
2023-04-18 10:25:02 -04:00
dependabot[bot] 66d9c5637b chore(deps): bump github.com/docker/docker (#1746)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 23.0.3+incompatible to 23.0.4+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v23.0.3...v23.0.4)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-18 10:22:41 -04:00
99 changed files with 2866 additions and 561 deletions
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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 && \
+74 -45
View File
@@ -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
+1 -1
View File
@@ -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
+2
View File
@@ -3,6 +3,8 @@ package main
import (
"log"
_ "modernc.org/sqlite"
"github.com/anchore/syft/cmd/syft/cli"
)
+23 -23
View File
@@ -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 (
+51 -61
View File
@@ -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=
+1 -1
View File
@@ -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
View File
@@ -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
+7
View File
@@ -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)
+1 -1
View File
@@ -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
+12 -8
View File
@@ -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
}
@@ -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",
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 {
+2 -2
View File
@@ -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)
+4 -6
View File
@@ -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,
+103 -23
View File
@@ -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
}
+2 -2
View File
@@ -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"
},
{
+1 -1
View File
@@ -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
@@ -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
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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"
}
}
+2 -2
View File
@@ -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
+4 -4
View File
@@ -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))
}
+2 -2
View File
@@ -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)
}
+1 -1
View File
@@ -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,
+6
View File
@@ -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
}()
+13
View File
@@ -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"
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
}
}
+6 -6
View File
@@ -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())
}
+2 -2
View File
@@ -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()
+58 -60
View File
@@ -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)
+17
View File
@@ -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 != "" {
+100 -1
View File
@@ -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
+13
View File
@@ -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
}
+3
View File
@@ -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
@@ -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
+1 -1
View File
@@ -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,
+9
View File
@@ -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...)
}
+3
View File
@@ -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{}),
+9
View File
@@ -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"`
}
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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))
+1 -1
View File
@@ -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() {
+2 -2
View File
@@ -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
}{
{
+3 -1
View File
@@ -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
View File
@@ -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
+4 -4
View File
@@ -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",
+11 -9
View File
@@ -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 {
+1 -1
View File
@@ -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
}
+2 -2
View File
@@ -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"):
+1 -1
View File
@@ -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
}
+1 -1
View File
@@ -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 -1
View File
@@ -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
+2 -2
View File
@@ -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,