Skip to content

Commit

Permalink
Scan command writejson (#193)
Browse files Browse the repository at this point in the history
* Delete supported_formats.json

* add json-path parameter

* update flag description

* added test

---------

Co-authored-by: Michael Chernov <[email protected]>
  • Loading branch information
psmf22 and 4ernovm authored Feb 12, 2024
1 parent bde5a86 commit 4199e21
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
4 changes: 4 additions & 0 deletions internal/cmd/scan/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var branchName string
var commitAuthor string
var repositoryUrl string
var integrationName string
var jsonFilePath string
var exclusions = file.Exclusions()
var verbose bool
var regenerate int
Expand Down Expand Up @@ -47,6 +48,7 @@ const (
CallGraphUploadTimeoutFlag = "callgraph-upload-timeout"
CallGraphGenerateTimeoutFlag = "callgraph-generate-timeout"
NpmPreferredFlag = "prefer-npm"
JsonFilePathFlag = "json-path"
)

var scanCmdError error
Expand Down Expand Up @@ -74,6 +76,7 @@ If the given path contains a git repository all flags but "integration" will be
"CLI",
`name of integration used to trigger scan. For example "GitHub Actions"`,
)
cmd.Flags().StringVarP(&jsonFilePath, JsonFilePathFlag, "j", "", "write upload result as json to provided path")

fileExclusionExample := filepath.Join("*", "**.lock")
dirExclusionExample := filepath.Join("**", "node_modules", "**")
Expand Down Expand Up @@ -159,6 +162,7 @@ func RunE(s *scan.IScanner) func(_ *cobra.Command, args []string) error {
CommitAuthor: viper.GetString(CommitAuthorFlag),
RepositoryUrl: viper.GetString(RepositoryUrlFlag),
IntegrationName: viper.GetString(IntegrationFlag),
JsonFilePath: viper.GetString(JsonFilePathFlag),
NpmPreferred: viper.GetBool(NpmPreferredFlag),
PassOnTimeOut: viper.GetBool(PassOnTimeOut),
CallGraph: viper.GetBool(CallGraphFlag),
Expand Down
11 changes: 11 additions & 0 deletions internal/scan/scanner.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package scan

import (
"encoding/json"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -55,6 +56,7 @@ type DebrickedOptions struct {
CommitAuthor string
RepositoryUrl string
IntegrationName string
JsonFilePath string
NpmPreferred bool
PassOnTimeOut bool
CallGraphUploadTimeout int
Expand Down Expand Up @@ -118,6 +120,8 @@ func (dScanner *DebrickedScanner) Scan(o IOptions) error {
return nil
}

WriteApiReplyToJsonFile(dOptions, result)

fmt.Printf("\n%d vulnerabilities found\n", result.VulnerabilitiesFound)
fmt.Println("")
failPipeline := false
Expand Down Expand Up @@ -259,3 +263,10 @@ func MapEnvToOptions(o *DebrickedOptions, env env.Env) {
o.Path = env.Filepath
}
}

func WriteApiReplyToJsonFile(options DebrickedOptions, result *upload.UploadResult) {
if options.JsonFilePath != "" {
file, _ := json.MarshalIndent(result, "", " ")
_ = os.WriteFile(options.JsonFilePath, file, 0600)
}
}
72 changes: 69 additions & 3 deletions internal/scan/scanner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import (
"github.com/stretchr/testify/assert"
)

const windowsOS = "windows"

var testdataNpm = filepath.Join("testdata", "npm")

var ciService ci.IService = ci.NewService([]ci.ICi{
Expand Down Expand Up @@ -64,7 +66,7 @@ func TestNewDebrickedScanner(t *testing.T) {
}

func TestScan(t *testing.T) {
if runtime.GOOS == "windows" {
if runtime.GOOS == windowsOS {
t.Skipf("TestScan is skipped due to Windows env")
}
clientMock := testdata.NewDebClientMock()
Expand Down Expand Up @@ -109,7 +111,6 @@ func TestScan(t *testing.T) {

outputAssertions := []string{
"Working directory: /",
"cli/internal/scan",
"Successfully uploaded",
"package.json\n",
"Successfully initialized scan\n",
Expand All @@ -126,6 +127,71 @@ func TestScan(t *testing.T) {
}
}

func TestScanWithJsonPath(t *testing.T) {
if runtime.GOOS == windowsOS {
t.Skipf("TestScan is skipped due to Windows env")
}
clientMock := testdata.NewDebClientMock()
addMockedFormatsResponse(clientMock, "package\\.json")
addMockedFileUploadResponse(clientMock)
addMockedFinishResponse(clientMock, http.StatusNoContent)
addMockedStatusResponse(clientMock, http.StatusOK, 50)
addMockedStatusResponse(clientMock, http.StatusOK, 100)
scanner := makeScanner(clientMock, nil, nil)

path := testdataNpm
repositoryName := path
cwd, _ := os.Getwd()

// reset working directory that has been manipulated in scanner.Scan
defer resetWd(t, cwd)
opts := DebrickedOptions{
Path: path,
Exclusions: nil,
RepositoryName: repositoryName,
CommitName: "commit",
BranchName: "",
CommitAuthor: "",
RepositoryUrl: "",
IntegrationName: "",
CallGraphUploadTimeout: 10 * 60,
CallGraphGenerateTimeout: 10 * 60,
JsonFilePath: "result.json",
}

rescueStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w

err := scanner.Scan(opts)

_ = w.Close()
output, _ := io.ReadAll(r)
os.Stdout = rescueStdout

if err != nil {
t.Error("failed to assert that scan ran without errors. Error:", err)
}

outputAssertions := []string{
"Working directory: /",
"Successfully uploaded",
"package.json",
"Successfully initialized scan\n",
"Scanning...",
"0% |",
"50% |",
"100% |",
"32m✔",
"0 vulnerabilities found\n\n",
"For full details, visit:",
}
for _, assertion := range outputAssertions {
assert.Contains(t, string(output), assertion)
}
assert.FileExists(t, filepath.Join(cwd, path, "result.json"))
}

func TestScanFailingMetaObject(t *testing.T) {
var debClient client.IDebClient = testdata.NewDebClientMock()
scanner := NewDebrickedScanner(&debClient, nil, nil, ciService, nil, nil, nil)
Expand Down Expand Up @@ -184,7 +250,7 @@ func TestScanBadOpts(t *testing.T) {
}

func TestScanEmptyResult(t *testing.T) {
if runtime.GOOS == "windows" {
if runtime.GOOS == windowsOS {
t.Skipf("TestScan is skipped due to Windows env")
}
clientMock := testdata.NewDebClientMock()
Expand Down

0 comments on commit 4199e21

Please sign in to comment.