diff --git a/cmd/crowdsec-cli/alerts.go b/cmd/crowdsec-cli/alerts.go index c498536daa1..3437a95361d 100644 --- a/cmd/crowdsec-cli/alerts.go +++ b/cmd/crowdsec-cli/alerts.go @@ -269,6 +269,7 @@ cscli alerts list --type ban`, var ActiveDecision *bool var AlertDeleteAll bool + var delAlertByID string var alertDeleteFilter = apiclient.AlertsDeleteOpts{ ScopeEquals: new(string), ValueEquals: new(string), @@ -292,7 +293,7 @@ cscli alerts delete -s crowdsecurity/ssh-bf"`, } if *alertDeleteFilter.ScopeEquals == "" && *alertDeleteFilter.ValueEquals == "" && *alertDeleteFilter.ScenarioEquals == "" && *alertDeleteFilter.IPEquals == "" && - *alertDeleteFilter.RangeEquals == "" { + *alertDeleteFilter.RangeEquals == "" && delAlertByID == "" { _ = cmd.Usage() log.Fatalln("At least one filter or --all must be specified") } @@ -334,12 +335,20 @@ cscli alerts delete -s crowdsecurity/ssh-bf"`, limit := 0 alertDeleteFilter = apiclient.AlertsDeleteOpts{Limit: &limit} } - alerts, _, err := Client.Alerts.Delete(context.Background(), alertDeleteFilter) - if err != nil { - log.Fatalf("Unable to delete alerts : %v", err) + + var alerts *models.DeleteAlertsResponse + if delAlertByID == "" { + alerts, _, err = Client.Alerts.Delete(context.Background(), alertDeleteFilter) + if err != nil { + log.Fatalf("Unable to delete alerts : %v", err) + } + } else { + alerts, _, err = Client.Alerts.DeleteOne(context.Background(), delAlertByID) + if err != nil { + log.Fatalf("Unable to delete alert : %v", err) + } } log.Infof("%s alert(s) deleted", alerts.NbDeleted) - }, } cmdAlertsDelete.Flags().SortFlags = false @@ -348,6 +357,7 @@ cscli alerts delete -s crowdsecurity/ssh-bf"`, cmdAlertsDelete.Flags().StringVarP(alertDeleteFilter.ScenarioEquals, "scenario", "s", "", "the scenario (ie. crowdsecurity/ssh-bf)") cmdAlertsDelete.Flags().StringVarP(alertDeleteFilter.IPEquals, "ip", "i", "", "Source ip (shorthand for --scope ip --value )") cmdAlertsDelete.Flags().StringVarP(alertDeleteFilter.RangeEquals, "range", "r", "", "Range source ip (shorthand for --scope range --value )") + cmdAlertsDelete.Flags().StringVar(&delAlertByID, "id", "", "alert ID") cmdAlertsDelete.Flags().BoolVarP(&AlertDeleteAll, "all", "a", false, "delete all alerts") cmdAlertsDelete.Flags().BoolVar(contained, "contained", false, "query decisions contained by range") diff --git a/tests/bats/80_alerts.bats b/tests/bats/80_alerts.bats index 39cd70a5a6a..514e90d6285 100644 --- a/tests/bats/80_alerts.bats +++ b/tests/bats/80_alerts.bats @@ -122,11 +122,29 @@ teardown() { assert_output "id,scope,value,reason,country,as,decisions,created_at,machine" } -@test "cscli alerts delete" { +@test "cscli alerts delete (by id)" { + run -0 cscli decisions add -i 127.0.0.1 -d 1h -R crowdsecurity/test + run -0 --separate-stderr cscli alerts delete --id 1 + refute_output + assert_stderr --partial "1 alert(s) deleted" + + run -1 --separate-stderr cscli alerts delete --id 1 + refute_output + assert_stderr --partial "Unable to delete alert" + assert_stderr --partial "API error: ent: alert not found" +} + +@test "cscli alerts delete (all)" { run -0 --separate-stderr cscli alerts delete --all - assert_stderr --partial 'alert(s) deleted' + assert_stderr --partial '0 alert(s) deleted' + + run -0 cscli decisions add -i 1.2.3.4 -d 1h -R crowdsecurity/test + run -0 cscli decisions add -i 1.2.3.5 -d 1h -R crowdsecurity/test + + run -0 --separate-stderr cscli alerts delete --all + assert_stderr --partial '2 alert(s) deleted' - # XXX TODO: delete by scope, id, value, scenario, range.. + # XXX TODO: delete by scope, value, scenario, range.. } @test "cscli alerts delete (with cascade to decisions)" {