mirror of
https://github.com/crowdsecurity/crowdsec.git
synced 2025-05-10 20:05:55 +02:00
custom duration type for "cscli decisions list", "cscli alerts list"
This commit is contained in:
parent
d10067e772
commit
45c6c11a15
9 changed files with 52 additions and 83 deletions
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/crowdsecurity/go-cs-lib/cstime"
|
||||
"github.com/crowdsecurity/go-cs-lib/maptools"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/args"
|
||||
|
@ -247,34 +248,6 @@ func (cli *cliAlerts) list(ctx context.Context, alertListFilter apiclient.Alerts
|
|||
alertListFilter.Limit = limit
|
||||
}
|
||||
|
||||
if *alertListFilter.Until == "" {
|
||||
alertListFilter.Until = nil
|
||||
} else if strings.HasSuffix(*alertListFilter.Until, "d") {
|
||||
/*time.ParseDuration support hours 'h' as bigger unit, let's make the user's life easier*/
|
||||
realDuration := strings.TrimSuffix(*alertListFilter.Until, "d")
|
||||
|
||||
days, err := strconv.Atoi(realDuration)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't parse duration %s, valid durations format: 1d, 4h, 4h15m", *alertListFilter.Until)
|
||||
}
|
||||
|
||||
*alertListFilter.Until = fmt.Sprintf("%d%s", days*24, "h")
|
||||
}
|
||||
|
||||
if *alertListFilter.Since == "" {
|
||||
alertListFilter.Since = nil
|
||||
} else if strings.HasSuffix(*alertListFilter.Since, "d") {
|
||||
// time.ParseDuration support hours 'h' as bigger unit, let's make the user's life easier
|
||||
realDuration := strings.TrimSuffix(*alertListFilter.Since, "d")
|
||||
|
||||
days, err := strconv.Atoi(realDuration)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't parse duration %s, valid durations format: 1d, 4h, 4h15m", *alertListFilter.Since)
|
||||
}
|
||||
|
||||
*alertListFilter.Since = fmt.Sprintf("%d%s", days*24, "h")
|
||||
}
|
||||
|
||||
if *alertListFilter.IncludeCAPI {
|
||||
*alertListFilter.Limit = 0
|
||||
}
|
||||
|
@ -330,8 +303,8 @@ func (cli *cliAlerts) newListCmd() *cobra.Command {
|
|||
ScenarioEquals: new(string),
|
||||
IPEquals: new(string),
|
||||
RangeEquals: new(string),
|
||||
Since: new(string),
|
||||
Until: new(string),
|
||||
Since: cstime.Duration(0),
|
||||
Until: cstime.Duration(0),
|
||||
TypeEquals: new(string),
|
||||
IncludeCAPI: new(bool),
|
||||
OriginEquals: new(string),
|
||||
|
@ -362,8 +335,8 @@ cscli alerts list --type ban`,
|
|||
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.Var(&alertListFilter.Until, "until", "restrict to alerts older than until (ie. 4h, 30d)")
|
||||
flags.Var(&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>)")
|
||||
|
|
|
@ -23,6 +23,8 @@ import (
|
|||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
|
||||
"github.com/crowdsecurity/go-cs-lib/cstime"
|
||||
)
|
||||
|
||||
type configGetter func() *csconfig.Config
|
||||
|
@ -184,34 +186,8 @@ func (cli *cliDecisions) list(ctx context.Context, filter apiclient.AlertsListOp
|
|||
if noSimu != nil && *noSimu {
|
||||
filter.IncludeSimulated = new(bool)
|
||||
}
|
||||
|
||||
/* nullify the empty entries to avoid bad filter */
|
||||
if *filter.Until == "" {
|
||||
filter.Until = nil
|
||||
} else if strings.HasSuffix(*filter.Until, "d") {
|
||||
/*time.ParseDuration support hours 'h' as bigger unit, let's make the user's life easier*/
|
||||
realDuration := strings.TrimSuffix(*filter.Until, "d")
|
||||
|
||||
days, err := strconv.Atoi(realDuration)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't parse duration %s, valid durations format: 1d, 4h, 4h15m", *filter.Until)
|
||||
}
|
||||
|
||||
*filter.Until = fmt.Sprintf("%d%s", days*24, "h")
|
||||
}
|
||||
|
||||
if *filter.Since == "" {
|
||||
filter.Since = nil
|
||||
} else if strings.HasSuffix(*filter.Since, "d") {
|
||||
/*time.ParseDuration support hours 'h' as bigger unit, let's make the user's life easier*/
|
||||
realDuration := strings.TrimSuffix(*filter.Since, "d")
|
||||
|
||||
days, err := strconv.Atoi(realDuration)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't parse duration %s, valid durations format: 1d, 4h, 4h15m", *filter.Since)
|
||||
}
|
||||
|
||||
*filter.Since = fmt.Sprintf("%d%s", days*24, "h")
|
||||
}
|
||||
|
||||
if *filter.IncludeCAPI {
|
||||
*filter.Limit = 0
|
||||
|
@ -270,8 +246,8 @@ func (cli *cliDecisions) newListCmd() *cobra.Command {
|
|||
OriginEquals: new(string),
|
||||
IPEquals: new(string),
|
||||
RangeEquals: new(string),
|
||||
Since: new(string),
|
||||
Until: new(string),
|
||||
Since: cstime.Duration(0),
|
||||
Until: cstime.Duration(0),
|
||||
TypeEquals: new(string),
|
||||
IncludeCAPI: new(bool),
|
||||
Limit: new(int),
|
||||
|
@ -300,8 +276,8 @@ cscli decisions list --origin lists --scenario list_name
|
|||
flags := cmd.Flags()
|
||||
flags.SortFlags = false
|
||||
flags.BoolVarP(filter.IncludeCAPI, "all", "a", false, "Include decisions from Central API")
|
||||
flags.StringVar(filter.Since, "since", "", "restrict to alerts newer than since (ie. 4h, 30d)")
|
||||
flags.StringVar(filter.Until, "until", "", "restrict to alerts older than until (ie. 4h, 30d)")
|
||||
flags.Var(&filter.Since, "since", "restrict to alerts newer than since (ie. 4h, 30d)")
|
||||
flags.Var(&filter.Until, "until", "restrict to alerts older than until (ie. 4h, 30d)")
|
||||
flags.StringVarP(filter.TypeEquals, "type", "t", "", "restrict to this decision type (ie. ban,captcha)")
|
||||
flags.StringVar(filter.ScopeEquals, "scope", "", "restrict to this scope (ie. ip,range,session)")
|
||||
flags.StringVar(filter.OriginEquals, "origin", "", fmt.Sprintf("the value to match for the specified origin (%s ...)", strings.Join(types.GetOrigins(), ",")))
|
||||
|
|
10
go.mod
10
go.mod
|
@ -24,7 +24,7 @@ require (
|
|||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/creack/pty v1.1.21 // indirect
|
||||
github.com/crowdsecurity/dlog v0.0.0-20170105205344-4fb5f8204f26
|
||||
github.com/crowdsecurity/go-cs-lib v0.0.18
|
||||
github.com/crowdsecurity/go-cs-lib v0.0.19-0.20250429135122-36305bb35807
|
||||
github.com/crowdsecurity/grokky v0.2.2
|
||||
github.com/crowdsecurity/machineid v1.0.2
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
|
||||
|
@ -87,8 +87,8 @@ require (
|
|||
github.com/shirou/gopsutil/v3 v3.23.5
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/slack-go/slack v0.16.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/umahmood/haversine v0.0.0-20151105152445-808ab04add26
|
||||
github.com/wasilibs/go-re2 v1.7.0
|
||||
|
@ -100,7 +100,7 @@ require (
|
|||
go.opentelemetry.io/otel/trace v1.28.0 // indirect
|
||||
golang.org/x/crypto v0.36.0
|
||||
golang.org/x/mod v0.23.0
|
||||
golang.org/x/net v0.38.0 // indirect
|
||||
golang.org/x/net v0.38.0
|
||||
golang.org/x/sync v0.12.0
|
||||
golang.org/x/sys v0.31.0
|
||||
golang.org/x/text v0.23.0
|
||||
|
@ -131,7 +131,7 @@ require (
|
|||
github.com/bytedance/sonic/loader v0.2.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.7 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
|
|
15
go.sum
15
go.sum
|
@ -100,8 +100,8 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7
|
|||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
|
@ -111,8 +111,8 @@ github.com/crowdsecurity/coraza/v3 v3.0.0-20250320231801-749b8bded21a h1:2Nyr+47
|
|||
github.com/crowdsecurity/coraza/v3 v3.0.0-20250320231801-749b8bded21a/go.mod h1:xSaXWOhFMSbrV8qOOfBKAyw3aOqfwaSaOy5BgSF8XlA=
|
||||
github.com/crowdsecurity/dlog v0.0.0-20170105205344-4fb5f8204f26 h1:r97WNVC30Uen+7WnLs4xDScS/Ex988+id2k6mDf8psU=
|
||||
github.com/crowdsecurity/dlog v0.0.0-20170105205344-4fb5f8204f26/go.mod h1:zpv7r+7KXwgVUZnUNjyP22zc/D7LKjyoY02weH2RBbk=
|
||||
github.com/crowdsecurity/go-cs-lib v0.0.18 h1:GNyvaag5MXfuapIy4E30pIOvIE5AyHoanJBNSMA1cmE=
|
||||
github.com/crowdsecurity/go-cs-lib v0.0.18/go.mod h1:XwGcvTt4lMq4Tm1IRMSKMDf0CVrnytTU8Uoofa7AR+g=
|
||||
github.com/crowdsecurity/go-cs-lib v0.0.19-0.20250429135122-36305bb35807 h1:vle0PUZT8/S+PBA+QjV47RzjyoDtY3jLOtO/RZW1JTc=
|
||||
github.com/crowdsecurity/go-cs-lib v0.0.19-0.20250429135122-36305bb35807/go.mod h1:vQljl8j38dF6QKjlxXCjIBHCADzYt3PcBTN6REPH42g=
|
||||
github.com/crowdsecurity/grokky v0.2.2 h1:yALsI9zqpDArYzmSSxfBq2dhYuGUTKMJq8KOEIAsuo4=
|
||||
github.com/crowdsecurity/grokky v0.2.2/go.mod h1:33usDIYzGDsgX1kHAThCbseso6JuWNJXOzRQDGXHtWM=
|
||||
github.com/crowdsecurity/machineid v1.0.2 h1:wpkpsUghJF8Khtmn/tg6GxgdhLA1Xflerh5lirI+bdc=
|
||||
|
@ -660,11 +660,12 @@ github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
|||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
|
||||
qs "github.com/google/go-querystring/query"
|
||||
|
||||
"github.com/crowdsecurity/go-cs-lib/cstime"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||
)
|
||||
|
||||
|
@ -19,9 +21,9 @@ type AlertsListOpts struct {
|
|||
IPEquals *string `url:"ip,omitempty"`
|
||||
RangeEquals *string `url:"range,omitempty"`
|
||||
OriginEquals *string `url:"origin,omitempty"`
|
||||
Since *string `url:"since,omitempty"`
|
||||
Since cstime.Duration `url:"since,omitempty"`
|
||||
TypeEquals *string `url:"decision_type,omitempty"`
|
||||
Until *string `url:"until,omitempty"`
|
||||
Until cstime.Duration `url:"until,omitempty"`
|
||||
IncludeSimulated *bool `url:"simulated,omitempty"`
|
||||
ActiveDecisionEquals *bool `url:"has_active_decision,omitempty"`
|
||||
IncludeCAPI *bool `url:"include_capi,omitempty"`
|
||||
|
@ -36,8 +38,8 @@ type AlertsDeleteOpts struct {
|
|||
ScenarioEquals *string `url:"scenario,omitempty"`
|
||||
IPEquals *string `url:"ip,omitempty"`
|
||||
RangeEquals *string `url:"range,omitempty"`
|
||||
Since *string `url:"since,omitempty"`
|
||||
Until *string `url:"until,omitempty"`
|
||||
Since cstime.Duration `url:"since,omitempty"`
|
||||
Until cstime.Duration `url:"until,omitempty"`
|
||||
OriginEquals *string `url:"origin,omitempty"`
|
||||
ActiveDecisionEquals *bool `url:"has_active_decision,omitempty"`
|
||||
SourceEquals *string `url:"alert_source,omitempty"`
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/crowdsecurity/go-cs-lib/cstime"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/alert"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/decision"
|
||||
|
@ -40,7 +42,9 @@ func handleScopeFilter(scope string, predicates *[]predicate.Alert) {
|
|||
}
|
||||
|
||||
func handleTimeFilters(param, value string, predicates *[]predicate.Alert) error {
|
||||
duration, err := ParseDuration(value)
|
||||
// crowsdec now always sends duration without days, but we allow them for
|
||||
// compatibility with other tools
|
||||
duration, err := cstime.ParseDuration(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("while parsing duration: %w", err)
|
||||
}
|
||||
|
|
|
@ -43,6 +43,15 @@ teardown() {
|
|||
assert_output --regexp " githubciXXXXXXXXXXXXXXXXXXXXXXXX([a-zA-Z0-9]{16})? "
|
||||
}
|
||||
|
||||
@test "cscli alerts list, accept duration parameters with days" {
|
||||
rune -1 cscli alerts list --until toto
|
||||
assert_stderr 'Error: invalid argument "toto" for "--until" flag: time: invalid duration "toto"'
|
||||
rune -0 cscli alerts list --until 2d12h --debug
|
||||
assert_stderr --partial "until=60h0m0s"
|
||||
rune -0 cscli alerts list --since 2d12h --debug
|
||||
assert_stderr --partial "since=60h0m0s"
|
||||
}
|
||||
|
||||
@test "cscli alerts list, human/json/raw" {
|
||||
rune -0 cscli decisions add -i 10.20.30.40 -t ban
|
||||
|
||||
|
|
|
@ -54,9 +54,13 @@ teardown() {
|
|||
assert_output --regexp " githubciXXXXXXXXXXXXXXXXXXXXXXXX([a-zA-Z0-9]{16})? "
|
||||
}
|
||||
|
||||
@test "cscli decisions list, incorrect parameters" {
|
||||
@test "cscli decisions list, accept duration parameters with days" {
|
||||
rune -1 cscli decisions list --until toto
|
||||
assert_stderr 'Error: unable to retrieve decisions: performing request: API error: while parsing duration: time: invalid duration "toto"'
|
||||
assert_stderr 'Error: invalid argument "toto" for "--until" flag: time: invalid duration "toto"'
|
||||
rune -0 cscli decisions list --until 2d12h --debug
|
||||
assert_stderr --partial "until=60h0m0s"
|
||||
rune -0 cscli decisions list --since 2d12h --debug
|
||||
assert_stderr --partial "since=60h0m0s"
|
||||
}
|
||||
|
||||
@test "cscli decisions import" {
|
||||
|
|
|
@ -124,7 +124,7 @@ teardown() {
|
|||
|
||||
rune -1 cscli allowlist add foo 10.10.10.10 10.20.30.40 -d comment -e '1 day'
|
||||
refute_output
|
||||
assert_stderr 'Error: strconv.Atoi: parsing "1 ": invalid syntax'
|
||||
assert_stderr 'Error: invalid day value in duration "1 day"'
|
||||
|
||||
rune -0 cscli allowlist add foo 10.10.10.10 -d comment -e '1d'
|
||||
assert_output 'added 1 values to allowlist foo'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue