Skip to content

Commit 6154c81

Browse files
authored
feat: host vuln time range flags (#1270)
1 parent ff326af commit 6154c81

File tree

5 files changed

+114
-17
lines changed

5 files changed

+114
-17
lines changed

cli/cmd/vuln_host.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ func init() {
8686
vulHostShowAssessmentCmd.Flags(),
8787
)
8888

89+
setTimeRangeFlags(
90+
vulHostListHostsCmd.Flags(),
91+
)
92+
8993
// the package manifest file
9094
vulHostScanPkgManifestCmd.Flags().StringVarP(&pkgManifestFile,
9195
"file", "f", "",

cli/cmd/vuln_host_list_hosts.go

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import (
2525
"strings"
2626
"time"
2727

28+
"github.com/lacework/go-sdk/lwtime"
29+
2830
"github.com/lacework/go-sdk/api"
2931
"github.com/pkg/errors"
3032
"github.com/spf13/cobra"
@@ -48,21 +50,47 @@ To list the CVEs found in the hosts of your environment run:
4850
4951
lacework vulnerability host list-cves`,
5052
RunE: func(_ *cobra.Command, args []string) error {
51-
now := time.Now().UTC()
52-
start := now.AddDate(0, 0, -1)
53-
filter := api.SearchFilter{
54-
TimeFilter: &api.TimeFilter{
55-
StartTime: &start,
56-
EndTime: &now,
57-
},
58-
Filters: []api.Filter{
59-
{Expression: "eq",
60-
Field: "vulnId",
61-
Value: args[0]},
62-
{Expression: "ne",
63-
Field: "status",
64-
Value: "Fixed"},
65-
}}
53+
var (
54+
filter api.SearchFilter
55+
start time.Time
56+
end time.Time
57+
err error
58+
)
59+
60+
if vulCmdState.Range != "" {
61+
cli.Log.Debugw("retrieving natural time range", "range", vulCmdState.Range)
62+
start, end, err = lwtime.ParseNatural(vulCmdState.Range)
63+
if err != nil {
64+
return errors.Wrap(err, "unable to parse natural time range")
65+
}
66+
67+
} else {
68+
cli.Log.Debugw("parsing start time", "start", vulCmdState.Start)
69+
start, err = parseQueryTime(vulCmdState.Start)
70+
if err != nil {
71+
return errors.Wrap(err, "unable to parse start time")
72+
}
73+
74+
cli.Log.Debugw("parsing end time", "end", vulCmdState.End)
75+
end, err = parseQueryTime(vulCmdState.End)
76+
if err != nil {
77+
return errors.Wrap(err, "unable to parse end time")
78+
}
79+
}
80+
81+
filter.TimeFilter = &api.TimeFilter{
82+
StartTime: &start,
83+
EndTime: &end,
84+
}
85+
86+
filter.Filters = []api.Filter{
87+
{Expression: "eq",
88+
Field: "vulnId",
89+
Value: args[0]},
90+
{Expression: "ne",
91+
Field: "status",
92+
Value: "Fixed"},
93+
}
6694

6795
cli.StartProgress("Fetching Hosts...")
6896
response, err := cli.LwApi.V2.Vulnerabilities.Hosts.SearchAllPages(filter)

cli/cmd/vulnerability.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,23 @@ func setActiveFlag(cmds ...*flag.FlagSet) {
231231
}
232232
}
233233

234+
func setTimeRangeFlags(cmds ...*flag.FlagSet) {
235+
for _, cmd := range cmds {
236+
if cmd != nil {
237+
238+
cmd.StringVar(&vulCmdState.Start,
239+
"start", "-24h", "start of the time range",
240+
)
241+
cmd.StringVar(&vulCmdState.End,
242+
"end", "now", "end of the time range",
243+
)
244+
cmd.StringVar(&vulCmdState.Range,
245+
"range", "", "natural time range for query",
246+
)
247+
}
248+
}
249+
}
250+
234251
func buildVulnContainerAssessmentReportTable(summary string, details string) string {
235252
report := &strings.Builder{}
236253

integration/host_vulnerability_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,3 +480,48 @@ func setHostVulnTestMachineID(lw *api.Client) {
480480
}
481481
}
482482
}
483+
484+
func TestHostVulnerabilityListHostsTimeFilters(t *testing.T) {
485+
var (
486+
out bytes.Buffer
487+
err bytes.Buffer
488+
exitcode int
489+
hostVulnCVEs []api.HostVulnCVE
490+
cveID string
491+
)
492+
493+
if os.Getenv("CI_SKIP_HOST_VULN") != "" {
494+
t.Skip(fmt.Sprintf("skipping %s", t.Name()))
495+
}
496+
497+
t.Run("list-cves", func(t *testing.T) {
498+
out, err, exitcode = LaceworkCLIWithTOMLConfig(
499+
"vulnerability", "host", "list-cves", "--json")
500+
assert.Empty(t, err.String(), "STDERR should be empty")
501+
assert.Equal(t, 0, exitcode, "EXITCODE is not the expected one")
502+
})
503+
504+
t.Run("inspecting json output", func(t *testing.T) {
505+
errJson := json.Unmarshal(out.Bytes(), &hostVulnCVEs)
506+
assert.Nil(t, errJson)
507+
assert.NotEmpty(t, hostVulnCVEs, "check JSON list-cves response")
508+
})
509+
510+
cveID = hostVulnCVEs[0].ID
511+
512+
t.Run(fmt.Sprintf("startEnd for '%s'", cveID), func(t *testing.T) {
513+
out, err, exitcode = LaceworkCLIWithTOMLConfig("vulnerability", "host", "list-hosts", cveID, "--start", "-48h", "--end", "-24h")
514+
assert.Empty(t, err.String(), "STDERR should be empty")
515+
assert.Equal(t, 0, exitcode, "EXITCODE is not the expected one")
516+
517+
assert.Contains(t, out, "1 High 1 Fixable", "Unexpected number of results")
518+
})
519+
520+
t.Run(fmt.Sprintf("Natural range for '%s'", cveID), func(t *testing.T) {
521+
out, err, exitcode = LaceworkCLIWithTOMLConfig("vulnerability", "host", "list-hosts", cveID, "--range", "last 6 days")
522+
assert.Empty(t, err.String(), "STDERR should be empty")
523+
assert.Equal(t, 0, exitcode, "EXITCODE is not the expected one")
524+
525+
assert.Contains(t, out, "1 High 6 Fixable", "Unexpected number of results")
526+
})
527+
}

integration/test_resources/help/vulnerability_host_list-hosts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ Usage:
88
lacework vulnerability host list-hosts <cve_id> [flags]
99

1010
Flags:
11-
--csv output vulnerability assessment in CSV format
12-
-h, --help help for list-hosts
11+
--csv output vulnerability assessment in CSV format
12+
--end string end of the time range (default "now")
13+
-h, --help help for list-hosts
14+
--range string natural time range for query
15+
--start string start of the time range (default "-24h")
1316

1417
Global Flags:
1518
-a, --account string account subdomain of URL (i.e. <ACCOUNT>.lacework.net)

0 commit comments

Comments
 (0)