Compare commits

...
142 Commits
Author SHA1 Message Date
Christopher Angelo Phillips dfcc07e512 feat: Add config option to allow user to select the default image source location
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-03-31 10:04:10 -04:00
dependabot[bot] 2fa238af7c chore(deps): bump github.com/docker/docker (#1699)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 23.0.1+incompatible to 23.0.2+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v23.0.1...v23.0.2)

---
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-03-29 10:00:37 -04:00
anchore-actions-token-generator[bot]andspiffcs 63bbd1e3ed chore(deps): update bootstrap tools to latest versions (#1697)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: spiffcs <spiffcs@users.noreply.github.com>
2023-03-27 09:17:34 -04:00
anchore-actions-token-generator[bot]andwagoodman 81b87dd108 chore(deps): update stereoscope to d7551b7f46f53179922d6229709d3d1602881080 (#1693)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: wagoodman <wagoodman@users.noreply.github.com>
2023-03-23 16:30:08 +00:00
Christopher Angelo Phillips f473bb75a8 1577 spdxlicense generate (#1691)
Update the license_list.go to have more permissible inputs for greater SPDXID matching.
EX:
GPL3 gpl3 gpl-3 and GPL-3 can all map to GPL-3.0-only

By moving all strings to lower and removing the "-" we're able to return valid SPDX license ID for a greater diversity of input strings.
---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-03-23 11:48:24 -04:00
dependabot[bot] 539bc2afcb chore(deps): bump github.com/vbatts/go-mtree from 0.5.2 to 0.5.3 (#1692)
Bumps [github.com/vbatts/go-mtree](https://github.com/vbatts/go-mtree) from 0.5.2 to 0.5.3.
- [Release notes](https://github.com/vbatts/go-mtree/releases)
- [Changelog](https://github.com/vbatts/go-mtree/blob/main/releases.md)
- [Commits](https://github.com/vbatts/go-mtree/compare/v0.5.2...v0.5.3)

---
updated-dependencies:
- dependency-name: github.com/vbatts/go-mtree
  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-03-23 11:09:32 -04:00
Avi DeitcherandKeith Zantow 9fd532246a feat: scan local go mod cache for licenses of golang packages (#1645)
Signed-off-by: Avi Deitcher <avi@deitcher.net>
Co-authored-by: Keith Zantow <kzantow@gmail.com>
2023-03-23 10:38:15 -04:00
Keith Zantow 11e926ab2f chore: fix flaky license sorting (#1690)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-03-22 14:41:49 -04:00
dependabot[bot] 168c5aed51 chore(deps): bump github.com/gookit/color from 1.5.2 to 1.5.3 (#1689) 2023-03-22 14:26:58 -04:00
Dan d02c56aa5f fix: shell completion by adding missing usage message required by spf13/cobra (#1688)
Signed-off-by: DanHam <DanHam@users.noreply.github.com>
2023-03-22 13:45:09 -04:00
anchore-actions-token-generator[bot] 829a71cd92 chore(deps): update bootstrap tools to latest versions (#1686) 2023-03-22 09:01:24 -04:00
Keith Zantow 34ace36a9e chore: tweak some workflow text (#1685)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-03-21 11:08:49 -04:00
Alex Goodman 100cf1003d Remove more side effects from application config testing (#1684)
* remove a few side effects from config testing

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* fix xdg config app name prefix

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* account for restoring and protecting xdg state throughout testing

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

---------

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-03-20 20:53:45 +00:00
Aidan DelaneyandChristopher Phillips f11a7b5e9f Deprecate config.yaml as valid config source; Add unit regression for correct config paths (#1640)
Warn user of future deprecation of ./config.yaml for v1.0.0 release

---------

Signed-off-by: Aidan Delaney <adelaney21@bloomberg.net>
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-03-20 15:13:35 -04:00
anchore-actions-token-generator[bot] 434aa7fd46 chore: Update syft bootstrap tools to latest versions. (#1682)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-03-20 13:20:48 -04:00
Marc-Etienne Vargenau 5fb0423b72 Update documentation: (#1680)
- Syft is now outputing SPDX 2.3 by default
- Give syntax to get SPDX 2.2

Signed-off-by: Marc-Etienne Vargenau <marc-etienne.vargenau@nokia.com>
2023-03-20 10:10:35 -04:00
anchore-actions-token-generator[bot] 7998520848 chore: Update Stereoscope to 7928713c391e20abaede6a029f4ce37b628a4c8b (#1681) 2023-03-18 10:32:39 -04:00
Keith Zantow d05000ff21 fix: reduce logging for bad dpkg lines (#1675)
* fix: reduce logging for bad dpkg lines to Trace level
---------

Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-03-17 13:08:51 -04:00
witchcraze f66e77e2c6 fix ruby classifier (#1678)
Signed-off-by: witchcraze <witchcraze@gmail.com>
2023-03-17 09:42:20 -04:00
Christopher Angelo Phillips 928c4a55ff feat: add shared dir for easier cleanup (#1676)
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-03-16 16:05:34 -04:00
dependabot[bot] 1899eb50d0 chore(deps): bump github.com/google/go-containerregistry (#1672)
Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.13.0 to 0.14.0.
- [Release notes](https://github.com/google/go-containerregistry/releases)
- [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml)
- [Commits](https://github.com/google/go-containerregistry/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: github.com/google/go-containerregistry
  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-03-16 12:07:47 -04:00
dependabot[bot] b5ec4d4f08 chore(deps): bump actions/setup-go from 3 to 4 (#1671)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 4.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-16 12:02:07 -04:00
Christopher Angelo Phillips 61362c04fa fix: move defer after error to protect panic case (#1670)
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-03-15 15:29:10 -04:00
Joye Lin e3140063d4 feat: add argocd, helm, kustomize and kubectl binary classifiers (#1663)
* add argocd, helm, kustomize and kubectl binary classifiers
* update golang PURL
* address PR faceback about binary/test-fixtures/Makefile
* remove the /v[n] suffix from the PURL in both argocd and helm

---------

Signed-off-by: y12studio <y12studio@gmail.com>
2023-03-15 14:53:22 -04:00
razzle 1d9ef34ec7 defer closing file (#1668)
Signed-off-by: razzle <harry@razzle.cloud>
2023-03-15 14:50:42 -04:00
Keith Zantow 302735097e fix: remove author contributing to javascript CPEs (#1669) 2023-03-14 14:10:24 +00:00
Keith Zantow cc0a376aba fix: more python matching support (#1667) 2023-03-13 13:26:43 -04:00
anchore-actions-token-generator[bot]andspiffcs b379dd9f27 Update syft bootstrap tools to latest versions. (#1666)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: spiffcs <spiffcs@users.noreply.github.com>
2023-03-13 10:40:13 -04:00
witchcraze a81e0c8008 feat: add ruby classifier (#1665)
Signed-off-by: witchcraze <witchcraze@gmail.com>
2023-03-10 08:29:40 -05:00
anchore-actions-token-generator[bot] 41cbbe09b2 Update syft bootstrap tools to latest versions. (#1658) 2023-03-07 12:54:32 -05:00
Keith Zantow 7714bc0521 fix: improved Python binary detection (#1648) 2023-03-07 10:52:29 -05:00
Weston Steimel 096d2b7bff fix: suppress some known incorrect vendor candidates for npm CPEs (#1659)
Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-03-07 10:18:44 -05:00
Keith Zantow 7cfdffab5f fix: sanitize SPDX LicenseRefs (#1657)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-03-06 10:55:23 -05:00
dependabot[bot] f43953d225 chore(deps): bump golang.org/x/mod from 0.8.0 to 0.9.0 (#1655) 2023-03-06 15:49:34 +00:00
dependabot[bot] eea1b48cbb chore(deps): bump golang.org/x/net from 0.7.0 to 0.8.0 (#1653) 2023-03-06 15:38:34 +00:00
dependabot[bot] a063cf300b chore(deps): bump github.com/spf13/afero from 1.9.4 to 1.9.5 (#1654) 2023-03-06 15:21:35 +00:00
dependabot[bot] b73903519c chore(deps): bump golang.org/x/term from 0.5.0 to 0.6.0 (#1656) 2023-03-06 15:20:43 +00:00
Keith Zantow 304be4a5a1 fix: dotnet PURL types are invalid (#1649)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-03-03 16:45:20 -05:00
Weston Steimel c4cbe211a3 feat: disable cpe vendor wildcards to reduce false positives (#1647)
* improved parsing of vendor from github url

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* stop generating wildcard vendors

Add logic for parsing javascript and ruby package vendor candidates from
url and author fields and stop generating wildcard vendor candidates

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

---------

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-03-03 17:26:46 +00:00
Avi Deitcher 01230aa766 read relative etc/apk/repositories for alpine version when no OS provided (#1615)
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2023-03-02 13:04:56 -05:00
Keith Zantow 5f90d03718 fix: possible race condition (#1639) 2023-03-01 15:35:01 -05:00
Weston Steimel e2ebc9769f fix: remove APK OriginPackage cpe candidates (#1637)
Adding APK OriginPackage CPE candidates to the child package
results in false positives in grype because it can't associate
CPE-based findings to the corresponding OriginPackage APK fixes.

This reverts changing the `upstream` in the PURL for APK packages
as the logic in Grype that uses it expects it to be an APK package
name.  This also allows refactoring to unexport and move the APK
CPE candidate generation logic closer to where CPE generation occurs

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-03-01 17:24:43 +00:00
Keith Zantow 2e6e3b0c74 fix: rebar lock file decoding panic (#1628) 2023-03-01 10:08:29 -05:00
Keith Zantow 24584a4d27 fix: handle individual cataloger panics (#1636) 2023-03-01 10:03:34 -05:00
Weston Steimel 8e1205f7ab fix: apk product/vendor generation for old metadata (#1635)
This fixes some instances where the improved APK CPE generation
logic caused regressions for older alpine package APK metadata.
It now generates multiple "upstream" candidates with both name
and package type which reduces the amount of duplicated code in
the apk cpe gen logic.  This also improves the handling of stream
version packages, so now we can correctly identify packages such
as ruby3.2-rexml as the rexml ruby gem.

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-03-01 14:58:35 +00:00
Weston Steimel e92b0fa629 feat: rust toolchain binary cataloger (#1601)
Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-03-01 14:53:37 +00:00
Weston Steimel bcc0751a40 feat: retain go package info when no module declared (#1632)
Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-03-01 14:26:44 +00:00
Weston Steimel f1169e56fc fix: improved CPE-generation for several more APK packages (#1631)
* fix: correct vendor for musl

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: correct vendor for firefox and thunderbird

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: correct vendor/product for chromium

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: correct product for apache http server

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: correct product for tiff

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: correct vendor for ghostscript

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: correct vendor for openjpeg

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: correct vendor/product for xorg-server

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: correct vendor for podofo

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: correct vendor for wpa_supplicant

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

---------

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-03-01 08:55:40 -05:00
Christopher Angelo Phillips 98e737fc27 chore: update deprecated release flag (#1629)
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-02-27 15:57:56 -05:00
dependabot[bot] ff34594284 chore(deps): bump actions/upload-artifact from 2 to 3 (#1627)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-27 14:17:29 -05:00
Benji Visser 9e953b1da3 feat: add support for SUPPORT_END in /etc/os-release (#1612)
Signed-off-by: Benji Visser <benji@093b.org>
2023-02-27 13:43:19 -05:00
Weston Steimel fbda21f4f4 fix: further improvements to CPE generation for apk packages (#1623)
* fix: consider upstream logic during apk cpe gen
* fix: correct apk CPE for go
* fix: correct apk CPE for ruby
* fix: correct apk CPE for bazel
* fix: correct apk CPE for clang
* fix: correct apk CPE for openjdk
* fix: correct apk CPE for glibc
* fix: correct apk CPE for gli
* fix: correct apk CPE for bas
* fix: correct apk CPE for alsa-lib
* fix: correct apk CPE for alsa
* fix: determine apk cpe vendor from known URLs
* fix: add more url prefix->vendor mappings for apk
* refactor: allow reuse of vendor by url prefix logic
* feat: extract username as vendor candidate from github/gitlab

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-02-27 13:16:04 -05:00
dependabot[bot] d23b4d4cbd chore(deps): bump github.com/stretchr/testify from 1.8.1 to 1.8.2 (#1625)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.1 to 1.8.2.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.1...v1.8.2)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  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-02-27 13:14:20 -05:00
dependabot[bot] f3acff81f3 chore(deps): bump actions/checkout from 2 to 3 (#1626)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-27 13:14:03 -05:00
Nils Hanke fa0a9fe8f9 feat: set cosign attest predicate type based on Syft output type (#1598)
Signed-off-by: Nils Hanke <nils.hanke@outlook.de>
2023-02-24 15:08:40 -05:00
dependabot[bot] 284bae9d5f chore(deps): bump github.com/spf13/afero from 1.9.3 to 1.9.4 (#1609)
Bumps [github.com/spf13/afero](https://github.com/spf13/afero) from 1.9.3 to 1.9.4.
- [Release notes](https://github.com/spf13/afero/releases)
- [Commits](https://github.com/spf13/afero/compare/v1.9.3...v1.9.4)

---
updated-dependencies:
- dependency-name: github.com/spf13/afero
  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-02-24 15:07:52 -05:00
Weston Steimel 3ee1af0dc6 fix: correct apk purls for other distros (#1620)
The apk purl spec allows for vendor-specific namespace.  I noticed
in the embedded SBOMs from wolfi that the purls are of the form
`pkg:apk/wolfi/curl@7.83.0-r0?arch=x86`, but the current logic in
syft actually prevents purl generation entirely if the distro isn't
alpine, so this corrects that behaviour.

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-02-24 15:07:07 -05:00
Weston Steimel 0c5f03235e refactor: move apk upstream logic to apk metadata (#1619)
* refactor: move apk upstream logic to apk metadata

Export the logic for parsing upstream APK package names
so it can be accessed from apk metadata objects directly.

This also tightens the upstream regex pattern as several
edge cases were being missed.

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: ensure correct handling for apk packages beginning with digits

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: upstream generation for ruby

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

---------

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-02-24 15:59:19 +00:00
Keith Zantow 5e8aa4da5e fix: decoding null apk metadata pullDependencies (#1614)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-02-23 19:55:49 +00:00
Benji Visser abfec62219 feat: haproxy binary matcher (#1591)
Signed-off-by: Benji Visser <benji@093b.org>
2023-02-23 14:39:08 -05:00
Weston Steimel 0c05855131 fix: determine upstream for apk version streams (#1610)
Determines better upstream package name for version-stream apk packages:

Examples:

- postgresql-13 -> postgresql
- postgresql15 -> postgresql
- go-1.19 -> go
- perl100.55 -> perl

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-02-23 17:32:34 +00:00
Weston Steimel 1150772d06 fix: improve CPE generation for curl APK (#1608)
Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-02-23 17:32:12 +00:00
Alex Goodman 669fee84d5 Revert "add workaround for macos github actions cache issue (#1584)" (#1605)
This reverts commit 0076b19893.

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-02-22 15:03:12 -05:00
anchore-actions-token-generator[bot]andwagoodman aa151da5fe Update Stereoscope to fab1c9638abc2c21cd53dca1f205f37d71148ee0 (#1604)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: wagoodman <wagoodman@users.noreply.github.com>
2023-02-22 19:08:35 +00:00
Keith Zantow 4bf677d555 chore: fix cataloger_test (#1603)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-02-22 17:30:41 +00:00
Keith Zantow f5e20521e0 fix: merging of binary packages (#1583) 2023-02-22 12:03:15 -05:00
Keith Zantow 8f6a317fef fix: issue when matching format versions (#1585)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-02-22 10:32:05 -05:00
anchore-actions-token-generator[bot] d339ffdcb5 chore: update syft bootstrap tools to latest versions. (#1593) 2023-02-22 10:16:14 -05:00
Benji Visser e84ffc6003 feat: add perl binary classifier (#1592)
Signed-off-by: Benji Visser <benji@093b.org>
2023-02-22 09:58:05 -05:00
anchore-actions-token-generator[bot] bb52a25c8a Update Stereoscope to 529924d6d5aa6c708cceffc651883b6e1e27f5df (#1602)
Signed-off-by: GitHub <noreply@github.com>
2023-02-22 08:49:04 +00:00
Marc-Etienne Vargenau 4b7b709473 Update SPDX license list to 3.20 (#1600)
Signed-off-by: Marc-Etienne Vargenau <marc-etienne.vargenau@nokia.com>
2023-02-21 15:12:28 -05:00
Keith Zantow 2ef2eed382 chore: update SPDX license list (#1599) 2023-02-21 17:31:24 +00:00
Alex Goodman f6716092af fix cataloger selection to be more specific (#1582)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-02-17 15:35:54 +00:00
Alex Goodman 0076b19893 add workaround for macos github actions cache issue (#1584)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-02-17 10:29:33 -05:00
anchore-actions-token-generator[bot]andwestonsteimel 2642a36161 Update Stereoscope to 4b5ebf8c7f4b81ca79c4c3f0af1d0723eab87d42 (#1576)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: westonsteimel <westonsteimel@users.noreply.github.com>
2023-02-16 10:22:43 -05:00
dependabot[bot] 1981b249f1 chore(deps): bump golang.org/x/net from 0.6.0 to 0.7.0 (#1574)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  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-02-15 12:54:55 -05:00
Keith Zantow a3ebb31e3c chore: update bug issue template (#1571)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-02-14 12:58:44 -05:00
Alex Goodman 9b9a7d6c98 allow convert to take stdin (#1570)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-02-14 10:03:47 -05:00
Weston Steimel 57a13ae355 fix: improve CPE and upstream generation logic for Alpine packages (#1567)
* fix: improved CPE-generation logic for alpine packages

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: improved alpine upstream name generation

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: improve CPE vendor for alpine

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: python vendor CPE gen

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: alpine cpe gen logic

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: apk CPE update for nodejs-current

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: CPE update for python pip

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix: CPE update for some ruby packages

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* fix linting

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

---------

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-02-13 17:23:13 +00:00
Keith Zantow 890fb3f0e8 fix: missing APK node vulnerabilities (#1565)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2023-02-10 15:52:13 -05:00
Weston Steimel e236054668 fix: python CPE generation for alpine (#1564)
Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-02-10 18:04:16 +00:00
dependabot[bot] 3013c8b691 chore(deps): bump github.com/docker/docker (#1563)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 23.0.0+incompatible to 23.0.1+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v23.0.0...v23.0.1)

---
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-02-10 10:43:19 -05:00
Alex Goodman 88c81d33ed switch from trigger-release target to release target (#1560)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-02-09 16:35:11 +00:00
Alex Goodman 988041ba6d Speed up cataloging by replacing globs searching with index lookups (#1510)
* replace raw globs with index equivelent operations

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add cataloger test for alpm cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* fix import sorting for binary cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* fix linting for mock resolver

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* separate portage cataloger parser impl from cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* enhance cataloger pkgtest utils to account for resolver responses

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for alpm cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for apkdb cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for dpkg cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for cpp cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for dart cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for dotnet cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for elixir cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for erlang cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for golang cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for haskell cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for java cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for javascript cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for php cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for portage cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for python cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for rpm cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for rust cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for sbom cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for swift cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* allow generic catloger to run all mimetype searches at once

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* remove stutter from php and javascript cataloger constructors

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* bump stereoscope

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add tests for generic.Search

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add exceptions for java archive git ignore entries

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* enhance basename and extension resolver methods to be variadic

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* dont allow * prefix on extension searches

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add glob-based cataloger tests for ruby cataloger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* remove unnecessary string casting

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* incorporate surfacing of leaf link resolitions from stereoscope results

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* [wip] switch to stereoscope file metadata

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* [wip + failing] revert to old globs but keep new resolvers

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* index files, links, and dirs within the directory resolver

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* fix several resolver bugs and inconsistencies

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* move format testutils to internal package

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* update syft json to account for file type string normalization

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* split up directory resolver from indexing

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* update docs to include details about searching

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* [wip] bump stereoscope to development version

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* fix linting

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* adjust symlinks fixture to be fixed to digest

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* fix all-locations resolver tests

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* fix test fixture reference

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* rename file.Type

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* bump stereoscope

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* fix PR comment to exclude extra *

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* bump to dev version of stereoscope

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* bump to final version of stereoscope

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* move observing resolver to pkgtest

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

---------

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-02-09 16:19:47 +00:00
anchore-actions-token-generator[bot] 550e2fc7c3 Update syft bootstrap tools to latest versions. (#1549) 2023-02-09 10:10:35 -05:00
witchcraze 43b53ac173 Fix installed versions (#1556)
Signed-off-by: witchcraze <witchcraze@gmail.com>
2023-02-09 09:03:40 -05:00
dependabot[bot] 08804842fa chore(deps): bump golang.org/x/net from 0.5.0 to 0.6.0 (#1558)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  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-02-09 09:01:56 -05:00
witchcrazeandAlex Goodman 284814153d feat: add postgresql classifier (#1536)
* add postgresql classifier
Signed-off-by: witchcraze <witchcraze@gmail.com>

* revert package dedup test upgrade

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

---------

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
Co-authored-by: Alex Goodman <alex.goodman@anchore.com>
2023-02-08 14:31:17 -05:00
Alex Goodman 8847ba5d0b Add release trigger (#1501)
* add release trigger

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* deduplicate version and changelog calls + add gh checks

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add more chronicle verbosity, but not when triggering releases

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* bump chronicle version to get --version-file feature

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* update bootstrap tool workflow to include glow

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* add version prefix check on tags in release quality gate

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

---------

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-02-08 11:38:27 -05:00
dependabot[bot] 48528efff3 chore(deps): bump golang.org/x/mod from 0.7.0 to 0.8.0 (#1552)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.7.0 to 0.8.0.
- [Release notes](https://github.com/golang/mod/releases)
- [Commits](https://github.com/golang/mod/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  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-02-08 10:07:37 -05:00
dependabot[bot] 8d856a7c7b chore(deps): bump golang.org/x/term from 0.4.0 to 0.5.0 (#1551)
Bumps [golang.org/x/term](https://github.com/golang/term) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/golang/term/releases)
- [Commits](https://github.com/golang/term/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/term
  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-02-08 09:23:31 -05:00
Avi Deitcher 38a090c218 fix: add support for licenses not found on list (#1540)
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2023-02-07 11:47:04 -05:00
deb7052f41 Update syft bootstrap tools to latest versions. (#1541)
* Update syft bootstrap tools to latest versions.
Signed-off-by: GitHub <noreply@github.com>

* fix: remove ineff assign
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

---------

Signed-off-by: GitHub <noreply@github.com>
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Co-authored-by: spiffcs <spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-02-07 15:41:14 +00:00
Keith Zantow 9650473298 feat: Allow specific versions of formats to be specified (#1543) 2023-02-07 10:40:43 -05:00
anchore-actions-token-generator[bot]andkzantow 95201840d2 Update Stereoscope to c49244e4d66f1ee789027ea23acc746968799c3b (#1539)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: kzantow <kzantow@users.noreply.github.com>
2023-02-07 10:05:18 -05:00
Justin Chadwell 6ba595344a source: when base is set, responsePath should be absolute (#1542)
When base is set, it should appear identically to when we scan the root
filesystem - and as a result, the path should begin with the path
separator.

E.g. when scanning the root `./target/` with the same base,
`target/bin/busybox` should appear in the output as `/bin/busybox`, not
as previously as `bin/busybox`.

Signed-off-by: Justin Chadwell <me@jedevc.com>
2023-02-06 12:06:04 -05:00
Christopher Angelo Phillips 9995950c70 fix: update config struct to not decode password/key (#1538)
* fix: update config struct to not decode password/key
* test: update tests to confirm no secrets in output

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

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-02-03 18:06:14 +00:00
anchore-actions-token-generator[bot]andspiffcs b6a496f18c Update syft bootstrap tools to latest versions. (#1537)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: spiffcs <spiffcs@users.noreply.github.com>
2023-02-03 12:35:33 -05:00
witchcraze 0853a50f4d feat: add traefik classifier (#1504)
Signed-off-by: witchcraze <witchcraze@gmail.com>
2023-02-02 13:59:26 -05:00
Nils Hanke a1b82c9664 fix: don't hardcode Cosign attest type (#1533)
Signed-off-by: Nils Hanke <nils.hanke@outlook.de>
2023-02-02 12:47:12 -05:00
dependabot[bot] ad8604c223 chore(deps): bump github.com/docker/docker (#1531)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.23+incompatible to 23.0.0+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v20.10.23...v23.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-02 10:53:22 -05:00
anchore-actions-token-generator[bot] d80ee966dc Update syft bootstrap tools to latest versions. (#1530) 2023-02-02 08:47:29 -05:00
Keith Zantow 1530ef354f chore: update spdx/tools-golang to v0.5.0-rc1 (#1503) 2023-01-31 11:53:16 -05:00
Bradley Jones cdac2245b5 feat: update golang to 1.19 (#1526)
* feat: update golang to 1.19

Signed-off-by: Bradley Jones <bradley.jones@anchore.com>

* chore: break out json schema drift check into separate script

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* chore: update git index refresh

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

---------

Signed-off-by: Bradley Jones <bradley.jones@anchore.com>
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-01-31 11:39:57 -05:00
anchore-actions-token-generator[bot] 8dba4c33dd Update syft bootstrap tools to latest versions. (#1525) 2023-01-31 09:27:38 -05:00
Justin Chadwell b81c9805dc Allow scanning unpacked container filesystems (#1485)
* source: avoid second-step of symlink resolution in directory resolver

We can use the already existing file tree to peform symlink resolution
for FilesByPath, instead of traversing the symlinks again.

This moves all of the symlink logic into the indexing code, and then we
can rely on syft's resolution algorithm over the index in this part of
the codebase.

Signed-off-by: Justin Chadwell <me@jedevc.com>

* source: add base parameter to directory resolver

The new base parameter is an optional parameter for the directory
resolver that resolves all symlinks relative to this root. There are two
intended use cases:

- base = "/". The previous behavior, symlinks are resolved relative to
the root filesystem.
- base = path. Symlinks are resolved relative to the target filesystem,
allowing correct behavior when scanning unpacked container filesystems
on disk.

Signed-off-by: Justin Chadwell <me@jedevc.com>

* source: add tests for new base parameter

Signed-off-by: Justin Chadwell <me@jedevc.com>

---------

Signed-off-by: Justin Chadwell <me@jedevc.com>
2023-01-30 13:47:24 -05:00
Keith Zantow ba55963104 fix: allow template for syft convert (#1521) 2023-01-26 12:07:36 -05:00
Christopher Angelo Phillips 8c91605541 1465 attestation with private key (#1502)
1465 attestation with private key (#1502)

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-01-26 11:19:13 -05:00
Weston Steimel 4c0aef09b8 fix: add relevant CPEs to python and busybox classifiers (#1517)
Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
2023-01-25 17:18:24 +00:00
anchore-actions-token-generator[bot] 02fb757c21 Update syft bootstrap tools to latest versions. (#1515) 2023-01-25 10:31:53 -05:00
Keith Zantow 674a54512c chore: correct bootstrap tool script (#1514) 2023-01-25 10:22:28 -05:00
dependabot[bot] 21ba5d0806 chore(deps): bump github.com/google/go-containerregistry (#1513)
Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.12.1 to 0.13.0.
- [Release notes](https://github.com/google/go-containerregistry/releases)
- [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml)
- [Commits](https://github.com/google/go-containerregistry/compare/v0.12.1...v0.13.0)

---
updated-dependencies:
- dependency-name: github.com/google/go-containerregistry
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-25 13:41:43 +00:00
Alex GoodmanandKeith Zantow 0ba57a5936 Fix AssertEncoderAgainstGoldenSnapshot calls to conditionally update (#1511)
* fix AssertEncoderAgainstGoldenSnapshot calls to conditionally update

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* chore: redact schema versions from syftjson comparison

Signed-off-by: Keith Zantow <kzantow@gmail.com>

* chore: does not need a multiline expression

Signed-off-by: Keith Zantow <kzantow@gmail.com>

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
Signed-off-by: Keith Zantow <kzantow@gmail.com>
Co-authored-by: Keith Zantow <kzantow@gmail.com>
2023-01-24 21:41:57 +00:00
dependabot[bot] 3269bc98d4 chore(deps): bump golang.org/x/mod from 0.6.0 to 0.7.0 (#1505)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/mod/releases)
- [Commits](https://github.com/golang/mod/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 15:01:25 -05:00
dependabot[bot] 7f3382f7eb chore(deps): bump github.com/docker/docker (#1506)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.20+incompatible to 20.10.23+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v20.10.20...v20.10.23)

---
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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 14:58:39 -05:00
dependabot[bot] 65e5ff63f0 chore(deps): bump github.com/Masterminds/sprig/v3 from 3.2.2 to 3.2.3 (#1507)
Bumps [github.com/Masterminds/sprig/v3](https://github.com/Masterminds/sprig) from 3.2.2 to 3.2.3.
- [Release notes](https://github.com/Masterminds/sprig/releases)
- [Changelog](https://github.com/Masterminds/sprig/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Masterminds/sprig/compare/v3.2.2...v3.2.3)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 14:48:22 -05:00
dependabot[bot] d287c22b69 chore(deps): bump github.com/dustin/go-humanize from 1.0.0 to 1.0.1 (#1508)
Bumps [github.com/dustin/go-humanize](https://github.com/dustin/go-humanize) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/dustin/go-humanize/releases)
- [Commits](https://github.com/dustin/go-humanize/compare/v1.0.0...v1.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 14:48:00 -05:00
Luca Comellini e8be93a8eb Bump github.com/spdx/tools-golang to v0.4.0 (#1450)
Signed-off-by: Luca Comellini <luca.com@gmail.com>
2023-01-20 17:00:21 -05:00
Dan LuhringandAlex Goodman e58050bac0 Fix panic in apkdb parsing on empty "provides" values (#1494)
* Add failing test for strip version specifiers panic

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

* Fix test

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

* Prevent panic scenario in helper func

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

* Fix lint issue

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>

* add tests for apk stripVersionSpecifier() and remove caller empty value check

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
Co-authored-by: Alex Goodman <alex.goodman@anchore.com>
2023-01-20 14:49:44 +00:00
Alex Goodman 36a0945c95 push detailed log statements to trace-level (#1500)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-01-20 14:33:23 +00:00
mikcl 396441e921 npm: package-lock license decoding to accept string or array (#1482)
Signed-off-by: mikcl <mikesmikes400@gmail.com>
2023-01-20 09:28:51 -05:00
Alex Goodman 972e4cdaeb always set the package ID for java packages (#1493)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2023-01-20 09:18:00 -05:00
Nils Hanke 99f55f6a81 fix: skip filling in empty fields in APK metadata (#1484)
Signed-off-by: Nils Hanke <nils.hanke@outlook.de>

Signed-off-by: Nils Hanke <nils.hanke@outlook.de>
2023-01-20 14:03:30 +00:00
dependabot[bot] 285112fe29 chore(deps): bump github.com/facebookincubator/nvdtools (#1499)
Bumps [github.com/facebookincubator/nvdtools](https://github.com/facebookincubator/nvdtools) from 0.1.4 to 0.1.5.
- [Release notes](https://github.com/facebookincubator/nvdtools/releases)
- [Commits](https://github.com/facebookincubator/nvdtools/compare/v0.1.4...v0.1.5)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-20 14:02:47 +00:00
dependabot[bot] f29bea5921 chore(deps): bump github.com/jinzhu/copier from 0.3.2 to 0.3.5 (#1498)
Bumps [github.com/jinzhu/copier](https://github.com/jinzhu/copier) from 0.3.2 to 0.3.5.
- [Release notes](https://github.com/jinzhu/copier/releases)
- [Commits](https://github.com/jinzhu/copier/compare/v0.3.2...v0.3.5)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-20 08:51:20 -05:00
dependabot[bot] 39cdbc42aa chore(deps): bump github.com/vbatts/go-mtree from 0.5.0 to 0.5.2 (#1497)
Bumps [github.com/vbatts/go-mtree](https://github.com/vbatts/go-mtree) from 0.5.0 to 0.5.2.
- [Release notes](https://github.com/vbatts/go-mtree/releases)
- [Changelog](https://github.com/vbatts/go-mtree/blob/main/releases.md)
- [Commits](https://github.com/vbatts/go-mtree/compare/v0.5.0...v0.5.2)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-20 08:50:59 -05:00
dependabot[bot] 27b62ce833 chore(deps): bump github.com/gookit/color from 1.4.2 to 1.5.2 (#1496)
Bumps [github.com/gookit/color](https://github.com/gookit/color) from 1.4.2 to 1.5.2.
- [Release notes](https://github.com/gookit/color/releases)
- [Commits](https://github.com/gookit/color/compare/v1.4.2...v1.5.2)

---
updated-dependencies:
- dependency-name: github.com/gookit/color
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-20 08:50:37 -05:00
dependabot[bot] 499e7c4e16 chore(deps): bump github.com/spf13/viper from 1.14.0 to 1.15.0 (#1495)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-20 08:50:19 -05:00
Alex GoodmanandChristopher Phillips 0f75f975c8 Relax error conditions for catalogers (#1492)
* binary cataloger should continue on errors

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* test: add redirect for cmd stderr stdout

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

* test: image update for test failure

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

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com>
2023-01-19 19:28:42 -05:00
witchcraze 7427445fe9 feat: add memcached classifier (#1486)
Signed-off-by: witchcraze <witchcraze@gmail.com>
2023-01-19 11:22:11 -05:00
dependabot[bot] 09a5baf523 chore(deps): bump github.com/spf13/viper from 1.13.0 to 1.14.0 (#1488)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.13.0 to 1.14.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.13.0...v1.14.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-19 10:39:04 -05:00
dependabot[bot] 33c08c8545 chore(deps): bump github.com/bmatcuk/doublestar/v4 from 4.0.2 to 4.6.0 (#1489)
Bumps [github.com/bmatcuk/doublestar/v4](https://github.com/bmatcuk/doublestar) from 4.0.2 to 4.6.0.
- [Release notes](https://github.com/bmatcuk/doublestar/releases)
- [Commits](https://github.com/bmatcuk/doublestar/compare/v4.0.2...v4.6.0)

---
updated-dependencies:
- dependency-name: github.com/bmatcuk/doublestar/v4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-19 10:38:50 -05:00
dependabot[bot] fd002db802 chore(deps): bump github.com/spf13/cobra from 1.6.0 to 1.6.1 (#1490)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.6.0 to 1.6.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.6.0...v1.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-19 14:16:50 +00:00
dependabot[bot] cb3e4b8e49 chore(deps): bump github.com/go-test/deep from 1.0.8 to 1.1.0 (#1491)
Bumps [github.com/go-test/deep](https://github.com/go-test/deep) from 1.0.8 to 1.1.0.
- [Release notes](https://github.com/go-test/deep/releases)
- [Changelog](https://github.com/go-test/deep/blob/master/CHANGES.md)
- [Commits](https://github.com/go-test/deep/compare/v1.0.8...v1.1.0)

---
updated-dependencies:
- dependency-name: github.com/go-test/deep
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-19 14:01:33 +00:00
dependabot[bot] 5917f8d8f9 chore(deps): bump github.com/google/go-containerregistry (#1487)
Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.11.0 to 0.12.1.
- [Release notes](https://github.com/google/go-containerregistry/releases)
- [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml)
- [Commits](https://github.com/google/go-containerregistry/compare/v0.11.0...v0.12.1)

---
updated-dependencies:
- dependency-name: github.com/google/go-containerregistry
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-19 13:47:36 +00:00
dependabot[bot] 70e6d0f2e3 chore(deps): bump golang.org/x/net from 0.4.0 to 0.5.0 (#1475)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-18 14:39:50 +00:00
dependabot[bot] 31a763c46d chore(deps): bump github.com/adrg/xdg from 0.3.3 to 0.4.0 (#1477)
Bumps [github.com/adrg/xdg](https://github.com/adrg/xdg) from 0.3.3 to 0.4.0.
- [Release notes](https://github.com/adrg/xdg/releases)
- [Commits](https://github.com/adrg/xdg/compare/v0.3.3...v0.4.0)

---
updated-dependencies:
- dependency-name: github.com/adrg/xdg
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-18 09:39:35 -05:00
dependabot[bot] ae6c9c2e97 chore(deps): bump github.com/sergi/go-diff from 1.2.0 to 1.3.1 (#1476)
Bumps [github.com/sergi/go-diff](https://github.com/sergi/go-diff) from 1.2.0 to 1.3.1.
- [Release notes](https://github.com/sergi/go-diff/releases)
- [Commits](https://github.com/sergi/go-diff/compare/v1.2.0...v1.3.1)

---
updated-dependencies:
- dependency-name: github.com/sergi/go-diff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-18 09:39:15 -05:00
dependabot[bot] f6a0dd33d1 chore(deps): bump github.com/vifraa/gopom from 0.1.0 to 0.2.1 (#1474)
Bumps [github.com/vifraa/gopom](https://github.com/vifraa/gopom) from 0.1.0 to 0.2.1.
- [Release notes](https://github.com/vifraa/gopom/releases)
- [Commits](https://github.com/vifraa/gopom/compare/v0.1.0...v0.2.1)

---
updated-dependencies:
- dependency-name: github.com/vifraa/gopom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-18 09:38:30 -05:00
dependabot[bot] b77c104aa6 chore(deps): bump github/codeql-action from 1 to 2 (#1473)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-18 09:38:06 -05:00
dependabot[bot] 10ca7f56ab chore(deps): bump actions/setup-go from 2 to 3 (#1472)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2 to 3.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-18 09:37:45 -05:00
Luca Comellini 6b2dc08ffb Add dependabot (#1451)
Signed-off-by: Luca Comellini <luca.com@gmail.com>

Signed-off-by: Luca Comellini <luca.com@gmail.com>
2023-01-18 09:29:24 -05:00
408 changed files with 253197 additions and 11462 deletions
+2 -2
View File
@@ -7,12 +7,12 @@ assignees: ''
---
**Please provide a set of steps on how to reproduce the issue**
**What happened**:
**What you expected to happen**:
**Steps to reproduce the issue**:
**Anything else we need to know?**:
**Environment**:
+1 -1
View File
@@ -4,7 +4,7 @@ inputs:
go-version:
description: "Go version to install"
required: true
default: "1.18.x"
default: "1.19.x"
use-go-cache:
description: "Restore go cache"
required: true
+10
View File
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: daily
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: daily
+1 -1
View File
@@ -6,6 +6,6 @@ normal=$(tput sgr0)
# assert we are running in CI (or die!)
if [[ -z "$CI" ]]; then
echo "${bold}${red}This script should ONLY be run in CI. Exiting...${normal}"
echo "${bold}${red}This step should ONLY be run in CI. Exiting...${normal}"
exit 1
fi
+1 -1
View File
@@ -4,7 +4,7 @@ set -eu
ORIGINAL_STATE_DIR=$(mktemp -d "TEMP-original-state-XXXXXXXXX")
TIDY_STATE_DIR=$(mktemp -d "TEMP-tidy-state-XXXXXXXXX")
trap "cp ${ORIGINAL_STATE_DIR}/* ./ && rm -fR ${ORIGINAL_STATE_DIR} ${TIDY_STATE_DIR}" EXIT
trap "cp -p ${ORIGINAL_STATE_DIR}/* ./ && git update-index -q --refresh && rm -fR ${ORIGINAL_STATE_DIR} ${TIDY_STATE_DIR}" EXIT
# capturing original state of files...
cp go.mod go.sum "${ORIGINAL_STATE_DIR}"
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -u
if ! git diff-index --quiet HEAD --; then
git diff-index HEAD --
git --no-pager diff
echo "there are uncommitted changes, please commit them before running this check"
exit 1
fi
success=true
if ! make generate-json-schema; then
echo "Generating json schema failed"
success=false
fi
if ! git diff-index --quiet HEAD --; then
git diff-index HEAD --
git --no-pager diff
echo "JSON schema drift detected!"
success=false
fi
if ! $success; then
exit 1
fi
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
set -eu
bold=$(tput bold)
normal=$(tput sgr0)
if ! [ -x "$(command -v gh)" ]; then
echo "The GitHub CLI could not be found. To continue follow the instructions at https://github.com/cli/cli#installation"
exit 1
fi
gh auth status
# we need all of the git state to determine the next version. Since tagging is done by
# the release pipeline it is possible to not have all of the tags from previous releases.
git fetch --tags
# populates the CHANGELOG.md and VERSION files
echo "${bold}Generating changelog...${normal}"
make changelog 2> /dev/null
NEXT_VERSION=$(cat VERSION)
if [[ "$NEXT_VERSION" == "" || "${NEXT_VERSION}" == "(Unreleased)" ]]; then
echo "Could not determine the next version to release. Exiting..."
exit 1
fi
while true; do
read -p "${bold}Do you want to trigger a release for version '${NEXT_VERSION}'?${normal} [y/n] " yn
case $yn in
[Yy]* ) echo; break;;
[Nn]* ) echo; echo "Cancelling release..."; exit;;
* ) echo "Please answer yes or no.";;
esac
done
echo "${bold}Kicking off release for ${NEXT_VERSION}${normal}..."
echo
gh workflow run release.yaml -f version=${NEXT_VERSION}
echo
echo "${bold}Waiting for release to start...${normal}"
sleep 10
set +e
echo "${bold}Head to the release workflow to monitor the release:${normal} $(gh run list --workflow=release.yaml --limit=1 --json url --jq '.[].url')"
id=$(gh run list --workflow=release.yaml --limit=1 --json databaseId --jq '.[].databaseId')
gh run watch $id --exit-status || (echo ; echo "${bold}Logs of failed step:${normal}" && GH_PAGER="" gh run view $id --log-failed)
+4 -4
View File
@@ -30,11 +30,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -45,7 +45,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -59,4 +59,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
+20 -16
View File
@@ -1,15 +1,13 @@
name: "Release"
on:
push:
# take no actions on push to any branch...
branches-ignore:
- "**"
# ... only act on release tags
tags:
- "v*"
workflow_dispatch:
inputs:
version:
description: tag the latest commit on main with the given version (prefixed with v)
required: true
env:
GO_VERSION: "1.18.x"
GO_VERSION: "1.19.x"
jobs:
quality-gate:
@@ -18,12 +16,11 @@ jobs:
steps:
- uses: actions/checkout@v3
# we don't want to release commits that have been pushed and tagged, but not necessarily merged onto main
- name: Ensure tagged commit is on main
- name: Check if tag already exists
# note: this will fail if the tag already exists
run: |
echo "Tag: ${GITHUB_REF##*/}"
git fetch origin main
git merge-base --is-ancestor ${GITHUB_REF##*/} origin/main && echo "${GITHUB_REF##*/} is a commit on main!"
[[ "${{ github.event.inputs.version }}" == v* ]] || (echo "version '${{ github.event.inputs.version }}' does not have a 'v' prefix" && exit 1)
git tag ${{ github.event.inputs.version }}
- name: Check static analysis results
uses: fountainhead/action-wait-for-check@v1.1.0
@@ -120,8 +117,15 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Tag release
run: |
git tag ${{ github.event.inputs.version }}
git push origin --tags
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build & publish release artifacts
run: make release
run: make ci-release
env:
# for mac signing and notarization...
QUILL_SIGN_P12: ${{ secrets.ANCHORE_APPLE_DEVELOPER_ID_CERT_CHAIN }}
@@ -147,12 +151,12 @@ jobs:
with:
status: ${{ job.status }}
fields: repo,workflow,action,eventName
text: "A new Syft release has been published: https://github.com/anchore/syft/releases/tag/${{ github.ref_name }}"
text: "A new Syft release has been published: https://github.com/anchore/syft/releases/tag/${{ github.event.inputs.version }}"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
if: ${{ success() }}
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: artifacts
path: dist/**/*
+22 -18
View File
@@ -6,7 +6,7 @@ on:
workflow_dispatch:
env:
GO_VERSION: "1.18.x"
GO_VERSION: "1.19.x"
GO_STABLE_VERSION: true
jobs:
@@ -16,7 +16,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v2
- uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
stable: ${{ env.GO_STABLE_VERSION }}
@@ -29,24 +29,27 @@ jobs:
GOSIMPORTS_LATEST_VERSION=$(go list -m -json github.com/rinchsan/gosimports@latest 2>/dev/null | jq -r '.Version')
YAJSV_LATEST_VERSION=$(go list -m -json github.com/neilpa/yajsv@latest 2>/dev/null | jq -r '.Version')
COSIGN_LATEST_VERSION=$(go list -m -json github.com/sigstore/cosign@latest 2>/dev/null | jq -r '.Version')
GLOW_LATEST_VERSION=$(go list -m -json github.com/charmbracelet/glow@latest 2>/dev/null | jq -r '.Version')
# update version variables in the Makefile
sed -r -i -e 's/^(GOLANGCILINT_VERSION = ).*/\1'${GOLANGCILINT_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(BOUNCER_VERSION = ).*/\1'${BOUNCER_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(CHRONICLE_VERSION = ).*/\1'${CHRONICLE_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(GORELEASER_VERSION = ).*/\1'${GORELEASER_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(GOSIMPORTS_VERSION = ).*/\1'${GOSIMPORTS_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(YAJSV_VERSION = ).*/\1'${YAJSV_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(COSIGN_VERSION = ).*/\1'${COSIGN_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(GOLANGCILINT_VERSION := ).*/\1'${GOLANGCILINT_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(BOUNCER_VERSION := ).*/\1'${BOUNCER_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(CHRONICLE_VERSION := ).*/\1'${CHRONICLE_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(GORELEASER_VERSION := ).*/\1'${GORELEASER_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(GOSIMPORTS_VERSION := ).*/\1'${GOSIMPORTS_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(YAJSV_VERSION := ).*/\1'${YAJSV_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(COSIGN_VERSION := ).*/\1'${COSIGN_LATEST_VERSION}'/' Makefile
sed -r -i -e 's/^(GLOW_VERSION := ).*/\1'${GLOW_LATEST_VERSION}'/' Makefile
# export the versions for use with create-pull-request
echo "::set-output name=GOLANGCILINT::$GOLANGCILINT_LATEST_VERSION"
echo "::set-output name=BOUNCER::$BOUNCER_LATEST_VERSION"
echo "::set-output name=CHRONICLE::$CHRONICLE_LATEST_VERSION"
echo "::set-output name=GORELEASER::$GORELEASER_LATEST_VERSION"
echo "::set-output name=GOSIMPORTS::$GOSIMPORTS_LATEST_VERSION"
echo "::set-output name=YAJSV::$YAJSV_LATEST_VERSION"
echo "::set-output name=COSIGN::$COSIGN_LATEST_VERSION"
echo "GOLANGCILINT=$GOLANGCILINT_LATEST_VERSION" >> $GITHUB_OUTPUT
echo "BOUNCER=$BOUNCER_LATEST_VERSION" >> $GITHUB_OUTPUT
echo "CHRONICLE=$CHRONICLE_LATEST_VERSION" >> $GITHUB_OUTPUT
echo "GORELEASER=$GORELEASER_LATEST_VERSION" >> $GITHUB_OUTPUT
echo "GOSIMPORTS=$GOSIMPORTS_LATEST_VERSION" >> $GITHUB_OUTPUT
echo "YAJSV=$YAJSV_LATEST_VERSION" >> $GITHUB_OUTPUT
echo "COSIGN=$COSIGN_LATEST_VERSION" >> $GITHUB_OUTPUT
echo "GLOW=GLOW_LATEST_VERSION" >> $GITHUB_OUTPUT
id: latest-versions
- uses: tibdex/github-app-token@v1
@@ -61,8 +64,8 @@ jobs:
delete-branch: true
branch: auto/latest-bootstrap-tools
labels: dependencies
commit-message: 'Update syft bootstrap tools to latest versions.'
title: 'Update syft bootstrap tools to latest versions.'
commit-message: 'chore(deps): update bootstrap tools to latest versions'
title: 'chore(deps): update bootstrap tools to latest versions'
body: |
- [golangci-lint ${{ steps.latest-versions.outputs.GOLANGCILINT }}](https://github.com/golangci/golangci-lint/releases/tag/${{ steps.latest-versions.outputs.GOLANGCILINT }})
- [bouncer ${{ steps.latest-versions.outputs.BOUNCER }}](https://github.com/wagoodman/go-bouncer/releases/tag/${{ steps.latest-versions.outputs.BOUNCER }})
@@ -71,5 +74,6 @@ jobs:
- [gosimports ${{ steps.latest-versions.outputs.GOSIMPORTS }}](https://github.com/rinchsan/gosimports/releases/tag/${{ steps.latest-versions.outputs.GOSIMPORTS }})
- [yajsv ${{ steps.latest-versions.outputs.YAJSV }}](https://github.com/neilpa/yajsv/releases/tag/${{ steps.latest-versions.outputs.YAJSV }})
- [cosign ${{ steps.latest-versions.outputs.COSIGN }}](https://github.com/sigstore/cosign/releases/tag/${{ steps.latest-versions.outputs.COSIGN }})
- [glow ${{ steps.latest-versions.outputs.GLOW }}](https://github.com/charmbracelet/glow/releases/tag/${{ steps.latest-versions.outputs.GLOW }})
This is an auto-generated pull request to update all of the bootstrap tools to the latest versions.
token: ${{ steps.generate-token.outputs.token }}
@@ -6,7 +6,7 @@ on:
workflow_dispatch:
env:
GO_VERSION: "1.18.x"
GO_VERSION: "1.19.x"
GO_STABLE_VERSION: true
jobs:
@@ -16,7 +16,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v2
- uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
stable: ${{ env.GO_STABLE_VERSION }}
@@ -42,10 +42,10 @@ jobs:
with:
signoff: true
delete-branch: true
branch: auto/latest
branch: auto/latest-stereoscope
labels: dependencies
commit-message: "Update Stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }}"
title: "Update Stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }}"
commit-message: "chore(deps): update stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }}"
title: "chore(deps): update stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }}"
body: |
Update Stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }}
token: ${{ steps.generate-token.outputs.token }}
+7
View File
@@ -54,6 +54,13 @@ jobs:
path: syft/pkg/cataloger/golang/test-fixtures/archs/binaries
key: ${{ runner.os }}-unit-go-binaries-cache-${{ hashFiles( 'syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint' ) }}
- name: Restore binary cataloger test-fixture cache
id: unit-binary-cataloger-cache
uses: actions/cache@v3
with:
path: syft/pkg/cataloger/binary/test-fixtures/classifiers/dynamic
key: ${{ runner.os }}-unit-binary-cataloger-cache-${{ hashFiles( 'syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint' ) }}
- name: Run unit tests
run: make unit
+1
View File
@@ -1,4 +1,5 @@
CHANGELOG.md
VERSION
/test/results
/dist
/snapshot
+13 -10
View File
@@ -6,7 +6,6 @@ issues:
# include:
# - EXC0002 # disable excluding of issues about comments from golint
linters:
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
disable-all: true
@@ -14,25 +13,24 @@ linters:
- asciicheck
- bodyclose
- depguard
- dogsled
- dupl
- errcheck
- errorlint
- exportloopref
- forcetypeassert
- funlen
- gocognit
- goconst
- gocritic
- gocyclo
- gofmt
- tparallel
- importas
- goimports
- goprintffuncname
- gosec
- gosimple
- govet
- ineffassign
- misspell
- nolintlint
- nakedret
- revive
- staticcheck
- stylecheck
@@ -41,6 +39,7 @@ linters:
- unparam
- unused
- whitespace
linters-settings:
funlen:
# Checks the number of lines in a function.
@@ -57,7 +56,7 @@ run:
timeout: 10m
# do not enable...
# - dogsled # found to be to niche and ineffective
# - deadcode # The owner seems to have abandoned the linter. Replaced by "unused".
# - goprintffuncname # does not catch all cases and there are exceptions
# - nakedret # does not catch all cases and should not fail a build
# - gochecknoglobals
@@ -73,7 +72,11 @@ run:
# - lll # without a way to specify per-line exception cases, this is not usable
# - maligned # this is an excellent linter, but tricky to optimize and we are not sensitive to memory layout optimizations
# - nestif
# - prealloc # following this rule isn't consistently a good idea, as it sometimes forces unnecessary allocations that result in less idiomatic code
# - scopelint # deprecated
# - nolintlint # as of go1.19 this conflicts with the behavior of gofmt, which is a deal-breaker (lint-fix will still fail when running lint)
# - prealloc # following this rule isn't consistently a good idea, as it sometimes forces unnecessary allocations that result in less idiomatic code
# - rowserrcheck # not in a repo with sql, so this is not useful
# - scopelint # deprecated
# - structcheck # The owner seems to have abandoned the linter. Replaced by "unused".
# - testpackage
# - wsl # this doens't have an auto-fixer yet and is pretty noisy (https://github.com/bombsimon/wsl/issues/90)
# - varcheck # The owner seems to have abandoned the linter. Replaced by "unused".
# - wsl # this doens't have an auto-fixer yet and is pretty noisy (https://github.com/bombsimon/wsl/issues/90)
+2 -2
View File
@@ -1,4 +1,4 @@
# Contributing to Syft
[#](#) Contributing to Syft
If you are looking to contribute to this project and want to open a GitHub pull request ("PR"), there are a few guidelines of what we are looking for in patches. Make sure you go through this document and ensure that your code proposal is aligned.
@@ -10,7 +10,7 @@ Before you can contribute to Syft, you need to configure your development enviro
You will need to install Go. The version on https://go.dev works best, using the system golang doesn't always work the way you might expect.
At the time of writing, Go 1.19 does not work correctly with Syft. Please use Go 1.18 for now.
Refer to the go.mod file in the root of this repo for the recommended version of Go to install.
You will also need Docker. There's no reason the system packages shouldn't work, but we used the official Docker package. You can find instructions for installing Docker in Debian [here](https://docs.docker.com/engine/install/debian/).
+22 -12
View File
@@ -118,45 +118,55 @@ sequenceDiagram
Catalogers are the way in which syft is able to identify and construct packages given some amount of source metadata.
For example, Syft can locate and process `package-lock.json` files when performing filesystem scans.
See: [how to specify file globs](https://github.com/anchore/syft/blob/main/syft/pkg/cataloger/javascript/cataloger.go#L16-L21)
and an implementation of the [package-lock.json parser](https://github.com/anchore/syft/blob/main/syft/pkg/cataloger/javascript/cataloger.go#L16-L21) fora quick review.
See: [how to specify file globs](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/javascript/cataloger.go#L16-L21)
and an implementation of the [package-lock.json parser](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/javascript/cataloger.go#L16-L21) fora quick review.
#### Building a new Cataloger
Catalogers must fulfill the interface [found here](https://github.com/anchore/syft/blob/main/syft/pkg/cataloger.go).
Catalogers must fulfill the interface [found here](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger.go).
This means that when building a new cataloger, the new struct must implement both method signatures of `Catalog` and `Name`.
A top level view of the functions that construct all the catalogers can be found [here](https://github.com/anchore/syft/blob/main/syft/pkg/cataloger/cataloger.go).
A top level view of the functions that construct all the catalogers can be found [here](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/cataloger.go).
When an author has finished writing a new cataloger this is the spot to plug in the new catalog constructor.
For a top level view of how the catalogers are used see [this function](https://github.com/anchore/syft/blob/main/syft/pkg/cataloger/catalog.go#L41-L100) as a reference. It ranges over all catalogers passed as an argument and invokes the `Catalog` method:
For a top level view of how the catalogers are used see [this function](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/catalog.go#L41-L100) as a reference. It ranges over all catalogers passed as an argument and invokes the `Catalog` method:
Each cataloger has its own `Catalog` method, but this does not mean that they are all vastly different.
Take a look at the `apkdb` cataloger for alpine to see how it [constructs a generic.NewCataloger](https://github.com/anchore/syft/blob/main/syft/pkg/cataloger/apkdb/cataloger.go).
Take a look at the `apkdb` cataloger for alpine to see how it [constructs a generic.NewCataloger](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/cataloger.go).
`generic.NewCataloger` is an abstraction syft uses to make writing common components easier. First, it takes the `catalogerName` to identify the cataloger.
On the other side of the call it uses two key pieces which inform the cataloger how to identify and return packages, the `globPatterns` and the `parseFunction`:
- The first piece is a `parseByGlob` matching pattern used to identify the files that contain the package metadata.
See [here for the APK example](https://github.com/anchore/syft/blob/main/syft/pkg/apk_metadata.go#L16-L41).
See [here for the APK example](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/apk_metadata.go#L16-L41).
- The other is a `parseFunction` which informs the cataloger what to do when it has found one of the above matches files.
See this [link for an example](https://github.com/anchore/syft/blob/main/syft/pkg/cataloger/apkdb/parse_apk_db.go#L22-L102).
See this [link for an example](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/parse_apk_db.go#L22-L102).
If you're unsure about using the `Generic Cataloger` and think the use case being filled requires something more custom
just file an issue or ask in our slack, and we'd be more than happy to help on the design.
Identified packages share a common struct so be sure that when the new cataloger is constructing a new package it is using the [`Package` struct](https://github.com/anchore/syft/blob/main/syft/pkg/package.go#L16-L31).
Identified packages share a common struct so be sure that when the new cataloger is constructing a new package it is using the [`Package` struct](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/package.go#L16-L31).
Metadata Note: Identified packages are also assigned specific metadata that can be unique to their environment.
See [this folder](https://github.com/anchore/syft/tree/main/syft/pkg) for examples of the different metadata types.
See [this folder](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg) for examples of the different metadata types.
These are plugged into the `MetadataType` and `Metadata` fields in the above struct. `MetadataType` informs which type is being used. `Metadata` is an interface converted to that type.
Finally, here is an example of where the package construction is done in the apk cataloger. The first link is where `newPackage` is called in the `parseFunction`. The second link shows the package construction:
- [Call for new package](https://github.com/anchore/syft/blob/6a7d6e6071829c7ce2943266c0e187b27c0b325c/syft/pkg/cataloger/apkdb/parse_apk_db.go#L96-L99)
- [APK Package Constructor](https://github.com/anchore/syft/blob/6a7d6e6071829c7ce2943266c0e187b27c0b325c/syft/pkg/cataloger/apkdb/package.go#L12-L27)
- [Call for new package](https://github.com/anchore/syft/blob/v0.70.0/syft/pkg/cataloger/apkdb/parse_apk_db.go#L106)
- [APK Package Constructor](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/package.go#L12-L27)
If you have more questions about implementing a cataloger or questions about one you might be currently working
always feel free to file an issue or reach out to us [on slack](https://anchore.com/slack).
#### Searching for files
All catalogers are provided an instance of the [`source.FileResolver`](https://github.com/anchore/syft/blob/v0.70.0/syft/source/file_resolver.go#L8) to interface with the image and search for files. The implementations for these
abstractions leverage [`stereoscope`](https://github.com/anchore/stereoscope) in order to perform searching. Here is a
rough outline how that works:
1. a stereoscope `file.Index` is searched based on the input given (a path, glob, or MIME type). The index is relatively fast to search, but requires results to be filtered down to the files that exist in the specific layer(s) of interest. This is done automatically by the `filetree.Searcher` abstraction. This abstraction will fallback to searching directly against the raw `filetree.FileTree` if the index does not contain the file(s) of interest. Note: the `filetree.Searcher` is used by the `source.FileResolver` abstraction.
2. Once the set of files are returned from the `filetree.Searcher` the results are filtered down further to return the most unique file results. For example, you may have requested for files by a glob that returns multiple results. These results are filtered down to deduplicate by real files, so if a result contains two references to the same file, say one accessed via symlink and one accessed via the real path, then the real path reference is returned and the symlink reference is filtered out. If both were accessed by symlink then the first (by lexical order) is returned. This is done automatically by the `source.FileResolver` abstraction.
3. By the time results reach the `pkg.Cataloger` you are guaranteed to have a set of unique files that exist in the layer(s) of interest (relative to what the resolver supports).
## Testing
### Levels of testing
+34 -19
View File
@@ -4,18 +4,21 @@ TEMP_DIR := ./.tmp
# Command templates #################################
LINT_CMD := $(TEMP_DIR)/golangci-lint run --tests=false
GOIMPORTS_CMD := $(TEMP_DIR)/gosimports -local github.com/anchore
RELEASE_CMD := $(TEMP_DIR)/goreleaser release --rm-dist
RELEASE_CMD := $(TEMP_DIR)/goreleaser release --clean
SNAPSHOT_CMD := $(RELEASE_CMD) --skip-publish --skip-sign --snapshot
CHRONICLE_CMD = $(TEMP_DIR)/chronicle
GLOW_CMD = $(TEMP_DIR)/glow
# Tool versions #################################
GOLANGCILINT_VERSION := v1.50.1
GOSIMPORTS_VERSION := v0.3.5
GOLANGCILINT_VERSION := v1.52.2
GOSIMPORTS_VERSION := v0.3.8
BOUNCER_VERSION := v0.4.0
CHRONICLE_VERSION := v0.4.2
GORELEASER_VERSION := v1.14.1
CHRONICLE_VERSION := v0.6.0
GORELEASER_VERSION := v1.16.2
YAJSV_VERSION := v1.4.1
COSIGN_VERSION := v1.13.1
QUILL_VERSION := v0.2.0
GLOW_VERSION := v1.5.0
# Formatting variables #################################
BOLD := $(shell tput -T linux bold)
@@ -88,6 +91,7 @@ bootstrap-tools: $(TEMP_DIR)
GOBIN="$(realpath $(TEMP_DIR))" go install github.com/rinchsan/gosimports/cmd/gosimports@$(GOSIMPORTS_VERSION)
GOBIN="$(realpath $(TEMP_DIR))" go install github.com/neilpa/yajsv@$(YAJSV_VERSION)
GOBIN="$(realpath $(TEMP_DIR))" go install github.com/sigstore/cosign/cmd/cosign@$(COSIGN_VERSION)
GOBIN="$(realpath $(TEMP_DIR))" go install github.com/charmbracelet/glow@$(GLOW_VERSION)
.PHONY: bootstrap-go
bootstrap-go:
@@ -132,10 +136,7 @@ check-go-mod-tidy:
check-json-schema-drift:
$(call title,Ensure there is no drift between the JSON schema and the code)
@git diff-index --quiet HEAD -- || (echo "there are uncommitted changes, please commit them before running this check" && false)
@make generate-json-schema || (echo "$(RED)$(BOLD)JSON schema drift detected!$(RESET)" && false)
@git diff-index --quiet HEAD -- || (echo "$(RED)$(BOLD)JSON schema drift detected!$(RESET)" && false)
@.github/scripts/json-schema-drift-check.sh
## Testing targets #################################
@@ -188,6 +189,10 @@ fingerprints:
cd test/integration/test-fixtures && \
make cache.fingerprint
# for BINARY test fixtures
cd syft/pkg/cataloger/binary/test-fixtures && \
make cache.fingerprint
# for JAVA BUILD test fixtures
cd syft/pkg/cataloger/java/test-fixtures/java-builds && \
make packages.fingerprint
@@ -213,6 +218,7 @@ fixtures:
$(call title,Generating test fixtures)
cd syft/pkg/cataloger/java/test-fixtures/java-builds && make
cd syft/pkg/cataloger/rpm/test-fixtures && make
cd syft/pkg/cataloger/binary/test-fixtures && make
.PHONY: show-test-image-cache
show-test-image-cache: ## Show all docker and image tar cache
@@ -246,6 +252,11 @@ install-test-ci-mac: $(SNAPSHOT_DIR)
cd test/install && \
make ci-test-mac
.PHONY: generate-compare-file
generate-compare-file:
$(call title,Generating compare test file)
go run ./cmd/syft $(COMPARE_TEST_IMAGE) -o json > $(COMPARE_DIR)/test-fixtures/acceptance-centos-8.2.2004.json
# note: we cannot clean the snapshot directory since the pipeline builds the snapshot separately
.PHONY: compare-mac
compare-mac: $(TEMP_DIR) $(SNAPSHOT_DIR) ## Run compare tests on build snapshot binaries and packages (Mac)
@@ -307,20 +318,20 @@ $(SNAPSHOT_DIR): ## Build snapshot release binaries and packages
$(SNAPSHOT_CMD) --config $(TEMP_DIR)/goreleaser.yaml
.PHONY: changelog
changelog: clean-changelog $(CHANGELOG) ## Generate and show the changelog for the current unreleased version
@docker run -it --rm \
-v $(shell pwd)/$(CHANGELOG):/$(CHANGELOG) \
rawkode/mdv \
-t 748.5989 \
/$(CHANGELOG)
changelog: clean-changelog ## Generate and show the changelog for the current unreleased version
$(CHRONICLE_CMD) -vvv -n --version-file VERSION > $(CHANGELOG)
@$(GLOW_CMD) $(CHANGELOG)
$(CHANGELOG):
$(TEMP_DIR)/chronicle -vv > $(CHANGELOG)
$(CHRONICLE_CMD) -vvv > $(CHANGELOG)
.PHONY: release
release: clean-dist $(CHANGELOG)
release:
@.github/scripts/trigger-release.sh
.PHONY: ci-release
ci-release: ci-check clean-dist $(CHANGELOG)
$(call title,Publishing release artifacts)
@.github/scripts/ci-check.sh
# create a config with the dist dir overridden
echo "dist: $(DIST_DIR)" > $(TEMP_DIR)/goreleaser.yaml
@@ -335,6 +346,10 @@ release: clean-dist $(CHANGELOG)
# upload the version file that supports the application version update check (excluding pre-releases)
.github/scripts/update-version-file.sh "$(DIST_DIR)" "$(VERSION)"
.PHONY: ci-check
ci-check:
@.github/scripts/ci-check.sh
## Cleanup targets #################################
.PHONY: clean
@@ -353,7 +368,7 @@ clean-dist: clean-changelog
.PHONY: clean-changelog
clean-changelog:
rm -f $(CHANGELOG)
rm -f $(CHANGELOG) VERSION
clean-test-image-cache: clean-test-image-tar-cache clean-test-image-docker-cache ## Clean test image cache
+28 -8
View File
@@ -110,9 +110,7 @@ The above output includes only software that is visible in the container (i.e.,
syft <image> --scope all-layers
```
## Supported sources
### Supported sources
Syft can generate a SBOM from a variety of sources:
@@ -141,7 +139,13 @@ file:path/to/yourproject/file read directly from a path on disk (any
registry:yourrepo/yourimage:tag pull image directly from a registry (no container runtime required)
```
#### Default Cataloger Configuration by scan type
If an image source is not provided and cannot be detected from the given reference it is assumed the image should be pulled from the Docker daemon.
If docker is not present, then the Podman daemon is attempted next, followed by reaching out directly to the image registry last.
This default behavior can be overridden with the `default-image-pull-source` configuration option (See [Configuration](https://github.com/anchore/syft#configuration) for more details).
### Default Cataloger Configuration by scan type
##### Image Scanning:
- alpmdb
@@ -179,7 +183,7 @@ registry:yourrepo/yourimage:tag pull image directly from a registry (no
- conan
- hackage
#### Non Default:
##### Non Default:
- cargo-auditable-binary
### Excluding file paths
@@ -213,8 +217,10 @@ Where the `formats` available are:
- `text`: A row-oriented, human-and-machine-friendly output.
- `cyclonedx-xml`: A XML report conforming to the [CycloneDX 1.4 specification](https://cyclonedx.org/specification/overview/).
- `cyclonedx-json`: A JSON report conforming to the [CycloneDX 1.4 specification](https://cyclonedx.org/specification/overview/).
- `spdx-tag-value`: A tag-value formatted report conforming to the [SPDX 2.2 specification](https://spdx.github.io/spdx-spec/).
- `spdx-json`: A JSON report conforming to the [SPDX 2.2 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.2/schemas/spdx-schema.json).
- `spdx-tag-value`: A tag-value formatted report conforming to the [SPDX 2.3 specification](https://spdx.github.io/spdx-spec/v2.3/).
- `spdx-tag-value@2.2`: A tag-value formatted report conforming to the [SPDX 2.2 specification](https://spdx.github.io/spdx-spec/v2.2.2/).
- `spdx-json`: A JSON report conforming to the [SPDX 2.3 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.3/schemas/spdx-schema.json).
- `spdx-json@2.2`: A JSON report conforming to the [SPDX 2.2 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.2/schemas/spdx-schema.json).
- `github`: A JSON report conforming to GitHub's dependency snapshot format.
- `table`: A columnar summary (default).
- `template`: Lets the user specify the output format. See ["Using templates"](#using-templates) below.
@@ -391,7 +397,7 @@ Certificate subject: test.email@testdomain.com
Certificate issuer URL: https://accounts.google.com
```
#### Local private key support
### Local private key support
To generate an SBOM attestation for a container image using a local private key:
```
@@ -434,6 +440,10 @@ file: ""
# same as SYFT_CHECK_FOR_APP_UPDATE env var
check-for-app-update: true
# allows users to specify which image source should be used to generate the sbom
# valid values are: registry, docker, podman
default-image-pull-source: ""
# a list of globs to exclude from scanning. same as --exclude ; for example:
# exclude:
# - "/etc/**"
@@ -492,6 +502,16 @@ package:
# same as -s ; SYFT_PACKAGE_CATALOGER_SCOPE env var
scope: "squashed"
golang:
# search for go package licences in the GOPATH of the system running Syft, note that this is outside the
# container filesystem and potentially outside the root of a local directory scan
# SYFT_GOLANG_SEARCH_LOCAL_MOD_CACHE_LICENSES env var
search-local-mod-cache-licenses: false
# specify an explicit go mod cache directory, if unset this defaults to $GOPATH/pkg/mod or $HOME/go/pkg/mod
# SYFT_GOLANG_LOCAL_MOD_CACHE_DIR env var
local-mod-cache-dir: ""
# cataloging file contents is exposed through the power-user subcommand
file-contents:
cataloger:
+51 -43
View File
@@ -1,14 +1,49 @@
# Release Process
# Release
## Creating a release
This release process itself should be as automated as possible, and has only a few steps:
1. **Trigger a new release with `make release`**. At this point you'll see a preview
changelog in the terminal. If you're happy with the changelog, press `y` to continue, otherwise
you can abort and adjust the labels on the PRs and issues to be included in the release and
re-run the release trigger command.
1. A release admin must approve the release on the GitHub Actions release pipeline run page.
Once approved, the release pipeline will generate all assets and publish a GitHub Release.
1. If there is a release Milestone, close it.
Ideally releasing should be done often with small increments when possible. Unless a
breaking change is blocking the release, or no fixes/features have been merged, a good
target release cadence is between every 1 or 2 weeks.
## Retracting a release
If a release is found to be problematic, it can be retracted with the following steps:
- Deleting the GitHub Release
- Untag the docker images in the `ghcr.io` and `docker.io` registries
- Revert the brew formula in [`anchore/homebrew-syft`](https://github.com/anchore/homebrew-syft) to point to the previous release
- Add a new `retract` entry in the go.mod for the versioned release
**Note**: do not delete release tags from the git repository since there may already be references to the release
in the go proxy, which will cause confusion when trying to reuse the tag later (the H1 hash will not match and there
will be a warning when users try to pull the new release).
## Background
A good release process has the following qualities:
1. There is a way to plan what should be in a release
1. There is a way to see what is actually in a release
1. Allow for different kinds of releases (major breaking vs backwards compatible
enhancements vs patch updates)
1. Allow for different kinds of releases (major breaking vs backwards compatible enhancements vs patch updates)
1. Specify a repeatable way to build and publish software artifacts
## Planning a release
### Planning a release
To indicate a set of features to be released together add each issue to an in-repository
Milestone named with major-minor version to be released (e.g. `v0.1`). It is OK for other
@@ -21,15 +56,13 @@ completed, would allow the release to be considered complete. A Milestone is onl
Not all releases need to be planned. For instance, patch releases for fixes should be
released when they are ready and when releasing would not interfere with another current
release (where some partial or breaking features have already been merged). Beta releases
and release candidates should not be independently planned from the non-beta release. That
is, the features for a `v0.1-beta.1` release should be planned under the `v0.1` Milestone,
not under a separate `v0.1-beta.1` Milestone.
release (where some partial or breaking features have already been merged).
Unless necessary, feature releases should be small and frequent, which may obviate the
need for regular release planning under a Milestone.
## What is in a release
### What is in a release
Milestones are specifically for planning a release, not necessarily tracking all changes
that a release may bring (and more importantly, not all releases are necessarily planned
@@ -42,9 +75,9 @@ Changelog line. Furthermore, there should be a place to see all released version
release date for each release, the semantic version of the release, and the set of changes
for each release.
This project auto-generates the Changelog contents for each current release and posts the
generated contents to the GitHub Release page. Leveraging the GitHub Releases feature
allows GitHub to manage the Changelog on each release outside of the git repository while
**This project auto-generates the Changelog contents for each current release and posts the
generated contents to the GitHub Release page**. Leveraging the GitHub Releases feature
allows GitHub to manage the Changelog on each release outside of the git source tree while
still being hosted with the released assets.
The Changelog is generated from the metadata from in-repository issues and PRs, using
@@ -60,45 +93,20 @@ The above suggestions imply that we should:
- The appropriate label is applied to PRs and/or issues to drive specific change type
sections (deprecated, breaking, security, bug, etc)
With this approach as we cultivate good organization of PRs and issues we automatically
get an equally good Changelog.
**With this approach as we cultivate good organization of PRs and issues we automatically
get an equally good Changelog.**
## Major, minor, and patch releases
### Major, minor, and patch releases
The latest version of the tool is the only supported version, which implies that multiple
parallel release branches will not be a regular process (if ever). Multiple releases can
be planned in parallel, however, only one can be actively developed at a time. That is, if
PRs attached to a release Milestone have been merged into the main branch, that release is
now the "next" release. This implies that the source of truth for release lies with the
git log and Changelog, not with the release Milestones (which are purely for planning and
now the "next" release. **This implies that the source of truth for release lies with the
git log and Changelog, not with the release Milestones** (which are purely for planning and
tracking).
Semantic versioning should be used to indicate breaking changes, new features, and fixes.
The exception to this is `< 1.0`, where the major version is not bumped for breaking changes,
instead the minor version indicates both new features and breaking changes.
## Cutting a release
Ideally releasing should be done often with small increments when possible. Unless a
breaking change is blocking the release, or no fixes/features have been merged, a good
target release cadence is between every 2 or 4 weeks.
This release process itself should be as automated as possible, and have only a few steps:
1. Tag the main branch with a full semantic-version, prefixed with a `v`. If there is a
milestone with a partial version, the full version should be used for the git tag (e.g.
with a Milestone of `v0.1` the tag should be `v0.1.0`). You can determine the changes going
into a release by running `make changelog-unreleased`. Use this change list to determine the
release increment. After determining the release increment (major, minor, patch), create the tag.
Given the above example the command to create the tag would be `git tag v0.1.0`.
1. Push the tag. Given the above example the command to push the tag would be `git push origin v0.1.0`.
1. A release admin must approve the release on the GitHub Actions release pipeline run page.
Once approved, the release pipeline will generate all assets and draft a GitHub Release.
1. Navigate to the GitHub Release draft page to review the final changelog and publish the
release. Once published, a release-follow-up pipeline will publish derivative artifacts
(docker image to DockerHub, brew formula to the external homebrew git repo, etc).
1. If there is a release Milestone, close it.
+8 -3
View File
@@ -20,8 +20,7 @@ const (
attestHelp = attestExample + attestSchemeHelp
)
//nolint:dupl
func Attest(v *viper.Viper, app *config.Application, ro *options.RootOptions, po *options.PackagesOptions) *cobra.Command {
func Attest(v *viper.Viper, app *config.Application, ro *options.RootOptions, po *options.PackagesOptions, ao *options.AttestOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "attest --output [FORMAT] <IMAGE>",
Short: "Generate an SBOM as an attestation for the given [SOURCE] container image",
@@ -50,11 +49,17 @@ func Attest(v *viper.Viper, app *config.Application, ro *options.RootOptions, po
},
}
// syft attest is an enhancment of the packages command, so it should have the same flags
// syft attest is an enhancement of the packages command, so it should have the same flags
err := po.AddFlags(cmd, v)
if err != nil {
log.Fatal(err)
}
// syft attest has its own options not included as part of the packages command
err = ao.AddFlags(cmd, v)
if err != nil {
log.Fatal(err)
}
return cmd
}
+34 -17
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"os/exec"
"strings"
"github.com/wagoodman/go-partybus"
"github.com/wagoodman/go-progress"
@@ -22,12 +23,11 @@ import (
"github.com/anchore/syft/syft/event/monitor"
"github.com/anchore/syft/syft/formats/syftjson"
"github.com/anchore/syft/syft/formats/table"
"github.com/anchore/syft/syft/formats/template"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
)
func Run(ctx context.Context, app *config.Application, args []string) error {
func Run(_ context.Context, app *config.Application, args []string) error {
err := ValidateOutputOptions(app)
if err != nil {
return err
@@ -47,7 +47,7 @@ func Run(ctx context.Context, app *config.Application, args []string) error {
// could be an image or a directory, with or without a scheme
// TODO: validate that source is image
userInput := args[0]
si, err := source.ParseInputWithName(userInput, app.Platform, true, app.Name)
si, err := source.ParseInputWithName(userInput, app.Platform, app.Name, app.DefaultImagePullSource)
if err != nil {
return fmt.Errorf("could not generate source input for packages command: %w", err)
}
@@ -97,6 +97,7 @@ func buildSBOM(app *config.Application, si source.Input, writer sbom.Writer, err
return sBytes, nil
}
//nolint:funlen
func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-chan error {
errs := make(chan error)
go func() {
@@ -130,10 +131,33 @@ func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-
return
}
args := []string{"attest", si.UserInput, "--type", "custom", "--predicate", f.Name()}
// Select Cosign predicate type based on defined output type
// As orientation, check: https://github.com/sigstore/cosign/blob/main/pkg/cosign/attestation/attestation.go
var predicateType string
switch strings.ToLower(o) {
case "cyclonedx-json":
predicateType = "cyclonedx"
case "spdx-tag-value":
predicateType = "spdx"
case "spdx-json":
predicateType = "spdxjson"
default:
predicateType = "custom"
}
args := []string{"attest", si.UserInput, "--predicate", f.Name(), "--type", predicateType}
if app.Attest.Key != "" {
args = append(args, "--key", app.Attest.Key)
}
execCmd := exec.Command(cmd, args...)
execCmd.Env = os.Environ()
execCmd.Env = append(execCmd.Env, "COSIGN_EXPERIMENTAL=1")
if app.Attest.Key != "" {
execCmd.Env = append(execCmd.Env, fmt.Sprintf("COSIGN_PASSWORD=%s", app.Attest.Password))
} else {
// no key provided, use cosign's keyless mode
execCmd.Env = append(execCmd.Env, "COSIGN_EXPERIMENTAL=1")
}
// bus adapter for ui to hook into stdout via an os pipe
r, w, err := os.Pipe()
@@ -143,7 +167,7 @@ func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-
}
defer w.Close()
b := &busWriter{r: r, w: w, mon: &progress.Manual{N: -1}}
b := &busWriter{r: r, w: w, mon: progress.NewManual(-1)}
execCmd.Stdout = b
execCmd.Stderr = b
defer b.mon.SetCompleted()
@@ -151,7 +175,7 @@ func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-
// attest the SBOM
err = execCmd.Run()
if err != nil {
b.mon.Err = err
b.mon.SetError(err)
errs <- fmt.Errorf("unable to attest SBOM: %w", err)
return
}
@@ -166,16 +190,9 @@ func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-
}
func ValidateOutputOptions(app *config.Application) error {
var usesTemplateOutput bool
for _, o := range app.Outputs {
if o == template.ID.String() {
usesTemplateOutput = true
break
}
}
if usesTemplateOutput && app.OutputTemplatePath == "" {
return fmt.Errorf(`must specify path to template file when using "template" output format`)
err := packages.ValidateOutputOptions(app)
if err != nil {
return err
}
if len(app.Outputs) > 1 {
+3 -1
View File
@@ -45,15 +45,17 @@ func New() (*cobra.Command, error) {
// we also need the command to have information about the `root` options because of this alias
ro := &options.RootOptions{}
po := &options.PackagesOptions{}
ao := &options.AttestOptions{}
packagesCmd := Packages(v, app, ro, po)
// root options are also passed to the attestCmd so that a user provided config location can be discovered
poweruserCmd := PowerUser(v, app, ro)
convertCmd := Convert(v, app, ro, po)
attestCmd := Attest(v, app, ro, po)
attestCmd := Attest(v, app, ro, po, ao)
// rootCmd is currently an alias for the packages command
rootCmd := &cobra.Command{
Use: fmt.Sprintf("%s [SOURCE]", internal.ApplicationName),
Short: packagesCmd.Short,
Long: packagesCmd.Long,
Args: packagesCmd.Args,
+3 -2
View File
@@ -14,8 +14,9 @@ import (
)
const (
convertExample = ` {{.appName}} {{.command}} img.syft.json -o spdx-json convert a syft SBOM to spdx-json, output goes to stdout in table format, by default
{{.appName}} {{.command}} img.syft.json -o cyclonedx-json=img.cdx.json convert a syft SBOM to CycloneDX, output goes to a file named img.cdx.json
convertExample = ` {{.appName}} {{.command}} img.syft.json -o spdx-json convert a syft SBOM to spdx-json, output goes to stdout
{{.appName}} {{.command}} img.syft.json -o cyclonedx-json=img.cdx.json convert a syft SBOM to CycloneDX, output is written to the file "img.cdx.json""
{{.appName}} {{.command}} - -o spdx-json convert an SBOM from STDIN to spdx-json
`
)
+20 -9
View File
@@ -3,17 +3,18 @@ package convert
import (
"context"
"fmt"
"io"
"os"
"github.com/anchore/syft/cmd/syft/cli/options"
"github.com/anchore/syft/internal/config"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/formats"
)
func Run(ctx context.Context, app *config.Application, args []string) error {
func Run(_ context.Context, app *config.Application, args []string) error {
log.Warn("convert is an experimental feature, run `syft convert -h` for help")
writer, err := options.MakeWriter(app.Outputs, app.File, "")
writer, err := options.MakeWriter(app.Outputs, app.File, app.OutputTemplatePath)
if err != nil {
return err
}
@@ -26,13 +27,23 @@ func Run(ctx context.Context, app *config.Application, args []string) error {
// this can only be a SBOM file
userInput := args[0]
f, err := os.Open(userInput)
if err != nil {
return fmt.Errorf("failed to open SBOM file: %w", err)
}
defer f.Close()
sbom, _, err := syft.Decode(f)
var reader io.ReadCloser
if userInput == "-" {
reader = os.Stdin
} else {
f, err := os.Open(userInput)
if err != nil {
return fmt.Errorf("failed to open SBOM file: %w", err)
}
defer func() {
_ = f.Close()
}()
reader = f
}
sbom, _, err := formats.Decode(reader)
if err != nil {
return fmt.Errorf("failed to decode SBOM: %w", err)
}
+1 -4
View File
@@ -46,14 +46,11 @@ 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())
if err != nil {
return nil, err
}
results.PackageCatalog = packageCatalog
results.LinuxDistribution = theDistro
return relationships, nil
return relationships, err
}
return task, nil
+26
View File
@@ -0,0 +1,26 @@
package options
import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)
type AttestOptions struct {
Key string
}
var _ Interface = (*AttestOptions)(nil)
func (o AttestOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error {
cmd.Flags().StringVarP(&o.Key, "key", "k", "", "the key to use for the attestation")
return bindAttestConfigOptions(cmd.Flags(), v)
}
//nolint:revive
func bindAttestConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error {
if err := v.BindPFlag("attest.key", flags.Lookup("key")); err != nil {
return err
}
return nil
}
-39
View File
@@ -1,39 +0,0 @@
package options
import (
"github.com/anchore/syft/syft/formats/cyclonedxjson"
"github.com/anchore/syft/syft/formats/cyclonedxxml"
"github.com/anchore/syft/syft/formats/github"
"github.com/anchore/syft/syft/formats/spdxjson"
"github.com/anchore/syft/syft/formats/spdxtagvalue"
"github.com/anchore/syft/syft/formats/syftjson"
"github.com/anchore/syft/syft/formats/table"
"github.com/anchore/syft/syft/formats/text"
"github.com/anchore/syft/syft/sbom"
)
func FormatAliases(ids ...sbom.FormatID) (aliases []string) {
for _, id := range ids {
switch id {
case syftjson.ID:
aliases = append(aliases, "syft-json")
case text.ID:
aliases = append(aliases, "text")
case table.ID:
aliases = append(aliases, "table")
case spdxjson.ID:
aliases = append(aliases, "spdx-json")
case spdxtagvalue.ID:
aliases = append(aliases, "spdx-tag-value")
case cyclonedxxml.ID:
aliases = append(aliases, "cyclonedx-xml")
case cyclonedxjson.ID:
aliases = append(aliases, "cyclonedx-json")
case github.ID:
aliases = append(aliases, "github", "github-json")
default:
aliases = append(aliases, string(id))
}
}
return aliases
}
+1
View File
@@ -31,6 +31,7 @@ func (o *FulcioOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error {
return bindFulcioConfigOptions(cmd.Flags(), v)
}
//nolint:revive
func bindFulcioConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error {
if err := v.BindPFlag("attest.fulcio-url", flags.Lookup("fulcio-url")); err != nil {
return err
+1
View File
@@ -31,6 +31,7 @@ func (o *OIDCOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error {
return bindOIDCConfigOptions(cmd.Flags(), v)
}
//nolint:revive
func bindOIDCConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error {
if err := v.BindPFlag("attest.oidc-issuer", flags.Lookup("oidc-issuer")); err != nil {
return err
+4 -3
View File
@@ -7,7 +7,7 @@ import (
"github.com/spf13/pflag"
"github.com/spf13/viper"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/formats"
"github.com/anchore/syft/syft/formats/table"
"github.com/anchore/syft/syft/pkg/cataloger"
"github.com/anchore/syft/syft/source"
@@ -30,8 +30,8 @@ func (o *PackagesOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error {
cmd.Flags().StringVarP(&o.Scope, "scope", "s", cataloger.DefaultSearchConfig().Scope.String(),
fmt.Sprintf("selection of layers to catalog, options=%v", source.AllScopes))
cmd.Flags().StringArrayVarP(&o.Output, "output", "o", FormatAliases(table.ID),
fmt.Sprintf("report output format, options=%v", FormatAliases(syft.FormatIDs()...)))
cmd.Flags().StringArrayVarP(&o.Output, "output", "o", []string{string(table.ID)},
fmt.Sprintf("report output format, options=%v", formats.AllIDs()))
cmd.Flags().StringVarP(&o.File, "file", "", "",
"file to write the default report output to (default is STDOUT)")
@@ -54,6 +54,7 @@ func (o *PackagesOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error {
return bindPackageConfigOptions(cmd.Flags(), v)
}
//nolint:revive
func bindPackageConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error {
// Formatting & Input options //////////////////////////////////////////////
+1
View File
@@ -22,6 +22,7 @@ func (o *RekorOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error {
return bindRekorConfigOptions(cmd.Flags(), v)
}
//nolint:revive
func bindRekorConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error {
// TODO: config re-design
if err := v.BindPFlag("attest.rekor-url", flags.Lookup("rekor-url")); err != nil {
+1
View File
@@ -22,6 +22,7 @@ func (o *RootOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error {
return bindRootConfigOptions(cmd.PersistentFlags(), v)
}
//nolint:revive
func bindRootConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error {
if err := v.BindPFlag("config", flags.Lookup("config")); err != nil {
return err
+1 -1
View File
@@ -11,7 +11,7 @@ type VersionOptions struct {
var _ Interface = (*VersionOptions)(nil)
func (o *VersionOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error {
func (o *VersionOptions) AddFlags(cmd *cobra.Command, _ *viper.Viper) error {
cmd.Flags().StringVarP(&o.Output, "output", "o", "text", "format to show version information (available=[text, json])")
return nil
}
+4 -4
View File
@@ -6,7 +6,7 @@ import (
"github.com/hashicorp/go-multierror"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/formats"
"github.com/anchore/syft/syft/formats/table"
"github.com/anchore/syft/syft/formats/template"
"github.com/anchore/syft/syft/sbom"
@@ -32,7 +32,7 @@ func MakeWriter(outputs []string, defaultFile, templateFilePath string) (sbom.Wr
func parseOutputs(outputs []string, defaultFile, templateFilePath string) (out []sbom.WriterOption, errs error) {
// always should have one option -- we generally get the default of "table", but just make sure
if len(outputs) == 0 {
outputs = append(outputs, string(table.ID))
outputs = append(outputs, table.ID.String())
}
for _, name := range outputs {
@@ -52,9 +52,9 @@ func parseOutputs(outputs []string, defaultFile, templateFilePath string) (out [
file = parts[1]
}
format := syft.FormatByName(name)
format := formats.ByName(name)
if format == nil {
errs = multierror.Append(errs, fmt.Errorf(`unsupported output format "%s", supported formats are: %+v`, name, FormatAliases(syft.FormatIDs()...)))
errs = multierror.Append(errs, fmt.Errorf(`unsupported output format "%s", supported formats are: %+v`, name, formats.AllIDs()))
continue
}
+4 -2
View File
@@ -18,8 +18,10 @@ const (
{{.appName}} {{.command}} alpine:latest -o json show all possible cataloging details
{{.appName}} {{.command}} alpine:latest -o cyclonedx show a CycloneDX formatted SBOM
{{.appName}} {{.command}} alpine:latest -o cyclonedx-json show a CycloneDX JSON formatted SBOM
{{.appName}} {{.command}} alpine:latest -o spdx show a SPDX 2.2 Tag-Value formatted SBOM
{{.appName}} {{.command}} alpine:latest -o spdx-json show a SPDX 2.2 JSON formatted SBOM
{{.appName}} {{.command}} alpine:latest -o spdx show a SPDX 2.3 Tag-Value formatted SBOM
{{.appName}} {{.command}} alpine:latest -o spdx@2.2 show a SPDX 2.2 Tag-Value formatted SBOM
{{.appName}} {{.command}} alpine:latest -o spdx-json show a SPDX 2.3 JSON formatted SBOM
{{.appName}} {{.command}} alpine:latest -o spdx-json@2.2 show a SPDX 2.2 JSON formatted SBOM
{{.appName}} {{.command}} alpine:latest -vv show verbose debug information
{{.appName}} {{.command}} alpine:latest -o template -t my_format.tmpl show a SBOM formatted according to given template file
+2 -2
View File
@@ -23,7 +23,7 @@ import (
"github.com/anchore/syft/syft/source"
)
func Run(ctx context.Context, app *config.Application, args []string) error {
func Run(_ context.Context, app *config.Application, args []string) error {
err := ValidateOutputOptions(app)
if err != nil {
return err
@@ -42,7 +42,7 @@ func Run(ctx context.Context, app *config.Application, args []string) error {
// could be an image or a directory, with or without a scheme
userInput := args[0]
si, err := source.ParseInputWithName(userInput, app.Platform, true, app.Name)
si, err := source.ParseInputWithName(userInput, app.Platform, app.Name, app.DefaultImagePullSource)
if err != nil {
return fmt.Errorf("could not generate source input for packages command: %w", err)
}
+4 -3
View File
@@ -26,9 +26,10 @@ import (
"github.com/anchore/syft/syft/source"
)
func Run(ctx context.Context, app *config.Application, args []string) error {
func Run(_ context.Context, app *config.Application, args []string) error {
f := syftjson.Format()
writer, err := sbom.NewWriter(sbom.WriterOption{
Format: syftjson.Format(),
Format: f,
Path: app.File,
})
if err != nil {
@@ -46,7 +47,7 @@ func Run(ctx context.Context, app *config.Application, args []string) error {
}()
userInput := args[0]
si, err := source.ParseInputWithName(userInput, app.Platform, true, app.Name)
si, err := source.ParseInputWithName(userInput, app.Platform, app.Name, app.DefaultImagePullSource)
if err != nil {
return fmt.Errorf("could not generate source input for packages command: %w", err)
}
+1 -1
View File
@@ -15,7 +15,7 @@ import (
"github.com/anchore/syft/internal/version"
)
func Version(v *viper.Viper, app *config.Application) *cobra.Command {
func Version(v *viper.Viper, _ *config.Application) *cobra.Command {
o := &options.VersionOptions{}
cmd := &cobra.Command{
Use: "version",
+52 -50
View File
@@ -1,24 +1,24 @@
module github.com/anchore/syft
go 1.18
go 1.19
require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/acobaugh/osrelease v0.1.0
github.com/adrg/xdg v0.3.3
github.com/adrg/xdg v0.4.0
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501
github.com/bmatcuk/doublestar/v4 v4.0.2
github.com/dustin/go-humanize v1.0.0
github.com/facebookincubator/nvdtools v0.1.4
github.com/go-test/deep v1.0.8
github.com/bmatcuk/doublestar/v4 v4.6.0
github.com/dustin/go-humanize v1.0.1
github.com/facebookincubator/nvdtools v0.1.5
github.com/go-test/deep v1.1.0
github.com/google/go-cmp v0.5.9
github.com/google/uuid v1.3.0
github.com/gookit/color v1.4.2
github.com/gookit/color v1.5.3
github.com/hashicorp/go-multierror v1.1.1
github.com/jinzhu/copier v0.3.2
github.com/jinzhu/copier v0.3.5
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/mholt/archiver/v3 v3.5.1
github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5
@@ -29,72 +29,75 @@ require (
github.com/pelletier/go-toml v1.9.5
// pinned to pull in 386 arch fix: https://github.com/scylladb/go-set/commit/cc7b2070d91ebf40d233207b633e28f5bd8f03a5
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e
github.com/sergi/go-diff v1.2.0
github.com/sergi/go-diff v1.3.1
github.com/sirupsen/logrus v1.9.0
github.com/spdx/tools-golang v0.3.1-0.20221108182156-8a01147e6342
github.com/spf13/afero v1.8.2
github.com/spf13/cobra v1.6.0
github.com/spdx/tools-golang v0.5.0-rc1
github.com/spf13/afero v1.9.5
github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.13.0
github.com/stretchr/testify v1.8.1
github.com/vifraa/gopom v0.1.0
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.2
github.com/vifraa/gopom v0.2.1
github.com/wagoodman/go-partybus v0.0.0-20210627031916-db1f5573bbc5
github.com/wagoodman/go-progress v0.0.0-20200731105512-1020f39e6240
github.com/wagoodman/go-progress v0.0.0-20230301185719-21920a456ad5
github.com/wagoodman/jotframe v0.0.0-20211129225309-56b0d0a4aebb
github.com/xeipuuv/gojsonschema v1.2.0
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
golang.org/x/net v0.4.0
golang.org/x/term v0.3.0
golang.org/x/mod v0.9.0
golang.org/x/net v0.8.0
golang.org/x/term v0.6.0
gopkg.in/yaml.v2 v2.4.0
)
require (
github.com/CycloneDX/cyclonedx-go v0.7.1-0.20221222100750-41a1ac565cce
github.com/Masterminds/sprig/v3 v3.2.2
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-20221208011002-c5ff155d72f1
github.com/docker/docker v20.10.17+incompatible
github.com/google/go-containerregistry v0.11.0
github.com/anchore/stereoscope v0.0.0-20230323161519-d7551b7f46f5
github.com/docker/docker v23.0.2+incompatible
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/opencontainers/go-digest v1.0.0
github.com/sassoftware/go-rpmutils v0.2.0
github.com/vbatts/go-mtree v0.5.0
golang.org/x/exp v0.0.0-20220823124025-807a23277127
github.com/vbatts/go-mtree v0.5.3
golang.org/x/exp v0.0.0-20230202163644-54bba9f4231b
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/DataDog/zstd v1.4.5 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/containerd/containerd v1.6.12 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.12.0 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
github.com/becheran/wildmatch-go v1.0.0 // indirect
github.com/containerd/containerd v1.6.18 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v20.10.17+incompatible // indirect
github.com/docker/cli v23.0.1+incompatible // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker-credential-helpers v0.6.4 // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.0 // indirect
github.com/go-restruct/restruct v1.2.0-alpha // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/compress v1.16.0 // 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.6 // 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-runewidth v0.0.13 // indirect
@@ -102,8 +105,8 @@ require (
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.0.3-0.20220114050600-8b9d41f48198 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
@@ -113,7 +116,7 @@ require (
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/sylabs/sif/v2 v2.8.1 // indirect
github.com/sylabs/squashfs v0.6.1 // indirect
github.com/therootcompany/xz v1.0.1 // indirect
@@ -123,15 +126,14 @@ require (
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
golang.org/x/tools v0.1.12 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/tools v0.7.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e // indirect
google.golang.org/grpc v1.50.1 // indirect
google.golang.org/protobuf v1.28.1 // 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
gopkg.in/ini.v1 v1.67.0 // indirect
lukechampine.com/uint128 v1.1.1 // indirect
modernc.org/cc/v3 v3.36.0 // indirect
@@ -150,7 +152,7 @@ require (
// go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be // indirect
golang.org/x/crypto v0.3.0 // indirect
)
retract (
+172 -1219
View File
File diff suppressed because it is too large Load Diff
+69 -26
View File
@@ -3,6 +3,7 @@ package config
import (
"errors"
"fmt"
"os"
"path"
"reflect"
"sort"
@@ -17,6 +18,7 @@ import (
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/pkg/cataloger"
golangCataloger "github.com/anchore/syft/syft/pkg/cataloger/golang"
)
var (
@@ -38,24 +40,27 @@ type Application struct {
ConfigPath string `yaml:"configPath,omitempty" json:"configPath" mapstructure:"config"`
Verbosity uint `yaml:"verbosity,omitempty" json:"verbosity" mapstructure:"verbosity"`
// -q, indicates to not show any status output to stderr (ETUI or logging UI)
Quiet bool `yaml:"quiet" json:"quiet" mapstructure:"quiet"`
Outputs []string `yaml:"output" json:"output" mapstructure:"output"` // -o, the format to use for output
OutputTemplatePath string `yaml:"output-template-path" json:"output-template-path" mapstructure:"output-template-path"` // -t template file to use for output
File string `yaml:"file" json:"file" mapstructure:"file"` // --file, the file to write report output to
CheckForAppUpdate bool `yaml:"check-for-app-update" json:"check-for-app-update" mapstructure:"check-for-app-update"` // whether to check for an application update on start up or not
Dev development `yaml:"dev" json:"dev" mapstructure:"dev"`
Log logging `yaml:"log" json:"log" mapstructure:"log"` // all logging-related options
Catalogers []string `yaml:"catalogers" json:"catalogers" mapstructure:"catalogers"`
Package pkg `yaml:"package" json:"package" mapstructure:"package"`
FileMetadata FileMetadata `yaml:"file-metadata" json:"file-metadata" mapstructure:"file-metadata"`
FileClassification fileClassification `yaml:"file-classification" json:"file-classification" mapstructure:"file-classification"`
FileContents fileContents `yaml:"file-contents" json:"file-contents" mapstructure:"file-contents"`
Secrets secrets `yaml:"secrets" json:"secrets" mapstructure:"secrets"`
Registry registry `yaml:"registry" json:"registry" mapstructure:"registry"`
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
Name string `yaml:"name" json:"name" mapstructure:"name"`
Parallelism int `yaml:"parallelism" json:"parallelism" mapstructure:"parallelism"` // the number of catalog workers to run in parallel
Quiet bool `yaml:"quiet" json:"quiet" mapstructure:"quiet"`
Outputs []string `yaml:"output" json:"output" mapstructure:"output"` // -o, the format to use for output
OutputTemplatePath string `yaml:"output-template-path" json:"output-template-path" mapstructure:"output-template-path"` // -t template file to use for output
File string `yaml:"file" json:"file" mapstructure:"file"` // --file, the file to write report output to
CheckForAppUpdate bool `yaml:"check-for-app-update" json:"check-for-app-update" mapstructure:"check-for-app-update"` // whether to check for an application update on start up or not
Dev development `yaml:"dev" json:"dev" mapstructure:"dev"`
Log logging `yaml:"log" json:"log" mapstructure:"log"` // all logging-related options
Catalogers []string `yaml:"catalogers" json:"catalogers" mapstructure:"catalogers"`
Package pkg `yaml:"package" json:"package" mapstructure:"package"`
Golang golang `yaml:"golang" json:"golang" mapstructure:"golang"`
Attest attest `yaml:"attest" json:"attest" mapstructure:"attest"`
FileMetadata FileMetadata `yaml:"file-metadata" json:"file-metadata" mapstructure:"file-metadata"`
FileClassification fileClassification `yaml:"file-classification" json:"file-classification" mapstructure:"file-classification"`
FileContents fileContents `yaml:"file-contents" json:"file-contents" mapstructure:"file-contents"`
Secrets secrets `yaml:"secrets" json:"secrets" mapstructure:"secrets"`
Registry registry `yaml:"registry" json:"registry" mapstructure:"registry"`
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
Name string `yaml:"name" json:"name" mapstructure:"name"`
Parallelism int `yaml:"parallelism" json:"parallelism" mapstructure:"parallelism"` // the number of catalog workers to run in parallel
DefaultImagePullSource string `yaml:"default-image-pull-source" json:"default-image-pull-source" mapstructure:"default-image-pull-source"` // specify default image pull source
}
func (cfg Application) ToCatalogerConfig() cataloger.Config {
@@ -67,6 +72,10 @@ func (cfg Application) ToCatalogerConfig() cataloger.Config {
},
Catalogers: cfg.Catalogers,
Parallelism: cfg.Parallelism,
Golang: golangCataloger.GoCatalogerOpts{
SearchLocalModCacheLicenses: cfg.Golang.SearchLocalModCacheLicenses,
LocalModCacheDir: cfg.Golang.LocalModCacheDir,
},
}
}
@@ -122,6 +131,12 @@ func (cfg *Application) parseConfigValues() error {
return err
}
}
if err := checkDefaultSourceValues(cfg.DefaultImagePullSource); err != nil {
return err
}
// check for valid default source options
// parse nested config options
// for each field in the configuration struct, see if the field implements the parser interface
// note: the app config is a pointer, so we need to grab the elements explicitly (to traverse the address)
@@ -184,6 +199,7 @@ func loadDefaultValues(v *viper.Viper) {
v.SetDefault("check-for-app-update", true)
v.SetDefault("catalogers", nil)
v.SetDefault("parallelism", 1)
v.SetDefault("default-image-pull-source", "")
// for each field in the configuration struct, see if the field implements the defaultValueLoader interface and invoke it if it does
value := reflect.ValueOf(Application{})
@@ -207,6 +223,7 @@ func (cfg Application) String() string {
return string(appaStr)
}
// nolint:funlen
func loadConfig(v *viper.Viper, configPath string) error {
var err error
// use explicitly the given user config
@@ -222,13 +239,26 @@ func loadConfig(v *viper.Viper, configPath string) error {
// start searching for valid configs in order...
// 1. look for .<appname>.yaml (in the current directory)
confFilePath := "." + internal.ApplicationName
// TODO: Remove this before v1.0.0
// See syft #1634
v.AddConfigPath(".")
v.SetConfigName("." + internal.ApplicationName)
if err = v.ReadInConfig(); err == nil {
v.Set("config", v.ConfigFileUsed())
return nil
} else if !errors.As(err, &viper.ConfigFileNotFoundError{}) {
return fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err)
v.SetConfigName(confFilePath)
// check if config.yaml exists in the current directory
// DEPRECATED: this will be removed in v1.0.0
if _, err := os.Stat("config.yaml"); err == nil {
log.Warn("DEPRECATED: ./config.yaml as a configuration file is deprecated and will be removed as an option in v1.0.0, please rename to .syft.yaml")
}
if _, err := os.Stat(confFilePath + ".yaml"); err == nil {
if err = v.ReadInConfig(); err == nil {
v.Set("config", v.ConfigFileUsed())
return nil
} else if !errors.As(err, &viper.ConfigFileNotFoundError{}) {
return fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err)
}
}
// 2. look for .<appname>/config.yaml (in the current directory)
@@ -255,11 +285,12 @@ func loadConfig(v *viper.Viper, configPath string) error {
}
// 4. look for <appname>/config.yaml in xdg locations (starting with xdg home config dir, then moving upwards)
v.AddConfigPath(path.Join(xdg.ConfigHome, internal.ApplicationName))
v.SetConfigName("config")
configPath = path.Join(xdg.ConfigHome, internal.ApplicationName)
v.AddConfigPath(configPath)
for _, dir := range xdg.ConfigDirs {
v.AddConfigPath(path.Join(dir, internal.ApplicationName))
}
v.SetConfigName("config")
if err = v.ReadInConfig(); err == nil {
v.Set("config", v.ConfigFileUsed())
return nil
@@ -268,3 +299,15 @@ func loadConfig(v *viper.Viper, configPath string) error {
}
return nil
}
var validDefaultSourceValues = []string{"registry", "docker", "podman", ""}
func checkDefaultSourceValues(source string) error {
validValues := internal.NewStringSet(validDefaultSourceValues...)
if !validValues.Contains(source) {
validValuesString := strings.Join(validDefaultSourceValues, ", ")
return fmt.Errorf("%s is not a valid default source; please use one of the following: %s''", source, validValuesString)
}
return nil
}
+129
View File
@@ -0,0 +1,129 @@
package config
import (
"fmt"
"os"
"path"
"testing"
"github.com/adrg/xdg"
"github.com/mitchellh/go-homedir"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TODO: set negative case when config.yaml is no longer a valid option
func TestApplicationConfig(t *testing.T) {
// disable homedir package cache for testing
originalCacheOpt := homedir.DisableCache
homedir.DisableCache = true
t.Cleanup(func() {
homedir.DisableCache = originalCacheOpt
})
// ensure we have no side effects for xdg package for future tests
originalXDG := os.Getenv("XDG_CONFIG_HOME")
t.Cleanup(func() {
// note: we're not using t.Setenv since the effect we're trying to eliminate is within the xdg package
require.NoError(t, os.Setenv("XDG_CONFIG_HOME", originalXDG))
xdg.Reload()
})
// config is picked up at desired configuration paths
// VALID: .syft.yaml, .syft/config.yaml, ~/.syft.yaml, <XDG_CONFIG_HOME>/syft/config.yaml
// DEPRECATED: config.yaml is currently supported by
tests := []struct {
name string
setup func(t *testing.T) string
assertions func(t *testing.T, app *Application)
cleanup func()
}{
{
name: "explicit config",
setup: func(t *testing.T) string {
return "./test-fixtures/.syft.yaml"
}, // no-op for explicit config
assertions: func(t *testing.T, app *Application) {
assert.Equal(t, "test-explicit-config", app.File)
},
},
{
name: "current working directory named config",
setup: func(t *testing.T) string {
err := os.Chdir("./test-fixtures/config-wd-file") // change application cwd to test-fixtures
require.NoError(t, err)
return ""
},
assertions: func(t *testing.T, app *Application) {
assert.Equal(t, "test-wd-named-config", app.File)
},
},
{
name: "current working directory syft dir config",
setup: func(t *testing.T) string {
err := os.Chdir("./test-fixtures/config-dir-test") // change application cwd to test-fixtures
require.NoError(t, err)
return ""
},
assertions: func(t *testing.T, app *Application) {
assert.Equal(t, "test-dir-config", app.File)
},
},
{
name: "home directory file config",
setup: func(t *testing.T) string {
// Because Setenv affects the whole process, it cannot be used in parallel tests or
// tests with parallel ancestors: see separate XDG test for consequence of this
t.Setenv("HOME", "./test-fixtures/config-home-test/config-file")
return ""
},
assertions: func(t *testing.T, app *Application) {
assert.Equal(t, "test-home-config", app.File)
},
},
{
name: "XDG file config",
setup: func(t *testing.T) string {
wd, err := os.Getwd()
require.NoError(t, err)
configDir := path.Join(wd, "./test-fixtures/config-home-test") // set HOME to testdata
// note: this explicitly has multiple XDG paths, make certain we use the first VALID one (not the first one)
t.Setenv("XDG_CONFIG_DIRS", fmt.Sprintf("/another/foo/bar:%s", configDir))
xdg.Reload()
return ""
},
assertions: func(t *testing.T, app *Application) {
assert.Equal(t, "test-home-XDG-config", app.File)
},
cleanup: func() {
require.NoError(t, os.Unsetenv("XDG_CONFIG_DIRS"))
xdg.Reload()
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if test.cleanup != nil {
t.Cleanup(test.cleanup)
}
wd, err := os.Getwd()
require.NoError(t, err)
defer os.Chdir(wd) // reset working directory after test
application := &Application{}
viperInstance := viper.New()
// this will override home in case you are running this test locally and DO have a syft config
// in your home directory... now it will be ignored. Same for XDG_CONFIG_DIRS.
t.Setenv("HOME", "/foo/bar")
t.Setenv("XDG_CONFIG_DIRS", "/foo/bar")
xdg.Reload()
configPath := test.setup(t)
err = application.LoadAllValues(viperInstance, configPath)
require.NoError(t, err)
test.assertions(t, application)
})
}
}
+14
View File
@@ -0,0 +1,14 @@
package config
import "github.com/spf13/viper"
type attest struct {
// IMPORTANT: do not show the attestation key/password in any YAML/JSON output (sensitive information)
Key string `yaml:"-" json:"-" mapstructure:"key"`
Password string `yaml:"-" json:"-" mapstructure:"password"`
}
func (cfg attest) loadDefaultValues(v *viper.Viper) {
v.SetDefault("attest.key", "")
v.SetDefault("attest.password", "")
}
+13
View File
@@ -0,0 +1,13 @@
package config
import "github.com/spf13/viper"
type golang struct {
SearchLocalModCacheLicenses bool `json:"search-local-mod-cache-licenses" yaml:"search-local-mod-cache-licenses" mapstructure:"search-local-mod-cache-licenses"`
LocalModCacheDir string `json:"local-mod-cache-dir" yaml:"local-mod-cache-dir" mapstructure:"local-mod-cache-dir"`
}
func (cfg golang) loadDefaultValues(v *viper.Viper) {
v.SetDefault("golang.search-local-mod-cache-licenses", false)
v.SetDefault("golang.local-mod-cache-dir", "")
}
+7
View File
@@ -0,0 +1,7 @@
# same as --file; write output report to a file (default is to write to stdout)
file: "test-explicit-config"
package:
cataloger:
scope: "squashed"
# same as --scope; limit the scope of the cataloger to only the specified types
@@ -0,0 +1,5 @@
# same as --file; write output report to a file (default is to write to stdout)
file: "test-dir-config"
package:
cataloger:
scope: "squashed"
@@ -0,0 +1,5 @@
# same as --file; write output report to a file (default is to write to stdout)
file: "test-home-config"
package:
cataloger:
scope: "squashed"
@@ -0,0 +1,5 @@
# same as --file; write output report to a file (default is to write to stdout)
file: "test-home-XDG-config"
package:
cataloger:
scope: "squashed"
@@ -0,0 +1,5 @@
# same as --file; write output report to a file (default is to write to stdout)
file: "test-wd-named-config"
package:
cataloger:
scope: "squashed"
+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 = "6.2.0"
JSONSchemaVersion = "7.0.1"
)
+1 -4
View File
@@ -161,10 +161,7 @@ func UnzipToDir(archivePath, targetDir string) error {
return err
}
if err = extractSingleFile(file, joinedPath, archivePath); err != nil {
return err
}
return nil
return extractSingleFile(file, joinedPath, archivePath)
}
return TraverseFilesInZip(archivePath, visitor)
-2
View File
@@ -146,9 +146,7 @@ func findArchiveStartOffset(r io.ReaderAt, size int64) (startOfArchive uint64, e
if err != nil {
return 0, err
}
startOfArchive = 0 // Prefixed data not supported
}
startOfArchive = uint64(directoryEndOffset) - d.directorySize - d.directoryOffset
// Make sure directoryOffset points to somewhere in our file.
+53
View File
@@ -0,0 +1,53 @@
package licenses
import "github.com/anchore/syft/internal"
// all of these taken from https://github.com/golang/pkgsite/blob/8996ff632abee854aef1b764ca0501f262f8f523/internal/licenses/licenses.go#L338
// which unfortunately is not exported. But fortunately is under BSD-style license.
var (
FileNames = []string{
"COPYING",
"COPYING.md",
"COPYING.markdown",
"COPYING.txt",
"LICENCE",
"LICENCE.md",
"LICENCE.markdown",
"LICENCE.txt",
"LICENSE",
"LICENSE.md",
"LICENSE.markdown",
"LICENSE.txt",
"LICENSE-2.0.txt",
"LICENCE-2.0.txt",
"LICENSE-APACHE",
"LICENCE-APACHE",
"LICENSE-APACHE-2.0.txt",
"LICENCE-APACHE-2.0.txt",
"LICENSE-MIT",
"LICENCE-MIT",
"LICENSE.MIT",
"LICENCE.MIT",
"LICENSE.code",
"LICENCE.code",
"LICENSE.docs",
"LICENCE.docs",
"LICENSE.rst",
"LICENCE.rst",
"MIT-LICENSE",
"MIT-LICENCE",
"MIT-LICENSE.md",
"MIT-LICENCE.md",
"MIT-LICENSE.markdown",
"MIT-LICENCE.markdown",
"MIT-LICENSE.txt",
"MIT-LICENCE.txt",
"MIT_LICENSE",
"MIT_LICENCE",
"UNLICENSE",
"UNLICENCE",
}
FileNameSet = internal.NewStringSet(FileNames...)
)
+33
View File
@@ -0,0 +1,33 @@
package licenses
import (
"io"
"github.com/google/licensecheck"
"golang.org/x/exp/slices"
)
const (
coverageThreshold = 75
unknownLicenseType = "UNKNOWN"
)
// Parse scans the contents of a license file to attempt to determine the type of license it is
func Parse(reader io.Reader) (licenses []string, err error) {
contents, err := io.ReadAll(reader)
if err != nil {
return nil, err
}
cov := licensecheck.Scan(contents)
if cov.Percent < float64(coverageThreshold) {
licenses = append(licenses, unknownLicenseType)
}
for _, m := range cov.Match {
if slices.Contains(licenses, m.ID) {
continue
}
licenses = append(licenses, m.ID)
}
return
}
@@ -11,8 +11,6 @@ import (
"strings"
"text/template"
"time"
"github.com/scylladb/go-set/strset"
)
// This program generates license_list.go.
@@ -35,7 +33,7 @@ var licenseIDs = map[string]string{
}
`))
var versionMatch = regexp.MustCompile(`-([0-9]+)\.?([0-9]+)?\.?([0-9]+)?\.?`)
var versionMatch = regexp.MustCompile(`([0-9]+)\.?([0-9]+)?\.?([0-9]+)?\.?`)
func main() {
if err := run(); err != nil {
@@ -49,7 +47,6 @@ func run() error {
if err != nil {
return fmt.Errorf("unable to get licenses list: %w", err)
}
var result LicenseList
if err = json.NewDecoder(resp.Body).Decode(&result); err != nil {
return fmt.Errorf("unable to decode license list: %w", err)
@@ -103,58 +100,59 @@ func run() error {
// The third pass is for overwriting deprecated licenses with replacements, for example GPL-2.0+ is deprecated
// and now maps to GPL-2.0-or-later.
func processSPDXLicense(result LicenseList) map[string]string {
// first pass build map
var licenseIDs = make(map[string]string)
for _, l := range result.Licenses {
cleanID := strings.ToLower(l.ID)
if _, exists := licenseIDs[cleanID]; exists {
log.Fatalf("duplicate license ID found: %q", cleanID)
}
licenseIDs[cleanID] = l.ID
}
// The order of variations/permutations of a license ID matters because of we how shuffle its digits,
// that is because the permutation code can generate the same value for two difference licenses,
// for example: The licenses `ABC-1.0` and `ABC-1.1` can both map to `ABC-1`,
// so we need to guarantee the order they are created to avoid mapping them wrongly. So we use a sorted list.
// To overwrite deprecated licenses during the first pass we would later on rely on map order,
// [which in go is not consistent by design](https://stackoverflow.com/a/55925880).
// The order of variations/permutations of a license ID matter.
// The permutation code can generate the same value for two difference licenses,
// for example: The licenses `ABC-1.0` and `ABC-1.1` can both map to `ABC1`,
// we need to guarantee the order they are created to avoid mapping them incorrectly.
// To do this we use a sorted list.
sort.Slice(result.Licenses, func(i, j int) bool {
return result.Licenses[i].ID < result.Licenses[j].ID
})
// second pass to build exceptions and replacements
replaced := strset.New()
// keys are simplified by removing dashes and lowercasing ID
// this is so license declarations in the wild like: LGPL3 LGPL-3 lgpl3 and lgpl-3 can all match
licenseIDs := make(map[string]string)
for _, l := range result.Licenses {
var multipleID []string
cleanID := strings.ToLower(l.ID)
// licensePerms includes the cleanID in return slice
cleanID := cleanLicenseID(l.ID)
licensePerms := buildLicenseIDPermutations(cleanID)
var replacement *License
// if license is deprecated, find its replacement and add to licenseIDs
if l.Deprecated {
replacement = result.findReplacementLicense(l)
idToMap := l.ID
replacement := result.findReplacementLicense(l)
if replacement != nil {
licenseIDs[cleanID] = replacement.ID
idToMap = replacement.ID
}
// it's important to use the original licensePerms here so that the deprecated license
// can now point to the new correct license
for _, id := range licensePerms {
if _, exists := licenseIDs[id]; exists {
// can be used to debug duplicate license permutations and confirm that examples like GPL1
// do not point to GPL-1.1
// log.Println("duplicate license list permutation found when mapping deprecated license to replacement")
// log.Printf("already have key: %q for SPDX ID: %q; attempted to map replacement ID: %q for deprecated ID: %q\n", id, value, replacement.ID, l.ID)
continue
}
licenseIDs[id] = idToMap
}
}
multipleID = append(multipleID, buildLicensePermutations(cleanID)...)
for _, id := range multipleID {
// don't make replacements for IDs that have already been replaced. Since we have a sorted license list
// the earliest replacement is correct (any future replacements are not.
// e.g. replace lgpl-2 with LGPL-2.1-only is wrong, but with LGPL-2.0-only is correct)
if replacement == nil || replaced.Has(id) {
if _, exists := licenseIDs[id]; !exists {
licenseIDs[id] = l.ID
}
} else {
// a useful debugging line during builds
log.Printf("replacing %s with %s\n", id, replacement.ID)
licenseIDs[id] = replacement.ID
replaced.Add(id)
// if license is not deprecated, add all permutations to licenseIDs
for _, id := range licensePerms {
if _, exists := licenseIDs[id]; exists {
// log.Println("found duplicate license permutation key for non deprecated license")
// log.Printf("already have key: %q for SPDX ID: %q; tried to insert as SPDX ID:%q\n", id, value, l.ID)
continue
}
licenseIDs[id] = l.ID
}
}
return licenseIDs
}
func cleanLicenseID(id string) string {
cleanID := strings.ToLower(id)
return strings.ReplaceAll(cleanID, "-", "")
}
File diff suppressed because it is too large Load Diff
+55 -53
View File
@@ -20,51 +20,7 @@ type License struct {
SeeAlso []string `json:"seeAlso"`
}
func (l License) canReplace(other License) bool {
if l.Deprecated {
return false
}
// We want to replace deprecated licenses with non-deprecated counterparts
// For more information, see: https://github.com/spdx/license-list-XML/issues/1676
if other.Deprecated {
switch {
case strings.ReplaceAll(l.ID, "-only", "") == other.ID:
return true
case strings.ReplaceAll(l.ID, "-or-later", "+") == other.ID:
return true
case l.ID == "BSD-2-Clause" && other.ID == "BSD-2-Clause-NetBSD":
return true
case l.ID == "BSD-2-Clause-Views" && other.ID == "BSD-2-Clause-FreeBSD":
return true
case l.ID == "bzip2-1.0.6" && other.ID == "bzip2-1.0.5":
return true
case l.ID == "SMLNJ" && other.ID == "StandardML-NJ":
return true
}
}
if l.Name != other.Name {
return false
}
if l.OSIApproved != other.OSIApproved {
return false
}
if len(l.SeeAlso) != len(other.SeeAlso) {
return false
}
for i, sa := range l.SeeAlso {
if sa != other.SeeAlso[i] {
return false
}
}
return l.ID == other.ID
}
// findReplacementLicense returns a replacement license for a deprecated license
func (ll LicenseList) findReplacementLicense(deprecated License) *License {
for _, l := range ll.Licenses {
if l.canReplace(deprecated) {
@@ -75,16 +31,62 @@ func (ll LicenseList) findReplacementLicense(deprecated License) *License {
return nil
}
func buildLicensePermutations(license string) (perms []string) {
lv := findLicenseVersion(license)
vp := versionPermutations(lv)
version := strings.Join(lv, ".")
for _, p := range vp {
perms = append(perms, strings.Replace(license, version, p, 1))
func (l License) canReplace(deprecated License) bool {
// don't replace a license with a deprecated license
if l.Deprecated {
return false
}
return perms
// We want to replace deprecated licenses with non-deprecated counterparts
// For more information, see: https://github.com/spdx/license-list-XML/issues/1676
switch {
case strings.ReplaceAll(l.ID, "-only", "") == deprecated.ID:
return true
case strings.ReplaceAll(l.ID, "-or-later", "+") == deprecated.ID:
return true
case l.ID == "BSD-2-Clause" && deprecated.ID == "BSD-2-Clause-NetBSD":
return true
case l.ID == "BSD-2-Clause-Views" && deprecated.ID == "BSD-2-Clause-FreeBSD":
return true
case l.ID == "bzip2-1.0.6" && deprecated.ID == "bzip2-1.0.5":
return true
case l.ID == "SMLNJ" && deprecated.ID == "StandardML-NJ":
return true
}
if l.Name != deprecated.Name {
return false
}
if l.OSIApproved != deprecated.OSIApproved {
return false
}
if len(l.SeeAlso) != len(deprecated.SeeAlso) {
return false
}
for i, sa := range l.SeeAlso {
if sa != deprecated.SeeAlso[i] {
return false
}
}
return l.ID == deprecated.ID
}
func buildLicenseIDPermutations(cleanID string) (perms []string) {
lv := findLicenseVersion(cleanID)
vp := versionPermutations(lv)
permSet := strset.New()
version := strings.Join(lv, ".")
for _, p := range vp {
permSet.Add(strings.Replace(cleanID, version, p, 1))
}
permSet.Add(cleanID)
return permSet.List()
}
func findLicenseVersion(license string) (version []string) {
+20 -23
View File
@@ -67,56 +67,57 @@ func TestLicensePermutations(t *testing.T) {
{
"GPL-1-only",
[]string{
"GPL-1-only",
"GPL-1.0-only",
"GPL-1.0.0-only",
"gpl1only",
"gpl1.0only",
"gpl1.0.0only",
},
},
{
"GPL-2",
[]string{
"GPL-2",
"GPL-2.0",
"GPL-2.0.0",
"gpl2",
"gpl2.0",
"gpl2.0.0",
},
},
{
"GPL-2.0+",
[]string{
"GPL-2+",
"GPL-2.0+",
"GPL-2.0.0+",
"gpl2+",
"gpl2.0+",
"gpl2.0.0+",
},
},
{
"GPL-3.0.0-or-later",
[]string{
"GPL-3-or-later",
"GPL-3.0-or-later",
"GPL-3.0.0-or-later",
"gpl3orlater",
"gpl3.0orlater",
"gpl3.0.0orlater",
},
},
{
"abc-1.1",
[]string{
"abc-1",
"abc-1.1",
"abc-1.1.0",
"abc1",
"abc1.1",
"abc1.1.0",
},
},
{
"oldap-2.0",
[]string{
"oldap-2",
"oldap-2.0",
"oldap-2.0.0",
"oldap2",
"oldap2.0",
"oldap2.0.0",
},
},
}
for _, test := range tests {
t.Run(test.shortName, func(t *testing.T) {
perms := buildLicensePermutations(test.shortName)
cleanID := cleanLicenseID(test.shortName)
perms := buildLicenseIDPermutations(cleanID)
assert.ElementsMatch(t, test.permutations, perms)
})
}
@@ -183,10 +184,6 @@ func TestFindLicenseVersion(t *testing.T) {
"GPL-2",
[]string{"2"},
},
{
"bzip2-1",
[]string{"1"},
},
{
"php-3.01",
[]string{"3", "01"},
File diff suppressed because it is too large Load Diff
+20 -3
View File
@@ -12,9 +12,26 @@ import (
// EX: gpl-2.0.0-only ---> GPL-2.0-only
// See the debian link for more details on the spdx license differences
const (
LicenseRefPrefix = "LicenseRef-" // prefix for non-standard licenses
)
//go:generate go run ./generate
func ID(id string) (string, bool) {
value, exists := licenseIDs[strings.ToLower(id)]
return value, exists
// ID returns the canonical license ID for the given license ID
// Note: this function is only concerned with returning a best match of an SPDX license ID
// SPDX Expressions will be handled by a parent package which will call this function
func ID(id string) (value string, exists bool) {
// first look for a canonical license
if value, exists := licenseIDs[cleanLicenseID(id)]; exists {
return value, exists
}
// we did not find, so treat it as a separate license
return "", false
}
func cleanLicenseID(id string) string {
id = strings.TrimSpace(id)
id = strings.ToLower(id)
return strings.ReplaceAll(id, "-", "")
}
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -9,8 +9,8 @@ import (
func TestLicenceListIDs(t *testing.T) {
// do a sanity check on the generated data
assert.Equal(t, "0BSD", licenseIDs["0bsd"])
assert.Equal(t, "ZPL-2.1", licenseIDs["zpl-2.1"])
assert.Equal(t, "GPL-2.0-only", licenseIDs["gpl-2"])
assert.Equal(t, "GPL-2.0-or-later", licenseIDs["gpl-2+"])
assert.Equal(t, "ZPL-2.1", licenseIDs["zpl2.1"])
assert.Equal(t, "GPL-2.0-only", licenseIDs["gpl2"])
assert.Equal(t, "GPL-2.0-or-later", licenseIDs["gpl2+"])
assert.NotEmpty(t, Version)
}
+34 -9
View File
@@ -6,55 +6,80 @@ import (
"github.com/stretchr/testify/assert"
)
func TestIDParse(t *testing.T) {
func TestSPDXIDRecognition(t *testing.T) {
var tests = []struct {
shortName string
spdx string
id string
found bool
}{
{
"GPL-1-only",
"GPL-1.0-only",
true,
},
{
"gpl1",
"GPL-1.0-only",
true,
},
{
"gpl-1",
"GPL-1.0-only",
true,
},
{
"GPL-2",
"GPL-2.0-only",
true,
},
{
"GPL-2+",
"GPL-2.0-or-later",
true,
},
{
"GPL-3.0.0-or-later",
"GPL-3.0-or-later",
true,
},
{
"GPL-3-with-autoconf-exception",
"GPL-3.0-with-autoconf-exception",
true,
},
{
"CC-by-nc-3-de",
"CC-BY-NC-3.0-DE",
true,
},
// the below few cases are NOT expected, however, seem unavoidable given the current approach
{
"w3c-20150513.0.0",
"W3C-20150513",
},
{
"spencer-86.0.0",
"Spencer-86",
true,
},
{
"unicode-dfs-2015.0.0",
"Unicode-DFS-2015",
true,
},
{
"Unknown",
"",
false,
},
{
" ",
"",
false,
},
}
for _, test := range tests {
t.Run(test.shortName, func(t *testing.T) {
got, exists := ID(test.shortName)
assert.True(t, exists)
assert.Equal(t, test.spdx, got)
value, exists := ID(test.shortName)
assert.Equal(t, test.found, exists)
assert.Equal(t, test.id, value)
})
}
}
+7
View File
@@ -28,3 +28,10 @@ func StringInSlice(a string, list []string) bool {
}
return false
}
func SplitAny(s string, seps string) []string {
splitter := func(r rune) bool {
return strings.ContainsRune(seps, r)
}
return strings.FieldsFunc(s, splitter)
}
+34
View File
@@ -104,3 +104,37 @@ func TestTruncateMiddleEllipsis(t *testing.T) {
})
}
}
func TestSplitAny(t *testing.T) {
tests := []struct {
name string
input string
fields string
want []string
}{
{
name: "simple",
input: "a,b,c",
fields: ",",
want: []string{"a", "b", "c"},
},
{
name: "empty",
input: "",
fields: ",",
want: []string{},
},
{
name: "multiple separators",
input: "a,b\nc:d",
fields: ",:\n",
want: []string{"a", "b", "c", "d"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, SplitAny(tt.input, tt.fields))
})
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -106,9 +106,8 @@ func stripSlashes(s string) string {
for i, c := range s {
if c == '\\' && i+1 < len(s) && strings.ContainsRune(allowedCPEPunctuation, rune(s[i+1])) {
continue
} else {
sb.WriteRune(c)
}
sb.WriteRune(c)
}
return sb.String()
}
+2 -1
View File
@@ -1,6 +1,7 @@
package file
import (
"github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/source"
)
@@ -20,7 +21,7 @@ func allRegularFiles(resolver source.FileResolver) (locations []source.Location)
continue
}
if metadata.Type != source.RegularFile {
if metadata.Type != file.TypeRegular {
continue
}
locations = append(locations, resolvedLocation)
+3 -2
View File
@@ -3,6 +3,7 @@ package file
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/scylladb/go-set/strset"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -69,8 +70,8 @@ func Test_allRegularFiles(t *testing.T) {
virtualLocations.Add(l.VirtualPath)
}
}
assert.ElementsMatch(t, tt.wantRealPaths.List(), realLocations.List(), "mismatched real paths")
assert.ElementsMatch(t, tt.wantVirtualPaths.List(), virtualLocations.List(), "mismatched virtual paths")
assert.ElementsMatch(t, tt.wantRealPaths.List(), realLocations.List(), "real paths differ: "+cmp.Diff(tt.wantRealPaths.List(), realLocations.List()))
assert.ElementsMatch(t, tt.wantVirtualPaths.List(), virtualLocations.List(), "virtual paths differ: "+cmp.Diff(tt.wantVirtualPaths.List(), virtualLocations.List()))
})
}
}
+5 -6
View File
@@ -11,6 +11,7 @@ import (
"github.com/wagoodman/go-partybus"
"github.com/wagoodman/go-progress"
"github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/bus"
"github.com/anchore/syft/internal/log"
@@ -50,10 +51,10 @@ func (i *DigestsCataloger) Catalog(resolver source.FileResolver) (map[source.Coo
if err != nil {
return nil, err
}
prog.N++
prog.Increment()
results[location.Coordinates] = result
}
log.Debugf("file digests cataloger processed %d files", prog.N)
log.Debugf("file digests cataloger processed %d files", prog.Current())
prog.SetCompleted()
return results, nil
}
@@ -65,7 +66,7 @@ func (i *DigestsCataloger) catalogLocation(resolver source.FileResolver, locatio
}
// we should only attempt to report digests for files that are regular files (don't attempt to resolve links)
if meta.Type != source.RegularFile {
if meta.Type != file.TypeRegular {
return nil, errUndigestableFile
}
@@ -122,9 +123,7 @@ func CleanDigestAlgorithmName(name string) string {
func digestsCatalogingProgress(locations int64) (*progress.Stage, *progress.Manual) {
stage := &progress.Stage{}
prog := &progress.Manual{
Total: locations,
}
prog := progress.NewManual(locations)
bus.Publish(partybus.Event{
Type: event.FileDigestsCatalogerStarted,
+1 -1
View File
@@ -146,7 +146,7 @@ func TestDigestsCataloger_MixFileTypes(t *testing.T) {
if err != nil {
t.Fatalf("unable to get file=%q : %+v", test.path, err)
}
l := source.NewLocationFromImage(test.path, *ref, img)
l := source.NewLocationFromImage(test.path, *ref.Reference, img)
if len(actual[l.Coordinates]) == 0 {
if test.expected != "" {
+3 -5
View File
@@ -32,18 +32,16 @@ func (i *MetadataCataloger) Catalog(resolver source.FileResolver) (map[source.Co
}
results[location.Coordinates] = metadata
prog.N++
prog.Increment()
}
log.Debugf("file metadata cataloger processed %d files", prog.N)
log.Debugf("file metadata cataloger processed %d files", prog.Current())
prog.SetCompleted()
return results, nil
}
func metadataCatalogingProgress(locations int64) (*progress.Stage, *progress.Manual) {
stage := &progress.Stage{}
prog := &progress.Manual{
Total: locations,
}
prog := progress.NewManual(locations)
bus.Publish(partybus.Event{
Type: event.FileMetadataCatalogerStarted,
+18 -11
View File
@@ -6,6 +6,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/stereoscope/pkg/imagetest"
@@ -50,8 +51,9 @@ func TestFileMetadataCataloger(t *testing.T) {
path: "/file-1.txt",
exists: true,
expected: source.FileMetadata{
Path: "/file-1.txt",
Mode: 0644,
Type: "RegularFile",
Type: file.TypeRegular,
UserID: 1,
GroupID: 2,
Size: 7,
@@ -62,8 +64,9 @@ func TestFileMetadataCataloger(t *testing.T) {
path: "/hardlink-1",
exists: true,
expected: source.FileMetadata{
Path: "/hardlink-1",
Mode: 0644,
Type: "HardLink",
Type: file.TypeHardLink,
LinkDestination: "file-1.txt",
UserID: 1,
GroupID: 2,
@@ -74,8 +77,9 @@ func TestFileMetadataCataloger(t *testing.T) {
path: "/symlink-1",
exists: true,
expected: source.FileMetadata{
Path: "/symlink-1",
Mode: 0777 | os.ModeSymlink,
Type: "SymbolicLink",
Type: file.TypeSymLink,
LinkDestination: "file-1.txt",
UserID: 0,
GroupID: 0,
@@ -86,8 +90,9 @@ func TestFileMetadataCataloger(t *testing.T) {
path: "/char-device-1",
exists: true,
expected: source.FileMetadata{
Path: "/char-device-1",
Mode: 0644 | os.ModeDevice | os.ModeCharDevice,
Type: "CharacterDevice",
Type: file.TypeCharacterDevice,
UserID: 0,
GroupID: 0,
MIMEType: "",
@@ -97,8 +102,9 @@ func TestFileMetadataCataloger(t *testing.T) {
path: "/block-device-1",
exists: true,
expected: source.FileMetadata{
Path: "/block-device-1",
Mode: 0644 | os.ModeDevice,
Type: "BlockDevice",
Type: file.TypeBlockDevice,
UserID: 0,
GroupID: 0,
MIMEType: "",
@@ -108,8 +114,9 @@ func TestFileMetadataCataloger(t *testing.T) {
path: "/fifo-1",
exists: true,
expected: source.FileMetadata{
Path: "/fifo-1",
Mode: 0644 | os.ModeNamedPipe,
Type: "FIFONode",
Type: file.TypeFIFO,
UserID: 0,
GroupID: 0,
MIMEType: "",
@@ -119,11 +126,13 @@ func TestFileMetadataCataloger(t *testing.T) {
path: "/bin",
exists: true,
expected: source.FileMetadata{
Path: "/bin",
Mode: 0755 | os.ModeDir,
Type: "Directory",
Type: file.TypeDirectory,
UserID: 0,
GroupID: 0,
MIMEType: "",
IsDir: true,
},
},
}
@@ -131,11 +140,9 @@ func TestFileMetadataCataloger(t *testing.T) {
for _, test := range tests {
t.Run(test.path, func(t *testing.T) {
_, ref, err := img.SquashedTree().File(file.Path(test.path))
if err != nil {
t.Fatalf("unable to get file: %+v", err)
}
require.NoError(t, err)
l := source.NewLocationFromImage(test.path, *ref, img)
l := source.NewLocationFromImage(test.path, *ref.Reference, img)
assert.Equal(t, test.expected, actual[l.Coordinates], "mismatched metadata")
+4 -6
View File
@@ -55,12 +55,12 @@ func (i *SecretsCataloger) Catalog(resolver source.FileResolver) (map[source.Coo
return nil, err
}
if len(result) > 0 {
secretsDiscovered.N += int64(len(result))
secretsDiscovered.Add(int64(len(result)))
results[location.Coordinates] = result
}
prog.N++
prog.Increment()
}
log.Debugf("secrets cataloger discovered %d secrets", secretsDiscovered.N)
log.Debugf("secrets cataloger discovered %d secrets", secretsDiscovered.Current())
prog.SetCompleted()
return results, nil
}
@@ -139,9 +139,7 @@ type SecretsMonitor struct {
func secretsCatalogingProgress(locations int64) (*progress.Stage, *progress.Manual, *progress.Manual) {
stage := &progress.Stage{}
secretsDiscovered := &progress.Manual{}
prog := &progress.Manual{
Total: locations,
}
prog := progress.NewManual(locations)
bus.Publish(partybus.Event{
Type: event.SecretsCatalogerStarted,
+2 -2
View File
@@ -30,12 +30,12 @@ const (
// TODO: deprecated, moved to syft/formats/formats.go. will be removed in v1.0.0
func FormatIDs() (ids []sbom.FormatID) {
return formats.IDs()
return formats.AllIDs()
}
// TODO: deprecated, moved to syft/formats/formats.go. will be removed in v1.0.0
func FormatByID(id sbom.FormatID) sbom.Format {
return formats.ByID(id)
return formats.ByNameAndVersion(string(id), "")
}
// TODO: deprecated, moved to syft/formats/formats.go. will be removed in v1.0.0
@@ -16,7 +16,15 @@ func encodeLicenses(p pkg.Package) *cyclonedx.Licenses {
ID: value,
},
})
continue
}
// not found so append the licenseName as is
lc = append(lc, cyclonedx.LicenseChoice{
License: &cyclonedx.License{
Name: licenseName,
},
})
}
if len(lc) > 0 {
return &lc
@@ -28,7 +36,16 @@ func decodeLicenses(c *cyclonedx.Component) (out []string) {
if c.Licenses != nil {
for _, l := range *c.Licenses {
if l.License != nil {
out = append(out, l.License.ID)
var lic string
switch {
case l.License.ID != "":
lic = l.License.ID
case l.License.Name != "":
lic = l.License.Name
default:
continue
}
out = append(out, lic)
}
}
}
@@ -27,7 +27,9 @@ func Test_encodeLicense(t *testing.T) {
"made-up",
},
},
expected: nil,
expected: &cyclonedx.Licenses{
{License: &cyclonedx.License{Name: "made-up"}},
},
},
{
name: "with SPDX license",
+18 -4
View File
@@ -22,10 +22,11 @@ func License(p pkg.Package) string {
}
// take all licenses and assume an AND expression; for information about license expressions see https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/
var parsedLicenses []string
for _, l := range p.Licenses {
if value, exists := spdxlicense.ID(l); exists {
parsedLicenses = append(parsedLicenses, value)
parsedLicenses := parseLicenses(p.Licenses)
for i, v := range parsedLicenses {
if strings.HasPrefix(v, spdxlicense.LicenseRefPrefix) {
parsedLicenses[i] = SanitizeElementID(v)
}
}
@@ -35,3 +36,16 @@ func License(p pkg.Package) string {
return strings.Join(parsedLicenses, " AND ")
}
func parseLicenses(raw []string) (parsedLicenses []string) {
for _, l := range raw {
if value, exists := spdxlicense.ID(l); exists {
parsedLicenses = append(parsedLicenses, value)
} else {
// we did not find a valid SPDX license ID so treat as separate license
otherLicense := spdxlicense.LicenseRefPrefix + l
parsedLicenses = append(parsedLicenses, otherLicense)
}
}
return
}
@@ -26,7 +26,7 @@ func Test_License(t *testing.T) {
"made-up",
},
},
expected: NOASSERTION,
expected: "LicenseRef-made-up",
},
{
name: "with SPDX license",
@@ -65,6 +65,17 @@ func Test_License(t *testing.T) {
},
expected: "GPL-2.0-only",
},
{
name: "includes valid LicenseRef-",
input: pkg.Package{
Licenses: []string{
"one thing first",
"two things/#$^second",
"MIT",
},
},
expected: "LicenseRef-one-thing-first AND LicenseRef-two-things----second AND MIT",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
@@ -8,8 +8,9 @@ import (
"strings"
"time"
"github.com/spdx/tools-golang/spdx/common"
spdx "github.com/spdx/tools-golang/spdx/v2_3"
"github.com/spdx/tools-golang/spdx"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log"
@@ -23,7 +24,6 @@ import (
)
const (
spdxVersion = "SPDX-2.3"
noAssertion = "NOASSERTION"
)
@@ -40,11 +40,11 @@ func ToFormatModel(s sbom.SBOM) *spdx.Document {
// for the primary package purpose field:
// https://spdx.github.io/spdx-spec/v2.3/package-information/#724-primary-package-purpose-field
documentDescribesRelationship := &spdx.Relationship{
RefA: common.DocElementID{
RefA: spdx.DocElementID{
ElementRefID: "DOCUMENT",
},
Relationship: string(DescribesRelationship),
RefB: common.DocElementID{
RefB: spdx.DocElementID{
ElementRefID: "DOCUMENT",
},
RelationshipComment: "",
@@ -55,11 +55,11 @@ func ToFormatModel(s sbom.SBOM) *spdx.Document {
return &spdx.Document{
// 6.1: SPDX Version; should be in the format "SPDX-x.x"
// Cardinality: mandatory, one
SPDXVersion: spdxVersion,
SPDXVersion: spdx.Version,
// 6.2: Data License; should be "CC0-1.0"
// Cardinality: mandatory, one
DataLicense: "CC0-1.0",
DataLicense: spdx.DataLicense,
// 6.3: SPDX Identifier; should be "DOCUMENT" to represent mandatory identifier of SPDXRef-DOCUMENT
// Cardinality: mandatory, one
@@ -104,7 +104,7 @@ func ToFormatModel(s sbom.SBOM) *spdx.Document {
// 6.8: Creators: may have multiple keys for Person, Organization
// and/or Tool
// Cardinality: mandatory, one or many
Creators: []common.Creator{
Creators: []spdx.Creator{
{
Creator: "Anchore, Inc",
CreatorType: "Organization",
@@ -126,10 +126,11 @@ func ToFormatModel(s sbom.SBOM) *spdx.Document {
Packages: toPackages(s.Artifacts.PackageCatalog, s),
Files: toFiles(s),
Relationships: relationships,
OtherLicenses: toOtherLicenses(s.Artifacts.PackageCatalog),
}
}
func toSPDXID(identifiable artifact.Identifiable) common.ElementID {
func toSPDXID(identifiable artifact.Identifiable) spdx.ElementID {
id := ""
if p, ok := identifiable.(pkg.Package); ok {
id = SanitizeElementID(fmt.Sprintf("Package-%+v-%s-%s", p.Type, p.Name, p.ID()))
@@ -137,7 +138,7 @@ func toSPDXID(identifiable artifact.Identifiable) common.ElementID {
id = string(identifiable.ID())
}
// NOTE: the spdx libraries prepend SPDXRef-, so we don't do it here
return common.ElementID(id)
return spdx.ElementID(id)
}
// packages populates all Package Information from the package Catalog (see https://spdx.github.io/spdx-spec/3-package-information/)
@@ -313,9 +314,9 @@ func toPackages(catalog *pkg.Catalog, sbom sbom.SBOM) (results []*spdx.Package)
return results
}
func toPackageChecksums(p pkg.Package) ([]common.Checksum, bool) {
func toPackageChecksums(p pkg.Package) ([]spdx.Checksum, bool) {
filesAnalyzed := false
var checksums []common.Checksum
var checksums []spdx.Checksum
switch meta := p.Metadata.(type) {
// we generate digest for some Java packages
// spdx.github.io/spdx-spec/package-information/#710-package-checksum-field
@@ -325,8 +326,8 @@ func toPackageChecksums(p pkg.Package) ([]common.Checksum, bool) {
filesAnalyzed = true
for _, digest := range meta.ArchiveDigests {
algo := strings.ToUpper(digest.Algorithm)
checksums = append(checksums, common.Checksum{
Algorithm: common.ChecksumAlgorithm(algo),
checksums = append(checksums, spdx.Checksum{
Algorithm: spdx.ChecksumAlgorithm(algo),
Value: digest.Value,
})
}
@@ -339,20 +340,20 @@ func toPackageChecksums(p pkg.Package) ([]common.Checksum, bool) {
break
}
algo = strings.ToUpper(algo)
checksums = append(checksums, common.Checksum{
Algorithm: common.ChecksumAlgorithm(algo),
checksums = append(checksums, spdx.Checksum{
Algorithm: spdx.ChecksumAlgorithm(algo),
Value: hexStr,
})
}
return checksums, filesAnalyzed
}
func toPackageOriginator(p pkg.Package) *common.Originator {
func toPackageOriginator(p pkg.Package) *spdx.Originator {
kind, originator := Originator(p)
if kind == "" || originator == "" {
return nil
}
return &common.Originator{
return &spdx.Originator{
Originator: originator,
OriginatorType: kind,
}
@@ -386,11 +387,11 @@ func toRelationships(relationships []artifact.Relationship) (result []*spdx.Rela
}
result = append(result, &spdx.Relationship{
RefA: common.DocElementID{
RefA: spdx.DocElementID{
ElementRefID: toSPDXID(r.From),
},
Relationship: string(relationshipType),
RefB: common.DocElementID{
RefB: spdx.DocElementID{
ElementRefID: toSPDXID(r.To),
},
RelationshipComment: comment,
@@ -462,10 +463,10 @@ func toFiles(s sbom.SBOM) (results []*spdx.File) {
return results
}
func toFileChecksums(digests []file.Digest) (checksums []common.Checksum) {
checksums = make([]common.Checksum, 0, len(digests))
func toFileChecksums(digests []file.Digest) (checksums []spdx.Checksum) {
checksums = make([]spdx.Checksum, 0, len(digests))
for _, digest := range digests {
checksums = append(checksums, common.Checksum{
checksums = append(checksums, spdx.Checksum{
Algorithm: toChecksumAlgorithm(digest.Algorithm),
Value: digest.Value,
})
@@ -473,9 +474,9 @@ func toFileChecksums(digests []file.Digest) (checksums []common.Checksum) {
return checksums
}
func toChecksumAlgorithm(algorithm string) common.ChecksumAlgorithm {
func toChecksumAlgorithm(algorithm string) spdx.ChecksumAlgorithm {
// this needs to be an uppercase version of our algorithm
return common.ChecksumAlgorithm(strings.ToUpper(algorithm))
return spdx.ChecksumAlgorithm(strings.ToUpper(algorithm))
}
func toFileTypes(metadata *source.FileMetadata) (ty []string) {
@@ -513,11 +514,37 @@ func toFileTypes(metadata *source.FileMetadata) (ty []string) {
return ty
}
func toOtherLicenses(catalog *pkg.Catalog) []*spdx.OtherLicense {
licenses := map[string]bool{}
for _, p := range catalog.Sorted() {
for _, license := range parseLicenses(p.Licenses) {
if strings.HasPrefix(license, spdxlicense.LicenseRefPrefix) {
licenses[license] = true
}
}
}
var result []*spdx.OtherLicense
sorted := maps.Keys(licenses)
slices.Sort(sorted)
for _, license := range sorted {
// separate the actual ID from the prefix
name := strings.TrimPrefix(license, spdxlicense.LicenseRefPrefix)
result = append(result, &spdx.OtherLicense{
LicenseIdentifier: SanitizeElementID(license),
LicenseName: name,
ExtractedText: NONE, // we probably should have some extracted text here, but this is good enough for now
})
}
return result
}
// TODO: handle SPDX excludes file case
// f file is an "excludes" file, skip it /* exclude SPDX analysis file(s) */
// see: https://spdx.github.io/spdx-spec/v2.3/package-information/#79-package-verification-code-field
// the above link contains the SPDX algorithm for a package verification code
func newPackageVerificationCode(p pkg.Package, sbom sbom.SBOM) *common.PackageVerificationCode {
func newPackageVerificationCode(p pkg.Package, sbom sbom.SBOM) *spdx.PackageVerificationCode {
// key off of the contains relationship;
// spdx validator will fail if a package claims to contain a file but no sha1 provided
// if a sha1 for a file is provided then the validator will fail if the package does not have
@@ -558,7 +585,7 @@ func newPackageVerificationCode(p pkg.Package, sbom sbom.SBOM) *common.PackageVe
//nolint:gosec
hasher := sha1.New()
_, _ = hasher.Write([]byte(b.String()))
return &common.PackageVerificationCode{
return &spdx.PackageVerificationCode{
// 7.9.1: Package Verification Code Value
// Cardinality: mandatory, one
Value: fmt.Sprintf("%+x", hasher.Sum(nil)),
@@ -4,8 +4,7 @@ import (
"fmt"
"testing"
"github.com/spdx/tools-golang/spdx/common"
spdx "github.com/spdx/tools-golang/spdx/v2_3"
"github.com/spdx/tools-golang/spdx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -21,7 +20,7 @@ func Test_toPackageChecksums(t *testing.T) {
tests := []struct {
name string
pkg pkg.Package
expected []common.Checksum
expected []spdx.Checksum
filesAnalyzed bool
}{
{
@@ -39,7 +38,7 @@ func Test_toPackageChecksums(t *testing.T) {
},
},
},
expected: []common.Checksum{
expected: []spdx.Checksum{
{
Algorithm: "SHA1",
Value: "1234",
@@ -57,7 +56,7 @@ func Test_toPackageChecksums(t *testing.T) {
ArchiveDigests: []file.Digest{},
},
},
expected: []common.Checksum{},
expected: []spdx.Checksum{},
filesAnalyzed: false,
},
{
@@ -67,7 +66,7 @@ func Test_toPackageChecksums(t *testing.T) {
Version: "1.0.0",
Language: pkg.Java,
},
expected: []common.Checksum{},
expected: []spdx.Checksum{},
filesAnalyzed: false,
},
{
@@ -81,7 +80,7 @@ func Test_toPackageChecksums(t *testing.T) {
H1Digest: "h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=",
},
},
expected: []common.Checksum{
expected: []spdx.Checksum{
{
Algorithm: "SHA256",
Value: "f5f1c0b4ad2e0dfa6f79eaaaa3586411925c16f61702208ddd4bad2fc17dc47c",
@@ -97,7 +96,7 @@ func Test_toPackageChecksums(t *testing.T) {
Language: pkg.Java,
Metadata: struct{}{},
},
expected: []common.Checksum{},
expected: []spdx.Checksum{},
filesAnalyzed: false,
},
}
@@ -229,7 +228,7 @@ func Test_toFileChecksums(t *testing.T) {
tests := []struct {
name string
digests []file.Digest
expected []common.Checksum
expected []spdx.Checksum
}{
{
name: "empty",
@@ -246,7 +245,7 @@ func Test_toFileChecksums(t *testing.T) {
Value: "meh",
},
},
expected: []common.Checksum{
expected: []spdx.Checksum{
{
Algorithm: "SHA256",
Value: "deadbeefcafe",
@@ -275,8 +274,8 @@ func Test_fileIDsForPackage(t *testing.T) {
FileSystemID: "nowhere",
}
docElementId := func(identifiable artifact.Identifiable) common.DocElementID {
return common.DocElementID{
docElementId := func(identifiable artifact.Identifiable) spdx.DocElementID {
return spdx.DocElementID{
ElementRefID: toSPDXID(identifiable),
}
}
@@ -370,7 +369,7 @@ func Test_fileIDsForPackage(t *testing.T) {
}
func Test_H1Digest(t *testing.T) {
sbom := sbom.SBOM{}
s := sbom.SBOM{}
tests := []struct {
name string
pkg pkg.Package
@@ -417,7 +416,7 @@ func Test_H1Digest(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
catalog := pkg.NewCatalog(test.pkg)
pkgs := toPackages(catalog, sbom)
pkgs := toPackages(catalog, s)
require.Len(t, pkgs, 1)
for _, p := range pkgs {
if test.expectedDigest == "" {
@@ -432,3 +431,67 @@ func Test_H1Digest(t *testing.T) {
})
}
}
func Test_OtherLicenses(t *testing.T) {
tests := []struct {
name string
pkg pkg.Package
expected []*spdx.OtherLicense
}{
{
name: "no licenseRef",
pkg: pkg.Package{
Licenses: []string{
"MIT",
},
},
expected: nil,
},
{
name: "single licenseRef",
pkg: pkg.Package{
Licenses: []string{
"un known",
},
},
expected: []*spdx.OtherLicense{
{
LicenseIdentifier: "LicenseRef-un-known",
LicenseName: "un known",
ExtractedText: NONE,
},
},
},
{
name: "multiple licenseRef",
pkg: pkg.Package{
Licenses: []string{
"un known",
"not known %s",
"MIT",
},
},
expected: []*spdx.OtherLicense{
{
LicenseIdentifier: "LicenseRef-not-known--s",
LicenseName: "not known %s",
ExtractedText: NONE,
},
{
LicenseIdentifier: "LicenseRef-un-known",
LicenseName: "un known",
ExtractedText: NONE,
},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
catalog := pkg.NewCatalog(test.pkg)
otherLicenses := toOtherLicenses(catalog)
require.Len(t, otherLicenses, len(test.expected))
require.Equal(t, test.expected, otherLicenses)
})
}
}
@@ -6,7 +6,7 @@ import (
"strconv"
"strings"
spdx "github.com/spdx/tools-golang/spdx/v2_3"
"github.com/spdx/tools-golang/spdx"
"github.com/anchore/packageurl-go"
"github.com/anchore/syft/internal/log"
@@ -3,8 +3,7 @@ package spdxhelpers
import (
"testing"
"github.com/spdx/tools-golang/spdx/common"
spdx "github.com/spdx/tools-golang/spdx/v2_3"
"github.com/spdx/tools-golang/spdx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -246,9 +245,9 @@ func TestH1Digest(t *testing.T) {
RefType: "purl",
},
},
PackageChecksums: []common.Checksum{
PackageChecksums: []spdx.Checksum{
{
Algorithm: common.SHA256,
Algorithm: spdx.SHA256,
Value: "f5f1c0b4ad2e0dfa6f79eaaaa3586411925c16f61702208ddd4bad2fc17dc47c",
},
},
@@ -267,9 +266,9 @@ func TestH1Digest(t *testing.T) {
RefType: "purl",
},
},
PackageChecksums: []common.Checksum{
PackageChecksums: []spdx.Checksum{
{
Algorithm: common.SHA1,
Algorithm: spdx.SHA1,
Value: "f5f1c0b4ad2e0dfa6f79eaaaa3586411925c16f61702208ddd4bad2fc17dc47c",
},
},
@@ -288,9 +287,9 @@ func TestH1Digest(t *testing.T) {
RefType: "purl",
},
},
PackageChecksums: []common.Checksum{
PackageChecksums: []spdx.Checksum{
{
Algorithm: common.SHA256,
Algorithm: spdx.SHA256,
Value: "",
},
},
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"regexp"
"testing"
"github.com/anchore/syft/syft/formats/common/testutils"
"github.com/anchore/syft/syft/formats/internal/testutils"
)
var updateCycloneDx = flag.Bool("update-cyclonedx", false, "update the *.golden files for cyclone-dx encoders")
+3 -2
View File
@@ -7,13 +7,14 @@ import (
"github.com/anchore/syft/syft/sbom"
)
const ID sbom.FormatID = "cyclonedx-1-json"
const ID sbom.FormatID = "cyclonedx-json"
func Format() sbom.Format {
return sbom.NewFormat(
ID,
sbom.AnyVersion,
encoder,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
ID,
)
}
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"regexp"
"testing"
"github.com/anchore/syft/syft/formats/common/testutils"
"github.com/anchore/syft/syft/formats/internal/testutils"
)
var updateCycloneDx = flag.Bool("update-cyclonedx", false, "update the *.golden files for cyclone-dx encoders")
+3 -2
View File
@@ -7,13 +7,14 @@ import (
"github.com/anchore/syft/syft/sbom"
)
const ID sbom.FormatID = "cyclonedx-1-xml"
const ID sbom.FormatID = "cyclonedx-xml"
func Format() sbom.Format {
return sbom.NewFormat(
ID,
sbom.AnyVersion,
encoder,
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
ID, "cyclonedx", "cyclone",
)
}
+52 -43
View File
@@ -5,8 +5,11 @@ import (
"errors"
"fmt"
"io"
"regexp"
"strings"
"golang.org/x/exp/slices"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/formats/cyclonedxjson"
"github.com/anchore/syft/syft/formats/cyclonedxxml"
@@ -26,8 +29,11 @@ func Formats() []sbom.Format {
cyclonedxxml.Format(),
cyclonedxjson.Format(),
github.Format(),
spdxtagvalue.Format(),
spdxjson.Format(),
spdxtagvalue.Format2_1(),
spdxtagvalue.Format2_2(),
spdxtagvalue.Format2_3(),
spdxjson.Format2_2(),
spdxjson.Format2_3(),
table.Format(),
text.Format(),
template.Format(),
@@ -38,7 +44,7 @@ func Identify(by []byte) sbom.Format {
for _, f := range Formats() {
if err := f.Validate(bytes.NewReader(by)); err != nil {
if !errors.Is(err, sbom.ErrValidationNotSupported) {
log.Debugf("format %s returned err: %+v", f.ID(), err)
log.WithFields("error", err).Tracef("format validation for %s failed", f.ID())
}
continue
}
@@ -47,53 +53,46 @@ func Identify(by []byte) sbom.Format {
return nil
}
// ByName accepts a name@version string, such as:
//
// spdx-json@2.1 or cyclonedx@2
func ByName(name string) sbom.Format {
cleanName := cleanFormatName(name)
for _, f := range Formats() {
if cleanFormatName(string(f.ID())) == cleanName {
return f
}
parts := strings.SplitN(name, "@", 2)
version := sbom.AnyVersion
if len(parts) > 1 {
version = parts[1]
}
// handle any aliases for any supported format
switch cleanName {
case "json", "syftjson":
return ByID(syftjson.ID)
case "cyclonedx", "cyclone", "cyclonedxxml":
return ByID(cyclonedxxml.ID)
case "cyclonedxjson":
return ByID(cyclonedxjson.ID)
case "github", "githubjson":
return ByID(github.ID)
case "spdx", "spdxtv", "spdxtagvalue":
return ByID(spdxtagvalue.ID)
case "spdxjson":
return ByID(spdxjson.ID)
case "table":
return ByID(table.ID)
case "text":
return ByID(text.ID)
case "template":
ByID(template.ID)
}
return nil
return ByNameAndVersion(parts[0], version)
}
func IDs() (ids []sbom.FormatID) {
func ByNameAndVersion(name string, version string) sbom.Format {
name = cleanFormatName(name)
var mostRecentFormat sbom.Format
for _, f := range Formats() {
ids = append(ids, f.ID())
}
return ids
}
func ByID(id sbom.FormatID) sbom.Format {
for _, f := range Formats() {
if f.ID() == id {
return f
for _, n := range f.IDs() {
if cleanFormatName(string(n)) == name && versionMatches(f.Version(), version) {
if mostRecentFormat == nil || f.Version() > mostRecentFormat.Version() {
mostRecentFormat = f
}
}
}
}
return nil
return mostRecentFormat
}
func versionMatches(version string, match string) bool {
if version == sbom.AnyVersion || match == sbom.AnyVersion {
return true
}
match = strings.ReplaceAll(match, ".", "\\.")
match = strings.ReplaceAll(match, "*", ".*")
match = fmt.Sprintf("^%s(\\..*)*$", match)
matcher, err := regexp.Compile(match)
if err != nil {
return false
}
return matcher.MatchString(version)
}
func cleanFormatName(name string) string {
@@ -127,3 +126,13 @@ func Decode(reader io.Reader) (*sbom.SBOM, sbom.Format, error) {
s, err := f.Decode(bytes.NewReader(by))
return s, f, err
}
func AllIDs() (ids []sbom.FormatID) {
for _, f := range Formats() {
if slices.Contains(ids, f.ID()) {
continue
}
ids = append(ids, f.ID())
}
return ids
}
+110 -19
View File
@@ -92,18 +92,6 @@ func TestByName(t *testing.T) {
name: "spdxtv", // clean variant
want: spdxtagvalue.ID,
},
{
name: "spdx-2-tag-value", // clean variant
want: spdxtagvalue.ID,
},
{
name: "spdx-2-tagvalue", // clean variant
want: spdxtagvalue.ID,
},
{
name: "spdx2-tagvalue", // clean variant
want: spdxtagvalue.ID,
},
// SPDX JSON
{
@@ -111,7 +99,7 @@ func TestByName(t *testing.T) {
want: spdxjson.ID,
},
{
name: "spdx-2-json",
name: "spdxjson", // clean variant
want: spdxjson.ID,
},
@@ -121,7 +109,7 @@ func TestByName(t *testing.T) {
want: cyclonedxjson.ID,
},
{
name: "cyclonedx-1-json",
name: "cyclonedxjson", // clean variant
want: cyclonedxjson.ID,
},
@@ -135,7 +123,7 @@ func TestByName(t *testing.T) {
want: cyclonedxxml.ID,
},
{
name: "cyclonedx-1-xml",
name: "cyclonedxxml", // clean variant
want: cyclonedxxml.ID,
},
@@ -144,7 +132,6 @@ func TestByName(t *testing.T) {
name: "table",
want: table.ID,
},
{
name: "syft-table",
want: table.ID,
@@ -155,7 +142,6 @@ func TestByName(t *testing.T) {
name: "text",
want: text.ID,
},
{
name: "syft-text",
want: text.ID,
@@ -166,23 +152,26 @@ func TestByName(t *testing.T) {
name: "json",
want: syftjson.ID,
},
{
name: "syft-json",
want: syftjson.ID,
},
{
name: "syftjson", // clean variant
want: syftjson.ID,
},
// GitHub JSON
{
name: "github",
want: github.ID,
},
{
name: "github-json",
want: github.ID,
},
// Syft template
{
name: "template",
want: template.ID,
@@ -200,3 +189,105 @@ func TestByName(t *testing.T) {
})
}
}
func Test_versionMatches(t *testing.T) {
tests := []struct {
name string
version string
match string
matches bool
}{
{
name: "any version matches number",
version: string(sbom.AnyVersion),
match: "6",
matches: true,
},
{
name: "number matches any version",
version: "6",
match: string(sbom.AnyVersion),
matches: true,
},
{
name: "same number matches",
version: "3",
match: "3",
matches: true,
},
{
name: "same major number matches",
version: "3.1",
match: "3",
matches: true,
},
{
name: "same minor number matches",
version: "3.1",
match: "3.1",
matches: true,
},
{
name: "wildcard-version matches minor",
version: "7.1.3",
match: "7.*",
matches: true,
},
{
name: "wildcard-version matches patch",
version: "7.4.8",
match: "7.4.*",
matches: true,
},
{
name: "sub-version matches major",
version: "7.19.11",
match: "7",
matches: true,
},
{
name: "sub-version matches minor",
version: "7.55.2",
match: "7.55",
matches: true,
},
{
name: "sub-version matches patch",
version: "7.32.6",
match: "7.32.6",
matches: true,
},
// negative tests
{
name: "different number does not match",
version: "3",
match: "4",
matches: false,
},
{
name: "sub-version doesn't match major",
version: "7.2.5",
match: "8.2.5",
matches: false,
},
{
name: "sub-version doesn't match minor",
version: "7.2.9",
match: "7.1",
matches: false,
},
{
name: "sub-version doesn't match patch",
version: "7.32.6",
match: "7.32.5",
matches: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
matches := versionMatches(test.version, test.match)
assert.Equal(t, test.matches, matches)
})
}
}
+3 -2
View File
@@ -7,11 +7,11 @@ import (
"github.com/anchore/syft/syft/sbom"
)
const ID sbom.FormatID = "github-0-json"
const ID sbom.FormatID = "github-json"
func Format() sbom.Format {
return sbom.NewFormat(
ID,
sbom.AnyVersion,
func(writer io.Writer, sbom sbom.SBOM) error {
bom := toGithubModel(&sbom)
@@ -25,5 +25,6 @@ func Format() sbom.Format {
},
nil,
nil,
ID, "github",
)
}
@@ -168,7 +168,7 @@ func populateImageCatalog(catalog *pkg.Catalog, img *image.Image) {
Name: "package-1",
Version: "1.0.1",
Locations: source.NewLocationSet(
source.NewLocationFromImage(string(ref1.RealPath), *ref1, img),
source.NewLocationFromImage(string(ref1.RealPath), *ref1.Reference, img),
),
Type: pkg.PythonPkg,
FoundBy: "the-cataloger-1",
@@ -188,7 +188,7 @@ func populateImageCatalog(catalog *pkg.Catalog, img *image.Image) {
Name: "package-2",
Version: "2.0.1",
Locations: source.NewLocationSet(
source.NewLocationFromImage(string(ref2.RealPath), *ref2, img),
source.NewLocationFromImage(string(ref2.RealPath), *ref2.Reference, img),
),
Type: pkg.DebPkg,
FoundBy: "the-cataloger-2",
+2 -2
View File
@@ -4,14 +4,14 @@ import (
"fmt"
"io"
spdx "github.com/spdx/tools-golang/json"
"github.com/spdx/tools-golang/json"
"github.com/anchore/syft/syft/formats/common/spdxhelpers"
"github.com/anchore/syft/syft/sbom"
)
func decoder(reader io.Reader) (s *sbom.SBOM, err error) {
doc, err := spdx.Load2_3(reader)
doc, err := json.Read(reader)
if err != nil {
return nil, fmt.Errorf("unable to decode spdx-json: %w", err)
}
+19 -1
View File
@@ -4,13 +4,31 @@ import (
"encoding/json"
"io"
"github.com/spdx/tools-golang/convert"
"github.com/spdx/tools-golang/spdx/v2/v2_2"
"github.com/anchore/syft/syft/formats/common/spdxhelpers"
"github.com/anchore/syft/syft/sbom"
)
func encoder(output io.Writer, s sbom.SBOM) error {
func encoder2_3(output io.Writer, s sbom.SBOM) error {
doc := spdxhelpers.ToFormatModel(s)
return encodeJSON(output, doc)
}
func encoder2_2(output io.Writer, s sbom.SBOM) error {
doc := spdxhelpers.ToFormatModel(s)
var out v2_2.Document
err := convert.Document(doc, &out)
if err != nil {
return err
}
return encodeJSON(output, out)
}
func encodeJSON(output io.Writer, doc interface{}) error {
enc := json.NewEncoder(output)
// prevent > and < from being escaped in the payload
enc.SetEscapeHTML(false)
+4 -4
View File
@@ -5,7 +5,7 @@ import (
"regexp"
"testing"
"github.com/anchore/syft/syft/formats/common/testutils"
"github.com/anchore/syft/syft/formats/internal/testutils"
)
var updateSpdxJson = flag.Bool("update-spdx-json", false, "update the *.golden files for spdx-json encoders")
@@ -48,11 +48,11 @@ func TestSPDXRelationshipOrder(t *testing.T) {
func spdxJsonRedactor(s []byte) []byte {
// each SBOM reports the time it was generated, which is not useful during snapshot testing
s = regexp.MustCompile(`"created":\s+"[^"]*",?`).ReplaceAll(s, []byte(""))
s = regexp.MustCompile(`"created":\s+"[^"]*"`).ReplaceAll(s, []byte(`"created":""`))
// each SBOM reports a unique documentNamespace when generated, this is not useful for snapshot testing
s = regexp.MustCompile(`"documentNamespace":\s+"[^"]*",?`).ReplaceAll(s, []byte(""))
s = regexp.MustCompile(`"documentNamespace":\s+"[^"]*"`).ReplaceAll(s, []byte(`"documentNamespace":""`))
// the license list will be updated periodically, the value here should not be directly tested in snapshot tests
return regexp.MustCompile(`"licenseListVersion":\s+"[^"]*",?`).ReplaceAll(s, []byte(""))
return regexp.MustCompile(`"licenseListVersion":\s+"[^"]*"`).ReplaceAll(s, []byte(`"licenseListVersion":""`))
}
+20 -4
View File
@@ -4,14 +4,30 @@ import (
"github.com/anchore/syft/syft/sbom"
)
const ID sbom.FormatID = "spdx-2-json"
const ID sbom.FormatID = "spdx-json"
var IDs = []sbom.FormatID{ID}
// note: this format is LOSSY relative to the syftjson format
func Format() sbom.Format {
func Format2_2() sbom.Format {
return sbom.NewFormat(
ID,
encoder,
"2.2",
encoder2_2,
decoder,
validator,
IDs...,
)
}
func Format2_3() sbom.Format {
return sbom.NewFormat(
"2.3",
encoder2_3,
decoder,
validator,
IDs...,
)
}
var Format = Format2_3
@@ -3,15 +3,14 @@
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "/some/path",
"documentNamespace": "https://anchore.com/syft/dir/some/path-e13c8924-4bbc-42f8-bd30-4e1554472d62",
"documentNamespace": "https://anchore.com/syft/dir/some/path-1fe34646-a616-48c7-974b-3d1e27d406e3",
"creationInfo": {
"licenseListVersion": "3.19",
"creators": [
"Organization: Anchore, Inc",
"Tool: syft-v0.42.0-bogus"
],
"created": "2022-12-22T23:33:52Z",
"comment": ""
"created": "2023-01-20T21:41:03Z"
},
"packages": [
{
@@ -27,14 +26,12 @@
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*",
"comment": ""
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "a-purl-2",
"comment": ""
"referenceLocator": "a-purl-2"
}
]
},
@@ -51,14 +48,12 @@
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*",
"comment": ""
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:deb/debian/package-2@2.0.1",
"comment": ""
"referenceLocator": "pkg:deb/debian/package-2@2.0.1"
}
]
}
@@ -3,15 +3,14 @@
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "user-image-input",
"documentNamespace": "https://anchore.com/syft/image/user-image-input-a1cc9d58-830a-4a4b-9dcd-f41ea3001216",
"documentNamespace": "https://anchore.com/syft/image/user-image-input-33759ac3-6006-4f2c-bdc4-f40b9287a7f0",
"creationInfo": {
"licenseListVersion": "3.19",
"creators": [
"Organization: Anchore, Inc",
"Tool: syft-v0.42.0-bogus"
],
"created": "2022-12-22T23:33:53Z",
"comment": ""
"created": "2023-01-20T21:41:03Z"
},
"packages": [
{
@@ -27,14 +26,12 @@
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*",
"comment": ""
"referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "a-purl-1",
"comment": ""
"referenceLocator": "a-purl-1"
}
]
},
@@ -51,14 +48,12 @@
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*",
"comment": ""
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:deb/debian/package-2@2.0.1",
"comment": ""
"referenceLocator": "pkg:deb/debian/package-2@2.0.1"
}
]
}
@@ -3,15 +3,14 @@
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "user-image-input",
"documentNamespace": "https://anchore.com/syft/image/user-image-input-fc663ee3-0f9b-402e-827f-3f29aeff164e",
"documentNamespace": "https://anchore.com/syft/image/user-image-input-ce98f51f-b483-4e93-9a15-5a8a16d35de6",
"creationInfo": {
"licenseListVersion": "3.19",
"creators": [
"Organization: Anchore, Inc",
"Tool: syft-v0.42.0-bogus"
],
"created": "2022-12-22T23:33:53Z",
"comment": ""
"created": "2023-01-20T21:41:03Z"
},
"packages": [
{
@@ -27,14 +26,12 @@
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*",
"comment": ""
"referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "a-purl-1",
"comment": ""
"referenceLocator": "a-purl-1"
}
]
},
@@ -51,14 +48,12 @@
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*",
"comment": ""
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:deb/debian/package-2@2.0.1",
"comment": ""
"referenceLocator": "pkg:deb/debian/package-2@2.0.1"
}
]
}
+2 -2
View File
@@ -4,14 +4,14 @@ import (
"fmt"
"io"
"github.com/spdx/tools-golang/tvloader"
"github.com/spdx/tools-golang/tagvalue"
"github.com/anchore/syft/syft/formats/common/spdxhelpers"
"github.com/anchore/syft/syft/sbom"
)
func decoder(reader io.Reader) (*sbom.SBOM, error) {
doc, err := tvloader.Load2_3(reader)
doc, err := tagvalue.Read(reader)
if err != nil {
return nil, fmt.Errorf("unable to decode spdx-tag-value: %w", err)
}

Some files were not shown because too many files have changed in this diff Show More