package v1 import ( "errors" "regexp" "slices" "edge-infra.dev/pkg/lib/networkvalidator" ) const ( portRangeValidationRegex = `^(\d+(:\d+)?)?$` ) func (cfw *ClusterFirewall) ValidateRules() error { for _, clustRule := range cfw.Spec.ClusterRules { if valid, reason := validateNodeRule(clustRule.NodeRule); !valid { return errors.New(reason) } } return nil } func (nfw *NodeFirewall) ValidateRules() (bool, string) { for _, rule := range nfw.Spec.Rules { if valid, reason := validateNodeRule(rule); !valid { return false, reason } } return true, "" } func validateNodeRule(rule NodeRule) (bool, string) { _, err := networkvalidator.ValidateMacAddress(rule.InterfaceMAC) validMac := err == nil switch { case !(rule.InterfaceMAC == "" || validMac): return false, "invalid InterfaceMAC" case !slices.Contains([]Direction{Input, Output}, rule.Direction): return false, "invalid Direction" case !validateAddressRange(rule.DestinationRanges): return false, "invalid DestinationRange" case !validateAddressRange(rule.SourceRanges): return false, "invalid SourceRange" case !validateFilters(rule.Filters): return false, "invalid Filter" } return true, "" } func validateAddressRange(addressRanges []string) bool { for _, addressRange := range addressRanges { if !networkvalidator.IsValidCIDR(addressRange) { return false } } return true } func validateFilters(filters []Filter) bool { r, err := regexp.Compile(portRangeValidationRegex) if err != nil { return false } for _, filter := range filters { if !slices.Contains([]IPProtocol{TCP, UDP}, filter.IPProtocol) || !r.MatchString(filter.PortRange) || !slices.Contains([]Action{Allow, Deny}, filter.Action) { return false } } return true }