71 lines
1.8 KiB
Go
71 lines
1.8 KiB
Go
package rule
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
"strings"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
var (
|
|
ErrInvalid = errors.New("规则内容不符合要求")
|
|
ErrNotFound = errors.New("规则不存在")
|
|
codePattern = regexp.MustCompile(`^[a-z0-9][a-z0-9_-]{1,127}$`)
|
|
)
|
|
|
|
type WriteInput struct {
|
|
Code string `json:"code"`
|
|
Name string `json:"name"`
|
|
EventType *string `json:"eventType"`
|
|
MinimumSeverity string `json:"minimumSeverity"`
|
|
LocationContains *string `json:"locationContains"`
|
|
}
|
|
|
|
func Normalize(input WriteInput, requireCode bool) (WriteInput, error) {
|
|
input.Code = strings.ToLower(strings.TrimSpace(input.Code))
|
|
input.Name = strings.TrimSpace(input.Name)
|
|
input.MinimumSeverity = strings.ToLower(strings.TrimSpace(input.MinimumSeverity))
|
|
if requireCode && !codePattern.MatchString(input.Code) {
|
|
return WriteInput{}, ErrInvalid
|
|
}
|
|
if !validText(input.Name, 128) || !validSeverity(input.MinimumSeverity) {
|
|
return WriteInput{}, ErrInvalid
|
|
}
|
|
var err error
|
|
if input.EventType, err = optionalText(input.EventType, 128); err != nil {
|
|
return WriteInput{}, err
|
|
}
|
|
if input.LocationContains, err = optionalText(input.LocationContains, 128); err != nil {
|
|
return WriteInput{}, err
|
|
}
|
|
return input, nil
|
|
}
|
|
|
|
func validSeverity(value string) bool {
|
|
switch value {
|
|
case "low", "medium", "high", "critical":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func optionalText(value *string, max int) (*string, error) {
|
|
if value == nil {
|
|
return nil, nil
|
|
}
|
|
normalized := strings.TrimSpace(*value)
|
|
if normalized == "" {
|
|
return nil, nil
|
|
}
|
|
if !validText(normalized, max) {
|
|
return nil, ErrInvalid
|
|
}
|
|
return &normalized, nil
|
|
}
|
|
|
|
func validText(value string, max int) bool {
|
|
return value != "" && utf8.ValidString(value) && utf8.RuneCountInString(value) <= max &&
|
|
!strings.ContainsAny(value, "\x00\r\n")
|
|
}
|