crowdsec/pkg/acquisition/modules/waf/utils.go
2023-06-16 16:52:01 +02:00

85 lines
2.4 KiB
Go

package wafacquisition
import (
"encoding/json"
"fmt"
"strings"
"time"
corazatypes "github.com/corazawaf/coraza/v3/types"
"github.com/crowdsecurity/crowdsec/pkg/types"
"github.com/pkg/errors"
)
func TxToEvents(r ParsedRequest, kind string) ([]types.Event, error) {
evts := []types.Event{}
if r.Tx == nil {
return nil, fmt.Errorf("tx is nil")
}
for _, rule := range r.Tx.MatchedRules() {
//log.Printf("rule %d", idx)
if rule.Message() == "" {
continue
}
evt, err := RuleMatchToEvent(rule, r.Tx, r, kind)
if err != nil {
return nil, errors.Wrap(err, "Cannot convert rule match to event")
}
evts = append(evts, evt)
}
return evts, nil
}
// Transforms a coraza interruption to a crowdsec event
func RuleMatchToEvent(rule corazatypes.MatchedRule, tx corazatypes.Transaction, r ParsedRequest, kind string) (types.Event, error) {
evt := types.Event{}
//we might want to change this based on in-band vs out-of-band ?
evt.Type = types.LOG
evt.ExpectMode = types.LIVE
//def needs fixing
evt.Stage = "s00-raw"
evt.Process = true
//we build a big-ass object that is going to be marshaled in line.raw and unmarshaled later.
//why ? because it's more consistent with the other data-sources etc. and it provides users with flexibility to alter our parsers
CorazaEvent := map[string]interface{}{
//core rule info
"rule_type": kind,
"rule_id": rule.Rule().ID(),
//"rule_action": tx.Interruption().Action,
"rule_disruptive": rule.Disruptive(),
"rule_tags": rule.Rule().Tags(),
"rule_file": rule.Rule().File(),
"rule_file_line": rule.Rule().Line(),
"rule_revision": rule.Rule().Revision(),
"rule_secmark": rule.Rule().SecMark(),
"rule_accuracy": rule.Rule().Accuracy(),
//http contextual infos
"upstream_addr": r.RemoteAddr,
"req_uuid": tx.ID(),
"source_ip": strings.Split(rule.ClientIPAddress(), ":")[0],
"uri": rule.URI(),
}
if tx.Interruption() != nil {
CorazaEvent["rule_action"] = tx.Interruption().Action
}
corazaEventB, err := json.Marshal(CorazaEvent)
if err != nil {
return evt, fmt.Errorf("Unable to marshal coraza alert: %w", err)
}
evt.Line = types.Line{
Time: time.Now(),
//should we add some info like listen addr/port/path ?
Labels: map[string]string{"type": "waf"},
Process: true,
Module: "waf",
Src: "waf",
Raw: string(corazaEventB),
}
return evt, nil
}