2020-11-30 09:37:17 +00:00
package main
import (
"context"
2021-12-29 13:08:47 +00:00
"encoding/csv"
2020-11-30 09:37:17 +00:00
"encoding/json"
"fmt"
"net/url"
"os"
2023-01-04 15:50:02 +00:00
"sort"
2020-11-30 09:37:17 +00:00
"strconv"
"strings"
2023-03-08 21:47:25 +00:00
"text/template"
2020-11-30 09:37:17 +00:00
2022-10-13 10:28:24 +00:00
"github.com/fatih/color"
2020-11-30 09:37:17 +00:00
"github.com/go-openapi/strfmt"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
2022-10-07 09:05:35 +00:00
2023-07-28 14:35:08 +00:00
"github.com/crowdsecurity/go-cs-lib/version"
2023-05-23 08:52:47 +00:00
2023-12-11 09:32:54 +00:00
"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
2022-10-07 09:05:35 +00:00
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
"github.com/crowdsecurity/crowdsec/pkg/database"
"github.com/crowdsecurity/crowdsec/pkg/models"
2023-01-31 13:47:44 +00:00
"github.com/crowdsecurity/crowdsec/pkg/types"
2020-11-30 09:37:17 +00:00
)
func DecisionsFromAlert ( alert * models . Alert ) string {
ret := ""
2024-02-09 16:51:29 +00:00
decMap := make ( map [ string ] int )
2020-11-30 09:37:17 +00:00
for _ , decision := range alert . Decisions {
k := * decision . Type
if * decision . Simulated {
k = fmt . Sprintf ( "(simul)%s" , k )
}
2024-02-09 16:51:29 +00:00
2020-11-30 09:37:17 +00:00
v := decMap [ k ]
decMap [ k ] = v + 1
}
2024-02-09 16:51:29 +00:00
2020-11-30 09:37:17 +00:00
for k , v := range decMap {
if len ( ret ) > 0 {
ret += " "
}
2024-02-09 16:51:29 +00:00
2020-11-30 09:37:17 +00:00
ret += fmt . Sprintf ( "%s:%d" , k , v )
}
2024-02-09 16:51:29 +00:00
2020-11-30 09:37:17 +00:00
return ret
}
2024-02-09 16:51:29 +00:00
func ( cli * cliAlerts ) alertsToTable ( alerts * models . GetAlertsResponse , printMachine bool ) error {
switch cli . cfg ( ) . Cscli . Output {
2024-02-01 16:24:00 +00:00
case "raw" :
2021-12-29 13:08:47 +00:00
csvwriter := csv . NewWriter ( os . Stdout )
2022-03-09 15:15:18 +00:00
header := [ ] string { "id" , "scope" , "value" , "reason" , "country" , "as" , "decisions" , "created_at" }
2024-02-09 16:51:29 +00:00
2020-11-30 09:37:17 +00:00
if printMachine {
2022-03-09 15:15:18 +00:00
header = append ( header , "machine" )
}
2024-02-09 16:51:29 +00:00
if err := csvwriter . Write ( header ) ; err != nil {
2022-03-09 15:15:18 +00:00
return err
2020-11-30 09:37:17 +00:00
}
2024-02-09 16:51:29 +00:00
2020-11-30 09:37:17 +00:00
for _ , alertItem := range * alerts {
2021-12-29 13:08:47 +00:00
row := [ ] string {
2024-02-09 16:51:29 +00:00
strconv . FormatInt ( alertItem . ID , 10 ) ,
2021-12-29 13:08:47 +00:00
* alertItem . Source . Scope ,
* alertItem . Source . Value ,
* alertItem . Scenario ,
alertItem . Source . Cn ,
2022-11-14 08:55:53 +00:00
alertItem . Source . GetAsNumberName ( ) ,
2021-12-29 13:08:47 +00:00
DecisionsFromAlert ( alertItem ) ,
* alertItem . StartAt ,
}
2020-11-30 09:37:17 +00:00
if printMachine {
2021-12-29 13:08:47 +00:00
row = append ( row , alertItem . MachineID )
}
2024-02-09 16:51:29 +00:00
if err := csvwriter . Write ( row ) ; err != nil {
2021-12-29 13:08:47 +00:00
return err
2020-11-30 09:37:17 +00:00
}
}
2024-02-09 16:51:29 +00:00
2021-12-29 13:08:47 +00:00
csvwriter . Flush ( )
2024-02-01 16:24:00 +00:00
case "json" :
2023-08-03 10:51:50 +00:00
if * alerts == nil {
// avoid returning "null" in json
// could be cleaner if we used slice of alerts directly
fmt . Println ( "[]" )
return nil
}
2024-02-09 16:51:29 +00:00
2020-11-30 09:37:17 +00:00
x , _ := json . MarshalIndent ( alerts , "" , " " )
2024-02-01 16:24:00 +00:00
fmt . Print ( string ( x ) )
case "human" :
2020-11-30 09:37:17 +00:00
if len ( * alerts ) == 0 {
fmt . Println ( "No active alerts" )
return nil
}
2024-02-09 16:51:29 +00:00
2022-10-13 10:28:24 +00:00
alertsTable ( color . Output , alerts , printMachine )
2020-11-30 09:37:17 +00:00
}
2024-02-09 16:51:29 +00:00
2020-11-30 09:37:17 +00:00
return nil
}
2023-03-08 21:47:25 +00:00
var alertTemplate = `
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
- ID : { { . ID } }
- Date : { { . CreatedAt } }
- Machine : { { . MachineID } }
- Simulation : { { . Simulated } }
- Reason : { { . Scenario } }
- Events Count : { { . EventsCount } }
- Scope : Value : { { . Source . Scope } } { { if . Source . Value } } : { { . Source . Value } } { { end } }
- Country : { { . Source . Cn } }
- AS : { { . Source . AsName } }
- Begin : { { . StartAt } }
- End : { { . StopAt } }
- UUID : { { . UUID } }
`
2024-02-09 16:51:29 +00:00
func ( cli * cliAlerts ) displayOneAlert ( alert * models . Alert , withDetail bool ) error {
2024-02-01 16:24:00 +00:00
tmpl , err := template . New ( "alert" ) . Parse ( alertTemplate )
if err != nil {
return err
}
2024-02-09 16:51:29 +00:00
if err = tmpl . Execute ( os . Stdout , alert ) ; err != nil {
2024-02-01 16:24:00 +00:00
return err
}
2020-11-30 09:37:17 +00:00
2024-02-01 16:24:00 +00:00
alertDecisionsTable ( color . Output , alert )
if len ( alert . Meta ) > 0 {
fmt . Printf ( "\n - Context :\n" )
sort . Slice ( alert . Meta , func ( i , j int ) bool {
return alert . Meta [ i ] . Key < alert . Meta [ j ] . Key
} )
2024-02-09 16:51:29 +00:00
2024-02-01 16:24:00 +00:00
table := newTable ( color . Output )
table . SetRowLines ( false )
table . SetHeaders ( "Key" , "Value" )
2024-02-09 16:51:29 +00:00
2024-02-01 16:24:00 +00:00
for _ , meta := range alert . Meta {
var valSlice [ ] string
if err := json . Unmarshal ( [ ] byte ( meta . Value ) , & valSlice ) ; err != nil {
2024-02-09 16:51:29 +00:00
return fmt . Errorf ( "unknown context value type '%s': %w" , meta . Value , err )
2024-02-01 16:24:00 +00:00
}
2024-02-09 16:51:29 +00:00
2024-02-01 16:24:00 +00:00
for _ , value := range valSlice {
table . AddRow (
meta . Key ,
value ,
)
2023-01-04 15:50:02 +00:00
}
}
2024-02-09 16:51:29 +00:00
2024-02-01 16:24:00 +00:00
table . Render ( )
}
2023-01-04 15:50:02 +00:00
2024-02-01 16:24:00 +00:00
if withDetail {
fmt . Printf ( "\n - Events :\n" )
2024-02-09 16:51:29 +00:00
2024-02-01 16:24:00 +00:00
for _ , event := range alert . Events {
alertEventTable ( color . Output , event )
2020-11-30 09:37:17 +00:00
}
}
2024-02-01 16:24:00 +00:00
2020-11-30 09:37:17 +00:00
return nil
}
2024-03-20 13:02:29 +00:00
type cliAlerts struct {
2024-02-01 16:24:00 +00:00
client * apiclient . ApiClient
2024-03-20 13:02:29 +00:00
cfg configGetter
2024-02-01 16:24:00 +00:00
}
2023-12-11 09:32:54 +00:00
2024-02-09 16:51:29 +00:00
func NewCLIAlerts ( getconfig configGetter ) * cliAlerts {
return & cliAlerts {
cfg : getconfig ,
}
2023-12-11 09:32:54 +00:00
}
2024-02-01 16:24:00 +00:00
func ( cli * cliAlerts ) NewCommand ( ) * cobra . Command {
2023-12-11 09:32:54 +00:00
cmd := & cobra . Command {
2021-09-03 10:56:17 +00:00
Use : "alerts [action]" ,
Short : "Manage alerts" ,
Args : cobra . MinimumNArgs ( 1 ) ,
DisableAutoGenTag : true ,
2023-09-23 18:35:02 +00:00
Aliases : [ ] string { "alert" } ,
2024-02-09 16:51:29 +00:00
PersistentPreRunE : func ( _ * cobra . Command , _ [ ] string ) error {
cfg := cli . cfg ( )
if err := cfg . LoadAPIClient ( ) ; err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "loading api client: %w" , err )
2020-11-30 09:37:17 +00:00
}
2024-02-09 16:51:29 +00:00
apiURL , err := url . Parse ( cfg . API . Client . Credentials . URL )
2020-11-30 09:37:17 +00:00
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "parsing api url %s: %w" , apiURL , err )
2020-11-30 09:37:17 +00:00
}
2024-02-01 16:24:00 +00:00
cli . client , err = apiclient . NewClient ( & apiclient . Config {
2024-02-09 16:51:29 +00:00
MachineID : cfg . API . Client . Credentials . Login ,
Password : strfmt . Password ( cfg . API . Client . Credentials . Password ) ,
2023-05-23 08:52:47 +00:00
UserAgent : fmt . Sprintf ( "crowdsec/%s" , version . String ( ) ) ,
2020-11-30 09:37:17 +00:00
URL : apiURL ,
VersionPrefix : "v1" ,
} )
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "new api client: %w" , err )
2020-11-30 09:37:17 +00:00
}
2024-02-09 16:51:29 +00:00
2022-05-19 08:48:08 +00:00
return nil
2020-11-30 09:37:17 +00:00
} ,
}
2023-12-11 09:32:54 +00:00
cmd . AddCommand ( cli . NewListCmd ( ) )
cmd . AddCommand ( cli . NewInspectCmd ( ) )
cmd . AddCommand ( cli . NewFlushCmd ( ) )
cmd . AddCommand ( cli . NewDeleteCmd ( ) )
2023-01-06 22:14:02 +00:00
2023-12-11 09:32:54 +00:00
return cmd
2023-01-06 22:14:02 +00:00
}
2024-02-01 16:24:00 +00:00
func ( cli * cliAlerts ) NewListCmd ( ) * cobra . Command {
2020-11-30 09:37:17 +00:00
var alertListFilter = apiclient . AlertsListOpts {
ScopeEquals : new ( string ) ,
ValueEquals : new ( string ) ,
ScenarioEquals : new ( string ) ,
IPEquals : new ( string ) ,
RangeEquals : new ( string ) ,
Since : new ( string ) ,
Until : new ( string ) ,
TypeEquals : new ( string ) ,
2022-07-28 15:31:53 +00:00
IncludeCAPI : new ( bool ) ,
2023-01-31 13:47:44 +00:00
OriginEquals : new ( string ) ,
2020-11-30 09:37:17 +00:00
}
2024-02-09 16:51:29 +00:00
2023-12-11 09:32:54 +00:00
limit := new ( int )
2021-01-15 08:48:39 +00:00
contained := new ( bool )
2024-02-09 16:51:29 +00:00
2023-01-06 22:14:02 +00:00
var printMachine bool
2023-12-11 09:32:54 +00:00
cmd := & cobra . Command {
2020-11-30 09:37:17 +00:00
Use : "list [filters]" ,
Short : "List alerts" ,
Example : ` cscli alerts list
cscli alerts list -- ip 1.2 .3 .4
cscli alerts list -- range 1.2 .3 .0 / 24
2024-03-20 13:02:29 +00:00
cscli alerts list -- origin lists
2020-11-30 09:37:17 +00:00
cscli alerts list - s crowdsecurity / ssh - bf
cscli alerts list -- type ban ` ,
2024-03-20 13:02:29 +00:00
Long : ` List alerts with optional filters ` ,
2021-08-31 13:03:47 +00:00
DisableAutoGenTag : true ,
2024-02-09 16:51:29 +00:00
RunE : func ( cmd * cobra . Command , _ [ ] string ) error {
2020-11-30 09:37:17 +00:00
if err := manageCliDecisionAlerts ( alertListFilter . IPEquals , alertListFilter . RangeEquals ,
alertListFilter . ScopeEquals , alertListFilter . ValueEquals ) ; err != nil {
2022-03-10 12:55:25 +00:00
printHelp ( cmd )
2023-02-20 14:05:42 +00:00
return err
2020-11-30 09:37:17 +00:00
}
if limit != nil {
alertListFilter . Limit = limit
}
if * alertListFilter . Until == "" {
alertListFilter . Until = nil
2022-11-07 09:36:50 +00:00
} else if strings . HasSuffix ( * alertListFilter . Until , "d" ) {
2020-11-30 09:37:17 +00:00
/*time.ParseDuration support hours 'h' as bigger unit, let's make the user's life easier*/
2022-11-07 09:36:50 +00:00
realDuration := strings . TrimSuffix ( * alertListFilter . Until , "d" )
days , err := strconv . Atoi ( realDuration )
if err != nil {
printHelp ( cmd )
2023-02-20 14:05:42 +00:00
return fmt . Errorf ( "can't parse duration %s, valid durations format: 1d, 4h, 4h15m" , * alertListFilter . Until )
2020-11-30 09:37:17 +00:00
}
2022-11-07 09:36:50 +00:00
* alertListFilter . Until = fmt . Sprintf ( "%d%s" , days * 24 , "h" )
2020-11-30 09:37:17 +00:00
}
if * alertListFilter . Since == "" {
alertListFilter . Since = nil
2022-11-07 09:36:50 +00:00
} else if strings . HasSuffix ( * alertListFilter . Since , "d" ) {
2020-11-30 09:37:17 +00:00
/*time.ParseDuration support hours 'h' as bigger unit, let's make the user's life easier*/
2022-11-07 09:36:50 +00:00
realDuration := strings . TrimSuffix ( * alertListFilter . Since , "d" )
days , err := strconv . Atoi ( realDuration )
if err != nil {
printHelp ( cmd )
2023-02-20 14:05:42 +00:00
return fmt . Errorf ( "can't parse duration %s, valid durations format: 1d, 4h, 4h15m" , * alertListFilter . Since )
2020-11-30 09:37:17 +00:00
}
2022-11-07 09:36:50 +00:00
* alertListFilter . Since = fmt . Sprintf ( "%d%s" , days * 24 , "h" )
2020-11-30 09:37:17 +00:00
}
2022-07-28 15:31:53 +00:00
if * alertListFilter . IncludeCAPI {
* alertListFilter . Limit = 0
}
2020-11-30 09:37:17 +00:00
if * alertListFilter . TypeEquals == "" {
alertListFilter . TypeEquals = nil
}
if * alertListFilter . ScopeEquals == "" {
alertListFilter . ScopeEquals = nil
}
if * alertListFilter . ValueEquals == "" {
alertListFilter . ValueEquals = nil
}
if * alertListFilter . ScenarioEquals == "" {
alertListFilter . ScenarioEquals = nil
}
if * alertListFilter . IPEquals == "" {
alertListFilter . IPEquals = nil
}
if * alertListFilter . RangeEquals == "" {
alertListFilter . RangeEquals = nil
}
2023-01-31 13:47:44 +00:00
if * alertListFilter . OriginEquals == "" {
alertListFilter . OriginEquals = nil
}
2021-01-15 08:48:39 +00:00
if contained != nil && * contained {
alertListFilter . Contains = new ( bool )
}
2023-01-31 13:47:44 +00:00
2024-02-01 16:24:00 +00:00
alerts , _ , err := cli . client . Alerts . List ( context . Background ( ) , alertListFilter )
2020-11-30 09:37:17 +00:00
if err != nil {
2024-02-09 16:51:29 +00:00
return fmt . Errorf ( "unable to list alerts: %w" , err )
2020-11-30 09:37:17 +00:00
}
2024-02-09 16:51:29 +00:00
if err = cli . alertsToTable ( alerts , printMachine ) ; err != nil {
return fmt . Errorf ( "unable to list alerts: %w" , err )
2020-11-30 09:37:17 +00:00
}
2023-02-20 14:05:42 +00:00
return nil
2020-11-30 09:37:17 +00:00
} ,
}
2024-02-09 16:51:29 +00:00
flags := cmd . Flags ( )
flags . SortFlags = false
flags . BoolVarP ( alertListFilter . IncludeCAPI , "all" , "a" , false , "Include decisions from Central API" )
flags . StringVar ( alertListFilter . Until , "until" , "" , "restrict to alerts older than until (ie. 4h, 30d)" )
flags . StringVar ( alertListFilter . Since , "since" , "" , "restrict to alerts newer than since (ie. 4h, 30d)" )
flags . StringVarP ( alertListFilter . IPEquals , "ip" , "i" , "" , "restrict to alerts from this source ip (shorthand for --scope ip --value <IP>)" )
flags . StringVarP ( alertListFilter . ScenarioEquals , "scenario" , "s" , "" , "the scenario (ie. crowdsecurity/ssh-bf)" )
flags . StringVarP ( alertListFilter . RangeEquals , "range" , "r" , "" , "restrict to alerts from this range (shorthand for --scope range --value <RANGE/X>)" )
flags . StringVar ( alertListFilter . TypeEquals , "type" , "" , "restrict to alerts with given decision type (ie. ban, captcha)" )
flags . StringVar ( alertListFilter . ScopeEquals , "scope" , "" , "restrict to alerts of this scope (ie. ip,range)" )
flags . StringVarP ( alertListFilter . ValueEquals , "value" , "v" , "" , "the value to match for in the specified scope" )
flags . StringVar ( alertListFilter . OriginEquals , "origin" , "" , fmt . Sprintf ( "the value to match for the specified origin (%s ...)" , strings . Join ( types . GetOrigins ( ) , "," ) ) )
flags . BoolVar ( contained , "contained" , false , "query decisions contained by range" )
flags . BoolVarP ( & printMachine , "machine" , "m" , false , "print machines that sent alerts" )
flags . IntVarP ( limit , "limit" , "l" , 50 , "limit size of alerts list table (0 to view all alerts)" )
2023-12-11 09:32:54 +00:00
return cmd
2023-01-06 22:14:02 +00:00
}
2024-02-01 16:24:00 +00:00
func ( cli * cliAlerts ) NewDeleteCmd ( ) * cobra . Command {
2024-02-09 16:51:29 +00:00
var (
ActiveDecision * bool
AlertDeleteAll bool
2024-03-20 13:02:29 +00:00
delAlertByID string
2024-02-09 16:51:29 +00:00
)
2020-11-30 09:37:17 +00:00
var alertDeleteFilter = apiclient . AlertsDeleteOpts {
ScopeEquals : new ( string ) ,
ValueEquals : new ( string ) ,
ScenarioEquals : new ( string ) ,
IPEquals : new ( string ) ,
RangeEquals : new ( string ) ,
}
2024-02-09 16:51:29 +00:00
contained := new ( bool )
2023-12-11 09:32:54 +00:00
cmd := & cobra . Command {
2020-11-30 09:37:17 +00:00
Use : "delete [filters] [--all]" ,
Short : ` Delete alerts
/ ! \ This command can be use only on the same machine than the local API . ` ,
Example : ` cscli alerts delete -- ip 1.2 .3 .4
cscli alerts delete -- range 1.2 .3 .0 / 24
cscli alerts delete - s crowdsecurity / ssh - bf " ` ,
2021-08-31 13:03:47 +00:00
DisableAutoGenTag : true ,
2022-04-20 13:44:48 +00:00
Aliases : [ ] string { "remove" } ,
2021-08-31 13:03:47 +00:00
Args : cobra . ExactArgs ( 0 ) ,
2024-02-09 16:51:29 +00:00
PreRunE : func ( cmd * cobra . Command , _ [ ] string ) error {
2020-11-30 09:37:17 +00:00
if AlertDeleteAll {
2023-02-20 14:05:42 +00:00
return nil
2020-11-30 09:37:17 +00:00
}
if * alertDeleteFilter . ScopeEquals == "" && * alertDeleteFilter . ValueEquals == "" &&
* alertDeleteFilter . ScenarioEquals == "" && * alertDeleteFilter . IPEquals == "" &&
2022-10-27 07:07:53 +00:00
* alertDeleteFilter . RangeEquals == "" && delAlertByID == "" {
2020-11-30 09:37:17 +00:00
_ = cmd . Usage ( )
2023-02-20 14:05:42 +00:00
return fmt . Errorf ( "at least one filter or --all must be specified" )
2020-11-30 09:37:17 +00:00
}
2023-02-20 14:05:42 +00:00
return nil
2020-11-30 09:37:17 +00:00
} ,
2024-02-09 16:51:29 +00:00
RunE : func ( cmd * cobra . Command , _ [ ] string ) error {
2020-11-30 09:37:17 +00:00
var err error
if ! AlertDeleteAll {
2024-02-09 16:51:29 +00:00
if err = manageCliDecisionAlerts ( alertDeleteFilter . IPEquals , alertDeleteFilter . RangeEquals ,
2020-11-30 09:37:17 +00:00
alertDeleteFilter . ScopeEquals , alertDeleteFilter . ValueEquals ) ; err != nil {
2022-03-10 12:55:25 +00:00
printHelp ( cmd )
2023-02-20 14:05:42 +00:00
return err
2020-11-30 09:37:17 +00:00
}
if ActiveDecision != nil {
alertDeleteFilter . ActiveDecisionEquals = ActiveDecision
}
if * alertDeleteFilter . ScopeEquals == "" {
alertDeleteFilter . ScopeEquals = nil
}
if * alertDeleteFilter . ValueEquals == "" {
alertDeleteFilter . ValueEquals = nil
}
if * alertDeleteFilter . ScenarioEquals == "" {
alertDeleteFilter . ScenarioEquals = nil
}
if * alertDeleteFilter . IPEquals == "" {
alertDeleteFilter . IPEquals = nil
}
if * alertDeleteFilter . RangeEquals == "" {
alertDeleteFilter . RangeEquals = nil
}
2021-01-15 08:48:39 +00:00
if contained != nil && * contained {
alertDeleteFilter . Contains = new ( bool )
}
2022-10-07 10:40:30 +00:00
limit := 0
alertDeleteFilter . Limit = & limit
2020-11-30 09:37:17 +00:00
} else {
2021-04-27 09:59:18 +00:00
limit := 0
alertDeleteFilter = apiclient . AlertsDeleteOpts { Limit : & limit }
2020-11-30 09:37:17 +00:00
}
2022-10-27 07:07:53 +00:00
var alerts * models . DeleteAlertsResponse
if delAlertByID == "" {
2024-02-01 16:24:00 +00:00
alerts , _ , err = cli . client . Alerts . Delete ( context . Background ( ) , alertDeleteFilter )
2022-10-27 07:07:53 +00:00
if err != nil {
2024-02-09 16:51:29 +00:00
return fmt . Errorf ( "unable to delete alerts: %w" , err )
2022-10-27 07:07:53 +00:00
}
} else {
2024-02-01 16:24:00 +00:00
alerts , _ , err = cli . client . Alerts . DeleteOne ( context . Background ( ) , delAlertByID )
2022-10-27 07:07:53 +00:00
if err != nil {
2024-02-09 16:51:29 +00:00
return fmt . Errorf ( "unable to delete alert: %w" , err )
2022-10-27 07:07:53 +00:00
}
2020-11-30 09:37:17 +00:00
}
log . Infof ( "%s alert(s) deleted" , alerts . NbDeleted )
2023-02-20 14:05:42 +00:00
return nil
2020-11-30 09:37:17 +00:00
} ,
}
2024-03-20 13:02:29 +00:00
2024-02-09 16:51:29 +00:00
flags := cmd . Flags ( )
flags . SortFlags = false
flags . StringVar ( alertDeleteFilter . ScopeEquals , "scope" , "" , "the scope (ie. ip,range)" )
flags . StringVarP ( alertDeleteFilter . ValueEquals , "value" , "v" , "" , "the value to match for in the specified scope" )
flags . StringVarP ( alertDeleteFilter . ScenarioEquals , "scenario" , "s" , "" , "the scenario (ie. crowdsecurity/ssh-bf)" )
flags . StringVarP ( alertDeleteFilter . IPEquals , "ip" , "i" , "" , "Source ip (shorthand for --scope ip --value <IP>)" )
flags . StringVarP ( alertDeleteFilter . RangeEquals , "range" , "r" , "" , "Range source ip (shorthand for --scope range --value <RANGE>)" )
flags . StringVar ( & delAlertByID , "id" , "" , "alert ID" )
flags . BoolVarP ( & AlertDeleteAll , "all" , "a" , false , "delete all alerts" )
flags . BoolVar ( contained , "contained" , false , "query decisions contained by range" )
2023-12-11 09:32:54 +00:00
return cmd
2023-01-06 22:14:02 +00:00
}
2020-11-30 09:37:17 +00:00
2024-02-01 16:24:00 +00:00
func ( cli * cliAlerts ) NewInspectCmd ( ) * cobra . Command {
2020-11-30 09:37:17 +00:00
var details bool
2024-02-09 16:51:29 +00:00
2023-12-11 09:32:54 +00:00
cmd := & cobra . Command {
2021-08-31 13:03:47 +00:00
Use : ` inspect "alert_id" ` ,
Short : ` Show info about an alert ` ,
Example : ` cscli alerts inspect 123 ` ,
DisableAutoGenTag : true ,
2023-02-20 14:05:42 +00:00
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2024-02-09 16:51:29 +00:00
cfg := cli . cfg ( )
2020-11-30 09:37:17 +00:00
if len ( args ) == 0 {
2022-03-10 12:55:25 +00:00
printHelp ( cmd )
2023-02-20 14:05:42 +00:00
return fmt . Errorf ( "missing alert_id" )
2020-11-30 09:37:17 +00:00
}
for _ , alertID := range args {
id , err := strconv . Atoi ( alertID )
if err != nil {
2023-02-20 14:05:42 +00:00
return fmt . Errorf ( "bad alert id %s" , alertID )
2020-11-30 09:37:17 +00:00
}
2024-02-01 16:24:00 +00:00
alert , _ , err := cli . client . Alerts . GetByID ( context . Background ( ) , id )
2020-11-30 09:37:17 +00:00
if err != nil {
2024-02-09 16:51:29 +00:00
return fmt . Errorf ( "can't find alert with id %s: %w" , alertID , err )
2020-11-30 09:37:17 +00:00
}
2024-02-09 16:51:29 +00:00
switch cfg . Cscli . Output {
2020-11-30 09:37:17 +00:00
case "human" :
2024-02-09 16:51:29 +00:00
if err := cli . displayOneAlert ( alert , details ) ; err != nil {
2020-11-30 09:37:17 +00:00
continue
}
case "json" :
data , err := json . MarshalIndent ( alert , "" , " " )
if err != nil {
2024-02-09 16:51:29 +00:00
return fmt . Errorf ( "unable to marshal alert with id %s: %w" , alertID , err )
2020-11-30 09:37:17 +00:00
}
fmt . Printf ( "%s\n" , string ( data ) )
case "raw" :
data , err := yaml . Marshal ( alert )
if err != nil {
2024-02-09 16:51:29 +00:00
return fmt . Errorf ( "unable to marshal alert with id %s: %w" , alertID , err )
2020-11-30 09:37:17 +00:00
}
2024-02-09 16:51:29 +00:00
fmt . Println ( string ( data ) )
2020-11-30 09:37:17 +00:00
}
}
2023-02-20 14:05:42 +00:00
return nil
2020-11-30 09:37:17 +00:00
} ,
}
2024-02-09 16:51:29 +00:00
2023-12-11 09:32:54 +00:00
cmd . Flags ( ) . SortFlags = false
cmd . Flags ( ) . BoolVarP ( & details , "details" , "d" , false , "show alerts with events" )
2020-11-30 09:37:17 +00:00
2023-12-11 09:32:54 +00:00
return cmd
2023-01-06 22:14:02 +00:00
}
2020-11-30 09:37:17 +00:00
2024-02-01 16:24:00 +00:00
func ( cli * cliAlerts ) NewFlushCmd ( ) * cobra . Command {
2024-02-09 16:51:29 +00:00
var (
maxItems int
2024-03-20 13:02:29 +00:00
maxAge string
2024-02-09 16:51:29 +00:00
)
2023-12-11 09:32:54 +00:00
cmd := & cobra . Command {
2021-10-26 11:33:45 +00:00
Use : ` flush ` ,
Short : ` Flush alerts
/ ! \ This command can be used only on the same machine than the local API ` ,
Example : ` cscli alerts flush --max-items 1000 --max-age 7d ` ,
DisableAutoGenTag : true ,
2024-02-09 16:51:29 +00:00
RunE : func ( _ * cobra . Command , _ [ ] string ) error {
cfg := cli . cfg ( )
if err := require . LAPI ( cfg ) ; err != nil {
2023-07-27 15:02:20 +00:00
return err
2021-10-26 11:33:45 +00:00
}
2024-02-09 16:51:29 +00:00
db , err := database . NewClient ( cfg . DbConfig )
2021-10-26 11:33:45 +00:00
if err != nil {
2024-02-09 16:51:29 +00:00
return fmt . Errorf ( "unable to create new database client: %w" , err )
2021-10-26 11:33:45 +00:00
}
log . Info ( "Flushing alerts. !! This may take a long time !!" )
2024-02-01 16:24:00 +00:00
err = db . FlushAlerts ( maxAge , maxItems )
2021-10-26 11:33:45 +00:00
if err != nil {
2024-02-09 16:51:29 +00:00
return fmt . Errorf ( "unable to flush alerts: %w" , err )
2021-10-26 11:33:45 +00:00
}
log . Info ( "Alerts flushed" )
2023-02-20 14:05:42 +00:00
return nil
2021-10-26 11:33:45 +00:00
} ,
}
2023-12-11 09:32:54 +00:00
cmd . Flags ( ) . SortFlags = false
cmd . Flags ( ) . IntVar ( & maxItems , "max-items" , 5000 , "Maximum number of alert items to keep in the database" )
cmd . Flags ( ) . StringVar ( & maxAge , "max-age" , "7d" , "Maximum age of alert items to keep in the database" )
2021-10-26 11:33:45 +00:00
2023-12-11 09:32:54 +00:00
return cmd
2020-11-30 09:37:17 +00:00
}