Files
EdgeNode/internal/waf/rule_group.go
GoEdgeLab c19be78e0d v1.4.1
2024-07-27 15:42:50 +08:00

144 lines
3.0 KiB
Go

package waf
import (
"fmt"
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
)
// rule group
type RuleGroup struct {
Id int64 `yaml:"id" json:"id"`
IsOn bool `yaml:"isOn" json:"isOn"`
Name string `yaml:"name" json:"name"` // such as SQL Injection
Description string `yaml:"description" json:"description"`
Code string `yaml:"code" json:"code"` // identify the group
RuleSets []*RuleSet `yaml:"ruleSets" json:"ruleSets"`
IsInbound bool `yaml:"isInbound" json:"isInbound"`
hasRuleSets bool
}
func NewRuleGroup() *RuleGroup {
return &RuleGroup{
IsOn: true,
}
}
func (this *RuleGroup) Init(waf *WAF) error {
this.hasRuleSets = len(this.RuleSets) > 0
if this.hasRuleSets {
for _, set := range this.RuleSets {
err := set.Init(waf)
if err != nil {
return fmt.Errorf("init set '%d' failed: %w", set.Id, err)
}
}
}
return nil
}
func (this *RuleGroup) AddRuleSet(ruleSet *RuleSet) {
this.RuleSets = append(this.RuleSets, ruleSet)
}
func (this *RuleGroup) FindRuleSet(id int64) *RuleSet {
for _, ruleSet := range this.RuleSets {
if ruleSet.Id == id {
return ruleSet
}
}
return nil
}
func (this *RuleGroup) FindRuleSetWithCode(code string) *RuleSet {
if len(code) == 0 {
return nil
}
for _, ruleSet := range this.RuleSets {
if ruleSet.Code == code {
return ruleSet
}
}
return nil
}
func (this *RuleGroup) RemoveRuleSet(id int64) {
result := []*RuleSet{}
for _, ruleSet := range this.RuleSets {
if ruleSet.Id == id {
continue
}
result = append(result, ruleSet)
}
this.RuleSets = result
}
func (this *RuleGroup) MatchRequest(req requests.Request) (b bool, hasRequestBody bool, resultSet *RuleSet, err error) {
if !this.hasRuleSets {
return
}
for _, set := range this.RuleSets {
if !set.IsOn {
continue
}
b, hasRequestBody, err = set.MatchRequest(req)
if err != nil {
return false, hasRequestBody, nil, err
}
if b {
return true, hasRequestBody, set, nil
}
}
return
}
func (this *RuleGroup) MatchResponse(req requests.Request, resp *requests.Response) (b bool, hasRequestBody bool, resultSet *RuleSet, err error) {
if !this.hasRuleSets {
return
}
for _, set := range this.RuleSets {
if !set.IsOn {
continue
}
b, hasRequestBody, err = set.MatchResponse(req, resp)
if err != nil {
return false, hasRequestBody, nil, err
}
if b {
return true, hasRequestBody, set, nil
}
}
return
}
func (this *RuleGroup) MoveRuleSet(fromIndex int, toIndex int) {
if fromIndex < 0 || fromIndex >= len(this.RuleSets) {
return
}
if toIndex < 0 || toIndex >= len(this.RuleSets) {
return
}
if fromIndex == toIndex {
return
}
location := this.RuleSets[fromIndex]
result := []*RuleSet{}
for i := 0; i < len(this.RuleSets); i++ {
if i == fromIndex {
continue
}
if fromIndex > toIndex && i == toIndex {
result = append(result, location)
}
result = append(result, this.RuleSets[i])
if fromIndex < toIndex && i == toIndex {
result = append(result, location)
}
}
this.RuleSets = result
}