Skip to content

Commit 7747b9c

Browse files
authored
refact pkg/parser: ExtraField / Static (#3913)
* refact parser: rename ExtraField -> Static * refact parser: split Static - RuntimeStatic * refact parser: extract RuntimeStatic.Apply() * lint
1 parent bca0483 commit 7747b9c

File tree

6 files changed

+269
-205
lines changed

6 files changed

+269
-205
lines changed

cmd/crowdsec-cli/clilapi/context.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package clilapi
33
import (
44
"errors"
55
"fmt"
6+
"os"
67
"slices"
78
"sort"
89
"strings"
@@ -114,7 +115,7 @@ func (cli *cliLapi) newContextStatusCmd() *cobra.Command {
114115
}
115116

116117
if len(cfg.Crowdsec.ContextToSend) == 0 {
117-
fmt.Println("No context found on this agent. You can use 'cscli lapi context add' to add context to your alerts.")
118+
fmt.Fprintln(os.Stdout, "No context found on this agent. You can use 'cscli lapi context add' to add context to your alerts.")
118119
return nil
119120
}
120121

@@ -123,7 +124,7 @@ func (cli *cliLapi) newContextStatusCmd() *cobra.Command {
123124
return fmt.Errorf("unable to show context status: %w", err)
124125
}
125126

126-
fmt.Print(string(dump))
127+
fmt.Fprint(os.Stdout, string(dump))
127128

128129
return nil
129130
},
@@ -185,11 +186,10 @@ cscli lapi context detect crowdsecurity/sshd-logs
185186
}
186187
}
187188

188-
fmt.Printf("Acquisition :\n\n")
189-
fmt.Printf(" - evt.Line.Module\n")
190-
fmt.Printf(" - evt.Line.Raw\n")
191-
fmt.Printf(" - evt.Line.Src\n")
192-
fmt.Println()
189+
fmt.Fprint(os.Stdout, "Acquisition :\n\n")
190+
fmt.Fprint(os.Stdout, " - evt.Line.Module\n")
191+
fmt.Fprint(os.Stdout, " - evt.Line.Raw\n")
192+
fmt.Fprint(os.Stdout, " - evt.Line.Src\n\n")
193193

194194
parsersKey := make([]string, 0)
195195
for k := range fieldByParsers {
@@ -201,13 +201,13 @@ cscli lapi context detect crowdsecurity/sshd-logs
201201
if len(fieldByParsers[k]) == 0 {
202202
continue
203203
}
204-
fmt.Printf("%s :\n\n", k)
204+
fmt.Fprintf(os.Stdout, "%s :\n\n", k)
205205
values := fieldByParsers[k]
206206
sort.Strings(values)
207207
for _, value := range values {
208-
fmt.Printf(" - %s\n", value)
208+
fmt.Fprintf(os.Stdout, " - %s\n", value)
209209
}
210-
fmt.Println()
210+
fmt.Fprintln(os.Stdout)
211211
}
212212

