Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): control the information #6854

Merged
merged 27 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions e2e/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func Test_E2E_CLI(t *testing.T) {
// Check log file
logData, _ := utils.ReadFixture(tt.Args.ExpectedLog.LogFile, "output")
validation := tt.Args.ExpectedLog.ValidationFunc(logData)

require.Truef(t, validation, "The output log file 'output/%s' doesn't match the regex validation",
tt.Args.ExpectedLog.LogFile)
}
Expand Down
6 changes: 3 additions & 3 deletions e2e/testcases/e2e-cli-007_scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ func init() { //nolint
Name: "should perform a simple scan [E2E-CLI-007]",
Args: args{
Args: []cmdArgs{
[]string{"scan", "-p", "/path/e2e/fixtures/samples/positive.yaml"},
[]string{"scan", "-p", "/path/e2e/fixtures/samples/positive.yaml", "-v"},
},
},
WantStatus: []int{50},
Validation: func(outputText string) bool {
match1, _ := regexp.MatchString(`Files scanned: \d+`, outputText)
match2, _ := regexp.MatchString(`Parsed files: \d+`, outputText)
match1, _ := regexp.MatchString(`Scanned Files: \d+`, outputText)
match2, _ := regexp.MatchString(`Parsed Files: \d+`, outputText)
match3, _ := regexp.MatchString(`Queries loaded: \d+`, outputText)
match4, _ := regexp.MatchString(`Queries failed to execute: \d+`, outputText)
match5, _ := regexp.MatchString(`Results Summary:`, outputText)
Expand Down
4 changes: 2 additions & 2 deletions e2e/testcases/e2e-cli-027_scan_exclude-paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ func init() { //nolint
Args: args{
Args: []cmdArgs{
[]string{"scan", "--exclude-paths", "/path/test/fixtures/test_swagger/swaggerFileWithoutAuthorizer.yaml",
"-p", "/path/test/fixtures/test_swagger/"},
"-p", "/path/test/fixtures/test_swagger/", "-v"},
},
},
Validation: func(outputText string) bool {
match, _ := regexp.MatchString(`Files scanned: 1`, outputText)
match, _ := regexp.MatchString(`Scanned Files: 1`, outputText)
return match
},
WantStatus: []int{40},
Expand Down
1 change: 1 addition & 0 deletions pkg/engine/inspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ func (c *Inspector) doRun(ctx *QueryContext) (vulns []model.Vulnerability, err e
if r := recover(); r != nil {
errMessage := fmt.Sprintf("Recovered from panic during query '%s' run. ", ctx.Query.Metadata.Query)
err = fmt.Errorf("panic: %v", r)
fmt.Println()
log.Err(err).Msg(errMessage)
}
}()
Expand Down
20 changes: 20 additions & 0 deletions pkg/printer/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,23 @@ func LogLevel(opt interface{}, changed bool) error {
}
return nil
}

type LogSink struct {
logs []string
}

func NewLogger(logs *LogSink) zerolog.Logger {
if logs == nil {
return log.Logger
}
return zerolog.New(logs)
}

func (l *LogSink) Write(p []byte) (n int, err error) {
l.logs = append(l.logs, string(p))
return len(p), nil
}

func (l *LogSink) Index(i int) string {
return l.logs[i]
}
15 changes: 2 additions & 13 deletions pkg/printer/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
)

const (
wordWrapCount = 5
charsLimitPerLine = 255
)

Expand Down Expand Up @@ -102,19 +101,9 @@ func WordWrap(s, indentation string, limit int) string {
}

