85 lines
2.4 KiB
Go
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
|
|
}
|