Add Linux Kernel cataloger (#1694)

* add kernel handler

Signed-off-by: Avi Deitcher <avi@deitcher.net>

* [wip] combine kernel and kernel module cataloging

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

* [wip] combine kernel and kernel module cataloging

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
Signed-off-by: Avi Deitcher <avi@deitcher.net>

* rename Kernel package to LinuxKernel package

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

* split kernel and module packages within cataloger

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

* wire up application configuration with kernel cataloger options

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

* dont use references for packages on relationships

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

* fix linting and tests

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

* kernel cataloger should be resistent to partial failure

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

* log upon kernel module metadata missing

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

* add tests for linux kernel cataloger

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

* update integration tests

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

* update cli package test counts

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

* add evidence annotations for kernel packages

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

* reduce noise in cli test output

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

* missed cli test to reduce noise for

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

* fix package counts

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

* update docs with linux kernel cataloging refs

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

* bump json schema with new metadata fields

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

---------

Signed-off-by: Avi Deitcher <avi@deitcher.net>
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
Signed-off-by: <>
Co-authored-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
Avi Deitcher
2023-04-14 14:33:36 -04:00
committed by GitHub
co-authored by Alex Goodman
parent 5d156b8241
commit cc731c7b19
37 changed files with 2516 additions and 78 deletions
+1 -5
View File
@@ -55,11 +55,7 @@ func TestAllFormatsConvertable(t *testing.T) {
for _, traitFn := range assertions {
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
})
}
}
+1 -6
View File
@@ -2,7 +2,6 @@ package cli
import (
"fmt"
"strings"
"testing"
"github.com/stretchr/testify/require"
@@ -34,11 +33,7 @@ func TestAllFormatsExpressible(t *testing.T) {
for _, traitFn := range commonAssertions {
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
})
}
}
+1 -5
View File
@@ -40,11 +40,7 @@ func TestConvertCmd(t *testing.T) {
for _, traitFn := range assertions {
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
})
}
}
+3 -15
View File
@@ -52,11 +52,7 @@ func TestValidCycloneDX(t *testing.T) {
for _, traitFn := range test.assertions {
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
validateCycloneDXJSON(t, stdout)
})
@@ -95,11 +91,7 @@ func assertValidCycloneDX(tb testing.TB, stdout, stderr string, rc int) {
tb.Errorf("expected no validation failures for cyclonedx-cli but got rc=%d", rc)
}
if tb.Failed() {
tb.Log("STDOUT:\n", stdout)
tb.Log("STDERR:\n", stderr)
tb.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(tb, cmd, stdout, stderr)
}
// validate --input-format json --input-version v1_4 --input-file bom.json
@@ -134,9 +126,5 @@ func validateCycloneDXJSON(t *testing.T, stdout string) {
t.Errorf("expected no validation failures for cyclonedx-cli but found invalid BOM")
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
}
+1 -6
View File
@@ -2,7 +2,6 @@ package cli
import (
"os/exec"
"strings"
"testing"
"time"
)
@@ -37,10 +36,6 @@ func TestDirectoryScanCompletesWithinTimeout(t *testing.T) {
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
}
+6 -15
View File
@@ -3,7 +3,6 @@ package cli
import (
"fmt"
"path/filepath"
"strings"
"testing"
)
@@ -97,7 +96,7 @@ func TestPackagesCmdFlags(t *testing.T) {
name: "squashed-scope-flag",
args: []string{"packages", "-o", "json", "-s", "squashed", coverageImage},
assertions: []traitAssertion{
assertPackageCount(35),
assertPackageCount(37),
assertSuccessfulReturnCode,
},
},
@@ -214,7 +213,7 @@ func TestPackagesCmdFlags(t *testing.T) {
// the application config in the log matches that of what we expect to have been configured.
assertInOutput("parallelism: 2"),
assertInOutput("parallelism=2"),
assertPackageCount(35),
assertPackageCount(37),
assertSuccessfulReturnCode,
},
},
@@ -225,7 +224,7 @@ func TestPackagesCmdFlags(t *testing.T) {
// the application config in the log matches that of what we expect to have been configured.
assertInOutput("parallelism: 1"),
assertInOutput("parallelism=1"),
assertPackageCount(35),
assertPackageCount(37),
assertSuccessfulReturnCode,
},
},
@@ -239,7 +238,7 @@ func TestPackagesCmdFlags(t *testing.T) {
assertions: []traitAssertion{
assertNotInOutput("secret_password"),
assertNotInOutput("secret_key_path"),
assertPackageCount(35),
assertPackageCount(37),
assertSuccessfulReturnCode,
},
},
@@ -251,11 +250,7 @@ func TestPackagesCmdFlags(t *testing.T) {
for _, traitFn := range test.assertions {
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
})
}
}
@@ -337,11 +332,7 @@ func TestRegistryAuth(t *testing.T) {
for _, traitAssertionFn := range test.assertions {
traitAssertionFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
})
}
}
+1 -6
View File
@@ -1,7 +1,6 @@
package cli
import (
"strings"
"testing"
)
@@ -96,11 +95,7 @@ func TestPowerUserCmdFlags(t *testing.T) {
for _, traitFn := range test.assertions {
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
})
}
}
+2 -11
View File
@@ -3,7 +3,6 @@ package cli
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/sergi/go-diff/diffmatchpatch"
@@ -109,11 +108,7 @@ func TestPersistentFlags(t *testing.T) {
for _, traitFn := range test.assertions {
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
})
}
}
@@ -151,11 +146,7 @@ func TestLogFile(t *testing.T) {
for _, traitFn := range test.assertions {
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
}
if t.Failed() {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
logOutputOnFailure(t, cmd, stdout, stderr)
})
}
}
+11
View File
@@ -3,6 +3,7 @@ package cli
import (
"bufio"
"bytes"
"flag"
"fmt"
"io"
"math"
@@ -21,6 +22,16 @@ import (
"github.com/anchore/stereoscope/pkg/imagetest"
)
var showOutput = flag.Bool("show-output", false, "show stdout and stderr for failing tests")
func logOutputOnFailure(t testing.TB, cmd *exec.Cmd, stdout, stderr string) {
if t.Failed() && showOutput != nil && *showOutput {
t.Log("STDOUT:\n", stdout)
t.Log("STDERR:\n", stderr)
t.Log("COMMAND:", strings.Join(cmd.Args, " "))
}
}
func runAndShow(t *testing.T, cmd *exec.Cmd) {
t.Helper()
@@ -11,6 +11,20 @@ type testCase struct {
}
var imageOnlyTestCases = []testCase{
{
name: "find kernel packages",
pkgType: pkg.LinuxKernelPkg,
pkgInfo: map[string]string{
"linux-kernel": "6.2.9-200.fc37.x86_64",
},
},
{
name: "find kernel module packages",
pkgType: pkg.LinuxKernelModulePkg,
pkgInfo: map[string]string{
"fsa4480": "",
},
},
{
name: "find gemspec packages",
pkgType: pkg.GemPkg,
@@ -221,6 +221,8 @@ func TestPkgCoverageDirectory(t *testing.T) {
observedPkgs.Remove(string(pkg.UnknownPkg))
definedPkgs.Remove(string(pkg.BinaryPkg))
definedPkgs.Remove(string(pkg.UnknownPkg))
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
// for directory scans we should not expect to see any of the following package types
definedPkgs.Remove(string(pkg.KbPkg))
@@ -1,5 +1,22 @@
FROM fedora:37@sha256:3f987b7657e944cf87a129cc262982d4f80e38bd98f7db313ccaf90ca7069dd2
RUN dnf install 'dnf-command(download)' cpio xz -y
RUN dnf download kernel-core kernel-modules-core -y
RUN rpm2cpio kernel-core-*.rpm | cpio -t && \
rpm2cpio kernel-core-*.rpm | cpio -idmv ./lib/modules/6.2.9-200.fc37.x86_64/vmlinuz
RUN rpm2cpio kernel-modules-core-*.rpm | cpio -t && \
rpm2cpio kernel-modules-core-*.rpm | cpio -idmv ./lib/modules/6.2.9-200.fc37.x86_64/kernel/drivers/usb/typec/mux/fsa4480.ko.xz
RUN unxz /lib/modules/6.2.9-200.fc37.x86_64/kernel/drivers/usb/typec/mux/fsa4480.ko.xz
FROM scratch
COPY --from=0 /lib/modules/6.2.9-200.fc37.x86_64/vmlinuz /lib/modules/6.2.9-200.fc37.x86_64/vmlinuz
COPY --from=0 /lib/modules/6.2.9-200.fc37.x86_64/kernel/drivers/usb/typec/mux/fsa4480.ko /lib/modules/6.2.9-200.fc37.x86_64/kernel/drivers/usb/typec/mux/fsa4480.ko
COPY pkgs/ .
# we duplicate to show a package count difference between all-layers and squashed scopes
COPY lib lib
COPY etc/ .
COPY etc/ .