// PrintResult prints on output the summary results
func PrintResult(summary *model.Summary, failedQueries map[string]error, printer *Printer, usingCustomQueries bool) error {
func PrintResult(summary *model.Summary, printer *Printer, usingCustomQueries bool) error {
log.Debug().Msg("helpers.PrintResult()")
fmt.Printf("Files scanned: %d\n", summary.ScannedFiles)
fmt.Printf("Parsed files: %d\n", summary.ParsedFiles)
fmt.Printf("Queries loaded: %d\n", summary.TotalQueries)

fmt.Printf("Queries failed to execute: %d\n\n", summary.FailedToExecuteQueries)
for queryName, err := range failedQueries {
fmt.Printf("\t- %s:\n", queryName)
fmt.Printf("%s", WordWrap(err.Error(), "\t\t", wordWrapCount))
}

fmt.Printf("------------------------------------\n\n")
fmt.Printf("\n\n")
for index := range summary.Queries {
idx := len(summary.Queries) - index - 1
if summary.Queries[idx].Severity == model.SeverityTrace {
Expand Down
155 changes: 15 additions & 140 deletions pkg/printer/printer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,159 +108,34 @@ var printTests = []struct {
expectedResultFull string
customQueries bool
}{

{
caseTest: test.ComplexSummaryMock,
expectedResult: "Files scanned: 2\n" +
"Parsed files: 2\n" +
"Queries loaded: 3\n" +
"Queries failed to execute: 0\n\n" +
"------------------------------------\n\n" +
"AMI Not Encrypted, Severity: HIGH, Results: 2\n" +
"\t[1]: positive.tf:30\n" +
"\t[2]: positive.tf:35\n" +
"AmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\n" +
"\t[1]: positive.tf:1\n" +
"ALB protocol is HTTP, Severity: HIGH, Results: 2\n" +
"\t[1]: positive.tf:25\n" +
"\t[2]: positive.tf:19\n\n" +
"Results Summary:\n" +
"HIGH: 4\n" +
"MEDIUM: 1\n" +
"LOW: 0\n" +
"INFO: 0\n" +
"TOTAL: 5\n\n",
expectedResultFull: "Files scanned: 2\n" +
"Parsed files: 2\n" +
"Queries loaded: 3\n" +
"Queries failed to execute: 0\n\n" +
"------------------------------------\n\n" +
"AMI Not Encrypted, Severity: HIGH, Results: 2\n" +
"Description: AWS AMI Encryption is not enabled\n" +
"Platform: \n" +
"CWE: 22\n" +
"Learn more about this vulnerability: https://docs.kics.io/latest/queries/-queries/97707503-a22c-4cd7-b7c0-f088fa7cf830\n\n" +
"\t[1]: positive.tf:30\n\n\n\n" +
"\t[2]: positive.tf:35\n\n\n\n" +
"AmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\n" +
"Description: AmazonMQ Broker should have Encryption Options defined\nPlatform: \n" +
"Learn more about this vulnerability: https://docs.kics.io/latest/queries/-queries/aws/3db3f534-e3a3-487f-88c7-0a9fbf64b702\n\n" +
"\t[1]: positive.tf:1\n\n\n\n" +
"ALB protocol is HTTP, Severity: HIGH, Results: 2\n" +
"Description: ALB protocol is HTTP Description\n" +
"Platform: \n" +
"Learn more about this vulnerability: https://docs.kics.io/latest/queries/-queries/de7f5e83-da88-4046-871f-ea18504b1d43\n\n" +
"\t[1]: positive.tf:25\n\n\n\n" +
"\t[2]: positive.tf:19\n\n\n\n\n" +
"Results Summary:\n" +
"HIGH: 4\n" +
"MEDIUM: 1\n" +
"LOW: 0\n" +
"INFO: 0\n" +
"TOTAL: 5\n\n",
customQueries: false,
caseTest: test.ComplexSummaryMock,
expectedResult: "\n\nAMI Not Encrypted, Severity: HIGH, Results: 2\n\t[1]: positive.tf:30\n\t[2]: positive.tf:35\nAmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\n\t[1]: positive.tf:1\nALB protocol is HTTP, Severity: HIGH, Results: 2\n\t[1]: positive.tf:25\n\t[2]: positive.tf:19\n\nResults Summary:\nHIGH: 4\nMEDIUM: 1\nLOW: 0\nINFO: 0\nTOTAL: 5\n\n",
expectedResultFull: "\n\nAMI Not Encrypted, Severity: HIGH, Results: 2\nDescription: AWS AMI Encryption is not enabled\nPlatform: \nCWE: 22\nLearn more about this vulnerability: https://docs.kics.io/latest/queries/-queries/97707503-a22c-4cd7-b7c0-f088fa7cf830\n\n\t[1]: positive.tf:30\n\n\n\n\t[2]: positive.tf:35\n\n\n\nAmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\nDescription: AmazonMQ Broker should have Encryption Options defined\nPlatform: \nLearn more about this vulnerability: https://docs.kics.io/latest/queries/-queries/aws/3db3f534-e3a3-487f-88c7-0a9fbf64b702\n\n\t[1]: positive.tf:1\n\n\n\nALB protocol is HTTP, Severity: HIGH, Results: 2\nDescription: ALB protocol is HTTP Description\nPlatform: \nLearn more about this vulnerability: https://docs.kics.io/latest/queries/-queries/de7f5e83-da88-4046-871f-ea18504b1d43\n\n\t[1]: positive.tf:25\n\n\n\n\t[2]: positive.tf:19\n\n\n\n\nResults Summary:\nHIGH: 4\nMEDIUM: 1\nLOW: 0\nINFO: 0\nTOTAL: 5\n\n",
customQueries: false,
},
{
caseTest: test.ComplexSummaryMock,
expectedResult: "Files scanned: 2\n" +
"Parsed files: 2\n" +
"Queries loaded: 3\n" +
"Queries failed to execute: 0\n\n" +
"------------------------------------\n\n" +
"AMI Not Encrypted, Severity: HIGH, Results: 2\n" +
"\t[1]: positive.tf:30\n" +
"\t[2]: positive.tf:35\n" +
"AmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\n" +
"\t[1]: positive.tf:1\n" +
"ALB protocol is HTTP, Severity: HIGH, Results: 2\n" +
"\t[1]: positive.tf:25\n" +
"\t[2]: positive.tf:19\n\n" +
"Results Summary:\n" +
"HIGH: 4\n" +
"MEDIUM: 1\n" +
"LOW: 0\n" +
"INFO: 0\n" +
"TOTAL: 5\n\n",
expectedResultFull: "Files scanned: 2\n" +
"Parsed files: 2\n" +
"Queries loaded: 3\n" +
"Queries failed to execute: 0\n\n" +
"------------------------------------\n\n" +
"AMI Not Encrypted, Severity: HIGH, Results: 2\n" +
"Description: AWS AMI Encryption is not enabled\n" +
"Platform: \n" +
"CWE: 22\n" +
"\t[1]: positive.tf:30\n\n\n\n" +
"\t[2]: positive.tf:35\n\n\n\n" +
"AmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\n" +
"Description: AmazonMQ Broker should have Encryption Options defined\nPlatform: \n" +
"\t[1]: positive.tf:1\n\n\n\n" +
"ALB protocol is HTTP, Severity: HIGH, Results: 2\n" +
"Description: ALB protocol is HTTP Description\n" +
"Platform: \n" +
"\t[1]: positive.tf:25\n\n\n\n" +
"\t[2]: positive.tf:19\n\n\n\n\n" +
"Results Summary:\n" +
"HIGH: 4\n" +
"MEDIUM: 1\n" +
"LOW: 0\n" +
"INFO: 0\n" +
"TOTAL: 5\n\n",
customQueries: true,
caseTest: test.ComplexSummaryMock,
expectedResult: "\n\nAMI Not Encrypted, Severity: HIGH, Results: 2\n\t[1]: positive.tf:30\n\t[2]: positive.tf:35\nAmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\n\t[1]: positive.tf:1\nALB protocol is HTTP, Severity: HIGH, Results: 2\n\t[1]: positive.tf:25\n\t[2]: positive.tf:19\n\nResults Summary:\nHIGH: 4\nMEDIUM: 1\nLOW: 0\nINFO: 0\nTOTAL: 5\n\n",
expectedResultFull: "\n\nAMI Not Encrypted, Severity: HIGH, Results: 2\nDescription: AWS AMI Encryption is not enabled\nPlatform: \nCWE: 22\n\t[1]: positive.tf:30\n\n\n\n\t[2]: positive.tf:35\n\n\n\nAmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\nDescription: AmazonMQ Broker should have Encryption Options defined\nPlatform: \n\t[1]: positive.tf:1\n\n\n\nALB protocol is HTTP, Severity: HIGH, Results: 2\nDescription: ALB protocol is HTTP Description\nPlatform: \n\t[1]: positive.tf:25\n\n\n\n\t[2]: positive.tf:19\n\n\n\n\nResults Summary:\nHIGH: 4\nMEDIUM: 1\nLOW: 0\nINFO: 0\nTOTAL: 5\n\n",
customQueries: true,
},
{
caseTest: test.ComplexSummaryMockWithExperimental,
expectedResult: "Files scanned: 2\n" +
"Parsed files: 2\n" +
"Queries loaded: 2\n" +
"Queries failed to execute: 0\n\n" +
"------------------------------------\n\n" +
"AmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\n" +
"\t[1]: positive.tf:1\n" +
"ALB protocol is HTTP, Severity: HIGH, Results: 2\n" +
"Note: this is an experimental query\n" +
"\t[1]: positive.tf:25\n" +
"\t[2]: positive.tf:19\n\n" +
"Results Summary:\n" +
"HIGH: 2\n" +
"MEDIUM: 1\n" +
"LOW: 0\n" +
"INFO: 0\n" +
"TOTAL: 3\n\n",
expectedResultFull: "Files scanned: 2\n" +
"Parsed files: 2\n" +
"Queries loaded: 2\n" +
"Queries failed to execute: 0\n\n" +
"------------------------------------\n\n" +
"AmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\n" +
"Description: AmazonMQ Broker should have Encryption Options defined\nPlatform: \n" +
"Learn more about this vulnerability: https://docs.kics.io/latest/queries/-queries/aws/3db3f534-e3a3-487f-88c7-0a9fbf64b702\n\n" +
"\t[1]: positive.tf:1\n\n\n\n" +
"ALB protocol is HTTP, Severity: HIGH, Results: 2\n" +
"Note: this is an experimental query\n" +
"Description: ALB protocol is HTTP Description\n" +
"Platform: \n" +
"Learn more about this vulnerability: https://docs.kics.io/latest/queries/-queries/de7f5e83-da88-4046-871f-ea18504b1d43\n\n" +
"\t[1]: positive.tf:25\n\n\n\n" +
"\t[2]: positive.tf:19\n\n\n\n\n" +
"Results Summary:\n" +
"HIGH: 2\n" +
"MEDIUM: 1\n" +
"LOW: 0\n" +
"INFO: 0\n" +
"TOTAL: 3\n\n",
customQueries: false,
caseTest: test.ComplexSummaryMockWithExperimental,
expectedResult: "\n\nAmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\n\t[1]: positive.tf:1\nALB protocol is HTTP, Severity: HIGH, Results: 2\nNote: this is an experimental query\n\t[1]: positive.tf:25\n\t[2]: positive.tf:19\n\nResults Summary:\nHIGH: 2\nMEDIUM: 1\nLOW: 0\nINFO: 0\nTOTAL: 3\n\n",
expectedResultFull: "\n\nAmazonMQ Broker Encryption Disabled, Severity: MEDIUM, Results: 1\nDescription: AmazonMQ Broker should have Encryption Options defined\nPlatform: \nLearn more about this vulnerability: https://docs.kics.io/latest/queries/-queries/aws/3db3f534-e3a3-487f-88c7-0a9fbf64b702\n\n\t[1]: positive.tf:1\n\n\n\nALB protocol is HTTP, Severity: HIGH, Results: 2\nNote: this is an experimental query\nDescription: ALB protocol is HTTP Description\nPlatform: \nLearn more about this vulnerability: https://docs.kics.io/latest/queries/-queries/de7f5e83-da88-4046-871f-ea18504b1d43\n\n\t[1]: positive.tf:25\n\n\n\n\t[2]: positive.tf:19\n\n\n\n\nResults Summary:\nHIGH: 2\nMEDIUM: 1\nLOW: 0\nINFO: 0\nTOTAL: 3\n\n",
customQueries: false,
},
}

var failedQueries = map[string]error{}

// TestPrintResult tests the functions [PrintResult()] and all the methods called by them
func TestPrintResult(t *testing.T) {
color.Disable()
for idx, testCase := range printTests {
t.Run(fmt.Sprintf("Print test case %d", idx), func(t *testing.T) {
out, err := test.CaptureOutput(func() error {
return PrintResult(&testCase.caseTest, failedQueries, NewPrinter(true), testCase.customQueries)
return PrintResult(&testCase.caseTest, NewPrinter(true), testCase.customQueries)
})
require.NoError(t, err)
require.Equal(t, testCase.expectedResult, out)
Expand All @@ -270,7 +145,7 @@ func TestPrintResult(t *testing.T) {
for idx, testCase := range printTests {
t.Run(fmt.Sprintf("Print test case %d no minimal", idx), func(t *testing.T) {
out, err := test.CaptureOutput(func() error {
return PrintResult(&testCase.caseTest, failedQueries, NewPrinter(false), testCase.customQueries)
return PrintResult(&testCase.caseTest, NewPrinter(false), testCase.customQueries)
})
require.NoError(t, err)
require.Equal(t, testCase.expectedResultFull, out)
Expand Down
11 changes: 4 additions & 7 deletions pkg/printer/utils.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package printer

import (
"fmt"
"time"

consoleFlags "github.com/Checkmarx/kics/internal/console/flags"
"github.com/rs/zerolog/log"
"github.com/rs/zerolog"
)

func validateFlags() error {
Expand All @@ -28,14 +27,12 @@ func validateFlags() error {
}

// PrintScanDuration prints the scan duration
func PrintScanDuration(elapsed time.Duration) {
func PrintScanDuration(logger *zerolog.Logger, elapsed time.Duration) {
if consoleFlags.GetBoolFlag(consoleFlags.CIFlag) {
elapsedStrFormat := "Scan duration: %vms\n"
fmt.Printf(elapsedStrFormat, elapsed.Milliseconds())
log.Info().Msgf(elapsedStrFormat, elapsed.Milliseconds())
(*logger).Info().Msgf(elapsedStrFormat, elapsed.Milliseconds())
} else {
elapsedStrFormat := "Scan duration: %v\n"
fmt.Printf(elapsedStrFormat, elapsed)
log.Info().Msgf(elapsedStrFormat, elapsed)
(*logger).Info().Msgf(elapsedStrFormat, elapsed)
}
}
24 changes: 9 additions & 15 deletions pkg/printer/utils_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package printer

import (
"io/ioutil"
"os"
"testing"
"time"

"github.com/Checkmarx/kics/internal/console/flags"
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/assert"
)

func Test_PrintScanDuration(t *testing.T) {
Expand All @@ -33,12 +31,12 @@ func Test_PrintScanDuration(t *testing.T) {
{
name: "should print scan duration",
cmd: mockCmd,
flagsListContent: "",
flagsListContent: ``,
persintentFlag: true,
supportedPlatforms: []string{"terraform"},
supportedCloudProviders: []string{"aws"},
elapsed: time.Duration(1),
expected: "Scan duration: 1ns\n",
expected: "Scan duration: 1ns",
},
{
name: "should print scan duration when ci flag is true",
Expand All @@ -53,25 +51,21 @@ func Test_PrintScanDuration(t *testing.T) {
supportedPlatforms: []string{"terraform"},
supportedCloudProviders: []string{"aws"},
elapsed: time.Duration(1),
expected: "Scan duration: 0ms\n",
expected: "Scan duration: 0ms",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
flags.InitJSONFlags(test.cmd, test.flagsListContent, test.persintentFlag, test.supportedPlatforms, test.supportedCloudProviders)

rescueStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
myBuffer := LogSink{}
logger := NewLogger(&myBuffer)

PrintScanDuration(test.elapsed)
PrintScanDuration(&logger, test.elapsed)
aux := myBuffer.Index(0)

w.Close()
out, _ := ioutil.ReadAll(r)
os.Stdout = rescueStdout

require.Equal(t, test.expected, string(out))
assert.Contains(t, aux, test.expected)
})
}
}
1 change: 0 additions & 1 deletion pkg/report/commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ func getCurrentTime() string {

func fileCreationReport(path, filename string) {
log.Info().Str("fileName", filename).Msgf("Results saved to file %s", path)
fmt.Printf("Results saved to file %s\n", path)
}

func closeFile(path, filename string, file *os.File) {
Expand Down
Loading
Loading