2021-09-23 01:53:32 +00:00
|
|
|
package integration
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"testing"
|
|
|
|
|
2022-03-03 19:50:24 +00:00
|
|
|
"github.com/scylladb/go-set/strset"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
2021-09-23 01:53:32 +00:00
|
|
|
"github.com/anchore/grype/grype"
|
|
|
|
"github.com/anchore/grype/grype/db"
|
|
|
|
"github.com/anchore/grype/internal"
|
2023-11-02 19:25:48 +00:00
|
|
|
"github.com/anchore/syft/syft/format/spdxjson"
|
|
|
|
"github.com/anchore/syft/syft/format/spdxtagvalue"
|
|
|
|
"github.com/anchore/syft/syft/format/syftjson"
|
2021-09-23 01:53:32 +00:00
|
|
|
syftPkg "github.com/anchore/syft/syft/pkg"
|
2022-03-14 21:15:09 +00:00
|
|
|
"github.com/anchore/syft/syft/sbom"
|
2021-09-23 01:53:32 +00:00
|
|
|
"github.com/anchore/syft/syft/source"
|
|
|
|
)
|
|
|
|
|
2022-07-05 18:03:16 +00:00
|
|
|
func getListingURL() string {
|
|
|
|
if value, ok := os.LookupEnv("GRYPE_DB_UPDATE_URL"); ok {
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
return internal.DBUpdateURL
|
|
|
|
}
|
|
|
|
|
2023-11-02 19:25:48 +00:00
|
|
|
func must(e sbom.FormatEncoder, err error) sbom.FormatEncoder {
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
|
2021-09-23 01:53:32 +00:00
|
|
|
func TestCompareSBOMInputToLibResults(t *testing.T) {
|
|
|
|
// get a grype DB
|
2022-07-12 13:54:42 +00:00
|
|
|
store, _, closer, err := grype.LoadVulnerabilityDB(db.Config{
|
2021-10-06 13:49:42 +00:00
|
|
|
DBRootDir: "test-fixtures/grype-db",
|
2022-07-05 18:03:16 +00:00
|
|
|
ListingURL: getListingURL(),
|
2021-09-23 01:53:32 +00:00
|
|
|
ValidateByHashOnGet: false,
|
|
|
|
}, true)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2022-07-12 13:54:42 +00:00
|
|
|
if closer != nil {
|
|
|
|
defer closer.Close()
|
|
|
|
}
|
|
|
|
|
2021-09-23 01:53:32 +00:00
|
|
|
definedPkgTypes := strset.New()
|
|
|
|
for _, p := range syftPkg.AllPkgs {
|
|
|
|
definedPkgTypes.Add(string(p))
|
|
|
|
}
|
2023-01-18 17:50:46 +00:00
|
|
|
// exceptions: rust, php, dart, msrc (kb), etc. are not under test
|
2021-11-15 22:11:56 +00:00
|
|
|
definedPkgTypes.Remove(
|
2023-08-17 19:39:41 +00:00
|
|
|
string(syftPkg.BinaryPkg), // these are removed due to overlap-by-file-ownership
|
2024-04-04 15:52:02 +00:00
|
|
|
string(syftPkg.PhpPeclPkg),
|
2021-11-15 22:11:56 +00:00
|
|
|
string(syftPkg.RustPkg),
|
|
|
|
string(syftPkg.KbPkg),
|
2022-04-01 15:21:37 +00:00
|
|
|
string(syftPkg.DartPubPkg),
|
2022-05-13 16:46:31 +00:00
|
|
|
string(syftPkg.DotnetPkg),
|
2021-11-15 22:11:56 +00:00
|
|
|
string(syftPkg.PhpComposerPkg),
|
2022-07-06 14:48:21 +00:00
|
|
|
string(syftPkg.ConanPkg),
|
2023-01-18 17:50:46 +00:00
|
|
|
string(syftPkg.HexPkg),
|
2022-07-11 19:15:12 +00:00
|
|
|
string(syftPkg.PortagePkg),
|
|
|
|
string(syftPkg.CocoapodsPkg),
|
2022-07-22 16:12:18 +00:00
|
|
|
string(syftPkg.HackagePkg),
|
2023-04-19 17:38:06 +00:00
|
|
|
string(syftPkg.NixPkg),
|
2022-02-10 21:43:12 +00:00
|
|
|
string(syftPkg.JenkinsPluginPkg), // package type cannot be inferred for all formats
|
2023-04-19 17:38:06 +00:00
|
|
|
string(syftPkg.LinuxKernelPkg),
|
|
|
|
string(syftPkg.LinuxKernelModulePkg),
|
2023-05-22 14:17:34 +00:00
|
|
|
string(syftPkg.Rpkg),
|
2024-08-09 18:32:05 +00:00
|
|
|
string(syftPkg.SwiplPackPkg),
|
2023-07-31 17:58:36 +00:00
|
|
|
string(syftPkg.SwiftPkg),
|
2023-09-20 20:39:23 +00:00
|
|
|
string(syftPkg.GithubActionPkg),
|
|
|
|
string(syftPkg.GithubActionWorkflowPkg),
|
2024-02-07 19:28:48 +00:00
|
|
|
string(syftPkg.ErlangOTPPkg),
|
2024-02-14 22:09:50 +00:00
|
|
|
string(syftPkg.WordpressPluginPkg), // TODO: remove me when there is a matcher for this merged in https://github.com/anchore/grype/pull/1553
|
2024-05-28 15:06:16 +00:00
|
|
|
string(syftPkg.LuaRocksPkg),
|
2021-11-15 22:11:56 +00:00
|
|
|
)
|
2021-09-23 01:53:32 +00:00
|
|
|
observedPkgTypes := strset.New()
|
2023-07-18 15:27:46 +00:00
|
|
|
testCases := []struct {
|
|
|
|
name string
|
|
|
|
image string
|
2023-11-02 19:25:48 +00:00
|
|
|
format sbom.FormatEncoder
|
2023-07-18 15:27:46 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:vulnerabilities-alpine",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: syftjson.NewFormatEncoder(),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "alpine-syft-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:vulnerabilities-alpine",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxjson.NewFormatEncoderWithConfig(spdxjson.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "alpine-spdx-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:vulnerabilities-alpine",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "alpine-spdx-tag-value",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:gems",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: syftjson.NewFormatEncoder(),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "gems-syft-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:gems",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxjson.NewFormatEncoderWithConfig(spdxjson.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "gems-spdx-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:gems",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "gems-spdx-tag-value",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:vulnerabilities-debian",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: syftjson.NewFormatEncoder(),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "debian-syft-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:vulnerabilities-debian",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxjson.NewFormatEncoderWithConfig(spdxjson.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "debian-spdx-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:vulnerabilities-debian",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "debian-spdx-tag-value",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:vulnerabilities-centos",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: syftjson.NewFormatEncoder(),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "centos-syft-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:vulnerabilities-centos",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxjson.NewFormatEncoderWithConfig(spdxjson.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "centos-spdx-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:vulnerabilities-centos",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "centos-spdx-tag-value",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:npm",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: syftjson.NewFormatEncoder(),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "npm-syft-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:npm",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxjson.NewFormatEncoderWithConfig(spdxjson.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "npm-spdx-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:npm",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "npm-spdx-tag-value",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:java",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: syftjson.NewFormatEncoder(),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "java-syft-json",
|
|
|
|
},
|
2021-09-23 01:53:32 +00:00
|
|
|
|
2023-07-18 15:27:46 +00:00
|
|
|
{
|
|
|
|
image: "anchore/test_images:java",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxjson.NewFormatEncoderWithConfig(spdxjson.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "java-spdx-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:java",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "java-spdx-tag-value",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:golang-56d52bc",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: syftjson.NewFormatEncoder(),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "go-syft-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:golang-56d52bc",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxjson.NewFormatEncoderWithConfig(spdxjson.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "go-spdx-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:golang-56d52bc",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "go-spdx-tag-value",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:arch",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: syftjson.NewFormatEncoder(),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "arch-syft-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:arch",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxjson.NewFormatEncoderWithConfig(spdxjson.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "arch-spdx-json",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
image: "anchore/test_images:arch",
|
2023-11-02 19:25:48 +00:00
|
|
|
format: must(spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.DefaultEncoderConfig())),
|
2023-07-18 15:27:46 +00:00
|
|
|
name: "arch-spdx-tag-value",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
|
|
imageArchive := PullThroughImageCache(t, tc.image)
|
2023-11-02 19:25:48 +00:00
|
|
|
|
2023-07-18 15:27:46 +00:00
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
// get SBOM from syft, write to temp file
|
2024-02-28 01:47:51 +00:00
|
|
|
sbomBytes := getSyftSBOM(t, imageArchive, "docker-archive", tc.format)
|
2023-07-18 15:27:46 +00:00
|
|
|
sbomFile, err := os.CreateTemp("", "")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
t.Cleanup(func() {
|
|
|
|
assert.NoError(t, os.Remove(sbomFile.Name()))
|
|
|
|
})
|
|
|
|
_, err = sbomFile.WriteString(sbomBytes)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NoError(t, sbomFile.Close())
|
|
|
|
|
|
|
|
// get vulns (sbom)
|
|
|
|
matchesFromSbom, _, pkgsFromSbom, err := grype.FindVulnerabilities(*store, fmt.Sprintf("sbom:%s", sbomFile.Name()), source.SquashedScope, nil)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// get vulns (image)
|
2024-02-28 01:47:51 +00:00
|
|
|
imageSource := fmt.Sprintf("docker-archive:%s", imageArchive)
|
2023-07-18 15:27:46 +00:00
|
|
|
matchesFromImage, _, _, err := grype.FindVulnerabilities(*store, imageSource, source.SquashedScope, nil)
|
|
|
|
assert.NoError(t, err)
|
2021-09-23 01:53:32 +00:00
|
|
|
|
2023-07-18 15:27:46 +00:00
|
|
|
// compare packages (shallow)
|
|
|
|
matchSetFromSbom := getMatchSet(matchesFromSbom)
|
|
|
|
matchSetFromImage := getMatchSet(matchesFromImage)
|
|
|
|
|
|
|
|
assert.Empty(t, strset.Difference(matchSetFromSbom, matchSetFromImage).List(), "vulnerabilities present only in results when using sbom as input")
|
|
|
|
assert.Empty(t, strset.Difference(matchSetFromImage, matchSetFromSbom).List(), "vulnerabilities present only in results when using image as input")
|
|
|
|
|
|
|
|
// track all covered package types (for use after the test)
|
|
|
|
for _, p := range pkgsFromSbom {
|
|
|
|
observedPkgTypes.Add(string(p.Type))
|
2022-03-14 21:15:09 +00:00
|
|
|
}
|
2022-02-10 21:43:12 +00:00
|
|
|
|
2023-07-18 15:27:46 +00:00
|
|
|
})
|
2021-09-23 01:53:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ensure we've covered all package types (-rust, -kb)
|
|
|
|
unobservedPackageTypes := strset.Difference(definedPkgTypes, observedPkgTypes)
|
|
|
|
assert.Empty(t, unobservedPackageTypes.List(), "not all package type were covered in testing")
|
|
|
|
}
|