Skip to content

Commit 171644e

Browse files
authored
feat: fail-fast in case of missing scanners (#25)
1 parent cd58e85 commit 171644e

File tree

4 files changed

+52
-7
lines changed

4 files changed

+52
-7
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Sheriff is a tool to scan repositories and generate security reports.
2828
## Quick Usage
2929

3030
```sh
31-
sheriff patrol --gitlab-groups your-namespace-or-group --report-gitlab-issue
31+
sheriff patrol --url gitlab://your-namespace-or-group --report-to-issue
3232
```
3333

3434
## How it works

internal/cli/patrol.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import (
44
"errors"
55
"fmt"
66
"net/url"
7+
"os/exec"
78
"sheriff/internal/git"
89
"sheriff/internal/gitlab"
910
"sheriff/internal/patrol"
1011
"sheriff/internal/scanner"
1112
"sheriff/internal/slack"
13+
"strings"
1214

1315
"github.com/urfave/cli/v2"
1416
"github.com/urfave/cli/v2/altsrc"
@@ -35,6 +37,7 @@ const gitlabTokenFlag = "gitlab-token"
3537
const slackTokenFlag = "slack-token"
3638

3739
var sensitiveFlags = []string{gitlabTokenFlag, slackTokenFlag}
40+
var necessaryScanners = []string{scanner.OsvCommandName}
3841

3942
var PatrolFlags = []cli.Flag{
4043
&cli.StringFlag{
@@ -122,6 +125,12 @@ func PatrolAction(cCtx *cli.Context) error {
122125

123126
patrolService := patrol.New(gitlabService, slackService, gitService, osvService)
124127

128+
// Check whether the necessary scanners are available
129+
missingScanners := getMissingScanners(necessaryScanners)
130+
if len(missingScanners) > 0 {
131+
return fmt.Errorf("Cannot find all necessary scanners in $PATH, missing: %v", strings.Join(missingScanners, ", "))
132+
}
133+
125134
// Do the patrol
126135
if warn, err := patrolService.Patrol(
127136
patrol.PatrolArgs{
@@ -173,3 +182,14 @@ func parseUrls(uris []string) ([]patrol.ProjectLocation, error) {
173182

174183
return locations, nil
175184
}
185+
186+
func getMissingScanners(necessary []string) []string {
187+
missingScanners := make([]string, 0, len(necessary))
188+
for _, scanner := range necessary {
189+
if _, err := exec.LookPath(scanner); err != nil {
190+
missingScanners = append(missingScanners, scanner)
191+
}
192+
}
193+
194+
return missingScanners
195+
}

internal/cli/patrol_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ import (
1111
)
1212

1313
func TestPatrolActionEmptyRun(t *testing.T) {
14+
// Monkey patch necessaryScanners to avoid missing scanners
15+
// during testing
16+
origNecessaryScanners := necessaryScanners
17+
necessaryScanners = []string{}
18+
defer func() {
19+
necessaryScanners = origNecessaryScanners
20+
}()
21+
1422
context := cli.NewContext(cli.NewApp(), flag.NewFlagSet("flagset", flag.ContinueOnError), nil)
1523

1624
err := PatrolAction(context)
@@ -46,3 +54,20 @@ func TestParseUrls(t *testing.T) {
4654
}
4755
}
4856
}
57+
58+
func TestGetMissingScanners(t *testing.T) {
59+
testCases := []struct {
60+
scanners []string
61+
want []string
62+
}{
63+
{[]string{"ls", "missing"}, []string{"missing"}},
64+
{[]string{"echo", "ls", "missing", "missing-another"}, []string{"missing", "missing-another"}},
65+
{[]string{"ls"}, []string{}},
66+
}
67+
68+
for _, tc := range testCases {
69+
missingScanners := getMissingScanners(tc.scanners)
70+
71+
assert.Equal(t, tc.want, missingScanners)
72+
}
73+
}

internal/scanner/osv.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ import (
1212
gogitlab "github.com/xanzy/go-gitlab"
1313
)
1414

15-
const osvTimeout = 30 * time.Second
16-
1715
type osvReferenceKind string
1816

1917
const (
20-
AdvisoryKind osvReferenceKind = "ADVISORY"
21-
WebKind osvReferenceKind = "WEB"
22-
PackageKind osvReferenceKind = "PACKAGE"
18+
OsvCommandName = "osv-scanner"
19+
AdvisoryKind osvReferenceKind = "ADVISORY"
20+
WebKind osvReferenceKind = "WEB"
21+
PackageKind osvReferenceKind = "PACKAGE"
22+
osvTimeout = 30 * time.Second
2323
)
2424

2525
type osvSource struct {
@@ -109,7 +109,7 @@ func (s *osvScanner) Scan(dir string) (*OsvReport, error) {
109109

110110
cmdOut, err := shell.ShellCommandRunner.Run(
111111
shell.CommandInput{
112-
Name: "osv-scanner",
112+
Name: OsvCommandName,
113113
Args: []string{"-r", "--verbosity", "error", "--format", "json", dir},
114114
Timeout: osvTimeout,
115115
},

0 commit comments

Comments
 (0)