Merge remote-tracking branch 'origin/main' into chore/build-syft-for-cli-tests

This commit is contained in:
Keith Zantow
2023-10-13 09:18:40 -04:00
270 changed files with 16230 additions and 4486 deletions
+45 -10
View File
@@ -6,6 +6,12 @@ import (
"testing"
)
const (
// this is the number of packages that should be found in the image-pkg-coverage fixture image
// when analyzed with the squashed scope.
coverageImageSquashedPackageCount = 24
)
func TestPackagesCmdFlags(t *testing.T) {
hiddenPackagesImage := "docker-archive:" + getFixtureImage(t, "image-hidden-packages")
coverageImage := "docker-archive:" + getFixtureImage(t, "image-pkg-coverage")
@@ -36,6 +42,24 @@ func TestPackagesCmdFlags(t *testing.T) {
assertSuccessfulReturnCode,
},
},
{
name: "quiet-flag-with-logger",
args: []string{"packages", "-qvv", "-o", "json", coverageImage},
assertions: []traitAssertion{
assertJsonReport,
assertNoStderr,
assertSuccessfulReturnCode,
},
},
{
name: "quiet-flag-with-tui",
args: []string{"packages", "-q", "-o", "json", coverageImage},
assertions: []traitAssertion{
assertJsonReport,
assertNoStderr,
assertSuccessfulReturnCode,
},
},
{
name: "multiple-output-flags",
args: []string{"packages", "-o", "table", "-o", "json=" + tmp + ".tmp/multiple-output-flag-test.json", coverageImage},
@@ -96,7 +120,7 @@ func TestPackagesCmdFlags(t *testing.T) {
name: "squashed-scope-flag",
args: []string{"packages", "-o", "json", "-s", "squashed", coverageImage},
assertions: []traitAssertion{
assertPackageCount(24),
assertPackageCount(coverageImageSquashedPackageCount),
assertSuccessfulReturnCode,
},
},
@@ -153,7 +177,7 @@ func TestPackagesCmdFlags(t *testing.T) {
},
{
name: "responds-to-package-cataloger-search-options",
args: []string{"packages", "-vv"},
args: []string{"--help"},
env: map[string]string{
"SYFT_PACKAGE_SEARCH_UNINDEXED_ARCHIVES": "true",
"SYFT_PACKAGE_SEARCH_INDEXED_ARCHIVES": "false",
@@ -213,7 +237,7 @@ func TestPackagesCmdFlags(t *testing.T) {
// the application config in the log matches that of what we expect to have been configured.
assertInOutput("parallelism: 2"),
assertInOutput("parallelism=2"),
assertPackageCount(24),
assertPackageCount(coverageImageSquashedPackageCount),
assertSuccessfulReturnCode,
},
},
@@ -224,7 +248,7 @@ func TestPackagesCmdFlags(t *testing.T) {
// the application config in the log matches that of what we expect to have been configured.
assertInOutput("parallelism: 1"),
assertInOutput("parallelism=1"),
assertPackageCount(24),
assertPackageCount(coverageImageSquashedPackageCount),
assertSuccessfulReturnCode,
},
},
@@ -238,7 +262,7 @@ func TestPackagesCmdFlags(t *testing.T) {
assertions: []traitAssertion{
assertNotInOutput("secret_password"),
assertNotInOutput("secret_key_path"),
assertPackageCount(24),
assertPackageCount(coverageImageSquashedPackageCount),
assertSuccessfulReturnCode,
},
},
@@ -258,7 +282,7 @@ func TestPackagesCmdFlags(t *testing.T) {
func TestRegistryAuth(t *testing.T) {
host := "localhost:17"
image := fmt.Sprintf("%s/something:latest", host)
args := []string{"packages", "-vv", fmt.Sprintf("registry:%s", image)}
args := []string{"packages", "-vvv", fmt.Sprintf("registry:%s", image)}
tests := []struct {
name string
@@ -272,7 +296,7 @@ func TestRegistryAuth(t *testing.T) {
assertions: []traitAssertion{
assertInOutput("source=OciRegistry"),
assertInOutput(image),
assertInOutput("no registry credentials configured, using the default keychain"),
assertInOutput(fmt.Sprintf("no registry credentials configured for %q, using the default keychain", host)),
},
},
{
@@ -294,7 +318,7 @@ func TestRegistryAuth(t *testing.T) {
args: args,
env: map[string]string{
"SYFT_REGISTRY_AUTH_AUTHORITY": host,
"SYFT_REGISTRY_AUTH_TOKEN": "token",
"SYFT_REGISTRY_AUTH_TOKEN": "my-token",
},
assertions: []traitAssertion{
assertInOutput("source=OciRegistry"),
@@ -303,7 +327,7 @@ func TestRegistryAuth(t *testing.T) {
},
},
{
name: "not enough info fallsback to keychain",
name: "not enough info fallback to keychain",
args: args,
env: map[string]string{
"SYFT_REGISTRY_AUTH_AUTHORITY": host,
@@ -311,7 +335,7 @@ func TestRegistryAuth(t *testing.T) {
assertions: []traitAssertion{
assertInOutput("source=OciRegistry"),
assertInOutput(image),
assertInOutput(`no registry credentials configured, using the default keychain`),
assertInOutput(fmt.Sprintf(`no registry credentials configured for %q, using the default keychain`, host)),
},
},
{
@@ -324,6 +348,17 @@ func TestRegistryAuth(t *testing.T) {
assertInOutput("insecure-use-http: true"),
},
},
{
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"),
},
},
}
for _, test := range tests {
@@ -1,4 +1,4 @@
FROM debian:sid
FROM debian:sid@sha256:bee393b48f83fdeb978ce68abb9dc955d6398b984fca88b52a09dceb45ac74b5
ADD sources.list /etc/apt/sources.list.d/sources.list
RUN apt update -y && apt install -y dpkg-dev
# this as a "macho-invalid" directory which is useful for testing
@@ -1,4 +1,4 @@
FROM centos:7.9.2009
FROM centos:7.9.2009@sha256:dead07b4d8ed7e29e98de0f4504d87e8880d4347859d839686a31da35a3b532f
# all-layers scope should pickup on vsftpd
RUN yum install -y vsftpd
RUN yum remove -y vsftpd
RUN yum remove -y vsftpd
@@ -1,4 +1,4 @@
FROM openjdk:11
FROM openjdk:11@sha256:e81b7f317654b0f26d3993e014b04bcb29250339b11b9de41e130feecd4cd43c
RUN wget --no-verbose https://github.com/spdx/tools-java/releases/download/v1.1.3/tools-java-1.1.3.zip && \
unzip tools-java-1.1.3.zip && \
@@ -1 +1 @@
FROM node:19-alpine3.15
FROM node:19-alpine3.15@sha256:07050181369f52460e788738272bcb22b71c7cfc6fafee0b5cd27d2022513a86
+1 -1
View File
@@ -1 +1 @@
FROM alpine:latest
FROM alpine@sha256:c5c5fda71656f28e49ac9c5416b3643eaa6a108a8093151d6d1afc9463be8e33
+11 -44
View File
@@ -4,8 +4,6 @@ import (
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"sort"
"strings"
@@ -85,11 +83,20 @@ func assertNotInOutput(data string) traitAssertion {
}
}
func assertNoStderr(tb testing.TB, _, stderr string, _ int) {
tb.Helper()
if len(stderr) > 0 {
tb.Errorf("expected stderr to be empty, but got %q", stderr)
}
}
func assertInOutput(data string) traitAssertion {
return func(tb testing.TB, stdout, stderr string, _ int) {
tb.Helper()
if !strings.Contains(stripansi.Strip(stderr), data) && !strings.Contains(stripansi.Strip(stdout), data) {
tb.Errorf("data=%q was NOT found in any output, but should have been there", data)
stdout = stripansi.Strip(stdout)
stderr = stripansi.Strip(stderr)
if !strings.Contains(stdout, data) && !strings.Contains(stderr, data) {
tb.Errorf("data=%q was NOT found in any output, but should have been there\nSTDOUT:%s\nSTDERR:%s", data, stdout, stderr)
}
}
}
@@ -148,46 +155,6 @@ func assertSuccessfulReturnCode(tb testing.TB, _, _ string, rc int) {
}
}
func assertVerifyAttestation(coverageImage string) traitAssertion {
return func(tb testing.TB, stdout, _ string, _ int) {
tb.Helper()
cosignPath := filepath.Join(repoRoot(tb), ".tmp/cosign")
err := os.WriteFile("attestation.json", []byte(stdout), 0664)
if err != nil {
tb.Errorf("could not write attestation to disk")
}
defer os.Remove("attestation.json")
attachCmd := exec.Command(
cosignPath,
"attach",
"attestation",
"--attestation",
"attestation.json",
coverageImage, // TODO which remote image to use?
)
stdout, stderr, _ := runCommand(attachCmd, nil)
if attachCmd.ProcessState.ExitCode() != 0 {
tb.Log("STDOUT", stdout)
tb.Log("STDERR", stderr)
tb.Fatalf("could not attach image")
}
verifyCmd := exec.Command(
cosignPath,
"verify-attestation",
coverageImage, // TODO which remote image to use?
)
stdout, stderr, _ = runCommand(verifyCmd, nil)
if attachCmd.ProcessState.ExitCode() != 0 {
tb.Log("STDOUT", stdout)
tb.Log("STDERR", stderr)
tb.Fatalf("could not verify attestation")
}
}
}
func assertFileExists(file string) traitAssertion {
return func(tb testing.TB, _, _ string, _ int) {
tb.Helper()
@@ -1,2 +1,2 @@
FROM alpine:3.6
RUN apk update && apk add python3 wget unzip make ca-certificates
FROM alpine:3.6@sha256:66790a2b79e1ea3e1dabac43990c54aca5d1ddf268d9a5a0285e4167c8b24475
RUN apk update && apk add python3 wget unzip make ca-certificates
@@ -1,2 +1,2 @@
FROM ubuntu:20.04
RUN apt update -y && apt install make python3 curl unzip -y
FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba
RUN apt update -y && apt install make python3 curl unzip -y
@@ -247,6 +247,8 @@ var dirOnlyTestCases = []testCase{
"Serilog.Sinks.Console": "4.0.1",
"System.Diagnostics.DiagnosticSource": "6.0.0",
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
"TestCommon": "1.0.0",
"TestLibrary": "1.0.0",
},
},
{
@@ -368,6 +370,20 @@ var dirOnlyTestCases = []testCase{
"swift-numerics": "1.0.2",
},
},
{
name: "find github action packages (from usage in workflow files and composite actions)",
pkgType: pkg.GithubActionPkg,
pkgInfo: map[string]string{
"actions/checkout": "v4",
},
},
{
name: "find github shared workflow calls (from usage in workflow files)",
pkgType: pkg.GithubActionWorkflowPkg,
pkgInfo: map[string]string{
"octo-org/this-repo/.github/workflows/workflow-1.yml": "172239021f7ba04fe7327647b213799853a9eb89",
},
},
}
var commonTestCases = []testCase{
+4 -2
View File
@@ -23,7 +23,7 @@ func BenchmarkImagePackageCatalogers(b *testing.B) {
tarPath := imagetest.GetFixtureImageTarPath(b, fixtureImageName)
var pc *pkg.Collection
for _, c := range cataloger.ImageCatalogers(defaultConfig()) {
for _, c := range cataloger.ImageCatalogers(cataloger.DefaultConfig()) {
// in case of future alteration where state is persisted, assume no dependency is safe to reuse
userInput := "docker-archive:" + tarPath
detection, err := source.Detect(userInput, source.DefaultDetectConfig())
@@ -96,6 +96,8 @@ func TestPkgCoverageImage(t *testing.T) {
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
definedPkgs.Remove(string(pkg.SwiftPkg))
definedPkgs.Remove(string(pkg.GithubActionPkg))
definedPkgs.Remove(string(pkg.GithubActionWorkflowPkg))
var cases []testCase
cases = append(cases, commonTestCases...)
@@ -260,7 +262,7 @@ func TestPkgCoverageCatalogerConfiguration(t *testing.T) {
assert.Equal(t, definedLanguages, observedLanguages)
// Verify that rust isn't actually an image cataloger
c := defaultConfig()
c := cataloger.DefaultConfig()
c.Catalogers = []string{"rust"}
assert.Len(t, cataloger.ImageCatalogers(c), 0)
}
+7 -7
View File
@@ -1,15 +1,14 @@
package integration
import (
"context"
"fmt"
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/anchore/syft/cmd/syft/cli/convert"
"github.com/anchore/syft/internal/config"
"github.com/anchore/syft/cmd/syft/cli/commands"
"github.com/anchore/syft/cmd/syft/cli/options"
"github.com/anchore/syft/syft/formats"
"github.com/anchore/syft/syft/formats/cyclonedxjson"
"github.com/anchore/syft/syft/formats/cyclonedxxml"
@@ -72,9 +71,10 @@ func TestConvertCmd(t *testing.T) {
_ = os.Remove(syftFile.Name())
}()
ctx := context.Background()
app := &config.Application{
Outputs: []string{fmt.Sprintf("%s=%s", test.format.ID().String(), formatFile.Name())},
opts := &commands.ConvertOptions{
MultiOutput: options.MultiOutput{
Outputs: []string{fmt.Sprintf("%s=%s", test.format.ID().String(), formatFile.Name())},
},
}
// stdout reduction of test noise
@@ -84,7 +84,7 @@ func TestConvertCmd(t *testing.T) {
os.Stdout = rescue
}()
err = convert.Run(ctx, app, []string{syftFile.Name()})
err = commands.RunConvert(opts, syftFile.Name())
require.NoError(t, err)
contents, err := os.ReadFile(formatFile.Name())
require.NoError(t, err)
+3 -3
View File
@@ -47,8 +47,8 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
formatOption: cyclonedxjson.ID,
redactor: func(in []byte) []byte {
// unstable values
in = regexp.MustCompile(`"(timestamp|serialNumber|bom-ref)": "[^"]+",`).ReplaceAll(in, []byte{})
in = regexp.MustCompile(`"(timestamp|serialNumber|bom-ref|ref)":\s*"(\n|[^"])+"`).ReplaceAll(in, []byte(`"$1": "redacted"`))
in = regexp.MustCompile(`"(dependsOn)":\s*\[(?:\s|[^]])+]`).ReplaceAll(in, []byte(`"$1": []`))
return in
},
json: true,
@@ -57,7 +57,7 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
formatOption: cyclonedxxml.ID,
redactor: func(in []byte) []byte {
// unstable values
in = regexp.MustCompile(`(serialNumber|bom-ref)="[^"]+"`).ReplaceAll(in, []byte{})
in = regexp.MustCompile(`(serialNumber|bom-ref|ref)="[^"]+"`).ReplaceAll(in, []byte{})
in = regexp.MustCompile(`<timestamp>[^<]+</timestamp>`).ReplaceAll(in, []byte{})
return in
@@ -0,0 +1,62 @@
package integration
import (
"testing"
"github.com/anchore/syft/syft/cpe"
"github.com/anchore/syft/syft/source"
)
func TestGolangCompilerDetection(t *testing.T) {
tests := []struct {
name string
image string
expectedCompilers []string
expectedCPE []cpe.CPE
expectedPURL []string
}{
{
name: "syft can detect a single golang compiler given the golang base image",
image: "image-golang-compiler",
expectedCompilers: []string{"go1.18.10"},
expectedCPE: []cpe.CPE{cpe.Must("cpe:2.3:a:golang:go:1.18.10:-:*:*:*:*:*:*")},
expectedPURL: []string{"pkg:golang/stdlib@1.18.10"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sbom, _ := catalogFixtureImage(t, tt.image, source.SquashedScope, nil)
packages := sbom.Artifacts.Packages.PackagesByName("stdlib")
foundCompilerVersions := make(map[string]struct{})
foundCPE := make(map[cpe.CPE]struct{})
foundPURL := make(map[string]struct{})
for _, pkg := range packages {
foundCompilerVersions[pkg.Version] = struct{}{}
foundPURL[pkg.PURL] = struct{}{}
for _, cpe := range pkg.CPEs {
foundCPE[cpe] = struct{}{}
}
}
for _, expectedCompiler := range tt.expectedCompilers {
if _, ok := foundCompilerVersions[expectedCompiler]; !ok {
t.Fatalf("expected %s version; not found in found compilers: %v", expectedCompiler, foundCompilerVersions)
}
}
for _, expectedPURL := range tt.expectedPURL {
if _, ok := foundPURL[expectedPURL]; !ok {
t.Fatalf("expected %s purl; not found in found purl: %v", expectedPURL, expectedPURLs)
}
}
for _, expectedCPE := range tt.expectedCPE {
if _, ok := foundCPE[expectedCPE]; !ok {
t.Fatalf("expected %s version; not found in found cpe: %v", expectedCPE, expectedCPE)
}
}
})
}
}
+197
View File
@@ -0,0 +1,197 @@
package integration
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/source"
)
func TestJavaPURLs(t *testing.T) {
sbom, _ := catalogFixtureImage(t, "image-test-java-purls", source.SquashedScope, nil)
found := make(map[string]string)
for _, p := range sbom.Artifacts.Packages.Sorted() {
if p.Type != pkg.JavaPkg && p.Type != pkg.JenkinsPluginPkg {
continue
}
key := fmt.Sprintf("%s@%s", p.Name, p.Version)
found[key] = p.PURL
}
for key, expectedPURL := range expectedPURLs {
purl := found[key]
assert.Equal(t, expectedPURL, purl, fmt.Sprintf("found wrong or missing PURL for %s want %s, got %s", key, expectedPURL, purl))
}
for key, foundPURL := range found {
expectedPURL := expectedPURLs[key]
assert.Equal(t, expectedPURL, foundPURL, fmt.Sprintf("found extra purl for %s want %s, got %s", key, expectedPURL, foundPURL))
}
}
// Constructed by:
// syft anchore/test_images:java-56d52bc -o template -t /tmp/test.templ | grep 'pkg:maven' | sort | uniq >> test/integration/java_purl_test.go
// where the template is:
/*
{{ range .Artifacts}}"{{.Name}}@{{.Version}}":"{{.PURL}}",
{{ end }}
*/
// The map was then hand-edited for correctness by comparing to Maven Central.
var expectedPURLs = map[string]string{
"TwilioNotifier@0.2.1": "pkg:maven/com.twilio.jenkins/TwilioNotifier@0.2.1",
"access-modifier-annotation@1.0": "pkg:maven/org.kohsuke/access-modifier-annotation@1.0",
"acegi-security@1.0.5": "pkg:maven/org.acegisecurity/acegi-security@1.0.5",
"activation@1.1.1-hudson-1": "pkg:maven/org.jvnet.hudson/activation@1.1.1-hudson-1",
"akuma@1.2": "pkg:maven/com.sun.akuma/akuma@1.2",
"animal-sniffer-annotation@1.0": "pkg:maven/org.jvnet/animal-sniffer-annotation@1.0",
"annotation-indexer@1.2": "pkg:maven/org.jvnet.hudson/annotation-indexer@1.2",
"annotations@13.0": "pkg:maven/org.jetbrains/annotations@13.0",
"ant-launcher@1.8.0": "pkg:maven/org.apache.ant/ant-launcher@1.8.0",
"ant@1.8.0": "pkg:maven/org.apache.ant/ant@1.8.0",
"antlr@2.7.6": "pkg:maven/antlr/antlr@2.7.6",
"aopalliance@1.0": "pkg:maven/aopalliance/aopalliance@1.0",
"args4j@2.0.16": "pkg:maven/args4j/args4j@2.0.16",
"asm-commons@2.2.3": "pkg:maven/asm-commons/asm-commons@2.2.3",
"asm-tree@2.2.3": "pkg:maven/asm-tree/asm-tree@2.2.3",
"asm@2.2.3": "pkg:maven/asm/asm@2.2.3",
"avalon-framework@4.1.3": "pkg:maven/avalon-framework/avalon-framework@4.1.3",
"bridge-method-annotation@1.2": "pkg:maven/com.infradna.tool/bridge-method-annotation@1.2",
"classworlds@1.1": "pkg:maven/org.codehaus.classworlds/classworlds@1.1",
"cli@1.390": "pkg:maven/org.jvnet.hudson.main/cli@1.390",
"commons-beanutils@1.8.0": "pkg:maven/commons-beanutils/commons-beanutils@1.8.0",
"commons-codec@1.2": "pkg:maven/commons-codec/commons-codec@1.2",
"commons-codec@1.4": "pkg:maven/commons-codec/commons-codec@1.4",
"commons-collections@3.2": "pkg:maven/commons-collections/commons-collections@3.2",
"commons-digester@1.7": "pkg:maven/commons-digester/commons-digester@1.7",
"commons-discovery@0.4": "pkg:maven/commons-discovery/commons-discovery@0.4",
"commons-fileupload@1.2.1": "pkg:maven/commons-fileupload/commons-fileupload@1.2.1",
"commons-httpclient@3.1": "pkg:maven/org.apache/commons-httpclient@3.1",
"commons-httpclient@3.1-rc1": "pkg:maven/commons-httpclient/commons-httpclient@3.1-rc1",
"commons-io@1.4": "pkg:maven/commons-io/commons-io@1.4",
"commons-jelly-tags-define@1.0.1-hudson-20071021": "pkg:maven/org.jvnet.hudson/commons-jelly-tags-define@1.0.1-hudson-20071021",
"commons-jelly-tags-fmt@1.0": "pkg:maven/commons-jelly-tags-fmt/commons-jelly-tags-fmt@1.0",
"commons-jelly-tags-xml@1.1": "pkg:maven/commons-jelly-tags-xml/commons-jelly-tags-xml@1.1",
"commons-jelly@1.1-hudson-20100305": "pkg:maven/org.jvnet.hudson/commons-jelly@1.1-hudson-20100305",
"commons-jexl@1.1-hudson-20090508": "pkg:maven/org.jvnet.hudson/commons-jexl@1.1-hudson-20090508",
"commons-lang@2.4": "pkg:maven/commons-lang/commons-lang@2.4",
"commons-lang@2.5": "pkg:maven/commons-lang/commons-lang@2.5",
"commons-logging@1.0.4": "pkg:maven/commons-logging/commons-logging@1.0.4", // see https://mvnrepository.com/artifact/commons-logging/commons-logging/1.0.4
"commons-logging@1.1": "pkg:maven/commons-logging/commons-logging@1.1", // see https://mvnrepository.com/artifact/commons-logging/commons-logging/1.1
"commons-logging@1.1.1": "pkg:maven/commons-logging/commons-logging@1.1.1", // see https://mvnrepository.com/artifact/commons-logging/commons-logging/1.1.1
"commons-pool@1.3": "pkg:maven/commons-pool/commons-pool@1.3",
"crypto-util@1.0": "pkg:maven/org.jvnet.hudson/crypto-util@1.0",
"cvs@1.2": "pkg:maven/org.jvnet.hudson.plugins/cvs@1.2",
"dom4j@1.6.1-hudson-3": "pkg:maven/dom4j/dom4j@1.6.1-hudson-3",
"doxia-sink-api@1.0-alpha-10": "pkg:maven/org.apache.maven.doxia/doxia-sink-api@1.0-alpha-10",
"easymock@2.4": "pkg:maven/org.easymock/easymock@2.4",
"embedded_su4j@1.1": "pkg:maven/com.sun.solaris/embedded_su4j@1.1",
"example-java-app-gradle@0.1.0": "pkg:maven/example-java-app-gradle/example-java-app-gradle@0.1.0",
"ezmorph@1.0.3": "pkg:maven/net.sf.ezmorph/ezmorph@1.0.3",
"graph-layouter@1.0": "pkg:maven/org.kohsuke/graph-layouter@1.0",
"groovy-all@1.6.0": "pkg:maven/groovy-all/groovy-all@1.6.0",
"gson@2.8.6": "pkg:maven/com.google.code.gson/gson@2.8.6",
"guava@r06": "pkg:maven/com.google.guava/guava@r06",
"httpclient@4.1.1": "pkg:maven/org.apache.httpcomponents/httpclient@4.1.1",
"httpcore@4.1": "pkg:maven/org.apache.httpcomponents/httpcore@4.1",
"hudson-cli@": "pkg:maven/hudson-cli/hudson-cli",
"hudson-core@1.390": "pkg:maven/org.jvnet.hudson.main/hudson-core@1.390",
"hudson-war@1.390": "pkg:maven/org.jvnet.hudson.main/hudson-war@1.390",
"j-interop@2.0.5": "pkg:maven/j-interop/j-interop@2.0.5",
"j-interopdeps@2.0.5": "pkg:maven/j-interopdeps/j-interopdeps@2.0.5",
"jaxen@1.1-beta-11": "pkg:maven/org.jaxen/jaxen@1.1-beta-11",
"jcaptcha-all@1.0-RC6": "pkg:maven/jcaptcha-all/jcaptcha-all@1.0-RC6",
"jcifs@1.3.14-kohsuke-1": "pkg:maven/org.samba.jcifs/jcifs@1.3.14-kohsuke-1",
"jcommon@1.0.12": "pkg:maven/jfree/jcommon@1.0.12",
"jfreechart@1.0.9": "pkg:maven/jfreechart/jfreechart@1.0.9",
"jinterop-proxy@1.1": "pkg:maven/org.kohsuke.jinterop/jinterop-proxy@1.1",
"jinterop-wmi@1.0": "pkg:maven/org.jvnet.hudson/jinterop-wmi@1.0",
"jline@0.9.94": "pkg:maven/jline/jline@0.9.94",
"jmdns@3.1.6-hudson-2": "pkg:maven/com.strangeberry.jmdns.tools.Main/jmdns@3.1.6-hudson-2",
"jna-posix@1.0.3": "pkg:maven/org.jruby.ext.posix/jna-posix@1.0.3",
"jna@3.2.4": "pkg:maven/com.sun.jna/jna@3.2.4",
"jsch@0.1.27": "pkg:maven/jsch/jsch@0.1.27",
"json-lib@2.1-rev6": "pkg:maven/json-lib/json-lib@2.1-rev6",
"json@20200518": "pkg:maven/org.json/json@20200518",
"jstl@1.1.0": "pkg:maven/com.sun/jstl@1.1.0",
"jtidy@4aug2000r7-dev-hudson-1": "pkg:maven/jtidy/jtidy@4aug2000r7-dev-hudson-1",
"junit@4.13.1": "pkg:maven/junit/junit@4.13.1",
"kotlin-stdlib-common@1.3.70": "pkg:maven/kotlin-stdlib-common/kotlin-stdlib-common@1.3.70",
"kotlin-stdlib@1.3.70": "pkg:maven/kotlin-stdlib/kotlin-stdlib@1.3.70",
"libpam4j@1.2": "pkg:maven/org.jvnet.libpam4j/libpam4j@1.2",
"libzfs@0.5": "pkg:maven/org.jvnet.libzfs/libzfs@0.5",
"localizer@1.10": "pkg:maven/org.jvnet.localizer/localizer@1.10",
"log4j@1.2.9": "pkg:maven/log4j/log4j@1.2.9",
"logkit@1.0.1": "pkg:maven/logkit/logkit@1.0.1",
"mail@1.4": "pkg:maven/com.sun/mail@1.4",
"maven-agent@1.390": "pkg:maven/org.jvnet.hudson.main/maven-agent@1.390",
"maven-artifact-manager@2.0.9": "pkg:maven/org.apache.maven/maven-artifact-manager@2.0.9",
"maven-artifact@2.0.9": "pkg:maven/org.apache.maven/maven-artifact@2.0.9",
"maven-core@2.0.9": "pkg:maven/org.apache.maven/maven-core@2.0.9",
"maven-embedder@2.0.4": "pkg:maven/org.apache.maven/maven-embedder@2.0.4",
"maven-embedder@2.0.4-hudson-1": "pkg:maven/org.jvnet.hudson/maven-embedder@2.0.4-hudson-1",
"maven-error-diagnostics@2.0.9": "pkg:maven/org.apache.maven/maven-error-diagnostics@2.0.9",
"maven-interceptor@1.390": "pkg:maven/org.jvnet.hudson.main/maven-interceptor@1.390",
"maven-model@2.0.9": "pkg:maven/org.apache.maven/maven-model@2.0.9",
"maven-monitor@2.0.9": "pkg:maven/org.apache.maven/maven-monitor@2.0.9",
"maven-plugin-api@2.0.9": "pkg:maven/org.apache.maven/maven-plugin-api@2.0.9",
"maven-plugin-descriptor@2.0.9": "pkg:maven/org.apache.maven/maven-plugin-descriptor@2.0.9",
"maven-plugin-parameter-documenter@2.0.9": "pkg:maven/org.apache.maven/maven-plugin-parameter-documenter@2.0.9",
"maven-plugin-registry@2.0.9": "pkg:maven/org.apache.maven/maven-plugin-registry@2.0.9",
"maven-plugin@1.390": "pkg:maven/org.jvnet.hudson.main/maven-plugin@1.390",
"maven-profile@2.0.9": "pkg:maven/org.apache.maven/maven-profile@2.0.9",
"maven-project@2.0.9": "pkg:maven/org.apache.maven/maven-project@2.0.9",
"maven-reporting-api@2.0.9": "pkg:maven/org.apache.maven.reporting/maven-reporting-api@2.0.9",
"maven-repository-metadata@2.0.9": "pkg:maven/org.apache.maven/maven-repository-metadata@2.0.9",
"maven-settings@2.0.9": "pkg:maven/org.apache.maven/maven-settings@2.0.9",
"maven2.1-interceptor@1.2": "pkg:maven/org.jvnet.hudson/maven2.1-interceptor@1.2",
"memory-monitor@1.3": "pkg:maven/org.jvnet.hudson/memory-monitor@1.3",
"nomad@0.7.4": "pkg:maven/org.jenkins-ci.plugins/nomad@0.7.4",
"okhttp@4.5.0": "pkg:maven/com.squareup.okhttp3/okhttp@4.5.0",
"okio@2.5.0": "pkg:maven/com.squareup.okio/okio@2.5.0",
"oro@2.0.8": "pkg:maven/org.apache.oro/oro@2.0.8",
"plexus-container-default@1.0-alpha-9-stable-1": "pkg:maven/org.codehaus.plexus/plexus-container-default@1.0-alpha-9-stable-1",
"plexus-interactivity-api@1.0-alpha-4": "pkg:maven/org.codehaus.plexus/plexus-interactivity-api@1.0-alpha-4",
"plexus-utils@1.5.1": "pkg:maven/org.codehaus.plexus/plexus-utils@1.5.1",
"remoting@1.390": "pkg:maven/org.jvnet.hudson.main/remoting@1.390",
"robust-http-client@1.1": "pkg:maven/org.jvnet.robust-http-client/robust-http-client@1.1",
"sdk@3.0": "pkg:maven/sdk/sdk@3.0",
"sezpoz@1.7": "pkg:maven/net.java.sezpoz/sezpoz@1.7",
"slave@": "pkg:maven/slave/slave",
"slide-webdavlib@2.1": "pkg:maven/slide-webdavlib/slide-webdavlib@2.1",
"spring-aop@2.5": "pkg:maven/org.springframework.bundle.spring.aop/spring-aop@2.5",
"spring-beans@2.5": "pkg:maven/org.springframework/spring-beans@2.5",
"spring-context@2.5": "pkg:maven/org.springframework.bundle.spring.context/spring-context@2.5",
"spring-core@2.5": "pkg:maven/org.springframework/spring-core@2.5",
"spring-dao@1.2.9": "pkg:maven/spring-dao/spring-dao@1.2.9",
"spring-jdbc@1.2.9": "pkg:maven/spring-jdbc/spring-jdbc@1.2.9",
"spring-web@2.5": "pkg:maven/org.springframework/spring-web@2.5",
"ssh-slaves@0.14": "pkg:maven/org.jvnet.hudson.plugins/ssh-slaves@0.14",
"stapler-adjunct-timeline@1.2": "pkg:maven/org.kohsuke.stapler/stapler-adjunct-timeline@1.2",
"stapler-jelly@1.155": "pkg:maven/org.kohsuke.stapler/stapler-jelly@1.155",
"stapler@1.155": "pkg:maven/org.kohsuke.stapler/stapler@1.155",
"stax-api@1.0.1": "pkg:maven/stax-api/stax-api@1.0.1",
"subversion@1.20": "pkg:maven/org.jvnet.hudson.plugins/subversion@1.20",
"svnkit@1.3.4-hudson-2": "pkg:maven/svnkit/svnkit@1.3.4-hudson-2",
"task-reactor@1.2": "pkg:maven/org.jvnet.hudson/task-reactor@1.2",
"tiger-types@1.3": "pkg:maven/org.jvnet/tiger-types@1.3",
"trilead-putty-extension@1.0": "pkg:maven/org.kohsuke/trilead-putty-extension@1.0",
"trilead-ssh2@build212-hudson-5": "pkg:maven/org.jvnet.hudson/trilead-ssh2@build212-hudson-5",
"txw2@20070624": "pkg:maven/txw2/txw2@20070624",
"wagon-file@1.0-beta-2": "pkg:maven/org.apache.maven.wagon/wagon-file@1.0-beta-2",
"wagon-http-lightweight@1.0-beta-2": "pkg:maven/org.apache.maven.wagon/wagon-http-lightweight@1.0-beta-2",
"wagon-http-shared@1.0-beta-2": "pkg:maven/org.apache.maven.wagon/wagon-http-shared@1.0-beta-2",
"wagon-provider-api@1.0-beta-2": "pkg:maven/org.apache.maven.wagon/wagon-provider-api@1.0-beta-2",
"wagon-ssh-common@1.0-beta-2": "pkg:maven/org.apache.maven.wagon/wagon-ssh-common@1.0-beta-2",
"wagon-ssh-external@1.0-beta-2": "pkg:maven/org.apache.maven.wagon/wagon-ssh-external@1.0-beta-2",
"wagon-ssh@1.0-beta-2": "pkg:maven/org.apache.maven.wagon/wagon-ssh@1.0-beta-2",
"wagon-webdav@1.0-beta-2-hudson-1": "pkg:maven/org.jvnet.hudson/wagon-webdav@1.0-beta-2-hudson-1",
"windows-remote-command@1.0": "pkg:maven/org.jvnet.hudson/windows-remote-command@1.0",
"winp@1.14": "pkg:maven/org.jvnet.winp/winp@1.14",
"winstone@0.9.10-hudson-24": "pkg:maven/org.jvnet.hudson.winstone/winstone@0.9.10-hudson-24",
"wstx-asl@3.2.7": "pkg:maven/wstx-asl/wstx-asl@3.2.7",
"xml-im-exporter@1.1": "pkg:maven/xml-im-exporter/xml-im-exporter@1.1",
"xpp3@1.1.4c": "pkg:maven/xpp3/xpp3@1.1.4c",
"xpp3_min@1.1.4c": "pkg:maven/xpp3_min/xpp3_min@1.1.4c",
"xstream@1.3.1-hudson-8": "pkg:maven/org.jvnet.hudson/xstream@1.3.1-hudson-8",
}
@@ -10,9 +10,9 @@ import (
func TestRegressionGoArchDiscovery(t *testing.T) {
const (
expectedELFPkg = 4
expectedWINPkg = 4
expectedMACOSPkg = 4
expectedELFPkg = 5
expectedWINPkg = 5
expectedMACOSPkg = 5
)
// This is a regression test to make sure the way we detect go binary packages
// stays consistent and reproducible as the tool chain evolves
@@ -0,0 +1,36 @@
package integration
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/source"
)
func TestWarCatalogedCorrectlyIfRenamed(t *testing.T) {
// install hudson-war@2.2.1 and renames the file to `/hudson.war`
sbom, _ := catalogFixtureImage(t, "image-java-virtualpath-regression", source.SquashedScope, nil)
badPURL := "pkg:maven/hudson/hudson@2.2.1"
goodPURL := "pkg:maven/org.jvnet.hudson.main/hudson-war@2.2.1"
foundCorrectPackage := false
badVirtualPath := "/hudson.war:org.jvnet.hudson.main:hudson-war"
goodVirtualPath := "/hudson.war"
for _, p := range sbom.Artifacts.Packages.Sorted() {
if p.Type == pkg.JavaPkg && strings.Contains(p.Name, "hudson") {
assert.NotEqual(t, badPURL, p.PURL, "must not find bad purl %q", badPURL)
virtPath := ""
if meta, ok := p.Metadata.(pkg.JavaMetadata); ok {
virtPath = meta.VirtualPath
if p.PURL == goodPURL && virtPath == goodVirtualPath {
foundCorrectPackage = true
}
}
assert.NotEqual(t, badVirtualPath, virtPath, "must not find bad virtual path %q", badVirtualPath)
}
}
assert.True(t, foundCorrectPackage, "must find correct package, but did not")
}
@@ -1,3 +1,3 @@
FROM busybox:1.31.1
FROM busybox:1.31.1@sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209
@@ -1,4 +1,4 @@
FROM golang:latest as builder
FROM golang:1.21.1@sha256:cffaba795c36f07e372c7191b35ceaae114d74c31c3763d442982e3a4df3b39e as builder
WORKDIR /app
COPY go.sum go.mod app.go ./
@@ -0,0 +1 @@
FROM golang:1.18.10-alpine
@@ -1,4 +1,4 @@
FROM jenkins/jenkins:2.346.3-slim-jdk17
FROM jenkins/jenkins:2.346.3-slim-jdk17@sha256:028fbbd9112c60ed086f5197fcba71992317864d27644e5949cf9c52ff4b65f0
USER root
@@ -0,0 +1,7 @@
FROM alpine:3.18.3@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a
RUN wget https://repo1.maven.org/maven2/org/jvnet/hudson/main/hudson-war/2.2.1/hudson-war-2.2.1.war
RUN mv hudson-war-2.2.1.war hudson.war
@@ -1,4 +1,4 @@
FROM alpine:latest
FROM alpine:3.18.3@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a
# syft should not longer show the binary package for this image:
# https://github.com/anchore/syft/issues/931
@@ -1,3 +1,3 @@
FROM ubuntu:20.04
FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba
# this covers rpm-python
RUN apt-get update && apt-get install -y python-pil=6.2.1-3
RUN apt-get update && apt-get install -y python-pil=6.2.1-3
@@ -1 +1 @@
FROM photon:5.0-20230729
FROM photon:5.0-20230729@sha256:4cf2a1ce0a3f4625f13a0becb6b9bccfdb014c565be6e9a2ec4c4aad1ff8a5d9
@@ -0,0 +1,18 @@
name: "Validations"
on:
workflow_dispatch:
pull_request:
push:
branches:
- main
jobs:
call-workflow-1-in-local-repo:
uses: octo-org/this-repo/.github/workflows/workflow-1.yml@172239021f7ba04fe7327647b213799853a9eb89
Unit-Test:
name: "Unit tests"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
@@ -1,2 +1,2 @@
# An image containing the example hello-auditable binary from https://github.com/Shnatsel/rust-audit/tree/master/hello-auditable
FROM docker.io/tofay/hello-rust-auditable:latest
FROM docker.io/tofay/hello-rust-auditable@sha256:1d35d1e007180b3f7500aae5e27560697909132ca9a6d480c4c825534c1c47a9
@@ -1,2 +1,2 @@
FROM registry.suse.com/suse/sle15:15.3.17.20.20
FROM registry.suse.com/suse/sle15:15.3.17.20.20@sha256:fd657ecbab5ca564d6933e887f6ae8542a9398e6a4b399f352ce10c3a24afc64
RUN zypper in -y wget
@@ -0,0 +1 @@
FROM anchore/test_images@sha256:10008791acbc5866de04108746a02a0c4029ce3a4400a9b3dad45d7f2245f9da
@@ -1,6 +1,6 @@
FROM centos:7.9.2009
FROM centos:7.9.2009@sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4
# modifying the RPM DB multiple times will result in duplicate packages when using all-layers (if there was no de-dup logic)
# curl is tricky, it already exists in the image and is being upgraded
RUN yum install -y wget-1.14-18.el7_6.1 curl-7.29.0-59.el7_9.1
RUN yum install -y vsftpd-3.0.2-29.el7_9
RUN yum install -y httpd-2.4.6-97.el7.centos.5
RUN yum install -y httpd-2.4.6-97.el7.centos.5
+2 -14
View File
@@ -8,8 +8,6 @@ import (
"github.com/anchore/stereoscope/pkg/imagetest"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/pkg/cataloger"
"github.com/anchore/syft/syft/pkg/cataloger/kernel"
"github.com/anchore/syft/syft/pkg/cataloger/python"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
)
@@ -26,7 +24,7 @@ func catalogFixtureImage(t *testing.T, fixtureImageName string, scope source.Sco
theSource.Close()
})
c := defaultConfig()
c := cataloger.DefaultConfig()
c.Catalogers = catalogerCfg
c.Search.Scope = scope
@@ -54,16 +52,6 @@ func catalogFixtureImage(t *testing.T, fixtureImageName string, scope source.Sco
}, theSource
}
func defaultConfig() cataloger.Config {
return cataloger.Config{
Search: cataloger.DefaultSearchConfig(),
Parallelism: 1,
LinuxKernel: kernel.DefaultLinuxCatalogerConfig(),
Python: python.DefaultCatalogerConfig(),
ExcludeBinaryOverlapByOwnership: true,
}
}
func catalogDirectory(t *testing.T, dir string) (sbom.SBOM, source.Source) {
userInput := "dir:" + dir
detection, err := source.Detect(userInput, source.DefaultDetectConfig())
@@ -75,7 +63,7 @@ func catalogDirectory(t *testing.T, dir string) (sbom.SBOM, source.Source) {
})
// TODO: this would be better with functional options (after/during API refactor)
c := defaultConfig()
c := cataloger.DefaultConfig()
c.Search.Scope = source.AllLayersScope
pkgCatalog, relationships, actualDistro, err := syft.CatalogPackages(theSource, c)
if err != nil {