From c3a4066646dfcde90627b01fca9dff42cd666d76 Mon Sep 17 00:00:00 2001 From: Sebastien Blot Date: Mon, 4 Dec 2023 21:41:51 +0100 Subject: [PATCH] appsec renaming, part 1 --- cmd/crowdsec/metrics.go | 8 +- cmd/crowdsec/parse.go | 2 +- pkg/acquisition/acquisition.go | 4 +- .../modules/{waap => appsec}/README.md | 0 .../{waap/waap.go => appsec/appsec.go} | 145 +++++++++--------- .../appsec_runner.go} | 34 ++-- pkg/acquisition/modules/appsec/metrics.go | 54 +++++++ .../modules/{waap => appsec}/rx_operator.go | 2 +- .../modules/{waap => appsec}/utils.go | 24 +-- pkg/acquisition/modules/waap/metrics.go | 54 ------- pkg/types/{waap_event.go => appsec_event.go} | 4 +- pkg/types/event.go | 4 +- 12 files changed, 167 insertions(+), 168 deletions(-) rename pkg/acquisition/modules/{waap => appsec}/README.md (100%) rename pkg/acquisition/modules/{waap/waap.go => appsec/appsec.go} (61%) rename pkg/acquisition/modules/{waap/waap_runner.go => appsec/appsec_runner.go} (89%) create mode 100644 pkg/acquisition/modules/appsec/metrics.go rename pkg/acquisition/modules/{waap => appsec}/rx_operator.go (98%) rename pkg/acquisition/modules/{waap => appsec}/utils.go (89%) delete mode 100644 pkg/acquisition/modules/waap/metrics.go rename pkg/types/{waap_event.go => appsec_event.go} (98%) diff --git a/cmd/crowdsec/metrics.go b/cmd/crowdsec/metrics.go index 33b36b851..c9d88501a 100644 --- a/cmd/crowdsec/metrics.go +++ b/cmd/crowdsec/metrics.go @@ -12,7 +12,7 @@ import ( "github.com/crowdsecurity/go-cs-lib/trace" "github.com/crowdsecurity/go-cs-lib/version" - waap "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/waap" + appsec "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/appsec" v1 "github.com/crowdsecurity/crowdsec/pkg/apiserver/controllers/v1" "github.com/crowdsecurity/crowdsec/pkg/cache" "github.com/crowdsecurity/crowdsec/pkg/csconfig" @@ -163,8 +163,8 @@ func registerPrometheus(config *csconfig.PrometheusCfg) { v1.LapiRouteHits, leaky.BucketsCurrentCount, cache.CacheMetrics, exprhelpers.RegexpCacheMetrics, - waap.WafGlobalParsingHistogram, waap.WafReqCounter, waap.WafRuleHits, - waap.WafBlockCounter, + appsec.AppsecGlobalParsingHistogram, appsec.AppsecReqCounter, appsec.AppsecRuleHits, + appsec.AppsecBlockCounter, ) } else { log.Infof("Loading prometheus collectors") @@ -175,7 +175,7 @@ func registerPrometheus(config *csconfig.PrometheusCfg) { leaky.BucketsPour, leaky.BucketsUnderflow, leaky.BucketsCanceled, leaky.BucketsInstantiation, leaky.BucketsOverflow, leaky.BucketsCurrentCount, globalActiveDecisions, globalAlerts, cache.CacheMetrics, exprhelpers.RegexpCacheMetrics, - waap.WafGlobalParsingHistogram, waap.WafInbandParsingHistogram, waap.WafOutbandParsingHistogram, waap.WafReqCounter, waap.WafRuleHits, waap.WafBlockCounter, + appsec.AppsecGlobalParsingHistogram, appsec.AppsecInbandParsingHistogram, appsec.AppsecOutbandParsingHistogram, appsec.AppsecReqCounter, appsec.AppsecRuleHits, appsec.AppsecBlockCounter, ) } diff --git a/cmd/crowdsec/parse.go b/cmd/crowdsec/parse.go index 13ae216fc..e1945b027 100644 --- a/cmd/crowdsec/parse.go +++ b/cmd/crowdsec/parse.go @@ -25,7 +25,7 @@ LOOP: /*Waap is going to generate 2 events: - one that is treated as a log and can go to scenarios - another one that will go directly to LAPI*/ - if event.Type == types.WAAP { + if event.Type == types.APPSEC { outputEventChan <- event continue } diff --git a/pkg/acquisition/acquisition.go b/pkg/acquisition/acquisition.go index 0e377a5cc..960de8241 100644 --- a/pkg/acquisition/acquisition.go +++ b/pkg/acquisition/acquisition.go @@ -18,6 +18,7 @@ import ( "github.com/crowdsecurity/go-cs-lib/trace" "github.com/crowdsecurity/crowdsec/pkg/acquisition/configuration" + appsecacquisition "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/appsec" cloudwatchacquisition "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/cloudwatch" dockeracquisition "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/docker" fileacquisition "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/file" @@ -28,7 +29,6 @@ import ( lokiacquisition "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/loki" s3acquisition "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/s3" syslogacquisition "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/syslog" - wafacquisition "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/waap" wineventlogacquisition "github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/wineventlog" "github.com/crowdsecurity/crowdsec/pkg/exprhelpers" @@ -77,7 +77,7 @@ var AcquisitionSources = map[string]func() DataSource{ "k8s-audit": func() DataSource { return &k8sauditacquisition.KubernetesAuditSource{} }, "loki": func() DataSource { return &lokiacquisition.LokiSource{} }, "s3": func() DataSource { return &s3acquisition.S3Source{} }, - "waf": func() DataSource { return &wafacquisition.WaapSource{} }, + "waf": func() DataSource { return &appsecacquisition.AppsecSource{} }, } var transformRuntimes = map[string]*vm.Program{} diff --git a/pkg/acquisition/modules/waap/README.md b/pkg/acquisition/modules/appsec/README.md similarity index 100% rename from pkg/acquisition/modules/waap/README.md rename to pkg/acquisition/modules/appsec/README.md diff --git a/pkg/acquisition/modules/waap/waap.go b/pkg/acquisition/modules/appsec/appsec.go similarity index 61% rename from pkg/acquisition/modules/waap/waap.go rename to pkg/acquisition/modules/appsec/appsec.go index 72e137216..0c147f932 100644 --- a/pkg/acquisition/modules/waap/waap.go +++ b/pkg/acquisition/modules/appsec/appsec.go @@ -1,4 +1,4 @@ -package wafacquisition +package appsecacquisition import ( "context" @@ -32,32 +32,32 @@ var ( ) // configuration structure of the acquis for the Waap -type WaapSourceConfig struct { +type AppsecSourceConfig struct { ListenAddr string `yaml:"listen_addr"` CertFilePath string `yaml:"cert_file"` KeyFilePath string `yaml:"key_file"` Path string `yaml:"path"` Routines int `yaml:"routines"` - WaapConfig string `yaml:"waap_config"` - WaapConfigPath string `yaml:"waap_config_path"` + AppsecConfig string `yaml:"appsec_config"` + AppsecConfigPath string `yaml:"appsec_config_path"` AuthCacheDuration *time.Duration `yaml:"auth_cache_duration"` configuration.DataSourceCommonCfg `yaml:",inline"` } // runtime structure of WaapSourceConfig -type WaapSource struct { - config WaapSourceConfig - logger *log.Entry - mux *http.ServeMux - server *http.Server - addr string - outChan chan types.Event - InChan chan waf.ParsedRequest - WaapRuntime *waf.WaapRuntimeConfig - WaapConfigs map[string]waf.WaapConfig - lapiURL string - AuthCache AuthCache - WaapRunners []WaapRunner //one for each go-routine +type AppsecSource struct { + config AppsecSourceConfig + logger *log.Entry + mux *http.ServeMux + server *http.Server + addr string + outChan chan types.Event + InChan chan waf.ParsedRequest + AppsecRuntime *waf.WaapRuntimeConfig + AppsecConfigs map[string]waf.WaapConfig + lapiURL string + AuthCache AuthCache + AppsecRunners []AppsecRunner //one for each go-routine } // Struct to handle cache of authentication @@ -91,11 +91,11 @@ type BodyResponse struct { Action string `json:"action"` } -func (wc *WaapSource) UnmarshalConfig(yamlConfig []byte) error { +func (wc *AppsecSource) UnmarshalConfig(yamlConfig []byte) error { err := yaml.UnmarshalStrict(yamlConfig, &wc.config) if err != nil { - return errors.Wrap(err, "Cannot parse waf configuration") + return errors.Wrap(err, "Cannot parse appsec configuration") } if wc.config.LogLevel == nil { @@ -124,8 +124,8 @@ func (wc *WaapSource) UnmarshalConfig(yamlConfig []byte) error { wc.config.Routines = 1 } - if wc.config.WaapConfig == "" && wc.config.WaapConfigPath == "" { - return fmt.Errorf("waap_config or waap_config_path must be set") + if wc.config.AppsecConfig == "" && wc.config.AppsecConfigPath == "" { + return fmt.Errorf("appsec_config or appsec_config_path must be set") } if wc.config.Name == "" { @@ -139,15 +139,15 @@ func (wc *WaapSource) UnmarshalConfig(yamlConfig []byte) error { return nil } -func (w *WaapSource) GetMetrics() []prometheus.Collector { +func (w *AppsecSource) GetMetrics() []prometheus.Collector { return nil } -func (w *WaapSource) GetAggregMetrics() []prometheus.Collector { +func (w *AppsecSource) GetAggregMetrics() []prometheus.Collector { return nil } -func (w *WaapSource) Configure(yamlConfig []byte, logger *log.Entry) error { +func (w *AppsecSource) Configure(yamlConfig []byte, logger *log.Entry) error { err := w.UnmarshalConfig(yamlConfig) if err != nil { return errors.Wrap(err, "unable to parse waf configuration") @@ -170,96 +170,95 @@ func (w *WaapSource) Configure(yamlConfig []byte, logger *log.Entry) error { } w.InChan = make(chan waf.ParsedRequest) - waapCfg := waf.WaapConfig{Logger: w.logger.WithField("component", "waap_config")} + appsecCfg := waf.WaapConfig{Logger: w.logger.WithField("component", "appsec_config")} - //let's load the associated waap_config: - if w.config.WaapConfigPath != "" { - err := waapCfg.LoadByPath(w.config.WaapConfigPath) + //let's load the associated appsec_config: + if w.config.AppsecConfigPath != "" { + err := appsecCfg.LoadByPath(w.config.AppsecConfigPath) if err != nil { - return fmt.Errorf("unable to load waap_config : %s", err) + return fmt.Errorf("unable to load appsec_config : %s", err) } - } else if w.config.WaapConfig != "" { - err := waapCfg.Load(w.config.WaapConfig) + } else if w.config.AppsecConfig != "" { + err := appsecCfg.Load(w.config.AppsecConfig) if err != nil { - return fmt.Errorf("unable to load waap_config : %s", err) + return fmt.Errorf("unable to load appsec_config : %s", err) } } else { - return fmt.Errorf("no waap_config provided") + return fmt.Errorf("no appsec_config provided") } - w.WaapRuntime, err = waapCfg.Build() + w.AppsecRuntime, err = appsecCfg.Build() if err != nil { - return fmt.Errorf("unable to build waap_config : %s", err) + return fmt.Errorf("unable to build appsec_config : %s", err) } - err = w.WaapRuntime.ProcessOnLoadRules() + err = w.AppsecRuntime.ProcessOnLoadRules() if err != nil { return fmt.Errorf("unable to process on load rules : %s", err) } - w.WaapRunners = make([]WaapRunner, w.config.Routines) + w.AppsecRunners = make([]AppsecRunner, w.config.Routines) for nbRoutine := 0; nbRoutine < w.config.Routines; nbRoutine++ { - - wafUUID := uuid.New().String() - //we copy WaapRutime for each runner - wrt := *w.WaapRuntime - runner := WaapRunner{ + appsecRunnerUUID := uuid.New().String() + //we copy AppsecRutime for each runner + wrt := *w.AppsecRuntime + runner := AppsecRunner{ inChan: w.InChan, - UUID: wafUUID, + UUID: appsecRunnerUUID, logger: w.logger.WithFields(log.Fields{ - "uuid": wafUUID, + "uuid": appsecRunnerUUID, }), WaapRuntime: &wrt, } - err := runner.Init(waapCfg.GetDataDir()) + err := runner.Init(appsecCfg.GetDataDir()) if err != nil { return fmt.Errorf("unable to initialize runner : %s", err) } - w.WaapRunners[nbRoutine] = runner + w.AppsecRunners[nbRoutine] = runner } - w.logger.Infof("Created %d waf runners", len(w.WaapRunners)) + w.logger.Infof("Created %d appsec runners", len(w.AppsecRunners)) //We donĀ“t use the wrapper provided by coraza because we want to fully control what happens when a rule match to send the information in crowdsec - w.mux.HandleFunc(w.config.Path, w.waapHandler) + w.mux.HandleFunc(w.config.Path, w.appsecHandler) return nil } -func (w *WaapSource) ConfigureByDSN(dsn string, labels map[string]string, logger *log.Entry, uuid string) error { - return fmt.Errorf("WAF datasource does not support command line acquisition") +func (w *AppsecSource) ConfigureByDSN(dsn string, labels map[string]string, logger *log.Entry, uuid string) error { + return fmt.Errorf("AppSec datasource does not support command line acquisition") } -func (w *WaapSource) GetMode() string { +func (w *AppsecSource) GetMode() string { return w.config.Mode } -func (w *WaapSource) GetName() string { - return "waf" +func (w *AppsecSource) GetName() string { + return "appsec" } -func (w *WaapSource) OneShotAcquisition(out chan types.Event, t *tomb.Tomb) error { - return fmt.Errorf("WAF datasource does not support command line acquisition") +func (w *AppsecSource) OneShotAcquisition(out chan types.Event, t *tomb.Tomb) error { + return fmt.Errorf("AppSec datasource does not support command line acquisition") } -func (w *WaapSource) StreamingAcquisition(out chan types.Event, t *tomb.Tomb) error { +func (w *AppsecSource) StreamingAcquisition(out chan types.Event, t *tomb.Tomb) error { w.outChan = out t.Go(func() error { - defer trace.CatchPanic("crowdsec/acquis/waf/live") + defer trace.CatchPanic("crowdsec/acquis/appsec/live") - w.logger.Infof("%d waf runner to start", len(w.WaapRunners)) - for _, runner := range w.WaapRunners { + w.logger.Infof("%d appsec runner to start", len(w.AppsecRunners)) + for _, runner := range w.AppsecRunners { runner := runner runner.outChan = out t.Go(func() error { - defer trace.CatchPanic("crowdsec/acquis/waf/live/runner") + defer trace.CatchPanic("crowdsec/acquis/appsec/live/runner") return runner.Run(t) }) } - w.logger.Infof("Starting WAF server on %s%s", w.config.ListenAddr, w.config.Path) + w.logger.Infof("Starting Appsec server on %s%s", w.config.ListenAddr, w.config.Path) t.Go(func() error { var err error if w.config.CertFilePath != "" && w.config.KeyFilePath != "" { @@ -269,31 +268,31 @@ func (w *WaapSource) StreamingAcquisition(out chan types.Event, t *tomb.Tomb) er } if err != nil && err != http.ErrServerClosed { - return errors.Wrap(err, "WAF server failed") + return errors.Wrap(err, "Appsec server failed") } return nil }) <-t.Dying() - w.logger.Infof("Stopping WAF server on %s%s", w.config.ListenAddr, w.config.Path) + w.logger.Infof("Stopping Appsec server on %s%s", w.config.ListenAddr, w.config.Path) w.server.Shutdown(context.TODO()) return nil }) return nil } -func (w *WaapSource) CanRun() error { +func (w *AppsecSource) CanRun() error { return nil } -func (w *WaapSource) GetUuid() string { +func (w *AppsecSource) GetUuid() string { return w.config.UniqueId } -func (w *WaapSource) Dump() interface{} { +func (w *AppsecSource) Dump() interface{} { return w } -func (w *WaapSource) IsAuth(apiKey string) bool { +func (w *AppsecSource) IsAuth(apiKey string) bool { client := &http.Client{ Timeout: 200 * time.Millisecond, } @@ -317,7 +316,7 @@ func (w *WaapSource) IsAuth(apiKey string) bool { } // should this be in the runner ? -func (w *WaapSource) waapHandler(rw http.ResponseWriter, r *http.Request) { +func (w *AppsecSource) appsecHandler(rw http.ResponseWriter, r *http.Request) { apiKey := r.Header.Get(waf.APIKeyHeaderName) clientIP := r.Header.Get(waf.IPHeaderName) remoteIP := r.RemoteAddr @@ -348,19 +347,19 @@ func (w *WaapSource) waapHandler(rw http.ResponseWriter, r *http.Request) { } parsedRequest.WaapEngine = w.config.Name - WafReqCounter.With(prometheus.Labels{"source": parsedRequest.RemoteAddrNormalized, "waap_engine": parsedRequest.WaapEngine}).Inc() + AppsecReqCounter.With(prometheus.Labels{"source": parsedRequest.RemoteAddrNormalized, "appsec_engine": parsedRequest.WaapEngine}).Inc() w.InChan <- parsedRequest response := <-parsedRequest.ResponseChannel if response.InBandInterrupt { - WafBlockCounter.With(prometheus.Labels{"source": parsedRequest.RemoteAddrNormalized, "waap_engine": parsedRequest.WaapEngine}).Inc() + AppsecBlockCounter.With(prometheus.Labels{"source": parsedRequest.RemoteAddrNormalized, "appsec_engine": parsedRequest.WaapEngine}).Inc() } - waapResponse := w.WaapRuntime.GenerateResponse(response) + appsecResponse := w.AppsecRuntime.GenerateResponse(response) - rw.WriteHeader(waapResponse.HTTPStatus) - body, err := json.Marshal(BodyResponse{Action: waapResponse.Action}) + rw.WriteHeader(appsecResponse.HTTPStatus) + body, err := json.Marshal(BodyResponse{Action: appsecResponse.Action}) if err != nil { log.Errorf("unable to marshal response: %s", err) rw.WriteHeader(http.StatusInternalServerError) diff --git a/pkg/acquisition/modules/waap/waap_runner.go b/pkg/acquisition/modules/appsec/appsec_runner.go similarity index 89% rename from pkg/acquisition/modules/waap/waap_runner.go rename to pkg/acquisition/modules/appsec/appsec_runner.go index 5375a4d2c..206e7523a 100644 --- a/pkg/acquisition/modules/waap/waap_runner.go +++ b/pkg/acquisition/modules/appsec/appsec_runner.go @@ -1,4 +1,4 @@ -package wafacquisition +package appsecacquisition import ( "fmt" @@ -16,7 +16,7 @@ import ( ) // that's the runtime structure of the WAAP as seen from the acquis -type WaapRunner struct { +type AppsecRunner struct { outChan chan types.Event inChan chan waf.ParsedRequest UUID string @@ -26,7 +26,7 @@ type WaapRunner struct { logger *log.Entry } -func (r *WaapRunner) Init(datadir string) error { +func (r *AppsecRunner) Init(datadir string) error { var err error fs := os.DirFS(datadir) @@ -101,7 +101,7 @@ func (r *WaapRunner) Init(datadir string) error { return nil } -func (r *WaapRunner) processRequest(tx waf.ExtendedTransaction, request *waf.ParsedRequest) error { +func (r *AppsecRunner) processRequest(tx waf.ExtendedTransaction, request *waf.ParsedRequest) error { var in *corazatypes.Interruption var err error request.Tx = tx @@ -185,21 +185,21 @@ func (r *WaapRunner) processRequest(tx waf.ExtendedTransaction, request *waf.Par return nil } -func (r *WaapRunner) ProcessInBandRules(request *waf.ParsedRequest) error { +func (r *AppsecRunner) ProcessInBandRules(request *waf.ParsedRequest) error { tx := waf.NewExtendedTransaction(r.WaapInbandEngine, request.UUID) r.WaapRuntime.InBandTx = tx err := r.processRequest(tx, request) return err } -func (r *WaapRunner) ProcessOutOfBandRules(request *waf.ParsedRequest) error { +func (r *AppsecRunner) ProcessOutOfBandRules(request *waf.ParsedRequest) error { tx := waf.NewExtendedTransaction(r.WaapOutbandEngine, request.UUID) r.WaapRuntime.OutOfBandTx = tx err := r.processRequest(tx, request) return err } -func (r *WaapRunner) handleInBandInterrupt(request *waf.ParsedRequest) { +func (r *AppsecRunner) handleInBandInterrupt(request *waf.ParsedRequest) { //create the associated event for crowdsec itself evt, err := EventFromRequest(request) if err != nil { @@ -238,17 +238,17 @@ func (r *WaapRunner) handleInBandInterrupt(request *waf.ParsedRequest) { // Should the in band match trigger an overflow ? if r.WaapRuntime.Response.SendAlert { - waapOvlfw, err := WaapEventGeneration(evt) + appsecOvlfw, err := AppsecEventGeneration(evt) if err != nil { - r.logger.Errorf("unable to generate waap event : %s", err) + r.logger.Errorf("unable to generate appsec event : %s", err) return } - r.outChan <- *waapOvlfw + r.outChan <- *appsecOvlfw } } } -func (r *WaapRunner) handleOutBandInterrupt(request *waf.ParsedRequest) { +func (r *AppsecRunner) handleOutBandInterrupt(request *waf.ParsedRequest) { evt, err := EventFromRequest(request) if err != nil { //let's not interrupt the pipeline for this @@ -274,24 +274,24 @@ func (r *WaapRunner) handleOutBandInterrupt(request *waf.ParsedRequest) { // Should the match trigger an overflow ? if r.WaapRuntime.Response.SendAlert { - waapOvlfw, err := WaapEventGeneration(evt) + appsecOvlfw, err := AppsecEventGeneration(evt) if err != nil { r.logger.Errorf("unable to generate waap event : %s", err) return } - r.outChan <- *waapOvlfw + r.outChan <- *appsecOvlfw } } } -func (r *WaapRunner) handleRequest(request *waf.ParsedRequest) { +func (r *AppsecRunner) handleRequest(request *waf.ParsedRequest) { r.logger.Debugf("Requests handled by runner %s", request.UUID) r.WaapRuntime.ClearResponse() request.IsInBand = true request.IsOutBand = false - //to measure the time spent in the WAF + //to measure the time spent in the Application Security Engine startParsing := time.Now() //inband WAAP rules @@ -306,7 +306,7 @@ func (r *WaapRunner) handleRequest(request *waf.ParsedRequest) { } elapsed := time.Since(startParsing) - WafInbandParsingHistogram.With(prometheus.Labels{"source": request.RemoteAddr}).Observe(elapsed.Seconds()) + AppsecInbandParsingHistogram.With(prometheus.Labels{"source": request.RemoteAddr}).Observe(elapsed.Seconds()) // send back the result to the HTTP handler for the InBand part request.ResponseChannel <- r.WaapRuntime.Response @@ -329,7 +329,7 @@ func (r *WaapRunner) handleRequest(request *waf.ParsedRequest) { } } -func (r *WaapRunner) Run(t *tomb.Tomb) error { +func (r *AppsecRunner) Run(t *tomb.Tomb) error { r.logger.Infof("Waap Runner ready to process event") for { select { diff --git a/pkg/acquisition/modules/appsec/metrics.go b/pkg/acquisition/modules/appsec/metrics.go new file mode 100644 index 000000000..9aa3c8bde --- /dev/null +++ b/pkg/acquisition/modules/appsec/metrics.go @@ -0,0 +1,54 @@ +package appsecacquisition + +import "github.com/prometheus/client_golang/prometheus" + +var AppsecGlobalParsingHistogram = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Help: "Time spent processing a request by the Application Security Engine.", + Name: "cs_appsec_parsing_time_seconds", + Buckets: []float64{0.0005, 0.001, 0.0015, 0.002, 0.0025, 0.003, 0.004, 0.005, 0.0075, 0.01}, + }, + []string{"source"}, +) + +var AppsecInbandParsingHistogram = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Help: "Time spent processing a request by the inband Application Security Engine.", + Name: "cs_appsec_inband_parsing_time_seconds", + Buckets: []float64{0.0005, 0.001, 0.0015, 0.002, 0.0025, 0.003, 0.004, 0.005, 0.0075, 0.01}, + }, + []string{"source"}, +) + +var AppsecOutbandParsingHistogram = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Help: "Time spent processing a request by the Application Security Engine.", + Name: "cs_appsec_outband_parsing_time_seconds", + Buckets: []float64{0.0005, 0.001, 0.0015, 0.002, 0.0025, 0.003, 0.004, 0.005, 0.0075, 0.01}, + }, + []string{"source"}, +) + +var AppsecReqCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "cs_appsec_reqs_total", + Help: "Total events processed by the Application Security Engine.", + }, + []string{"source", "appsec_engine"}, +) + +var AppsecBlockCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "cs_appsec_block_total", + Help: "Total events blocked by the Application Security Engine.", + }, + []string{"source", "appsec_engine"}, +) + +var AppsecRuleHits = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "cs_appsec_rule_hits", + Help: "Count of triggered rule, by rule_name, type (inband/outofband), appsec_engine and source", + }, + []string{"rule_name", "type", "appsec_engine", "source"}, +) diff --git a/pkg/acquisition/modules/waap/rx_operator.go b/pkg/acquisition/modules/appsec/rx_operator.go similarity index 98% rename from pkg/acquisition/modules/waap/rx_operator.go rename to pkg/acquisition/modules/appsec/rx_operator.go index f1335c7e3..43aaf9e94 100644 --- a/pkg/acquisition/modules/waap/rx_operator.go +++ b/pkg/acquisition/modules/appsec/rx_operator.go @@ -1,4 +1,4 @@ -package wafacquisition +package appsecacquisition import ( "fmt" diff --git a/pkg/acquisition/modules/waap/utils.go b/pkg/acquisition/modules/appsec/utils.go similarity index 89% rename from pkg/acquisition/modules/waap/utils.go rename to pkg/acquisition/modules/appsec/utils.go index cf02abae7..ebec71ef4 100644 --- a/pkg/acquisition/modules/waap/utils.go +++ b/pkg/acquisition/modules/appsec/utils.go @@ -1,4 +1,4 @@ -package wafacquisition +package appsecacquisition import ( "encoding/json" @@ -15,13 +15,13 @@ import ( log "github.com/sirupsen/logrus" ) -func WaapEventGeneration(inEvt types.Event) (*types.Event, error) { +func AppsecEventGeneration(inEvt types.Event) (*types.Event, error) { //if the request didnd't trigger inband rules, we don't want to generate an event to LAPI/CAPI if !inEvt.Waap.HasInBandMatches { return nil, nil } evt := types.Event{} - evt.Type = types.WAAP + evt.Type = types.APPSEC evt.Process = true source := models.Source{ Value: ptr.Of(inEvt.Parsed["source_ip"]), @@ -53,7 +53,7 @@ func WaapEventGeneration(inEvt types.Event) (*types.Event, error) { alert.EventsCount = ptr.Of(int32(1)) alert.Labels = []string{"waf"} //don't know what to do about this alert.Leakspeed = ptr.Of("") - msg := fmt.Sprintf("WAF alert: %s", inEvt.Waap.MatchedRules.GetName()) + msg := fmt.Sprintf("Application Security Engine alert: %s", inEvt.Waap.MatchedRules.GetName()) alert.Message = &msg alert.Scenario = ptr.Of(inEvt.Waap.MatchedRules.GetName()) // @sbl : should we be able to do inEvt.Waap.MatchedRules.GetHash() alert.ScenarioHash = ptr.Of(inEvt.Waap.MatchedRules.GetHash()) // @sbl : should we be able to do inEvt.Waap.MatchedRules.GetHash() @@ -91,18 +91,18 @@ func EventFromRequest(r *waf.ParsedRequest) (types.Event, error) { evt.Line = types.Line{ Time: time.Now(), //should we add some info like listen addr/port/path ? - Labels: map[string]string{"type": "crowdsec-waap"}, + Labels: map[string]string{"type": "crowdsec-waap"}, //FIXME: use the labels from the acquis Process: true, - Module: "waap", - Src: "waap", + Module: "appsec", + Src: "appsec", Raw: "dummy-waap-data", //we discard empty Line.Raw items :) } - evt.Waap = types.WaapEvent{} + evt.Waap = types.AppsecEvent{} return evt, nil } -func LogWaapEvent(evt *types.Event, logger *log.Entry) { +func LogAppsecEvent(evt *types.Event, logger *log.Entry) { req := evt.Parsed["target_uri"] if len(req) > 12 { req = req[:10] + ".." @@ -125,12 +125,12 @@ func LogWaapEvent(evt *types.Event, logger *log.Entry) { "module": "waf", "source": evt.Parsed["source_ip"], "target_uri": req, - }).Debugf("%s triggerd non-blocking rules on %s (%d rules) [%v]", evt.Parsed["source_ip"], req, len(evt.Waap.MatchedRules), evt.Waap.GetRuleIDs()) + }).Debugf("%s triggered non-blocking rules on %s (%d rules) [%v]", evt.Parsed["source_ip"], req, len(evt.Waap.MatchedRules), evt.Waap.GetRuleIDs()) } } -func (r *WaapRunner) AccumulateTxToEvent(evt *types.Event, req *waf.ParsedRequest) error { +func (r *AppsecRunner) AccumulateTxToEvent(evt *types.Event, req *waf.ParsedRequest) error { if evt == nil { //an error was already emitted, let's not spam the logs @@ -215,7 +215,7 @@ func (r *WaapRunner) AccumulateTxToEvent(evt *types.Event, req *waf.ParsedReques r.logger.Debugf("custom rule for event, setting name: %s, version: %s, hash: %s", name, version, hash) } - WafRuleHits.With(prometheus.Labels{"rule_name": ruleNameProm, "type": kind, "source": req.RemoteAddrNormalized, "waap_engine": req.WaapEngine}).Inc() + AppsecRuleHits.With(prometheus.Labels{"rule_name": ruleNameProm, "type": kind, "source": req.RemoteAddrNormalized, "appsec_engine": req.WaapEngine}).Inc() corazaRule := map[string]interface{}{ "id": rule.Rule().ID(), diff --git a/pkg/acquisition/modules/waap/metrics.go b/pkg/acquisition/modules/waap/metrics.go deleted file mode 100644 index fd917a8b2..000000000 --- a/pkg/acquisition/modules/waap/metrics.go +++ /dev/null @@ -1,54 +0,0 @@ -package wafacquisition - -import "github.com/prometheus/client_golang/prometheus" - -var WafGlobalParsingHistogram = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Help: "Time spent processing a request by the WAF.", - Name: "cs_waf_parsing_time_seconds", - Buckets: []float64{0.0005, 0.001, 0.0015, 0.002, 0.0025, 0.003, 0.004, 0.005, 0.0075, 0.01}, - }, - []string{"source"}, -) - -var WafInbandParsingHistogram = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Help: "Time spent processing a request by the inband WAF.", - Name: "cs_waf_inband_parsing_time_seconds", - Buckets: []float64{0.0005, 0.001, 0.0015, 0.002, 0.0025, 0.003, 0.004, 0.005, 0.0075, 0.01}, - }, - []string{"source"}, -) - -var WafOutbandParsingHistogram = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Help: "Time spent processing a request by the WAF.", - Name: "cs_waf_outband_parsing_time_seconds", - Buckets: []float64{0.0005, 0.001, 0.0015, 0.002, 0.0025, 0.003, 0.004, 0.005, 0.0075, 0.01}, - }, - []string{"source"}, -) - -var WafReqCounter = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "cs_waf_reqs_total", - Help: "Total events processed by the WAF.", - }, - []string{"source", "waap_engine"}, -) - -var WafBlockCounter = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "cs_waf_block_total", - Help: "Total events blocked by the WAF.", - }, - []string{"source", "waap_engine"}, -) - -var WafRuleHits = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "cs_waf_rule_hits", - Help: "Count of triggered rule, by rule_name, type (inband/outofband), waap_engine and source", - }, - []string{"rule_name", "type", "waap_engine", "source"}, -) diff --git a/pkg/types/waap_event.go b/pkg/types/appsec_event.go similarity index 98% rename from pkg/types/waap_event.go rename to pkg/types/appsec_event.go index 9b64d8d7a..83ee06fd7 100644 --- a/pkg/types/waap_event.go +++ b/pkg/types/appsec_event.go @@ -19,7 +19,7 @@ len(evt.Waf.ByTagRx("*CVE*").ByConfidence("high").ByAction("block")) > 1 type MatchedRules []map[string]interface{} -type WaapEvent struct { +type AppsecEvent struct { HasInBandMatches, HasOutBandMatches bool MatchedRules Vars map[string]string @@ -44,7 +44,7 @@ const ( Kind Field = "kind" ) -func (w WaapEvent) GetVar(varName string) string { +func (w AppsecEvent) GetVar(varName string) string { if w.Vars == nil { return "" } diff --git a/pkg/types/event.go b/pkg/types/event.go index 0e8de7f8e..2456df867 100644 --- a/pkg/types/event.go +++ b/pkg/types/event.go @@ -13,7 +13,7 @@ import ( const ( LOG = iota OVFLW - WAAP + APPSEC ) // Event is the structure representing a runtime event (log or overflow) @@ -41,7 +41,7 @@ type Event struct { StrTimeFormat string `yaml:"StrTimeFormat,omitempty" json:"StrTimeFormat,omitempty"` MarshaledTime string `yaml:"MarshaledTime,omitempty" json:"MarshaledTime,omitempty"` Process bool `yaml:"Process,omitempty" json:"Process,omitempty"` //can be set to false to avoid processing line - Waap WaapEvent `yaml:"Waap,omitempty" json:"Waap,omitempty"` + Waap AppsecEvent `yaml:"Waap,omitempty" json:"Waap,omitempty"` /* Meta is the only part that will make it to the API - it should be normalized */ Meta map[string]string `yaml:"Meta,omitempty" json:"Meta,omitempty"` }