Skip to content

Commit

Permalink
refactor pkg/database, pkg/models (#3022)
Browse files Browse the repository at this point in the history
* pkg/models: Source.String()

* pkg/models: Alert.FormatAsStrings()

* cscli alerts list: sort remediation keys

avoid printing
"ban: ... captcha: ..."
in one line, and
"captcha: ... ban: ..."
in another

* remove unused methods; drop else branch

* lint
  • Loading branch information
mmetc authored Jun 5, 2024
1 parent 73e03ef commit 9e859c0
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 110 deletions.
6 changes: 4 additions & 2 deletions cmd/crowdsec-cli/alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"

"github.com/crowdsecurity/go-cs-lib/maptools"

"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
Expand All @@ -41,12 +43,12 @@ func DecisionsFromAlert(alert *models.Alert) string {
decMap[k] = v + 1
}

for k, v := range decMap {
for _, key := range maptools.SortedKeys(decMap) {
if len(ret) > 0 {
ret += " "
}

ret += fmt.Sprintf("%s:%d", k, v)
ret += fmt.Sprintf("%s:%d", key, decMap[key])
}

return ret
Expand Down
100 changes: 3 additions & 97 deletions pkg/database/alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"strings"
"time"

"github.com/davecgh/go-spew/spew"
"github.com/mattn/go-sqlite3"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
Expand All @@ -33,101 +32,6 @@ const (
maxLockRetries = 10 // how many times to retry a bulk operation when sqlite3.ErrBusy is encountered
)

func formatAlertCN(source models.Source) string {
cn := source.Cn

if source.AsNumber != "" {
cn += "/" + source.AsNumber
}

return cn
}

func formatAlertSource(alert *models.Alert) string {
if alert.Source == nil || alert.Source.Scope == nil || *alert.Source.Scope == "" {
return "empty source"
}

if *alert.Source.Scope == types.Ip {
ret := "ip " + *alert.Source.Value

cn := formatAlertCN(*alert.Source)
if cn != "" {
ret += " (" + cn + ")"
}

return ret
}

if *alert.Source.Scope == types.Range {
ret := "range " + *alert.Source.Value

cn := formatAlertCN(*alert.Source)
if cn != "" {
ret += " (" + cn + ")"
}

return ret
}

return *alert.Source.Scope + " " + *alert.Source.Value
}

func formatAlertAsString(machineID string, alert *models.Alert) []string {
src := formatAlertSource(alert)

msg := "empty scenario"
if alert.Scenario != nil && *alert.Scenario != "" {
msg = *alert.Scenario
} else if alert.Message != nil && *alert.Message != "" {
msg = *alert.Message
}

reason := fmt.Sprintf("%s by %s", msg, src)

if len(alert.Decisions) == 0 {
return []string{fmt.Sprintf("(%s) alert : %s", machineID, reason)}
}

var retStr []string

if alert.Decisions[0].Origin != nil && *alert.Decisions[0].Origin == types.CscliImportOrigin {
return []string{fmt.Sprintf("(%s) alert : %s", machineID, reason)}
}

for i, decisionItem := range alert.Decisions {
decision := ""
if alert.Simulated != nil && *alert.Simulated {
decision = "(simulated alert)"
} else if decisionItem.Simulated != nil && *decisionItem.Simulated {
decision = "(simulated decision)"
}

if log.GetLevel() >= log.DebugLevel {
/*spew is expensive*/
log.Debugf("%s", spew.Sdump(decisionItem))
}

if len(alert.Decisions) > 1 {
reason = fmt.Sprintf("%s for %d/%d decisions", msg, i+1, len(alert.Decisions))
}

var machineIDOrigin string
if machineID == "" {
machineIDOrigin = *decisionItem.Origin
} else {
machineIDOrigin = fmt.Sprintf("%s/%s", machineID, *decisionItem.Origin)
}

decision += fmt.Sprintf("%s %s on %s %s", *decisionItem.Duration,
*decisionItem.Type, *decisionItem.Scope, *decisionItem.Value)
retStr = append(retStr,
fmt.Sprintf("(%s) %s : %s", machineIDOrigin, reason, decision))
}

return retStr
}

// CreateOrUpdateAlert is specific to PAPI : It checks if alert already exists, otherwise inserts it
// if alert already exists, it checks it associated decisions already exists
// if some associated decisions are missing (ie. previous insert ended up in error) it inserts them
Expand Down Expand Up @@ -562,8 +466,9 @@ func (c *Client) createAlertChunk(machineID string, owner *ent.Machine, alerts [

stopAtTime = time.Now().UTC()
}

/*display proper alert in logs*/
for _, disp := range formatAlertAsString(machineID, alertItem) {
for _, disp := range alertItem.FormatAsStrings(machineID, log.StandardLogger()) {
c.Log.Info(disp)
}

Expand Down Expand Up @@ -649,6 +554,7 @@ func (c *Client) createAlertChunk(machineID string, owner *ent.Machine, alerts [

if len(metaItem.Value) > 4095 {
c.Log.Warningf("truncated meta %s : value too long", metaItem.Key)

value = value[:4095]
}

Expand Down
113 changes: 102 additions & 11 deletions pkg/models/helpers.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,41 @@
package models

func (a *Alert) HasRemediation() bool {
return true
}
import (
"fmt"

"github.com/davecgh/go-spew/spew"
log "github.com/sirupsen/logrus"
)

const (
// these are duplicated from pkg/types
// TODO XXX: de-duplicate
Ip = "Ip"
Range = "Range"
CscliImportOrigin = "cscli-import"
)

func (a *Alert) GetScope() string {
if a.Source.Scope == nil {
return ""
}
return *a.Source.Scope
return a.Source.GetScope()
}

func (a *Alert) GetValue() string {
if a.Source.Value == nil {
return ""
}
return *a.Source.Value
return a.Source.GetValue()
}

func (a *Alert) GetScenario() string {
if a.Scenario == nil {
return ""
}

return *a.Scenario
}

func (a *Alert) GetEventsCount() int32 {
if a.EventsCount == nil {
return 0
}

return *a.EventsCount
}

Expand All @@ -38,6 +45,7 @@ func (e *Event) GetMeta(key string) string {
return meta.Value
}
}

return ""
}

Expand All @@ -47,20 +55,23 @@ func (a *Alert) GetMeta(key string) string {
return meta.Value
}
}

return ""
}

func (s Source) GetValue() string {
if s.Value == nil {
return ""
}

return *s.Value
}

func (s Source) GetScope() string {
if s.Scope == nil {
return ""
}

return *s.Scope
}

Expand All @@ -69,8 +80,88 @@ func (s Source) GetAsNumberName() string {
if s.AsNumber != "0" {
ret += s.AsNumber
}

if s.AsName != "" {
ret += " " + s.AsName
}

return ret
}

func (s *Source) String() string {
if s == nil || s.Scope == nil || *s.Scope == "" {
return "empty source"
}

cn := s.Cn

if s.AsNumber != "" {
cn += "/" + s.AsNumber
}

if cn != "" {
cn = " (" + cn + ")"
}

switch *s.Scope {
case Ip:
return "ip " + *s.Value + cn
case Range:
return "range " + *s.Value + cn
default:
return *s.Scope + " " + *s.Value
}
}

func (a *Alert) FormatAsStrings(machineID string, logger *log.Logger) []string {
src := a.Source.String()

msg := "empty scenario"
if a.Scenario != nil && *a.Scenario != "" {
msg = *a.Scenario
} else if a.Message != nil && *a.Message != "" {
msg = *a.Message
}

reason := fmt.Sprintf("%s by %s", msg, src)

if len(a.Decisions) == 0 {
return []string{fmt.Sprintf("(%s) alert : %s", machineID, reason)}
}

var retStr []string

if a.Decisions[0].Origin != nil && *a.Decisions[0].Origin == CscliImportOrigin {
return []string{fmt.Sprintf("(%s) alert : %s", machineID, reason)}
}

for i, decisionItem := range a.Decisions {
decision := ""
if a.Simulated != nil && *a.Simulated {
decision = "(simulated alert)"
} else if decisionItem.Simulated != nil && *decisionItem.Simulated {
decision = "(simulated decision)"
}

if logger.GetLevel() >= log.DebugLevel {
/*spew is expensive*/
logger.Debug(spew.Sdump(decisionItem))
}

if len(a.Decisions) > 1 {
reason = fmt.Sprintf("%s for %d/%d decisions", msg, i+1, len(a.Decisions))
}

origin := *decisionItem.Origin
if machineID != "" {
origin = machineID + "/" + origin
}

decision += fmt.Sprintf("%s %s on %s %s", *decisionItem.Duration,
*decisionItem.Type, *decisionItem.Scope, *decisionItem.Value)
retStr = append(retStr,
fmt.Sprintf("(%s) %s : %s", origin, reason, decision))
}

return retStr
}

0 comments on commit 9e859c0

Please sign in to comment.