213213
if len(args) > 0 {
@@ -270,7 +270,7 @@ func (cli *cliLapi) newContextCmd() *cobra.Command {
270270
return cmd
271271
}
272272

273-
func detectStaticField(grokStatics []parser.ExtraField) []string {
273+
func detectStaticField(grokStatics []parser.Static) []string {
274274
ret := make([]string, 0)
275275

276276
for _, static := range grokStatics {

pkg/hubtest/hubtest_item.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type HubTestItemConfig struct {
3535
LogType string `yaml:"log_type,omitempty"`
3636
Labels map[string]string `yaml:"labels,omitempty"`
3737
IgnoreParsers bool `yaml:"ignore_parsers,omitempty"` // if we test a scenario, we don't want to assert on Parser
38-
OverrideStatics []parser.ExtraField `yaml:"override_statics,omitempty"` // Allow to override statics. Executed before s00
38+
OverrideStatics []parser.Static `yaml:"override_statics,omitempty"` // Allow to override statics. Executed before s00
3939
OwnDataDir bool `yaml:"own_data_dir,omitempty"` // Don't share dataDir with the other tests
4040
}
4141

@@ -290,26 +290,34 @@ func (*HubTestItem) ImprovedLogDisplay(crowdsecLogFile string) error {
290290
if err != nil {
291291
log.Errorf("unable to read crowdsec log file '%s': %s", crowdsecLogFile, err)
292292
}
293+
293294
success := []string{}
294295
failures := []string{}
295296
general := []string{}
297+
296298
for _, line := range strings.Split(string(crowdsecLog), "\n") {
297299
if strings.Contains(line, `"Evaluating operator: MATCH"`) {
298300
success = append(success, line)
299301
} else if strings.Contains(line, `"Evaluating operator: NO MATCH"`) {
300302
failures = append(failures, line)
301303
}
304+
302305
general = append(general, line)
303306
}
307+
304308
log.Infof("General log -------------\n%s\n", strings.Join(general, "\n"))
309+
305310
if len(success) > 0 {
306311
log.Infof("Success log -------------")
312+
307313
for _, line := range success {
308314
log.Infof("%s - %s", emoji.GreenCircle, line)
309315
}
310316
}
317+
311318
if len(failures) > 0 {
312319
log.Errorf("Failure log -------------")
320+
313321
for _, line := range failures {
314322
log.Infof("%s - %s", emoji.RedCircle, line)
315323
}
@@ -335,7 +343,7 @@ func (t *HubTestItem) RunWithNucleiTemplate(ctx context.Context) error {
335343
output, err := cscliRegisterCmd.CombinedOutput()
336344
if err != nil {
337345
if !strings.Contains(string(output), "unable to create machine: user 'testMachine': user already exist") {
338-
fmt.Println(string(output))
346+
fmt.Fprintln(os.Stdout, string(output))
339347
return fmt.Errorf("fail to run '%s' for test '%s': %w", cscliRegisterCmd.String(), t.Name, err)
340348
}
341349
}

pkg/parser/grok.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package parser
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"time"
7+
8+
"github.com/expr-lang/expr"
9+
"github.com/expr-lang/expr/vm"
10+
11+
"github.com/crowdsecurity/grokky"
12+
log "github.com/sirupsen/logrus"
13+
14+
"github.com/crowdsecurity/crowdsec/pkg/exprhelpers"
15+
"github.com/crowdsecurity/crowdsec/pkg/types"
16+
)
17+
18+
type Static struct {
19+
// if the target is indicated by name Struct.Field etc,
20+
TargetByName string `yaml:"target,omitempty"`
21+
// if the target field is in Event map
22+
Parsed string `yaml:"parsed,omitempty"`
23+
// if the target field is in Meta map
24+
Meta string `yaml:"meta,omitempty"`
25+
// if the target field is in Enriched map
26+
Enriched string `yaml:"enriched,omitempty"`
27+
// the source is a static value
28+
Value string `yaml:"value,omitempty"`
29+
// or the result of an Expression
30+
ExpValue string `yaml:"expression,omitempty"`
31+
// or an enrichment method
32+
Method string `yaml:"method,omitempty"`
33+
}
34+
35+
type RuntimeStatic struct {
36+
Config *Static
37+
RunTimeValue *vm.Program
38+
}
39+
40+
func (s *Static) Validate(ectx EnricherCtx) error {
41+
if s.Method != "" {
42+
if s.Value == "" && s.ExpValue == "" {
43+
return errors.New("when method is set, expression must be present")
44+
}
45+
46+
if _, ok := ectx.Registered[s.Method]; !ok {
47+
log.Warningf("the method %q doesn't exist or the plugin has not been initialized", s.Method)
48+
}
49+
50+
return nil
51+
}
52+
53+
if s.Meta == "" && s.Parsed == "" && s.TargetByName == "" {
54+
return errors.New("at least one of meta/event/target must be set")
55+
}
56+
57+
if s.Value == "" && s.ExpValue == "" {
58+
return errors.New("value or expression must be set")
59+
}
60+
61+
return nil
62+
}
63+
64+
func (s *Static) Compile() (*RuntimeStatic, error) {
65+
cs := &RuntimeStatic{Config: s}
66+
67+
if s.ExpValue != "" {
68+
prog, err := expr.Compile(s.ExpValue,
69+
exprhelpers.GetExprOptions(map[string]any{"evt": &types.Event{}})...)
70+
if err != nil {
71+
return nil, fmt.Errorf("compiling static expression %q: %w", s.ExpValue, err)
72+
}
73+
74+
cs.RunTimeValue = prog
75+
}
76+
77+
return cs, nil
78+
}
79+
80+
type GrokPattern struct {
81+
// the field to which regexp is going to apply
82+
TargetField string `yaml:"apply_on,omitempty"`
83+
// the grok/regexp by name (loaded from patterns/*)
84+
RegexpName string `yaml:"name,omitempty"`
85+
// a proper grok pattern
86+
RegexpValue string `yaml:"pattern,omitempty"`
87+
// the runtime form of regexpname / regexpvalue
88+
RunTimeRegexp grokky.Pattern `yaml:"-"` // the actual regexp
89+
// the output of the expression is going to be the source for regexp
90+
ExpValue string `yaml:"expression,omitempty"`
91+
RunTimeValue *vm.Program `yaml:"-"` // the actual compiled filter
92+
// a grok can contain statics that apply if pattern is successful
93+
Statics []Static `yaml:"statics,omitempty"`
94+
RuntimeStatics []RuntimeStatic `yaml:"-"`
95+
}
96+
97+
type DataCapture struct {
98+
Name string `yaml:"name,omitempty"`
99+
Key string `yaml:"key,omitempty"`
100+
KeyExpression *vm.Program `yaml:"-"`
101+
Value string `yaml:"value,omitempty"`
102+
ValueExpression *vm.Program `yaml:"-"`
103+
TTL string `yaml:"ttl,omitempty"`
104+
TTLVal time.Duration `yaml:"-"`
105+
MaxMapSize int `yaml:"size,omitempty"`
106+
Strategy string `yaml:"strategy,omitempty"`
107+
}

pkg/parser/grok_pattern.go

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)