mirror of
https://github.com/kubescape/kubescape.git
synced 2026-02-14 09:59:54 +00:00
Merge pull request #1932 from kubescape/scan-images
add verbose option to scan-images
This commit is contained in:
57298
core/cautils/getter/testdata/policy.json
vendored
57298
core/cautils/getter/testdata/policy.json
vendored
File diff suppressed because one or more lines are too long
@@ -70,7 +70,7 @@ func (jp *JsonPrinter) convertToImageScanSummary(imageScanData []cautils.ImageSc
|
||||
imageScanSummary.Images = append(imageScanSummary.Images, imageScanData[i].Image)
|
||||
}
|
||||
|
||||
CVEs := extractCVEs(imageScanData[i].Matches)
|
||||
CVEs := extractCVEs(imageScanData[i].Matches, imageScanData[i].Image)
|
||||
imageScanSummary.CVEs = append(imageScanSummary.CVEs, CVEs...)
|
||||
|
||||
setPkgNameToScoreMap(imageScanData[i].Matches, imageScanSummary.PackageScores)
|
||||
|
||||
@@ -55,13 +55,13 @@ func NewPrettyPrinter(verboseMode bool, formatVersion string, attackTree bool, v
|
||||
func (pp *PrettyPrinter) SetMainPrinter() {
|
||||
switch pp.scanType {
|
||||
case cautils.ScanTypeCluster:
|
||||
pp.mainPrinter = prettyprinter.NewClusterPrinter(pp.writer)
|
||||
pp.mainPrinter = prettyprinter.NewClusterPrinter(pp.writer, pp.verboseMode)
|
||||
case cautils.ScanTypeRepo:
|
||||
pp.mainPrinter = prettyprinter.NewRepoPrinter(pp.writer, pp.inputPatterns)
|
||||
pp.mainPrinter = prettyprinter.NewRepoPrinter(pp.writer, pp.inputPatterns, pp.verboseMode)
|
||||
case cautils.ScanTypeImage:
|
||||
pp.mainPrinter = prettyprinter.NewImagePrinter(pp.writer, pp.verboseMode)
|
||||
case cautils.ScanTypeWorkload:
|
||||
pp.mainPrinter = prettyprinter.NewWorkloadPrinter(pp.writer)
|
||||
pp.mainPrinter = prettyprinter.NewWorkloadPrinter(pp.writer, pp.verboseMode)
|
||||
default:
|
||||
pp.mainPrinter = prettyprinter.NewSummaryPrinter(pp.writer, pp.verboseMode)
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func (pp *PrettyPrinter) convertToImageScanSummary(imageScanData []cautils.Image
|
||||
imageScanSummary.Images = append(imageScanSummary.Images, imageScanData[i].Image)
|
||||
}
|
||||
|
||||
CVEs := extractCVEs(imageScanData[i].Matches)
|
||||
CVEs := extractCVEs(imageScanData[i].Matches, imageScanData[i].Image)
|
||||
imageScanSummary.CVEs = append(imageScanSummary.CVEs, CVEs...)
|
||||
|
||||
setPkgNameToScoreMap(imageScanData[i].Matches, imageScanSummary.PackageScores)
|
||||
|
||||
@@ -14,20 +14,30 @@ import (
|
||||
type ClusterPrinter struct {
|
||||
writer *os.File
|
||||
categoriesTablePrinter configurationprinter.TablePrinter
|
||||
imageTablePrinter imageprinter.TablePrinter
|
||||
verboseMode bool
|
||||
}
|
||||
|
||||
func NewClusterPrinter(writer *os.File) *ClusterPrinter {
|
||||
func NewClusterPrinter(writer *os.File, verboseMode bool) *ClusterPrinter {
|
||||
return &ClusterPrinter{
|
||||
writer: writer,
|
||||
categoriesTablePrinter: configurationprinter.NewClusterPrinter(),
|
||||
imageTablePrinter: imageprinter.NewTableWriter(),
|
||||
verboseMode: verboseMode,
|
||||
}
|
||||
}
|
||||
|
||||
var _ MainPrinter = &ClusterPrinter{}
|
||||
|
||||
func (cp *ClusterPrinter) PrintImageScanning(summary *imageprinter.ImageScanSummary) {
|
||||
printImageScanningSummary(cp.writer, *summary, false)
|
||||
printImagesCommands(cp.writer, *summary)
|
||||
if cp.verboseMode {
|
||||
cp.imageTablePrinter.PrintImageScanningTable(cp.writer, *summary)
|
||||
cautils.SimpleDisplay(cp.writer, "\n")
|
||||
}
|
||||
printImageScanningSummary(cp.writer, *summary, cp.verboseMode)
|
||||
if !cp.verboseMode {
|
||||
printImagesCommands(cp.writer, *summary)
|
||||
}
|
||||
}
|
||||
|
||||
func (cp *ClusterPrinter) PrintConfigurationsScanning(summaryDetails *reportsummary.SummaryDetails, sortedControlIDs [][]string, topWorkloadsByScore []reporthandling.IResource) {
|
||||
|
||||
@@ -42,17 +42,21 @@ func TestClusterScan_getWorkloadScanCommand(t *testing.T) {
|
||||
|
||||
func TestNewClusterPrinter(t *testing.T) {
|
||||
// Test case 1: Valid writer
|
||||
cp := NewClusterPrinter(os.Stdout)
|
||||
cp := NewClusterPrinter(os.Stdout, false)
|
||||
assert.NotNil(t, cp)
|
||||
assert.Equal(t, os.Stdout, cp.writer)
|
||||
assert.NotNil(t, cp.categoriesTablePrinter)
|
||||
assert.NotNil(t, cp.imageTablePrinter)
|
||||
assert.False(t, cp.verboseMode)
|
||||
|
||||
// Test case 2: Nil writer
|
||||
var writer *os.File
|
||||
cp = NewClusterPrinter(writer)
|
||||
cp = NewClusterPrinter(writer, true)
|
||||
assert.NotNil(t, cp)
|
||||
assert.Nil(t, cp.writer)
|
||||
assert.NotNil(t, cp.categoriesTablePrinter)
|
||||
assert.NotNil(t, cp.imageTablePrinter)
|
||||
assert.True(t, cp.verboseMode)
|
||||
}
|
||||
|
||||
func TestPrintNextSteps(t *testing.T) {
|
||||
@@ -63,7 +67,7 @@ func TestPrintNextSteps(t *testing.T) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
cp := NewClusterPrinter(f)
|
||||
cp := NewClusterPrinter(f, false)
|
||||
|
||||
// Redirect stderr to the temporary file
|
||||
oldStderr := os.Stderr
|
||||
@@ -88,7 +92,7 @@ func TestPrintNextSteps(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetWorkloadScanCommand(t *testing.T) {
|
||||
cp := NewClusterPrinter(os.Stdout)
|
||||
cp := NewClusterPrinter(os.Stdout, false)
|
||||
assert.NotNil(t, cp)
|
||||
assert.Equal(t, os.Stdout, cp.writer)
|
||||
assert.NotNil(t, cp.categoriesTablePrinter)
|
||||
|
||||
@@ -3,6 +3,7 @@ package prettyprinter
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
@@ -15,6 +16,7 @@ type SummaryPrinter struct {
|
||||
writer *os.File
|
||||
verboseMode bool
|
||||
summaryTablePrinter configurationprinter.TablePrinter
|
||||
imageTablePrinter imageprinter.TablePrinter
|
||||
}
|
||||
|
||||
func NewSummaryPrinter(writer *os.File, verboseMode bool) *SummaryPrinter {
|
||||
@@ -22,12 +24,21 @@ func NewSummaryPrinter(writer *os.File, verboseMode bool) *SummaryPrinter {
|
||||
writer: writer,
|
||||
verboseMode: verboseMode,
|
||||
summaryTablePrinter: configurationprinter.NewFrameworkPrinter(verboseMode),
|
||||
imageTablePrinter: imageprinter.NewTableWriter(),
|
||||
}
|
||||
}
|
||||
|
||||
var _ MainPrinter = &RepoPrinter{}
|
||||
|
||||
func (sp *SummaryPrinter) PrintImageScanning(*imageprinter.ImageScanSummary) {}
|
||||
func (sp *SummaryPrinter) PrintImageScanning(summary *imageprinter.ImageScanSummary) {
|
||||
if sp.verboseMode {
|
||||
sp.imageTablePrinter.PrintImageScanningTable(sp.writer, *summary)
|
||||
cautils.SimpleDisplay(sp.writer, "\n")
|
||||
}
|
||||
printImageScanningSummary(sp.writer, *summary, sp.verboseMode)
|
||||
if !sp.verboseMode {
|
||||
printImagesCommands(sp.writer, *summary)
|
||||
}
|
||||
printTopComponents(sp.writer, *summary)
|
||||
}
|
||||
|
||||
func (sp *SummaryPrinter) PrintNextSteps() {}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ func TestNewSummaryPrinter(t *testing.T) {
|
||||
assert.Equal(t, os.Stdout, printer.writer)
|
||||
assert.Equal(t, verbose, printer.verboseMode)
|
||||
assert.NotNil(t, printer.summaryTablePrinter)
|
||||
assert.NotNil(t, printer.imageTablePrinter)
|
||||
|
||||
// Test case 2: Valid writer and non-verbose mode
|
||||
verbose = false
|
||||
@@ -23,6 +24,7 @@ func TestNewSummaryPrinter(t *testing.T) {
|
||||
assert.Equal(t, os.Stdout, printer.writer)
|
||||
assert.Equal(t, verbose, printer.verboseMode)
|
||||
assert.NotNil(t, printer.summaryTablePrinter)
|
||||
assert.NotNil(t, printer.imageTablePrinter)
|
||||
|
||||
// Test case 3: Nil writer and verbose mode
|
||||
var writer *os.File
|
||||
@@ -32,6 +34,7 @@ func TestNewSummaryPrinter(t *testing.T) {
|
||||
assert.Nil(t, printer.writer)
|
||||
assert.Equal(t, verbose, printer.verboseMode)
|
||||
assert.NotNil(t, printer.summaryTablePrinter)
|
||||
assert.NotNil(t, printer.imageTablePrinter)
|
||||
|
||||
// Test case 4: Nil writer and non-verbose mode
|
||||
verbose = false
|
||||
@@ -40,6 +43,7 @@ func TestNewSummaryPrinter(t *testing.T) {
|
||||
assert.Nil(t, printer.writer)
|
||||
assert.Equal(t, verbose, printer.verboseMode)
|
||||
assert.NotNil(t, printer.summaryTablePrinter)
|
||||
assert.NotNil(t, printer.imageTablePrinter)
|
||||
}
|
||||
|
||||
func TestGetVerboseMode(t *testing.T) {
|
||||
|
||||
@@ -15,20 +15,30 @@ import (
|
||||
type RepoPrinter struct {
|
||||
writer *os.File
|
||||
categoriesTablePrinter configurationprinter.TablePrinter
|
||||
imageTablePrinter imageprinter.TablePrinter
|
||||
verboseMode bool
|
||||
}
|
||||
|
||||
func NewRepoPrinter(writer *os.File, inputPatterns []string) *RepoPrinter {
|
||||
func NewRepoPrinter(writer *os.File, inputPatterns []string, verboseMode bool) *RepoPrinter {
|
||||
return &RepoPrinter{
|
||||
writer: writer,
|
||||
categoriesTablePrinter: configurationprinter.NewRepoPrinter(inputPatterns),
|
||||
imageTablePrinter: imageprinter.NewTableWriter(),
|
||||
verboseMode: verboseMode,
|
||||
}
|
||||
}
|
||||
|
||||
var _ MainPrinter = &RepoPrinter{}
|
||||
|
||||
func (rp *RepoPrinter) PrintImageScanning(summary *imageprinter.ImageScanSummary) {
|
||||
printImageScanningSummary(rp.writer, *summary, false)
|
||||
printImagesCommands(rp.writer, *summary)
|
||||
if rp.verboseMode {
|
||||
rp.imageTablePrinter.PrintImageScanningTable(rp.writer, *summary)
|
||||
cautils.SimpleDisplay(rp.writer, "\n")
|
||||
}
|
||||
printImageScanningSummary(rp.writer, *summary, rp.verboseMode)
|
||||
if !rp.verboseMode {
|
||||
printImagesCommands(rp.writer, *summary)
|
||||
}
|
||||
printTopComponents(rp.writer, *summary)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ type CVE struct {
|
||||
Version string
|
||||
FixVersions []string
|
||||
FixedState string
|
||||
Image string
|
||||
}
|
||||
|
||||
type PackageScore struct {
|
||||
|
||||
@@ -10,6 +10,7 @@ const (
|
||||
imageColumnComponent = iota
|
||||
imageColumnVersion = iota
|
||||
imageColumnFixedIn = iota
|
||||
imageColumnImage = iota
|
||||
)
|
||||
|
||||
type TableWriter struct {
|
||||
|
||||
@@ -25,6 +25,7 @@ func TestPrintImageScanningTable(t *testing.T) {
|
||||
Package: "package1",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "nginx:latest",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-0002",
|
||||
@@ -32,6 +33,7 @@ func TestPrintImageScanningTable(t *testing.T) {
|
||||
Package: "package2",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "alpine:3.18",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-0003",
|
||||
@@ -39,10 +41,11 @@ func TestPrintImageScanningTable(t *testing.T) {
|
||||
Package: "package3",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "ubuntu:22.04",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: "╭──────────┬───────────────┬───────────┬─────────┬──────────╮\n│ Severity │ Vulnerability │ Component │ Version │ Fixed in │\n├──────────┼───────────────┼───────────┼─────────┼──────────┤\n│ High │ CVE-2020-0002 │ package2 │ 1.0.0 │ │\n│ Medium │ CVE-2020-0003 │ package3 │ 1.0.0 │ │\n│ Low │ CVE-2020-0001 │ package1 │ 1.0.0 │ │\n╰──────────┴───────────────┴───────────┴─────────┴──────────╯\n",
|
||||
want: "╭──────────┬───────────────┬───────────┬─────────┬──────────┬──────────────╮\n│ Severity │ Vulnerability │ Component │ Version │ Fixed in │ Image │\n├──────────┼───────────────┼───────────┼─────────┼──────────┼──────────────┤\n│ High │ CVE-2020-0002 │ package2 │ 1.0.0 │ │ alpine:3.18 │\n│ Medium │ CVE-2020-0003 │ package3 │ 1.0.0 │ │ ubuntu:22.04 │\n│ Low │ CVE-2020-0001 │ package1 │ 1.0.0 │ │ nginx:latest │\n╰──────────┴───────────────┴───────────┴─────────┴──────────┴──────────────╯\n",
|
||||
},
|
||||
{
|
||||
name: "check fixed CVEs show versions",
|
||||
@@ -54,6 +57,7 @@ func TestPrintImageScanningTable(t *testing.T) {
|
||||
Package: "package1",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "test:latest",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-0002",
|
||||
@@ -62,10 +66,11 @@ func TestPrintImageScanningTable(t *testing.T) {
|
||||
Version: "1.0.0",
|
||||
FixVersions: []string{"v1", "v2"},
|
||||
FixedState: string(v5.FixedState),
|
||||
Image: "golang:1.24",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: "╭──────────┬───────────────┬───────────┬─────────┬──────────╮\n│ Severity │ Vulnerability │ Component │ Version │ Fixed in │\n├──────────┼───────────────┼───────────┼─────────┼──────────┤\n│ High │ CVE-2020-0002 │ package2 │ 1.0.0 │ v1,v2 │\n│ Low │ CVE-2020-0001 │ package1 │ 1.0.0 │ │\n╰──────────┴───────────────┴───────────┴─────────┴──────────╯\n",
|
||||
want: "╭──────────┬───────────────┬───────────┬─────────┬──────────┬─────────────╮\n│ Severity │ Vulnerability │ Component │ Version │ Fixed in │ Image │\n├──────────┼───────────────┼───────────┼─────────┼──────────┼─────────────┤\n│ High │ CVE-2020-0002 │ package2 │ 1.0.0 │ v1,v2 │ golang:1.24 │\n│ Low │ CVE-2020-0001 │ package1 │ 1.0.0 │ │ test:latest │\n╰──────────┴───────────────┴───────────┴─────────┴──────────┴─────────────╯\n",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,12 @@ func renderTable(writer io.Writer, headers table.Row, columnAlignments []table.C
|
||||
func generateRows(summary ImageScanSummary) []table.Row {
|
||||
rows := make([]table.Row, 0, len(summary.CVEs))
|
||||
|
||||
// sort CVEs by severity
|
||||
// sort CVEs by severity (descending) and then by CVE ID (ascending)
|
||||
sort.Slice(summary.CVEs, func(i, j int) bool {
|
||||
return utils.ImageSeverityToInt(summary.CVEs[i].Severity) > utils.ImageSeverityToInt(summary.CVEs[j].Severity)
|
||||
if utils.ImageSeverityToInt(summary.CVEs[i].Severity) != utils.ImageSeverityToInt(summary.CVEs[j].Severity) {
|
||||
return utils.ImageSeverityToInt(summary.CVEs[i].Severity) > utils.ImageSeverityToInt(summary.CVEs[j].Severity)
|
||||
}
|
||||
return summary.CVEs[i].ID < summary.CVEs[j].ID
|
||||
})
|
||||
|
||||
for _, cve := range summary.CVEs {
|
||||
@@ -42,11 +45,12 @@ func generateRows(summary ImageScanSummary) []table.Row {
|
||||
}
|
||||
|
||||
func generateRow(cve CVE) table.Row {
|
||||
row := make(table.Row, 5)
|
||||
row := make(table.Row, 6)
|
||||
row[imageColumnSeverity] = utils.GetColorForVulnerabilitySeverity(cve.Severity)(cve.Severity)
|
||||
row[imageColumnName] = cve.ID
|
||||
row[imageColumnComponent] = cve.Package
|
||||
row[imageColumnVersion] = cve.Version
|
||||
row[imageColumnImage] = cve.Image
|
||||
|
||||
// if the CVE is fixed, show all the versions that fix it
|
||||
if cve.FixedState == string(v5.FixedState) {
|
||||
@@ -62,12 +66,13 @@ func generateRow(cve CVE) table.Row {
|
||||
}
|
||||
|
||||
func getImageScanningHeaders() table.Row {
|
||||
headers := make(table.Row, 5)
|
||||
headers := make(table.Row, 6)
|
||||
headers[imageColumnSeverity] = "Severity"
|
||||
headers[imageColumnName] = "Vulnerability"
|
||||
headers[imageColumnComponent] = "Component"
|
||||
headers[imageColumnVersion] = "Version"
|
||||
headers[imageColumnFixedIn] = "Fixed in"
|
||||
headers[imageColumnImage] = "Image"
|
||||
return headers
|
||||
}
|
||||
|
||||
@@ -78,5 +83,6 @@ func getImageScanningColumnsAlignments() []table.ColumnConfig {
|
||||
{Number: 3, Align: text.AlignLeft},
|
||||
{Number: 4, Align: text.AlignLeft},
|
||||
{Number: 5, Align: text.AlignLeft},
|
||||
{Number: 6, Align: text.AlignLeft},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ func TestRenderTable(t *testing.T) {
|
||||
Package: "package1",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "nginx:latest",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-0002",
|
||||
@@ -35,6 +36,7 @@ func TestRenderTable(t *testing.T) {
|
||||
Package: "package2",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "alpine:3.18",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-0003",
|
||||
@@ -42,10 +44,11 @@ func TestRenderTable(t *testing.T) {
|
||||
Package: "package3",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "ubuntu:22.04",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: "╭──────────┬───────────────┬───────────┬─────────┬──────────╮\n│ Severity │ Vulnerability │ Component │ Version │ Fixed in │\n├──────────┼───────────────┼───────────┼─────────┼──────────┤\n│ High │ CVE-2020-0002 │ package2 │ 1.0.0 │ │\n│ Medium │ CVE-2020-0003 │ package3 │ 1.0.0 │ │\n│ Low │ CVE-2020-0001 │ package1 │ 1.0.0 │ │\n╰──────────┴───────────────┴───────────┴─────────┴──────────╯\n",
|
||||
want: "╭──────────┬───────────────┬───────────┬─────────┬──────────┬──────────────╮\n│ Severity │ Vulnerability │ Component │ Version │ Fixed in │ Image │\n├──────────┼───────────────┼───────────┼─────────┼──────────┼──────────────┤\n│ High │ CVE-2020-0002 │ package2 │ 1.0.0 │ │ alpine:3.18 │\n│ Medium │ CVE-2020-0003 │ package3 │ 1.0.0 │ │ ubuntu:22.04 │\n│ Low │ CVE-2020-0001 │ package1 │ 1.0.0 │ │ nginx:latest │\n╰──────────┴───────────────┴───────────┴─────────┴──────────┴──────────────╯\n",
|
||||
},
|
||||
{
|
||||
name: "check fixed CVEs show versions",
|
||||
@@ -57,6 +60,7 @@ func TestRenderTable(t *testing.T) {
|
||||
Package: "package1",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "test:latest",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-0002",
|
||||
@@ -65,10 +69,11 @@ func TestRenderTable(t *testing.T) {
|
||||
Version: "1.0.0",
|
||||
FixVersions: []string{"v1", "v2"},
|
||||
FixedState: string(v5.FixedState),
|
||||
Image: "golang:1.24",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: "╭──────────┬───────────────┬───────────┬─────────┬──────────╮\n│ Severity │ Vulnerability │ Component │ Version │ Fixed in │\n├──────────┼───────────────┼───────────┼─────────┼──────────┤\n│ High │ CVE-2020-0002 │ package2 │ 1.0.0 │ v1,v2 │\n│ Low │ CVE-2020-0001 │ package1 │ 1.0.0 │ │\n╰──────────┴───────────────┴───────────┴─────────┴──────────╯\n",
|
||||
want: "╭──────────┬───────────────┬───────────┬─────────┬──────────┬─────────────╮\n│ Severity │ Vulnerability │ Component │ Version │ Fixed in │ Image │\n├──────────┼───────────────┼───────────┼─────────┼──────────┼─────────────┤\n│ High │ CVE-2020-0002 │ package2 │ 1.0.0 │ v1,v2 │ golang:1.24 │\n│ Low │ CVE-2020-0001 │ package1 │ 1.0.0 │ │ test:latest │\n╰──────────┴───────────────┴───────────┴─────────┴──────────┴─────────────╯\n",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -121,6 +126,7 @@ func TestGenerateRows(t *testing.T) {
|
||||
Package: "package1",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "nginx:latest",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-0002",
|
||||
@@ -128,6 +134,7 @@ func TestGenerateRows(t *testing.T) {
|
||||
Package: "package2",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "alpine:3.18",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-0003",
|
||||
@@ -135,13 +142,14 @@ func TestGenerateRows(t *testing.T) {
|
||||
Package: "package3",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "ubuntu:22.04",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedRows: [][]string{
|
||||
{"High", "CVE-2020-0002", "package2", "1.0.0", ""},
|
||||
{"Medium", "CVE-2020-0003", "package3", "1.0.0", ""},
|
||||
{"Low", "CVE-2020-0001", "package1", "1.0.0", ""},
|
||||
{"High", "CVE-2020-0002", "package2", "1.0.0", "", "alpine:3.18"},
|
||||
{"Medium", "CVE-2020-0003", "package3", "1.0.0", "", "ubuntu:22.04"},
|
||||
{"Low", "CVE-2020-0001", "package1", "1.0.0", "", "nginx:latest"},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -154,6 +162,7 @@ func TestGenerateRows(t *testing.T) {
|
||||
Package: "package1",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "test:latest",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-0002",
|
||||
@@ -162,12 +171,13 @@ func TestGenerateRows(t *testing.T) {
|
||||
Version: "1.0.0",
|
||||
FixVersions: []string{"v1", "v2"},
|
||||
FixedState: string(v5.FixedState),
|
||||
Image: "golang:1.24",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedRows: [][]string{
|
||||
{"High", "CVE-2020-0002", "package2", "1.0.0", "v1,v2"},
|
||||
{"Low", "CVE-2020-0001", "package1", "1.0.0", ""},
|
||||
{"High", "CVE-2020-0002", "package2", "1.0.0", "v1,v2", "golang:1.24"},
|
||||
{"Low", "CVE-2020-0001", "package1", "1.0.0", "", "test:latest"},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -206,8 +216,9 @@ func TestGenerateRow(t *testing.T) {
|
||||
Version: "1.0.0",
|
||||
FixVersions: []string{"v1", "v2"},
|
||||
FixedState: string(v5.FixedState),
|
||||
Image: "golang:1.24",
|
||||
},
|
||||
want: []string{"High", "CVE-2020-0001", "package1", "1.0.0", "v1,v2"},
|
||||
want: []string{"High", "CVE-2020-0001", "package1", "1.0.0", "v1,v2", "golang:1.24"},
|
||||
},
|
||||
{
|
||||
name: "check row with not fixed version",
|
||||
@@ -217,8 +228,9 @@ func TestGenerateRow(t *testing.T) {
|
||||
Package: "package1",
|
||||
Version: "1.0.0",
|
||||
FixedState: string(v5.NotFixedState),
|
||||
Image: "nginx:latest",
|
||||
},
|
||||
want: []string{"High", "CVE-2020-0001", "package1", "1.0.0", ""},
|
||||
want: []string{"High", "CVE-2020-0001", "package1", "1.0.0", "", "nginx:latest"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -238,7 +250,7 @@ func TestGenerateRow(t *testing.T) {
|
||||
func TestGetImageScanningHeaders(t *testing.T) {
|
||||
headers := getImageScanningHeaders()
|
||||
|
||||
expectedHeaders := []string{"Severity", "Vulnerability", "Component", "Version", "Fixed in"}
|
||||
expectedHeaders := []string{"Severity", "Vulnerability", "Component", "Version", "Fixed in", "Image"}
|
||||
|
||||
for i := range headers {
|
||||
if headers[i] != expectedHeaders[i] {
|
||||
|
||||
@@ -3,6 +3,7 @@ package prettyprinter
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
@@ -12,20 +13,30 @@ import (
|
||||
type WorkloadPrinter struct {
|
||||
writer *os.File
|
||||
categoriesTablePrinter configurationprinter.TablePrinter
|
||||
imageTablePrinter imageprinter.TablePrinter
|
||||
verboseMode bool
|
||||
}
|
||||
|
||||
func NewWorkloadPrinter(writer *os.File) *WorkloadPrinter {
|
||||
func NewWorkloadPrinter(writer *os.File, verboseMode bool) *WorkloadPrinter {
|
||||
return &WorkloadPrinter{
|
||||
writer: writer,
|
||||
categoriesTablePrinter: configurationprinter.NewWorkloadPrinter(),
|
||||
imageTablePrinter: imageprinter.NewTableWriter(),
|
||||
verboseMode: verboseMode,
|
||||
}
|
||||
}
|
||||
|
||||
var _ MainPrinter = &WorkloadPrinter{}
|
||||
|
||||
func (wp *WorkloadPrinter) PrintImageScanning(summary *imageprinter.ImageScanSummary) {
|
||||
printImageScanningSummary(wp.writer, *summary, false)
|
||||
printImagesCommands(wp.writer, *summary)
|
||||
if wp.verboseMode {
|
||||
wp.imageTablePrinter.PrintImageScanningTable(wp.writer, *summary)
|
||||
cautils.SimpleDisplay(wp.writer, "\n")
|
||||
}
|
||||
printImageScanningSummary(wp.writer, *summary, wp.verboseMode)
|
||||
if !wp.verboseMode {
|
||||
printImagesCommands(wp.writer, *summary)
|
||||
}
|
||||
}
|
||||
|
||||
func (wp *WorkloadPrinter) PrintNextSteps() {
|
||||
|
||||
@@ -289,7 +289,7 @@ func setPkgNameToScoreMap(matches match.Matches, pkgScores map[string]*imageprin
|
||||
}
|
||||
}
|
||||
|
||||
func extractCVEs(matches match.Matches) []imageprinter.CVE {
|
||||
func extractCVEs(matches match.Matches, image string) []imageprinter.CVE {
|
||||
var CVEs []imageprinter.CVE
|
||||
for _, m := range matches.Sorted() {
|
||||
cve := imageprinter.CVE{
|
||||
@@ -299,6 +299,7 @@ func extractCVEs(matches match.Matches) []imageprinter.CVE {
|
||||
Version: m.Package.Version,
|
||||
FixVersions: m.Vulnerability.Fix.Versions,
|
||||
FixedState: m.Vulnerability.Fix.State.String(),
|
||||
Image: image,
|
||||
}
|
||||
CVEs = append(CVEs, cve)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ func TestExtractCVEs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
matches match.Matches
|
||||
image string
|
||||
want []imageprinter.CVE
|
||||
}{
|
||||
{
|
||||
@@ -40,6 +41,7 @@ func TestExtractCVEs(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}...),
|
||||
image: "nginx:latest",
|
||||
want: []imageprinter.CVE{
|
||||
{
|
||||
ID: "CVE-2020-1234",
|
||||
@@ -48,6 +50,7 @@ func TestExtractCVEs(t *testing.T) {
|
||||
Version: "1.2.3",
|
||||
FixVersions: []string{"1.2.3"},
|
||||
FixedState: "Fixed",
|
||||
Image: "nginx:latest",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -106,6 +109,7 @@ func TestExtractCVEs(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}...),
|
||||
image: "golang:1.24.6",
|
||||
want: []imageprinter.CVE{
|
||||
{
|
||||
ID: "CVE-2020-1234",
|
||||
@@ -114,6 +118,7 @@ func TestExtractCVEs(t *testing.T) {
|
||||
Version: "1.2.3",
|
||||
FixVersions: []string{"1.2.3"},
|
||||
FixedState: "Fixed",
|
||||
Image: "golang:1.24.6",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-1235",
|
||||
@@ -122,6 +127,7 @@ func TestExtractCVEs(t *testing.T) {
|
||||
Version: "1",
|
||||
FixVersions: []string{"1"},
|
||||
FixedState: "Fixed",
|
||||
Image: "golang:1.24.6",
|
||||
},
|
||||
{
|
||||
ID: "CVE-2020-1236",
|
||||
@@ -130,19 +136,21 @@ func TestExtractCVEs(t *testing.T) {
|
||||
Version: "3",
|
||||
FixVersions: []string{"2", "3", "4"},
|
||||
FixedState: "Not fixed",
|
||||
Image: "golang:1.24.6",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty vulns",
|
||||
matches: match.NewMatches([]match.Match{}...),
|
||||
image: "test:latest",
|
||||
want: []imageprinter.CVE{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual := extractCVEs(tt.matches)
|
||||
actual := extractCVEs(tt.matches, tt.image)
|
||||
if len(actual) != len(tt.want) {
|
||||
t.Errorf("extractCVEs() = %v, want %v", actual, tt.want)
|
||||
}
|
||||
@@ -170,6 +178,9 @@ func TestExtractCVEs(t *testing.T) {
|
||||
t.Errorf("extractCVEs() = %v, want %v", actual, tt.want)
|
||||
}
|
||||
}
|
||||
if actual[i].Image != tt.want[i].Image {
|
||||
t.Errorf("extractCVEs() image = %v, want %v", actual[i].Image, tt.want[i].Image)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user