Sebastien Blot 1 年間 前
コミット
5f254769ae

+ 4 - 4
pkg/acquisition/modules/waap/utils.go

@@ -68,7 +68,7 @@ func WaapEventGeneration(inEvt types.Event) (*types.Event, error) {
 	return &evt, nil
 }
 
-func EventFromRequest(r waf.ParsedRequest) (types.Event, error) {
+func EventFromRequest(r *waf.ParsedRequest) (types.Event, error) {
 	evt := types.Event{}
 	//we might want to change this based on in-band vs out-of-band ?
 	evt.Type = types.LOG
@@ -81,7 +81,7 @@ func EventFromRequest(r waf.ParsedRequest) (types.Event, error) {
 		"target_uri":  r.URI,
 		"method":      r.Method,
 		"req_uuid":    r.Tx.ID(),
-		"source":      "coraza",
+		"source":      "crowdsec-waap",
 
 		//TBD:
 		//http_status
@@ -91,7 +91,7 @@ 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": "coraza-waap"},
+		Labels:  map[string]string{"type": "crowdsec-waap"},
 		Process: true,
 		Module:  "waap",
 		Src:     "waap",
@@ -130,7 +130,7 @@ func LogWaapEvent(evt *types.Event, logger *log.Entry) {
 
 }
 
-func (r *WaapRunner) AccumulateTxToEvent(evt *types.Event, req waf.ParsedRequest) error {
+func (r *WaapRunner) AccumulateTxToEvent(evt *types.Event, req *waf.ParsedRequest) error {
 
 	if evt == nil {
 		//an error was already emitted, let's not spam the logs

+ 112 - 76
pkg/acquisition/modules/waap/waap_runner.go

@@ -170,97 +170,133 @@ func (r *WaapRunner) ProcessOutOfBandRules(request *waf.ParsedRequest) error {
 	return err
 }
 
-func (r *WaapRunner) Run(t *tomb.Tomb) error {
-	r.logger.Infof("Waap Runner ready to process event")
-	for {
-		select {
-		case <-t.Dying():
-			r.logger.Infof("Waf Runner is dying")
-			return nil
-		case request := <-r.inChan:
-			r.logger.Debugf("Requests handled by runner %s", request.UUID)
-			r.WaapRuntime.ClearResponse()
-
-			request.IsInBand = true
-			request.IsOutBand = false
+func (r *WaapRunner) handleInBandInterrupt(request *waf.ParsedRequest) {
+	//create the associated event for crowdsec itself
+	evt, err := EventFromRequest(request)
+	if err != nil {
+		//let's not interrupt the pipeline for this
+		r.logger.Errorf("unable to create event from request : %s", err)
+	}
+	err = r.AccumulateTxToEvent(&evt, request)
+	if err != nil {
+		r.logger.Errorf("unable to accumulate tx to event : %s", err)
+	}
+	if in := request.Tx.Interruption(); in != nil {
+		r.logger.Debugf("inband rules matched : %d", in.RuleID)
+		r.WaapRuntime.Response.InBandInterrupt = true
 
-			//to measure the time spent in the WAF
-			startParsing := time.Now()
+		err = r.WaapRuntime.ProcessOnMatchRules(request)
+		if err != nil {
+			r.logger.Errorf("unable to process OnMatch rules: %s", err)
+			return
+		}
+		// Should the in band match trigger an event ?
+		if r.WaapRuntime.Response.SendEvent {
+			r.outChan <- evt
+		}
 
-			//inband WAAP rules
-			err := r.ProcessInBandRules(&request)
-			if err != nil {
-				r.logger.Errorf("unable to process InBand rules: %s", err)
-				continue
-			}
-			//create the associated event for crowdsec itself
-			evt, err := EventFromRequest(request)
+		// Should the in band match trigger an overflow ?
+		if r.WaapRuntime.Response.SendAlert {
+			waapOvlfw, err := WaapEventGeneration(evt)
 			if err != nil {
-				//let's not interrupt the pipeline for this
-				r.logger.Errorf("unable to create event from request : %s", err)
+				r.logger.Errorf("unable to generate waap event : %s", err)
+				return
 			}
-			err = r.AccumulateTxToEvent(&evt, request)
+			r.outChan <- *waapOvlfw
+		}
+	}
+}
+
+func (r *WaapRunner) handleOutBandInterrupt(request *waf.ParsedRequest) {
+	evt, err := EventFromRequest(request)
+	if err != nil {
+		//let's not interrupt the pipeline for this
+		r.logger.Errorf("unable to create event from request : %s", err)
+	}
+	err = r.AccumulateTxToEvent(&evt, request)
+	if err != nil {
+		r.logger.Errorf("unable to accumulate tx to event : %s", err)
+	}
+	if in := request.Tx.Interruption(); in != nil {
+		r.logger.Debugf("inband rules matched : %d", in.RuleID)
+		r.WaapRuntime.Response.OutOfBandInterrupt = true
+
+		err = r.WaapRuntime.ProcessOnMatchRules(request)
+		if err != nil {
+			r.logger.Errorf("unable to process OnMatch rules: %s", err)
+			return
+		}
+		// Should the match trigger an event ?
+		if r.WaapRuntime.Response.SendEvent {
+			r.outChan <- evt
+		}
+
+		// Should the match trigger an overflow ?
+		if r.WaapRuntime.Response.SendAlert {
+			waapOvlfw, err := WaapEventGeneration(evt)
 			if err != nil {
-				r.logger.Errorf("unable to accumulate tx to event : %s", err)
-			}
-			if in := request.Tx.Interruption(); in != nil {
-				r.logger.Debugf("inband rules matched : %d", in.RuleID)
-				r.WaapRuntime.Response.InBandInterrupt = true
-
-				err = r.WaapRuntime.ProcessOnMatchRules(&request)
-				if err != nil {
-					r.logger.Errorf("unable to process OnMatch rules: %s", err)
-					continue
-				}
+				r.logger.Errorf("unable to generate waap event : %s", err)
+				return
 			}
+			r.outChan <- *waapOvlfw
+		}
+	}
+}
 
-			elapsed := time.Since(startParsing)
-			WafInbandParsingHistogram.With(prometheus.Labels{"source": request.RemoteAddr}).Observe(elapsed.Seconds())
+func (r *WaapRunner) handleRequest(request *waf.ParsedRequest) {
+	r.logger.Debugf("Requests handled by runner %s", request.UUID)
+	r.WaapRuntime.ClearResponse()
 
-			//generate reponse for the remediation component, based on the WAAP config + inband rules evaluation
-			//@tko : this should move in the WaapRuntimeConfig as it knows what to do with the interruption and the expected remediation
+	request.IsInBand = true
+	request.IsOutBand = false
 
-			// send back the result to the HTTP handler for the InBand part
+	//to measure the time spent in the WAF
+	startParsing := time.Now()
 
-			r.logger.Infof("Response: %+v", r.WaapRuntime.Response)
+	//inband WAAP rules
+	err := r.ProcessInBandRules(request)
+	if err != nil {
+		r.logger.Errorf("unable to process InBand rules: %s", err)
+		return
+	}
 
-			request.ResponseChannel <- r.WaapRuntime.Response
+	if request.Tx.IsInterrupted() {
+		r.handleInBandInterrupt(request)
+	}
 
-			request.IsInBand = false
-			request.IsOutBand = true
+	elapsed := time.Since(startParsing)
+	WafInbandParsingHistogram.With(prometheus.Labels{"source": request.RemoteAddr}).Observe(elapsed.Seconds())
 
-			err = r.ProcessOutOfBandRules(&request)
-			if err != nil {
-				r.logger.Errorf("unable to process OutOfBand rules: %s", err)
-				continue
-			}
-			err = r.AccumulateTxToEvent(&evt, request)
-			if err != nil {
-				r.logger.Errorf("unable to accumulate tx to event : %s", err)
-			}
-			if in := request.Tx.Interruption(); in != nil {
-				r.logger.Debugf("outband rules matched : %d", in.RuleID)
-				r.WaapRuntime.Response.OutOfBandInterrupt = true
-				err = r.WaapRuntime.ProcessOnMatchRules(&request)
-				if err != nil {
-					r.logger.Errorf("unable to process OnMatch rules: %s", err)
-					continue
-				}
-			}
+	// send back the result to the HTTP handler for the InBand part
+	request.ResponseChannel <- r.WaapRuntime.Response
 
-			if !evt.Process {
-				continue
-			}
+	//Now let's process the out of band rules
 
-			//we generate two events: one that is going to be picked up by the acquisition pipeline (parsers, scenarios etc.)
-			//and a second one that will go straight to LAPI
-			r.outChan <- evt
-			waapOvlfw, err := WaapEventGeneration(evt)
-			if err != nil {
-				r.logger.Errorf("unable to generate waap event : %s", err)
-			} else if waapOvlfw != nil {
-				r.outChan <- *waapOvlfw
-			}
+	request.IsInBand = false
+	request.IsOutBand = true
+	r.WaapRuntime.Response.SendAlert = false
+	r.WaapRuntime.Response.SendEvent = true
+
+	err = r.ProcessOutOfBandRules(request)
+	if err != nil {
+		r.logger.Errorf("unable to process OutOfBand rules: %s", err)
+		return
+	}
+
+	if request.Tx.IsInterrupted() {
+		r.handleOutBandInterrupt(request)
+	}
+}
+
+func (r *WaapRunner) Run(t *tomb.Tomb) error {
+	r.logger.Infof("Waap Runner ready to process event")
+	for {
+		select {
+		case <-t.Dying():
+			r.logger.Infof("Waf Runner is dying")
+			return nil
+		case request := <-r.inChan:
+			r.handleRequest(&request)
 		}
 	}
 }

+ 2 - 1
pkg/waf/waap.go

@@ -120,7 +120,8 @@ func (w *WaapRuntimeConfig) ClearResponse() {
 	log.Debugf("-> %p", w.Config)
 	w.Response.Action = w.Config.DefaultPassAction
 	w.Response.HTTPResponseCode = w.Config.PassedHTTPCode
-	w.Response.SendEvent = true
+	w.Response.SendEvent = false
+	w.Response.SendAlert = true
 }
 
 func (wc *WaapConfig) LoadByPath(file string) error {