diff --git a/.github/workflows/go-tests-windows.yml b/.github/workflows/go-tests-windows.yml index 4407a3bcc..f327e7bbc 100644 --- a/.github/workflows/go-tests-windows.yml +++ b/.github/workflows/go-tests-windows.yml @@ -58,6 +58,6 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 with: - version: v2.2 + version: v2.3 args: --issues-exit-code=1 --timeout 10m only-new-issues: false diff --git a/.github/workflows/go-tests.yml b/.github/workflows/go-tests.yml index 9d58601ac..e737adcf1 100644 --- a/.github/workflows/go-tests.yml +++ b/.github/workflows/go-tests.yml @@ -209,6 +209,6 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 with: - version: v2.2 + version: v2.3 args: --issues-exit-code=1 --timeout 10m only-new-issues: false diff --git a/.golangci.yml b/.golangci.yml index cd6166f3b..2ebdc20cd 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -22,13 +22,19 @@ linters: - intrange # intrange is a linter to find places where for loops could make use of an integer range. - funcorder + # we allow named returns (to improve readability, in the function signatures) + # but disallow implicit (or "naked") returns, to improve readability in the actual code. + # + # Implicit returns are still useful with deferred functions, in which case they can be //nolinted. + # https://go.dev/wiki/CodeReviewComments#named-result-parameters + - nonamedreturns + # # Recommended? (easy) # - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and reports occasions, where the check for the returned error can be omitted. - - exhaustive # check exhaustiveness of enum switch statements - godot # Check if comments end in a period - gosec # (gas): Inspects source code for security problems - musttag # enforce field tags in (un)marshaled structs @@ -227,6 +233,8 @@ linters: disabled: true - name: empty-lines disabled: true + - name: enforce-switch-style + disabled: true - name: error-naming disabled: true - name: flag-parameter @@ -341,12 +349,6 @@ linters: - bodyclose text: response body must be closed - # named/naked returns are evil, with a single exception - # https://go.dev/wiki/CodeReviewComments#named-result-parameters - - linters: - - nonamedreturns - text: named return .* with type .* found - - linters: - revive path: pkg/leakybucket/manager_load.go @@ -472,6 +474,28 @@ linters: - containedctx path: cmd/notification-file/main.go text: found a struct that contains a context.Context field + + # migrate over time + + - linters: + - noctx + text: "net.Listen must not be called" + + - linters: + - noctx + text: "exec.Command must not be called" + + - linters: + - noctx + text: "net.LookupAddr must not be called" + + - linters: + - noctx + text: "net.Dial must not be called" + + - linters: + - noctx + text: "net.LookupHost must not be called" paths: - pkg/yamlpatch/merge.go - pkg/yamlpatch/merge_test.go diff --git a/cmd/crowdsec/win_service.go b/cmd/crowdsec/win_service.go index ae48e7744..6df61d6c6 100644 --- a/cmd/crowdsec/win_service.go +++ b/cmd/crowdsec/win_service.go @@ -36,7 +36,7 @@ func (m *crowdsec_winservice) Execute(args []string, r <-chan svc.ChangeRequest, case <-tick: case c := <-r: - switch c.Cmd { + switch c.Cmd { //nolint:exhaustive case svc.Interrogate: changes <- c.CurrentStatus case svc.Stop, svc.Shutdown: diff --git a/pkg/acquisition/modules/docker/docker.go b/pkg/acquisition/modules/docker/docker.go index 6e2485aa4..e6c187b0b 100644 --- a/pkg/acquisition/modules/docker/docker.go +++ b/pkg/acquisition/modules/docker/docker.go @@ -7,6 +7,7 @@ import ( "fmt" "net/url" "regexp" + "slices" "strconv" "strings" "time" @@ -25,7 +26,6 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/acquisition/configuration" "github.com/crowdsecurity/crowdsec/pkg/types" - "slices" ) var linesRead = prometheus.NewCounterVec( @@ -36,18 +36,19 @@ var linesRead = prometheus.NewCounterVec( []string{"source"}) type DockerConfiguration struct { - CheckInterval string `yaml:"check_interval"` - FollowStdout bool `yaml:"follow_stdout"` - FollowStdErr bool `yaml:"follow_stderr"` - Until string `yaml:"until"` - Since string `yaml:"since"` - DockerHost string `yaml:"docker_host"` - ContainerName []string `yaml:"container_name"` - ContainerID []string `yaml:"container_id"` - ContainerNameRegexp []string `yaml:"container_name_regexp"` - ContainerIDRegexp []string `yaml:"container_id_regexp"` - UseContainerLabels bool `yaml:"use_container_labels"` configuration.DataSourceCommonCfg `yaml:",inline"` + + CheckInterval string `yaml:"check_interval"` + FollowStdout bool `yaml:"follow_stdout"` + FollowStdErr bool `yaml:"follow_stderr"` + Until string `yaml:"until"` + Since string `yaml:"since"` + DockerHost string `yaml:"docker_host"` + ContainerName []string `yaml:"container_name"` + ContainerID []string `yaml:"container_id"` + ContainerNameRegexp []string `yaml:"container_name_regexp"` + ContainerIDRegexp []string `yaml:"container_id_regexp"` + UseContainerLabels bool `yaml:"use_container_labels"` } type DockerSource struct { @@ -350,7 +351,9 @@ func (d *DockerSource) OneShotAcquisition(ctx context.Context, out chan types.Ev evt.Line = l evt.Process = true evt.Type = types.LOG + out <- evt + d.logger.Debugf("Sent line to parsing: %+v", evt.Line.Raw) } } @@ -389,8 +392,8 @@ func (d *DockerSource) CanRun() error { return nil } -func (d *DockerSource) getContainerTTY(ctx context.Context, containerId string) bool { - containerDetails, err := d.Client.ContainerInspect(ctx, containerId) +func (d *DockerSource) getContainerTTY(ctx context.Context, containerID string) bool { + containerDetails, err := d.Client.ContainerInspect(ctx, containerID) if err != nil { return false } @@ -398,10 +401,10 @@ func (d *DockerSource) getContainerTTY(ctx context.Context, containerId string) return containerDetails.Config.Tty } -func (d *DockerSource) getContainerLabels(ctx context.Context, containerId string) map[string]interface{} { - containerDetails, err := d.Client.ContainerInspect(ctx, containerId) +func (d *DockerSource) getContainerLabels(ctx context.Context, containerID string) map[string]any { + containerDetails, err := d.Client.ContainerInspect(ctx, containerID) if err != nil { - return map[string]interface{}{} + return map[string]any{} } return parseLabels(containerDetails.Config.Labels) @@ -466,7 +469,7 @@ func (d *DockerSource) EvalContainer(ctx context.Context, container dockerTypes. return nil } - labelsTypeCast, ok := parsedLabels["labels"].(map[string]interface{}) + labelsTypeCast, ok := parsedLabels["labels"].(map[string]any) if !ok { d.logger.Error("container has 'crowdsec.enable' label set to true but 'labels' is not a map") return nil @@ -539,6 +542,7 @@ func (d *DockerSource) checkContainers(ctx context.Context, monitChan chan *Cont } d.logger.Tracef("Reading logs from %d containers", len(d.runningContainerState)) + return nil } @@ -669,7 +673,7 @@ func (d *DockerSource) StreamingAcquisition(ctx context.Context, out chan types. return d.WatchContainer(ctx, monitChan, deleteChan) } -func (d *DockerSource) Dump() interface{} { +func (d *DockerSource) Dump() any { return d } @@ -677,6 +681,7 @@ func ReadTailScanner(scanner *bufio.Scanner, out chan string, t *tomb.Tomb) erro for scanner.Scan() { out <- scanner.Text() } + return scanner.Err() } @@ -714,6 +719,7 @@ func (d *DockerSource) TailDocker(ctx context.Context, container *ContainerConfi if line == "" { continue } + l := types.Line{} l.Raw = line l.Labels = container.Labels diff --git a/pkg/csplugin/hclog_adapter.go b/pkg/csplugin/hclog_adapter.go index 44a224637..377e0da3f 100644 --- a/pkg/csplugin/hclog_adapter.go +++ b/pkg/csplugin/hclog_adapter.go @@ -42,7 +42,7 @@ type HCLogAdapter struct { } func (h HCLogAdapter) Log(level hclog.Level, msg string, args ...interface{}) { - switch level { + switch level { //nolint:exhaustive case hclog.NoLevel: return case hclog.Trace: @@ -140,7 +140,7 @@ func (h HCLogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Write // level2logrus maps hclog levels to Logrus levels. func level2logrus(level hclog.Level) logrus.Level { - switch level { + switch level { //nolint:exhaustive case hclog.NoLevel: // Logrus does not have NoLevel, so use Info instead. return logrus.InfoLevel @@ -160,7 +160,7 @@ func level2logrus(level hclog.Level) logrus.Level { } func level2hclog(level logrus.Level) hclog.Level { - switch level { + switch level { //nolint:exhaustive case logrus.TraceLevel: return hclog.Trace case logrus.DebugLevel: diff --git a/pkg/parser/runtime.go b/pkg/parser/runtime.go index cd0b32d75..07e7a4a98 100644 --- a/pkg/parser/runtime.go +++ b/pkg/parser/runtime.go @@ -51,7 +51,7 @@ func SetTargetByName(target string, value string, evt *types.Event) bool { /* ** According to current Event layout we only have to handle struct and map */ - switch iter.Kind() { + switch iter.Kind() { //nolint:exhaustive case reflect.Map: tmp := iter.MapIndex(reflect.ValueOf(f)) /*if we're in a map and the field doesn't exist, the user wants to add it :) */ @@ -82,7 +82,8 @@ func SetTargetByName(target string, value string, evt *types.Event) bool { return false } } - //now we should have the final member :) + + // now we should have the final member :) if !iter.CanSet() { log.Errorf("'%s' can't be set", target) return false @@ -119,6 +120,7 @@ func (n *Node) ProcessStatics(statics []ExtraField, event *types.Event) error { //we have a few cases : //(meta||key) + (static||reference||expr) var value string + clog := n.Logger for _, static := range statics { @@ -131,6 +133,7 @@ func (n *Node) ProcessStatics(statics []ExtraField, event *types.Event) error { clog.Warningf("failed to run RunTimeValue : %v", err) continue } + switch out := output.(type) { case string: value = out @@ -151,7 +154,7 @@ func (n *Node) ProcessStatics(statics []ExtraField, event *types.Event) error { } if value == "" { - //allow ParseDate to have empty input + // allow ParseDate to have empty input if static.Method != "ParseDate" { clog.Debugf("Empty value for %s, skip.", printStaticTarget(static)) continue @@ -180,6 +183,7 @@ func (n *Node) ProcessStatics(statics []ExtraField, event *types.Event) error { } else { clog.Debugf("method '%s' doesn't exist or plugin not initialized", static.Method) } + if !processed { clog.Debugf("method '%s' doesn't exist", static.Method) } @@ -202,6 +206,7 @@ func (n *Node) ProcessStatics(statics []ExtraField, event *types.Event) error { clog.Fatal("unable to process static : unknown target") } } + return nil } @@ -253,6 +258,7 @@ func stageidx(stage string, stages []string) int { return i } } + return -1 }