2021-03-18 13:00:28 +00:00
|
|
|
package cli
|
|
|
|
|
|
|
|
import (
|
2022-02-06 15:53:55 +00:00
|
|
|
"fmt"
|
2022-03-08 15:37:28 +00:00
|
|
|
"path/filepath"
|
2021-03-18 13:00:28 +00:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2023-09-15 18:51:21 +00:00
|
|
|
const (
|
|
|
|
// this is the number of packages that should be found in the image-pkg-coverage fixture image
|
|
|
|
// when analyzed with the squashed scope.
|
2024-05-24 20:56:34 +00:00
|
|
|
coverageImageSquashedPackageCount = 30
|
2023-09-15 18:51:21 +00:00
|
|
|
)
|
|
|
|
|
2021-03-18 13:00:28 +00:00
|
|
|
func TestPackagesCmdFlags(t *testing.T) {
|
2022-03-31 19:45:51 +00:00
|
|
|
hiddenPackagesImage := "docker-archive:" + getFixtureImage(t, "image-hidden-packages")
|
2021-12-10 16:49:50 +00:00
|
|
|
coverageImage := "docker-archive:" + getFixtureImage(t, "image-pkg-coverage")
|
2022-10-31 16:45:11 +00:00
|
|
|
nodeBinaryImage := "docker-archive:" + getFixtureImage(t, "image-node-binary")
|
2023-07-19 19:34:07 +00:00
|
|
|
// badBinariesImage := "docker-archive:" + getFixtureImage(t, "image-bad-binaries")
|
2022-01-06 22:52:20 +00:00
|
|
|
tmp := t.TempDir() + "/"
|
2021-03-18 13:00:28 +00:00
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args []string
|
|
|
|
env map[string]string
|
|
|
|
assertions []traitAssertion
|
|
|
|
}{
|
2021-06-30 16:53:12 +00:00
|
|
|
{
|
|
|
|
name: "no-args-shows-help",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan"},
|
2021-06-30 16:53:12 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertInOutput("an image/directory argument is required"), // specific error that should be shown
|
|
|
|
assertInOutput("Generate a packaged-based Software Bill Of Materials"), // excerpt from help description
|
|
|
|
assertFailingReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2021-03-18 13:00:28 +00:00
|
|
|
{
|
|
|
|
name: "json-output-flag",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "json", coverageImage},
|
2021-03-18 13:00:28 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertJsonReport,
|
2023-11-20 15:29:34 +00:00
|
|
|
assertInOutput(`"metadataType":"apk-db-entry"`),
|
|
|
|
assertNotInOutput(`"metadataType":"ApkMetadata"`),
|
2021-03-18 13:00:28 +00:00
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2023-08-31 14:40:11 +00:00
|
|
|
{
|
|
|
|
name: "quiet-flag-with-logger",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-qvv", "-o", "json", coverageImage},
|
2023-08-31 14:40:11 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertJsonReport,
|
|
|
|
assertNoStderr,
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "quiet-flag-with-tui",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-q", "-o", "json", coverageImage},
|
2023-08-31 14:40:11 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertJsonReport,
|
|
|
|
assertNoStderr,
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2022-01-06 22:52:20 +00:00
|
|
|
{
|
|
|
|
name: "multiple-output-flags",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "table", "-o", "json=" + tmp + ".tmp/multiple-output-flag-test.json", coverageImage},
|
2022-01-06 22:52:20 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertTableReport,
|
|
|
|
assertFileExists(tmp + ".tmp/multiple-output-flag-test.json"),
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2021-12-22 20:55:37 +00:00
|
|
|
// I haven't been able to reproduce locally yet, but in CI this has proven to be unstable:
|
|
|
|
// For the same commit:
|
|
|
|
// pass: https://github.com/anchore/syft/runs/4611344142?check_suite_focus=true
|
|
|
|
// fail: https://github.com/anchore/syft/runs/4611343586?check_suite_focus=true
|
|
|
|
// For the meantime this test will be commented out, but should be added back in as soon as possible.
|
|
|
|
//
|
2023-07-19 19:34:07 +00:00
|
|
|
// {
|
2021-12-22 20:55:37 +00:00
|
|
|
// name: "regression-survive-bad-binaries",
|
|
|
|
// // this image has all sorts of rich binaries from the clang-13 test suite that should do pretty bad things
|
|
|
|
// // to the go cataloger binary path. We should NEVER let a panic stop the cataloging process for these
|
|
|
|
// // specific cases.
|
|
|
|
//
|
|
|
|
// // this is more of an integration test, however, to assert the output we want to see from the application
|
|
|
|
// // a CLI test is much easier.
|
2024-01-04 16:56:57 +00:00
|
|
|
// args: []string{"scan", "-vv", badBinariesImage},
|
2021-12-22 20:55:37 +00:00
|
|
|
// assertions: []traitAssertion{
|
|
|
|
// assertInOutput("could not parse possible go binary"),
|
|
|
|
// assertSuccessfulReturnCode,
|
|
|
|
// },
|
2023-07-19 19:34:07 +00:00
|
|
|
// },
|
2021-03-18 13:00:28 +00:00
|
|
|
{
|
|
|
|
name: "output-env-binding",
|
|
|
|
env: map[string]string{
|
|
|
|
"SYFT_OUTPUT": "json",
|
|
|
|
},
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", coverageImage},
|
2021-03-18 13:00:28 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertJsonReport,
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "table-output-flag",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "table", coverageImage},
|
2021-03-18 13:00:28 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertTableReport,
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "default-output-flag",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", coverageImage},
|
2021-03-18 13:00:28 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertTableReport,
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2023-10-30 16:12:04 +00:00
|
|
|
{
|
|
|
|
name: "legacy-json-output-flag",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "json", coverageImage},
|
2023-10-30 16:12:04 +00:00
|
|
|
env: map[string]string{
|
|
|
|
"SYFT_FORMAT_JSON_LEGACY": "true",
|
|
|
|
},
|
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertJsonReport,
|
2023-11-20 15:29:34 +00:00
|
|
|
assertNotInOutput(`"metadataType":"apk-db-entry"`),
|
|
|
|
assertInOutput(`"metadataType":"ApkMetadata"`),
|
2023-10-30 16:12:04 +00:00
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2021-03-18 13:00:28 +00:00
|
|
|
{
|
|
|
|
name: "squashed-scope-flag",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "json", "-s", "squashed", coverageImage},
|
2021-03-18 13:00:28 +00:00
|
|
|
assertions: []traitAssertion{
|
2023-09-15 18:51:21 +00:00
|
|
|
assertPackageCount(coverageImageSquashedPackageCount),
|
2021-03-18 13:00:28 +00:00
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2022-03-31 19:45:51 +00:00
|
|
|
{
|
|
|
|
name: "squashed-scope-flag-hidden-packages",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "json", "-s", "squashed", hiddenPackagesImage},
|
2022-03-31 19:45:51 +00:00
|
|
|
assertions: []traitAssertion{
|
2024-09-09 15:15:13 +00:00
|
|
|
assertPackageCount(14),
|
|
|
|
// package 1: alpine-baselayout-data@3.6.5-r0 (apk)
|
|
|
|
// package 2: alpine-baselayout@3.6.5-r0 (apk)
|
|
|
|
// package 3: alpine-keys@2.4-r1 (apk)
|
|
|
|
// package 4: apk-tools@2.14.4-r0 (apk)
|
|
|
|
// package 5: busybox-binsh@1.36.1-r29 (apk)
|
|
|
|
// package 6: busybox@1.36.1-r29 (apk)
|
|
|
|
// package 7: ca-certificates-bundle@20240705-r0 (apk)
|
|
|
|
// package 8: libcrypto3@3.3.1-r3 (apk)
|
|
|
|
// package 9: libssl3@3.3.1-r3 (apk)
|
|
|
|
// package 10: musl-utils@1.2.5-r0 (apk)
|
|
|
|
// package 11: musl@1.2.5-r0 (apk)
|
|
|
|
// package 12: scanelf@1.3.7-r2 (apk)
|
|
|
|
// package 13: ssl_client@1.36.1-r29 (apk)
|
|
|
|
// package 14: zlib@1.3.1-r1 (apk)
|
|
|
|
assertNotInOutput(`"name":"curl"`), // hidden package
|
2022-03-31 19:45:51 +00:00
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2021-03-18 13:00:28 +00:00
|
|
|
{
|
|
|
|
name: "all-layers-scope-flag",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "json", "-s", "all-layers", hiddenPackagesImage},
|
2021-03-18 13:00:28 +00:00
|
|
|
assertions: []traitAssertion{
|
2024-09-09 15:15:13 +00:00
|
|
|
assertPackageCount(24),
|
|
|
|
// package 1: alpine-baselayout-data@3.6.5-r0 (apk)
|
|
|
|
// package 2: alpine-baselayout@3.6.5-r0 (apk)
|
|
|
|
// package 3: alpine-keys@2.4-r1 (apk)
|
|
|
|
// package 4: apk-tools@2.14.4-r0 (apk)
|
|
|
|
// package 5: brotli-libs@1.1.0-r2 (apk)
|
|
|
|
// package 6: busybox-binsh@1.36.1-r29 (apk)
|
|
|
|
// package 7: busybox@1.36.1-r29 (apk)
|
|
|
|
// package 8: c-ares@1.28.1-r0 (apk)
|
|
|
|
// package 9: ca-certificates-bundle@20240705-r0 (apk)
|
|
|
|
// package 10: ca-certificates@20240705-r0 (apk)
|
|
|
|
// package 11: curl@8.9.1-r1 (apk)
|
|
|
|
// package 12: libcrypto3@3.3.1-r3 (apk)
|
|
|
|
// package 13: libcurl@8.9.1-r1 (apk)
|
|
|
|
// package 14: libidn2@2.3.7-r0 (apk)
|
|
|
|
// package 15: libpsl@0.21.5-r1 (apk)
|
|
|
|
// package 16: libssl3@3.3.1-r3 (apk)
|
|
|
|
// package 17: libunistring@1.2-r0 (apk)
|
|
|
|
// package 18: musl-utils@1.2.5-r0 (apk)
|
|
|
|
// package 19: musl@1.2.5-r0 (apk)
|
|
|
|
// package 20: nghttp2-libs@1.62.1-r0 (apk)
|
|
|
|
// package 21: scanelf@1.3.7-r2 (apk)
|
|
|
|
// package 22: ssl_client@1.36.1-r29 (apk)
|
|
|
|
// package 23: zlib@1.3.1-r1 (apk)
|
|
|
|
// package 24: zstd-libs@1.5.6-r0 (apk)
|
2022-03-31 19:45:51 +00:00
|
|
|
assertInOutput("all-layers"),
|
2024-09-09 15:15:13 +00:00
|
|
|
assertInOutput(`"name":"curl"`), // hidden package
|
2021-03-18 13:00:28 +00:00
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2021-11-05 14:05:49 +00:00
|
|
|
name: "all-layers-scope-flag-by-env",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "json", hiddenPackagesImage},
|
2021-03-18 13:00:28 +00:00
|
|
|
env: map[string]string{
|
2024-01-12 22:39:13 +00:00
|
|
|
"SYFT_SCOPE": "all-layers",
|
2021-03-18 13:00:28 +00:00
|
|
|
},
|
|
|
|
assertions: []traitAssertion{
|
2024-09-09 15:15:13 +00:00
|
|
|
assertPackageCount(24), // packages are now deduplicated for this case
|
2022-03-31 19:45:51 +00:00
|
|
|
assertInOutput("all-layers"),
|
2024-09-09 15:15:13 +00:00
|
|
|
assertInOutput(`"name":"curl"`), // hidden package
|
2021-03-18 13:00:28 +00:00
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2021-11-02 16:09:06 +00:00
|
|
|
{
|
|
|
|
// we want to make certain that syft can catalog a single go binary and get a SBOM report that is not empty
|
|
|
|
name: "catalog-single-go-binary",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "json", getSyftBinaryLocation(t)},
|
2021-11-02 16:09:06 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertJsonReport,
|
|
|
|
assertStdoutLengthGreaterThan(1000),
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2022-10-31 16:45:11 +00:00
|
|
|
{
|
|
|
|
name: "catalog-node-js-binary",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "json", nodeBinaryImage},
|
2022-10-31 16:45:11 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertJsonReport,
|
|
|
|
assertInOutput("node.js"),
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2024-02-09 20:59:25 +00:00
|
|
|
// TODO: uncomment this test when we can use `syft config`
|
|
|
|
//{
|
|
|
|
// // TODO: this could be a unit test
|
|
|
|
// name: "responds-to-package-cataloger-search-options",
|
|
|
|
// args: []string{"--help"},
|
|
|
|
// env: map[string]string{
|
|
|
|
// "SYFT_PACKAGE_SEARCH_UNINDEXED_ARCHIVES": "true",
|
|
|
|
// "SYFT_PACKAGE_SEARCH_INDEXED_ARCHIVES": "false",
|
|
|
|
// },
|
|
|
|
// assertions: []traitAssertion{
|
|
|
|
// // the application config in the log matches that of what we expect to have been configured. Note:
|
|
|
|
// // we are not testing further wiring of this option, only that the config responds to
|
|
|
|
// // package-cataloger-level options.
|
|
|
|
// assertInOutput("search-unindexed-archives: true"),
|
|
|
|
// assertInOutput("search-indexed-archives: false"),
|
|
|
|
// },
|
|
|
|
//},
|
2022-03-04 22:41:38 +00:00
|
|
|
{
|
|
|
|
name: "platform-option-wired-up",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "--platform", "arm64", "-o", "json", "registry:busybox:1.31"},
|
2022-03-04 22:41:38 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertInOutput("sha256:1ee006886991ad4689838d3a288e0dd3fd29b70e276622f16b67a8922831a853"), // linux/arm64 image digest
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2022-03-08 15:37:28 +00:00
|
|
|
{
|
|
|
|
name: "json-file-flag",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", "json", "--file", filepath.Join(tmp, "output-1.json"), coverageImage},
|
2022-03-08 15:37:28 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
assertFileOutput(t, filepath.Join(tmp, "output-1.json"),
|
|
|
|
assertJsonReport,
|
|
|
|
),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "json-output-flag-to-file",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-o", fmt.Sprintf("json=%s", filepath.Join(tmp, "output-2.json")), coverageImage},
|
2022-03-08 15:37:28 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
assertFileOutput(t, filepath.Join(tmp, "output-2.json"),
|
|
|
|
assertJsonReport,
|
|
|
|
),
|
|
|
|
},
|
|
|
|
},
|
2022-06-21 13:06:25 +00:00
|
|
|
{
|
2024-01-12 22:39:13 +00:00
|
|
|
name: "legacy-catalogers-option",
|
|
|
|
// This will detect enable:
|
|
|
|
// - python-installed-package-cataloger
|
|
|
|
// - python-package-cataloger
|
|
|
|
// - ruby-gemspec-cataloger
|
|
|
|
// - ruby-installed-gemspec-cataloger
|
|
|
|
args: []string{"packages", "-o", "json", "--catalogers", "python,gemspec", coverageImage},
|
2022-06-21 13:06:25 +00:00
|
|
|
assertions: []traitAssertion{
|
2024-01-12 22:39:13 +00:00
|
|
|
assertInOutput("Flag --catalogers has been deprecated, use: override-default-catalogers and select-catalogers"),
|
2022-08-04 21:14:23 +00:00
|
|
|
assertPackageCount(13),
|
2022-06-21 13:06:25 +00:00
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2024-01-12 22:39:13 +00:00
|
|
|
{
|
|
|
|
name: "select-catalogers-option",
|
|
|
|
// This will detect enable:
|
|
|
|
// - python-installed-package-cataloger
|
|
|
|
// - ruby-installed-gemspec-cataloger
|
|
|
|
args: []string{"scan", "-o", "json", "--select-catalogers", "python,gemspec", coverageImage},
|
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertPackageCount(6),
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "override-default-catalogers-option",
|
|
|
|
// This will detect enable:
|
|
|
|
// - python-installed-package-cataloger
|
|
|
|
// - python-package-cataloger
|
|
|
|
// - ruby-gemspec-cataloger
|
|
|
|
// - ruby-installed-gemspec-cataloger
|
|
|
|
args: []string{"packages", "-o", "json", "--override-default-catalogers", "python,gemspec", coverageImage},
|
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertPackageCount(13),
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "new and old cataloger options are mutually exclusive",
|
|
|
|
args: []string{"packages", "-o", "json", "--override-default-catalogers", "python", "--catalogers", "gemspec", coverageImage},
|
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertFailingReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2023-01-11 20:18:02 +00:00
|
|
|
{
|
|
|
|
name: "override-default-parallelism",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-vvv", "-o", "json", coverageImage},
|
2023-01-11 20:18:02 +00:00
|
|
|
env: map[string]string{
|
|
|
|
"SYFT_PARALLELISM": "2",
|
|
|
|
},
|
|
|
|
assertions: []traitAssertion{
|
|
|
|
// the application config in the log matches that of what we expect to have been configured.
|
2024-01-12 22:39:13 +00:00
|
|
|
assertInOutput(`parallelism: 2`),
|
2023-09-15 18:51:21 +00:00
|
|
|
assertPackageCount(coverageImageSquashedPackageCount),
|
2023-01-11 20:18:02 +00:00
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "default-parallelism",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-vvv", "-o", "json", coverageImage},
|
2023-01-11 20:18:02 +00:00
|
|
|
assertions: []traitAssertion{
|
|
|
|
// the application config in the log matches that of what we expect to have been configured.
|
2024-01-12 22:39:13 +00:00
|
|
|
assertInOutput(`parallelism: 1`),
|
2023-09-15 18:51:21 +00:00
|
|
|
assertPackageCount(coverageImageSquashedPackageCount),
|
2023-01-11 20:18:02 +00:00
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2023-02-03 18:06:14 +00:00
|
|
|
{
|
|
|
|
name: "password and key not in config output",
|
2024-01-04 16:56:57 +00:00
|
|
|
args: []string{"scan", "-vvv", "-o", "json", coverageImage},
|
2023-02-03 18:06:14 +00:00
|
|
|
env: map[string]string{
|
|
|
|
"SYFT_ATTEST_PASSWORD": "secret_password",
|
|
|
|
"SYFT_ATTEST_KEY": "secret_key_path",
|
|
|
|
},
|
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertNotInOutput("secret_password"),
|
|
|
|
assertNotInOutput("secret_key_path"),
|
2023-09-15 18:51:21 +00:00
|
|
|
assertPackageCount(coverageImageSquashedPackageCount),
|
2023-02-03 18:06:14 +00:00
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2024-01-04 16:56:57 +00:00
|
|
|
// Testing packages alias //////////////////////////////////////////////
|
|
|
|
{
|
|
|
|
name: "packages-alias-command-works",
|
|
|
|
args: []string{"packages", coverageImage},
|
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertTableReport,
|
|
|
|
assertInOutput("Command \"packages\" is deprecated, use `syft scan` instead"),
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "packages-alias-command--output-flag",
|
|
|
|
args: []string{"packages", "-o", "json", coverageImage},
|
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertJsonReport,
|
|
|
|
assertSuccessfulReturnCode,
|
|
|
|
},
|
|
|
|
},
|
2021-03-18 13:00:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
2021-06-29 22:06:47 +00:00
|
|
|
cmd, stdout, stderr := runSyft(t, test.env, test.args...)
|
2021-03-18 13:00:28 +00:00
|
|
|
for _, traitFn := range test.assertions {
|
|
|
|
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
|
|
|
|
}
|
2023-04-14 18:33:36 +00:00
|
|
|
logOutputOnFailure(t, cmd, stdout, stderr)
|
2021-03-18 13:00:28 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2021-04-13 13:30:57 +00:00
|
|
|
|
|
|
|
func TestRegistryAuth(t *testing.T) {
|
2022-02-06 15:53:55 +00:00
|
|
|
host := "localhost:17"
|
|
|
|
image := fmt.Sprintf("%s/something:latest", host)
|
2024-02-27 21:44:37 +00:00
|
|
|
args := []string{"scan", "-vvv", image, "--from", "registry"}
|
2022-02-06 15:53:55 +00:00
|
|
|
|
2021-04-13 13:30:57 +00:00
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args []string
|
|
|
|
env map[string]string
|
|
|
|
assertions []traitAssertion
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "fallback to keychain",
|
2022-02-06 15:53:55 +00:00
|
|
|
args: args,
|
2021-04-13 13:30:57 +00:00
|
|
|
assertions: []traitAssertion{
|
2024-02-27 21:44:37 +00:00
|
|
|
assertInOutput("from registry"),
|
2022-02-06 15:53:55 +00:00
|
|
|
assertInOutput(image),
|
2023-08-29 15:45:20 +00:00
|
|
|
assertInOutput(fmt.Sprintf("no registry credentials configured for %q, using the default keychain", host)),
|
2021-04-13 13:30:57 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "use creds",
|
2022-02-06 15:53:55 +00:00
|
|
|
args: args,
|
2021-04-13 13:30:57 +00:00
|
|
|
env: map[string]string{
|
2022-02-06 15:53:55 +00:00
|
|
|
"SYFT_REGISTRY_AUTH_AUTHORITY": host,
|
2021-04-13 13:30:57 +00:00
|
|
|
"SYFT_REGISTRY_AUTH_USERNAME": "username",
|
|
|
|
"SYFT_REGISTRY_AUTH_PASSWORD": "password",
|
|
|
|
},
|
|
|
|
assertions: []traitAssertion{
|
2024-02-27 21:44:37 +00:00
|
|
|
assertInOutput("from registry"),
|
2022-02-06 15:53:55 +00:00
|
|
|
assertInOutput(image),
|
|
|
|
assertInOutput(fmt.Sprintf(`using basic auth for registry "%s"`, host)),
|
2021-04-13 13:30:57 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "use token",
|
2022-02-06 15:53:55 +00:00
|
|
|
args: args,
|
2021-04-13 13:30:57 +00:00
|
|
|
env: map[string]string{
|
2022-02-06 15:53:55 +00:00
|
|
|
"SYFT_REGISTRY_AUTH_AUTHORITY": host,
|
2023-08-29 19:52:26 +00:00
|
|
|
"SYFT_REGISTRY_AUTH_TOKEN": "my-token",
|
2021-04-13 13:30:57 +00:00
|
|
|
},
|
|
|
|
assertions: []traitAssertion{
|
2024-02-27 21:44:37 +00:00
|
|
|
assertInOutput("from registry"),
|
2022-02-06 15:53:55 +00:00
|
|
|
assertInOutput(image),
|
|
|
|
assertInOutput(fmt.Sprintf(`using token for registry "%s"`, host)),
|
2021-04-13 13:30:57 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-08-29 19:52:26 +00:00
|
|
|
name: "not enough info fallback to keychain",
|
2022-02-06 15:53:55 +00:00
|
|
|
args: args,
|
2021-04-13 13:30:57 +00:00
|
|
|
env: map[string]string{
|
2022-02-06 15:53:55 +00:00
|
|
|
"SYFT_REGISTRY_AUTH_AUTHORITY": host,
|
2021-04-13 13:30:57 +00:00
|
|
|
},
|
|
|
|
assertions: []traitAssertion{
|
2024-02-27 21:44:37 +00:00
|
|
|
assertInOutput("from registry"),
|
2022-02-06 15:53:55 +00:00
|
|
|
assertInOutput(image),
|
2023-08-29 15:45:20 +00:00
|
|
|
assertInOutput(fmt.Sprintf(`no registry credentials configured for %q, using the default keychain`, host)),
|
2021-04-13 13:30:57 +00:00
|
|
|
},
|
|
|
|
},
|
2021-08-17 16:52:51 +00:00
|
|
|
{
|
|
|
|
name: "allows insecure http flag",
|
2022-02-06 15:53:55 +00:00
|
|
|
args: args,
|
2021-08-17 16:52:51 +00:00
|
|
|
env: map[string]string{
|
|
|
|
"SYFT_REGISTRY_INSECURE_USE_HTTP": "true",
|
|
|
|
},
|
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertInOutput("insecure-use-http: true"),
|
|
|
|
},
|
|
|
|
},
|
2023-08-29 15:45:20 +00:00
|
|
|
{
|
|
|
|
name: "use tls configuration",
|
|
|
|
args: args,
|
|
|
|
env: map[string]string{
|
|
|
|
"SYFT_REGISTRY_AUTH_TLS_CERT": "place.crt",
|
|
|
|
"SYFT_REGISTRY_AUTH_TLS_KEY": "place.key",
|
|
|
|
},
|
|
|
|
assertions: []traitAssertion{
|
|
|
|
assertInOutput("using custom TLS credentials from"),
|
|
|
|
},
|
|
|
|
},
|
2021-04-13 13:30:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
2021-06-29 22:06:47 +00:00
|
|
|
cmd, stdout, stderr := runSyft(t, test.env, test.args...)
|
2021-04-13 13:30:57 +00:00
|
|
|
for _, traitAssertionFn := range test.assertions {
|
|
|
|
traitAssertionFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
|
|
|
|
}
|
2023-04-14 18:33:36 +00:00
|
|
|
logOutputOnFailure(t, cmd, stdout, stderr)
|
2021-04-13 13:30:57 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|