Skip to content

Commit

Permalink
feat(cli): filter events by severity
Browse files Browse the repository at this point in the history
Show me all the events from the last 7 days that has
severity high and above (Critical & High)
```
$ lacework events list --severity high
```

Show me all the events from the last day that has severity
medium and above (Critical, High and Medium)
```
$ lacework events list --severity medium --days 1
```

Closes #195

Signed-off-by: Salim Afiune Maya <[email protected]>
  • Loading branch information
afiune committed Aug 25, 2020
1 parent 0474765 commit 2d8fdf4
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 10 deletions.
3 changes: 3 additions & 0 deletions api/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ type EventsService struct {
client *Client
}

// ValidEventSeverities is a list of all valid event severities
var ValidEventSeverities = []string{"critical", "high", "medium", "low", "info"}

// List leverages ListDateRange and returns a list of events from the last 7 days
func (svc *EventsService) List() (EventsResponse, error) {
var (
Expand Down
98 changes: 88 additions & 10 deletions cli/cmd/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ var (

// list events from an specific number of days
Days int

// list events with a specific severity
Severity string
}{}

// easily add or remove borders to all event details tables
Expand All @@ -58,17 +61,33 @@ var (
// eventListCmd represents the list sub-command inside the event command
eventListCmd = &cobra.Command{
Use: "list",
Short: "list all events from a date range (default last 7 days)",
Long: `List all events from a time range, by default this command displays the
events from the last 7 days, but it is possible to specify a different
time range.`,
Short: "list all events (default last 7 days)",
Long: `List all events for the last 7 days by default, or pass --start and --end to
specify a custom time period. You can also pass --serverity to filter by a
severity threshold.
Additionally, pass --days to list events for a specified number of days.
For example, to list all events from the last day with severity medium and above
(Critical, High and Medium) run:
$ lacework events list --severity medium --days 1`,
Args: cobra.NoArgs,
RunE: func(_ *cobra.Command, _ []string) error {

var (
response api.EventsResponse
err error
)

if eventsCmdState.Severity != "" {
if !array.ContainsStr(api.ValidEventSeverities, eventsCmdState.Severity) {
return errors.Errorf("the severity %s is not valid, use one of %s",
eventsCmdState.Severity, strings.Join(api.ValidEventSeverities, ", "),
)
}
}

if eventsCmdState.Start != "" || eventsCmdState.End != "" {
start, end, errT := parseStartAndEndTime(eventsCmdState.Start, eventsCmdState.End)
if errT != nil {
Expand Down Expand Up @@ -97,16 +116,30 @@ time range.`,
}

cli.Log.Debugw("events", "raw", response)
// Sort the events from the response by severity
sort.Slice(response.Events, func(i, j int) bool {
return response.Events[i].Severity < response.Events[j].Severity

// filter events by severity, if the user didn't specify a severity
// the funtion will return it back without modifications
events := filterEventsWithSeverity(response.Events)

// Sort the events by severity
sort.Slice(events, func(i, j int) bool {
return events[i].Severity < events[j].Severity
})

if cli.JSONOutput() {
return cli.OutputJSON(response.Events)
return cli.OutputJSON(events)
}

if len(events) == 0 {
if eventsCmdState.Severity != "" {
cli.OutputHuman("There are no events with the specified severity.\n")
} else {
cli.OutputHuman("There are no events in your account in the specified time range.\n")
}
return nil
}

cli.OutputHuman(eventsToTableReport(response.Events))
cli.OutputHuman(eventsToTableReport(events))
return nil
},
}
Expand Down Expand Up @@ -164,7 +197,15 @@ func init() {
)
// add days flag to events list command
eventListCmd.Flags().IntVar(&eventsCmdState.Days,
"days", 0, "list events from an specific number of days (max: 7 days)",
"days", 0, "list events for specified number of days (max: 7 days)",
)
// add severity flag to events list command
eventListCmd.Flags().StringVar(&eventsCmdState.Severity,
"severity", "",
fmt.Sprintf(
"filter events by severity threshold (%s)",
strings.Join(api.ValidEventSeverities, ", "),
),
)

eventCmd.AddCommand(eventShowCmd)
Expand Down Expand Up @@ -913,3 +954,40 @@ func eventMachineEntitiesTable(machines []api.EventMachineEntity) string {

return r.String()
}

func filterEventsWithSeverity(events []api.Event) []api.Event {
if eventsCmdState.Severity == "" {
return events
}

sevThreshold, sevString := eventSeverityToProperTypes(eventsCmdState.Severity)
cli.Log.Debugw("filtering events", "threshold", sevThreshold, "severity", sevString)
eFiltered := []api.Event{}
for _, event := range events {
eventSeverity, _ := eventSeverityToProperTypes(event.Severity)
if eventSeverity <= sevThreshold {
eFiltered = append(eFiltered, event)
}
}

cli.Log.Debugw("filtered events", "events", eFiltered)

return eFiltered
}

func eventSeverityToProperTypes(severity string) (int, string) {
switch strings.ToLower(severity) {
case "1", "critical":
return 1, "Critical"
case "2", "high":
return 2, "High"
case "3", "medium":
return 3, "Medium"
case "4", "low":
return 4, "Low"
case "5", "info":
return 5, "Info"
default:
return 6, "Unknown"
}
}
11 changes: 11 additions & 0 deletions integration/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ func TestEventCommandListDays(t *testing.T) {
"EXITCODE is not the expected one")
}

func TestEventCommandListSeverityError(t *testing.T) {
out, err, exitcode := LaceworkCLIWithTOMLConfig("event", "list", "--severity", "foo")
assert.Contains(t, err.String(), "ERROR the severity foo is not valid, use one of critical, high, medium, low, info",
"STDERR the message to the user has changed, update please")
assert.Empty(t,
out.String(),
"STDOUT should be empty")
assert.Equal(t, 1, exitcode,
"EXITCODE is not the expected one")
}

func TestEventCommandListTimeRange(t *testing.T) {
var (
now = time.Now().UTC()
Expand Down

0 comments on commit 2d8fdf4

Please sign in to comment.