crowdsec/pkg/waf/waap_rules_collection.go

146 lines
3.6 KiB
Go
Raw Normal View History

2023-09-11 08:35:14 +00:00
package waf
2023-09-14 07:39:24 +00:00
import (
"fmt"
"os"
2023-09-14 09:18:33 +00:00
"path/filepath"
"strings"
2023-09-14 07:39:24 +00:00
corazatypes "github.com/crowdsecurity/coraza/v3/types"
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
2023-10-25 16:45:49 +00:00
"github.com/crowdsecurity/crowdsec/pkg/waf/waap_rule"
2023-09-14 07:39:24 +00:00
log "github.com/sirupsen/logrus"
)
2023-09-11 08:35:14 +00:00
// to be filled w/ seb update
type WaapCollection struct {
2023-09-14 07:39:24 +00:00
collectionName string
2023-09-14 09:18:33 +00:00
Rules []string
2023-09-11 08:35:14 +00:00
}
2023-10-18 15:11:43 +00:00
var WAAP_RULE = "waap-rule"
2023-09-11 08:35:14 +00:00
// to be filled w/ seb update
type WaapCollectionConfig struct {
2023-10-25 16:45:49 +00:00
Type string `yaml:"type"`
Name string `yaml:"name"`
2023-10-27 09:08:54 +00:00
Debug bool `yaml:"debug"`
2023-10-25 16:45:49 +00:00
Description string `yaml:"description"`
SecLangFilesRules []string `yaml:"seclang_files_rules"`
SecLangRules []string `yaml:"seclang_rules"`
Rules []waap_rule.CustomRule `yaml:"rules"`
2023-10-27 09:10:17 +00:00
Data interface{} `yaml:"data"` //Ignore it
hash string `yaml:"-"`
version string `yaml:"-"`
}
type RulesDetails struct {
LogLevel log.Level
Hash string
Version string
Name string
2023-09-11 08:35:14 +00:00
}
2023-10-27 09:10:17 +00:00
// Should it be a global ?
// Is using the id is a good idea ? might be too specific to coraza and not easily reusable
var WaapRulesDetails = make(map[int]RulesDetails)
2023-09-11 08:35:14 +00:00
func LoadCollection(collection string) (WaapCollection, error) {
2023-09-14 07:39:24 +00:00
2023-10-19 12:19:37 +00:00
hub, err := cwhub.GetHub()
if err != nil {
return WaapCollection{}, fmt.Errorf("unable to load hub : %s", err)
}
2023-09-14 07:39:24 +00:00
var loadedRule WaapCollectionConfig
2023-09-14 09:18:33 +00:00
var ok bool
2023-09-14 07:39:24 +00:00
2023-09-14 09:18:33 +00:00
if loadedRule, ok = waapRules[collection]; !ok {
2023-09-14 07:39:24 +00:00
return WaapCollection{}, fmt.Errorf("no waap rules found for collection %s", collection)
}
2023-09-14 09:18:33 +00:00
waapCol := WaapCollection{
2023-09-14 07:39:24 +00:00
collectionName: loadedRule.Name,
2023-09-14 09:18:33 +00:00
}
if loadedRule.SecLangFilesRules != nil {
for _, rulesFile := range loadedRule.SecLangFilesRules {
2023-10-19 12:19:37 +00:00
fullPath := filepath.Join(hub.GetDataDir(), rulesFile)
2023-09-14 09:18:33 +00:00
c, err := os.ReadFile(fullPath)
if err != nil {
log.Errorf("unable to read file %s : %s", rulesFile, err)
continue
}
for _, line := range strings.Split(string(c), "\n") {
if strings.HasPrefix(line, "#") {
continue
}
if strings.TrimSpace(line) == "" {
continue
}
waapCol.Rules = append(waapCol.Rules, line)
}
}
}
if loadedRule.SecLangRules != nil {
waapCol.Rules = append(waapCol.Rules, loadedRule.SecLangRules...)
}
2023-10-17 07:32:40 +00:00
if loadedRule.Rules != nil {
for _, rule := range loadedRule.Rules {
2023-10-27 09:17:27 +00:00
strRule, rulesId, err := rule.Convert(waap_rule.ModsecurityRuleType, loadedRule.Name)
2023-10-25 16:45:49 +00:00
if err != nil {
log.Errorf("unable to convert rule %s : %s", rule.Name, err)
return WaapCollection{}, err
}
log.Infof("Adding rule %s", strRule)
waapCol.Rules = append(waapCol.Rules, strRule)
2023-10-27 09:10:17 +00:00
2023-10-27 09:17:27 +00:00
//We only take the first id, as it's the one of the "main" rule
if _, ok := WaapRulesDetails[int(rulesId[0])]; !ok {
WaapRulesDetails[int(rulesId[0])] = RulesDetails{
2023-10-27 09:10:17 +00:00
LogLevel: log.InfoLevel,
Hash: loadedRule.hash,
Version: loadedRule.version,
Name: loadedRule.Name,
}
} else {
2023-10-27 09:17:27 +00:00
log.Warnf("conflicting id %d for rule %s !", rulesId[0], rule.Name)
}
for _, id := range rulesId {
SetRuleDebug(int(id), loadedRule.Debug)
2023-10-27 09:10:17 +00:00
}
2023-10-17 07:32:40 +00:00
}
}
2023-09-14 09:18:33 +00:00
return waapCol, nil
2023-09-11 08:35:14 +00:00
}
func (wcc WaapCollectionConfig) LoadCollection(collection string) (WaapCollection, error) {
return WaapCollection{}, nil
}
func (w WaapCollection) Check() error {
return nil
}
func (w WaapCollection) Eval(req ParsedRequest) (*corazatypes.Interruption, error) {
return nil, nil
}
func (w WaapCollection) GetDisplayName() string {
2023-09-14 07:39:24 +00:00
return w.collectionName
2023-09-11 08:35:14 +00:00
}
2023-09-19 11:16:33 +00:00
func (w WaapCollection) String() string {
ret := ""
for _, rule := range w.Rules {
ret += rule + "\n"
}
return ret
}